Skip to content

Commit bd10851

Browse files
committed
Add developer option to always show update alert
Introduces a new developer setting 'Always Show Update Alert' with supporting UI, ViewModel, and datastore logic. Refactors Alert and Card components to support outside content padding and onClick handlers. Cleans up developerMode extension functions and updates usages to support the new setting.
1 parent 14e1bd2 commit bd10851

File tree

10 files changed

+81
-61
lines changed

10 files changed

+81
-61
lines changed

app/src/main/kotlin/com/dergoogler/mmrl/ui/screens/home/HomeScreen.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ import com.dergoogler.mmrl.ext.managerVersion
4848
import com.dergoogler.mmrl.ext.navigateSingleTopTo
4949
import com.dergoogler.mmrl.ext.none
5050
import com.dergoogler.mmrl.ext.nullable
51-
import com.dergoogler.mmrl.ext.onClick
5251
import com.dergoogler.mmrl.ext.takeTrue
5352
import com.dergoogler.mmrl.model.online.Changelog
5453
import com.dergoogler.mmrl.network.runRequest
@@ -162,17 +161,16 @@ fun HomeScreen(
162161
}
163162

164163
AnimatedVisibility(
165-
visible = if (latest.preRelease) {
164+
visible = userPreferences.developerMode { devAlwaysShowUpdateAlert } || (if (latest.preRelease) {
166165
userPreferences.checkAppUpdatesPreReleases && latest.versionCode > context.managerVersion.second
167166
} else {
168167
latest.versionCode > context.managerVersion.second
169-
},
168+
}),
170169
enter = fadeIn() + expandVertically(),
171170
exit = shrinkVertically() + fadeOut()
172171
) {
173-
174172
Alert(
175-
modifier = Modifier.onClick {
173+
onClick = {
176174
changelogSheet = true
177175
},
178176
backgroundColor = MaterialTheme.colorScheme.tertiaryContainer,

app/src/main/kotlin/com/dergoogler/mmrl/ui/screens/repositories/screens/view/NewViewScreen.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,8 @@ fun NewViewScreen(
613613
)
614614
}
615615

616+
val alertPadding = PaddingValues(horizontal = 16.dp)
617+
616618
module.hasBlacklist {
617619
var open by remember { mutableStateOf(false) }
618620
if (open) {
@@ -627,7 +629,7 @@ fun NewViewScreen(
627629
backgroundColor = MaterialTheme.colorScheme.errorContainer,
628630
textColor = MaterialTheme.colorScheme.onErrorContainer,
629631
message = stringResource(R.string.blacklisted_desc),
630-
modifier = Modifier.padding(horizontal = 16.dp),
632+
outsideContentPadding = alertPadding,
631633
)
632634
}
633635

@@ -638,15 +640,15 @@ fun NewViewScreen(
638640
backgroundColor = MaterialTheme.colorScheme.errorContainer,
639641
textColor = MaterialTheme.colorScheme.onErrorContainer,
640642
message = stringResource(id = R.string.view_module_unsupported_desc),
641-
modifier = Modifier.padding(horizontal = 16.dp)
643+
outsideContentPadding = alertPadding,
642644
)
643645
} else {
644646
Alert(
645647
title = stringResource(id = R.string.view_module_low_root_version),
646648
backgroundColor = MaterialTheme.colorScheme.tertiaryContainer,
647649
textColor = MaterialTheme.colorScheme.onTertiaryContainer,
648650
message = stringResource(id = R.string.view_module_low_root_version_desc),
649-
modifier = Modifier.padding(horizontal = 16.dp)
651+
outsideContentPadding = alertPadding,
650652
)
651653
}
652654

@@ -659,7 +661,7 @@ fun NewViewScreen(
659661
backgroundColor = MaterialTheme.colorScheme.errorContainer,
660662
textColor = MaterialTheme.colorScheme.onErrorContainer,
661663
message = stringResource(id = R.string.view_module_unsupported_device_desc),
662-
modifier = Modifier.padding(horizontal = 16.dp)
664+
outsideContentPadding = alertPadding,
663665
)
664666

665667
Spacer(modifier = Modifier.height(16.dp))
@@ -671,7 +673,7 @@ fun NewViewScreen(
671673
backgroundColor = MaterialTheme.colorScheme.errorContainer,
672674
textColor = MaterialTheme.colorScheme.onErrorContainer,
673675
message = stringResource(id = R.string.view_module_unsupported_arch_desc),
674-
modifier = Modifier.padding(horizontal = 16.dp)
676+
outsideContentPadding = alertPadding,
675677
)
676678

677679
Spacer(modifier = Modifier.height(16.dp))
@@ -685,13 +687,13 @@ fun NewViewScreen(
685687
textColor = MaterialTheme.colorScheme.onErrorContainer,
686688
title = it.title,
687689
message = it.message!!,
688-
modifier = Modifier.padding(horizontal = 16.dp)
690+
outsideContentPadding = alertPadding,
689691
)
690692
} else {
691693
Alert(
692694
title = it.title,
693695
message = it.message!!,
694-
modifier = Modifier.padding(horizontal = 16.dp)
696+
outsideContentPadding = alertPadding,
695697
)
696698
}
697699

app/src/main/kotlin/com/dergoogler/mmrl/ui/screens/settings/developer/DeveloperScreen.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,31 @@ package com.dergoogler.mmrl.ui.screens.settings.developer
33
import androidx.compose.runtime.Composable
44
import com.dergoogler.mmrl.R
55
import com.dergoogler.mmrl.ui.component.SettingsScaffold
6+
import com.dergoogler.mmrl.ui.component.listItem.dsl.ListItemScope
7+
import com.dergoogler.mmrl.ui.component.listItem.dsl.ListScope
68
import com.dergoogler.mmrl.ui.component.listItem.dsl.component.SwitchItem
79
import com.dergoogler.mmrl.ui.component.listItem.dsl.component.item.Description
810
import com.dergoogler.mmrl.ui.component.listItem.dsl.component.item.Title
911
import com.dergoogler.mmrl.ui.providable.LocalSettings
1012
import com.dergoogler.mmrl.ui.providable.LocalUserPreferences
1113

14+
@Composable
15+
fun ListScope.DeveloperSwitch(
16+
enabled: Boolean = true,
17+
onChange: (Boolean) -> Unit,
18+
checked: Boolean,
19+
content: @Composable ListItemScope.() -> Unit,
20+
) {
21+
val userPrefs = LocalUserPreferences.current
22+
23+
SwitchItem(
24+
checked = userPrefs.developerMode && checked,
25+
onChange = onChange,
26+
enabled = userPrefs.developerMode && enabled,
27+
content = content
28+
)
29+
}
30+
1231
@Composable
1332
fun DeveloperScreen() {
1433
val viewModel = LocalSettings.current
@@ -24,5 +43,12 @@ fun DeveloperScreen() {
2443
Title(R.string.settings_developer_mode)
2544
Description(R.string.settings_developer_mode_desc)
2645
}
46+
47+
DeveloperSwitch(
48+
checked = userPreferences.devAlwaysShowUpdateAlert,
49+
onChange = viewModel::setDevAlwaysShowUpdateAlert,
50+
) {
51+
Title(R.string.settings_always_show_update_alert)
52+
}
2753
}
2854
}

