@@ -2,21 +2,40 @@ package app.revanced.manager.compose.ui.screen
22
33import androidx.activity.compose.rememberLauncherForActivityResult
44import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
5- import androidx.compose.foundation.layout.Column
6- import androidx.compose.foundation.layout.fillMaxSize
7- import androidx.compose.foundation.layout.padding
8- import androidx.compose.material3.Button
9- import androidx.compose.material3.ExperimentalMaterial3Api
10- import androidx.compose.material3.MaterialTheme
11- import androidx.compose.material3.Text
5+ import androidx.compose.animation.AnimatedVisibility
6+ import androidx.compose.foundation.background
7+ import androidx.compose.foundation.layout.*
8+ import androidx.compose.foundation.shape.RoundedCornerShape
9+ import androidx.compose.material.icons.Icons
10+ import androidx.compose.material.icons.filled.Cancel
11+ import androidx.compose.material.icons.filled.CheckCircle
12+ import androidx.compose.material.icons.filled.KeyboardArrowDown
13+ import androidx.compose.material.icons.filled.KeyboardArrowUp
14+ import androidx.compose.material.icons.outlined.HelpOutline
15+ import androidx.compose.material.icons.outlined.MoreVert
16+ import androidx.compose.material3.*
1217import androidx.compose.runtime.Composable
18+ import androidx.compose.runtime.getValue
19+ import androidx.compose.runtime.mutableStateOf
20+ import androidx.compose.runtime.saveable.rememberSaveable
21+ import androidx.compose.runtime.setValue
22+ import androidx.compose.ui.Alignment
1323import androidx.compose.ui.Modifier
24+ import androidx.compose.ui.draw.clip
1425import androidx.compose.ui.res.stringResource
26+ import androidx.compose.ui.semantics.contentDescription
27+ import androidx.compose.ui.semantics.semantics
28+ import androidx.compose.ui.text.style.TextOverflow
29+ import androidx.compose.ui.unit.Dp
30+ import androidx.compose.ui.unit.dp
1531import app.revanced.manager.compose.R
32+ import app.revanced.manager.compose.patcher.worker.StepGroup
33+ import app.revanced.manager.compose.patcher.worker.StepStatus
1634import app.revanced.manager.compose.ui.component.AppScaffold
1735import app.revanced.manager.compose.ui.component.AppTopBar
1836import app.revanced.manager.compose.ui.viewmodel.InstallerScreenViewModel
1937import app.revanced.manager.compose.util.APK_MIMETYPE
38+ import kotlin.math.floor
2039
2140@OptIn(ExperimentalMaterial3Api ::class )
2241@Composable
@@ -31,6 +50,14 @@ fun InstallerScreen(
3150 AppTopBar (
3251 title = stringResource(R .string.installer),
3352 onBackClick = onBackClick,
53+ actions = {
54+ IconButton (onClick = {}) {
55+ Icon (Icons .Outlined .HelpOutline , stringResource(R .string.help))
56+ }
57+ IconButton (onClick = {}) {
58+ Icon (Icons .Outlined .MoreVert , stringResource(R .string.more))
59+ }
60+ }
3461 )
3562 }
3663 ) { paddingValues ->
@@ -40,34 +67,139 @@ fun InstallerScreen(
4067 .fillMaxSize()
4168 ) {
4269 vm.stepGroups.forEach {
43- Column {
44- Text (
45- text = " ${stringResource(it.name)} : ${it.status} " ,
46- style = MaterialTheme .typography.titleLarge
47- )
70+ InstallGroup (it)
71+ }
72+ Spacer (modifier = Modifier .weight(1f ))
73+ Row (
74+ verticalAlignment = Alignment .Bottom ,
75+ horizontalArrangement = Arrangement .spacedBy(12 .dp, Alignment .End ),
76+ modifier = Modifier
77+ .fillMaxWidth()
78+ .padding(start = 16 .dp, end = 16 .dp, bottom = 16 .dp)
79+ ) {
80+ Button (
81+ onClick = { exportApkLauncher.launch(" ${vm.packageName} .apk" ) },
82+ enabled = vm.canInstall
83+ ) {
84+ Text (stringResource(R .string.export_app))
85+ }
4886
49- it.steps.forEach {
50- Text (
51- text = " ${it.name} : ${it.status} " ,
52- style = MaterialTheme .typography.titleMedium
53- )
54- }
87+ Button (
88+ onClick = vm::installApk,
89+ enabled = vm.canInstall
90+ ) {
91+ Text (stringResource(R .string.install_app))
5592 }
5693 }
94+ }
95+ }
96+ }
5797
58- Button (
59- onClick = vm::installApk,
60- enabled = vm.canInstall
61- ) {
62- Text (stringResource(R .string.install_app))
98+ // Credits: https://github.com/Aliucord/AliucordManager/blob/main/app/src/main/kotlin/com/aliucord/manager/ui/component/installer/InstallGroup.kt
99+
100+ @Composable
101+ fun InstallGroup (group : StepGroup ) {
102+ var expanded by rememberSaveable { mutableStateOf(true ) }
103+ Column (
104+ modifier = Modifier
105+ .padding(start = 16 .dp, end = 16 .dp, top = 8 .dp, bottom = 8 .dp)
106+ .fillMaxWidth()
107+ .clip(RoundedCornerShape (16 .dp))
108+ .run {
109+ if (expanded) {
110+ background(MaterialTheme .colorScheme.secondaryContainer)
111+ } else this
63112 }
113+ ) {
114+ Row (
115+ verticalAlignment = Alignment .CenterVertically ,
116+ horizontalArrangement = Arrangement .spacedBy(12 .dp),
117+ modifier = Modifier
118+ .fillMaxWidth()
119+ .padding(start = 16 .dp, end = 16 .dp)
120+ .run { if (expanded) {
121+ background(MaterialTheme .colorScheme.secondaryContainer)
122+ } else
123+ background(MaterialTheme .colorScheme.surface)
124+ }
125+ ) {
126+ StepIcon (group.status, 24 .dp)
127+
128+ Text (text = stringResource(group.name), style = MaterialTheme .typography.titleMedium)
129+
130+ Spacer (modifier = Modifier .weight(1f ))
64131
65- Button (
66- onClick = { exportApkLauncher.launch(" ${vm.packageName} .apk" ) },
67- enabled = vm.canInstall
132+ IconButton (onClick = { expanded = ! expanded }) {
133+ if (expanded) {
134+ Icon (
135+ imageVector = Icons .Filled .KeyboardArrowUp ,
136+ contentDescription = " collapse"
137+ )
138+ } else {
139+ Icon (
140+ imageVector = Icons .Filled .KeyboardArrowDown ,
141+ contentDescription = " expand"
142+ )
143+ }
144+ }
145+ }
146+
147+ AnimatedVisibility (visible = expanded) {
148+ Column (
149+ verticalArrangement = Arrangement .spacedBy(16 .dp),
150+ modifier = Modifier
151+ .background(MaterialTheme .colorScheme.background.copy(0.6f ))
152+ .fillMaxWidth()
153+ .padding(16 .dp)
154+ .padding(start = 4 .dp)
68155 ) {
69- Text (stringResource(R .string.export_app))
156+ group.steps.forEach {
157+ Row (
158+ verticalAlignment = Alignment .CenterVertically ,
159+ horizontalArrangement = Arrangement .spacedBy(16 .dp),
160+ ) {
161+ StepIcon (it.status, size = 18 .dp)
162+
163+ Text (
164+ text = it.name,
165+ style = MaterialTheme .typography.titleSmall,
166+ maxLines = 1 ,
167+ overflow = TextOverflow .Ellipsis ,
168+ modifier = Modifier .weight(1f , true ),
169+ )
170+ }
171+ }
70172 }
71173 }
72174 }
73- }
175+ }
176+
177+ @Composable
178+ fun StepIcon (status : StepStatus , size : Dp ) {
179+ val strokeWidth = Dp (floor(size.value / 10 ) + 1 )
180+
181+ when (status) {
182+ StepStatus .COMPLETED -> Icon (
183+ Icons .Filled .CheckCircle ,
184+ contentDescription = " success" ,
185+ tint = MaterialTheme .colorScheme.surfaceTint,
186+ modifier = Modifier .size(size)
187+ )
188+
189+ StepStatus .FAILURE -> Icon (
190+ Icons .Filled .Cancel ,
191+ contentDescription = " failed" ,
192+ tint = MaterialTheme .colorScheme.error,
193+ modifier = Modifier .size(size)
194+ )
195+
196+ StepStatus .WAITING -> CircularProgressIndicator (
197+ strokeWidth = strokeWidth,
198+ modifier = Modifier
199+ .size(size)
200+ .semantics {
201+ contentDescription = " waiting"
202+ }
203+ )
204+ }
205+ }
0 commit comments