@@ -5,19 +5,17 @@ import androidx.compose.animation.core.spring
55import androidx.compose.foundation.layout.Arrangement
66import androidx.compose.foundation.layout.Column
77import androidx.compose.foundation.layout.ColumnScope
8- import androidx.compose.foundation.layout.Row
9- import androidx.compose.foundation.layout.Spacer
108import androidx.compose.foundation.layout.fillMaxSize
119import androidx.compose.foundation.layout.fillMaxWidth
1210import androidx.compose.foundation.layout.padding
1311import androidx.compose.foundation.rememberScrollState
1412import androidx.compose.foundation.verticalScroll
1513import androidx.compose.material.icons.Icons
14+ import androidx.compose.material.icons.outlined.Cancel
15+ import androidx.compose.material.icons.outlined.InstallMobile
1616import androidx.compose.material.icons.outlined.Update
1717import androidx.compose.material3.AlertDialog
18- import androidx.compose.material3.Button
1918import androidx.compose.material3.ExperimentalMaterial3Api
20- import androidx.compose.material3.HorizontalDivider
2119import androidx.compose.material3.Icon
2220import androidx.compose.material3.LinearProgressIndicator
2321import androidx.compose.material3.MaterialTheme
@@ -28,16 +26,15 @@ import androidx.compose.material3.TopAppBarDefaults
2826import androidx.compose.material3.rememberTopAppBarState
2927import androidx.compose.runtime.Composable
3028import androidx.compose.runtime.Stable
31- import androidx.compose.ui.Alignment
3229import androidx.compose.ui.Modifier
3330import androidx.compose.ui.input.nestedscroll.nestedScroll
3431import androidx.compose.ui.platform.LocalContext
3532import androidx.compose.ui.res.stringResource
3633import androidx.compose.ui.unit.dp
37- import app.revanced.manager.BuildConfig
3834import app.revanced.manager.R
3935import app.revanced.manager.network.dto.ReVancedAsset
4036import app.revanced.manager.ui.component.AppTopBar
37+ import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
4138import app.revanced.manager.ui.component.settings.Changelog
4239import app.revanced.manager.ui.viewmodel.UpdateViewModel
4340import app.revanced.manager.ui.viewmodel.UpdateViewModel.State
@@ -60,37 +57,81 @@ fun UpdateScreen(
6057 Scaffold (
6158 topBar = {
6259 AppTopBar (
63- title = stringResource(R .string.update),
60+ title = {
61+ Column {
62+ Text (stringResource(vm.state.title))
63+
64+ if (vm.state == State .DOWNLOADING ) {
65+ Text (
66+ text = " ${vm.downloadedSize.div(1000000 )} MB / ${
67+ vm.totalSize.div(1000000 )
68+ } MB (${vm.downloadProgress.times(100 ).toInt()} %)" ,
69+ style = MaterialTheme .typography.bodySmall,
70+ color = MaterialTheme .colorScheme.outline
71+ )
72+ }
73+ }
74+ },
6475 scrollBehavior = scrollBehavior,
6576 onBackClick = onBackClick
6677 )
6778 },
79+ floatingActionButton = {
80+ val buttonConfig = when (vm.state) {
81+ State .CAN_DOWNLOAD -> Triple (
82+ { vm.downloadUpdate() },
83+ R .string.download,
84+ Icons .Outlined .InstallMobile
85+ )
86+
87+ State .DOWNLOADING -> Triple (onBackClick, R .string.cancel, Icons .Outlined .Cancel )
88+ State .CAN_INSTALL -> Triple (
89+ { vm.installUpdate() },
90+ R .string.install_app,
91+ Icons .Outlined .InstallMobile
92+ )
93+
94+ else -> null
95+ }
96+
97+ buttonConfig?.let { (onClick, textRes, icon) ->
98+ HapticExtendedFloatingActionButton (
99+ onClick = onClick::invoke,
100+ icon = { Icon (icon, null ) },
101+ text = { Text (stringResource(textRes)) }
102+ )
103+ }
104+
105+ },
68106 modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection),
69107 ) { paddingValues ->
70- AnimatedVisibility (visible = vm.showInternetCheckDialog) {
71- MeteredDownloadConfirmationDialog (
72- onDismiss = { vm.showInternetCheckDialog = false },
73- onDownloadAnyways = { vm.downloadUpdate(true ) }
74- )
75- }
76108 Column (
77109 modifier = Modifier
78- .fillMaxSize()
79- .padding(paddingValues)
80- .padding(vertical = 16 .dp, horizontal = 24 .dp)
81- .verticalScroll(rememberScrollState()),
82- verticalArrangement = Arrangement .spacedBy(32 .dp)
110+ .padding(paddingValues),
83111 ) {
84- Header (
85- vm.state,
86- vm.releaseInfo,
87- DownloadData (vm.downloadProgress, vm.downloadedSize, vm.totalSize)
88- )
89- vm.releaseInfo?.let { changelog ->
90- HorizontalDivider ()
91- Changelog (changelog)
92- } ? : Spacer (modifier = Modifier .weight(1f ))
93- Buttons (vm.state, vm::downloadUpdate, vm::installUpdate, onBackClick)
112+ if (vm.state == State .DOWNLOADING )
113+ LinearProgressIndicator (
114+ progress = { vm.downloadProgress },
115+ modifier = Modifier .fillMaxWidth(),
116+ )
117+
118+ AnimatedVisibility (visible = vm.showInternetCheckDialog) {
119+ MeteredDownloadConfirmationDialog (
120+ onDismiss = { vm.showInternetCheckDialog = false },
121+ onDownloadAnyways = { vm.downloadUpdate(true ) }
122+ )
123+ }
124+ Column (
125+ modifier = Modifier
126+ .fillMaxSize()
127+ .padding(16 .dp)
128+ .verticalScroll(rememberScrollState()),
129+ verticalArrangement = Arrangement .spacedBy(32 .dp)
130+ ) {
131+ vm.releaseInfo?.let { changelog ->
132+ Changelog (changelog)
133+ }
134+ }
94135 }
95136 }
96137}
@@ -123,58 +164,6 @@ private fun MeteredDownloadConfirmationDialog(
123164 )
124165}
125166
126- @Composable
127- private fun Header (state : State , releaseInfo : ReVancedAsset ? , downloadData : DownloadData ) {
128- Column (verticalArrangement = Arrangement .spacedBy(16 .dp)) {
129- Text (
130- text = stringResource(state.title),
131- style = MaterialTheme .typography.headlineMedium
132- )
133- if (state == State .CAN_DOWNLOAD ) {
134- Column {
135- Text (
136- text = stringResource(
137- id = R .string.current_version,
138- BuildConfig .VERSION_NAME
139- ),
140- style = MaterialTheme .typography.bodyMedium,
141- color = MaterialTheme .colorScheme.onSurfaceVariant
142- )
143- releaseInfo?.version?.let {
144- Text (
145- text = stringResource(
146- R .string.new_version,
147- it.replace(" v" , " " )
148- ),
149- style = MaterialTheme .typography.bodyMedium,
150- color = MaterialTheme .colorScheme.onSurfaceVariant
151- )
152- }
153- }
154- } else if (state == State .DOWNLOADING ) {
155- LinearProgressIndicator (
156- progress = { downloadData.downloadProgress },
157- modifier = Modifier .fillMaxWidth(),
158- )
159- Text (
160- text =
161- " ${downloadData.downloadedSize.div(1000000 )} MB / ${
162- downloadData.totalSize.div(
163- 1000000
164- )
165- } MB (${
166- downloadData.downloadProgress.times(
167- 100
168- ).toInt()
169- } %)" ,
170- style = MaterialTheme .typography.bodyMedium,
171- color = MaterialTheme .colorScheme.outline,
172- modifier = Modifier .align(Alignment .CenterHorizontally )
173- )
174- }
175- }
176- }
177-
178167@Composable
179168private fun ColumnScope.Changelog (releaseInfo : ReVancedAsset ) {
180169 val scrollState = rememberScrollState()
@@ -205,40 +194,4 @@ private fun ColumnScope.Changelog(releaseInfo: ReVancedAsset) {
205194 publishDate = releaseInfo.createdAt.relativeTime(LocalContext .current)
206195 )
207196 }
208- }
209-
210- @Composable
211- private fun Buttons (
212- state : State ,
213- onDownloadClick : () -> Unit ,
214- onInstallClick : () -> Unit ,
215- onBackClick : () -> Unit
216- ) {
217- Row (modifier = Modifier .fillMaxWidth()) {
218- if (state.showCancel) {
219- TextButton (
220- onClick = onBackClick,
221- ) {
222- Text (text = stringResource(R .string.cancel))
223- }
224- }
225- Spacer (modifier = Modifier .weight(1f ))
226- if (state == State .CAN_DOWNLOAD ) {
227- Button (onClick = onDownloadClick) {
228- Text (text = stringResource(R .string.update))
229- }
230- } else if (state == State .CAN_INSTALL ) {
231- Button (
232- onClick = onInstallClick
233- ) {
234- Text (text = stringResource(R .string.install_app))
235- }
236- }
237- }
238- }
239-
240- data class DownloadData (
241- val downloadProgress : Float ,
242- val downloadedSize : Long ,
243- val totalSize : Long
244- )
197+ }
0 commit comments