Add a settings screen.
This commit is contained in:
parent
90bf11909f
commit
a6124cbe79
28 changed files with 668 additions and 63 deletions
|
|
@ -161,6 +161,9 @@ dependencies {
|
|||
implementation("androidx.room:room-ktx:2.6.1")
|
||||
ksp("androidx.room:room-compiler:2.6.1")
|
||||
|
||||
// DataStore
|
||||
implementation("androidx.datastore:datastore-preferences:1.1.1")
|
||||
|
||||
// Image
|
||||
implementation("io.coil-kt:coil-compose:2.6.0")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
|
|
@ -57,6 +56,7 @@ val LocalRollOverlay = compositionLocalOf<BlurredRollOverlayHostState> {
|
|||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
private val themeViewModel: ThemeViewModel by viewModels()
|
||||
private val launcherViewModel: LauncherViewModel by viewModels()
|
||||
private val rollViewModel: RollOverlayViewModel by viewModels()
|
||||
|
||||
|
|
@ -72,16 +72,18 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
|
||||
setContent {
|
||||
LexiconTheme {
|
||||
val snack = remember { SnackbarHostState() }
|
||||
val overlay = rememberBlurredRollOverlayHostState(
|
||||
viewModel = rollViewModel,
|
||||
)
|
||||
val snack = remember { SnackbarHostState() }
|
||||
val overlay = rememberBlurredRollOverlayHostState(
|
||||
viewModel = rollViewModel,
|
||||
)
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalActivity provides this,
|
||||
LocalSnack provides snack,
|
||||
LocalRollOverlay provides overlay,
|
||||
CompositionLocalProvider(
|
||||
LocalActivity provides this,
|
||||
LocalSnack provides snack,
|
||||
LocalRollOverlay provides overlay,
|
||||
) {
|
||||
LexiconTheme(
|
||||
isDarkTheme = themeViewModel.useDarkTheme.value
|
||||
) {
|
||||
Scaffold(
|
||||
contentWindowInsets = NO_WINDOW_INSETS,
|
||||
|
|
@ -106,7 +108,7 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
},
|
||||
snackbarHost = {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val isDarkTheme = themeViewModel.useDarkTheme.value
|
||||
val elevation = remember {
|
||||
derivedStateOf { if (isDarkTheme) 2.dp else 0.dp }
|
||||
}
|
||||
|
|
@ -145,15 +147,17 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
)
|
||||
BackHandler(enabled = overlay.isOverlayVisible) {
|
||||
overlay.hideOverlay()
|
||||
}
|
||||
}
|
||||
|
||||
HandleFetchError(
|
||||
snack = snack,
|
||||
errors = launcherViewModel.error,
|
||||
)
|
||||
BackHandler(
|
||||
enabled = overlay.isOverlayVisible,
|
||||
onBack = { overlay.hideOverlay() },
|
||||
)
|
||||
|
||||
HandleFetchError(
|
||||
snack = snack,
|
||||
errors = launcherViewModel.error,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
52
app/src/main/java/com/pixelized/rplexicon/ThemeViewModel.kt
Normal file
52
app/src/main/java/com/pixelized/rplexicon/ThemeViewModel.kt
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package com.pixelized.rplexicon
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.pixelized.rplexicon.data.repository.preferences.PreferencesRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ThemeViewModel @Inject constructor(
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
val useDarkTheme: State<Boolean>
|
||||
@Composable
|
||||
@Stable
|
||||
get() {
|
||||
val systemDarkTheme = isSystemInDarkTheme()
|
||||
val useDarkTheme = preferencesRepository.useDarkThemeFlow.collectAsState(
|
||||
initial = preferencesRepository.useDarkThemeFlow.value ?: systemDarkTheme
|
||||
)
|
||||
return remember {
|
||||
derivedStateOf {
|
||||
useDarkTheme.value ?: systemDarkTheme
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateDarkThemeUsage(useDarkTheme: Boolean) {
|
||||
preferencesRepository.updateUseDarkTheme(useDarkTheme = useDarkTheme)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun isInDarkTheme(): Boolean {
|
||||
val view = LocalView.current
|
||||
return if (view.isInEditMode) {
|
||||
isSystemInDarkTheme()
|
||||
} else {
|
||||
val themeViewModel: ThemeViewModel = hiltViewModel()
|
||||
themeViewModel.useDarkTheme.value
|
||||
}
|
||||
}
|
||||
|
|
@ -7,4 +7,5 @@ data class LexiconConfig(
|
|||
val featureQuests: Boolean,
|
||||
val featureSummary: Boolean,
|
||||
val featureSearch: Boolean,
|
||||
val featureOther: Boolean,
|
||||
)
|
||||
|
|
@ -24,6 +24,7 @@ class RemoteConfigRepository @Inject constructor() {
|
|||
featureQuests = DEFAULT[FEATURE_QUESTS] as Boolean,
|
||||
featureSummary = DEFAULT[FEATURE_SUMMARY] as Boolean,
|
||||
featureSearch = DEFAULT[FEATURE_SEARCH] as Boolean,
|
||||
featureOther = DEFAULT[FEATURE_OTHER] as Boolean,
|
||||
)
|
||||
)
|
||||
val config: StateFlow<LexiconConfig> get() = _config
|
||||
|
|
@ -54,6 +55,7 @@ class RemoteConfigRepository @Inject constructor() {
|
|||
featureQuests = firebase.getBoolean(FEATURE_QUESTS),
|
||||
featureSummary = firebase.getBoolean(FEATURE_SUMMARY),
|
||||
featureSearch = firebase.getBoolean(FEATURE_SEARCH),
|
||||
featureOther = firebase.getBoolean(FEATURE_OTHER),
|
||||
)
|
||||
_config.value = config
|
||||
}
|
||||
|
|
@ -70,6 +72,7 @@ class RemoteConfigRepository @Inject constructor() {
|
|||
private const val FEATURE_QUESTS = "feature_quests"
|
||||
private const val FEATURE_SUMMARY = "feature_summary"
|
||||
private const val FEATURE_SEARCH = "feature_search"
|
||||
private const val FEATURE_OTHER = "feature_other"
|
||||
|
||||
private val DEFAULT: HashMap<String, Any?> = hashMapOf(
|
||||
FEATURE_ADVENTURE to false,
|
||||
|
|
@ -78,6 +81,7 @@ class RemoteConfigRepository @Inject constructor() {
|
|||
FEATURE_QUESTS to false,
|
||||
FEATURE_SUMMARY to false,
|
||||
FEATURE_SEARCH to false,
|
||||
FEATURE_OTHER to false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.pixelized.rplexicon.data.repository.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PreferencesRepository @Inject constructor(
|
||||
@ApplicationContext context: Context
|
||||
) {
|
||||
private val Context.dataStore by preferencesDataStore(name = "user_preferences")
|
||||
private val dataStore = context.dataStore
|
||||
|
||||
val useDarkThemeFlow: StateFlow<Boolean?> = dataStore.data
|
||||
.catch {
|
||||
emit(emptyPreferences())
|
||||
}.map { preferences ->
|
||||
preferences[PreferencesKeys.USE_DARK_THEME]
|
||||
}.stateIn(
|
||||
scope = CoroutineScope(Dispatchers.Default + Job()),
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = false,
|
||||
)
|
||||
|
||||
suspend fun updateUseDarkTheme(useDarkTheme: Boolean) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[PreferencesKeys.USE_DARK_THEME] = useDarkTheme
|
||||
}
|
||||
}
|
||||
|
||||
object PreferencesKeys {
|
||||
val USE_DARK_THEME = booleanPreferencesKey("use_dark_theme")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
|||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fun BackgroundImage(
|
|||
fun rememberSaturationFilter(
|
||||
saturation: Float = 0f,
|
||||
): ColorFilter {
|
||||
return remember {
|
||||
return remember(saturation) {
|
||||
ColorFilter.colorMatrix(
|
||||
ColorMatrix().also { it.setToSaturation(saturation) }
|
||||
)
|
||||
|
|
@ -86,7 +86,7 @@ fun rememberBackgroundGradient(
|
|||
vararg gradients: Float,
|
||||
): Brush {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
return remember {
|
||||
return remember(colorScheme) {
|
||||
Brush.verticalGradient(
|
||||
colors = gradients.map { colorScheme.surface.copy(alpha = it) }
|
||||
)
|
||||
|
|
@ -99,7 +99,7 @@ fun rememberBackgroundGradient(
|
|||
to: Float = 1.0f,
|
||||
): Brush {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
return remember {
|
||||
return remember(colorScheme) {
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
colorScheme.surface.copy(alpha = from),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.pixelized.rplexicon.ui.composable
|
||||
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -50,4 +51,25 @@ fun rememberAnimatedShadow(
|
|||
targetValue = shadowTarget.value,
|
||||
label = "animated shadow",
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberAnimatedShadow(
|
||||
scrollState: ScrollState,
|
||||
rest: Dp = 0.dp,
|
||||
target: Dp = 4.dp,
|
||||
): State<Dp> {
|
||||
val shadowTarget = remember(scrollState) {
|
||||
derivedStateOf {
|
||||
if (scrollState.value > 0) {
|
||||
target
|
||||
} else {
|
||||
rest
|
||||
}
|
||||
}
|
||||
}
|
||||
return animateDpAsState(
|
||||
targetValue = shadowTarget.value,
|
||||
label = "animated shadow",
|
||||
)
|
||||
}
|
||||
|
|
@ -10,9 +10,9 @@ import androidx.navigation.NavOptionsBuilder
|
|||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.AUTHENTICATION_ROUTE
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAdventureDetail
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAdventureBooks
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAdventureChapters
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAdventureDetail
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableAuthentication
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableCharacterSheet
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableLanding
|
||||
|
|
@ -23,6 +23,7 @@ import com.pixelized.rplexicon.ui.navigation.screens.composableLocations
|
|||
import com.pixelized.rplexicon.ui.navigation.screens.composableQuestDetail
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableQuests
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableSearch
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableSettings
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableSpellDetail
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.composableSummary
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLanding
|
||||
|
|
@ -66,6 +67,7 @@ fun ScreenNavHost(
|
|||
composableAdventureBooks()
|
||||
composableAdventureChapters()
|
||||
composableAdventureDetail()
|
||||
composableSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.pixelized.rplexicon.ui.navigation.screens
|
||||
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavOptionsBuilder
|
||||
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
|
||||
import com.pixelized.rplexicon.ui.navigation.animatedComposable
|
||||
import com.pixelized.rplexicon.ui.screens.settings.SettingsScreen
|
||||
|
||||
private val ROUTE = "settings"
|
||||
|
||||
val SETTINGS_ROUTE = ROUTE
|
||||
|
||||
fun NavGraphBuilder.composableSettings() {
|
||||
animatedComposable(
|
||||
route = SETTINGS_ROUTE,
|
||||
animation = NavigationAnimation.Push,
|
||||
) {
|
||||
SettingsScreen()
|
||||
}
|
||||
}
|
||||
|
||||
fun NavHostController.navigateToSettings(
|
||||
option: NavOptionsBuilder.() -> Unit = {},
|
||||
) {
|
||||
val route = ROUTE
|
||||
navigate(route = route, builder = option)
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import androidx.compose.runtime.Stable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -52,7 +53,6 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.credentials.exceptions.GetCredentialCancellationException
|
||||
import androidx.credentials.exceptions.GetCredentialProviderConfigurationException
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.LocalActivity
|
||||
import com.pixelized.rplexicon.LocalSnack
|
||||
|
|
@ -61,6 +61,7 @@ import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
|||
import com.pixelized.rplexicon.ui.theme.colors.GoogleColorPalette
|
||||
import com.pixelized.rplexicon.utilitary.sensor.Gyroscope
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.E
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
|
@ -90,6 +91,7 @@ fun AuthenticationScreen(
|
|||
val context = LocalContext.current
|
||||
val snack = LocalSnack.current
|
||||
val activity = LocalActivity.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Surface {
|
||||
PartyBackground()
|
||||
|
|
@ -101,7 +103,9 @@ fun AuthenticationScreen(
|
|||
.padding(all = 16.dp),
|
||||
version = versionVM.version,
|
||||
onGoogleSignIn = {
|
||||
authenticationVM.signIn(activity = activity)
|
||||
scope.launch {
|
||||
authenticationVM.signIn(activity = activity)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -344,7 +348,7 @@ private fun animatedWeight(
|
|||
@Composable
|
||||
private fun rememberBackgroundGradient(): Brush {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
return remember {
|
||||
return remember(colorScheme) {
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
colorScheme.surface.copy(alpha = 0.25f),
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ class AuthenticationViewModel @Inject constructor(
|
|||
AuthenticationStateUio.Initial
|
||||
)
|
||||
|
||||
fun signIn(activity: Activity) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
suspend fun signIn(activity: Activity) {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
// create the credential manager
|
||||
val credentialManager = CredentialManager.create(
|
||||
|
|
@ -101,4 +101,14 @@ class AuthenticationViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun signOut() {
|
||||
withContext(Dispatchers.IO) {
|
||||
Firebase.auth.signOut()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
authenticationState.value = AuthenticationStateUio.Initial
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,7 +58,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import com.pixelized.rplexicon.LocalRollOverlay
|
||||
import com.pixelized.rplexicon.NO_WINDOW_INSETS
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ui.composable.Handle
|
||||
import com.pixelized.rplexicon.ui.composable.KeepOnScreen
|
||||
import com.pixelized.rplexicon.ui.composable.Loader
|
||||
import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ data class LandingItemUio(
|
|||
QUEST,
|
||||
MAP,
|
||||
ADVENTURE,
|
||||
OTHERS,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import com.pixelized.rplexicon.ui.navigation.screens.navigateToLexicon
|
|||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLocation
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToQuestList
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSearch
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSettings
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSummary
|
||||
import com.pixelized.rplexicon.ui.screens.authentication.VersionViewModel
|
||||
import com.pixelized.rplexicon.ui.screens.landing.LandingItemUio.Feature.ADVENTURE
|
||||
|
|
@ -95,6 +96,7 @@ fun LandingScreen(
|
|||
characters = viewModel.characterSheets,
|
||||
tools = viewModel.toolFeatures,
|
||||
encyclopedia = viewModel.lexiconFeatures,
|
||||
others = viewModel.otherFeatures,
|
||||
version = versionVM.version,
|
||||
onFeature = {
|
||||
when (it.feature) {
|
||||
|
|
@ -130,6 +132,10 @@ fun LandingScreen(
|
|||
ADVENTURE -> {
|
||||
screen.navigateToAdventures()
|
||||
}
|
||||
|
||||
LandingItemUio.Feature.OTHERS -> {
|
||||
screen.navigateToSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -150,6 +156,7 @@ private fun LandingContent(
|
|||
characters: State<List<List<LandingItemUio>>>,
|
||||
tools: State<List<List<LandingItemUio>>>,
|
||||
encyclopedia: State<List<List<LandingItemUio>>>,
|
||||
others: State<List<List<LandingItemUio>>>,
|
||||
version: VersionViewModel.Version,
|
||||
onFeature: (LandingItemUio) -> Unit,
|
||||
) {
|
||||
|
|
@ -334,6 +341,44 @@ private fun LandingContent(
|
|||
}
|
||||
}
|
||||
|
||||
if (others.value.isNotEmpty()) {
|
||||
Text(
|
||||
modifier = Modifier.padding(top = sectionPadding),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = stringResource(id = R.string.landing__caterogy__other),
|
||||
)
|
||||
}
|
||||
others.value.forEach { group ->
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||
) {
|
||||
group.forEach { item ->
|
||||
LandingItem(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.aspectRatio(ratio = 1f),
|
||||
imagePadding = PaddingValues(
|
||||
top = 8.dp,
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 24.dp,
|
||||
),
|
||||
item = item,
|
||||
backgroundFilter = null,
|
||||
backgroundGradientFrom = 0.0f,
|
||||
backgroundGradientTo = 0.5f,
|
||||
onClick = { onFeature(item) },
|
||||
)
|
||||
}
|
||||
repeat(3 - group.size) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.End)
|
||||
|
|
@ -383,8 +428,8 @@ private fun Modifier.magic(): Modifier = composed {
|
|||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO, heightDp = 1332)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES, heightDp = 1332)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO, heightDp = 1452)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES, heightDp = 1452)
|
||||
private fun LandingPreview() {
|
||||
LexiconTheme {
|
||||
Surface {
|
||||
|
|
@ -484,6 +529,20 @@ private fun LandingPreview() {
|
|||
),
|
||||
)
|
||||
},
|
||||
others = remember {
|
||||
mutableStateOf(
|
||||
listOf(
|
||||
listOf(
|
||||
LandingItemUio(
|
||||
feature = LandingItemUio.Feature.OTHERS,
|
||||
title = "Settings",
|
||||
subTitle = null,
|
||||
icon = R.drawable.icbg_item_foundry_misc_gear_a,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
version = VersionViewModel.Version(R.string.app_name, "0.0.0", "0", true),
|
||||
onFeature = { },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -137,4 +137,30 @@ class LandingViewModel @Inject constructor(
|
|||
}
|
||||
}.collectAsState(initial = emptyList())
|
||||
}
|
||||
|
||||
val otherFeatures: State<List<List<LandingItemUio>>>
|
||||
@Composable
|
||||
get() {
|
||||
val context = LocalContext.current
|
||||
return remember {
|
||||
configRepository.config
|
||||
.map { config ->
|
||||
listOfNotNull(
|
||||
when (config.featureOther) {
|
||||
true -> LandingItemUio(
|
||||
feature = LandingItemUio.Feature.OTHERS,
|
||||
title = context.getString(R.string.settings__title),
|
||||
subTitle = null,
|
||||
icon = R.drawable.icbg_item_foundry_misc_gear_a,
|
||||
)
|
||||
|
||||
else -> null
|
||||
}
|
||||
)
|
||||
}
|
||||
.map { items ->
|
||||
items.groupBy { items.indexOf(it) / 3 }.values.toList()
|
||||
}
|
||||
}.collectAsState(initial = emptyList())
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import androidx.compose.animation.slideOutVertically
|
|||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -84,6 +85,7 @@ import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
|
|||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
|
||||
import com.pixelized.rplexicon.isInDarkTheme
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -98,6 +100,7 @@ fun RollOverlay(
|
|||
|
||||
RollOverlayContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
isDarkTheme = isInDarkTheme(),
|
||||
drawer = drawer,
|
||||
dice = viewModel.dice,
|
||||
card = viewModel.card,
|
||||
|
|
@ -145,6 +148,7 @@ fun RollOverlay(
|
|||
@Composable
|
||||
private fun RollOverlayContent(
|
||||
modifier: Modifier = Modifier,
|
||||
isDarkTheme: Boolean,
|
||||
drawer: DrawerState,
|
||||
dice: State<RollDiceUio?>,
|
||||
card: State<ThrowsCardUio?>,
|
||||
|
|
@ -321,6 +325,7 @@ private fun RollOverlayContent(
|
|||
modifier = Modifier
|
||||
.padding(bottom = if (enableDrawer.value) 32.dp else 0.dp)
|
||||
.padding(all = 16.dp),
|
||||
isDarkTheme = isDarkTheme,
|
||||
throws = it,
|
||||
showDetail = showDetail,
|
||||
onClick = onCard,
|
||||
|
|
@ -358,6 +363,7 @@ private fun RollOverlayPreview(
|
|||
Surface {
|
||||
RollOverlayContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
isDarkTheme = isSystemInDarkTheme(),
|
||||
drawer = rememberDrawerState(initialValue = preview.drawer),
|
||||
dice = preview.dice,
|
||||
card = preview.card,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import androidx.compose.animation.fadeOut
|
|||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -52,6 +51,7 @@ import com.pixelized.rplexicon.R
|
|||
import com.pixelized.rplexicon.ui.agsl.dancingColor
|
||||
import com.pixelized.rplexicon.ui.agsl.rememberTimeState
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio.Throw.Type
|
||||
import com.pixelized.rplexicon.isInDarkTheme
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
import com.pixelized.rplexicon.utilitary.extentions.annotatedSpan
|
||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||
|
|
@ -98,12 +98,12 @@ data class ThrowsCardUio(
|
|||
@Composable
|
||||
fun ThrowsCard(
|
||||
modifier: Modifier = Modifier,
|
||||
isDarkTheme: Boolean = isInDarkTheme(),
|
||||
throws: ThrowsCardUio,
|
||||
showDetail: State<Boolean>,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val isDarkMode = isSystemInDarkTheme()
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val typography = MaterialTheme.typography
|
||||
val highlight = remember { SpanStyle(color = colorScheme.primary) }
|
||||
|
|
@ -118,10 +118,13 @@ fun ThrowsCard(
|
|||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.ddBorder(inner = inner, outline = remember { CutCornerShape(size = 16.dp) })
|
||||
.ddBorder(
|
||||
inner = inner,
|
||||
outline = remember { CutCornerShape(size = 16.dp) },
|
||||
)
|
||||
.clip(shape = inner)
|
||||
.clickable(onClick = onClick),
|
||||
tonalElevation = if (isDarkMode) 4.dp else 0.dp,
|
||||
tonalElevation = if (isDarkTheme) 4.dp else 0.dp,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
package com.pixelized.rplexicon.ui.screens.settings
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ThemeViewModel
|
||||
import com.pixelized.rplexicon.ui.composable.rememberAnimatedShadow
|
||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||
import com.pixelized.rplexicon.ui.navigation.rootOption
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToAuthentication
|
||||
import com.pixelized.rplexicon.ui.screens.authentication.AuthenticationViewModel
|
||||
import com.pixelized.rplexicon.ui.screens.settings.composable.ButtonPreference
|
||||
import com.pixelized.rplexicon.ui.screens.settings.composable.SwitchPreference
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@Composable
|
||||
fun SettingsScreen(
|
||||
themeViewModel: ThemeViewModel = hiltViewModel(),
|
||||
authenticationViewModel: AuthenticationViewModel = hiltViewModel(),
|
||||
) {
|
||||
val screen = LocalScreenNavHost.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
SettingsContent(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding(),
|
||||
isInDarkTheme = themeViewModel.useDarkTheme.value,
|
||||
onBack = {
|
||||
screen.popBackStack()
|
||||
},
|
||||
onThemeChange = {
|
||||
scope.launch {
|
||||
themeViewModel.updateDarkThemeUsage(useDarkTheme = it)
|
||||
}
|
||||
},
|
||||
onLogout = {
|
||||
scope.launch {
|
||||
authenticationViewModel.signOut()
|
||||
screen.navigateToAuthentication(option = rootOption())
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SettingsContent(
|
||||
modifier: Modifier = Modifier,
|
||||
isInDarkTheme: Boolean,
|
||||
scrollState: ScrollState = rememberScrollState(),
|
||||
onBack: () -> Unit,
|
||||
onThemeChange: (Boolean) -> Unit,
|
||||
onLogout: () -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
val shadow = rememberAnimatedShadow(scrollState = scrollState)
|
||||
TopAppBar(
|
||||
modifier = Modifier.shadow(elevation = shadow.value),
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onBack) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_arrow_back_ios_new_24),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = stringResource(id = R.string.settings__title))
|
||||
},
|
||||
)
|
||||
},
|
||||
content = { paddings ->
|
||||
Surface(
|
||||
modifier = Modifier.verticalScroll(state = scrollState)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(paddingValues = paddings),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
ButtonPreference(
|
||||
title = stringResource(id = R.string.settings__logout__title),
|
||||
description = stringResource(id = R.string.settings__logout__description),
|
||||
action = stringResource(id = R.string.settings__logout__action),
|
||||
onClick = onLogout,
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
|
||||
SwitchPreference(
|
||||
title = stringResource(id = R.string.settings__dark_theme__title),
|
||||
description = stringResource(id = R.string.settings__dark_theme__description),
|
||||
value = isInDarkTheme,
|
||||
onCheckedChange = onThemeChange,
|
||||
)
|
||||
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun SettingsPreview() {
|
||||
LexiconTheme {
|
||||
SettingsContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
isInDarkTheme = false,
|
||||
onBack = {},
|
||||
onThemeChange = {},
|
||||
onLogout = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.pixelized.rplexicon.ui.screens.settings.composable
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
|
||||
@Composable
|
||||
fun ButtonPreference(
|
||||
modifier: Modifier = Modifier,
|
||||
paddingValues: PaddingValues = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 8.dp,
|
||||
top = 8.dp,
|
||||
bottom = 8.dp,
|
||||
),
|
||||
title: String,
|
||||
description: String,
|
||||
action: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(paddingValues = paddingValues)
|
||||
.height(IntrinsicSize.Min)
|
||||
.then(other = modifier),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
text = title
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = description
|
||||
)
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = onClick,
|
||||
) {
|
||||
Text(text = action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun ButtonPreferencePreview() {
|
||||
LexiconTheme {
|
||||
ButtonPreference(
|
||||
title = stringResource(id = R.string.settings__logout__title),
|
||||
description = stringResource(id = R.string.settings__logout__description),
|
||||
action = stringResource(id = R.string.settings__logout__action),
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.pixelized.rplexicon.ui.screens.settings.composable
|
||||
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
|
||||
@Composable
|
||||
fun SwitchPreference(
|
||||
modifier: Modifier = Modifier,
|
||||
paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
|
||||
title: String,
|
||||
description: String,
|
||||
value: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(paddingValues = paddingValues)
|
||||
.height(IntrinsicSize.Min)
|
||||
.then(other = modifier),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
text = title
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = description
|
||||
)
|
||||
}
|
||||
|
||||
Switch(
|
||||
checked = value,
|
||||
onCheckedChange = onCheckedChange
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun TogglePreferencePreview() {
|
||||
LexiconTheme {
|
||||
Surface {
|
||||
SwitchPreference(
|
||||
title = "Title",
|
||||
description = "description",
|
||||
value = true,
|
||||
onCheckedChange = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
|
|
@ -40,12 +41,12 @@ data class LexiconTheme(
|
|||
|
||||
@Composable
|
||||
fun LexiconTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
isDarkTheme: Boolean = isSystemInDarkTheme(),
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val lexiconTheme = remember(density) {
|
||||
val colorScheme = when (darkTheme) {
|
||||
val lexiconTheme = remember(density, isDarkTheme) {
|
||||
val colorScheme = when (isDarkTheme) {
|
||||
true -> darkColorScheme()
|
||||
else -> lightColorScheme()
|
||||
}
|
||||
|
|
@ -58,29 +59,29 @@ fun LexiconTheme(
|
|||
)
|
||||
}
|
||||
|
||||
val view = LocalView.current
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
val window = (view.context as Activity).window
|
||||
window.statusBarColor = lexiconTheme.colorScheme.status.toArgb()
|
||||
window.navigationBarColor = lexiconTheme.colorScheme.navigation.toArgb()
|
||||
WindowCompat.getInsetsController(window, view).let {
|
||||
it.isAppearanceLightStatusBars = !darkTheme
|
||||
it.isAppearanceLightNavigationBars = !darkTheme
|
||||
}
|
||||
}
|
||||
}
|
||||
CompositionLocalProvider(
|
||||
LocalLexiconTheme provides lexiconTheme,
|
||||
) {
|
||||
val theme = LocalLexiconTheme.current
|
||||
val view = LocalView.current
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = lexiconTheme.colorScheme.base,
|
||||
shapes = lexiconTheme.shapes.base,
|
||||
typography = lexiconTheme.typography.base,
|
||||
content = {
|
||||
CompositionLocalProvider(
|
||||
LocalLexiconTheme provides lexiconTheme,
|
||||
) {
|
||||
content()
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
val window = (view.context as Activity).window
|
||||
window.statusBarColor = theme.colorScheme.status.toArgb()
|
||||
window.navigationBarColor = theme.colorScheme.navigation.toArgb()
|
||||
WindowCompat.getInsetsController(window, view).let {
|
||||
it.isAppearanceLightStatusBars = !isDarkTheme
|
||||
it.isAppearanceLightNavigationBars = !isDarkTheme
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = theme.colorScheme.base,
|
||||
typography = theme.typography.base,
|
||||
shapes = theme.shapes.base,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import androidx.compose.foundation.border
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectTransformGestures
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -43,6 +42,7 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.placeholder.PlaceholderHighlight
|
||||
import com.google.accompanist.placeholder.placeholder
|
||||
import com.pixelized.rplexicon.isInDarkTheme
|
||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||
|
||||
fun Modifier.placeholder(
|
||||
|
|
@ -114,7 +114,7 @@ fun Modifier.ddBorder(
|
|||
inner: Shape,
|
||||
innerWidth: Dp = 1.dp,
|
||||
): Modifier = composed {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val isDarkTheme = isInDarkTheme()
|
||||
val elevation = remember { derivedStateOf { if (isDarkTheme) 2.dp else 0.dp } }
|
||||
val colorScheme = MaterialTheme.lexicon.colorScheme
|
||||
this then Modifier
|
||||
|
|
@ -147,7 +147,8 @@ fun Modifier.ddBorder(
|
|||
|
||||
fun Modifier.lexiconShadow(): Modifier {
|
||||
return this then composed {
|
||||
if (isSystemInDarkTheme()) {
|
||||
val isDarkTheme = isInDarkTheme()
|
||||
if (isDarkTheme) {
|
||||
val color = DividerDefaults.color
|
||||
drawWithContent {
|
||||
drawContent()
|
||||
|
|
|
|||
BIN
app/src/main/res/drawable/icbg_item_foundry_misc_gear_a.png
Normal file
BIN
app/src/main/res/drawable/icbg_item_foundry_misc_gear_a.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
|
|
@ -239,6 +239,14 @@
|
|||
<string name="landing__caterogy__character">Feuilles de personnage</string>
|
||||
<string name="landing__caterogy__encyclopedia">Encyclopédie</string>
|
||||
<string name="landing__caterogy__tools">Outils</string>
|
||||
<string name="landing__caterogy__other">Autre</string>
|
||||
|
||||
<string name="adventures_title">Histoires & Péripéties</string>
|
||||
|
||||
<string name="settings__title">Paramêtres</string>
|
||||
<string name="settings__dark_theme__title">Theme sombre</string>
|
||||
<string name="settings__dark_theme__description">Utilise un fond noir pour économiser la batterie.</string>
|
||||
<string name="settings__logout__title">Authentification</string>
|
||||
<string name="settings__logout__description">Déconnectez vous de votre compte google.</string>
|
||||
<string name="settings__logout__action">Se déconnectez</string>
|
||||
</resources>
|
||||
|
|
@ -50,6 +50,7 @@
|
|||
<string name="landing__caterogy__character">Character\'s sheets</string>
|
||||
<string name="landing__caterogy__tools">Tools</string>
|
||||
<string name="landing__caterogy__encyclopedia">Encyclopedia</string>
|
||||
<string name="landing__caterogy__other">Other</string>
|
||||
<string name="landing__character_brulkhai" translatable="false">Brulkhai</string>
|
||||
<string name="landing__character_leandre" translatable="false">Léandre</string>
|
||||
<string name="landing__character_nelia" translatable="false">Nelia</string>
|
||||
|
|
@ -246,4 +247,11 @@
|
|||
<string name="summary__title">Game Master</string>
|
||||
|
||||
<string name="adventures_title">Stories & Adventures</string>
|
||||
|
||||
<string name="settings__title">Settings</string>
|
||||
<string name="settings__dark_theme__title">Dark theme</string>
|
||||
<string name="settings__dark_theme__description">Use black background to save battery.</string>
|
||||
<string name="settings__logout__title">Authentication</string>
|
||||
<string name="settings__logout__description">Logout from your google account.</string>
|
||||
<string name="settings__logout__action">Logout</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue