Skip to content

Commit f3ae909

Browse files
committed
feature: added "about" headers
1 parent 1d6f2e9 commit f3ae909

File tree

21 files changed

+274
-39
lines changed

21 files changed

+274
-39
lines changed

app/src/main/kotlin/com/androidvip/sysctlgui/ui/main/AppNavHost.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ internal fun AppNavHost(
8484

8585
composable<UiRoute.Settings> {
8686
SettingsScreen(
87-
onNavigateToUserParams = {
88-
navController.navigate(UiRoute.UserParams)
87+
onNavigate = { route ->
88+
navController.navigate(route)
8989
}
9090
)
9191
}

app/src/main/kotlin/com/androidvip/sysctlgui/ui/main/MainTopBar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ fun MainTopBar(
6565
private fun MainTopBarPreview() {
6666
SysctlGuiTheme {
6767
MainTopBar(
68-
title = "SysctlGUI",
68+
title = "Sysctl GUI",
6969
showBack = false,
7070
showSearch = true,
7171
onSearchPressed = {},

app/src/main/kotlin/com/androidvip/sysctlgui/ui/main/MainViewState.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.compose.material3.SnackbarResult
44
import com.androidvip.sysctlgui.data.repository.CONTRAST_LEVEL_NORMAL
55

66
data class MainViewState(
7-
val topBarTitle: String = "SysctlGUI",
7+
val topBarTitle: String = "Sysctl GUI",
88
val showTopBar: Boolean = true,
99
val showNavBar: Boolean = true,
1010
val showBackButton: Boolean = false,

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

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,23 @@ package com.androidvip.sysctlgui.ui.settings
33
import android.Manifest
44
import android.content.pm.PackageManager
55
import android.os.Build
6+
import android.widget.Toast
67
import androidx.activity.compose.rememberLauncherForActivityResult
78
import androidx.activity.result.contract.ActivityResultContracts
89
import androidx.compose.foundation.background
10+
import androidx.compose.foundation.layout.Arrangement
911
import androidx.compose.foundation.layout.Box
12+
import androidx.compose.foundation.layout.Row
1013
import androidx.compose.foundation.layout.fillMaxWidth
1114
import androidx.compose.foundation.layout.padding
15+
import androidx.compose.foundation.layout.size
1216
import androidx.compose.foundation.lazy.grid.GridCells
1317
import androidx.compose.foundation.lazy.grid.GridItemSpan
1418
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
1519
import androidx.compose.foundation.lazy.grid.items
20+
import androidx.compose.material.icons.Icons
21+
import androidx.compose.material.icons.rounded.Info
22+
import androidx.compose.material3.Icon
1623
import androidx.compose.material3.MaterialTheme
1724
import androidx.compose.material3.Text
1825
import androidx.compose.runtime.Composable
@@ -21,13 +28,18 @@ import androidx.compose.runtime.getValue
2128
import androidx.compose.runtime.mutableStateOf
2229
import androidx.compose.runtime.remember
2330
import androidx.compose.runtime.setValue
31+
import androidx.compose.ui.Alignment
2432
import androidx.compose.ui.Modifier
2533
import androidx.compose.ui.platform.LocalContext
34+
import androidx.compose.ui.res.stringResource
35+
import androidx.compose.ui.text.style.TextAlign
2636
import androidx.compose.ui.tooling.preview.Preview
2737
import androidx.compose.ui.tooling.preview.PreviewLightDark
2838
import androidx.compose.ui.unit.dp
2939
import androidx.core.content.ContextCompat
3040
import androidx.lifecycle.compose.collectAsStateWithLifecycle
41+
import com.androidvip.sysctlgui.R
42+
import com.androidvip.sysctlgui.core.navigation.UiRoute
3143
import com.androidvip.sysctlgui.data.Prefs
3244
import com.androidvip.sysctlgui.design.theme.SysctlGuiTheme
3345
import com.androidvip.sysctlgui.design.utils.isLandscape
@@ -38,11 +50,13 @@ import com.androidvip.sysctlgui.ui.main.MainViewEvent
3850
import com.androidvip.sysctlgui.ui.main.MainViewModel
3951
import com.androidvip.sysctlgui.ui.main.MainViewState
4052
import com.androidvip.sysctlgui.ui.settings.components.HeaderComponent
53+
import com.androidvip.sysctlgui.ui.settings.components.SettingsComponentColumn
4154
import com.androidvip.sysctlgui.ui.settings.components.SliderSettingComponent
4255
import com.androidvip.sysctlgui.ui.settings.components.SwitchSettingComponent
4356
import com.androidvip.sysctlgui.ui.settings.components.TextSettingComponent
4457
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEffect
4558
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEvent
59+
import com.androidvip.sysctlgui.utils.browse
4660
import org.koin.androidx.compose.koinViewModel
4761

4862
internal const val DISABLED_ALPHA = 0.38f
@@ -51,7 +65,7 @@ internal const val DISABLED_ALPHA = 0.38f
5165
internal fun SettingsScreen(
5266
mainViewModel: MainViewModel = koinViewModel(),
5367
viewModel: SettingsViewModel = koinViewModel(),
54-
onNavigateToUserParams: () -> Unit
68+
onNavigate: (UiRoute) -> Unit
5569
) {
5670
val state = viewModel.uiState.collectAsStateWithLifecycle()
5771
val context = LocalContext.current
@@ -97,13 +111,27 @@ internal fun SettingsScreen(
97111
}
98112
}
99113
}
114+
115+
is SettingsViewEffect.OpenBrowser -> {
116+
context.browse(effect.url)
117+
}
118+
119+
is SettingsViewEffect.Navigate -> {
120+
onNavigate(effect.route)
121+
}
122+
123+
is SettingsViewEffect.ShowToast -> {
124+
Toast.makeText(context, effect.message, Toast.LENGTH_SHORT).show()
125+
}
100126
}
101127
}
102128
}
103129

104130
SettingsScreenContent(
105131
settings = state.value.settings,
106-
onNavigateToUserParams = onNavigateToUserParams,
132+
onSettingHeaderClicked = { appSetting ->
133+
viewModel.onEvent(SettingsViewEvent.SettingHeaderClicked(appSetting))
134+
},
107135
onValueChanged = { appSetting, newValue ->
108136
viewModel.onEvent(SettingsViewEvent.SettingValueChanged(appSetting, newValue))
109137
}
@@ -113,7 +141,7 @@ internal fun SettingsScreen(
113141
@Composable
114142
private fun SettingsScreenContent(
115143
settings: List<AppSetting<*>> = emptyList(),
116-
onNavigateToUserParams: () -> Unit,
144+
onSettingHeaderClicked: (AppSetting<*>) -> Unit,
117145
onValueChanged: (AppSetting<*>, Any) -> Unit
118146
) {
119147
val groupedSettings = settings.groupBy { it.category }
@@ -157,7 +185,7 @@ private fun SettingsScreenContent(
157185
HeaderComponent(
158186
modifier = itemModifier,
159187
appSetting = appSetting,
160-
onClick = onNavigateToUserParams
188+
onClick = { onSettingHeaderClicked(appSetting) }
161189
)
162190
}
163191
SettingItemType.List -> {
@@ -190,6 +218,47 @@ private fun SettingsScreenContent(
190218
}
191219
}
192220
}
221+
222+
item(span = { GridItemSpan(columns) }) {
223+
Box(contentAlignment = Alignment.Center) {
224+
Row(
225+
modifier = Modifier.padding(all = 16.dp),
226+
verticalAlignment = Alignment.CenterVertically,
227+
horizontalArrangement = Arrangement.spacedBy(space = 16.dp)
228+
) {
229+
230+
Icon(
231+
imageVector = Icons.Rounded.Info,
232+
contentDescription = null,
233+
tint = MaterialTheme.colorScheme.onBackground,
234+
modifier = Modifier.size(24.dp)
235+
)
236+
237+
SettingsComponentColumn(
238+
title = stringResource(R.string.about),
239+
description = stringResource(R.string.sysctl_help),
240+
modifier = Modifier.fillMaxWidth()
241+
)
242+
}
243+
}
244+
}
245+
246+
item(span = { GridItemSpan(columns) }) {
247+
Text(
248+
text = "Developed with ❤️ by Lennoard Silva\nAndroid enthusiast 🤖",
249+
style = MaterialTheme.typography.bodySmall,
250+
color = MaterialTheme.colorScheme.onBackground,
251+
textAlign = TextAlign.Center,
252+
modifier = Modifier
253+
.fillMaxWidth()
254+
.padding(
255+
top = 64.dp,
256+
bottom = 32.dp,
257+
start = 24.dp,
258+
end = 24.dp,
259+
)
260+
)
261+
}
193262
}
194263
}
195264

@@ -257,7 +326,7 @@ internal fun SettingsScreenPreview() {
257326
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
258327
SettingsScreenContent(
259328
settings = settings,
260-
onNavigateToUserParams = {},
329+
onSettingHeaderClicked = {},
261330
onValueChanged = { _, _ -> }
262331
)
263332
}

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ package com.androidvip.sysctlgui.ui.settings
33
import android.content.SharedPreferences
44
import androidx.core.content.edit
55
import androidx.lifecycle.viewModelScope
6+
import com.androidvip.sysctlgui.R
7+
import com.androidvip.sysctlgui.core.navigation.UiRoute
68
import com.androidvip.sysctlgui.data.Prefs
9+
import com.androidvip.sysctlgui.domain.StringProvider
710
import com.androidvip.sysctlgui.domain.enums.SettingItemType
11+
import com.androidvip.sysctlgui.domain.models.KEY_CONTRIBUTORS
12+
import com.androidvip.sysctlgui.domain.models.KEY_DELETE_HISTORY
13+
import com.androidvip.sysctlgui.domain.models.KEY_MANAGE_PARAMS
14+
import com.androidvip.sysctlgui.domain.models.KEY_SOURCE_CODE
15+
import com.androidvip.sysctlgui.domain.models.KEY_TRANSLATIONS
816
import com.androidvip.sysctlgui.domain.usecase.GetAppSettingsUseCase
917
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEffect
1018
import com.androidvip.sysctlgui.ui.settings.model.SettingsViewEvent
@@ -14,7 +22,8 @@ import kotlinx.coroutines.launch
1422

1523
class SettingsViewModel(
1624
private val sharedPreferences: SharedPreferences,
17-
private val getSettings: GetAppSettingsUseCase
25+
private val getSettings: GetAppSettingsUseCase,
26+
private val stringProvider: StringProvider
1827
) : BaseViewModel<SettingsViewEvent, SettingsViewState, SettingsViewEffect>() {
1928

2029
init {
@@ -66,6 +75,27 @@ class SettingsViewModel(
6675
loadSettings()
6776
}
6877
}
78+
79+
is SettingsViewEvent.SettingHeaderClicked<*> -> {
80+
when (event.appSetting.key) {
81+
KEY_MANAGE_PARAMS -> {
82+
setEffect { SettingsViewEffect.Navigate(UiRoute.UserParams) }
83+
}
84+
85+
KEY_DELETE_HISTORY -> {
86+
sharedPreferences.edit { remove(Prefs.SearchHistory.key) }
87+
setEffect {
88+
SettingsViewEffect.ShowToast(stringProvider.getString(R.string.history_deleted))
89+
}
90+
}
91+
92+
KEY_SOURCE_CODE, KEY_CONTRIBUTORS, KEY_TRANSLATIONS -> {
93+
setEffect {
94+
SettingsViewEffect.OpenBrowser(event.appSetting.value as String)
95+
}
96+
}
97+
}
98+
}
6999
}
70100
}
71101

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,46 @@ import androidx.compose.foundation.clickable
44
import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Box
66
import androidx.compose.foundation.layout.Row
7+
import androidx.compose.foundation.layout.Spacer
78
import androidx.compose.foundation.layout.fillMaxWidth
89
import androidx.compose.foundation.layout.padding
910
import androidx.compose.foundation.layout.size
11+
import androidx.compose.material3.Icon
12+
import androidx.compose.material3.MaterialTheme
1013
import androidx.compose.runtime.Composable
1114
import androidx.compose.ui.Alignment
1215
import androidx.compose.ui.Modifier
16+
import androidx.compose.ui.res.painterResource
1317
import androidx.compose.ui.unit.dp
1418
import com.androidvip.sysctlgui.domain.models.AppSetting
1519

1620
@Composable
1721
fun HeaderComponent(
1822
modifier: Modifier = Modifier,
1923
appSetting: AppSetting<*>,
20-
onClick: () -> Unit,
21-
icon: @Composable (() -> Unit)? = null
24+
onClick: () -> Unit
2225
) {
23-
Box(modifier = modifier.clickable(onClick = onClick)) {
26+
Box(
27+
modifier = modifier.clickable(onClick = onClick),
28+
contentAlignment = Alignment.Center
29+
) {
2430
Row(
2531
modifier = Modifier.padding(all = 16.dp),
2632
verticalAlignment = Alignment.CenterVertically,
2733
horizontalArrangement = Arrangement.spacedBy(space = 16.dp)
2834
) {
2935

30-
Box(
31-
modifier = Modifier
32-
.align(Alignment.CenterVertically)
33-
.size(24.dp)
34-
) {
35-
icon?.invoke()
36+
if (appSetting.iconResource != null) {
37+
Box(modifier = Modifier.align(Alignment.CenterVertically)) {
38+
Icon(
39+
painter = painterResource(appSetting.iconResource!!),
40+
contentDescription = null,
41+
tint = MaterialTheme.colorScheme.onSurface,
42+
modifier = Modifier.size(24.dp)
43+
)
44+
}
45+
} else {
46+
Spacer(modifier = Modifier.size(24.dp))
3647
}
3748

3849
SettingsComponentColumn(

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import androidx.compose.foundation.clickable
55
import androidx.compose.foundation.layout.Arrangement
66
import androidx.compose.foundation.layout.Box
77
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.Spacer
89
import androidx.compose.foundation.layout.fillMaxSize
910
import androidx.compose.foundation.layout.fillMaxWidth
1011
import androidx.compose.foundation.layout.padding
1112
import androidx.compose.foundation.layout.size
12-
import androidx.compose.material3.DropdownMenuItem
1313
import androidx.compose.material3.DropdownMenu
14+
import androidx.compose.material3.DropdownMenuItem
15+
import androidx.compose.material3.Icon
1416
import androidx.compose.material3.MaterialTheme
1517
import androidx.compose.material3.Text
1618
import androidx.compose.runtime.Composable
@@ -20,9 +22,11 @@ import androidx.compose.runtime.remember
2022
import androidx.compose.runtime.setValue
2123
import androidx.compose.ui.Alignment
2224
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.res.painterResource
2326
import androidx.compose.ui.tooling.preview.PreviewLightDark
2427
import androidx.compose.ui.unit.DpOffset
2528
import androidx.compose.ui.unit.dp
29+
import com.androidvip.sysctlgui.R
2630
import com.androidvip.sysctlgui.design.theme.SysctlGuiTheme
2731
import com.androidvip.sysctlgui.domain.enums.SettingItemType
2832
import com.androidvip.sysctlgui.domain.models.AppSetting
@@ -31,8 +35,7 @@ import com.androidvip.sysctlgui.domain.models.AppSetting
3135
fun TextSettingComponent(
3236
modifier: Modifier = Modifier,
3337
appSetting: AppSetting<*>,
34-
onValueChange: (String) -> Unit,
35-
icon: @Composable (() -> Unit)? = null
38+
onValueChange: (String) -> Unit
3639
) {
3740
var expanded by remember { mutableStateOf(false) }
3841

@@ -47,12 +50,17 @@ fun TextSettingComponent(
4750
verticalAlignment = Alignment.CenterVertically,
4851
horizontalArrangement = Arrangement.spacedBy(space = 16.dp)
4952
) {
50-
Box(
51-
modifier = Modifier
52-
.align(Alignment.CenterVertically)
53-
.size(24.dp)
54-
) {
55-
icon?.invoke()
53+
if (appSetting.iconResource != null) {
54+
Box(modifier = Modifier.align(Alignment.CenterVertically)) {
55+
Icon(
56+
painter = painterResource(appSetting.iconResource!!),
57+
contentDescription = null,
58+
tint = MaterialTheme.colorScheme.onSurface,
59+
modifier = Modifier.size(24.dp)
60+
)
61+
}
62+
} else {
63+
Spacer(modifier = Modifier.size(24.dp))
5664
}
5765

5866
SettingsComponentColumn(
@@ -101,6 +109,7 @@ private fun TextSettingComponentPreview() {
101109
description = "Description",
102110
value = "sysctl",
103111
category = "",
112+
iconResource = R.drawable.ic_history,
104113
values = listOf("sysctl", "echo"),
105114
type = SettingItemType.List
106115
),

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package com.androidvip.sysctlgui.ui.settings.model
22

3+
import com.androidvip.sysctlgui.core.navigation.UiRoute
34
import com.androidvip.sysctlgui.domain.models.AppSetting
45

56
sealed interface SettingsViewEvent {
67
class SettingValueChanged<T>(val appSetting: AppSetting<T>, val newValue: Any) : SettingsViewEvent
8+
class SettingHeaderClicked<T>(val appSetting: AppSetting<T>) : SettingsViewEvent
79
}
810

911
sealed interface SettingsViewEffect {
1012
object RequestNotificationPermission : SettingsViewEffect
13+
class OpenBrowser(val url: String) : SettingsViewEffect
14+
class Navigate(val route: UiRoute) : SettingsViewEffect
15+
class ShowToast(val message: String) : SettingsViewEffect
1116
}
1217

1318
data class SettingsViewState(

0 commit comments

Comments
 (0)