~repos /only-bible-app

#kotlin#android#ios

git clone https://pyrossh.dev/repos/only-bible-app.git

The only bible app you will ever need. No ads. No in-app purchases. No distractions.


5536ef8c Peter John

1 year ago
fix theming
app/src/main/AndroidManifest.xml CHANGED
@@ -8,11 +8,13 @@
8
8
  android:icon="@mipmap/ic_launcher"
9
9
  android:roundIcon="@mipmap/ic_launcher_round"
10
10
  android:supportsRtl="true"
11
- android:theme="@style/Theme.BibleAppSplashLight"
11
+ android:theme="@style/Theme.BibleAppSplash"
12
12
  >
13
13
  <activity
14
14
  android:name=".MainActivity"
15
- android:exported="true">
15
+ android:exported="true"
16
+ android:configChanges="uiMode"
17
+ android:theme="@style/Theme.BibleAppSplash">
16
18
  <intent-filter>
17
19
  <action android:name="android.intent.action.MAIN" />
18
20
 
app/src/main/java/dev/pyrossh/onlyBible/AppTheme.kt CHANGED
@@ -1,8 +1,9 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
+ import android.content.res.Configuration.UI_MODE_NIGHT_MASK
3
- import android.content.Context
4
+ import android.content.res.Configuration.UI_MODE_NIGHT_NO
5
+ import android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED
4
6
  import androidx.compose.foundation.isSystemInDarkTheme
5
- import androidx.compose.material3.ColorScheme
6
7
  import androidx.compose.material3.MaterialTheme
7
8
  import androidx.compose.material3.dynamicDarkColorScheme
8
9
  import androidx.compose.material3.dynamicLightColorScheme
@@ -29,26 +30,9 @@ enum class FontType {
29
30
  }
30
31
  }
31
32
 
