From c756db870c3f4b2d6db055b6b2725ae36de3d0b2 Mon Sep 17 00:00:00 2001 From: Baidaidai_GFWD <1302064396@qq.com> Date: Thu, 9 Apr 2026 15:25:37 +0800 Subject: [PATCH 1/2] feat(ui): Add Shizuku action icons --- .../main/res/drawable/material_shizuku_icon.xml | 14 ++++++++++++++ .../main/res/drawable/material_symbols_check.xml | 10 ++++++++++ .../res/drawable/material_symbols_play_arrow.xml | 10 ++++++++++ 3 files changed, 34 insertions(+) create mode 100644 app/src/main/res/drawable/material_shizuku_icon.xml create mode 100644 app/src/main/res/drawable/material_symbols_check.xml create mode 100644 app/src/main/res/drawable/material_symbols_play_arrow.xml diff --git a/app/src/main/res/drawable/material_shizuku_icon.xml b/app/src/main/res/drawable/material_shizuku_icon.xml new file mode 100644 index 0000000..98c29ac --- /dev/null +++ b/app/src/main/res/drawable/material_shizuku_icon.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/material_symbols_check.xml b/app/src/main/res/drawable/material_symbols_check.xml new file mode 100644 index 0000000..280f0bd --- /dev/null +++ b/app/src/main/res/drawable/material_symbols_check.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/material_symbols_play_arrow.xml b/app/src/main/res/drawable/material_symbols_play_arrow.xml new file mode 100644 index 0000000..9bc6b5d --- /dev/null +++ b/app/src/main/res/drawable/material_symbols_play_arrow.xml @@ -0,0 +1,10 @@ + + + From 928719f4b420c9995de31556d00c9c320a22ae90 Mon Sep 17 00:00:00 2001 From: Baidaidai_GFWD <1302064396@qq.com> Date: Thu, 9 Apr 2026 15:33:37 +0800 Subject: [PATCH 2/2] refactor!: Restructure Shizuku ADB screen components Extract Shizuku ADB screen UI pieces into a dedicated components file. Update the screen flow and add a simple top app bar for the Shizuku auth activity. --- .../rootless_store/ShizukuActivity.kt | 15 +- .../ShizukuAdbScreenNecessaryComponents.kt | 220 ++++++++++++++++++ .../ui/screens/ShizukuAdbScreen.kt | 199 +++++++--------- 3 files changed, 312 insertions(+), 122 deletions(-) create mode 100644 app/src/main/java/com/baidaidai/rootless_store/components/shizukuAdbScreen/ShizukuAdbScreenNecessaryComponents.kt diff --git a/app/src/main/java/com/baidaidai/rootless_store/ShizukuActivity.kt b/app/src/main/java/com/baidaidai/rootless_store/ShizukuActivity.kt index b2d2f46..a6824d6 100644 --- a/app/src/main/java/com/baidaidai/rootless_store/ShizukuActivity.kt +++ b/app/src/main/java/com/baidaidai/rootless_store/ShizukuActivity.kt @@ -4,8 +4,11 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -21,7 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class ShizukuActivity: ComponentActivity() { - @OptIn(ExperimentalMaterial3ExpressiveApi::class) + @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -34,7 +37,15 @@ class ShizukuActivity: ComponentActivity() { } } RootlessStoreTheme { - Scaffold { contentPadding -> + Scaffold( + topBar = { + TopAppBar( + title = { + Text("Shizuku Auth") + } + ) + } + ) { contentPadding -> if (sharedEvent is RootlessStoreError){ StartScreenErrorDialog(shizukuAdbScreenViewModel, sharedEvent) } diff --git a/app/src/main/java/com/baidaidai/rootless_store/components/shizukuAdbScreen/ShizukuAdbScreenNecessaryComponents.kt b/app/src/main/java/com/baidaidai/rootless_store/components/shizukuAdbScreen/ShizukuAdbScreenNecessaryComponents.kt new file mode 100644 index 0000000..b04ef58 --- /dev/null +++ b/app/src/main/java/com/baidaidai/rootless_store/components/shizukuAdbScreen/ShizukuAdbScreenNecessaryComponents.kt @@ -0,0 +1,220 @@ +package com.baidaidai.rootless_store.components.shizukuAdbScreen + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.baidaidai.rootless_store.R + +object ShizukuAdbScreenNecessaryComponents { + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun ShizukuAdbScreenModelSheet( + remainderTime: Int, + onDismissRequest: ()-> Unit, + onCloseButtonClick: ()-> Unit, + onReturnButtonClick: ()-> Unit + ){ + ModalBottomSheet( + onDismissRequest = onDismissRequest, + sheetState = rememberModalBottomSheetState(), + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .padding(top = 8.dp, bottom = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .size(84.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primaryContainer), + contentAlignment = Alignment.Center + ) { + Icon( + painterResource(R.drawable.material_symbols_check), + contentDescription = null, + tint = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.size(40.dp) + ) + } + + Spacer(Modifier.height(16.dp)) + + Text( + text = "All done", + style = MaterialTheme.typography.headlineSmall, + color = MaterialTheme.colorScheme.onSurface, + textAlign = TextAlign.Center + ) + + Spacer(Modifier.height(8.dp)) + + Text( + text = "Returning to Home in $remainderTime s", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center + ) + + Spacer(Modifier.height(20.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + OutlinedButton( + onClick = onCloseButtonClick, + modifier = Modifier.weight(1f) + ) { + Text("Close") + } + Button( + onClick = onReturnButtonClick, + modifier = Modifier.weight(1f) + ) { + Text("Return now") + } + } + } + } + } + + @OptIn(ExperimentalMaterial3ExpressiveApi::class) + @Composable + fun ShizukuAdbScreenActionCard( + step: String, + title: String, + description: String, + targetStatus: Boolean, + onClick: () -> Unit + ){ + Card( + modifier = Modifier + .fillMaxWidth(), + elevation = CardDefaults.cardElevation(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainer + ) + ) { + Column( + modifier = Modifier + .padding(20.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Column{ + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .height(60.dp) + ){ + Column{ + Text( + text = step, + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.primary + ) + Text( + text = title, + style = MaterialTheme.typography.titleMediumEmphasized + ) + } + Button( + onClick = onClick, + modifier = Modifier.size(48.dp), + contentPadding = PaddingValues(0.dp) + ) { + Icon( + painter = if (targetStatus){ + painterResource(R.drawable.material_symbols_check) + }else{ + painterResource(R.drawable.material_symbols_play_arrow) + }, + contentDescription = "Start", + modifier = Modifier.size(24.dp) + ) + } + } + Spacer(modifier = Modifier.height(15.dp)) + HorizontalDivider() + Spacer(modifier = Modifier.height(15.dp)) + Text( + text = description, + style = MaterialTheme.typography.bodyMediumEmphasized + ) + } + } + } + } + + @OptIn(ExperimentalMaterial3ExpressiveApi::class) + @Composable + fun ShizukuAdbScreenOverviewCard(){ + OutlinedCard( + modifier = Modifier + .fillMaxWidth(), + elevation = CardDefaults.cardElevation(), + ) { + Column( + modifier = Modifier + .padding(24.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Row( + modifier = Modifier + .height(50.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ){ + Text( + text = "Shizuku Access", + style = MaterialTheme.typography.titleLargeEmphasized + ) + Icon( + painterResource(R.drawable.material_shizuku_icon), + contentDescription = "Shizuku Icon", + tint = MaterialTheme.colorScheme.primary, + ) + } + Text( + text = "Rootless Store uses Shizuku’s ADB shell for some features so please request ADB authorization.\nFirst then connect to Shizuku.", + style = MaterialTheme.typography.bodyMedium + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/baidaidai/rootless_store/ui/screens/ShizukuAdbScreen.kt b/app/src/main/java/com/baidaidai/rootless_store/ui/screens/ShizukuAdbScreen.kt index 2913202..9818a89 100644 --- a/app/src/main/java/com/baidaidai/rootless_store/ui/screens/ShizukuAdbScreen.kt +++ b/app/src/main/java/com/baidaidai/rootless_store/ui/screens/ShizukuAdbScreen.kt @@ -4,33 +4,32 @@ import android.app.Activity import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.Button -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text +import androidx.compose.material3.LinearWavyProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.baidaidai.rootless_store.domain.error.RootlessStoreError +import com.baidaidai.rootless_store.components.shizukuAdbScreen.ShizukuAdbScreenNecessaryComponents.ShizukuAdbScreenActionCard +import com.baidaidai.rootless_store.components.shizukuAdbScreen.ShizukuAdbScreenNecessaryComponents.ShizukuAdbScreenModelSheet +import com.baidaidai.rootless_store.components.shizukuAdbScreen.ShizukuAdbScreenNecessaryComponents.ShizukuAdbScreenOverviewCard import com.baidaidai.rootless_store.ui.model.RootlessStoreShizukuAdbScreenViewModel -import com.baidaidai.rootless_store.ui.theme.RootlessStoreTheme +import kotlinx.coroutines.delay +@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable fun ShizukuAdbScreen( contentPaddingValues: PaddingValues, @@ -42,124 +41,84 @@ fun ShizukuAdbScreen( val context = LocalContext.current val activity = context as? Activity + var sheetState by remember { mutableStateOf(false) } + var remainderTime by remember { mutableIntStateOf(6) } + LaunchedEffect(endpointActived) { if (endpointActived) { + sheetState = true + while (remainderTime > 0){ + delay(1000) + remainderTime-- + } activity?.finish() } } - LazyColumn( - modifier = Modifier - .padding(contentPaddingValues) - .padding(horizontal = 15.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(vertical = 15.dp) - ) { - item { - ShizukuAdbScreenOverviewCard() - } - item { - ShizukuAdbScreenActionCard( - step = "Step 1", - title = "Request ADB Authorization", - description = "Grant Rootless Store the ADB authorization it needs before entering the shell flow. Finish this step first so the following connection step can continue normally.", - buttonText = if (shizukuActived) { - "Actived ✓" - } else { - "Request Authorization" - }, - onClick = { - shizukuAdbScreenViewModel.activeShizuku() - } - ) - } - item { - ShizukuAdbScreenActionCard( - step = "Step 2", - title = "Connect to Shizuku UserActivity", - description = "After ADB authorization is ready, open Shizuku's UserActivity and enter the ADB shell session used by Rootless Store. This is the final step before the user can continue with the shell-based workflow.", - buttonText = if (endpointActived) { - "Actived ✓" - } else { - "Connect to Shizuku" - }, - onClick = { - shizukuAdbScreenViewModel.activeShizukuEndpoint() - } - ) - } - } -} - -@Composable -private fun ShizukuAdbScreenOverviewCard(){ - Card( - modifier = Modifier - .fillMaxWidth(), - elevation = CardDefaults.cardElevation(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainer - ) - ) { - Column( - modifier = Modifier - .padding(24.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - Text( - text = "Rootless Store ADB", - style = MaterialTheme.typography.titleMedium - ) - Text( - text = "Some Rootless Store features depend on an ADB shell instead of a full root shell. This page helps the user complete the required setup in the correct order: request ADB authorization first, then connect into Shizuku's ADB shell environment.", - style = MaterialTheme.typography.bodyMedium - ) - } - } -} - -@Composable -private fun ShizukuAdbScreenActionCard( - step: String, - title: String, - description: String, - buttonText: String, - onClick: () -> Unit -){ - Card( - modifier = Modifier - .fillMaxWidth(), - elevation = CardDefaults.cardElevation(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceContainer + if (sheetState){ + ShizukuAdbScreenModelSheet( + remainderTime = remainderTime, + onDismissRequest = { sheetState = false}, + onCloseButtonClick = { sheetState = false }, + onReturnButtonClick = { activity?.finish() } ) - ) { - Column( + }else{ + LazyColumn( modifier = Modifier - .padding(24.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) + .padding(contentPaddingValues) + .padding(horizontal = 15.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + contentPadding = PaddingValues(vertical = 15.dp) ) { - Text( - text = step, - style = MaterialTheme.typography.labelMedium, - color = MaterialTheme.colorScheme.primary - ) - Text( - text = title, - style = MaterialTheme.typography.titleMedium - ) - Text( - text = description, - style = MaterialTheme.typography.bodyMedium - ) - HorizontalDivider() - Button( - onClick = onClick, - modifier = Modifier - .fillMaxWidth() - ) { - Text(buttonText) + item { + ShizukuAdbScreenOverviewCard() + } + item { + Column( + modifier = Modifier + .fillMaxWidth() + ) { + Spacer(modifier = Modifier.height(10.dp)) + LinearWavyProgressIndicator( + progress = { + if (endpointActived) { + 1f + }else if (shizukuActived){ + 0.5f + }else{ + 0.05f + } + }, + amplitude = {1f}, + waveSpeed = 10.dp, + modifier = Modifier + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(10.dp)) + } + } + item { + ShizukuAdbScreenActionCard( + step = "Step 1", + title = "Request Shizuku Auth", + description = "Grant ADB authorization so Rootless Store can start the shell workflow and unlock the next step", + targetStatus = shizukuActived, + onClick = { + shizukuAdbScreenViewModel.activeShizuku() + } + ) + } + item { + ShizukuAdbScreenActionCard( + step = "Step 2", + title = "Connect to Shizuku", + description = "After authorization is ready open Shizuku and enter the ADB shell session to finish setup and continue", + targetStatus = endpointActived, + onClick = { + shizukuAdbScreenViewModel.activeShizukuEndpoint() + } + ) } } }