Skip to content

Commit d4a3faa

Browse files
authored
Merge pull request #582 from namehillsoftware/feature/add-theme-options
[Feature] Add Theme Options
2 parents fe9c9b0 + b8d6c01 commit d4a3faa

34 files changed

+1126
-590
lines changed

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/ActivityDependencies.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import com.lasthopesoftware.bluewater.client.stored.library.items.StateChangeBro
1818
import com.lasthopesoftware.bluewater.client.stored.library.items.files.StoredFileAccess
1919
import com.lasthopesoftware.bluewater.settings.ApplicationSettingsViewModel
2020
import com.lasthopesoftware.bluewater.settings.hidden.HiddenSettingsViewModel
21-
import com.lasthopesoftware.bluewater.settings.repository.access.CachingApplicationSettingsRepository.Companion.getApplicationSettingsRepository
2221
import com.lasthopesoftware.bluewater.shared.android.messages.ViewModelMessageBus
2322
import com.lasthopesoftware.bluewater.shared.android.viewmodels.buildViewModelLazily
2423
import com.lasthopesoftware.bluewater.shared.messages.application.ApplicationMessageBus
@@ -39,7 +38,7 @@ class ActivityDependencies(
3938

4039
private val selectedPlaybackEngineTypeAccess by lazy {
4140
SelectedPlaybackEngineTypeAccess(
42-
applicationSettingsRepository,
41+
applicationSettings,
4342
DefaultPlaybackEngineLookup
4443
)
4544
}
@@ -48,7 +47,7 @@ class ActivityDependencies(
4847

4948
private val libraryBrowserSelection by lazy {
5049
BrowserLibrarySelection(
51-
applicationSettingsRepository,
50+
applicationSettings,
5251
messageBus,
5352
libraryProvider,
5453
)
@@ -97,7 +96,12 @@ class ActivityDependencies(
9796

9897
override val navigationMessages by activity.buildViewModelLazily { ViewModelMessageBus<NavigationMessage>() }
9998

100-
override val applicationSettingsRepository by lazy { applicationContext.getApplicationSettingsRepository() }
99+
override val applicationViewModel by activity.buildViewModelLazily {
100+
ApplicationViewModel(
101+
applicationSettings,
102+
messageBus,
103+
)
104+
}
101105

102106
override val selectedLibraryViewModel: SelectedLibraryViewModel by activity.buildViewModelLazily {
103107
SelectedLibraryViewModel(
@@ -115,7 +119,7 @@ class ActivityDependencies(
115119

116120
override val applicationSettingsViewModel by activity.buildViewModelLazily {
117121
ApplicationSettingsViewModel(
118-
applicationSettingsRepository,
122+
applicationSettings,
119123
selectedPlaybackEngineTypeAccess,
120124
librarySettingsProvider,
121125
libraryNameLookup,
@@ -125,7 +129,7 @@ class ActivityDependencies(
125129
}
126130

127131
override val hiddenSettingsViewModel by activity.buildViewModelLazily {
128-
HiddenSettingsViewModel(applicationSettingsRepository)
132+
HiddenSettingsViewModel(applicationSettings)
129133
}
130134

131135
override val userSslCertificateProvider by lazy {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.lasthopesoftware.bluewater
2+
3+
import androidx.lifecycle.ViewModel
4+
import com.lasthopesoftware.bluewater.settings.ApplicationSettingsUpdated
5+
import com.lasthopesoftware.bluewater.settings.repository.ApplicationSettings
6+
import com.lasthopesoftware.bluewater.settings.repository.access.HoldApplicationSettings
7+
import com.lasthopesoftware.bluewater.shared.messages.application.RegisterForApplicationMessages
8+
import com.lasthopesoftware.bluewater.shared.messages.registerReceiver
9+
import com.lasthopesoftware.bluewater.shared.observables.MutableInteractionState
10+
import com.namehillsoftware.handoff.promises.Promise
11+
12+
class ApplicationViewModel(
13+
private val applicationSettingsRepository: HoldApplicationSettings,
14+
messageBus: RegisterForApplicationMessages,
15+
) : ViewModel() {
16+
17+
init {
18+
addCloseable(messageBus.registerReceiver { _: ApplicationSettingsUpdated ->
19+
loadSettings()
20+
})
21+
}
22+
23+
private val mutableTheme = MutableInteractionState(ApplicationSettings.Theme.SYSTEM)
24+
val theme = mutableTheme.asInteractionState()
25+
26+
fun loadSettings(): Promise<*> =
27+
applicationSettingsRepository
28+
.promiseApplicationSettings()
29+
.then { settings ->
30+
mutableTheme.value = settings.theme ?: ApplicationSettings.Theme.SYSTEM
31+
}
32+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.lasthopesoftware.bluewater
2+
3+
import com.lasthopesoftware.bluewater.settings.repository.access.TvApplicationSettingsRepository
4+
5+
class TvApplicationDependencies(
6+
private val dependencies: ApplicationDependencies
7+
) : ApplicationDependencies by dependencies {
8+
override val applicationSettings by lazy {
9+
TvApplicationSettingsRepository(dependencies.applicationSettings)
10+
}
11+
}

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/android/ui/components/LabeledSelection.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.padding
55
import androidx.compose.foundation.selection.selectable
66
import androidx.compose.material.Text
77
import androidx.compose.runtime.Composable
8+
import androidx.compose.ui.Alignment
89
import androidx.compose.ui.Modifier
910
import androidx.compose.ui.semantics.Role
1011
import com.lasthopesoftware.bluewater.android.ui.theme.Dimensions
@@ -14,9 +15,10 @@ fun LabeledSelection(
1415
label: String,
1516
selected: Boolean,
1617
onSelected: () -> Unit,
18+
selectableContent: @Composable () -> Unit,
19+
modifier: Modifier = Modifier,
1720
role: Role? = null,
1821
enabled: Boolean = true,
19-
selectableContent: @Composable () -> Unit,
2022
) {
2123
Row(
2224
modifier = Modifier
@@ -25,7 +27,9 @@ fun LabeledSelection(
2527
onClick = onSelected,
2628
enabled = enabled,
2729
role = role,
28-
),
30+
)
31+
.then(modifier),
32+
verticalAlignment = Alignment.CenterVertically,
2933
) {
3034
selectableContent()
3135

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/android/ui/theme/Color.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ object SharedColors {
1313

1414
object Light {
1515
val ProjectBlue = Color(0xFF97ACEC)
16-
val ProjectBlueLight = Color(0xFFCADEFF)
17-
val ProjectBlueDark = Color(0xFF667DB9)
16+
val ProjectBlueLight = Color(0xFFabbcef)
17+
val ProjectBlueDark = Color(0xFF6978a5)
1818
}
1919

2020
object Dark {
2121
val ProjectBlue = Color(0xFF303F9F)
22-
val ProjectBlueLight = Color(0xFF666AD1)
23-
val ProjectBlueDark = Color(0xFF001970)
22+
val ProjectBlueLight = Color(0xFF5965b2)
23+
val ProjectBlueDark = Color(0xFF212c6f)
2424
}

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/android/ui/theme/Theme.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import androidx.compose.runtime.Composable
88
import androidx.compose.ui.graphics.Color
99

1010
private val DarkColorPalette = darkColors(
11-
primary = Dark.ProjectBlue,
11+
primary = Dark.ProjectBlueLight,
1212
onPrimary = Color.White,
13-
primaryVariant = Dark.ProjectBlueLight,
14-
secondary = Dark.ProjectBlueDark,
13+
primaryVariant = Dark.ProjectBlueDark,
14+
secondary = Dark.ProjectBlue,
1515
onSecondary = Color.White,
1616
onError = Color.White,
1717
)

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/EntryActivity.kt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import androidx.activity.compose.setContent
77
import androidx.activity.enableEdgeToEdge
88
import androidx.appcompat.app.AppCompatActivity
99
import androidx.appcompat.app.AppCompatDelegate
10+
import androidx.compose.foundation.isSystemInDarkTheme
11+
import androidx.compose.runtime.getValue
1012
import androidx.core.app.ActivityCompat
1113
import androidx.core.view.WindowCompat
1214
import com.lasthopesoftware.bluewater.ActivityDependencies
1315
import com.lasthopesoftware.bluewater.ApplicationDependenciesContainer.applicationDependencies
16+
import com.lasthopesoftware.bluewater.TvApplicationDependencies
1417
import com.lasthopesoftware.bluewater.android.intents.safelyGetParcelableExtra
1518
import com.lasthopesoftware.bluewater.android.ui.ProjectBlueComposableApplication
1619
import com.lasthopesoftware.bluewater.client.browsing.navigation.Destination
@@ -19,11 +22,13 @@ import com.lasthopesoftware.bluewater.client.playback.nowplaying.view.NowPlaying
1922
import com.lasthopesoftware.bluewater.client.settings.PermissionsDependencies
2023
import com.lasthopesoftware.bluewater.permissions.ApplicationPermissionsRequests
2124
import com.lasthopesoftware.bluewater.permissions.read.ApplicationReadPermissionsRequirementsProvider
25+
import com.lasthopesoftware.bluewater.settings.repository.ApplicationSettings
2226
import com.lasthopesoftware.bluewater.shared.MagicPropertyBuilder
2327
import com.lasthopesoftware.bluewater.shared.android.permissions.ManagePermissions
2428
import com.lasthopesoftware.bluewater.shared.android.permissions.OsPermissionsChecker
2529
import com.lasthopesoftware.bluewater.shared.cls
2630
import com.lasthopesoftware.bluewater.shared.lazyLogger
31+
import com.lasthopesoftware.bluewater.shared.observables.subscribeAsState
2732
import com.lasthopesoftware.promises.extensions.registerResultActivityLauncher
2833
import com.namehillsoftware.handoff.Messenger
2934
import com.namehillsoftware.handoff.promises.Promise
@@ -42,7 +47,17 @@ class EntryActivity :
4247
PermissionsDependencies,
4348
ActivitySuppliedDependencies
4449
{
45-
private val browserViewDependencies by lazy { ActivityDependencies(this, this, applicationDependencies) }
50+
private val activityApplicationDependencies by lazy {
51+
if (!isInLeanbackMode) applicationDependencies
52+
else TvApplicationDependencies(applicationDependencies)
53+
}
54+
private val browserViewDependencies by lazy {
55+
ActivityDependencies(
56+
this,
57+
this,
58+
activityApplicationDependencies
59+
)
60+
}
4661

4762
override val registeredActivityResultsLauncher = registerResultActivityLauncher()
4863

@@ -84,8 +99,13 @@ class EntryActivity :
8499
enableEdgeToEdge()
85100

86101
setContent {
102+
val theme by browserViewDependencies.applicationViewModel.run {
103+
loadSettings()
104+
theme.subscribeAsState()
105+
}
106+
val isDarkTheme = theme == ApplicationSettings.Theme.DARK || (theme == ApplicationSettings.Theme.SYSTEM && isSystemInDarkTheme())
87107
if (!isInLeanbackMode) {
88-
ProjectBlueComposableApplication {
108+
ProjectBlueComposableApplication(darkTheme = isDarkTheme) {
89109
HandheldApplication(
90110
entryDependencies = browserViewDependencies,
91111
permissionsDependencies = this,
@@ -94,7 +114,7 @@ class EntryActivity :
94114
}
95115
} else {
96116
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
97-
ProjectBlueComposableApplication(darkTheme = true) {
117+
ProjectBlueComposableApplication(darkTheme = isDarkTheme) {
98118
NowPlayingTvApplication(
99119
entryDependencies = browserViewDependencies,
100120
permissionsDependencies = this,

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/HandheldApplication.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ fun HandheldApplication(
379379
LaunchedEffect(key1 = Unit) {
380380
try {
381381
val settings =
382-
applicationSettingsRepository.promiseApplicationSettings().suspend()
382+
applicationSettings.promiseApplicationSettings().suspend()
383383
if (settings.chosenLibraryId > -1) {
384384
val libraryId = LibraryId(settings.chosenLibraryId)
385385
applicationNavigation.viewLibrary(libraryId).suspend()
@@ -399,7 +399,7 @@ fun HandheldApplication(
399399
LaunchedEffect(key1 = Unit) {
400400
try {
401401
val settings =
402-
applicationSettingsRepository.promiseApplicationSettings().suspend()
402+
applicationSettings.promiseApplicationSettings().suspend()
403403
if (settings.chosenLibraryId > -1) {
404404
val libraryId = LibraryId(settings.chosenLibraryId)
405405
applicationNavigation.viewLibrary(libraryId).suspend()

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/EntryDependencies.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.lasthopesoftware.bluewater.client.browsing
33
import androidx.activity.compose.BackHandler
44
import androidx.compose.runtime.Composable
55
import com.lasthopesoftware.bluewater.ApplicationDependencies
6+
import com.lasthopesoftware.bluewater.ApplicationViewModel
67
import com.lasthopesoftware.bluewater.NavigateApplication
78
import com.lasthopesoftware.bluewater.client.browsing.items.list.ReusableChildItemViewModelProvider
89
import com.lasthopesoftware.bluewater.client.browsing.items.list.menus.changes.ItemListMenuMessage
@@ -14,19 +15,18 @@ import com.lasthopesoftware.bluewater.client.connection.trust.ProvideUserSslCert
1415
import com.lasthopesoftware.bluewater.client.stored.library.items.files.StoredFileAccess
1516
import com.lasthopesoftware.bluewater.settings.ApplicationSettingsViewModel
1617
import com.lasthopesoftware.bluewater.settings.hidden.HiddenSettingsViewModel
17-
import com.lasthopesoftware.bluewater.settings.repository.access.HoldApplicationSettings
1818
import com.lasthopesoftware.bluewater.shared.android.messages.ViewModelMessageBus
1919
import com.lasthopesoftware.bluewater.shared.messages.RegisterForTypedMessages
2020

2121
interface EntryDependencies : ApplicationDependencies {
22+
val applicationViewModel: ApplicationViewModel
2223
val selectedLibraryViewModel: SelectedLibraryViewModel
2324
val libraryRemoval: RemoveLibraries
2425
val menuMessageBus: ViewModelMessageBus<ItemListMenuMessage>
2526
val itemListMenuBackPressedHandler: ItemListMenuBackPressedHandler
2627
val applicationNavigation: NavigateApplication
2728
val storedFileAccess: StoredFileAccess
2829
val navigationMessages: RegisterForTypedMessages<NavigationMessage>
29-
val applicationSettingsRepository: HoldApplicationSettings
3030
val reusableChildItemViewModelProvider: ReusableChildItemViewModelProvider
3131
val applicationSettingsViewModel: ApplicationSettingsViewModel
3232
val hiddenSettingsViewModel: HiddenSettingsViewModel

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/browsing/library/access/session/CachedSelectedLibraryIdProvider.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.lasthopesoftware.bluewater.client.browsing.library.access.session
22

3-
import android.content.Context
43
import com.lasthopesoftware.bluewater.client.browsing.library.repository.LibraryId
5-
import com.lasthopesoftware.bluewater.settings.repository.access.CachingApplicationSettingsRepository.Companion.getApplicationSettingsRepository
64
import com.lasthopesoftware.bluewater.shared.messages.application.ApplicationMessageBus
75
import com.lasthopesoftware.bluewater.shared.messages.registerReceiver
86
import com.lasthopesoftware.promises.extensions.toPromise
@@ -14,13 +12,6 @@ class CachedSelectedLibraryIdProvider(
1412
private val selectedLibraryIdCache: HoldSelectedLibraryId = SelectedLibraryIdCache
1513
) : ProvideSelectedLibraryId
1614
{
17-
companion object {
18-
fun Context.getCachedSelectedLibraryIdProvider() = CachedSelectedLibraryIdProvider(
19-
SelectedLibraryIdProvider(getApplicationSettingsRepository()),
20-
SelectedLibraryIdCache
21-
)
22-
}
23-
2415
private object SelectedLibraryIdCache : HoldSelectedLibraryId, (BrowserLibrarySelection.LibraryChosenMessage) -> Unit {
2516
private val cachedPromisedLibrary = AtomicReference<Promise<LibraryId?>?>(null)
2617

0 commit comments

Comments
 (0)