32
- enum class ThemeType {
33
- Light,
34
- Dark,
35
- Auto;
36
- }
37
-
38
- fun getColorScheme(context: Context, themeType: ThemeType, darkTheme: Boolean): ColorScheme {
33
+ fun isLightTheme(uiMode: Int, isSystemDark: Boolean): Boolean {
39
- return when {
34
+ val maskedMode = uiMode and UI_MODE_NIGHT_MASK
40
- themeType == ThemeType.Light || (themeType == ThemeType.Auto && !darkTheme) ->
35
+ return maskedMode == UI_MODE_NIGHT_NO || (maskedMode == UI_MODE_NIGHT_UNDEFINED && !isSystemDark)
41
- dynamicLightColorScheme(context).copy(
42
- outline = Color.LightGray,
43
- )
44
-
45
- else ->
46
- dynamicDarkColorScheme(context).copy(
47
- background = Color(0xFF090F12),
48
- surface = Color(0xFF090F12),
49
- outline = Color(0xAA5D4979),
50
- )
51
- }
52
36
  }
53
37
 
54
38
  @Composable
@@ -57,15 +41,20 @@ fun AppTheme(
57
41
  content: @Composable() () -> Unit
58
42
  ) {
59
43
  val context = LocalContext.current
60
- val darkTheme = isSystemInDarkTheme()
61
44
  val systemUiController = rememberSystemUiController()
62
- val themeType = ThemeType.valueOf(model.themeType)
63
- val colorScheme = getColorScheme(context, themeType, darkTheme)
45
+ val colorScheme = if (isLightTheme(model.uiMode, isSystemInDarkTheme()))
46
+ dynamicLightColorScheme(context).copy(
47
+ onSurface = Color.Black,
48
+ outline = Color.LightGray,
49
+ )
50
+ else
51
+ dynamicDarkColorScheme(context).copy(
52
+ background = Color(0xFF090F12),
53
+ surface = Color(0xFF090F12),
54
+ outline = Color(0xAA5D4979),
55
+ )
56
+ println("AppTheme ${model.uiMode}")
64
- LaunchedEffect(key1 = model.themeType) {
57
+ LaunchedEffect(key1 = model.uiMode) {
65
- // val view = LocalView.current
66
- // val window = (view.context as Activity).window
67
- // window.statusBarColor = colorScheme.primary.toArgb()
68
- // WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
69
58
  systemUiController.setSystemBarsColor(
70
59
  color = colorScheme.background
71
60
  )
app/src/main/java/dev/pyrossh/onlyBible/AppViewModel.kt CHANGED
@@ -1,11 +1,14 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
3
  import android.app.Application
4
+ import android.app.UiModeManager
4
5
  import android.content.Context
5
6
  import android.content.Intent
7
+ import android.content.res.Configuration
6
8
  import androidx.compose.foundation.lazy.LazyListState
7
9
  import androidx.compose.runtime.MutableState
8
10
  import androidx.compose.runtime.getValue
11
+ import androidx.compose.runtime.mutableIntStateOf
9
12
  import androidx.compose.runtime.mutableStateOf
10
13
  import androidx.compose.runtime.setValue
11
14
  import androidx.datastore.preferences.core.Preferences
@@ -73,14 +76,7 @@ class AppViewModel(application: Application) : AndroidViewModel(application) {
73
76
  0,
74
77
  0
75
78
  )
76
- var themeType by preferenceMutableState(
79
+ var uiMode by mutableIntStateOf(Configuration.UI_MODE_NIGHT_NO)
77
- coroutineScope = viewModelScope,
78
- context = context,
79
- keyName = "themeType",
80
- initialValue = ThemeType.Auto.name,
81
- defaultValue = ThemeType.Auto.name,
82
- getPreferencesKey = ::stringPreferencesKey,
83
- )
84
80
  var fontType by preferenceMutableState(
85
81
  coroutineScope = viewModelScope,
86
82
  context = context,
@@ -106,10 +102,6 @@ class AppViewModel(application: Application) : AndroidViewModel(application) {
106
102
  getPreferencesKey = ::booleanPreferencesKey,
107
103
  )
108
104
 
109
- fun isDarkTheme(isSystemDark: Boolean): Boolean {
110
- val themeType = ThemeType.valueOf(themeType)
111
- return themeType == ThemeType.Dark || (themeType == ThemeType.Auto && isSystemDark)
112
- }
113
105
 
114
106
  fun showSheet() {
115
107
  showBottomSheet = true
@@ -125,6 +117,7 @@ class AppViewModel(application: Application) : AndroidViewModel(application) {
125
117
  }
126
118
 
127
119
  fun initData(p: Preferences) {
120
+ uiMode = context.applicationContext.resources.configuration.uiMode
128
121
  bibleName = p[stringPreferencesKey("bibleName")] ?: "English"
129
122
  scrollState = LazyListState(
130
123
  p[intPreferencesKey("scrollIndex")] ?: 0,
app/src/main/java/dev/pyrossh/onlyBible/ChapterScreen.kt CHANGED
@@ -148,7 +148,7 @@ fun ChapterScreen(
148
148
  openDrawer: (MenuType, Int) -> Job,
149
149
  ) {
150
150
  val context = LocalContext.current
151
- val darkTheme = model.isDarkTheme(isSystemInDarkTheme())
151
+ val isLight = isLightTheme(model.uiMode, isSystemInDarkTheme())
152
152
  val fontType = FontType.valueOf(model.fontType)
153
153
  val fontSizeDelta = model.fontSizeDelta
154
154
  val boldWeight = if (model.fontBoldEnabled) FontWeight.W700 else FontWeight.W400
@@ -245,12 +245,15 @@ fun ChapterScreen(
245
245
  },
246
246
  bottomBar = {
247
247
  val bottomOffset = WindowInsets.navigationBars.getBottom(LocalDensity.current)
248
+ val bottomPadding =
248
- val bottomPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
249
+ WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
249
250
  AnimatedVisibility(
251
+ modifier = Modifier
252
+ .height(104.dp)
250
- modifier = Modifier.height(104.dp).padding(bottom = bottomPadding),
253
+ .padding(bottom = bottomPadding),
251
254
  visible = selectedVerses.isNotEmpty(),
252
- enter = slideInVertically(initialOffsetY = { it/2 + bottomOffset }),
255
+ enter = slideInVertically(initialOffsetY = { it / 2 + bottomOffset }),
253
- exit = slideOutVertically(targetOffsetY = { it/2 + bottomOffset }),
256
+ exit = slideOutVertically(targetOffsetY = { it / 2 + bottomOffset }),
254
257
  ) {
255
258
  Surface(
256
259
  modifier = Modifier,
@@ -373,10 +376,10 @@ fun ChapterScreen(
373
376
  else
374
377
  Color.Unspecified,
375
378
  fontFamily = fontType.family(),
376
- color = if (darkTheme)
379
+ color = if (isLight)
377
- Color(0xFFBCBCBC)
380
+ Color(0xFF000104)
378
381
  else
379
- Color(0xFF000104),
382
+ Color(0xFFBCBCBC),
380
383
  fontWeight = boldWeight,
381
384
  fontSize = (17 + fontSizeDelta).sp,
382
385
  lineHeight = (23 + fontSizeDelta).sp,
@@ -389,9 +392,10 @@ fun ChapterScreen(
389
392
  withStyle(
390
393
  style = SpanStyle(
391
394
  fontSize = (13 + fontSizeDelta).sp,
392
- color = if (darkTheme)
395
+ color = if (isLight)
396
+ Color(0xFFA20101)
397
+ else
393
- Color(0xFFCCCCCC)
398
+ Color(0xFFCCCCCC),
394
- else Color(0xFFA20101),
395
399
  fontWeight = FontWeight.W700,
396
400
  )
397
401
  ) {
@@ -405,8 +409,8 @@ fun ChapterScreen(
405
409
  val end = spanned.getSpanEnd(span)
406
410
  when (span) {
407
411
  is ForegroundColorSpan ->
408
- if (darkTheme) SpanStyle(color = Color(0xFFFF636B))
412
+ if (isLight) SpanStyle(color = Color(0xFFFF0000))
409
- else SpanStyle(color = Color(0xFFFF0000))
413
+ else SpanStyle(color = Color(0xFFFF636B))
410
414
 
411
415
  is StyleSpan -> when (span.style) {
412
416
  Typeface.BOLD -> SpanStyle(fontWeight = FontWeight.Bold)
app/src/main/java/dev/pyrossh/onlyBible/MainActivity.kt CHANGED
@@ -1,7 +1,6 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
3
  import android.animation.ObjectAnimator
4
- import android.content.res.Configuration
5
4
  import android.os.Bundle
6
5
  import android.view.View
7
6
  import android.view.animation.AccelerateInterpolator
@@ -22,12 +21,6 @@ class MainActivity : ComponentActivity() {
22
21
  private val model by viewModels<AppViewModel>()
23
22
 
24
23
  override fun onCreate(savedInstanceState: Bundle?) {
25
- val isSystemDark = applicationContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
26
- // if (isSystemDark) {
27
- // setTheme(R.style.Theme_BibleAppSplashDark)
28
- // } else {
29
- // setTheme(R.style.Theme_BibleAppSplashLight)
30
- // }
31
24
  val splashScreen = installSplashScreen()
32
25
  super.onCreate(savedInstanceState)
33
26
  enableEdgeToEdge()
@@ -54,6 +47,9 @@ class MainActivity : ComponentActivity() {
54
47
  start()
55
48
  }
56
49
  }
50
+ addOnConfigurationChangedListener {
51
+ model.uiMode = it.uiMode
52
+ }
57
53
  setContent {
58
54
  AppTheme {
59
55
  AppHost()
app/src/main/java/dev/pyrossh/onlyBible/TextSettingsBottomSheet.kt CHANGED
@@ -1,5 +1,11 @@
1
1
  package dev.pyrossh.onlyBible
2
2
 
3
+ import android.app.UiModeManager
4
+ import android.content.Context.UI_MODE_SERVICE
5
+ import android.content.res.Configuration
6
+ import android.content.res.Configuration.UI_MODE_NIGHT_NO
7
+ import android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED
8
+ import android.content.res.Configuration.UI_MODE_NIGHT_YES
3
9
  import androidx.compose.foundation.BorderStroke
4
10
  import androidx.compose.foundation.background
5
11
  import androidx.compose.foundation.layout.Arrangement
@@ -31,21 +37,20 @@ import androidx.compose.runtime.Composable
31
37
  import androidx.compose.runtime.rememberCoroutineScope
32
38
  import androidx.compose.ui.Alignment
33
39
  import androidx.compose.ui.Modifier
40
+ import androidx.compose.ui.platform.LocalContext
34
41
  import androidx.compose.ui.text.TextStyle
35
42
  import androidx.compose.ui.text.font.FontWeight
36
43
  import androidx.compose.ui.unit.dp
37
44
  import androidx.compose.ui.unit.sp
38
- import dev.pyrossh.onlyBible.ThemeType.Auto
39
- import dev.pyrossh.onlyBible.ThemeType.Dark
40
- import dev.pyrossh.onlyBible.ThemeType.Light
41
45
  import kotlinx.coroutines.launch
42
46
 
43
47
  @Composable
44
48
  @OptIn(ExperimentalMaterial3Api::class)
45
49
  fun TextSettingsBottomSheet(model: AppViewModel) {
50
+ val uiModeManager = LocalContext.current.getSystemService(UI_MODE_SERVICE) as UiModeManager
51
+ val uiMode = model.uiMode and Configuration.UI_MODE_NIGHT_MASK
46
52
  val scope = rememberCoroutineScope()
47
53
  val sheetState = rememberModalBottomSheetState()
48
- val themeType = ThemeType.valueOf(model.themeType)
49
54
  val fontType = FontType.valueOf(model.fontType)
50
55
  return ModalBottomSheet(
51
56
  tonalElevation = 2.dp,
@@ -228,17 +233,17 @@ fun TextSettingsBottomSheet(model: AppViewModel) {
228
233
  horizontalArrangement = Arrangement.SpaceBetween,
229
234
  verticalAlignment = Alignment.CenterVertically,
230
235
  ) {
231
- ThemeType.entries.map {
236
+ listOf(UI_MODE_NIGHT_NO, UI_MODE_NIGHT_YES, UI_MODE_NIGHT_UNDEFINED).map {
232
237
  Surface(
233
238
  shape = RoundedCornerShape(8.dp),
234
- border = if (themeType == it) BorderStroke(
239
+ border = if (uiMode == it) BorderStroke(
235
240
  2.dp, MaterialTheme.colorScheme.primary
236
241
  ) else null,
237
- color = if (themeType == it)
242
+ color = if (uiMode == it)
238
243
  MaterialTheme.colorScheme.primary
239
244
  else
240
245
  MaterialTheme.colorScheme.onSurface,
241
- contentColor = if (themeType == it)
246
+ contentColor = if (uiMode == it)
242
247
  MaterialTheme.colorScheme.primary
243
248
  else
244
249
  MaterialTheme.colorScheme.onSurface,
@@ -251,12 +256,24 @@ fun TextSettingsBottomSheet(model: AppViewModel) {
251
256
  scope.launch {
252
257
  sheetState.hide()
253
258
  model.closeSheet()
259
+ when (it) {
260
+ UI_MODE_NIGHT_NO -> uiModeManager.setApplicationNightMode(
261
+ UiModeManager.MODE_NIGHT_NO
262
+ )
263
+
264
+ UI_MODE_NIGHT_YES -> uiModeManager.setApplicationNightMode(
254
- model.themeType = it.name
265
+ UiModeManager.MODE_NIGHT_YES
266
+ )
267
+
268
+ UI_MODE_NIGHT_UNDEFINED -> uiModeManager.setApplicationNightMode(
269
+ UiModeManager.MODE_NIGHT_AUTO
270
+ )
271
+ }
255
272
  }
256
273
  }
257
274
  ) {
258
275
  when (it) {
259
- Light -> Icon(
276
+ UI_MODE_NIGHT_NO -> Icon(
260
277
  imageVector = Icons.Filled.LightMode,
261
278
  contentDescription = "Light",
262
279
  modifier = Modifier
@@ -264,7 +281,7 @@ fun TextSettingsBottomSheet(model: AppViewModel) {
264
281
  .padding(12.dp)
265
282
  )
266
283
 
267
- Dark -> Icon(
284
+ UI_MODE_NIGHT_YES -> Icon(
268
285
  imageVector = Icons.Filled.DarkMode,
269
286
  contentDescription = "Dark",
270
287
  modifier = Modifier
@@ -272,7 +289,7 @@ fun TextSettingsBottomSheet(model: AppViewModel) {
272
289
  .padding(12.dp)
273
290
  )
274
291
 
275
- Auto -> Column(
292
+ UI_MODE_NIGHT_UNDEFINED -> Column(
276
293
  modifier = Modifier.background(
277
294
  color = MaterialTheme.colorScheme.background,
278
295
  ),
app/src/main/res/values-night/colors.xml ADDED
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <color name="splash_bg">#00000000</color>
4
+ </resources>
app/src/main/res/values/colors.xml CHANGED
@@ -1,10 +1,4 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <resources>
3
- <color name="purple_200">#FFBB86FC</color>
4
- <color name="purple_500">#FF6200EE</color>
5
- <color name="purple_700">#FF3700B3</color>
6
- <color name="teal_200">#FF03DAC5</color>
7
- <color name="teal_700">#FF018786</color>
8
- <color name="black">#FF000000</color>
9
- <color name="white">#FFFFFFFF</color>
3
+ <color name="splash_bg">#FFFFFFFF</color>
10
4
  </resources>
app/src/main/res/values/themes.xml CHANGED
@@ -1,18 +1,9 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <resources>
3
- <style name="Theme.BibleAppSplashLight" parent="Theme.SplashScreen">
3
+ <style name="Theme.BibleAppSplash" parent="Theme.SplashScreen">
4
4
  <item name="windowSplashScreenAnimatedIcon">@drawable/anim_icon</item>
5
- <item name="windowSplashScreenBackground">#FFFFFF</item>
5
+ <item name="windowSplashScreenBackground">@color/splash_bg</item>
6
- <item name="postSplashScreenTheme">@style/Theme.MaterialComponents.Light.NoActionBar</item>
6
+ <item name="postSplashScreenTheme">@style/Theme.BibleApp</item>
7
- <item name="windowActionBar">false</item>
8
- <item name="windowNoTitle">true</item>
9
7
  </style>
10
- <style name="Theme.BibleAppSplashDark" parent="Theme.SplashScreen">
11
- <item name="windowSplashScreenAnimatedIcon">@drawable/anim_icon</item>
12
- <item name="windowSplashScreenBackground">#000000</item>
13
- <item name="postSplashScreenTheme">@style/Theme.AppCompat.DayNight.DarkActionBar</item>
14
- <item name="windowActionBar">false</item>
15
- <item name="windowNoTitle">true</item>
16
- </style>
17
- <style name="Theme.BibleApp" parent="android:Theme.Material.Light.NoActionBar" />
8
+ <style name="Theme.BibleApp" parent="Theme.MaterialComponents.DayNight.NoActionBar" />
18
9
  </resources>