Skip to content

Commit afc72ff

Browse files
authored
feat: Show manager update dialog (#2069)
Closes #1963, closes #1958
1 parent cdc69ea commit afc72ff

7 files changed

Lines changed: 136 additions & 47 deletions

File tree

app/src/main/java/app/revanced/manager/domain/manager/PreferencesManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class PreferencesManager(
2323

2424
val firstLaunch = booleanPreference("first_launch", true)
2525
val managerAutoUpdates = booleanPreference("manager_auto_updates", false)
26+
val showManagerUpdateDialogOnLaunch = booleanPreference("show_manager_update_dialog_on_launch", true)
2627

2728
val disablePatchVersionCompatCheck = booleanPreference("disable_patch_version_compatibility_check", false)
2829
val disableSelectionWarning = booleanPreference("disable_selection_warning", false)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package app.revanced.manager.ui.component
2+
3+
import androidx.compose.foundation.clickable
4+
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.PaddingValues
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.material.icons.Icons
9+
import androidx.compose.material.icons.outlined.Update
10+
import androidx.compose.material3.*
11+
import androidx.compose.runtime.*
12+
import androidx.compose.runtime.saveable.rememberSaveable
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.res.stringResource
15+
import androidx.compose.ui.unit.dp
16+
import app.revanced.manager.R
17+
18+
@OptIn(ExperimentalMaterial3Api::class)
19+
@Composable
20+
fun AvailableUpdateDialog(
21+
onDismiss: () -> Unit,
22+
onConfirm: () -> Unit,
23+
setShowManagerUpdateDialogOnLaunch: (Boolean) -> Unit,
24+
newVersion: String
25+
) {
26+
var dontShowAgain by rememberSaveable { mutableStateOf(false) }
27+
val dismissDialog = {
28+
setShowManagerUpdateDialogOnLaunch(!dontShowAgain)
29+
onDismiss()
30+
}
31+
32+
AlertDialogExtended(
33+
onDismissRequest = dismissDialog,
34+
confirmButton = {
35+
TextButton(
36+
onClick = {
37+
dismissDialog()
38+
onConfirm()
39+
}
40+
) {
41+
Text(stringResource(R.string.show))
42+
}
43+
},
44+
dismissButton = {
45+
TextButton(
46+
onClick = dismissDialog
47+
) {
48+
Text(stringResource(R.string.dismiss))
49+
}
50+
},
51+
icon = {
52+
Icon(imageVector = Icons.Outlined.Update, contentDescription = null)
53+
},
54+
title = {
55+
Text(stringResource(R.string.update_available))
56+
},
57+
text = {
58+
Column(
59+
modifier = Modifier.padding(horizontal = 8.dp),
60+
verticalArrangement = Arrangement.spacedBy(4.dp),
61+
) {
62+
Text(
63+
modifier = Modifier.padding(horizontal = 16.dp),
64+
text = stringResource(R.string.update_available_dialog_description, newVersion)
65+
)
66+
ListItem(
67+
modifier = Modifier.clickable { dontShowAgain = !dontShowAgain },
68+
headlineContent = {
69+
Text(stringResource(R.string.never_show_again))
70+
},
71+
leadingContent = {
72+
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) {
73+
Checkbox(checked = dontShowAgain, onCheckedChange = { dontShowAgain = it })
74+
}
75+
}
76+
)
77+
}
78+
},
79+
textHorizontalPadding = PaddingValues(0.dp)
80+
)
81+
}

app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,17 @@ import android.net.Uri
66
import android.provider.Settings
77
import androidx.activity.compose.BackHandler
88
import androidx.compose.foundation.ExperimentalFoundationApi
9-
import androidx.compose.foundation.layout.Arrangement
10-
import androidx.compose.foundation.layout.Column
11-
import androidx.compose.foundation.layout.fillMaxSize
12-
import androidx.compose.foundation.layout.padding
9+
import androidx.compose.foundation.layout.*
1310
import androidx.compose.foundation.pager.HorizontalPager
1411
import androidx.compose.foundation.pager.rememberPagerState
1512
import androidx.compose.material.icons.Icons
1613
import androidx.compose.material.icons.filled.Add
1714
import androidx.compose.material.icons.filled.BatteryAlert
1815
import androidx.compose.material.icons.filled.Close
19-
import androidx.compose.material.icons.outlined.Apps
20-
import androidx.compose.material.icons.outlined.DeleteOutline
21-
import androidx.compose.material.icons.outlined.Refresh
22-
import androidx.compose.material.icons.outlined.Settings
23-
import androidx.compose.material.icons.outlined.Source
24-
import androidx.compose.material.icons.outlined.Update
25-
import androidx.compose.material.icons.outlined.WarningAmber
26-
import androidx.compose.material3.ExperimentalMaterial3Api
27-
import androidx.compose.material3.FloatingActionButton
28-
import androidx.compose.material3.Icon
29-
import androidx.compose.material3.IconButton
30-
import androidx.compose.material3.MaterialTheme
31-
import androidx.compose.material3.Scaffold
32-
import androidx.compose.material3.Tab
33-
import androidx.compose.material3.TabRow
34-
import androidx.compose.material3.Text
35-
import androidx.compose.material3.TextButton
36-
import androidx.compose.material3.surfaceColorAtElevation
37-
import androidx.compose.runtime.Composable
38-
import androidx.compose.runtime.LaunchedEffect
39-
import androidx.compose.runtime.derivedStateOf
40-
import androidx.compose.runtime.getValue
41-
import androidx.compose.runtime.mutableStateOf
42-
import androidx.compose.runtime.remember
43-
import androidx.compose.runtime.rememberCoroutineScope
16+
import androidx.compose.material.icons.outlined.*
17+
import androidx.compose.material3.*
18+
import androidx.compose.runtime.*
4419
import androidx.compose.runtime.saveable.rememberSaveable
45-
import androidx.compose.runtime.setValue
4620
import androidx.compose.ui.Modifier
4721
import androidx.compose.ui.graphics.vector.ImageVector
4822
import androidx.compose.ui.platform.LocalContext
@@ -55,6 +29,7 @@ import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.isDefaul
5529
import app.revanced.manager.patcher.aapt.Aapt
5630
import app.revanced.manager.ui.component.AppTopBar
5731
import app.revanced.manager.ui.component.AutoUpdatesDialog
32+
import app.revanced.manager.ui.component.AvailableUpdateDialog
5833
import app.revanced.manager.ui.component.NotificationCard
5934
import app.revanced.manager.ui.component.bundle.BundleItem
6035
import app.revanced.manager.ui.component.bundle.BundleTopBar
@@ -113,6 +88,20 @@ fun DashboardScreen(
11388
)
11489
}
11590

