Skip to content

Commit dee4ddd

Browse files
committed
feat: add setting to revert changes
This introduces a new setting in the "Startup" category that allows users to easily revert any changes made by the app.
1 parent 151dfed commit dee4ddd

7 files changed

Lines changed: 79 additions & 13 deletions

File tree

app/src/main/kotlin/com/androidvip/sysctlgui/ui/settings/SettingsScreen.kt

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import androidx.compose.foundation.layout.fillMaxSize
1717
import androidx.compose.foundation.layout.fillMaxWidth
1818
import androidx.compose.foundation.layout.padding
1919
import androidx.compose.foundation.layout.size
20-
import androidx.compose.foundation.lazy.grid.GridCells
21-
import androidx.compose.foundation.lazy.grid.GridItemSpan
22-
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
20+
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
21+
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
22+
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
2323
import androidx.compose.foundation.shape.RoundedCornerShape
24+
import androidx.compose.material3.AlertDialog
2425
import androidx.compose.material3.Icon
2526
import androidx.compose.material3.MaterialTheme
2627
import androidx.compose.material3.Text
28+
import androidx.compose.material3.TextButton
2729
import androidx.compose.runtime.Composable
2830
import androidx.compose.runtime.LaunchedEffect
2931
import androidx.compose.runtime.getValue
@@ -34,6 +36,7 @@ import androidx.compose.ui.Alignment
3436
import androidx.compose.ui.Modifier
3537
import androidx.compose.ui.draw.clip
3638
import androidx.compose.ui.platform.LocalContext
39+
import androidx.compose.ui.platform.LocalUriHandler
3740
import androidx.compose.ui.res.painterResource
3841
import androidx.compose.ui.res.stringResource
3942
import androidx.compose.ui.text.style.TextAlign
@@ -60,8 +63,8 @@ import com.androidvip.sysctlgui.ui.settings.components.SwitchSettingComponent
6063
import com.androidvip.sysctlgui.ui.settings.components.TextSettingComponent
6164
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEffect
6265
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEvent
63-
import com.androidvip.sysctlgui.utils.browse
6466
import org.koin.androidx.compose.koinViewModel
67+
import com.androidvip.sysctlgui.data.R as DataR
6568

6669
internal const val DISABLED_ALPHA = 0.38f
6770

