This commit is contained in:
chenjuntao
2025-04-08 17:33:06 +08:00
parent 0e9301f4dc
commit cef4526b35
8 changed files with 85 additions and 48 deletions

View File

@ -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?) {

View File

@ -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<PermissionResult> = 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
}
}
}

View File

@ -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

View File

@ -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<PermissionResult?>(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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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