app/src/main/kotlin/com/dergoogler/mmrl/ui/screens/settings/security/SecurityScreen.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ fun SecurityScreen() {
4343
}
4444

4545
SwitchItem(
46-
checked = userPreferences.hideFingerprintInHome,
47-
onChange = viewModel::setHideFingerprintInHome
46+
checked = userPreferences.strictMode,
47+
onChange = viewModel::setStrictMode
4848
) {
4949
Title(R.string.settings_strict_mode)
5050
}

app/src/main/kotlin/com/dergoogler/mmrl/viewmodel/SettingsViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ class SettingsViewModel @Inject constructor(
250250
}
251251
}
252252

253+
fun setDevAlwaysShowUpdateAlert(value: Boolean) {
254+
viewModelScope.launch {
255+
userPreferencesRepository.setDevAlwaysShowUpdateAlert(value)
256+
}
257+
}
258+
253259
fun setWebUIEngine(value: WebUIEngine) {
254260
viewModelScope.launch {
255261
userPreferencesRepository.setWebUIEngine(value)

datastore/src/main/kotlin/com/dergoogler/mmrl/datastore/UserPreferencesDataSource.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,14 @@ class UserPreferencesDataSource @Inject constructor(
307307
}
308308
}
309309

310+
suspend fun setDevAlwaysShowUpdateAlert(value: Boolean) = withContext(Dispatchers.IO) {
311+
userPreferences.updateData {
312+
it.copy(
313+
devAlwaysShowUpdateAlert = value
314+
)
315+
}
316+
}
317+
310318
suspend fun setWebUIEngine(value: WebUIEngine) = withContext(Dispatchers.IO) {
311319
userPreferences.updateData {
312320
it.copy(

datastore/src/main/kotlin/com/dergoogler/mmrl/datastore/UserPreferencesRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class UserPreferencesRepository @Inject constructor(
113113
suspend fun setShowTerminalLineNumbers(value: Boolean) =
114114
userPreferencesDataSource.setShowTerminalLineNumbers(value)
115115

116+
suspend fun setDevAlwaysShowUpdateAlert(value: Boolean) =
117+
userPreferencesDataSource.setDevAlwaysShowUpdateAlert(value)
118+
116119
suspend fun setEnableToolbarEvents(value: Boolean) =
117120
userPreferencesDataSource.setEnableToolbarEvents(value)
118121

datastore/src/main/kotlin/com/dergoogler/mmrl/datastore/model/UserPreferences.kt

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ data class UserPreferences(
7070
@ProtoNumber(36) val enableToolbarEvents: Boolean = true,
7171
@ProtoNumber(37) val webuiEngine: WebUIEngine = WebUIEngine.PREFER_MODULE,
7272
@ProtoNumber(38) val showTerminalLineNumbers: Boolean = true,
73+
@ProtoNumber(39) val devAlwaysShowUpdateAlert: Boolean = false,
7374
) {
7475
fun isDarkMode() = when (darkMode) {
7576
DarkMode.AlwaysOff -> false
@@ -89,6 +90,17 @@ data class UserPreferences(
8990
ProtoBuf.encodeToByteArray(this)
9091
)
9192

93+
@OptIn(ExperimentalContracts::class)
94+
fun developerMode(
95+
also: UserPreferences.() -> Boolean,
96+
): Boolean {
97+
contract {
98+
callsInPlace(also, InvocationKind.AT_MOST_ONCE)
99+
}
100+
101+
return developerMode && also()
102+
}
103+
92104
companion object {
93105
val PUBLIC_DOWNLOADS: File = Environment.getExternalStoragePublicDirectory(
94106
Environment.DIRECTORY_DOWNLOADS
@@ -99,48 +111,3 @@ data class UserPreferences(
99111
ProtoBuf.decodeFromByteArray(input.readBytes())
100112
}
101113
}
102-
103-
@OptIn(ExperimentalContracts::class)
104-
inline fun <R> UserPreferences.developerMode(block: UserPreferences.() -> R): R? {
105-
contract {
106-
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
107-
}
108-
109-
return if (developerMode) block() else null
110-
}
111-
112-
@OptIn(ExperimentalContracts::class)
113-
inline fun <R> UserPreferences.developerMode(
114-
also: UserPreferences.() -> Boolean,
115-
block: UserPreferences.() -> R,
116-
): R? {
117-
contract {
118-
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
119-
}
120-
121-
return if (developerMode && also()) block() else null
122-
}
123-
124-
@OptIn(ExperimentalContracts::class)
125-
inline fun UserPreferences.developerMode(
126-
also: UserPreferences.() -> Boolean,
127-
): Boolean {
128-
contract {
129-
callsInPlace(also, InvocationKind.AT_MOST_ONCE)
130-
}
131-
132-
return developerMode && also()
133-
}
134-
135-
@OptIn(ExperimentalContracts::class)
136-
inline fun <R> UserPreferences.developerMode(
137-
also: UserPreferences.() -> Boolean,
138-
default: R,
139-
block: UserPreferences.() -> R,
140-
): R {
141-
contract {
142-
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
143-
}
144-
145-
return if (developerMode && also()) block() else default
146-
}

ui/src/main/kotlin/com/dergoogler/mmrl/ui/component/Alert.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.dergoogler.mmrl.ui.component
33
import androidx.annotation.DrawableRes
44
import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.PaddingValues
67
import androidx.compose.foundation.layout.fillMaxWidth
78
import androidx.compose.foundation.layout.padding
89
import androidx.compose.material3.MaterialTheme
@@ -26,11 +27,16 @@ fun Alert(
2627
textColor: Color = contentColorFor(backgroundColor),
2728
title: String?,
2829
message: String,
30+
outsideContentPadding: PaddingValues = PaddingValues(0.dp),
31+
onClick: (() -> Unit)? = null,
2932
@DrawableRes icon: Int? = null,
3033
) = Card(
31-
modifier = modifier
34+
onClick = onClick,
35+
modifier = Modifier
3236
.padding(vertical = 16.dp, horizontal = 25.dp)
33-
.fillMaxWidth(),
37+
.fillMaxWidth()
38+
.then(modifier),
39+
outsideContentPadding = outsideContentPadding,
3440
color = backgroundColor,
3541
contentColor = textColor,
3642
) {

ui/src/main/kotlin/com/dergoogler/mmrl/ui/component/card/Card.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import androidx.compose.foundation.hoverable
99
import androidx.compose.foundation.interaction.Interaction
1010
import androidx.compose.foundation.interaction.MutableInteractionSource
1111
import androidx.compose.foundation.interaction.collectIsHoveredAsState
12+
import androidx.compose.foundation.layout.PaddingValues
13+
import androidx.compose.foundation.layout.padding
1214
import androidx.compose.foundation.shape.RoundedCornerShape
1315
import androidx.compose.material3.LocalAbsoluteTonalElevation
1416
import androidx.compose.material3.LocalContentColor
@@ -72,6 +74,7 @@ fun Card(
7274
color: Color = MaterialTheme.colorScheme.surface,
7375
contentColor: Color = contentColorFor(color),
7476
shape: Shape = RoundedCornerShape(20.dp),
77+
outsideContentPadding: PaddingValues = PaddingValues(0.dp),
7578
tonalElevation: Dp = 1.dp,
7679
shadowElevation: Dp = 0.dp,
7780
border: BorderStroke? = null,
@@ -106,6 +109,7 @@ fun Card(
106109
) {
107110
Layout(
108111
modifier = Modifier
112+
.padding(outsideContentPadding)
109113
.card(
110114
shape = shape,
111115
backgroundColor = MaterialTheme.colorScheme.applyTonalElevation(

0 commit comments

Comments
 (0)