@@ -71,8 +74,10 @@ internal fun SettingsScreen(
7174
viewModel: SettingsViewModel = koinViewModel(),
7275
onNavigate: (UiRoute) -> Unit
7376
) {
74-
val state = viewModel.uiState.collectAsStateWithLifecycle()
77+
val state by viewModel.uiState.collectAsStateWithLifecycle()
7578
val context = LocalContext.current
79+
val uriHandler = LocalUriHandler.current
80+
var showRevertChangesDialog by remember { mutableStateOf(false) }
7681
var hasNotificationPermission by remember {
7782
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
7883
mutableStateOf(
@@ -117,7 +122,7 @@ internal fun SettingsScreen(
117122
}
118123

119124
is SettingsViewEffect.OpenBrowser -> {
120-
context.browse(effect.url)
125+
uriHandler.openUri(effect.url)
121126
}
122127

123128
is SettingsViewEffect.Navigate -> {
@@ -127,19 +132,27 @@ internal fun SettingsScreen(
127132
is SettingsViewEffect.ShowToast -> {
128133
Toast.makeText(context, effect.message, Toast.LENGTH_SHORT).show()
129134
}
135+
136+
SettingsViewEffect.ShowRevertDialog -> {
137+
showRevertChangesDialog = true
138+
}
130139
}
131140
}
132141
}
133142

134143
SettingsScreenContent(
135-
settings = state.value.settings,
144+
settings = state.settings,
136145
onSettingHeaderClicked = { appSetting ->
137146
viewModel.onEvent(SettingsViewEvent.SettingHeaderClicked(appSetting))
138147
},
139148
onValueChanged = { appSetting, newValue ->
140149
viewModel.onEvent(SettingsViewEvent.SettingValueChanged(appSetting, newValue))
141150
}
142151
)
152+
153+
if (showRevertChangesDialog) {
154+
RevertChangesDialog(onDismissRequest = { showRevertChangesDialog = false })
155+
}
143156
}
144157

145158
@Composable
@@ -152,15 +165,15 @@ private fun SettingsScreenContent(
152165
val columns = if (isLandscape()) 2 else 1
153166
val containerColor = MaterialTheme.colorScheme.surfaceContainer
154167

155-
LazyVerticalGrid(
156-
columns = GridCells.Fixed(columns),
168+
LazyVerticalStaggeredGrid(
169+
columns = StaggeredGridCells.Fixed(columns),
157170
modifier = Modifier.fillMaxSize(),
158171
contentPadding = PaddingValues(16.dp),
159-
verticalArrangement = Arrangement.spacedBy(16.dp),
172+
verticalItemSpacing = 16.dp,
160173
horizontalArrangement = Arrangement.spacedBy(16.dp)
161174
) {
162175
groupedSettings.forEach { (category, settingsGroup) ->
163-
item(span = { GridItemSpan(columns) }) {
176+
item {
164177
Column(
165178
modifier = Modifier
166179
.fillMaxWidth()
@@ -187,7 +200,7 @@ private fun SettingsScreenContent(
187200
}
188201
}
189202

190-
item(span = { GridItemSpan(columns) }) {
203+
item {
191204
Box(
192205
modifier = Modifier
193206
.clip(RoundedCornerShape(24.dp))
@@ -216,7 +229,7 @@ private fun SettingsScreenContent(
216229
}
217230
}
218231

219-
item(span = { GridItemSpan(columns) }) {
232+
item(span = StaggeredGridItemSpan.FullLine) {
220233
Text(
221234
text = "Developed with ❤️ by Lennoard Silva\nAndroid enthusiast 🤖",
222235
style = MaterialTheme.typography.bodySmall,
@@ -297,6 +310,31 @@ private fun SettingsGroupItem(
297310
}
298311
}
299312

313+
314+
@Composable
315+
fun RevertChangesDialog(onDismissRequest: () -> Unit) {
316+
AlertDialog(
317+
onDismissRequest = onDismissRequest,
318+
confirmButton = {
319+
TextButton(onClick = onDismissRequest) {
320+
Text(text = stringResource(android.R.string.ok))
321+
}
322+
},
323+
icon = {
324+
Icon(
325+
painter = painterResource(R.drawable.ic_restore_settings),
326+
contentDescription = null
327+
)
328+
},
329+
title = {
330+
Text(text = stringResource(DataR.string.prefs_startup_revert_changes))
331+
},
332+
text = {
333+
Text(text = stringResource(DataR.string.prefs_startup_revert_changes_message))
334+
}
335+
)
336+
}
337+
300338
@Composable
301339
@PreviewLightDark
302340
@Preview(device = "spec:parent=pixel_5,orientation=landscape")

app/src/main/kotlin/com/androidvip/sysctlgui/ui/settings/SettingsViewModel.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.androidvip.sysctlgui.domain.enums.SettingItemType
1111
import com.androidvip.sysctlgui.domain.models.KEY_CONTRIBUTORS
1212
import com.androidvip.sysctlgui.domain.models.KEY_DELETE_HISTORY
1313
import com.androidvip.sysctlgui.domain.models.KEY_MANAGE_PARAMS
14+
import com.androidvip.sysctlgui.domain.models.KEY_REVERT_CHANGES
1415
import com.androidvip.sysctlgui.domain.models.KEY_SOURCE_CODE
1516
import com.androidvip.sysctlgui.domain.models.KEY_TRANSLATIONS
1617
import com.androidvip.sysctlgui.domain.usecase.GetAppSettingsUseCase
@@ -78,6 +79,16 @@ class SettingsViewModel(
7879

7980
is SettingsViewEvent.SettingHeaderClicked<*> -> {
8081
when (event.appSetting.key) {
82+
KEY_REVERT_CHANGES -> {
83+
setEffect { SettingsViewEffect.ShowRevertDialog }
84+
viewModelScope.launch {
85+
sharedPreferences.edit(commit = true) {
86+
putBoolean(Prefs.RunOnStartup.key, false)
87+
}
88+
loadSettings()
89+
}
90+
}
91+
8192
KEY_MANAGE_PARAMS -> {
8293
setEffect { SettingsViewEffect.Navigate(UiRoute.UserParams) }
8394
}

app/src/main/kotlin/com/androidvip/sysctlgui/ui/settings/model/SettingsViewEvent.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ sealed interface SettingsViewEffect {
1313
class OpenBrowser(val url: String) : SettingsViewEffect
1414
class Navigate(val route: UiRoute) : SettingsViewEffect
1515
class ShowToast(val message: String) : SettingsViewEffect
16+
data object ShowRevertDialog : SettingsViewEffect
1617
}
1718

1819
data class SettingsViewState(

data/src/main/java/com/androidvip/sysctlgui/data/repository/AppSettingsRepositoryImpl.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.androidvip.sysctlgui.domain.models.AppSetting
1212
import com.androidvip.sysctlgui.domain.models.KEY_CONTRIBUTORS
1313
import com.androidvip.sysctlgui.domain.models.KEY_DELETE_HISTORY
1414
import com.androidvip.sysctlgui.domain.models.KEY_MANAGE_PARAMS
15+
import com.androidvip.sysctlgui.domain.models.KEY_REVERT_CHANGES
1516
import com.androidvip.sysctlgui.domain.models.KEY_SOURCE_CODE
1617
import com.androidvip.sysctlgui.domain.models.KEY_TRANSLATIONS
1718
import com.androidvip.sysctlgui.domain.repository.AppSettingsRepository
@@ -171,6 +172,14 @@ class AppSettingsRepositoryImpl(
171172
type = SettingItemType.Slider,
172173
values = (0..10).toList(),
173174
),
175+
AppSetting(
176+
key = KEY_REVERT_CHANGES,
177+
value = Unit,
178+
category = context.getString(R.string.prefs_category_startup),
179+
title = context.getString(R.string.prefs_startup_revert_changes),
180+
description = context.getString(R.string.prefs_startup_revert_changes_description),
181+
type = SettingItemType.Text
182+
),
174183

175184
/////////// OTHERS ////////////
176185
AppSetting(

data/src/main/res/values-pt-rBR/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@
3737
<string name="pref_contributors_title">Contribuidores</string>
3838
<string name="pref_translations_title">Traduções</string>
3939
<string name="pref_translations_description">Ajude a traduzir este aplicativo</string>
40+
<string name="prefs_startup_revert_changes">Reverter mudanças</string>
41+
<string name="prefs_startup_revert_changes_description">Reverter alterações feitas por este aplicativo</string>
42+
<string name="prefs_startup_revert_changes_message">Devido à natureza do kernel, as alterações feitas em tempo de execução podem ser revertidas com uma simples reinicialização do dispositivo. O aplicativo não tentará mais reaplicar as alterações após um ciclo de inicialização completo.</string>
4043
</resources>

data/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,7 @@
3737
<string name="pref_contributors_title">Contributors</string>
3838
<string name="pref_translations_title">Translations</string>
3939
<string name="pref_translations_description">Help translate this application</string>
40+
<string name="prefs_startup_revert_changes">Revert changes</string>
41+
<string name="prefs_startup_revert_changes_description">Revert changes made by this app</string>
42+
<string name="prefs_startup_revert_changes_message">By the nature of the kernel, changes done at runtime can be reverted by a simple device reboot. The app will no longer attempt to reapply changes right after a completed boot cycle.</string>
4043
</resources>

domain/src/main/java/com/androidvip/sysctlgui/domain/models/AppSetting.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ data class AppSetting<T>(
3232
val iconResource: Int? = null
3333
)
3434

35+
const val KEY_REVERT_CHANGES = "revertChanges"
3536
const val KEY_MANAGE_PARAMS = "manageParams"
3637
const val KEY_DELETE_HISTORY = "deleteHistory"
3738
const val KEY_SOURCE_CODE = "sauce"

0 commit comments

Comments
 (0)