91+
var showDialog by rememberSaveable { mutableStateOf(vm.prefs.showManagerUpdateDialogOnLaunch.getBlocking()) }
92+
val availableUpdate by remember {
93+
derivedStateOf { vm.updatedManagerVersion.takeIf { showDialog } }
94+
}
95+
96+
availableUpdate?.let { version ->
97+
AvailableUpdateDialog(
98+
onDismiss = { showDialog = false },
99+
setShowManagerUpdateDialogOnLaunch = vm::setShowManagerUpdateDialogOnLaunch,
100+
onConfirm = onUpdateClick,
101+
newVersion = version
102+
)
103+
}
104+
116105
Scaffold(
117106
topBar = {
118107
if (bundlesSelectable) {
@@ -154,6 +143,23 @@ fun DashboardScreen(
154143
AppTopBar(
155144
title = stringResource(R.string.app_name),
156145
actions = {
146+
if (!vm.updatedManagerVersion.isNullOrEmpty()) {
147+
IconButton(
148+
onClick = onUpdateClick,
149+
) {
150+
BadgedBox(
151+
badge = {
152+
Badge(
153+
// A size value above 6.dp forces the Badge icon to be closer to the center, fixing a clipping issue
154+
modifier = Modifier.size(7.dp),
155+
containerColor = MaterialTheme.colorScheme.primary,
156+
)
157+
}
158+
) {
159+
Icon(Icons.Outlined.Update, stringResource(R.string.update))
160+
}
161+
}
162+
}
157163
IconButton(onClick = onSettingsClick) {
158164
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
159165
}
@@ -230,23 +236,7 @@ fun DashboardScreen(
230236
}
231237
)
232238
}
233-
} else null,
234-
vm.updatedManagerVersion?.let {
235-
{
236-
NotificationCard(
237-
text = stringResource(R.string.update_available_dialog_description, it),
238-
icon = Icons.Outlined.Update,
239-
actions = {
240-
TextButton(onClick = vm::dismissUpdateDialog) {
241-
Text(stringResource(R.string.dismiss))
242-
}
243-
TextButton(onClick = onUpdateClick) {
244-
Text(stringResource(R.string.show))
245-
}
246-
}
247-
)
248-
}
249-
}
239+
} else null
250240
)
251241

252242
HorizontalPager(

app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ fun UpdatesSettingsScreen(
6464
headline = R.string.update_checking_manager,
6565
description = R.string.update_checking_manager_description
6666
)
67+
68+
BooleanItem(
69+
preference = vm.showManagerUpdateDialogOnLaunch,
70+
headline = R.string.show_manager_update_dialog_on_launch,
71+
description = R.string.update_checking_manager_description
72+
)
6773
}
6874
}
6975
}

app/src/main/java/app/revanced/manager/ui/viewmodel/DashboardViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ class DashboardViewModel(
6464
}
6565
}
6666

67+
fun setShowManagerUpdateDialogOnLaunch(value: Boolean) {
68+
viewModelScope.launch {
69+
prefs.showManagerUpdateDialogOnLaunch.update(value)
70+
}
71+
}
72+
6773
fun applyAutoUpdatePrefs(manager: Boolean, patches: Boolean) = viewModelScope.launch {
6874
prefs.firstLaunch.update(false)
6975

app/src/main/java/app/revanced/manager/ui/viewmodel/UpdatesSettingsViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class UpdatesSettingsViewModel(
1414
private val reVancedAPI: ReVancedAPI,
1515
) : ViewModel() {
1616
val managerAutoUpdates = prefs.managerAutoUpdates
17+
val showManagerUpdateDialogOnLaunch = prefs.showManagerUpdateDialogOnLaunch
1718

1819
suspend fun checkForUpdates(): Boolean {
1920
uiSafe(app, R.string.failed_to_check_updates, "Failed to check for updates") {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,4 +367,8 @@
367367
<string name="add_patch_bundle">Add patch bundle</string>
368368
<string name="bundle_url">Bundle URL</string>
369369
<string name="auto_update">Auto update</string>
370+
<string name="never_show_again">Never show again</string>
371+
<string name="show_manager_update_dialog_on_launch">Show update message on launch</string>
372+
<string name="show_manager_update_dialog_on_launch_description">Shows a popup notification whenever there is a new update available on launch.</string>
373+
370374
</resources>

0 commit comments

Comments
 (0)