fix: pull to refresh indicator in filtered contents (#856)
This commit is contained in:
parent
f9ed0337fc
commit
8c167c8975
@ -17,7 +17,6 @@ import kotlinx.coroutines.flow.launchIn
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
var loadingFinished = false
|
var loadingFinished = false
|
||||||
installSplashScreen().setKeepOnScreenCondition {
|
installSplashScreen().setKeepOnScreenCondition {
|
||||||
@ -27,7 +26,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
// manage exit confirmation
|
// manage exit confirmation
|
||||||
val navigationCoordinator = getNavigationCoordinator()
|
val navigationCoordinator = getNavigationCoordinator()
|
||||||
val backPressedCallback = object : OnBackPressedCallback(true) {
|
val backPressedCallback =
|
||||||
|
object : OnBackPressedCallback(true) {
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
// if in home, ask for confirmation
|
// if in home, ask for confirmation
|
||||||
if (navigationCoordinator.currentSection.value == TabNavigationSection.Home) {
|
if (navigationCoordinator.currentSection.value == TabNavigationSection.Home) {
|
||||||
@ -46,7 +46,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// when back is detected and the confirmation callback is not active, terminate the activity
|
// when back is detected and the confirmation callback is not active, terminate the activity
|
||||||
val finishBackPressedCallback = object : OnBackPressedCallback(false) {
|
val finishBackPressedCallback =
|
||||||
|
object : OnBackPressedCallback(false) {
|
||||||
override fun handleOnBackPressed() {
|
override fun handleOnBackPressed() {
|
||||||
navigationCoordinator.setExitMessageVisible(false)
|
navigationCoordinator.setExitMessageVisible(false)
|
||||||
finish()
|
finish()
|
||||||
@ -75,13 +76,16 @@ class MainActivity : ComponentActivity() {
|
|||||||
handleIntent(intent)
|
handleIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleIntent(intent: Intent?) = intent?.apply {
|
private fun handleIntent(intent: Intent?) =
|
||||||
|
intent?.apply {
|
||||||
when (action) {
|
when (action) {
|
||||||
Intent.ACTION_SEND -> intent.getStringExtra(Intent.EXTRA_TEXT)?.let { content ->
|
Intent.ACTION_SEND ->
|
||||||
|
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { content ->
|
||||||
handleCreatePost(content)
|
handleCreatePost(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> data.toString().takeUnless { it.isEmpty() }?.also { url ->
|
else ->
|
||||||
|
data.toString().takeUnless { it.isEmpty() }?.also { url ->
|
||||||
handleDeeplink(url)
|
handleDeeplink(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +98,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private fun handleCreatePost(content: String) {
|
private fun handleCreatePost(content: String) {
|
||||||
val looksLikeAnUrl = Patterns.WEB_URL.matcher(content).matches()
|
val looksLikeAnUrl = Patterns.WEB_URL.matcher(content).matches()
|
||||||
val event = if (looksLikeAnUrl) {
|
val event =
|
||||||
|
if (looksLikeAnUrl) {
|
||||||
ComposeEvent.WithUrl(content)
|
ComposeEvent.WithUrl(content)
|
||||||
} else {
|
} else {
|
||||||
ComposeEvent.WithText(content)
|
ComposeEvent.WithText(content)
|
||||||
|
@ -24,7 +24,8 @@ class MainApplication : Application(), ImageLoaderFactory {
|
|||||||
sharedHelperModule,
|
sharedHelperModule,
|
||||||
)
|
)
|
||||||
|
|
||||||
AppInfo.versionCode = buildString {
|
AppInfo.versionCode =
|
||||||
|
buildString {
|
||||||
append(BuildConfig.VERSION_NAME)
|
append(BuildConfig.VERSION_NAME)
|
||||||
append(" (")
|
append(" (")
|
||||||
append(BuildConfig.VERSION_CODE)
|
append(BuildConfig.VERSION_CODE)
|
||||||
|
@ -5,11 +5,12 @@ import com.github.diegoberaldin.raccoonforlemmy.core.api.provider.ServiceProvide
|
|||||||
import org.koin.core.qualifier.named
|
import org.koin.core.qualifier.named
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val coreApiModule = module {
|
val coreApiModule =
|
||||||
|
module {
|
||||||
single<ServiceProvider>(named("default")) {
|
single<ServiceProvider>(named("default")) {
|
||||||
DefaultServiceProvider()
|
DefaultServiceProvider()
|
||||||
}
|
}
|
||||||
single<ServiceProvider>(named("custom")) {
|
single<ServiceProvider>(named("custom")) {
|
||||||
DefaultServiceProvider()
|
DefaultServiceProvider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import io.ktor.serialization.kotlinx.json.json
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
internal class DefaultServiceProvider : ServiceProvider {
|
internal class DefaultServiceProvider : ServiceProvider {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val DEFAULT_INSTANCE = "lemmy.world"
|
private const val DEFAULT_INSTANCE = "lemmy.world"
|
||||||
private const val VERSION = "v3"
|
private const val VERSION = "v3"
|
||||||
@ -74,7 +73,8 @@ internal class DefaultServiceProvider : ServiceProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun reinitialize() {
|
private fun reinitialize() {
|
||||||
val client = HttpClient(factory) {
|
val client =
|
||||||
|
HttpClient(factory) {
|
||||||
defaultRequest {
|
defaultRequest {
|
||||||
url {
|
url {
|
||||||
host = currentInstance
|
host = currentInstance
|
||||||
@ -100,7 +100,8 @@ internal class DefaultServiceProvider : ServiceProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val ktorfit = Ktorfit.Builder()
|
val ktorfit =
|
||||||
|
Ktorfit.Builder()
|
||||||
.baseUrl(baseUrl)
|
.baseUrl(baseUrl)
|
||||||
.httpClient(client)
|
.httpClient(client)
|
||||||
.build()
|
.build()
|
||||||
|
@ -3,8 +3,9 @@ package com.github.diegoberaldin.raccoonforlemmy.core.api.provider
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.debug.logDebug
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.debug.logDebug
|
||||||
import io.ktor.client.plugins.logging.Logger
|
import io.ktor.client.plugins.logging.Logger
|
||||||
|
|
||||||
internal val defaultLogger = object : Logger {
|
internal val defaultLogger =
|
||||||
|
object : Logger {
|
||||||
override fun log(message: String) {
|
override fun log(message: String) {
|
||||||
logDebug(message)
|
logDebug(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.api.service.SiteService
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.api.service.UserService
|
import com.github.diegoberaldin.raccoonforlemmy.core.api.service.UserService
|
||||||
|
|
||||||
interface ServiceProvider {
|
interface ServiceProvider {
|
||||||
|
|
||||||
val currentInstance: String
|
val currentInstance: String
|
||||||
val auth: AuthService
|
val auth: AuthService
|
||||||
val post: PostService
|
val post: PostService
|
||||||
|
@ -26,7 +26,6 @@ import de.jensklingenberg.ktorfit.http.PUT
|
|||||||
import de.jensklingenberg.ktorfit.http.Query
|
import de.jensklingenberg.ktorfit.http.Query
|
||||||
|
|
||||||
interface CommunityService {
|
interface CommunityService {
|
||||||
|
|
||||||
@GET("community")
|
@GET("community")
|
||||||
suspend fun get(
|
suspend fun get(
|
||||||
@Header("Authorization") authHeader: String? = null,
|
@Header("Authorization") authHeader: String? = null,
|
||||||
|
@ -25,7 +25,6 @@ import de.jensklingenberg.ktorfit.http.PUT
|
|||||||
import de.jensklingenberg.ktorfit.http.Query
|
import de.jensklingenberg.ktorfit.http.Query
|
||||||
|
|
||||||
interface UserService {
|
interface UserService {
|
||||||
|
|
||||||
@GET("user")
|
@GET("user")
|
||||||
suspend fun getDetails(
|
suspend fun getDetails(
|
||||||
@Header("Authorization") authHeader: String? = null,
|
@Header("Authorization") authHeader: String? = null,
|
||||||
|
@ -13,15 +13,20 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
|
|
||||||
class DefaultBarColorProvider : BarColorProvider {
|
class DefaultBarColorProvider : BarColorProvider {
|
||||||
@Composable
|
@Composable
|
||||||
override fun setBarColorAccordingToTheme(theme: UiTheme, barTheme: UiBarTheme) {
|
override fun setBarColorAccordingToTheme(
|
||||||
|
theme: UiTheme,
|
||||||
|
barTheme: UiBarTheme,
|
||||||
|
) {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
LaunchedEffect(theme, barTheme) {
|
LaunchedEffect(theme, barTheme) {
|
||||||
(view.context as? Activity)?.window?.apply {
|
(view.context as? Activity)?.window?.apply {
|
||||||
val baseColor = when (theme) {
|
val baseColor =
|
||||||
|
when (theme) {
|
||||||
UiTheme.Light -> Color.White
|
UiTheme.Light -> Color.White
|
||||||
else -> Color.Black
|
else -> Color.Black
|
||||||
}
|
}
|
||||||
val barColor = when (barTheme) {
|
val barColor =
|
||||||
|
when (barTheme) {
|
||||||
UiBarTheme.Opaque -> baseColor.copy(alpha = 0.25f)
|
UiBarTheme.Opaque -> baseColor.copy(alpha = 0.25f)
|
||||||
UiBarTheme.Transparent -> baseColor.copy(alpha = 0.01f)
|
UiBarTheme.Transparent -> baseColor.copy(alpha = 0.01f)
|
||||||
else -> baseColor
|
else -> baseColor
|
||||||
@ -40,11 +45,13 @@ class DefaultBarColorProvider : BarColorProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WindowCompat.getInsetsController(this, decorView).apply {
|
WindowCompat.getInsetsController(this, decorView).apply {
|
||||||
isAppearanceLightStatusBars = when (theme) {
|
isAppearanceLightStatusBars =
|
||||||
|
when (theme) {
|
||||||
UiTheme.Light -> true
|
UiTheme.Light -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
isAppearanceLightNavigationBars = when (theme) {
|
isAppearanceLightNavigationBars =
|
||||||
|
when (theme) {
|
||||||
UiTheme.Light -> true
|
UiTheme.Light -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
import com.materialkolor.dynamicColorScheme
|
import com.materialkolor.dynamicColorScheme
|
||||||
|
|
||||||
internal class DefaultColorSchemeProvider(private val context: Context) : ColorSchemeProvider {
|
internal class DefaultColorSchemeProvider(private val context: Context) : ColorSchemeProvider {
|
||||||
|
|
||||||
override val supportsDynamicColors: Boolean
|
override val supportsDynamicColors: Boolean
|
||||||
@ChecksSdkIntAtLeast(31)
|
@ChecksSdkIntAtLeast(31)
|
||||||
get() {
|
get() {
|
||||||
@ -24,7 +23,8 @@ internal class DefaultColorSchemeProvider(private val context: Context) : ColorS
|
|||||||
theme: UiTheme,
|
theme: UiTheme,
|
||||||
dynamic: Boolean,
|
dynamic: Boolean,
|
||||||
customSeed: Color?,
|
customSeed: Color?,
|
||||||
): ColorScheme = when (theme) {
|
): ColorScheme =
|
||||||
|
when (theme) {
|
||||||
UiTheme.Dark -> {
|
UiTheme.Dark -> {
|
||||||
when {
|
when {
|
||||||
dynamic -> {
|
dynamic -> {
|
||||||
|
@ -13,7 +13,6 @@ import kotlin.test.assertNotEquals
|
|||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
class DefaultThemeRepositoryTest {
|
class DefaultThemeRepositoryTest {
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val dispatcherTestRule = DispatcherTestRule()
|
val dispatcherTestRule = DispatcherTestRule()
|
||||||
|
|
||||||
|
@ -6,62 +6,72 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface CommentBarTheme {
|
sealed interface CommentBarTheme {
|
||||||
data object Green : CommentBarTheme
|
data object Green : CommentBarTheme
|
||||||
|
|
||||||
data object Blue : CommentBarTheme
|
data object Blue : CommentBarTheme
|
||||||
|
|
||||||
data object Red : CommentBarTheme
|
data object Red : CommentBarTheme
|
||||||
|
|
||||||
data object Rainbow : CommentBarTheme
|
data object Rainbow : CommentBarTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int?.toCommentBarTheme(): CommentBarTheme = when (this) {
|
fun Int?.toCommentBarTheme(): CommentBarTheme =
|
||||||
|
when (this) {
|
||||||
3 -> CommentBarTheme.Rainbow
|
3 -> CommentBarTheme.Rainbow
|
||||||
2 -> CommentBarTheme.Red
|
2 -> CommentBarTheme.Red
|
||||||
1 -> CommentBarTheme.Green
|
1 -> CommentBarTheme.Green
|
||||||
else -> CommentBarTheme.Blue
|
else -> CommentBarTheme.Blue
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CommentBarTheme.toInt(): Int = when (this) {
|
fun CommentBarTheme.toInt(): Int =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> 3
|
CommentBarTheme.Rainbow -> 3
|
||||||
CommentBarTheme.Red -> 2
|
CommentBarTheme.Red -> 2
|
||||||
CommentBarTheme.Green -> 1
|
CommentBarTheme.Green -> 1
|
||||||
CommentBarTheme.Blue -> 0
|
CommentBarTheme.Blue -> 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentBarTheme?.toReadableName() = when (this) {
|
fun CommentBarTheme?.toReadableName() =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> LocalXmlStrings.current.settingsCommentBarThemeMulti
|
CommentBarTheme.Rainbow -> LocalXmlStrings.current.settingsCommentBarThemeMulti
|
||||||
CommentBarTheme.Red -> LocalXmlStrings.current.settingsCommentBarThemeRed
|
CommentBarTheme.Red -> LocalXmlStrings.current.settingsCommentBarThemeRed
|
||||||
CommentBarTheme.Green -> LocalXmlStrings.current.settingsCommentBarThemeGreen
|
CommentBarTheme.Green -> LocalXmlStrings.current.settingsCommentBarThemeGreen
|
||||||
CommentBarTheme.Blue -> LocalXmlStrings.current.settingsCommentBarThemeBlue
|
CommentBarTheme.Blue -> LocalXmlStrings.current.settingsCommentBarThemeBlue
|
||||||
else -> LocalXmlStrings.current.settingsColorCustom
|
else -> LocalXmlStrings.current.settingsColorCustom
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CommentBarTheme?.toUpVoteColor(): Color = when (this) {
|
fun CommentBarTheme?.toUpVoteColor(): Color =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> Color(0xFF00FF00)
|
CommentBarTheme.Rainbow -> Color(0xFF00FF00)
|
||||||
CommentBarTheme.Red -> Color(0xFFD00000)
|
CommentBarTheme.Red -> Color(0xFFD00000)
|
||||||
CommentBarTheme.Green -> Color(0xFF52B788)
|
CommentBarTheme.Green -> Color(0xFF52B788)
|
||||||
CommentBarTheme.Blue -> Color(0xFF014F86)
|
CommentBarTheme.Blue -> Color(0xFF014F86)
|
||||||
else -> Color.Transparent
|
else -> Color.Transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CommentBarTheme?.toDownVoteColor(): Color = when (this) {
|
fun CommentBarTheme?.toDownVoteColor(): Color =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> Color(0xFFFF0000)
|
CommentBarTheme.Rainbow -> Color(0xFFFF0000)
|
||||||
CommentBarTheme.Red -> Color(0xFF2FFFFF)
|
CommentBarTheme.Red -> Color(0xFF2FFFFF)
|
||||||
CommentBarTheme.Green -> Color(0xFFAD4877)
|
CommentBarTheme.Green -> Color(0xFFAD4877)
|
||||||
CommentBarTheme.Blue -> Color(0xFF9400D3)
|
CommentBarTheme.Blue -> Color(0xFF9400D3)
|
||||||
else -> Color.Transparent
|
else -> Color.Transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CommentBarTheme?.toReplyColor(): Color = when (this) {
|
fun CommentBarTheme?.toReplyColor(): Color =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> Color(0xFFFF5722)
|
CommentBarTheme.Rainbow -> Color(0xFFFF5722)
|
||||||
CommentBarTheme.Red -> Color(0xFF8BC34A)
|
CommentBarTheme.Red -> Color(0xFF8BC34A)
|
||||||
CommentBarTheme.Green -> Color(0xFFFF9800)
|
CommentBarTheme.Green -> Color(0xFFFF9800)
|
||||||
CommentBarTheme.Blue -> Color(0xFF388E3C)
|
CommentBarTheme.Blue -> Color(0xFF388E3C)
|
||||||
else -> Color.Transparent
|
else -> Color.Transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CommentBarTheme?.toSaveColor(): Color = when (this) {
|
fun CommentBarTheme?.toSaveColor(): Color =
|
||||||
|
when (this) {
|
||||||
CommentBarTheme.Rainbow -> Color(0xFFE040FB)
|
CommentBarTheme.Rainbow -> Color(0xFFE040FB)
|
||||||
CommentBarTheme.Red -> Color(0xFFFFC107)
|
CommentBarTheme.Red -> Color(0xFFFFC107)
|
||||||
CommentBarTheme.Green -> Color(0xFF388E3C)
|
CommentBarTheme.Green -> Color(0xFF388E3C)
|
||||||
CommentBarTheme.Blue -> Color(0xFF7C4DFF)
|
CommentBarTheme.Blue -> Color(0xFF7C4DFF)
|
||||||
else -> Color.Transparent
|
else -> Color.Transparent
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,23 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface FontScale {
|
sealed interface FontScale {
|
||||||
data object Largest : FontScale
|
data object Largest : FontScale
|
||||||
|
|
||||||
data object Larger : FontScale
|
data object Larger : FontScale
|
||||||
|
|
||||||
data object Large : FontScale
|
data object Large : FontScale
|
||||||
|
|
||||||
data object Normal : FontScale
|
data object Normal : FontScale
|
||||||
|
|
||||||
data object Small : FontScale
|
data object Small : FontScale
|
||||||
|
|
||||||
data object Smaller : FontScale
|
data object Smaller : FontScale
|
||||||
|
|
||||||
data object Smallest : FontScale
|
data object Smallest : FontScale
|
||||||
}
|
}
|
||||||
|
|
||||||
val FontScale.scaleFactor: Float
|
val FontScale.scaleFactor: Float
|
||||||
get() = when (this) {
|
get() =
|
||||||
|
when (this) {
|
||||||
FontScale.Largest -> ReferenceValues.largest
|
FontScale.Largest -> ReferenceValues.largest
|
||||||
FontScale.Larger -> ReferenceValues.larger
|
FontScale.Larger -> ReferenceValues.larger
|
||||||
FontScale.Large -> ReferenceValues.large
|
FontScale.Large -> ReferenceValues.large
|
||||||
@ -25,7 +32,8 @@ val FontScale.scaleFactor: Float
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FontScale.toReadableName(): String = when (this) {
|
fun FontScale.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
FontScale.Largest -> LocalXmlStrings.current.settingsContentFontLargest
|
FontScale.Largest -> LocalXmlStrings.current.settingsContentFontLargest
|
||||||
FontScale.Larger -> LocalXmlStrings.current.settingsContentFontLarger
|
FontScale.Larger -> LocalXmlStrings.current.settingsContentFontLarger
|
||||||
FontScale.Large -> LocalXmlStrings.current.settingsContentFontLarge
|
FontScale.Large -> LocalXmlStrings.current.settingsContentFontLarge
|
||||||
@ -33,9 +41,10 @@ fun FontScale.toReadableName(): String = when (this) {
|
|||||||
FontScale.Small -> LocalXmlStrings.current.settingsContentFontSmall
|
FontScale.Small -> LocalXmlStrings.current.settingsContentFontSmall
|
||||||
FontScale.Smaller -> LocalXmlStrings.current.settingsContentFontSmaller
|
FontScale.Smaller -> LocalXmlStrings.current.settingsContentFontSmaller
|
||||||
FontScale.Smallest -> LocalXmlStrings.current.settingsContentFontSmallest
|
FontScale.Smallest -> LocalXmlStrings.current.settingsContentFontSmallest
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Float.toFontScale(): FontScale = when (this) {
|
fun Float.toFontScale(): FontScale =
|
||||||
|
when (this) {
|
||||||
ReferenceValues.largest -> FontScale.Largest
|
ReferenceValues.largest -> FontScale.Largest
|
||||||
ReferenceValues.larger -> FontScale.Larger
|
ReferenceValues.larger -> FontScale.Larger
|
||||||
ReferenceValues.large -> FontScale.Large
|
ReferenceValues.large -> FontScale.Large
|
||||||
@ -43,7 +52,7 @@ fun Float.toFontScale(): FontScale = when (this) {
|
|||||||
ReferenceValues.smaller -> FontScale.Smaller
|
ReferenceValues.smaller -> FontScale.Smaller
|
||||||
ReferenceValues.smallest -> FontScale.Smallest
|
ReferenceValues.smallest -> FontScale.Smallest
|
||||||
else -> FontScale.Normal
|
else -> FontScale.Normal
|
||||||
}
|
}
|
||||||
|
|
||||||
// log(2 + 0.1 * n) / log(2)
|
// log(2 + 0.1 * n) / log(2)
|
||||||
private object ReferenceValues {
|
private object ReferenceValues {
|
||||||
|
@ -5,25 +5,30 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface PostLayout {
|
sealed interface PostLayout {
|
||||||
data object Card : PostLayout
|
data object Card : PostLayout
|
||||||
|
|
||||||
data object Compact : PostLayout
|
data object Compact : PostLayout
|
||||||
|
|
||||||
data object Full : PostLayout
|
data object Full : PostLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PostLayout.toReadableName(): String = when (this) {
|
fun PostLayout.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
PostLayout.Full -> LocalXmlStrings.current.settingsPostLayoutFull
|
PostLayout.Full -> LocalXmlStrings.current.settingsPostLayoutFull
|
||||||
PostLayout.Compact -> LocalXmlStrings.current.settingsPostLayoutCompact
|
PostLayout.Compact -> LocalXmlStrings.current.settingsPostLayoutCompact
|
||||||
else -> LocalXmlStrings.current.settingsPostLayoutCard
|
else -> LocalXmlStrings.current.settingsPostLayoutCard
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toPostLayout(): PostLayout = when (this) {
|
fun Int.toPostLayout(): PostLayout =
|
||||||
|
when (this) {
|
||||||
1 -> PostLayout.Compact
|
1 -> PostLayout.Compact
|
||||||
2 -> PostLayout.Full
|
2 -> PostLayout.Full
|
||||||
else -> PostLayout.Card
|
else -> PostLayout.Card
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PostLayout.toInt(): Int = when (this) {
|
fun PostLayout.toInt(): Int =
|
||||||
|
when (this) {
|
||||||
PostLayout.Full -> 2
|
PostLayout.Full -> 2
|
||||||
PostLayout.Compact -> 1
|
PostLayout.Compact -> 1
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
@ -5,19 +5,23 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface UiBarTheme {
|
sealed interface UiBarTheme {
|
||||||
data object Solid : UiBarTheme
|
data object Solid : UiBarTheme
|
||||||
|
|
||||||
data object Transparent : UiBarTheme
|
data object Transparent : UiBarTheme
|
||||||
|
|
||||||
data object Opaque : UiBarTheme
|
data object Opaque : UiBarTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UiBarTheme?.toInt(): Int = when (this) {
|
fun UiBarTheme?.toInt(): Int =
|
||||||
|
when (this) {
|
||||||
UiBarTheme.Transparent -> 2
|
UiBarTheme.Transparent -> 2
|
||||||
UiBarTheme.Opaque -> 1
|
UiBarTheme.Opaque -> 1
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UiBarTheme?.toReadableName(): String = when (this) {
|
fun UiBarTheme?.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
UiBarTheme.Transparent -> LocalXmlStrings.current.barThemeTransparent
|
UiBarTheme.Transparent -> LocalXmlStrings.current.barThemeTransparent
|
||||||
UiBarTheme.Opaque -> LocalXmlStrings.current.barThemeOpaque
|
UiBarTheme.Opaque -> LocalXmlStrings.current.barThemeOpaque
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
|
@ -10,24 +10,27 @@ enum class UiFontFamily {
|
|||||||
Poppins,
|
Poppins,
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toUiFontFamily() = when (this) {
|
fun Int.toUiFontFamily() =
|
||||||
|
when (this) {
|
||||||
0 -> UiFontFamily.Poppins
|
0 -> UiFontFamily.Poppins
|
||||||
3 -> UiFontFamily.NotoSans
|
3 -> UiFontFamily.NotoSans
|
||||||
4 -> UiFontFamily.CharisSIL
|
4 -> UiFontFamily.CharisSIL
|
||||||
else -> UiFontFamily.Default
|
else -> UiFontFamily.Default
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UiFontFamily.toInt() = when (this) {
|
fun UiFontFamily.toInt() =
|
||||||
|
when (this) {
|
||||||
UiFontFamily.Poppins -> 0
|
UiFontFamily.Poppins -> 0
|
||||||
UiFontFamily.NotoSans -> 3
|
UiFontFamily.NotoSans -> 3
|
||||||
UiFontFamily.CharisSIL -> 4
|
UiFontFamily.CharisSIL -> 4
|
||||||
UiFontFamily.Default -> 7
|
UiFontFamily.Default -> 7
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UiFontFamily.toReadableName() = when (this) {
|
fun UiFontFamily.toReadableName() =
|
||||||
|
when (this) {
|
||||||
UiFontFamily.Poppins -> "Poppins"
|
UiFontFamily.Poppins -> "Poppins"
|
||||||
UiFontFamily.NotoSans -> "Noto Sans"
|
UiFontFamily.NotoSans -> "Noto Sans"
|
||||||
UiFontFamily.CharisSIL -> "Charis SIL"
|
UiFontFamily.CharisSIL -> "Charis SIL"
|
||||||
UiFontFamily.Default -> LocalXmlStrings.current.settingsFontFamilyDefault
|
UiFontFamily.Default -> LocalXmlStrings.current.settingsFontFamilyDefault
|
||||||
}
|
}
|
||||||
|
@ -10,34 +10,40 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface UiTheme {
|
sealed interface UiTheme {
|
||||||
data object Light : UiTheme
|
data object Light : UiTheme
|
||||||
|
|
||||||
data object Dark : UiTheme
|
data object Dark : UiTheme
|
||||||
|
|
||||||
data object Black : UiTheme
|
data object Black : UiTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int?.toUiTheme(): UiTheme? = when (this) {
|
fun Int?.toUiTheme(): UiTheme? =
|
||||||
|
when (this) {
|
||||||
2 -> UiTheme.Black
|
2 -> UiTheme.Black
|
||||||
1 -> UiTheme.Dark
|
1 -> UiTheme.Dark
|
||||||
0 -> UiTheme.Light
|
0 -> UiTheme.Light
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UiTheme?.toInt(): Int? = when (this) {
|
fun UiTheme?.toInt(): Int? =
|
||||||
|
when (this) {
|
||||||
UiTheme.Black -> 2
|
UiTheme.Black -> 2
|
||||||
UiTheme.Dark -> 1
|
UiTheme.Dark -> 1
|
||||||
UiTheme.Light -> 0
|
UiTheme.Light -> 0
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UiTheme?.toReadableName(): String = when (this) {
|
fun UiTheme?.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
UiTheme.Black -> LocalXmlStrings.current.settingsThemeBlack
|
UiTheme.Black -> LocalXmlStrings.current.settingsThemeBlack
|
||||||
UiTheme.Dark -> LocalXmlStrings.current.settingsThemeDark
|
UiTheme.Dark -> LocalXmlStrings.current.settingsThemeDark
|
||||||
UiTheme.Light -> LocalXmlStrings.current.settingsThemeLight
|
UiTheme.Light -> LocalXmlStrings.current.settingsThemeLight
|
||||||
else -> LocalXmlStrings.current.settingsFontFamilyDefault
|
else -> LocalXmlStrings.current.settingsFontFamilyDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UiTheme.toIcon(): ImageVector = when (this) {
|
fun UiTheme.toIcon(): ImageVector =
|
||||||
|
when (this) {
|
||||||
UiTheme.Black -> Icons.Default.DarkMode
|
UiTheme.Black -> Icons.Default.DarkMode
|
||||||
UiTheme.Dark -> Icons.Outlined.DarkMode
|
UiTheme.Dark -> Icons.Outlined.DarkMode
|
||||||
UiTheme.Light -> Icons.Default.LightMode
|
UiTheme.Light -> Icons.Default.LightMode
|
||||||
}
|
}
|
||||||
|
@ -9,32 +9,38 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface VoteFormat {
|
sealed interface VoteFormat {
|
||||||
data object Aggregated : VoteFormat
|
data object Aggregated : VoteFormat
|
||||||
|
|
||||||
data object Separated : VoteFormat
|
data object Separated : VoteFormat
|
||||||
|
|
||||||
data object Percentage : VoteFormat
|
data object Percentage : VoteFormat
|
||||||
|
|
||||||
data object Hidden : VoteFormat
|
data object Hidden : VoteFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VoteFormat.toLong(): Long = when (this) {
|
fun VoteFormat.toLong(): Long =
|
||||||
|
when (this) {
|
||||||
VoteFormat.Percentage -> 2L
|
VoteFormat.Percentage -> 2L
|
||||||
VoteFormat.Separated -> 1L
|
VoteFormat.Separated -> 1L
|
||||||
VoteFormat.Aggregated -> 0L
|
VoteFormat.Aggregated -> 0L
|
||||||
VoteFormat.Hidden -> -1L
|
VoteFormat.Hidden -> -1L
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Long.toVoteFormat(): VoteFormat = when (this) {
|
fun Long.toVoteFormat(): VoteFormat =
|
||||||
|
when (this) {
|
||||||
2L -> VoteFormat.Percentage
|
2L -> VoteFormat.Percentage
|
||||||
1L -> VoteFormat.Separated
|
1L -> VoteFormat.Separated
|
||||||
-1L -> VoteFormat.Hidden
|
-1L -> VoteFormat.Hidden
|
||||||
else -> VoteFormat.Aggregated
|
else -> VoteFormat.Aggregated
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VoteFormat.toReadableName(): String = when (this) {
|
fun VoteFormat.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
VoteFormat.Percentage -> LocalXmlStrings.current.settingsVoteFormatPercentage
|
VoteFormat.Percentage -> LocalXmlStrings.current.settingsVoteFormatPercentage
|
||||||
VoteFormat.Separated -> LocalXmlStrings.current.settingsVoteFormatSeparated
|
VoteFormat.Separated -> LocalXmlStrings.current.settingsVoteFormatSeparated
|
||||||
VoteFormat.Hidden -> LocalXmlStrings.current.settingsVoteFormatHidden
|
VoteFormat.Hidden -> LocalXmlStrings.current.settingsVoteFormatHidden
|
||||||
else -> LocalXmlStrings.current.settingsVoteFormatAggregated
|
else -> LocalXmlStrings.current.settingsVoteFormatAggregated
|
||||||
}
|
}
|
||||||
|
|
||||||
fun formatToReadableValue(
|
fun formatToReadableValue(
|
||||||
voteFormat: VoteFormat,
|
voteFormat: VoteFormat,
|
||||||
@ -45,7 +51,8 @@ fun formatToReadableValue(
|
|||||||
downVoteColor: Color,
|
downVoteColor: Color,
|
||||||
upVoted: Boolean = false,
|
upVoted: Boolean = false,
|
||||||
downVoted: Boolean = false,
|
downVoted: Boolean = false,
|
||||||
): AnnotatedString = buildAnnotatedString {
|
): AnnotatedString =
|
||||||
|
buildAnnotatedString {
|
||||||
when (voteFormat) {
|
when (voteFormat) {
|
||||||
VoteFormat.Percentage -> {
|
VoteFormat.Percentage -> {
|
||||||
val totalVotes = upVotes + downVotes
|
val totalVotes = upVotes + downVotes
|
||||||
@ -107,4 +114,4 @@ fun formatToReadableValue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.repository.Theme
|
|||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val coreAppearanceModule = module {
|
val coreAppearanceModule =
|
||||||
|
module {
|
||||||
includes(nativeAppearanceModule)
|
includes(nativeAppearanceModule)
|
||||||
|
|
||||||
singleOf<ThemeRepository>(::DefaultThemeRepository)
|
singleOf<ThemeRepository>(::DefaultThemeRepository)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.ColorSchem
|
|||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
|
||||||
expect val nativeAppearanceModule: Module
|
expect val nativeAppearanceModule: Module
|
||||||
|
|
||||||
expect fun getThemeRepository(): ThemeRepository
|
expect fun getThemeRepository(): ThemeRepository
|
||||||
|
|
||||||
expect fun getColorSchemeProvider(): ColorSchemeProvider
|
expect fun getColorSchemeProvider(): ColorSchemeProvider
|
||||||
|
|
||||||
expect fun getBarColorProvider(): BarColorProvider
|
expect fun getBarColorProvider(): BarColorProvider
|
||||||
|
@ -9,7 +9,10 @@ data class ContentFontScales(
|
|||||||
|
|
||||||
sealed interface ContentFontClass {
|
sealed interface ContentFontClass {
|
||||||
data object Title : ContentFontClass
|
data object Title : ContentFontClass
|
||||||
|
|
||||||
data object Body : ContentFontClass
|
data object Body : ContentFontClass
|
||||||
|
|
||||||
data object Comment : ContentFontClass
|
data object Comment : ContentFontClass
|
||||||
|
|
||||||
data object AncillaryText : ContentFontClass
|
data object AncillaryText : ContentFontClass
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
internal class DefaultThemeRepository : ThemeRepository {
|
internal class DefaultThemeRepository : ThemeRepository {
|
||||||
|
|
||||||
override val uiTheme = MutableStateFlow<UiTheme?>(null)
|
override val uiTheme = MutableStateFlow<UiTheme?>(null)
|
||||||
override val uiFontFamily = MutableStateFlow(UiFontFamily.Poppins)
|
override val uiFontFamily = MutableStateFlow(UiFontFamily.Poppins)
|
||||||
override val uiFontScale = MutableStateFlow(1f)
|
override val uiFontScale = MutableStateFlow(1f)
|
||||||
@ -52,7 +51,10 @@ internal class DefaultThemeRepository : ThemeRepository {
|
|||||||
dynamicColors.value = value
|
dynamicColors.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCommentBarColor(depth: Int, commentBarTheme: CommentBarTheme): Color {
|
override fun getCommentBarColor(
|
||||||
|
depth: Int,
|
||||||
|
commentBarTheme: CommentBarTheme,
|
||||||
|
): Color {
|
||||||
val colors = getCommentBarColors(commentBarTheme)
|
val colors = getCommentBarColors(commentBarTheme)
|
||||||
if (colors.isEmpty()) {
|
if (colors.isEmpty()) {
|
||||||
return Color.Transparent
|
return Color.Transparent
|
||||||
@ -91,7 +93,8 @@ internal class DefaultThemeRepository : ThemeRepository {
|
|||||||
|
|
||||||
override fun getCommentBarColors(commentBarTheme: CommentBarTheme): List<Color> =
|
override fun getCommentBarColors(commentBarTheme: CommentBarTheme): List<Color> =
|
||||||
when (commentBarTheme) {
|
when (commentBarTheme) {
|
||||||
CommentBarTheme.Green -> buildList {
|
CommentBarTheme.Green ->
|
||||||
|
buildList {
|
||||||
this += Color(0xFF1B4332)
|
this += Color(0xFF1B4332)
|
||||||
this += Color(0xFF2D6A4F)
|
this += Color(0xFF2D6A4F)
|
||||||
this += Color(0xFF40916C)
|
this += Color(0xFF40916C)
|
||||||
@ -100,7 +103,8 @@ internal class DefaultThemeRepository : ThemeRepository {
|
|||||||
this += Color(0xFF95D5B2)
|
this += Color(0xFF95D5B2)
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentBarTheme.Red -> buildList {
|
CommentBarTheme.Red ->
|
||||||
|
buildList {
|
||||||
this += Color(0xFF6A040F)
|
this += Color(0xFF6A040F)
|
||||||
this += Color(0xFF9D0208)
|
this += Color(0xFF9D0208)
|
||||||
this += Color(0xFFD00000)
|
this += Color(0xFFD00000)
|
||||||
@ -109,7 +113,8 @@ internal class DefaultThemeRepository : ThemeRepository {
|
|||||||
this += Color(0xFFF48C06)
|
this += Color(0xFFF48C06)
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentBarTheme.Blue -> buildList {
|
CommentBarTheme.Blue ->
|
||||||
|
buildList {
|
||||||
this += Color(0xFF012A4A)
|
this += Color(0xFF012A4A)
|
||||||
this += Color(0xFF013A63)
|
this += Color(0xFF013A63)
|
||||||
this += Color(0xFF014F86)
|
this += Color(0xFF014F86)
|
||||||
@ -118,7 +123,8 @@ internal class DefaultThemeRepository : ThemeRepository {
|
|||||||
this += Color(0xFFA9D6E5)
|
this += Color(0xFFA9D6E5)
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentBarTheme.Rainbow -> buildList {
|
CommentBarTheme.Rainbow ->
|
||||||
|
buildList {
|
||||||
this += Color(0xFF9400D3)
|
this += Color(0xFF9400D3)
|
||||||
this += Color(0xFF0000FF)
|
this += Color(0xFF0000FF)
|
||||||
this += Color(0xFF00FF00)
|
this += Color(0xFF00FF00)
|
||||||
|
@ -10,7 +10,6 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
interface ThemeRepository {
|
interface ThemeRepository {
|
||||||
|
|
||||||
val uiTheme: StateFlow<UiTheme?>
|
val uiTheme: StateFlow<UiTheme?>
|
||||||
val uiFontFamily: StateFlow<UiFontFamily>
|
val uiFontFamily: StateFlow<UiFontFamily>
|
||||||
val uiFontScale: StateFlow<Float>
|
val uiFontScale: StateFlow<Float>
|
||||||
@ -40,7 +39,10 @@ interface ThemeRepository {
|
|||||||
|
|
||||||
fun changeDynamicColors(value: Boolean)
|
fun changeDynamicColors(value: Boolean)
|
||||||
|
|
||||||
fun getCommentBarColor(depth: Int, commentBarTheme: CommentBarTheme): Color
|
fun getCommentBarColor(
|
||||||
|
depth: Int,
|
||||||
|
commentBarTheme: CommentBarTheme,
|
||||||
|
): Color
|
||||||
|
|
||||||
fun changeCustomSeedColor(color: Color?)
|
fun changeCustomSeedColor(color: Color?)
|
||||||
|
|
||||||
@ -49,6 +51,7 @@ interface ThemeRepository {
|
|||||||
fun changeDownVoteColor(color: Color?)
|
fun changeDownVoteColor(color: Color?)
|
||||||
|
|
||||||
fun changeReplyColor(color: Color?)
|
fun changeReplyColor(color: Color?)
|
||||||
|
|
||||||
fun changeSaveColor(color: Color?)
|
fun changeSaveColor(color: Color?)
|
||||||
|
|
||||||
fun changePostLayout(value: PostLayout)
|
fun changePostLayout(value: PostLayout)
|
||||||
|
@ -18,20 +18,23 @@ fun AppTheme(
|
|||||||
barTheme: UiBarTheme = UiBarTheme.Solid,
|
barTheme: UiBarTheme = UiBarTheme.Solid,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
val repository = remember {
|
val repository =
|
||||||
|
remember {
|
||||||
getThemeRepository()
|
getThemeRepository()
|
||||||
}
|
}
|
||||||
|
|
||||||
val themeState by repository.uiTheme.collectAsState()
|
val themeState by repository.uiTheme.collectAsState()
|
||||||
val customSeedColor by repository.customSeedColor.collectAsState()
|
val customSeedColor by repository.customSeedColor.collectAsState()
|
||||||
val defaultTheme = if (isSystemInDarkTheme()) {
|
val defaultTheme =
|
||||||
|
if (isSystemInDarkTheme()) {
|
||||||
UiTheme.Dark
|
UiTheme.Dark
|
||||||
} else {
|
} else {
|
||||||
UiTheme.Light
|
UiTheme.Light
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorSchemeProvider = remember { getColorSchemeProvider() }
|
val colorSchemeProvider = remember { getColorSchemeProvider() }
|
||||||
val colorScheme = colorSchemeProvider.getColorScheme(
|
val colorScheme =
|
||||||
|
colorSchemeProvider.getColorScheme(
|
||||||
theme = themeState ?: defaultTheme,
|
theme = themeState ?: defaultTheme,
|
||||||
dynamic = useDynamicColors,
|
dynamic = useDynamicColors,
|
||||||
customSeed = customSeedColor,
|
customSeed = customSeedColor,
|
||||||
|
@ -6,5 +6,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
|
|
||||||
interface BarColorProvider {
|
interface BarColorProvider {
|
||||||
@Composable
|
@Composable
|
||||||
fun setBarColorAccordingToTheme(theme: UiTheme, barTheme: UiBarTheme)
|
fun setBarColorAccordingToTheme(
|
||||||
|
theme: UiTheme,
|
||||||
|
barTheme: UiBarTheme,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
interface ColorSchemeProvider {
|
interface ColorSchemeProvider {
|
||||||
|
|
||||||
val supportsDynamicColors: Boolean
|
val supportsDynamicColors: Boolean
|
||||||
|
|
||||||
fun getColorScheme(
|
fun getColorScheme(
|
||||||
@ -17,7 +16,8 @@ interface ColorSchemeProvider {
|
|||||||
): ColorScheme
|
): ColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ColorScheme.blackify(): ColorScheme = copy(
|
fun ColorScheme.blackify(): ColorScheme =
|
||||||
|
copy(
|
||||||
background = md_theme_black_background,
|
background = md_theme_black_background,
|
||||||
onBackground = md_theme_black_onBackground,
|
onBackground = md_theme_black_onBackground,
|
||||||
surface = md_theme_black_surface,
|
surface = md_theme_black_surface,
|
||||||
@ -30,4 +30,4 @@ fun ColorScheme.blackify(): ColorScheme = copy(
|
|||||||
onSecondaryContainer = md_theme_black_onSecondaryContainer,
|
onSecondaryContainer = md_theme_black_onSecondaryContainer,
|
||||||
tertiaryContainer = md_theme_black_tertiaryContainer,
|
tertiaryContainer = md_theme_black_tertiaryContainer,
|
||||||
onTertiaryContainer = md_theme_black_onTertiaryContainer,
|
onTertiaryContainer = md_theme_black_onTertiaryContainer,
|
||||||
)
|
)
|
||||||
|
@ -3,7 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme
|
|||||||
import androidx.compose.material3.darkColorScheme
|
import androidx.compose.material3.darkColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
|
|
||||||
internal val LightColors = lightColorScheme(
|
internal val LightColors =
|
||||||
|
lightColorScheme(
|
||||||
primary = md_theme_light_primary,
|
primary = md_theme_light_primary,
|
||||||
onPrimary = md_theme_light_onPrimary,
|
onPrimary = md_theme_light_onPrimary,
|
||||||
primaryContainer = md_theme_light_primaryContainer,
|
primaryContainer = md_theme_light_primaryContainer,
|
||||||
@ -33,9 +34,10 @@ internal val LightColors = lightColorScheme(
|
|||||||
surfaceTint = md_theme_light_surfaceTint,
|
surfaceTint = md_theme_light_surfaceTint,
|
||||||
outlineVariant = md_theme_light_outlineVariant,
|
outlineVariant = md_theme_light_outlineVariant,
|
||||||
scrim = md_theme_light_scrim,
|
scrim = md_theme_light_scrim,
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val DarkColors = darkColorScheme(
|
internal val DarkColors =
|
||||||
|
darkColorScheme(
|
||||||
primary = md_theme_dark_primary,
|
primary = md_theme_dark_primary,
|
||||||
onPrimary = md_theme_dark_onPrimary,
|
onPrimary = md_theme_dark_onPrimary,
|
||||||
primaryContainer = md_theme_dark_primaryContainer,
|
primaryContainer = md_theme_dark_primaryContainer,
|
||||||
@ -65,6 +67,6 @@ internal val DarkColors = darkColorScheme(
|
|||||||
surfaceTint = md_theme_dark_surfaceTint,
|
surfaceTint = md_theme_dark_surfaceTint,
|
||||||
outlineVariant = md_theme_dark_outlineVariant,
|
outlineVariant = md_theme_dark_outlineVariant,
|
||||||
scrim = md_theme_dark_scrim,
|
scrim = md_theme_dark_scrim,
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val BlackColors = DarkColors.blackify()
|
internal val BlackColors = DarkColors.blackify()
|
||||||
|
@ -17,7 +17,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.resources.di.getCoreResourc
|
|||||||
@Composable
|
@Composable
|
||||||
fun UiFontFamily.toTypography(): Typography {
|
fun UiFontFamily.toTypography(): Typography {
|
||||||
val coreResources = remember { getCoreResources() }
|
val coreResources = remember { getCoreResources() }
|
||||||
val fontFamily = when (this) {
|
val fontFamily =
|
||||||
|
when (this) {
|
||||||
UiFontFamily.NotoSans -> coreResources.notoSans
|
UiFontFamily.NotoSans -> coreResources.notoSans
|
||||||
UiFontFamily.CharisSIL -> coreResources.charisSil
|
UiFontFamily.CharisSIL -> coreResources.charisSil
|
||||||
UiFontFamily.Poppins -> coreResources.poppins
|
UiFontFamily.Poppins -> coreResources.poppins
|
||||||
@ -25,7 +26,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
}
|
}
|
||||||
return Typography(
|
return Typography(
|
||||||
// h1
|
// h1
|
||||||
displayLarge = TextStyle(
|
displayLarge =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 57.sp,
|
fontSize = 57.sp,
|
||||||
@ -33,7 +35,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 64.sp,
|
lineHeight = 64.sp,
|
||||||
),
|
),
|
||||||
// h2
|
// h2
|
||||||
displayMedium = TextStyle(
|
displayMedium =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 45.sp,
|
fontSize = 45.sp,
|
||||||
@ -41,14 +44,16 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 52.sp,
|
lineHeight = 52.sp,
|
||||||
),
|
),
|
||||||
// h3
|
// h3
|
||||||
displaySmall = TextStyle(
|
displaySmall =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 36.sp,
|
fontSize = 36.sp,
|
||||||
letterSpacing = 0.sp,
|
letterSpacing = 0.sp,
|
||||||
lineHeight = 44.sp,
|
lineHeight = 44.sp,
|
||||||
),
|
),
|
||||||
headlineLarge = TextStyle(
|
headlineLarge =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 32.sp,
|
fontSize = 32.sp,
|
||||||
@ -56,7 +61,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 40.sp,
|
lineHeight = 40.sp,
|
||||||
),
|
),
|
||||||
// h4
|
// h4
|
||||||
headlineMedium = TextStyle(
|
headlineMedium =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 28.sp,
|
fontSize = 28.sp,
|
||||||
@ -64,7 +70,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 36.sp,
|
lineHeight = 36.sp,
|
||||||
),
|
),
|
||||||
// h5
|
// h5
|
||||||
headlineSmall = TextStyle(
|
headlineSmall =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 24.sp,
|
fontSize = 24.sp,
|
||||||
@ -72,7 +79,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 23.sp,
|
lineHeight = 23.sp,
|
||||||
),
|
),
|
||||||
// h6
|
// h6
|
||||||
titleLarge = TextStyle(
|
titleLarge =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 22.sp,
|
fontSize = 22.sp,
|
||||||
@ -80,7 +88,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 28.sp,
|
lineHeight = 28.sp,
|
||||||
),
|
),
|
||||||
// subtitle1
|
// subtitle1
|
||||||
titleMedium = TextStyle(
|
titleMedium =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
@ -88,7 +97,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 24.sp,
|
lineHeight = 24.sp,
|
||||||
),
|
),
|
||||||
// subtitle2
|
// subtitle2
|
||||||
titleSmall = TextStyle(
|
titleSmall =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
@ -96,7 +106,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
// body1
|
// body1
|
||||||
bodyLarge = TextStyle(
|
bodyLarge =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
@ -104,7 +115,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 24.sp,
|
lineHeight = 24.sp,
|
||||||
),
|
),
|
||||||
// body2
|
// body2
|
||||||
bodyMedium = TextStyle(
|
bodyMedium =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
@ -112,7 +124,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
// caption
|
// caption
|
||||||
bodySmall = TextStyle(
|
bodySmall =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
@ -120,14 +133,16 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
),
|
),
|
||||||
// button
|
// button
|
||||||
labelLarge = TextStyle(
|
labelLarge =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
letterSpacing = (0.1).sp,
|
letterSpacing = (0.1).sp,
|
||||||
lineHeight = 20.sp,
|
lineHeight = 20.sp,
|
||||||
),
|
),
|
||||||
labelMedium = TextStyle(
|
labelMedium =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
@ -135,7 +150,8 @@ fun UiFontFamily.toTypography(): Typography {
|
|||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
),
|
),
|
||||||
// overline
|
// overline
|
||||||
labelSmall = TextStyle(
|
labelSmall =
|
||||||
|
TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontWeight = FontWeight.Medium,
|
fontWeight = FontWeight.Medium,
|
||||||
fontSize = 11.sp,
|
fontSize = 11.sp,
|
||||||
|
@ -4,8 +4,9 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material3.Shapes
|
import androidx.compose.material3.Shapes
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
internal val shapes = Shapes(
|
internal val shapes =
|
||||||
|
Shapes(
|
||||||
small = RoundedCornerShape(4.dp),
|
small = RoundedCornerShape(4.dp),
|
||||||
medium = RoundedCornerShape(4.dp),
|
medium = RoundedCornerShape(4.dp),
|
||||||
large = RoundedCornerShape(0.dp),
|
large = RoundedCornerShape(0.dp),
|
||||||
)
|
)
|
||||||
|
@ -11,19 +11,19 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
actual fun getThemeRepository(): ThemeRepository = CoreAppearanceHelper.repository
|
actual fun getThemeRepository(): ThemeRepository = CoreAppearanceHelper.repository
|
||||||
|
|
||||||
actual val nativeAppearanceModule = module {
|
actual val nativeAppearanceModule =
|
||||||
|
module {
|
||||||
single<ColorSchemeProvider> {
|
single<ColorSchemeProvider> {
|
||||||
DefaultColorSchemeProvider()
|
DefaultColorSchemeProvider()
|
||||||
}
|
}
|
||||||
single<BarColorProvider> {
|
single<BarColorProvider> {
|
||||||
DefaultBarColorProvider()
|
DefaultBarColorProvider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getColorSchemeProvider(): ColorSchemeProvider = CoreAppearanceHelper.colorSchemeProvider
|
actual fun getColorSchemeProvider(): ColorSchemeProvider = CoreAppearanceHelper.colorSchemeProvider
|
||||||
|
|
||||||
actual fun getBarColorProvider(): BarColorProvider =
|
actual fun getBarColorProvider(): BarColorProvider = CoreAppearanceHelper.barColorProvider
|
||||||
CoreAppearanceHelper.barColorProvider
|
|
||||||
|
|
||||||
object CoreAppearanceHelper : KoinComponent {
|
object CoreAppearanceHelper : KoinComponent {
|
||||||
internal val repository: ThemeRepository by inject()
|
internal val repository: ThemeRepository by inject()
|
||||||
|
@ -11,9 +11,13 @@ import platform.UIKit.setStatusBarStyle
|
|||||||
|
|
||||||
class DefaultBarColorProvider : BarColorProvider {
|
class DefaultBarColorProvider : BarColorProvider {
|
||||||
@Composable
|
@Composable
|
||||||
override fun setBarColorAccordingToTheme(theme: UiTheme, transparent: UiBarTheme) {
|
override fun setBarColorAccordingToTheme(
|
||||||
|
theme: UiTheme,
|
||||||
|
transparent: UiBarTheme,
|
||||||
|
) {
|
||||||
LaunchedEffect(theme) {
|
LaunchedEffect(theme) {
|
||||||
val style = when {
|
val style =
|
||||||
|
when {
|
||||||
theme == UiTheme.Light -> UIStatusBarStyleLightContent
|
theme == UiTheme.Light -> UIStatusBarStyleLightContent
|
||||||
else -> UIStatusBarStyleDarkContent
|
else -> UIStatusBarStyleDarkContent
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
|
|||||||
import com.materialkolor.dynamicColorScheme
|
import com.materialkolor.dynamicColorScheme
|
||||||
|
|
||||||
internal class DefaultColorSchemeProvider : ColorSchemeProvider {
|
internal class DefaultColorSchemeProvider : ColorSchemeProvider {
|
||||||
|
|
||||||
override val supportsDynamicColors = false
|
override val supportsDynamicColors = false
|
||||||
|
|
||||||
override fun getColorScheme(
|
override fun getColorScheme(
|
||||||
theme: UiTheme,
|
theme: UiTheme,
|
||||||
dynamic: Boolean,
|
dynamic: Boolean,
|
||||||
customSeed: Color?,
|
customSeed: Color?,
|
||||||
): ColorScheme = when (theme) {
|
): ColorScheme =
|
||||||
|
when (theme) {
|
||||||
UiTheme.Dark -> {
|
UiTheme.Dark -> {
|
||||||
if (customSeed != null) {
|
if (customSeed != null) {
|
||||||
dynamicColorScheme(customSeed, true)
|
dynamicColorScheme(customSeed, true)
|
||||||
|
@ -18,7 +18,6 @@ import kotlinx.coroutines.flow.update
|
|||||||
abstract class DefaultMviModel<Intent, State, Effect>(
|
abstract class DefaultMviModel<Intent, State, Effect>(
|
||||||
initialState: State,
|
initialState: State,
|
||||||
) : MviModel<Intent, State, Effect> {
|
) : MviModel<Intent, State, Effect> {
|
||||||
|
|
||||||
override val uiState = MutableStateFlow(initialState)
|
override val uiState = MutableStateFlow(initialState)
|
||||||
override val effects = MutableSharedFlow<Effect>()
|
override val effects = MutableSharedFlow<Effect>()
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
* Model contract for Model-View-Intent architecture.
|
* Model contract for Model-View-Intent architecture.
|
||||||
*/
|
*/
|
||||||
interface MviModel<Intent, State, Effect> {
|
interface MviModel<Intent, State, Effect> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of the state holder's state for the view to consume.
|
* Representation of the state holder's state for the view to consume.
|
||||||
*/
|
*/
|
||||||
|
@ -39,12 +39,18 @@ actual fun CustomWebView(
|
|||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
factory = { context ->
|
factory = { context ->
|
||||||
WebView(context).apply {
|
WebView(context).apply {
|
||||||
layoutParams = ViewGroup.LayoutParams(
|
layoutParams =
|
||||||
|
ViewGroup.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
)
|
)
|
||||||
webViewClient = object : WebViewClient() {
|
webViewClient =
|
||||||
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
|
object : WebViewClient() {
|
||||||
|
override fun onPageStarted(
|
||||||
|
view: WebView,
|
||||||
|
url: String?,
|
||||||
|
favicon: Bitmap?,
|
||||||
|
) {
|
||||||
navigator.canGoBack = view.canGoBack()
|
navigator.canGoBack = view.canGoBack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +58,8 @@ actual fun CustomWebView(
|
|||||||
|
|
||||||
setOnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY ->
|
setOnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY ->
|
||||||
scrollConnection?.onPreScroll(
|
scrollConnection?.onPreScroll(
|
||||||
available = Offset(
|
available =
|
||||||
|
Offset(
|
||||||
x = (oldScrollX - scrollX) / density,
|
x = (oldScrollX - scrollX) / density,
|
||||||
y = (oldScrollY - scrollY) / density,
|
y = (oldScrollY - scrollY) / density,
|
||||||
),
|
),
|
||||||
|
@ -29,16 +29,19 @@ actual fun VideoPlayer(
|
|||||||
onPlaybackStarted: (() -> Unit)?,
|
onPlaybackStarted: (() -> Unit)?,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val exoPlayer = remember {
|
val exoPlayer =
|
||||||
|
remember {
|
||||||
ExoPlayer.Builder(context)
|
ExoPlayer.Builder(context)
|
||||||
.build()
|
.build()
|
||||||
.apply {
|
.apply {
|
||||||
val defaultDataSourceFactory = DefaultDataSource.Factory(context)
|
val defaultDataSourceFactory = DefaultDataSource.Factory(context)
|
||||||
val dataSourceFactory: DataSource.Factory = DefaultDataSource.Factory(
|
val dataSourceFactory: DataSource.Factory =
|
||||||
|
DefaultDataSource.Factory(
|
||||||
context,
|
context,
|
||||||
defaultDataSourceFactory,
|
defaultDataSourceFactory,
|
||||||
)
|
)
|
||||||
val source = ProgressiveMediaSource.Factory(dataSourceFactory)
|
val source =
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||||
.createMediaSource(MediaItem.fromUri(url))
|
.createMediaSource(MediaItem.fromUri(url))
|
||||||
setMediaSource(source)
|
setMediaSource(source)
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ fun BottomSheetHeader(
|
|||||||
modifier = Modifier.padding(bottom = Spacing.xs),
|
modifier = Modifier.padding(bottom = Spacing.xs),
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
top = Spacing.xs,
|
top = Spacing.xs,
|
||||||
bottom = Spacing.xs,
|
bottom = Spacing.xs,
|
||||||
),
|
),
|
||||||
@ -44,11 +45,10 @@ fun BottomSheetHeader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BottomSheetHandle(
|
private fun BottomSheetHandle(modifier: Modifier = Modifier) {
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.width(60.dp)
|
modifier =
|
||||||
|
modifier.width(60.dp)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
bottom = Spacing.xxxs,
|
bottom = Spacing.xxxs,
|
||||||
|
@ -18,7 +18,8 @@ fun CustomizedContent(
|
|||||||
val themeRepository = remember { getThemeRepository() }
|
val themeRepository = remember { getThemeRepository() }
|
||||||
val fontScale by themeRepository.contentFontScale.collectAsState()
|
val fontScale by themeRepository.contentFontScale.collectAsState()
|
||||||
val uiFontScale by themeRepository.uiFontScale.collectAsState()
|
val uiFontScale by themeRepository.uiFontScale.collectAsState()
|
||||||
val scaleFactor = when (contentClass) {
|
val scaleFactor =
|
||||||
|
when (contentClass) {
|
||||||
ContentFontClass.Title -> fontScale.title
|
ContentFontClass.Title -> fontScale.title
|
||||||
ContentFontClass.Body -> fontScale.body
|
ContentFontClass.Body -> fontScale.body
|
||||||
ContentFontClass.Comment -> fontScale.comment
|
ContentFontClass.Comment -> fontScale.comment
|
||||||
@ -26,7 +27,8 @@ fun CustomizedContent(
|
|||||||
} * uiFontScale
|
} * uiFontScale
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalDensity provides Density(
|
LocalDensity provides
|
||||||
|
Density(
|
||||||
density = LocalDensity.current.density,
|
density = LocalDensity.current.density,
|
||||||
fontScale = scaleFactor,
|
fontScale = scaleFactor,
|
||||||
),
|
),
|
||||||
|
@ -32,6 +32,7 @@ import kotlin.math.roundToInt
|
|||||||
|
|
||||||
private sealed interface SlideAnchorPosition {
|
private sealed interface SlideAnchorPosition {
|
||||||
data object Opened : SlideAnchorPosition
|
data object Opened : SlideAnchorPosition
|
||||||
|
|
||||||
data object Closed : SlideAnchorPosition
|
data object Closed : SlideAnchorPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,10 +47,12 @@ fun DraggableSideMenu(
|
|||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val maxWidth = if (availableWidth.isSpecified) availableWidth * 0.85f else 500.dp
|
val maxWidth = if (availableWidth.isSpecified) availableWidth * 0.85f else 500.dp
|
||||||
val draggableState = remember(availableWidth) {
|
val draggableState =
|
||||||
|
remember(availableWidth) {
|
||||||
AnchoredDraggableState(
|
AnchoredDraggableState(
|
||||||
initialValue = SlideAnchorPosition.Closed,
|
initialValue = SlideAnchorPosition.Closed,
|
||||||
anchors = DraggableAnchors<SlideAnchorPosition> {
|
anchors =
|
||||||
|
DraggableAnchors<SlideAnchorPosition> {
|
||||||
SlideAnchorPosition.Closed at with(density) { availableWidth.toPx() }
|
SlideAnchorPosition.Closed at with(density) { availableWidth.toPx() }
|
||||||
SlideAnchorPosition.Opened at with(density) { (availableWidth - maxWidth).toPx() }
|
SlideAnchorPosition.Opened at with(density) { (availableWidth - maxWidth).toPx() }
|
||||||
},
|
},
|
||||||
@ -60,7 +63,8 @@ fun DraggableSideMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(opened) {
|
LaunchedEffect(opened) {
|
||||||
val target = if (opened) {
|
val target =
|
||||||
|
if (opened) {
|
||||||
SlideAnchorPosition.Opened
|
SlideAnchorPosition.Opened
|
||||||
} else {
|
} else {
|
||||||
SlideAnchorPosition.Closed
|
SlideAnchorPosition.Closed
|
||||||
@ -77,7 +81,8 @@ fun DraggableSideMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.width(maxWidth)
|
.width(maxWidth)
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.offset {
|
.offset {
|
||||||
|
@ -32,7 +32,8 @@ fun FeedbackButton(
|
|||||||
animationSpec = spring(stiffness = StiffnessMediumLow),
|
animationSpec = spring(stiffness = StiffnessMediumLow),
|
||||||
)
|
)
|
||||||
Image(
|
Image(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.scale(scale)
|
.scale(scale)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
@ -48,7 +49,8 @@ fun FeedbackButton(
|
|||||||
},
|
},
|
||||||
imageVector = imageVector,
|
imageVector = imageVector,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(
|
colorFilter =
|
||||||
|
ColorFilter.tint(
|
||||||
color = tintColor,
|
color = tintColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -63,25 +63,29 @@ fun FloatingActionButtonMenu(
|
|||||||
val dynamicColors by themeRepository.dynamicColors.collectAsState()
|
val dynamicColors by themeRepository.dynamicColors.collectAsState()
|
||||||
var fabExpanded by remember { mutableStateOf(false) }
|
var fabExpanded by remember { mutableStateOf(false) }
|
||||||
val fabRotation by animateFloatAsState(if (fabExpanded) 45f else 0f)
|
val fabRotation by animateFloatAsState(if (fabExpanded) 45f else 0f)
|
||||||
val enterTransition = remember {
|
val enterTransition =
|
||||||
|
remember {
|
||||||
fadeIn(
|
fadeIn(
|
||||||
initialAlpha = 0.3f,
|
initialAlpha = 0.3f,
|
||||||
animationSpec = tween(ANIMATION_DURATION, easing = FastOutSlowInEasing),
|
animationSpec = tween(ANIMATION_DURATION, easing = FastOutSlowInEasing),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val exitTransition = remember {
|
val exitTransition =
|
||||||
|
remember {
|
||||||
fadeOut(
|
fadeOut(
|
||||||
animationSpec = tween(ANIMATION_DURATION, easing = FastOutSlowInEasing),
|
animationSpec = tween(ANIMATION_DURATION, easing = FastOutSlowInEasing),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val numberOfItems by animateIntAsState(
|
val numberOfItems by animateIntAsState(
|
||||||
targetValue = if (fabExpanded) items.size else 0,
|
targetValue = if (fabExpanded) items.size else 0,
|
||||||
animationSpec = tween(
|
animationSpec =
|
||||||
|
tween(
|
||||||
durationMillis = ANIMATION_DURATION * items.size,
|
durationMillis = ANIMATION_DURATION * items.size,
|
||||||
easing = LinearEasing,
|
easing = LinearEasing,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
val indices: List<Int> = if (numberOfItems == 0) {
|
val indices: List<Int> =
|
||||||
|
if (numberOfItems == 0) {
|
||||||
emptyList()
|
emptyList()
|
||||||
} else {
|
} else {
|
||||||
buildList {
|
buildList {
|
||||||
@ -107,7 +111,8 @@ fun FloatingActionButtonMenu(
|
|||||||
exit = exitTransition,
|
exit = exitTransition,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
fabExpanded = false
|
fabExpanded = false
|
||||||
item.onSelected?.invoke()
|
item.onSelected?.invoke()
|
||||||
@ -117,7 +122,8 @@ fun FloatingActionButtonMenu(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(horizontal = Spacing.xs)
|
.padding(horizontal = Spacing.xs)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
@ -131,7 +137,8 @@ fun FloatingActionButtonMenu(
|
|||||||
color = MaterialTheme.colorScheme.onBackground,
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.size(IconSize.m)
|
.size(IconSize.m)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.primaryContainer,
|
color = MaterialTheme.colorScheme.primaryContainer,
|
||||||
@ -147,8 +154,10 @@ fun FloatingActionButtonMenu(
|
|||||||
Spacer(modifier = Modifier.height(Spacing.xxs))
|
Spacer(modifier = Modifier.height(Spacing.xxs))
|
||||||
}
|
}
|
||||||
|
|
||||||
val fabContainerColor = when (theme) {
|
val fabContainerColor =
|
||||||
UiTheme.Black -> schemeProvider.getColorScheme(
|
when (theme) {
|
||||||
|
UiTheme.Black ->
|
||||||
|
schemeProvider.getColorScheme(
|
||||||
theme = UiTheme.Dark,
|
theme = UiTheme.Dark,
|
||||||
dynamic = dynamicColors,
|
dynamic = dynamicColors,
|
||||||
customSeed = seedColor,
|
customSeed = seedColor,
|
||||||
|
@ -23,7 +23,8 @@ fun PlaceholderImage(
|
|||||||
title: String,
|
title: String,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(size)
|
.size(size)
|
||||||
.background(
|
.background(
|
||||||
@ -34,7 +35,8 @@ fun PlaceholderImage(
|
|||||||
) {
|
) {
|
||||||
val translationAmount = with(LocalDensity.current) { 2.dp.toPx() }
|
val translationAmount = with(LocalDensity.current) { 2.dp.toPx() }
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.graphicsLayer {
|
modifier =
|
||||||
|
Modifier.graphicsLayer {
|
||||||
translationY = -translationAmount
|
translationY = -translationAmount
|
||||||
},
|
},
|
||||||
text = title.firstOrNull()?.toString().orEmpty().uppercase(),
|
text = title.firstOrNull()?.toString().orEmpty().uppercase(),
|
||||||
|
@ -16,7 +16,8 @@ fun ProgressHud(
|
|||||||
color: Color = MaterialTheme.colorScheme.primary,
|
color: Color = MaterialTheme.colorScheme.primary,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(overlayColor),
|
.background(overlayColor),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
|
@ -23,7 +23,8 @@ fun SectionSelector(
|
|||||||
onSectionSelected: (Int) -> Unit,
|
onSectionSelected: (Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
var isTowardsStart by remember { mutableStateOf(false) }
|
var isTowardsStart by remember { mutableStateOf(false) }
|
||||||
val draggableState = remember {
|
val draggableState =
|
||||||
|
remember {
|
||||||
DraggableState { delta ->
|
DraggableState { delta ->
|
||||||
isTowardsStart = delta > 0
|
isTowardsStart = delta > 0
|
||||||
}
|
}
|
||||||
@ -34,7 +35,8 @@ fun SectionSelector(
|
|||||||
tabs = {
|
tabs = {
|
||||||
titles.forEachIndexed { i, title ->
|
titles.forEachIndexed { i, title ->
|
||||||
Tab(
|
Tab(
|
||||||
modifier = Modifier.then(
|
modifier =
|
||||||
|
Modifier.then(
|
||||||
if (draggable) {
|
if (draggable) {
|
||||||
Modifier.draggable(
|
Modifier.draggable(
|
||||||
state = draggableState,
|
state = draggableState,
|
||||||
|
@ -52,8 +52,10 @@ fun SwipeActionCard(
|
|||||||
var secondNotified by remember { mutableStateOf(false) }
|
var secondNotified by remember { mutableStateOf(false) }
|
||||||
val gestureBeginCallback by rememberUpdatedState(onGestureBegin)
|
val gestureBeginCallback by rememberUpdatedState(onGestureBegin)
|
||||||
var lastProgress by remember { mutableStateOf(0.0f) }
|
var lastProgress by remember { mutableStateOf(0.0f) }
|
||||||
val dismissState = rememberNoFlingSwipeToDismissBoxState(
|
val dismissState =
|
||||||
confirmValueChange = rememberCallbackArgs { value ->
|
rememberNoFlingSwipeToDismissBoxState(
|
||||||
|
confirmValueChange =
|
||||||
|
rememberCallbackArgs { value ->
|
||||||
when (value) {
|
when (value) {
|
||||||
SwipeToDismissBoxValue.StartToEnd -> {
|
SwipeToDismissBoxValue.StartToEnd -> {
|
||||||
val enableSecondAction = swipeToEndActions.size > 1
|
val enableSecondAction = swipeToEndActions.size > 1
|
||||||
@ -83,7 +85,8 @@ fun SwipeActionCard(
|
|||||||
)
|
)
|
||||||
LaunchedEffect(dismissState, swipeToEndActions, swipeToEndActions) {
|
LaunchedEffect(dismissState, swipeToEndActions, swipeToEndActions) {
|
||||||
snapshotFlow { dismissState.progress }.onEach { progress ->
|
snapshotFlow { dismissState.progress }.onEach { progress ->
|
||||||
val enableSecondAction = when (dismissState.targetValue) {
|
val enableSecondAction =
|
||||||
|
when (dismissState.targetValue) {
|
||||||
SwipeToDismissBoxValue.Settled -> false
|
SwipeToDismissBoxValue.Settled -> false
|
||||||
SwipeToDismissBoxValue.StartToEnd -> swipeToEndActions.size > 1
|
SwipeToDismissBoxValue.StartToEnd -> swipeToEndActions.size > 1
|
||||||
SwipeToDismissBoxValue.EndToStart -> swipeToStartActions.size > 1
|
SwipeToDismissBoxValue.EndToStart -> swipeToStartActions.size > 1
|
||||||
@ -120,14 +123,16 @@ fun SwipeActionCard(
|
|||||||
enableDismissFromEndToStart = swipeToStartActions.isNotEmpty(),
|
enableDismissFromEndToStart = swipeToStartActions.isNotEmpty(),
|
||||||
backgroundContent = {
|
backgroundContent = {
|
||||||
val direction = dismissState.dismissDirection
|
val direction = dismissState.dismissDirection
|
||||||
val actions = when (dismissState.targetValue) {
|
val actions =
|
||||||
|
when (dismissState.targetValue) {
|
||||||
SwipeToDismissBoxValue.Settled -> listOf()
|
SwipeToDismissBoxValue.Settled -> listOf()
|
||||||
SwipeToDismissBoxValue.StartToEnd -> swipeToEndActions
|
SwipeToDismissBoxValue.StartToEnd -> swipeToEndActions
|
||||||
SwipeToDismissBoxValue.EndToStart -> swipeToStartActions
|
SwipeToDismissBoxValue.EndToStart -> swipeToStartActions
|
||||||
}
|
}
|
||||||
val enableSecondAction = actions.size > 1
|
val enableSecondAction = actions.size > 1
|
||||||
val bgColor by animateColorAsState(
|
val bgColor by animateColorAsState(
|
||||||
targetValue = if (
|
targetValue =
|
||||||
|
if (
|
||||||
dismissState.progress < SECOND_ACTION_THRESHOLD ||
|
dismissState.progress < SECOND_ACTION_THRESHOLD ||
|
||||||
dismissState.targetValue == SwipeToDismissBoxValue.Settled ||
|
dismissState.targetValue == SwipeToDismissBoxValue.Settled ||
|
||||||
!enableSecondAction
|
!enableSecondAction
|
||||||
@ -137,7 +142,8 @@ fun SwipeActionCard(
|
|||||||
actions.getOrNull(1)?.backgroundColor ?: Color.Transparent
|
actions.getOrNull(1)?.backgroundColor ?: Color.Transparent
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
val alignment = when (direction) {
|
val alignment =
|
||||||
|
when (direction) {
|
||||||
SwipeToDismissBoxValue.StartToEnd -> Alignment.CenterStart
|
SwipeToDismissBoxValue.StartToEnd -> Alignment.CenterStart
|
||||||
else -> Alignment.CenterEnd
|
else -> Alignment.CenterEnd
|
||||||
}
|
}
|
||||||
@ -180,7 +186,8 @@ private fun rememberNoFlingSwipeToDismissBoxState(
|
|||||||
// instead of LocalDensity.current we use a value that makes velocityThreshold to skyrocket
|
// instead of LocalDensity.current we use a value that makes velocityThreshold to skyrocket
|
||||||
val density = Density(Float.POSITIVE_INFINITY)
|
val density = Density(Float.POSITIVE_INFINITY)
|
||||||
return rememberSaveable(
|
return rememberSaveable(
|
||||||
saver = SwipeToDismissBoxState.Saver(
|
saver =
|
||||||
|
SwipeToDismissBoxState.Saver(
|
||||||
confirmValueChange = confirmValueChange,
|
confirmValueChange = confirmValueChange,
|
||||||
density = density,
|
density = density,
|
||||||
positionalThreshold = positionalThreshold,
|
positionalThreshold = positionalThreshold,
|
||||||
|
@ -58,14 +58,16 @@ fun ZoomableImage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(Color.Black),
|
.background(Color.Black),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(visible = visible) {
|
AnimatedVisibility(visible = visible) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
onDoubleClick = {
|
onDoubleClick = {
|
||||||
if (scale > 1f) {
|
if (scale > 1f) {
|
||||||
@ -86,7 +88,8 @@ fun ZoomableImage(
|
|||||||
|
|
||||||
scale = (scale * gestureZoom).coerceIn(1f, 16f)
|
scale = (scale * gestureZoom).coerceIn(1f, 16f)
|
||||||
|
|
||||||
offset = if (scale > 1) {
|
offset =
|
||||||
|
if (scale > 1) {
|
||||||
Offset(
|
Offset(
|
||||||
x = (offset.x + pan.x * scale).coerceIn(-maxX, maxX),
|
x = (offset.x + pan.x * scale).coerceIn(-maxX, maxX),
|
||||||
y = (offset.y + pan.y * scale).coerceIn(-maxY, maxY),
|
y = (offset.y + pan.y * scale).coerceIn(-maxY, maxY),
|
||||||
@ -116,14 +119,16 @@ fun ZoomableImage(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onLoading = { progress ->
|
onLoading = { progress ->
|
||||||
val prog = if (progress != null) {
|
val prog =
|
||||||
|
if (progress != null) {
|
||||||
progress
|
progress
|
||||||
} else {
|
} else {
|
||||||
val transition = rememberInfiniteTransition()
|
val transition = rememberInfiniteTransition()
|
||||||
val res by transition.animateFloat(
|
val res by transition.animateFloat(
|
||||||
initialValue = 0f,
|
initialValue = 0f,
|
||||||
targetValue = 1f,
|
targetValue = 1f,
|
||||||
animationSpec = InfiniteRepeatableSpec(
|
animationSpec =
|
||||||
|
InfiniteRepeatableSpec(
|
||||||
animation = tween(LOADING_ANIMATION_DURATION),
|
animation = tween(LOADING_ANIMATION_DURATION),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,8 @@ actual fun CustomImage(
|
|||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
if (shouldBeRendered) {
|
if (shouldBeRendered) {
|
||||||
val painterResource = asyncPainterResource(
|
val painterResource =
|
||||||
|
asyncPainterResource(
|
||||||
data = url,
|
data = url,
|
||||||
filterQuality = quality,
|
filterQuality = quality,
|
||||||
)
|
)
|
||||||
|
@ -50,7 +50,8 @@ actual fun CustomWebView(
|
|||||||
|
|
||||||
UIKitView(
|
UIKitView(
|
||||||
factory = {
|
factory = {
|
||||||
val config = WKWebViewConfiguration().apply {
|
val config =
|
||||||
|
WKWebViewConfiguration().apply {
|
||||||
allowsInlineMediaPlayback = true
|
allowsInlineMediaPlayback = true
|
||||||
}
|
}
|
||||||
WKWebView(
|
WKWebView(
|
||||||
@ -59,7 +60,8 @@ actual fun CustomWebView(
|
|||||||
).apply {
|
).apply {
|
||||||
userInteractionEnabled = true
|
userInteractionEnabled = true
|
||||||
allowsBackForwardNavigationGestures = true
|
allowsBackForwardNavigationGestures = true
|
||||||
val navigationDelegate = object : NSObject(), WKNavigationDelegateProtocol {
|
val navigationDelegate =
|
||||||
|
object : NSObject(), WKNavigationDelegateProtocol {
|
||||||
override fun webView(
|
override fun webView(
|
||||||
webView: WKWebView,
|
webView: WKWebView,
|
||||||
didFinishNavigation: WKNavigation?,
|
didFinishNavigation: WKNavigation?,
|
||||||
@ -68,7 +70,8 @@ actual fun CustomWebView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.navigationDelegate = navigationDelegate
|
this.navigationDelegate = navigationDelegate
|
||||||
this.scrollView.delegate = object : NSObject(), UIScrollViewDelegateProtocol {
|
this.scrollView.delegate =
|
||||||
|
object : NSObject(), UIScrollViewDelegateProtocol {
|
||||||
override fun scrollViewDidScroll(scrollView: UIScrollView) {
|
override fun scrollViewDidScroll(scrollView: UIScrollView) {
|
||||||
scrollView.contentOffset.useContents {
|
scrollView.contentOffset.useContents {
|
||||||
val offsetX = (lastOffsetX - x).toFloat() / density
|
val offsetX = (lastOffsetX - x).toFloat() / density
|
||||||
|
@ -31,7 +31,6 @@ class DefaultDetailOpener(
|
|||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val communityRepository: CommunityRepository,
|
private val communityRepository: CommunityRepository,
|
||||||
) : DetailOpener {
|
) : DetailOpener {
|
||||||
|
|
||||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
|
|
||||||
override fun openCommunityDetail(
|
override fun openCommunityDetail(
|
||||||
@ -39,7 +38,8 @@ class DefaultDetailOpener(
|
|||||||
otherInstance: String,
|
otherInstance: String,
|
||||||
) {
|
) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val (actualCommunity, actualInstance) = withContext(Dispatchers.IO) {
|
val (actualCommunity, actualInstance) =
|
||||||
|
run {
|
||||||
val defaultResult = community to otherInstance
|
val defaultResult = community to otherInstance
|
||||||
if (otherInstance.isNotEmpty()) {
|
if (otherInstance.isNotEmpty()) {
|
||||||
val found = searchCommunity(name = community.name, host = otherInstance)
|
val found = searchCommunity(name = community.name, host = otherInstance)
|
||||||
@ -52,9 +52,7 @@ class DefaultDetailOpener(
|
|||||||
defaultResult
|
defaultResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
itemCache.putCommunity(actualCommunity)
|
itemCache.putCommunity(actualCommunity)
|
||||||
}
|
|
||||||
navigationCoordinator.pushScreen(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
communityId = actualCommunity.id,
|
communityId = actualCommunity.id,
|
||||||
@ -64,7 +62,10 @@ class DefaultDetailOpener(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openUserDetail(user: UserModel, otherInstance: String) {
|
override fun openUserDetail(
|
||||||
|
user: UserModel,
|
||||||
|
otherInstance: String,
|
||||||
|
) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
itemCache.putUser(user)
|
itemCache.putUser(user)
|
||||||
@ -118,7 +119,8 @@ class DefaultDetailOpener(
|
|||||||
itemCache.putComment(editedComment)
|
itemCache.putComment(editedComment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val screen = CreateCommentScreen(
|
val screen =
|
||||||
|
CreateCommentScreen(
|
||||||
draftId = draftId,
|
draftId = draftId,
|
||||||
originalPostId = originalPost?.id,
|
originalPostId = originalPost?.id,
|
||||||
originalCommentId = originalComment?.id,
|
originalCommentId = originalComment?.id,
|
||||||
@ -149,7 +151,8 @@ class DefaultDetailOpener(
|
|||||||
itemCache.putPost(crossPost)
|
itemCache.putPost(crossPost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val screen = CreatePostScreen(
|
val screen =
|
||||||
|
CreatePostScreen(
|
||||||
draftId = draftId,
|
draftId = draftId,
|
||||||
editedPostId = editedPost?.id,
|
editedPostId = editedPost?.id,
|
||||||
crossPostId = crossPost?.id,
|
crossPostId = crossPost?.id,
|
||||||
@ -164,11 +167,15 @@ class DefaultDetailOpener(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun searchCommunity(name: String, host: String): CommunityModel? {
|
private suspend fun searchCommunity(
|
||||||
|
name: String,
|
||||||
|
host: String,
|
||||||
|
): CommunityModel? {
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
|
|
||||||
tailrec suspend fun searchRec(page: Int = 0): CommunityModel? {
|
tailrec suspend fun searchRec(page: Int = 0): CommunityModel? {
|
||||||
val results = communityRepository.search(
|
val results =
|
||||||
|
communityRepository.search(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
query = name,
|
query = name,
|
||||||
resultType = SearchResultType.Communities,
|
resultType = SearchResultType.Communities,
|
||||||
@ -176,7 +183,8 @@ class DefaultDetailOpener(
|
|||||||
limit = 50,
|
limit = 50,
|
||||||
).filterIsInstance<SearchResult.Community>()
|
).filterIsInstance<SearchResult.Community>()
|
||||||
|
|
||||||
val found = results.firstOrNull {
|
val found =
|
||||||
|
results.firstOrNull {
|
||||||
it.model.name == name && it.model.host == host
|
it.model.name == name && it.model.host == host
|
||||||
}?.model
|
}?.model
|
||||||
// iterates for no more than a number of pages before giving up
|
// iterates for no more than a number of pages before giving up
|
||||||
|
@ -5,19 +5,23 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface BlockActionType {
|
sealed interface BlockActionType {
|
||||||
data object User : BlockActionType
|
data object User : BlockActionType
|
||||||
|
|
||||||
data object Community : BlockActionType
|
data object Community : BlockActionType
|
||||||
|
|
||||||
data object Instance : BlockActionType
|
data object Instance : BlockActionType
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toBlockActionType(): BlockActionType = when (this) {
|
fun Int.toBlockActionType(): BlockActionType =
|
||||||
|
when (this) {
|
||||||
2 -> BlockActionType.Instance
|
2 -> BlockActionType.Instance
|
||||||
1 -> BlockActionType.Community
|
1 -> BlockActionType.Community
|
||||||
else -> BlockActionType.User
|
else -> BlockActionType.User
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BlockActionType.toReadableName(): String = when (this) {
|
fun BlockActionType.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
BlockActionType.Community -> LocalXmlStrings.current.blockActionCommunity
|
BlockActionType.Community -> LocalXmlStrings.current.blockActionCommunity
|
||||||
BlockActionType.Instance -> LocalXmlStrings.current.communityDetailBlockInstance
|
BlockActionType.Instance -> LocalXmlStrings.current.communityDetailBlockInstance
|
||||||
BlockActionType.User -> LocalXmlStrings.current.blockActionUser
|
BlockActionType.User -> LocalXmlStrings.current.blockActionUser
|
||||||
}
|
}
|
||||||
|
@ -53,22 +53,26 @@ fun CollapsedCommentCard(
|
|||||||
val commentBarTheme by themeRepository.commentBarTheme.collectAsState()
|
val commentBarTheme by themeRepository.commentBarTheme.collectAsState()
|
||||||
var commentHeight by remember { mutableStateOf(0f) }
|
var commentHeight by remember { mutableStateOf(0f) }
|
||||||
val barWidth = 2.dp
|
val barWidth = 2.dp
|
||||||
val barColor = themeRepository.getCommentBarColor(
|
val barColor =
|
||||||
|
themeRepository.getCommentBarColor(
|
||||||
depth = comment.depth,
|
depth = comment.depth,
|
||||||
commentBarTheme = commentBarTheme,
|
commentBarTheme = commentBarTheme,
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier.onClick(
|
modifier =
|
||||||
|
modifier.onClick(
|
||||||
onClick = onClick ?: {},
|
onClick = onClick ?: {},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
start = (INDENT_AMOUNT * comment.depth).dp,
|
start = (INDENT_AMOUNT * comment.depth).dp,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(start = barWidth)
|
.padding(start = barWidth)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
@ -116,7 +120,8 @@ fun CollapsedCommentCard(
|
|||||||
}
|
}
|
||||||
if (comment.depth > 0) {
|
if (comment.depth > 0) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(top = Spacing.xxs)
|
.padding(top = Spacing.xxs)
|
||||||
.width(barWidth)
|
.width(barWidth)
|
||||||
.height(commentHeight.toLocalDp())
|
.height(commentHeight.toLocalDp())
|
||||||
|
@ -77,7 +77,8 @@ fun CommentCard(
|
|||||||
val themeRepository = remember { getThemeRepository() }
|
val themeRepository = remember { getThemeRepository() }
|
||||||
var commentHeight by remember { mutableStateOf(0f) }
|
var commentHeight by remember { mutableStateOf(0f) }
|
||||||
val commentBarTheme by themeRepository.commentBarTheme.collectAsState()
|
val commentBarTheme by themeRepository.commentBarTheme.collectAsState()
|
||||||
val barColor = themeRepository.getCommentBarColor(
|
val barColor =
|
||||||
|
themeRepository.getCommentBarColor(
|
||||||
depth = comment.depth,
|
depth = comment.depth,
|
||||||
commentBarTheme = commentBarTheme,
|
commentBarTheme = commentBarTheme,
|
||||||
)
|
)
|
||||||
@ -87,17 +88,20 @@ fun CommentCard(
|
|||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = onClick ?: {},
|
onClick = onClick ?: {},
|
||||||
onDoubleClick = onDoubleClick ?: {},
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
).padding(
|
).padding(
|
||||||
start = indentAmount.takeIf { it > 0 }?.let {
|
start =
|
||||||
|
indentAmount.takeIf { it > 0 }?.let {
|
||||||
(it * comment.depth).dp + Spacing.xxxs
|
(it * comment.depth).dp + Spacing.xxxs
|
||||||
} ?: 0.dp,
|
} ?: 0.dp,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(start = barWidth + Spacing.xxs)
|
.padding(start = barWidth + Spacing.xxs)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
@ -119,10 +123,12 @@ fun CommentCard(
|
|||||||
distinguished = comment.distinguished,
|
distinguished = comment.distinguished,
|
||||||
isOp = isOp,
|
isOp = isOp,
|
||||||
isBot = comment.creator?.bot.takeIf { showBot } ?: false,
|
isBot = comment.creator?.bot.takeIf { showBot } ?: false,
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator =
|
||||||
|
rememberCallbackArgs { user ->
|
||||||
onOpenCreator?.invoke(user, "")
|
onOpenCreator?.invoke(user, "")
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity =
|
||||||
|
rememberCallbackArgs { community ->
|
||||||
onOpenCommunity?.invoke(community, "")
|
onOpenCommunity?.invoke(community, "")
|
||||||
},
|
},
|
||||||
onToggleExpanded = onToggleExpanded,
|
onToggleExpanded = onToggleExpanded,
|
||||||
@ -136,7 +142,8 @@ fun CommentCard(
|
|||||||
} else {
|
} else {
|
||||||
CustomizedContent(ContentFontClass.Body) {
|
CustomizedContent(ContentFontClass.Body) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalDensity provides Density(
|
LocalDensity provides
|
||||||
|
Density(
|
||||||
density = LocalDensity.current.density,
|
density = LocalDensity.current.density,
|
||||||
// additional downscale for font in comments
|
// additional downscale for font in comments
|
||||||
fontScale = LocalDensity.current.fontScale * COMMENT_TEXT_SCALE_FACTOR,
|
fontScale = LocalDensity.current.fontScale * COMMENT_TEXT_SCALE_FACTOR,
|
||||||
@ -180,7 +187,8 @@ fun CommentCard(
|
|||||||
}
|
}
|
||||||
if (indentAmount > 0 && comment.depth > 0) {
|
if (indentAmount > 0 && comment.depth > 0) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(top = Spacing.xxs)
|
.padding(top = Spacing.xxs)
|
||||||
.width(barWidth)
|
.width(barWidth)
|
||||||
.height(commentHeight.toLocalDp())
|
.height(commentHeight.toLocalDp())
|
||||||
|
@ -37,7 +37,8 @@ fun CommentCardPlaceholder(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.size(IconSize.s)
|
modifier =
|
||||||
|
Modifier.size(IconSize.s)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
@ -46,13 +47,15 @@ fun CommentCardPlaceholder(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth(0.5f)
|
.fillMaxWidth(0.5f)
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -61,14 +64,16 @@ fun CommentCardPlaceholder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(80.dp)
|
.height(80.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
|
@ -81,7 +81,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
if (communityIcon.isNotEmpty()) {
|
if (communityIcon.isNotEmpty()) {
|
||||||
if (autoLoadImages) {
|
if (autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
@ -99,7 +100,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PlaceholderImage(
|
PlaceholderImage(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
@ -114,7 +116,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
} else if (creatorAvatar.isNotEmpty()) {
|
} else if (creatorAvatar.isNotEmpty()) {
|
||||||
if (autoLoadImages) {
|
if (autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
@ -132,7 +135,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PlaceholderImage(
|
PlaceholderImage(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
@ -151,7 +155,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
if (community != null) {
|
if (community != null) {
|
||||||
CustomizedContent(ContentFontClass.AncillaryText) {
|
CustomizedContent(ContentFontClass.AncillaryText) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
@ -168,7 +173,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
CustomizedContent(ContentFontClass.AncillaryText) {
|
CustomizedContent(ContentFontClass.AncillaryText) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
@ -234,7 +240,8 @@ fun CommunityAndCreatorInfo(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (indicatorExpanded != null) {
|
if (indicatorExpanded != null) {
|
||||||
val expandedModifier = Modifier
|
val expandedModifier =
|
||||||
|
Modifier
|
||||||
.padding(end = Spacing.xs)
|
.padding(end = Spacing.xs)
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
|
@ -67,11 +67,14 @@ fun CommunityHeader(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(
|
.background(
|
||||||
brush = Brush.horizontalGradient(
|
brush =
|
||||||
colors = listOf(
|
Brush.horizontalGradient(
|
||||||
|
colors =
|
||||||
|
listOf(
|
||||||
MaterialTheme.colorScheme.background.copy(alpha = 0.95f),
|
MaterialTheme.colorScheme.background.copy(alpha = 0.95f),
|
||||||
Color.Transparent,
|
Color.Transparent,
|
||||||
MaterialTheme.colorScheme.background.copy(alpha = 0.75f),
|
MaterialTheme.colorScheme.background.copy(alpha = 0.75f),
|
||||||
@ -92,7 +95,8 @@ fun CommunityHeader(
|
|||||||
// avatar
|
// avatar
|
||||||
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(IconSize.xxl)
|
.size(IconSize.xxl)
|
||||||
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
||||||
@ -144,7 +148,8 @@ fun CommunityHeader(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = community.subscribers.getPrettyNumber(
|
text =
|
||||||
|
community.subscribers.getPrettyNumber(
|
||||||
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
||||||
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
||||||
),
|
),
|
||||||
@ -159,7 +164,8 @@ fun CommunityHeader(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = community.monthlyActiveUsers.getPrettyNumber(
|
text =
|
||||||
|
community.monthlyActiveUsers.getPrettyNumber(
|
||||||
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
||||||
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
||||||
),
|
),
|
||||||
@ -172,7 +178,8 @@ fun CommunityHeader(
|
|||||||
|
|
||||||
if (onInfo != null) {
|
if (onInfo != null) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(end = Spacing.s)
|
.padding(end = Spacing.s)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.onClick(onClick = onInfo),
|
.onClick(onClick = onInfo),
|
||||||
|
@ -69,7 +69,8 @@ fun CommunityItem(
|
|||||||
var optionsMenuOpen by remember { mutableStateOf(false) }
|
var optionsMenuOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.then(
|
modifier =
|
||||||
|
modifier.then(
|
||||||
if (noPadding) {
|
if (noPadding) {
|
||||||
Modifier
|
Modifier
|
||||||
} else {
|
} else {
|
||||||
@ -81,7 +82,8 @@ fun CommunityItem(
|
|||||||
) {
|
) {
|
||||||
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
@ -98,7 +100,8 @@ fun CommunityItem(
|
|||||||
modifier = Modifier.weight(1f).padding(start = Spacing.xs),
|
modifier = Modifier.weight(1f).padding(start = Spacing.xs),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = buildString {
|
text =
|
||||||
|
buildString {
|
||||||
append(title)
|
append(title)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
@ -107,7 +110,8 @@ fun CommunityItem(
|
|||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = buildString {
|
text =
|
||||||
|
buildString {
|
||||||
append("!")
|
append("!")
|
||||||
append(communityHandle)
|
append(communityHandle)
|
||||||
},
|
},
|
||||||
@ -147,12 +151,14 @@ fun CommunityItem(
|
|||||||
|
|
||||||
showSubscribeButton -> {
|
showSubscribeButton -> {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.size(IconSize.m)
|
.size(IconSize.m)
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = { onSubscribe?.invoke() },
|
onClick = { onSubscribe?.invoke() },
|
||||||
),
|
),
|
||||||
imageVector = when (community.subscribed) {
|
imageVector =
|
||||||
|
when (community.subscribed) {
|
||||||
true -> {
|
true -> {
|
||||||
Icons.Outlined.RemoveCircleOutline
|
Icons.Outlined.RemoveCircleOutline
|
||||||
}
|
}
|
||||||
@ -174,7 +180,8 @@ fun CommunityItem(
|
|||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Box {
|
Box {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.m)
|
modifier =
|
||||||
|
Modifier.size(IconSize.m)
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
@ -194,7 +201,8 @@ fun CommunityItem(
|
|||||||
onDismiss = {
|
onDismiss = {
|
||||||
optionsMenuOpen = false
|
optionsMenuOpen = false
|
||||||
},
|
},
|
||||||
offset = DpOffset(
|
offset =
|
||||||
|
DpOffset(
|
||||||
x = optionsOffset.x.toLocalDp(),
|
x = optionsOffset.x.toLocalDp(),
|
||||||
y = optionsOffset.y.toLocalDp(),
|
y = optionsOffset.y.toLocalDp(),
|
||||||
),
|
),
|
||||||
|
@ -23,7 +23,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.shimmerEffect
|
|||||||
@Composable
|
@Composable
|
||||||
fun CommunityItemPlaceholder() {
|
fun CommunityItemPlaceholder() {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
),
|
),
|
||||||
@ -31,7 +32,8 @@ fun CommunityItemPlaceholder() {
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.xs),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.xs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(IconSize.l)
|
.size(IconSize.l)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
@ -42,14 +44,16 @@ fun CommunityItemPlaceholder() {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(40.dp)
|
.height(40.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(20.dp)
|
.height(20.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
|
@ -2,5 +2,6 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui
|
|||||||
|
|
||||||
sealed interface CreatePostSection {
|
sealed interface CreatePostSection {
|
||||||
data object Edit : CreatePostSection
|
data object Edit : CreatePostSection
|
||||||
|
|
||||||
data object Preview : CreatePostSection
|
data object Preview : CreatePostSection
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ fun DetailInfoItem(
|
|||||||
Icon(imageVector = icon, contentDescription = null)
|
Icon(imageVector = icon, contentDescription = null)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = buildAnnotatedString {
|
text =
|
||||||
|
buildAnnotatedString {
|
||||||
withStyle(
|
withStyle(
|
||||||
SpanStyle(
|
SpanStyle(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
|
@ -22,14 +22,18 @@ internal class DefaultFabNestedScrollConnection : FabNestedScrollConnection {
|
|||||||
private val fabVisible = MutableStateFlow(true)
|
private val fabVisible = MutableStateFlow(true)
|
||||||
private val scope = CoroutineScope(SupervisorJob())
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
override val isFabVisible: StateFlow<Boolean>
|
override val isFabVisible: StateFlow<Boolean>
|
||||||
get() = fabVisible
|
get() =
|
||||||
|
fabVisible
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
started = SharingStarted.WhileSubscribed(5_000),
|
started = SharingStarted.WhileSubscribed(5_000),
|
||||||
initialValue = true,
|
initialValue = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
override fun onPreScroll(
|
||||||
|
available: Offset,
|
||||||
|
source: NestedScrollSource,
|
||||||
|
): Offset {
|
||||||
if (available.y < -THRESHOLD) {
|
if (available.y < -THRESHOLD) {
|
||||||
fabVisible.value = false
|
fabVisible.value = false
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
|||||||
|
|
||||||
sealed interface InboxCardType {
|
sealed interface InboxCardType {
|
||||||
data object Mention : InboxCardType
|
data object Mention : InboxCardType
|
||||||
|
|
||||||
data object Reply : InboxCardType
|
data object Reply : InboxCardType
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,8 @@ fun InboxCard(
|
|||||||
onReply: (() -> Unit)? = null,
|
onReply: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.then(
|
modifier =
|
||||||
|
Modifier.then(
|
||||||
if (postLayout == PostLayout.Card) {
|
if (postLayout == PostLayout.Card) {
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = Spacing.xs)
|
.padding(horizontal = Spacing.xs)
|
||||||
@ -94,7 +96,8 @@ fun InboxCard(
|
|||||||
} else {
|
} else {
|
||||||
CustomizedContent(ContentFontClass.Body) {
|
CustomizedContent(ContentFontClass.Body) {
|
||||||
PostCardBody(
|
PostCardBody(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
),
|
),
|
||||||
// takes just the first line
|
// takes just the first line
|
||||||
@ -108,7 +111,8 @@ fun InboxCard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InboxReplySubtitle(
|
InboxReplySubtitle(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
start = Spacing.s,
|
start = Spacing.s,
|
||||||
end = Spacing.s,
|
end = Spacing.s,
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -127,7 +131,8 @@ fun InboxCard(
|
|||||||
downVoted = mention.myVote < 0,
|
downVoted = mention.myVote < 0,
|
||||||
options = options,
|
options = options,
|
||||||
onOpenCommunity = onOpenCommunity,
|
onOpenCommunity = onOpenCommunity,
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator =
|
||||||
|
rememberCallbackArgs { user ->
|
||||||
onOpenCreator(user)
|
onOpenCreator(user)
|
||||||
},
|
},
|
||||||
onUpVote = onUpVote,
|
onUpVote = onUpVote,
|
||||||
|
@ -22,11 +22,10 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.shimmerEffect
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.shimmerEffect
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InboxCardPlaceholder(
|
fun InboxCardPlaceholder(postLayout: PostLayout = PostLayout.Card) {
|
||||||
postLayout: PostLayout = PostLayout.Card,
|
|
||||||
) {
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.then(
|
modifier =
|
||||||
|
Modifier.then(
|
||||||
if (postLayout == PostLayout.Card) {
|
if (postLayout == PostLayout.Card) {
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = Spacing.xs)
|
.padding(horizontal = Spacing.xs)
|
||||||
@ -43,14 +42,16 @@ fun InboxCardPlaceholder(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(vertical = Spacing.xxxs)
|
.padding(vertical = Spacing.xxxs)
|
||||||
.height(50.dp)
|
.height(50.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -58,7 +59,8 @@ fun InboxCardPlaceholder(
|
|||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
|
@ -29,7 +29,8 @@ fun InboxCardHeader(
|
|||||||
) {
|
) {
|
||||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
val header = buildAnnotatedString {
|
val header =
|
||||||
|
buildAnnotatedString {
|
||||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold, color = fullColor)) {
|
withStyle(SpanStyle(fontWeight = FontWeight.Bold, color = fullColor)) {
|
||||||
append(mention.creator.name)
|
append(mention.creator.name)
|
||||||
}
|
}
|
||||||
@ -60,7 +61,8 @@ fun InboxCardHeader(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
@ -72,7 +74,8 @@ fun InboxCardHeader(
|
|||||||
)
|
)
|
||||||
if (!mention.read) {
|
if (!mention.read) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(end = Spacing.s)
|
.padding(end = Spacing.s)
|
||||||
.size(IconSize.xs),
|
.size(IconSize.xs),
|
||||||
imageVector = Icons.Filled.FiberManualRecord,
|
imageVector = Icons.Filled.FiberManualRecord,
|
||||||
|
@ -104,7 +104,8 @@ fun InboxReplySubtitle(
|
|||||||
) {
|
) {
|
||||||
if (creatorName.isNotEmpty()) {
|
if (creatorName.isNotEmpty()) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
@ -118,7 +119,8 @@ fun InboxReplySubtitle(
|
|||||||
) {
|
) {
|
||||||
if (creatorAvatar.isNotEmpty() && autoLoadImages) {
|
if (creatorAvatar.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
@ -141,7 +143,8 @@ fun InboxReplySubtitle(
|
|||||||
}
|
}
|
||||||
if (communityName.isNotEmpty()) {
|
if (communityName.isNotEmpty()) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
@ -156,7 +159,8 @@ fun InboxReplySubtitle(
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
@ -185,7 +189,8 @@ fun InboxReplySubtitle(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 3.5.dp,
|
top = 3.5.dp,
|
||||||
bottom = 3.5.dp,
|
bottom = 3.5.dp,
|
||||||
end = 3.5.dp,
|
end = 3.5.dp,
|
||||||
@ -216,7 +221,8 @@ fun InboxReplySubtitle(
|
|||||||
}
|
}
|
||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.m)
|
modifier =
|
||||||
|
Modifier.size(IconSize.m)
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
@ -233,13 +239,15 @@ fun InboxReplySubtitle(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
FeedbackButton(
|
FeedbackButton(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 2.5.dp,
|
top = 2.5.dp,
|
||||||
bottom = 2.5.dp,
|
bottom = 2.5.dp,
|
||||||
end = 2.5.dp,
|
end = 2.5.dp,
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowCircleUp,
|
imageVector = Icons.Default.ArrowCircleUp,
|
||||||
tintColor = if (upVoted) {
|
tintColor =
|
||||||
|
if (upVoted) {
|
||||||
upVoteColor ?: defaultUpvoteColor
|
upVoteColor ?: defaultUpvoteColor
|
||||||
} else {
|
} else {
|
||||||
ancillaryColor
|
ancillaryColor
|
||||||
@ -250,7 +258,8 @@ fun InboxReplySubtitle(
|
|||||||
)
|
)
|
||||||
if (showScores) {
|
if (showScores) {
|
||||||
Text(
|
Text(
|
||||||
text = formatToReadableValue(
|
text =
|
||||||
|
formatToReadableValue(
|
||||||
voteFormat = voteFormat,
|
voteFormat = voteFormat,
|
||||||
score = score,
|
score = score,
|
||||||
upVotes = upVotes,
|
upVotes = upVotes,
|
||||||
@ -265,13 +274,15 @@ fun InboxReplySubtitle(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
FeedbackButton(
|
FeedbackButton(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 2.5.dp,
|
top = 2.5.dp,
|
||||||
bottom = 2.5.dp,
|
bottom = 2.5.dp,
|
||||||
start = 2.5.dp,
|
start = 2.5.dp,
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowCircleDown,
|
imageVector = Icons.Default.ArrowCircleDown,
|
||||||
tintColor = if (downVoted) {
|
tintColor =
|
||||||
|
if (downVoted) {
|
||||||
downVoteColor ?: defaultDownVoteColor
|
downVoteColor ?: defaultDownVoteColor
|
||||||
} else {
|
} else {
|
||||||
ancillaryColor
|
ancillaryColor
|
||||||
@ -286,7 +297,8 @@ fun InboxReplySubtitle(
|
|||||||
onDismiss = {
|
onDismiss = {
|
||||||
optionsExpanded = false
|
optionsExpanded = false
|
||||||
},
|
},
|
||||||
offset = DpOffset(
|
offset =
|
||||||
|
DpOffset(
|
||||||
x = optionsOffset.x.toLocalDp(),
|
x = optionsOffset.x.toLocalDp(),
|
||||||
y = optionsOffset.y.toLocalDp(),
|
y = optionsOffset.y.toLocalDp(),
|
||||||
),
|
),
|
||||||
|
@ -22,7 +22,8 @@ fun IndicatorChip(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.border(
|
.border(
|
||||||
color = MaterialTheme.colorScheme.onBackground,
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
width = Dp.Hairline,
|
width = Dp.Hairline,
|
||||||
|
@ -10,33 +10,38 @@ import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
|||||||
|
|
||||||
sealed interface ModeratorZoneAction {
|
sealed interface ModeratorZoneAction {
|
||||||
data object GlobalModLog : ModeratorZoneAction
|
data object GlobalModLog : ModeratorZoneAction
|
||||||
|
|
||||||
data object GlobalReports : ModeratorZoneAction
|
data object GlobalReports : ModeratorZoneAction
|
||||||
|
|
||||||
data object ModeratedContents : ModeratorZoneAction
|
data object ModeratedContents : ModeratorZoneAction
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toModeratorZoneAction(): ModeratorZoneAction = when (this) {
|
fun Int.toModeratorZoneAction(): ModeratorZoneAction =
|
||||||
|
when (this) {
|
||||||
2 -> ModeratorZoneAction.ModeratedContents
|
2 -> ModeratorZoneAction.ModeratedContents
|
||||||
1 -> ModeratorZoneAction.GlobalReports
|
1 -> ModeratorZoneAction.GlobalReports
|
||||||
else -> ModeratorZoneAction.GlobalModLog
|
else -> ModeratorZoneAction.GlobalModLog
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ModeratorZoneAction.toInt(): Int = when (this) {
|
fun ModeratorZoneAction.toInt(): Int =
|
||||||
|
when (this) {
|
||||||
ModeratorZoneAction.GlobalModLog -> 0
|
ModeratorZoneAction.GlobalModLog -> 0
|
||||||
ModeratorZoneAction.GlobalReports -> 1
|
ModeratorZoneAction.GlobalReports -> 1
|
||||||
ModeratorZoneAction.ModeratedContents -> 2
|
ModeratorZoneAction.ModeratedContents -> 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ModeratorZoneAction.toReadableName(): String = when (this) {
|
fun ModeratorZoneAction.toReadableName(): String =
|
||||||
|
when (this) {
|
||||||
ModeratorZoneAction.GlobalModLog -> LocalXmlStrings.current.modlogTitle
|
ModeratorZoneAction.GlobalModLog -> LocalXmlStrings.current.modlogTitle
|
||||||
ModeratorZoneAction.GlobalReports -> LocalXmlStrings.current.reportListTitle
|
ModeratorZoneAction.GlobalReports -> LocalXmlStrings.current.reportListTitle
|
||||||
ModeratorZoneAction.ModeratedContents -> LocalXmlStrings.current.moderatorZoneActionContents
|
ModeratorZoneAction.ModeratedContents -> LocalXmlStrings.current.moderatorZoneActionContents
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ModeratorZoneAction.toIcon(): ImageVector = when (this) {
|
fun ModeratorZoneAction.toIcon(): ImageVector =
|
||||||
|
when (this) {
|
||||||
ModeratorZoneAction.GlobalModLog -> Icons.AutoMirrored.Default.ListAlt
|
ModeratorZoneAction.GlobalModLog -> Icons.AutoMirrored.Default.ListAlt
|
||||||
ModeratorZoneAction.GlobalReports -> Icons.Default.Report
|
ModeratorZoneAction.GlobalReports -> Icons.Default.Report
|
||||||
ModeratorZoneAction.ModeratedContents -> Icons.Default.Shield
|
ModeratorZoneAction.ModeratedContents -> Icons.Default.Shield
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ fun MultiCommunityItem(
|
|||||||
) {
|
) {
|
||||||
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
if (communityIcon.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier.padding(Spacing.xxxs).size(iconSize)
|
modifier =
|
||||||
|
Modifier.padding(Spacing.xxxs).size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
@ -77,7 +78,8 @@ fun MultiCommunityItem(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(vertical = Spacing.s),
|
modifier = Modifier.padding(vertical = Spacing.s),
|
||||||
text = buildString {
|
text =
|
||||||
|
buildString {
|
||||||
append(title)
|
append(title)
|
||||||
},
|
},
|
||||||
color = fullColor,
|
color = fullColor,
|
||||||
@ -88,7 +90,8 @@ fun MultiCommunityItem(
|
|||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Box {
|
Box {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.m)
|
modifier =
|
||||||
|
Modifier.size(IconSize.m)
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
@ -108,7 +111,8 @@ fun MultiCommunityItem(
|
|||||||
onDismiss = {
|
onDismiss = {
|
||||||
optionsMenuOpen = false
|
optionsMenuOpen = false
|
||||||
},
|
},
|
||||||
offset = DpOffset(
|
offset =
|
||||||
|
DpOffset(
|
||||||
x = optionsOffset.x.toLocalDp(),
|
x = optionsOffset.x.toLocalDp(),
|
||||||
y = optionsOffset.y.toLocalDp(),
|
y = optionsOffset.y.toLocalDp(),
|
||||||
),
|
),
|
||||||
|
@ -7,32 +7,60 @@ data class Option(
|
|||||||
|
|
||||||
sealed class OptionId(val value: Int) {
|
sealed class OptionId(val value: Int) {
|
||||||
data object Share : OptionId(0)
|
data object Share : OptionId(0)
|
||||||
|
|
||||||
data object Hide : OptionId(1)
|
data object Hide : OptionId(1)
|
||||||
|
|
||||||
data object SeeRaw : OptionId(2)
|
data object SeeRaw : OptionId(2)
|
||||||
|
|
||||||
data object CrossPost : OptionId(3)
|
data object CrossPost : OptionId(3)
|
||||||
|
|
||||||
data object Report : OptionId(4)
|
data object Report : OptionId(4)
|
||||||
|
|
||||||
data object Edit : OptionId(5)
|
data object Edit : OptionId(5)
|
||||||
|
|
||||||
data object Delete : OptionId(6)
|
data object Delete : OptionId(6)
|
||||||
|
|
||||||
data object Purge : OptionId(7)
|
data object Purge : OptionId(7)
|
||||||
|
|
||||||
data object InfoInstance : OptionId(8)
|
data object InfoInstance : OptionId(8)
|
||||||
|
|
||||||
data object Block : OptionId(9)
|
data object Block : OptionId(9)
|
||||||
|
|
||||||
data object BlockInstance : OptionId(10)
|
data object BlockInstance : OptionId(10)
|
||||||
|
|
||||||
data object ToggleRead : OptionId(11)
|
data object ToggleRead : OptionId(11)
|
||||||
|
|
||||||
data object FeaturePost : OptionId(13)
|
data object FeaturePost : OptionId(13)
|
||||||
|
|
||||||
data object LockPost : OptionId(14)
|
data object LockPost : OptionId(14)
|
||||||
|
|
||||||
data object Remove : OptionId(15)
|
data object Remove : OptionId(15)
|
||||||
|
|
||||||
data object DistinguishComment : OptionId(16)
|
data object DistinguishComment : OptionId(16)
|
||||||
|
|
||||||
data object OpenReports : OptionId(17)
|
data object OpenReports : OptionId(17)
|
||||||
|
|
||||||
data object ResolveReport : OptionId(18)
|
data object ResolveReport : OptionId(18)
|
||||||
|
|
||||||
data object BanUser : OptionId(19)
|
data object BanUser : OptionId(19)
|
||||||
|
|
||||||
data object AddMod : OptionId(20)
|
data object AddMod : OptionId(20)
|
||||||
|
|
||||||
data object Favorite : OptionId(21)
|
data object Favorite : OptionId(21)
|
||||||
|
|
||||||
data object ViewModlog : OptionId(22)
|
data object ViewModlog : OptionId(22)
|
||||||
|
|
||||||
data object Unban : OptionId(23)
|
data object Unban : OptionId(23)
|
||||||
|
|
||||||
data object SetCustomSort : OptionId(24)
|
data object SetCustomSort : OptionId(24)
|
||||||
|
|
||||||
data object Search : OptionId(25)
|
data object Search : OptionId(25)
|
||||||
|
|
||||||
data object Copy : OptionId(26)
|
data object Copy : OptionId(26)
|
||||||
|
|
||||||
data object ExploreInstance : OptionId(27)
|
data object ExploreInstance : OptionId(27)
|
||||||
|
|
||||||
data object Unsubscribe : OptionId(28)
|
data object Unsubscribe : OptionId(28)
|
||||||
|
|
||||||
data object PurgeCreator : OptionId(29)
|
data object PurgeCreator : OptionId(29)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,8 @@ fun PostCard(
|
|||||||
) {
|
) {
|
||||||
val markRead = post.read && fadeRead
|
val markRead = post.read && fadeRead
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.then(
|
modifier =
|
||||||
|
modifier.then(
|
||||||
if (postLayout == PostLayout.Card) {
|
if (postLayout == PostLayout.Card) {
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = Spacing.xs)
|
.padding(horizontal = Spacing.xs)
|
||||||
@ -116,7 +117,8 @@ fun PostCard(
|
|||||||
post = post,
|
post = post,
|
||||||
isFromModerator = isFromModerator,
|
isFromModerator = isFromModerator,
|
||||||
hideAuthor = hideAuthor,
|
hideAuthor = hideAuthor,
|
||||||
backgroundColor = when (postLayout) {
|
backgroundColor =
|
||||||
|
when (postLayout) {
|
||||||
PostLayout.Card -> MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp)
|
PostLayout.Card -> MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp)
|
||||||
else -> MaterialTheme.colorScheme.background
|
else -> MaterialTheme.colorScheme.background
|
||||||
},
|
},
|
||||||
@ -218,7 +220,8 @@ private fun CompactPost(
|
|||||||
post.url.orEmpty().takeIf { !it.looksLikeAnImage && !it.looksLikeAVideo }.orEmpty()
|
post.url.orEmpty().takeIf { !it.looksLikeAnImage && !it.looksLikeAVideo }.orEmpty()
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.background(MaterialTheme.colorScheme.background)
|
.background(MaterialTheme.colorScheme.background)
|
||||||
.padding(horizontal = Spacing.xs)
|
.padding(horizontal = Spacing.xs)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
@ -242,16 +245,19 @@ private fun CompactPost(
|
|||||||
locked = post.locked,
|
locked = post.locked,
|
||||||
markRead = markRead,
|
markRead = markRead,
|
||||||
isFromModerator = isFromModerator,
|
isFromModerator = isFromModerator,
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity =
|
||||||
|
rememberCallbackArgs { community ->
|
||||||
onOpenCommunity?.invoke(community, "")
|
onOpenCommunity?.invoke(community, "")
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator =
|
||||||
|
rememberCallbackArgs { user ->
|
||||||
onOpenCreator?.invoke(user, "")
|
onOpenCreator?.invoke(user, "")
|
||||||
},
|
},
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
preferNicknames = preferNicknames,
|
preferNicknames = preferNicknames,
|
||||||
onDoubleClick = onDoubleClick,
|
onDoubleClick = onDoubleClick,
|
||||||
onLongClick = rememberCallback {
|
onLongClick =
|
||||||
|
rememberCallback {
|
||||||
optionsMenuOpen.value = true
|
optionsMenuOpen.value = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -281,13 +287,15 @@ private fun CompactPost(
|
|||||||
|
|
||||||
if (post.videoUrl.isNotEmpty()) {
|
if (post.videoUrl.isNotEmpty()) {
|
||||||
PostCardVideo(
|
PostCardVideo(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(0.25f)
|
.weight(0.25f)
|
||||||
.padding(vertical = Spacing.xxs),
|
.padding(vertical = Spacing.xxs),
|
||||||
url = post.videoUrl,
|
url = post.videoUrl,
|
||||||
blurred = blurNsfw && post.nsfw,
|
blurred = blurNsfw && post.nsfw,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onOpen = rememberCallback {
|
onOpen =
|
||||||
|
rememberCallback {
|
||||||
if (postLinkUrl.isNotEmpty()) {
|
if (postLinkUrl.isNotEmpty()) {
|
||||||
navigationCoordinator.handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = postLinkUrl,
|
url = postLinkUrl,
|
||||||
@ -306,7 +314,8 @@ private fun CompactPost(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PostCardImage(
|
PostCardImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(0.25f)
|
.weight(0.25f)
|
||||||
.then(
|
.then(
|
||||||
if (fullHeightImage) {
|
if (fullHeightImage) {
|
||||||
@ -325,7 +334,8 @@ private fun CompactPost(
|
|||||||
Icon(imageVector = Icons.Default.Download, contentDescription = null)
|
Icon(imageVector = Icons.Default.Download, contentDescription = null)
|
||||||
},
|
},
|
||||||
blurred = blurNsfw && post.nsfw,
|
blurred = blurNsfw && post.nsfw,
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
if (postLinkUrl.isNotEmpty()) {
|
if (postLinkUrl.isNotEmpty()) {
|
||||||
navigationCoordinator.handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = postLinkUrl,
|
url = postLinkUrl,
|
||||||
@ -342,14 +352,16 @@ private fun CompactPost(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDoubleClick = onDoubleClick,
|
onDoubleClick = onDoubleClick,
|
||||||
onLongClick = rememberCallback {
|
onLongClick =
|
||||||
|
rememberCallback {
|
||||||
optionsMenuOpen.value = true
|
optionsMenuOpen.value = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PostCardFooter(
|
PostCardFooter(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
top = Spacing.xxs,
|
top = Spacing.xxs,
|
||||||
start = Spacing.xs,
|
start = Spacing.xs,
|
||||||
end = Spacing.xs,
|
end = Spacing.xs,
|
||||||
@ -359,7 +371,8 @@ private fun CompactPost(
|
|||||||
voteFormat = voteFormat,
|
voteFormat = voteFormat,
|
||||||
score = post.score,
|
score = post.score,
|
||||||
showScores = showScores,
|
showScores = showScores,
|
||||||
unreadComments = post.unreadComments.takeIf {
|
unreadComments =
|
||||||
|
post.unreadComments.takeIf {
|
||||||
it != null && it > 0 && showUnreadComments && it != post.comments
|
it != null && it > 0 && showUnreadComments && it != post.comments
|
||||||
},
|
},
|
||||||
upVotes = post.upvotes,
|
upVotes = post.upvotes,
|
||||||
@ -421,7 +434,8 @@ private fun ExtendedPost(
|
|||||||
val customTabsHelper = remember { getCustomTabsHelper() }
|
val customTabsHelper = remember { getCustomTabsHelper() }
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val optionsMenuOpen = remember { mutableStateOf(false) }
|
val optionsMenuOpen = remember { mutableStateOf(false) }
|
||||||
val postLinkUrl = post.url.orEmpty().takeIf {
|
val postLinkUrl =
|
||||||
|
post.url.orEmpty().takeIf {
|
||||||
it != post.imageUrl &&
|
it != post.imageUrl &&
|
||||||
it != post.videoUrl &&
|
it != post.videoUrl &&
|
||||||
!it.looksLikeAnImage &&
|
!it.looksLikeAnImage &&
|
||||||
@ -430,7 +444,8 @@ private fun ExtendedPost(
|
|||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
@ -453,22 +468,26 @@ private fun ExtendedPost(
|
|||||||
locked = post.locked,
|
locked = post.locked,
|
||||||
markRead = markRead,
|
markRead = markRead,
|
||||||
isFromModerator = isFromModerator,
|
isFromModerator = isFromModerator,
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity =
|
||||||
|
rememberCallbackArgs { community ->
|
||||||
onOpenCommunity?.invoke(community, "")
|
onOpenCommunity?.invoke(community, "")
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator =
|
||||||
|
rememberCallbackArgs { user ->
|
||||||
onOpenCreator?.invoke(user, "")
|
onOpenCreator?.invoke(user, "")
|
||||||
},
|
},
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
preferNicknames = preferNicknames,
|
preferNicknames = preferNicknames,
|
||||||
onDoubleClick = onDoubleClick,
|
onDoubleClick = onDoubleClick,
|
||||||
onLongClick = rememberCallback {
|
onLongClick =
|
||||||
|
rememberCallback {
|
||||||
optionsMenuOpen.value = true
|
optionsMenuOpen.value = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
CustomizedContent(ContentFontClass.Title) {
|
CustomizedContent(ContentFontClass.Title) {
|
||||||
PostCardTitle(
|
PostCardTitle(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
),
|
),
|
||||||
@ -483,7 +502,8 @@ private fun ExtendedPost(
|
|||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
onOpenImage = onOpenImage,
|
onOpenImage = onOpenImage,
|
||||||
onDoubleClick = onDoubleClick,
|
onDoubleClick = onDoubleClick,
|
||||||
onLongClick = rememberCallback {
|
onLongClick =
|
||||||
|
rememberCallback {
|
||||||
optionsMenuOpen.value = true
|
optionsMenuOpen.value = true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -491,7 +511,8 @@ private fun ExtendedPost(
|
|||||||
|
|
||||||
if (post.embeddedUrl.isNotEmpty()) {
|
if (post.embeddedUrl.isNotEmpty()) {
|
||||||
PostCardEmbeddedWebView(
|
PostCardEmbeddedWebView(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xxs,
|
vertical = Spacing.xxs,
|
||||||
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
||||||
@ -518,7 +539,8 @@ private fun ExtendedPost(
|
|||||||
)
|
)
|
||||||
} else if (post.videoUrl.isNotEmpty()) {
|
} else if (post.videoUrl.isNotEmpty()) {
|
||||||
PostCardVideo(
|
PostCardVideo(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xxs,
|
vertical = Spacing.xxs,
|
||||||
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
||||||
@ -546,7 +568,8 @@ private fun ExtendedPost(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
PostCardImage(
|
PostCardImage(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
horizontal = if (fullWidthImage) 0.dp else Spacing.s,
|
||||||
@ -566,7 +589,8 @@ private fun ExtendedPost(
|
|||||||
),
|
),
|
||||||
imageUrl = post.imageUrl,
|
imageUrl = post.imageUrl,
|
||||||
blurred = blurNsfw && post.nsfw,
|
blurred = blurNsfw && post.nsfw,
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
if (postLinkUrl.isNotEmpty()) {
|
if (postLinkUrl.isNotEmpty()) {
|
||||||
navigationCoordinator.handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = postLinkUrl,
|
url = postLinkUrl,
|
||||||
@ -601,13 +625,15 @@ private fun ExtendedPost(
|
|||||||
} else {
|
} else {
|
||||||
CustomizedContent(ContentFontClass.Body) {
|
CustomizedContent(ContentFontClass.Body) {
|
||||||
PostCardBody(
|
PostCardBody(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
top = Spacing.xxs,
|
top = Spacing.xxs,
|
||||||
start = Spacing.s,
|
start = Spacing.s,
|
||||||
end = Spacing.s,
|
end = Spacing.s,
|
||||||
),
|
),
|
||||||
text = post.text,
|
text = post.text,
|
||||||
maxLines = if (limitBodyHeight) {
|
maxLines =
|
||||||
|
if (limitBodyHeight) {
|
||||||
settings.postBodyMaxLines
|
settings.postBodyMaxLines
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -630,7 +656,8 @@ private fun ExtendedPost(
|
|||||||
}
|
}
|
||||||
if (postLinkUrl.isNotEmpty()) {
|
if (postLinkUrl.isNotEmpty()) {
|
||||||
PostLinkBanner(
|
PostLinkBanner(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
bottom = Spacing.xxs,
|
bottom = Spacing.xxs,
|
||||||
@ -656,7 +683,8 @@ private fun ExtendedPost(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
PostCardFooter(
|
PostCardFooter(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
top = Spacing.xs,
|
top = Spacing.xs,
|
||||||
start = Spacing.s,
|
start = Spacing.s,
|
||||||
end = Spacing.s,
|
end = Spacing.s,
|
||||||
@ -666,7 +694,8 @@ private fun ExtendedPost(
|
|||||||
voteFormat = voteFormat,
|
voteFormat = voteFormat,
|
||||||
score = post.score,
|
score = post.score,
|
||||||
showScores = showScores,
|
showScores = showScores,
|
||||||
unreadComments = post.unreadComments.takeIf {
|
unreadComments =
|
||||||
|
post.unreadComments.takeIf {
|
||||||
it != null && it > 0 && showUnreadComments && it != post.comments
|
it != null && it > 0 && showUnreadComments && it != post.comments
|
||||||
},
|
},
|
||||||
upVotes = post.upvotes,
|
upVotes = post.upvotes,
|
||||||
|
@ -57,7 +57,8 @@ fun PostCardBody(
|
|||||||
content = text,
|
content = text,
|
||||||
maxLines = maxLines,
|
maxLines = maxLines,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
typography = markdownTypography(
|
typography =
|
||||||
|
markdownTypography(
|
||||||
h1 = typography.titleLarge,
|
h1 = typography.titleLarge,
|
||||||
h2 = typography.titleLarge,
|
h2 = typography.titleLarge,
|
||||||
h3 = typography.titleMedium,
|
h3 = typography.titleMedium,
|
||||||
@ -72,14 +73,16 @@ fun PostCardBody(
|
|||||||
ordered = typography.bodyMedium,
|
ordered = typography.bodyMedium,
|
||||||
code = typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
code = typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
||||||
),
|
),
|
||||||
colors = markdownColor(
|
colors =
|
||||||
|
markdownColor(
|
||||||
text = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
text = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
||||||
linkText = MaterialTheme.colorScheme.primary.copy(alpha = additionalAlphaFactor),
|
linkText = MaterialTheme.colorScheme.primary.copy(alpha = additionalAlphaFactor),
|
||||||
codeText = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
codeText = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
||||||
codeBackground = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
|
codeBackground = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
|
||||||
dividerColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
|
dividerColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
|
||||||
),
|
),
|
||||||
onOpenUrl = rememberCallbackArgs { url ->
|
onOpenUrl =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = url,
|
url = url,
|
||||||
openingMode = settingsRepository.currentSettings.value.urlOpeningMode.toUrlOpeningMode(),
|
openingMode = settingsRepository.currentSettings.value.urlOpeningMode.toUrlOpeningMode(),
|
||||||
@ -91,7 +94,8 @@ fun PostCardBody(
|
|||||||
onOpenWeb = onOpenWeb,
|
onOpenWeb = onOpenWeb,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenImage = rememberCallbackArgs { url ->
|
onOpenImage =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
onOpenImage?.invoke(url)
|
onOpenImage?.invoke(url)
|
||||||
},
|
},
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
@ -97,7 +97,8 @@ fun PostCardFooter(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 3.5.dp,
|
top = 3.5.dp,
|
||||||
end = 3.5.dp,
|
end = 3.5.dp,
|
||||||
bottom = 3.5.dp,
|
bottom = 3.5.dp,
|
||||||
@ -120,7 +121,8 @@ fun PostCardFooter(
|
|||||||
}
|
}
|
||||||
if (unreadComments != null) {
|
if (unreadComments != null) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(start = Spacing.xxs)
|
.padding(start = Spacing.xxs)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
@ -144,14 +146,16 @@ fun PostCardFooter(
|
|||||||
) {
|
) {
|
||||||
val isShowingUpdateDate = !updateDate.isNullOrBlank()
|
val isShowingUpdateDate = !updateDate.isNullOrBlank()
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.s).then(
|
modifier =
|
||||||
|
Modifier.size(IconSize.s).then(
|
||||||
if (!isShowingUpdateDate) {
|
if (!isShowingUpdateDate) {
|
||||||
Modifier.padding(0.5.dp)
|
Modifier.padding(0.5.dp)
|
||||||
} else {
|
} else {
|
||||||
Modifier
|
Modifier
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = if (isShowingUpdateDate) {
|
imageVector =
|
||||||
|
if (isShowingUpdateDate) {
|
||||||
Icons.Default.Update
|
Icons.Default.Update
|
||||||
} else {
|
} else {
|
||||||
Icons.Default.Schedule
|
Icons.Default.Schedule
|
||||||
@ -169,7 +173,8 @@ fun PostCardFooter(
|
|||||||
}
|
}
|
||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.m)
|
modifier =
|
||||||
|
Modifier.size(IconSize.m)
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
@ -187,17 +192,20 @@ fun PostCardFooter(
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
if (actionButtonsActive) {
|
if (actionButtonsActive) {
|
||||||
FeedbackButton(
|
FeedbackButton(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 2.5.dp,
|
top = 2.5.dp,
|
||||||
bottom = 2.5.dp,
|
bottom = 2.5.dp,
|
||||||
end = 2.5.dp,
|
end = 2.5.dp,
|
||||||
),
|
),
|
||||||
imageVector = if (!saved) {
|
imageVector =
|
||||||
|
if (!saved) {
|
||||||
Icons.Default.BookmarkBorder
|
Icons.Default.BookmarkBorder
|
||||||
} else {
|
} else {
|
||||||
Icons.Default.Bookmark
|
Icons.Default.Bookmark
|
||||||
},
|
},
|
||||||
tintColor = if (saved) {
|
tintColor =
|
||||||
|
if (saved) {
|
||||||
MaterialTheme.colorScheme.secondary
|
MaterialTheme.colorScheme.secondary
|
||||||
} else {
|
} else {
|
||||||
ancillaryColor
|
ancillaryColor
|
||||||
@ -209,12 +217,14 @@ fun PostCardFooter(
|
|||||||
}
|
}
|
||||||
FeedbackButton(
|
FeedbackButton(
|
||||||
modifier = buttonModifier.padding(all = 2.5.dp),
|
modifier = buttonModifier.padding(all = 2.5.dp),
|
||||||
imageVector = if (actionButtonsActive) {
|
imageVector =
|
||||||
|
if (actionButtonsActive) {
|
||||||
Icons.Default.ArrowCircleUp
|
Icons.Default.ArrowCircleUp
|
||||||
} else {
|
} else {
|
||||||
Icons.Default.ArrowUpward
|
Icons.Default.ArrowUpward
|
||||||
},
|
},
|
||||||
tintColor = if (upVoted) {
|
tintColor =
|
||||||
|
if (upVoted) {
|
||||||
upVoteColor ?: defaultUpvoteColor
|
upVoteColor ?: defaultUpvoteColor
|
||||||
} else {
|
} else {
|
||||||
ancillaryColor
|
ancillaryColor
|
||||||
@ -225,7 +235,8 @@ fun PostCardFooter(
|
|||||||
)
|
)
|
||||||
if (showScores) {
|
if (showScores) {
|
||||||
Text(
|
Text(
|
||||||
text = formatToReadableValue(
|
text =
|
||||||
|
formatToReadableValue(
|
||||||
voteFormat = voteFormat,
|
voteFormat = voteFormat,
|
||||||
score = score,
|
score = score,
|
||||||
upVotes = upVotes,
|
upVotes = upVotes,
|
||||||
@ -240,17 +251,20 @@ fun PostCardFooter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
FeedbackButton(
|
FeedbackButton(
|
||||||
modifier = buttonModifier.padding(
|
modifier =
|
||||||
|
buttonModifier.padding(
|
||||||
top = 2.5.dp,
|
top = 2.5.dp,
|
||||||
bottom = 2.5.dp,
|
bottom = 2.5.dp,
|
||||||
end = 2.5.dp,
|
end = 2.5.dp,
|
||||||
),
|
),
|
||||||
imageVector = if (actionButtonsActive) {
|
imageVector =
|
||||||
|
if (actionButtonsActive) {
|
||||||
Icons.Default.ArrowCircleDown
|
Icons.Default.ArrowCircleDown
|
||||||
} else {
|
} else {
|
||||||
Icons.Default.ArrowDownward
|
Icons.Default.ArrowDownward
|
||||||
},
|
},
|
||||||
tintColor = if (downVoted) {
|
tintColor =
|
||||||
|
if (downVoted) {
|
||||||
downVoteColor ?: defaultDownVoteColor
|
downVoteColor ?: defaultDownVoteColor
|
||||||
} else {
|
} else {
|
||||||
ancillaryColor
|
ancillaryColor
|
||||||
@ -266,7 +280,8 @@ fun PostCardFooter(
|
|||||||
onDismiss = {
|
onDismiss = {
|
||||||
optionsMenuOpen.value = false
|
optionsMenuOpen.value = false
|
||||||
},
|
},
|
||||||
offset = DpOffset(
|
offset =
|
||||||
|
DpOffset(
|
||||||
x = optionsOffset.x.toLocalDp(),
|
x = optionsOffset.x.toLocalDp(),
|
||||||
y = optionsOffset.y.toLocalDp(),
|
y = optionsOffset.y.toLocalDp(),
|
||||||
),
|
),
|
||||||
|
@ -37,7 +37,8 @@ fun PostCardImage(
|
|||||||
) {
|
) {
|
||||||
if (imageUrl.isNotEmpty()) {
|
if (imageUrl.isNotEmpty()) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = modifier.fillMaxWidth()
|
modifier =
|
||||||
|
modifier.fillMaxWidth()
|
||||||
.heightIn(min = minHeight, max = maxHeight)
|
.heightIn(min = minHeight, max = maxHeight)
|
||||||
.blur(radius = if (blurred) 60.dp else 0.dp)
|
.blur(radius = if (blurred) 60.dp else 0.dp)
|
||||||
.onClick(
|
.onClick(
|
||||||
@ -59,14 +60,16 @@ fun PostCardImage(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onLoading = { progress ->
|
onLoading = { progress ->
|
||||||
val prog = if (progress != null) {
|
val prog =
|
||||||
|
if (progress != null) {
|
||||||
progress
|
progress
|
||||||
} else {
|
} else {
|
||||||
val transition = rememberInfiniteTransition()
|
val transition = rememberInfiniteTransition()
|
||||||
val res by transition.animateFloat(
|
val res by transition.animateFloat(
|
||||||
initialValue = 0f,
|
initialValue = 0f,
|
||||||
targetValue = 1f,
|
targetValue = 1f,
|
||||||
animationSpec = InfiniteRepeatableSpec(
|
animationSpec =
|
||||||
|
InfiniteRepeatableSpec(
|
||||||
animation = tween(1000),
|
animation = tween(1000),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,8 @@ fun PostCardPlaceholder(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.size(IconSize.s)
|
modifier =
|
||||||
|
Modifier.size(IconSize.s)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
@ -51,13 +52,15 @@ fun PostCardPlaceholder(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth(0.5f)
|
.fillMaxWidth(0.5f)
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -69,14 +72,16 @@ fun PostCardPlaceholder(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.xs),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.xs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(0.2f)
|
.weight(0.2f)
|
||||||
.aspectRatio(1.33f)
|
.aspectRatio(1.33f)
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(40.dp)
|
.height(40.dp)
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
@ -84,7 +89,8 @@ fun PostCardPlaceholder(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
@ -95,7 +101,8 @@ fun PostCardPlaceholder(
|
|||||||
|
|
||||||
PostLayout.Card -> {
|
PostLayout.Card -> {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.shadow(elevation = 5.dp, shape = RoundedCornerShape(CornerSize.l))
|
.shadow(elevation = 5.dp, shape = RoundedCornerShape(CornerSize.l))
|
||||||
.clip(RoundedCornerShape(CornerSize.l))
|
.clip(RoundedCornerShape(CornerSize.l))
|
||||||
.background(
|
.background(
|
||||||
@ -109,7 +116,8 @@ fun PostCardPlaceholder(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.size(IconSize.l)
|
.size(IconSize.l)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -119,13 +127,15 @@ fun PostCardPlaceholder(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth(0.5f)
|
.fillMaxWidth(0.5f)
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -133,20 +143,23 @@ fun PostCardPlaceholder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.l)
|
modifier =
|
||||||
|
Modifier.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(200.dp)
|
.height(200.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
@ -165,7 +178,8 @@ fun PostCardPlaceholder(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.size(IconSize.l)
|
.size(IconSize.l)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -175,13 +189,15 @@ fun PostCardPlaceholder(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.height(IconSize.s)
|
modifier =
|
||||||
|
Modifier.height(IconSize.s)
|
||||||
.fillMaxWidth(0.5f)
|
.fillMaxWidth(0.5f)
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
@ -189,21 +205,24 @@ fun PostCardPlaceholder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(200.dp)
|
.height(200.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.s))
|
.clip(RoundedCornerShape(CornerSize.s))
|
||||||
.shimmerEffect(),
|
.shimmerEffect(),
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(IconSize.l)
|
.height(IconSize.l)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(CornerSize.m))
|
.clip(RoundedCornerShape(CornerSize.m))
|
||||||
|
@ -50,12 +50,14 @@ fun PostCardTitle(
|
|||||||
val themeRepository = remember { getThemeRepository() }
|
val themeRepository = remember { getThemeRepository() }
|
||||||
val fontFamily by themeRepository.contentFontFamily.collectAsState()
|
val fontFamily by themeRepository.contentFontFamily.collectAsState()
|
||||||
val typography = fontFamily.toTypography()
|
val typography = fontFamily.toTypography()
|
||||||
val weightNormalOrLight = if (bolder) {
|
val weightNormalOrLight =
|
||||||
|
if (bolder) {
|
||||||
FontWeight.Normal
|
FontWeight.Normal
|
||||||
} else {
|
} else {
|
||||||
FontWeight.Light
|
FontWeight.Light
|
||||||
}
|
}
|
||||||
val weightMediumOrNormal = if (bolder) {
|
val weightMediumOrNormal =
|
||||||
|
if (bolder) {
|
||||||
FontWeight.Medium
|
FontWeight.Medium
|
||||||
} else {
|
} else {
|
||||||
FontWeight.Normal
|
FontWeight.Normal
|
||||||
@ -66,7 +68,8 @@ fun PostCardTitle(
|
|||||||
modifier = modifier.padding(horizontal = Spacing.xxs),
|
modifier = modifier.padding(horizontal = Spacing.xxs),
|
||||||
content = text,
|
content = text,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
typography = markdownTypography(
|
typography =
|
||||||
|
markdownTypography(
|
||||||
h1 = typography.titleLarge.copy(fontWeight = weightNormalOrLight),
|
h1 = typography.titleLarge.copy(fontWeight = weightNormalOrLight),
|
||||||
h2 = typography.titleLarge.copy(fontWeight = weightNormalOrLight),
|
h2 = typography.titleLarge.copy(fontWeight = weightNormalOrLight),
|
||||||
h3 = typography.titleMedium.copy(fontWeight = weightMediumOrNormal),
|
h3 = typography.titleMedium.copy(fontWeight = weightMediumOrNormal),
|
||||||
@ -81,13 +84,15 @@ fun PostCardTitle(
|
|||||||
ordered = typography.bodyMedium,
|
ordered = typography.bodyMedium,
|
||||||
code = typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
code = typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
|
||||||
),
|
),
|
||||||
colors = markdownColor(
|
colors =
|
||||||
|
markdownColor(
|
||||||
text = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
text = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
||||||
codeText = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
codeText = MaterialTheme.colorScheme.onBackground.copy(alpha = additionalAlphaFactor),
|
||||||
codeBackground = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
|
codeBackground = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
|
||||||
dividerColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
|
dividerColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f),
|
||||||
),
|
),
|
||||||
onOpenUrl = rememberCallbackArgs { url ->
|
onOpenUrl =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = url,
|
url = url,
|
||||||
openingMode = settingsRepository.currentSettings.value.urlOpeningMode.toUrlOpeningMode(),
|
openingMode = settingsRepository.currentSettings.value.urlOpeningMode.toUrlOpeningMode(),
|
||||||
@ -99,7 +104,8 @@ fun PostCardTitle(
|
|||||||
onOpenWeb = onOpenWeb,
|
onOpenWeb = onOpenWeb,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenImage = rememberCallbackArgs { url ->
|
onOpenImage =
|
||||||
|
rememberCallbackArgs { url ->
|
||||||
onOpenImage?.invoke(url)
|
onOpenImage?.invoke(url)
|
||||||
},
|
},
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
@ -24,7 +24,8 @@ fun PostLinkBanner(
|
|||||||
) {
|
) {
|
||||||
if (url.isNotEmpty()) {
|
if (url.isNotEmpty()) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f),
|
color = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f),
|
||||||
shape = RoundedCornerShape(CornerSize.l),
|
shape = RoundedCornerShape(CornerSize.l),
|
||||||
|
@ -2,5 +2,6 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui
|
|||||||
|
|
||||||
sealed interface ProfileLoggedSection {
|
sealed interface ProfileLoggedSection {
|
||||||
data object Posts : ProfileLoggedSection
|
data object Posts : ProfileLoggedSection
|
||||||
|
|
||||||
data object Comments : ProfileLoggedSection
|
data object Comments : ProfileLoggedSection
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ fun SettingsFormattedInfo(
|
|||||||
) {
|
) {
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
|
@ -24,7 +24,8 @@ fun SettingsHeader(
|
|||||||
) {
|
) {
|
||||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.padding(
|
modifier =
|
||||||
|
modifier.padding(
|
||||||
vertical = Spacing.xxs,
|
vertical = Spacing.xxs,
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
),
|
),
|
||||||
|
@ -31,7 +31,8 @@ fun SettingsImageInfo(
|
|||||||
) {
|
) {
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
|
@ -33,7 +33,8 @@ fun SettingsIntValueRow(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(vertical = Spacing.s),
|
.padding(vertical = Spacing.s),
|
||||||
) {
|
) {
|
||||||
@ -59,7 +60,8 @@ fun SettingsIntValueRow(
|
|||||||
onClick = onDecrement,
|
onClick = onDecrement,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.sizeIn(minWidth = 40.dp)
|
.sizeIn(minWidth = 40.dp)
|
||||||
.padding(horizontal = Spacing.s),
|
.padding(horizontal = Spacing.s),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
@ -38,7 +38,8 @@ fun SettingsRow(
|
|||||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
horizontal = Spacing.m,
|
horizontal = Spacing.m,
|
||||||
|
@ -27,7 +27,8 @@ fun SettingsTextualInfo(
|
|||||||
val fullColor = MaterialTheme.colorScheme.onBackground
|
val fullColor = MaterialTheme.colorScheme.onBackground
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier =
|
||||||
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
|
@ -57,12 +57,15 @@ fun TextFormattingBar(
|
|||||||
// bold
|
// bold
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val selection = textFieldValue.selection
|
val selection = textFieldValue.selection
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
val newText = buildString {
|
textFieldValue.let {
|
||||||
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("**")
|
append("**")
|
||||||
if (selection.collapsed) {
|
if (selection.collapsed) {
|
||||||
@ -83,7 +86,8 @@ fun TextFormattingBar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val newSelection = if (selection.collapsed) {
|
val newSelection =
|
||||||
|
if (selection.collapsed) {
|
||||||
TextRange(index = selection.start + textPlaceholder.length + 2)
|
TextRange(index = selection.start + textPlaceholder.length + 2)
|
||||||
} else {
|
} else {
|
||||||
TextRange(
|
TextRange(
|
||||||
@ -105,12 +109,15 @@ fun TextFormattingBar(
|
|||||||
// italic
|
// italic
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val selection = textFieldValue.selection
|
val selection = textFieldValue.selection
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
val newText = buildString {
|
textFieldValue.let {
|
||||||
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("*")
|
append("*")
|
||||||
if (selection.collapsed) {
|
if (selection.collapsed) {
|
||||||
@ -131,7 +138,8 @@ fun TextFormattingBar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val newSelection = if (selection.collapsed) {
|
val newSelection =
|
||||||
|
if (selection.collapsed) {
|
||||||
TextRange(index = selection.start + textPlaceholder.length + 1)
|
TextRange(index = selection.start + textPlaceholder.length + 1)
|
||||||
} else {
|
} else {
|
||||||
TextRange(
|
TextRange(
|
||||||
@ -153,12 +161,15 @@ fun TextFormattingBar(
|
|||||||
// strikethrough
|
// strikethrough
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val selection = textFieldValue.selection
|
val selection = textFieldValue.selection
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
val newText = buildString {
|
textFieldValue.let {
|
||||||
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("~~")
|
append("~~")
|
||||||
if (selection.collapsed) {
|
if (selection.collapsed) {
|
||||||
@ -179,7 +190,8 @@ fun TextFormattingBar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val newSelection = if (selection.collapsed) {
|
val newSelection =
|
||||||
|
if (selection.collapsed) {
|
||||||
TextRange(index = selection.start + textPlaceholder.length + 2)
|
TextRange(index = selection.start + textPlaceholder.length + 2)
|
||||||
} else {
|
} else {
|
||||||
TextRange(
|
TextRange(
|
||||||
@ -202,7 +214,8 @@ fun TextFormattingBar(
|
|||||||
if (onSelectImage != null) {
|
if (onSelectImage != null) {
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
onSelectImage.invoke()
|
onSelectImage.invoke()
|
||||||
},
|
},
|
||||||
@ -217,12 +230,15 @@ fun TextFormattingBar(
|
|||||||
// hyperlink
|
// hyperlink
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
|
textFieldValue.let {
|
||||||
val selection = it.selection
|
val selection = it.selection
|
||||||
val newText = buildString {
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("[")
|
append("[")
|
||||||
if (selection.collapsed) {
|
if (selection.collapsed) {
|
||||||
@ -245,7 +261,8 @@ fun TextFormattingBar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val newSelection = if (selection.collapsed) {
|
val newSelection =
|
||||||
|
if (selection.collapsed) {
|
||||||
TextRange(index = selection.start + textPlaceholder.length + 1)
|
TextRange(index = selection.start + textPlaceholder.length + 1)
|
||||||
} else {
|
} else {
|
||||||
TextRange(
|
TextRange(
|
||||||
@ -267,12 +284,15 @@ fun TextFormattingBar(
|
|||||||
// inline code
|
// inline code
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
|
textFieldValue.let {
|
||||||
val selection = it.selection
|
val selection = it.selection
|
||||||
val newText = buildString {
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("`")
|
append("`")
|
||||||
if (selection.collapsed) {
|
if (selection.collapsed) {
|
||||||
@ -293,7 +313,8 @@ fun TextFormattingBar(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val newSelection = if (selection.collapsed) {
|
val newSelection =
|
||||||
|
if (selection.collapsed) {
|
||||||
TextRange(index = selection.start + textPlaceholder.length + 1)
|
TextRange(index = selection.start + textPlaceholder.length + 1)
|
||||||
} else {
|
} else {
|
||||||
TextRange(
|
TextRange(
|
||||||
@ -315,12 +336,15 @@ fun TextFormattingBar(
|
|||||||
// block quote
|
// block quote
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
|
textFieldValue.let {
|
||||||
val selection = it.selection
|
val selection = it.selection
|
||||||
val newText = buildString {
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("\n> ")
|
append("\n> ")
|
||||||
append(
|
append(
|
||||||
@ -345,12 +369,15 @@ fun TextFormattingBar(
|
|||||||
// bulleted list
|
// bulleted list
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
|
textFieldValue.let {
|
||||||
val selection = it.selection
|
val selection = it.selection
|
||||||
val newText = buildString {
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("\n- ")
|
append("\n- ")
|
||||||
append(
|
append(
|
||||||
@ -375,12 +402,15 @@ fun TextFormattingBar(
|
|||||||
// numbered list
|
// numbered list
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
key = textFieldValue,
|
key = textFieldValue,
|
||||||
onClick = {
|
onClick = {
|
||||||
val newValue = textFieldValue.let {
|
val newValue =
|
||||||
|
textFieldValue.let {
|
||||||
val selection = it.selection
|
val selection = it.selection
|
||||||
val newText = buildString {
|
val newText =
|
||||||
|
buildString {
|
||||||
append(it.text.substring(0, selection.start))
|
append(it.text.substring(0, selection.start))
|
||||||
append("\n1. ")
|
append("\n1. ")
|
||||||
append(
|
append(
|
||||||
@ -406,7 +436,8 @@ fun TextFormattingBar(
|
|||||||
if (onSelectLanguage != null) {
|
if (onSelectLanguage != null) {
|
||||||
item {
|
item {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.size(IconSize.m)
|
.size(IconSize.m)
|
||||||
.border(
|
.border(
|
||||||
color = MaterialTheme.colorScheme.onBackground,
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
@ -417,7 +448,8 @@ fun TextFormattingBar(
|
|||||||
.padding(Spacing.xxxs),
|
.padding(Spacing.xxxs),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
val languageCode = availableLanguages.firstOrNull { l ->
|
val languageCode =
|
||||||
|
availableLanguages.firstOrNull { l ->
|
||||||
l.id == currentLanguageId
|
l.id == currentLanguageId
|
||||||
}?.takeIf { l ->
|
}?.takeIf { l ->
|
||||||
l.id > 0 // undetermined language
|
l.id > 0 // undetermined language
|
||||||
@ -436,7 +468,8 @@ fun TextFormattingBar(
|
|||||||
if (lastActionIcon != null && onLastAction != null) {
|
if (lastActionIcon != null && onLastAction != null) {
|
||||||
item {
|
item {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier =
|
||||||
|
Modifier.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
onLastAction()
|
onLastAction()
|
||||||
},
|
},
|
||||||
|
@ -93,7 +93,8 @@ fun NavigationCoordinator.handleUrl(
|
|||||||
private fun normalizeUrl(url: String?): Pair<String, String> {
|
private fun normalizeUrl(url: String?): Pair<String, String> {
|
||||||
val matches = Regex("https?://(?<instance>.*?)(?<pathAndQuery>/.*)").findAll(url.orEmpty())
|
val matches = Regex("https?://(?<instance>.*?)(?<pathAndQuery>/.*)").findAll(url.orEmpty())
|
||||||
var instance = ""
|
var instance = ""
|
||||||
val res = buildString {
|
val res =
|
||||||
|
buildString {
|
||||||
if (matches.count() > 0) {
|
if (matches.count() > 0) {
|
||||||
val match = matches.iterator().next()
|
val match = matches.iterator().next()
|
||||||
val value = match.groups["pathAndQuery"]?.value.orEmpty()
|
val value = match.groups["pathAndQuery"]?.value.orEmpty()
|
||||||
@ -110,7 +111,8 @@ private fun normalizeUrl(url: String?): Pair<String, String> {
|
|||||||
return res to instance
|
return res to instance
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractCommunity(url: String): CommunityModel? = when {
|
private fun extractCommunity(url: String): CommunityModel? =
|
||||||
|
when {
|
||||||
url.startsWith("/c/") -> {
|
url.startsWith("/c/") -> {
|
||||||
val cleanString = url.substring(3)
|
val cleanString = url.substring(3)
|
||||||
if (cleanString.count { it == '@' } == 1) {
|
if (cleanString.count { it == '@' } == 1) {
|
||||||
@ -142,9 +144,10 @@ private fun extractCommunity(url: String): CommunityModel? = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractUser(url: String): UserModel? = when {
|
private fun extractUser(url: String): UserModel? =
|
||||||
|
when {
|
||||||
url.startsWith("@") -> {
|
url.startsWith("@") -> {
|
||||||
val cleanString = url.substring(1)
|
val cleanString = url.substring(1)
|
||||||
if (cleanString.count { it == '@' } == 1) {
|
if (cleanString.count { it == '@' } == 1) {
|
||||||
@ -176,12 +179,13 @@ private fun extractUser(url: String): UserModel? = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractPost(url: String): PostModel? {
|
private fun extractPost(url: String): PostModel? {
|
||||||
val regex = Regex("/post/(?<postId>.*$)")
|
val regex = Regex("/post/(?<postId>.*$)")
|
||||||
val match = regex.find(url)
|
val match = regex.find(url)
|
||||||
val id = match
|
val id =
|
||||||
|
match
|
||||||
?.let { it.groups["postId"]?.value.orEmpty() }?.toLongOrNull()
|
?.let { it.groups["postId"]?.value.orEmpty() }?.toLongOrNull()
|
||||||
return if (id != null) {
|
return if (id != null) {
|
||||||
PostModel(id = id)
|
PostModel(id = id)
|
||||||
|
@ -2,5 +2,6 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui
|
|||||||
|
|
||||||
sealed interface UserDetailSection {
|
sealed interface UserDetailSection {
|
||||||
data object Posts : UserDetailSection
|
data object Posts : UserDetailSection
|
||||||
|
|
||||||
data object Comments : UserDetailSection
|
data object Comments : UserDetailSection
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,12 @@ fun UserHeader(
|
|||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize().background(
|
modifier =
|
||||||
brush = Brush.horizontalGradient(
|
Modifier.fillMaxSize().background(
|
||||||
colors = listOf(
|
brush =
|
||||||
|
Brush.horizontalGradient(
|
||||||
|
colors =
|
||||||
|
listOf(
|
||||||
MaterialTheme.colorScheme.background.copy(alpha = 0.95f),
|
MaterialTheme.colorScheme.background.copy(alpha = 0.95f),
|
||||||
Color.Transparent,
|
Color.Transparent,
|
||||||
MaterialTheme.colorScheme.background.copy(alpha = 0.75f),
|
MaterialTheme.colorScheme.background.copy(alpha = 0.75f),
|
||||||
@ -92,7 +95,8 @@ fun UserHeader(
|
|||||||
val userAvatar = user.avatar.orEmpty()
|
val userAvatar = user.avatar.orEmpty()
|
||||||
if (userAvatar.isNotEmpty() && autoLoadImages) {
|
if (userAvatar.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier.padding(Spacing.xxxs)
|
modifier =
|
||||||
|
Modifier.padding(Spacing.xxxs)
|
||||||
.size(IconSize.xxl)
|
.size(IconSize.xxl)
|
||||||
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
||||||
.onClick(
|
.onClick(
|
||||||
@ -145,7 +149,8 @@ fun UserHeader(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = postScore.getPrettyNumber(
|
text =
|
||||||
|
postScore.getPrettyNumber(
|
||||||
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
||||||
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
||||||
),
|
),
|
||||||
@ -163,7 +168,8 @@ fun UserHeader(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = commentScore.getPrettyNumber(
|
text =
|
||||||
|
commentScore.getPrettyNumber(
|
||||||
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
thousandLabel = LocalXmlStrings.current.profileThousandShort,
|
||||||
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
millionLabel = LocalXmlStrings.current.profileMillionShort,
|
||||||
),
|
),
|
||||||
@ -199,7 +205,8 @@ fun UserHeader(
|
|||||||
|
|
||||||
if (onInfo != null) {
|
if (onInfo != null) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(end = Spacing.s)
|
.padding(end = Spacing.s)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.onClick(onClick = onInfo),
|
.onClick(onClick = onInfo),
|
||||||
|
@ -60,7 +60,8 @@ fun UserItem(
|
|||||||
var optionsMenuOpen by remember { mutableStateOf(false) }
|
var optionsMenuOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.padding(
|
modifier =
|
||||||
|
modifier.padding(
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
),
|
),
|
||||||
@ -69,7 +70,8 @@ fun UserItem(
|
|||||||
) {
|
) {
|
||||||
if (avatar.isNotEmpty() && autoLoadImages) {
|
if (avatar.isNotEmpty() && autoLoadImages) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier.padding(Spacing.xxxs).size(iconSize)
|
modifier =
|
||||||
|
Modifier.padding(Spacing.xxxs).size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = avatar,
|
url = avatar,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
@ -86,7 +88,8 @@ fun UserItem(
|
|||||||
modifier = Modifier.weight(1f).padding(start = Spacing.xs),
|
modifier = Modifier.weight(1f).padding(start = Spacing.xs),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = buildString {
|
text =
|
||||||
|
buildString {
|
||||||
append(displayName)
|
append(displayName)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
@ -95,7 +98,8 @@ fun UserItem(
|
|||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = buildString {
|
text =
|
||||||
|
buildString {
|
||||||
append("!")
|
append("!")
|
||||||
append(userHandle)
|
append(userHandle)
|
||||||
},
|
},
|
||||||
@ -107,7 +111,8 @@ fun UserItem(
|
|||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Box {
|
Box {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(IconSize.m)
|
modifier =
|
||||||
|
Modifier.size(IconSize.m)
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
@ -127,7 +132,8 @@ fun UserItem(
|
|||||||
onDismiss = {
|
onDismiss = {
|
||||||
optionsMenuOpen = false
|
optionsMenuOpen = false
|
||||||
},
|
},
|
||||||
offset = DpOffset(
|
offset =
|
||||||
|
DpOffset(
|
||||||
x = optionsOffset.x.toLocalDp(),
|
x = optionsOffset.x.toLocalDp(),
|
||||||
y = optionsOffset.y.toLocalDp(),
|
y = optionsOffset.y.toLocalDp(),
|
||||||
),
|
),
|
||||||
|
@ -4,8 +4,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.DefaultFab
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.FabNestedScrollConnection
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.FabNestedScrollConnection
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val lemmyUiModule = module {
|
val lemmyUiModule =
|
||||||
|
module {
|
||||||
factory<FabNestedScrollConnection> {
|
factory<FabNestedScrollConnection> {
|
||||||
DefaultFabNestedScrollConnection()
|
DefaultFabNestedScrollConnection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.FabNestedS
|
|||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
actual fun getFabNestedScrollConnection(): FabNestedScrollConnection =
|
actual fun getFabNestedScrollConnection(): FabNestedScrollConnection = LemmyUiDiHelper.fabNestedScrollConnection
|
||||||
LemmyUiDiHelper.fabNestedScrollConnection
|
|
||||||
|
|
||||||
object LemmyUiDiHelper : KoinComponent {
|
object LemmyUiDiHelper : KoinComponent {
|
||||||
val fabNestedScrollConnection: FabNestedScrollConnection by inject()
|
val fabNestedScrollConnection: FabNestedScrollConnection by inject()
|
||||||
|
@ -33,7 +33,8 @@ class AppIconBottomSheet : Screen {
|
|||||||
val coreResources = remember { getCoreResources() }
|
val coreResources = remember { getCoreResources() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -44,7 +45,8 @@ class AppIconBottomSheet : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
BottomSheetHeader(LocalXmlStrings.current.settingsAppIcon)
|
BottomSheetHeader(LocalXmlStrings.current.settingsAppIcon)
|
||||||
val values = listOf(
|
val values =
|
||||||
|
listOf(
|
||||||
AppIconVariant.Default,
|
AppIconVariant.Default,
|
||||||
AppIconVariant.Alt1,
|
AppIconVariant.Alt1,
|
||||||
)
|
)
|
||||||
@ -56,7 +58,8 @@ class AppIconBottomSheet : Screen {
|
|||||||
SettingsRow(
|
SettingsRow(
|
||||||
modifier = Modifier.padding(vertical = Spacing.xxs),
|
modifier = Modifier.padding(vertical = Spacing.xxs),
|
||||||
title = value.toReadableName(),
|
title = value.toReadableName(),
|
||||||
painter = when (value) {
|
painter =
|
||||||
|
when (value) {
|
||||||
AppIconVariant.Alt1 -> coreResources.appIconAlt1
|
AppIconVariant.Alt1 -> coreResources.appIconAlt1
|
||||||
else -> coreResources.appIconDefault
|
else -> coreResources.appIconDefault
|
||||||
},
|
},
|
||||||
|
@ -27,13 +27,13 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotific
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
|
|
||||||
class BarThemeBottomSheet : Screen {
|
class BarThemeBottomSheet : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -44,7 +44,8 @@ class BarThemeBottomSheet : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
BottomSheetHeader(LocalXmlStrings.current.settingsBarTheme)
|
BottomSheetHeader(LocalXmlStrings.current.settingsBarTheme)
|
||||||
val values = listOf(
|
val values =
|
||||||
|
listOf(
|
||||||
UiBarTheme.Transparent,
|
UiBarTheme.Transparent,
|
||||||
UiBarTheme.Opaque,
|
UiBarTheme.Opaque,
|
||||||
)
|
)
|
||||||
@ -54,7 +55,8 @@ class BarThemeBottomSheet : Screen {
|
|||||||
) {
|
) {
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
)
|
)
|
||||||
|
@ -37,14 +37,14 @@ class BlockBottomSheet(
|
|||||||
private val userInstanceName: String? = null,
|
private val userInstanceName: String? = null,
|
||||||
private val userInstanceId: Long? = null,
|
private val userInstanceId: Long? = null,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -59,30 +59,35 @@ class BlockBottomSheet(
|
|||||||
modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
|
modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
|
||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
val values: List<Triple<BlockActionType, Long, String>> = buildList {
|
val values: List<Triple<BlockActionType, Long, String>> =
|
||||||
|
buildList {
|
||||||
if (userName != null && userId != null) {
|
if (userName != null && userId != null) {
|
||||||
this += Triple(
|
this +=
|
||||||
|
Triple(
|
||||||
BlockActionType.User,
|
BlockActionType.User,
|
||||||
userId,
|
userId,
|
||||||
userName,
|
userName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (communityName != null && communityId != null) {
|
if (communityName != null && communityId != null) {
|
||||||
this += Triple(
|
this +=
|
||||||
|
Triple(
|
||||||
BlockActionType.Community,
|
BlockActionType.Community,
|
||||||
communityId,
|
communityId,
|
||||||
communityName,
|
communityName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (instanceName != null && instanceId != null) {
|
if (instanceName != null && instanceId != null) {
|
||||||
this += Triple(
|
this +=
|
||||||
|
Triple(
|
||||||
BlockActionType.Instance,
|
BlockActionType.Instance,
|
||||||
instanceId,
|
instanceId,
|
||||||
instanceName,
|
instanceName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (userInstanceName != null && userInstanceId != null && userInstanceName != instanceName) {
|
if (userInstanceName != null && userInstanceId != null && userInstanceName != instanceName) {
|
||||||
this += Triple(
|
this +=
|
||||||
|
Triple(
|
||||||
BlockActionType.Instance,
|
BlockActionType.Instance,
|
||||||
userInstanceId,
|
userInstanceId,
|
||||||
userInstanceName,
|
userInstanceName,
|
||||||
@ -91,7 +96,8 @@ class BlockBottomSheet(
|
|||||||
}
|
}
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -99,8 +105,10 @@ class BlockBottomSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
val event = when (value.first) {
|
val event =
|
||||||
BlockActionType.Community -> NotificationCenterEvent.BlockActionSelected(
|
when (value.first) {
|
||||||
|
BlockActionType.Community ->
|
||||||
|
NotificationCenterEvent.BlockActionSelected(
|
||||||
communityId = value.second,
|
communityId = value.second,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,7 +117,8 @@ class BlockBottomSheet(
|
|||||||
instanceId = value.second,
|
instanceId = value.second,
|
||||||
)
|
)
|
||||||
|
|
||||||
BlockActionType.User -> NotificationCenterEvent.BlockActionSelected(
|
BlockActionType.User ->
|
||||||
|
NotificationCenterEvent.BlockActionSelected(
|
||||||
userId = value.second,
|
userId = value.second,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -119,7 +128,8 @@ class BlockBottomSheet(
|
|||||||
),
|
),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
val valueText = buildString {
|
val valueText =
|
||||||
|
buildString {
|
||||||
append(value.first.toReadableName())
|
append(value.first.toReadableName())
|
||||||
val additionalText = value.third
|
val additionalText = value.third
|
||||||
if (additionalText.isNotEmpty()) {
|
if (additionalText.isNotEmpty()) {
|
||||||
|
@ -29,14 +29,14 @@ class CopyPostBottomSheet(
|
|||||||
private val title: String? = null,
|
private val title: String? = null,
|
||||||
private val text: String? = null,
|
private val text: String? = null,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -55,7 +55,8 @@ class CopyPostBottomSheet(
|
|||||||
val textCanBeCopied = !text.isNullOrBlank()
|
val textCanBeCopied = !text.isNullOrBlank()
|
||||||
if (titleCanBeCopied) {
|
if (titleCanBeCopied) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -79,7 +80,8 @@ class CopyPostBottomSheet(
|
|||||||
}
|
}
|
||||||
if (textCanBeCopied) {
|
if (textCanBeCopied) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -101,13 +103,15 @@ class CopyPostBottomSheet(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (titleCanBeCopied) {
|
if (titleCanBeCopied) {
|
||||||
val textToCopy = buildString {
|
val textToCopy =
|
||||||
|
buildString {
|
||||||
append(title)
|
append(title)
|
||||||
append("\n")
|
append("\n")
|
||||||
append(text)
|
append(text)
|
||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
|
@ -34,7 +34,8 @@ enum class DurationBottomSheetType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DurationBottomSheet(
|
class DurationBottomSheet(
|
||||||
private val values: List<Duration> = listOf(
|
private val values: List<Duration> =
|
||||||
|
listOf(
|
||||||
1.seconds,
|
1.seconds,
|
||||||
2.seconds,
|
2.seconds,
|
||||||
3.seconds,
|
3.seconds,
|
||||||
@ -43,13 +44,13 @@ class DurationBottomSheet(
|
|||||||
),
|
),
|
||||||
private val type: DurationBottomSheetType = DurationBottomSheetType.ZOMBIE_MODE_INTERVAL,
|
private val type: DurationBottomSheetType = DurationBottomSheetType.ZOMBIE_MODE_INTERVAL,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -59,7 +60,8 @@ class DurationBottomSheet(
|
|||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
val title = when (type) {
|
val title =
|
||||||
|
when (type) {
|
||||||
DurationBottomSheetType.ZOMBIE_MODE_INTERVAL -> LocalXmlStrings.current.settingsZombieModeInterval
|
DurationBottomSheetType.ZOMBIE_MODE_INTERVAL -> LocalXmlStrings.current.settingsZombieModeInterval
|
||||||
DurationBottomSheetType.INBOX_CHECK_PERIOD -> LocalXmlStrings.current.settingsInboxBackgroundCheckPeriod
|
DurationBottomSheetType.INBOX_CHECK_PERIOD -> LocalXmlStrings.current.settingsInboxBackgroundCheckPeriod
|
||||||
}
|
}
|
||||||
@ -70,7 +72,8 @@ class DurationBottomSheet(
|
|||||||
) {
|
) {
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -78,7 +81,8 @@ class DurationBottomSheet(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
onClick = {
|
onClick = {
|
||||||
val event = when (type) {
|
val event =
|
||||||
|
when (type) {
|
||||||
DurationBottomSheetType.ZOMBIE_MODE_INTERVAL ->
|
DurationBottomSheetType.ZOMBIE_MODE_INTERVAL ->
|
||||||
NotificationCenterEvent.ChangeZombieInterval(value)
|
NotificationCenterEvent.ChangeZombieInterval(value)
|
||||||
|
|
||||||
@ -92,7 +96,8 @@ class DurationBottomSheet(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = value.getPrettyDuration(
|
text =
|
||||||
|
value.getPrettyDuration(
|
||||||
secondsLabel = LocalXmlStrings.current.postSecondShort,
|
secondsLabel = LocalXmlStrings.current.postSecondShort,
|
||||||
minutesLabel = LocalXmlStrings.current.postMinuteShort,
|
minutesLabel = LocalXmlStrings.current.postMinuteShort,
|
||||||
hoursLabel = LocalXmlStrings.current.postHourShort,
|
hoursLabel = LocalXmlStrings.current.postHourShort,
|
||||||
|
@ -64,7 +64,8 @@ fun EditFormattedInfoDialog(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.imePadding()
|
.imePadding()
|
||||||
.background(color = MaterialTheme.colorScheme.surface)
|
.background(color = MaterialTheme.colorScheme.surface)
|
||||||
.padding(Spacing.s),
|
.padding(Spacing.s),
|
||||||
@ -82,16 +83,19 @@ fun EditFormattedInfoDialog(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
|
||||||
) {
|
) {
|
||||||
SectionSelector(
|
SectionSelector(
|
||||||
titles = listOf(
|
titles =
|
||||||
|
listOf(
|
||||||
LocalXmlStrings.current.createPostTabEditor,
|
LocalXmlStrings.current.createPostTabEditor,
|
||||||
LocalXmlStrings.current.createPostTabPreview,
|
LocalXmlStrings.current.createPostTabPreview,
|
||||||
),
|
),
|
||||||
currentSection = when (currentSection) {
|
currentSection =
|
||||||
|
when (currentSection) {
|
||||||
CreatePostSection.Preview -> 1
|
CreatePostSection.Preview -> 1
|
||||||
else -> 0
|
else -> 0
|
||||||
},
|
},
|
||||||
onSectionSelected = {
|
onSectionSelected = {
|
||||||
val section = when (it) {
|
val section =
|
||||||
|
when (it) {
|
||||||
1 -> CreatePostSection.Preview
|
1 -> CreatePostSection.Preview
|
||||||
else -> CreatePostSection.Edit
|
else -> CreatePostSection.Edit
|
||||||
}
|
}
|
||||||
@ -101,7 +105,8 @@ fun EditFormattedInfoDialog(
|
|||||||
|
|
||||||
if (currentSection == CreatePostSection.Edit) {
|
if (currentSection == CreatePostSection.Edit) {
|
||||||
TextFormattingBar(
|
TextFormattingBar(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
start = Spacing.s,
|
start = Spacing.s,
|
||||||
end = Spacing.s,
|
end = Spacing.s,
|
||||||
@ -112,10 +117,12 @@ fun EditFormattedInfoDialog(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(400.dp)
|
.height(400.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
colors = TextFieldDefaults.colors(
|
colors =
|
||||||
|
TextFieldDefaults.colors(
|
||||||
focusedContainerColor = Color.Transparent,
|
focusedContainerColor = Color.Transparent,
|
||||||
unfocusedContainerColor = Color.Transparent,
|
unfocusedContainerColor = Color.Transparent,
|
||||||
disabledContainerColor = Color.Transparent,
|
disabledContainerColor = Color.Transparent,
|
||||||
@ -128,7 +135,8 @@ fun EditFormattedInfoDialog(
|
|||||||
},
|
},
|
||||||
textStyle = typography.bodyMedium,
|
textStyle = typography.bodyMedium,
|
||||||
value = textFieldValue,
|
value = textFieldValue,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions =
|
||||||
|
KeyboardOptions(
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
autoCorrect = true,
|
autoCorrect = true,
|
||||||
capitalization = KeyboardCapitalization.Sentences,
|
capitalization = KeyboardCapitalization.Sentences,
|
||||||
@ -139,12 +147,14 @@ fun EditFormattedInfoDialog(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.height(400.dp)
|
.height(400.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
PostCardBody(
|
PostCardBody(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(Spacing.s)
|
.padding(Spacing.s)
|
||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState()),
|
||||||
text = textFieldValue.text,
|
text = textFieldValue.text,
|
||||||
|
@ -52,7 +52,8 @@ fun EditTextualInfoDialog(
|
|||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.imePadding()
|
.imePadding()
|
||||||
.background(color = MaterialTheme.colorScheme.surface)
|
.background(color = MaterialTheme.colorScheme.surface)
|
||||||
.padding(Spacing.s),
|
.padding(Spacing.s),
|
||||||
@ -68,7 +69,8 @@ fun EditTextualInfoDialog(
|
|||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
colors = TextFieldDefaults.colors(
|
colors =
|
||||||
|
TextFieldDefaults.colors(
|
||||||
focusedContainerColor = Color.Transparent,
|
focusedContainerColor = Color.Transparent,
|
||||||
unfocusedContainerColor = Color.Transparent,
|
unfocusedContainerColor = Color.Transparent,
|
||||||
disabledContainerColor = Color.Transparent,
|
disabledContainerColor = Color.Transparent,
|
||||||
@ -81,7 +83,8 @@ fun EditTextualInfoDialog(
|
|||||||
},
|
},
|
||||||
textStyle = typography.bodyMedium,
|
textStyle = typography.bodyMedium,
|
||||||
value = textFieldValue,
|
value = textFieldValue,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions =
|
||||||
|
KeyboardOptions(
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
autoCorrect = true,
|
autoCorrect = true,
|
||||||
),
|
),
|
||||||
|
@ -32,7 +32,8 @@ class InboxTypeSheet : Screen {
|
|||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -48,7 +49,8 @@ class InboxTypeSheet : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -71,7 +73,8 @@ class InboxTypeSheet : Screen {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
|
@ -30,13 +30,13 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageFlag
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageName
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageName
|
||||||
|
|
||||||
class LanguageBottomSheet : Screen {
|
class LanguageBottomSheet : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.safeContent)
|
.windowInsetsPadding(WindowInsets.safeContent)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -47,7 +47,8 @@ class LanguageBottomSheet : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
BottomSheetHeader(LocalXmlStrings.current.settingsLanguage)
|
BottomSheetHeader(LocalXmlStrings.current.settingsLanguage)
|
||||||
val values = listOf(
|
val values =
|
||||||
|
listOf(
|
||||||
Locales.Ar,
|
Locales.Ar,
|
||||||
Locales.Bg,
|
Locales.Bg,
|
||||||
Locales.Cs,
|
Locales.Cs,
|
||||||
@ -84,7 +85,8 @@ class LanguageBottomSheet : Screen {
|
|||||||
Locales.Uk,
|
Locales.Uk,
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.verticalScroll(rememberScrollState()),
|
.verticalScroll(rememberScrollState()),
|
||||||
@ -92,7 +94,8 @@ class LanguageBottomSheet : Screen {
|
|||||||
) {
|
) {
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
)
|
)
|
||||||
@ -108,7 +111,8 @@ class LanguageBottomSheet : Screen {
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = buildAnnotatedString {
|
text =
|
||||||
|
buildAnnotatedString {
|
||||||
with(value) {
|
with(value) {
|
||||||
append(toLanguageFlag())
|
append(toLanguageFlag())
|
||||||
append(" ")
|
append(" ")
|
||||||
|
@ -32,7 +32,8 @@ class LikedTypeSheet : Screen {
|
|||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -48,7 +49,8 @@ class LikedTypeSheet : Screen {
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
@ -71,7 +73,8 @@ class LikedTypeSheet : Screen {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
|
@ -41,7 +41,8 @@ class ListingTypeBottomSheet(
|
|||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier =
|
||||||
|
Modifier
|
||||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||||
.padding(
|
.padding(
|
||||||
top = Spacing.s,
|
top = Spacing.s,
|
||||||
@ -52,7 +53,8 @@ class ListingTypeBottomSheet(
|
|||||||
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
verticalArrangement = Arrangement.spacedBy(Spacing.s),
|
||||||
) {
|
) {
|
||||||
BottomSheetHeader(LocalXmlStrings.current.homeListingTitle)
|
BottomSheetHeader(LocalXmlStrings.current.homeListingTitle)
|
||||||
val values = buildList {
|
val values =
|
||||||
|
buildList {
|
||||||
if (isLogged) {
|
if (isLogged) {
|
||||||
this += ListingType.Subscribed
|
this += ListingType.Subscribed
|
||||||
}
|
}
|
||||||
@ -65,7 +67,8 @@ class ListingTypeBottomSheet(
|
|||||||
) {
|
) {
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(
|
modifier =
|
||||||
|
Modifier.padding(
|
||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
)
|
)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user