diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/compose/ApkManagerActivity.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/compose/ApkManagerActivity.kt index aabd95b04c..b0bd95de68 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/compose/ApkManagerActivity.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/compose/ApkManagerActivity.kt @@ -7,8 +7,8 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier -import com.gh.gamecenter.apkmanager.data.ui.AppManagerScreen -import com.gh.gamecenter.apkmanager.data.ui.theme.CustomAppTheme +import com.gh.gamecenter.apkmanager.ui.AppManagerScreen +import com.gh.gamecenter.apkmanager.ui.theme.CustomAppTheme class ApkManagerActivity: AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/domain/CheckStoragePermissionUseCase.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/domain/CheckStoragePermissionUseCase.kt new file mode 100644 index 0000000000..0a8ddcc7bd --- /dev/null +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/domain/CheckStoragePermissionUseCase.kt @@ -0,0 +1,28 @@ +package com.gh.gamecenter.apkmanager.domain + +import android.Manifest +import android.app.Activity +import android.content.Context +import android.content.pm.PackageManager +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +data class PermissionResult(val isGranted: Boolean, val shouldShowRationale: Boolean) + +class CheckStoragePermissionUseCase(private val context: Context) { + + fun execute(): Flow = flow { + val permission = Manifest.permission.READ_EXTERNAL_STORAGE + val permissionGranted = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED + + if (permissionGranted) { + emit(PermissionResult(isGranted = true, shouldShowRationale = false)) // Permission already granted + } else { + val shouldShowRationale = ActivityCompat.shouldShowRequestPermissionRationale(context as Activity, permission) + emit(PermissionResult(false, shouldShowRationale)) // Permission not granted, signal to UI + } + } + +} \ No newline at end of file diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerScreen.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerScreen.kt similarity index 86% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerScreen.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerScreen.kt index eb8e701a91..74e28094bf 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerScreen.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerScreen.kt @@ -1,4 +1,4 @@ -package com.gh.gamecenter.apkmanager.data.ui +package com.gh.gamecenter.apkmanager.ui import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -19,27 +19,22 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Share import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -59,14 +54,36 @@ import androidx.compose.ui.window.Dialog import androidx.lifecycle.viewmodel.compose.viewModel import com.gh.gamecenter.apkmanager.data.model.InstalledApp -@OptIn(ExperimentalMaterial3Api::class) @Composable fun AppManagerScreen( viewModel: AppManagerViewModel = viewModel(), ) { val uiState by viewModel.uiState.collectAsState() - Scaffold() { paddingValues -> + // 权限请求对话框 + if (!uiState.permissionResult.isGranted) { + AlertDialog( + onDismissRequest = { }, + title = { Text("需要文件管理权限") }, + text = { Text("为了扫描和清理安装包,需要获取文件管理权限。请允许应用访问所有文件。") }, + confirmButton = { + TextButton( + onClick = { +// requestStoragePermission() + } + ) { + Text("去设置") + } + }, + dismissButton = { + TextButton(onClick = { }) { + Text("取消") + } + } + ) + } + + Scaffold { paddingValues -> if (uiState.isLoading) { Box( modifier = Modifier @@ -84,33 +101,6 @@ fun AppManagerScreen( .padding(paddingValues) .background(Color(0xFFF5F5F5)) ) { - // 搜索框 - OutlinedTextField( - value = uiState.searchQuery, - onValueChange = { viewModel.handleIntent(AppManagerIntent.UpdateSearchQuery(it)) }, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp), - placeholder = { Text("找到${uiState.totalCount}个安装包,占用${uiState.totalSize}空间") }, - leadingIcon = { Icon(Icons.Default.Search, contentDescription = "搜索") }, - trailingIcon = { - if (uiState.searchQuery.isNotEmpty()) { - IconButton(onClick = { - viewModel.handleIntent( - AppManagerIntent.UpdateSearchQuery( - "" - ) - ) - }) { - Icon(Icons.Default.Check, contentDescription = "清除") - } - } - }, - singleLine = true, - colors = TextFieldDefaults.colors(), - shape = RoundedCornerShape(4.dp) - ) - // 应用列表 - 使用权重确保它填充剩余空间 LazyColumn( modifier = Modifier diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerViewModel.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerViewModel.kt similarity index 83% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerViewModel.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerViewModel.kt index e841957101..b0deb47e7d 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/AppManagerViewModel.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/AppManagerViewModel.kt @@ -1,10 +1,12 @@ -package com.gh.gamecenter.apkmanager.data.ui +package com.gh.gamecenter.apkmanager.ui import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.gh.gamecenter.apkmanager.data.model.InstalledApp import com.gh.gamecenter.apkmanager.data.repository.AppRepository +import com.gh.gamecenter.apkmanager.domain.CheckStoragePermissionUseCase +import com.gh.gamecenter.apkmanager.domain.PermissionResult import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -13,7 +15,11 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -class AppManagerViewModel : ViewModel() { +class AppManagerViewModel( + private val checkStoragePermissionUseCase: CheckStoragePermissionUseCase) : ViewModel() { + + private val _permissionState = MutableStateFlow(null) + private val repository = AppRepository() private val _uiState = MutableStateFlow(AppManagerUiState()) @@ -30,7 +36,7 @@ class AppManagerViewModel : ViewModel() { selectedSize = selectedSize, totalCount = storageInfo.totalApps, totalSize = storageInfo.totalSize, - isLoading = false + isLoading = false, ) }.stateIn( scope = viewModelScope, @@ -38,6 +44,15 @@ class AppManagerViewModel : ViewModel() { initialValue = AppManagerUiState(isLoading = true) ) + init { + viewModelScope.launch { + checkStoragePermissionUseCase.execute() + .collect { result -> + _permissionState.value = result + } + } + } + // 处理用户操作 fun handleIntent(intent: AppManagerIntent) { when (intent) { @@ -98,7 +113,11 @@ data class AppManagerUiState( val totalCount: Int = 0, val totalSize: String = "0", val searchQuery: String = "", - val isLoading: Boolean = false + val permissionResult: PermissionResult = PermissionResult( + isGranted = false, + shouldShowRationale = true + ), + val isLoading: Boolean = false, ) sealed class AppManagerIntent { diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Color.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Color.kt similarity index 98% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Color.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Color.kt index aeda639fb6..9bcccbfca9 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Color.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package com.gh.gamecenter.apkmanager.data.ui.theme +package com.gh.gamecenter.apkmanager.ui.theme import androidx.compose.ui.graphics.Color diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/CustomTheme.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/CustomTheme.kt similarity index 98% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/CustomTheme.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/CustomTheme.kt index 4c574388ef..8f2f4798bf 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/CustomTheme.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/CustomTheme.kt @@ -1,4 +1,4 @@ -package com.gh.gamecenter.apkmanager.data.ui.theme +package com.gh.gamecenter.apkmanager.ui.theme import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.shape.RoundedCornerShape diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Theme.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Theme.kt similarity index 98% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Theme.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Theme.kt index 2017bf76de..18c6f96ae4 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Theme.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Theme.kt @@ -1,4 +1,4 @@ -package com.gh.gamecenter.apkmanager.data.ui.theme +package com.gh.gamecenter.apkmanager.ui.theme import android.app.Activity import android.os.Build diff --git a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Type.kt b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Type.kt similarity index 94% rename from feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Type.kt rename to feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Type.kt index c9e80bbb9a..3cc844cfb0 100644 --- a/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/data/ui/theme/Type.kt +++ b/feature/apk_manager/src/main/java/com/gh/gamecenter/apkmanager/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package com.gh.gamecenter.apkmanager.data.ui.theme +package com.gh.gamecenter.apkmanager.ui.theme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle