@@ -38,6 +38,8 @@ import com.xayah.core.ui.route.MainRoutes
3838import com.xayah.core.model.OpType
3939import com.xayah.core.util.navigateSingle
4040import com.xayah.core.util.localBackupSaveDir
41+ import com.xayah.core.ui.component.LocalSlotScope
42+ import com.xayah.core.ui.component.confirm
4143import com.xayah.core.ui.component.BodyMediumText
4244import com.xayah.core.ui.component.ProgressButton
4345import com.xayah.core.ui.component.Title
@@ -60,17 +62,32 @@ fun CloudFilesBackupDetailPage(
6062 viewModel : CloudFilesRestoreViewModel = hiltViewModel()
6163) {
6264 val resticProgress by viewModel.resticProgress.collectAsStateWithLifecycle()
65+ val dialogState = LocalSlotScope .current!! .dialogSlot
66+ val coroutineScope = rememberCoroutineScope()
67+ val context = LocalContext .current
68+
6369 LaunchedEffect (accountName) {
6470 viewModel.setCloudEntity(accountName)
6571 }
72+
73+ // 状态变量
74+ val isDeleting = resticProgress.isDeleting
6675 val isRestoring = resticProgress.totalDataTypes > 0 &&
67- resticProgress.currentDataTypeIndex < resticProgress.totalDataTypes
68- val isCompleted = resticProgress.isCompleted
69- val buttonEnabled = ! isRestoring && ! isCompleted
70- val coroutineScope = rememberCoroutineScope()
71- val context = LocalContext .current
76+ resticProgress.currentDataTypeIndex < resticProgress.totalDataTypes &&
77+ ! isDeleting
78+ val isCompleted = resticProgress.isCompleted && ! isDeleting
79+ val deleteButtonEnabled = ! isRestoring && ! isCompleted && ! isDeleting
80+ val restoreButtonEnabled = ! isRestoring && ! isCompleted && ! isDeleting
7281
73- // 计算进度信息
82+ val totalSnapshots = group.backups.size
83+ val totalSteps = totalSnapshots + 1
84+ val currentStep = if (isDeleting) {
85+ resticProgress.currentDataTypeIndex + 1
86+ } else {
87+ 0
88+ }
89+
90+ // 进度信息
7491 val currentProgress = if (resticProgress.bytesTotal > 0 ) {
7592 resticProgress.bytesWritten.toFloat() / resticProgress.bytesTotal
7693 } else 0f
@@ -99,58 +116,97 @@ fun CloudFilesBackupDetailPage(
99116 scrollBehavior = TopAppBarDefaults .exitUntilCollapsedScrollBehavior(rememberTopAppBarState()),
100117 title = " 云端文件备份详情" ,
101118 actions = {
102- ProgressButton (
119+ Column (
103120 modifier = Modifier .fillMaxWidth(),
104- progress = currentProgress,
105- currentIndex = currentIndex,
106- totalCount = totalCount,
107- speed = speed,
108- progressSize = progressSize,
109- enabled = buttonEnabled,
110- text = when {
111- isRestoring -> {
112- val currentDataType = getCurrentDataTypeName(group, currentIndex)
113- " 正在恢复${currentDataType} 快照"
121+ verticalArrangement = Arrangement .spacedBy(SizeTokens .Level8 )
122+ ) {
123+ // 删除按钮
124+ ProgressButton (
125+ modifier = Modifier .fillMaxWidth(),
126+ progress = 0f ,
127+ currentIndex = if (isDeleting) currentStep else 0 ,
128+ totalCount = if (isDeleting) totalSteps else 0 ,
129+ speed = " " ,
130+ progressSize = " " ,
131+ enabled = deleteButtonEnabled,
132+ text = if (isDeleting) {
133+ if (currentStep <= totalSnapshots) {
134+ val currentDataType = getCurrentDataTypeName(group, currentIndex)
135+ " 正在删除${currentDataType} 快照 ($currentStep /$totalSteps )"
136+ } else {
137+ " 正在清理存储空间 ($totalSteps /$totalSteps )"
138+ }
139+ } else {
140+ " 删除云端文件快照"
141+ },
142+ onClick = {
143+ if (! isDeleting) {
144+ coroutineScope.launch {
145+ if (dialogState.confirm(
146+ title = " 提示" ,
147+ text = " 确认删除该文件的所有云端快照?\n 共计 ${group.backups.size} 个快照"
148+ )) {
149+ val success = viewModel.deleteCloudFileSnapshots(group)
150+ if (success) {
151+ navController.popBackStack()
152+ }
153+ }
154+ }
155+ }
114156 }
115- isCompleted -> " 云端文件恢复已完成"
116- else -> " 恢复云端文件快照"
117- },
118- onClick = {
119- if (! isRestoring && ! isCompleted) {
120- coroutineScope.launch {
121- try {
122- Log .d(" CloudFilesRestore" , " 用户点击恢复按钮,开始云端文件恢复流程" )
123- val success = viewModel.restoreFromCloudFileSnapshots(group)
124- Log .d(" CloudFilesRestore" , " 云端文件恢复结果: $success " )
125-
126- if (success) {
127- Log .d(" CloudFilesRestore" , " 云端文件恢复成功,准备读取备份目录" )
128- val backupDir = " ${context.localBackupSaveDir()} /restore/"
129- Log .d(" CloudFilesRestore" , " 导航到文件恢复页面,备份目录: $backupDir " )
130- viewModel.refreshLocalDatabase(backupDir)
131-
132- // 在数据库刷新完成后计算文件大小
133- viewModel.calculateSizesForActivatedMedia()
134- val route = MainRoutes .MediumRestoreProcessingGraph .getRoute(
135- cloudName = URLEncoder .encode(" " , " UTF-8" ), // 与本地恢复一致
136- backupDir = URLEncoder .encode(backupDir, " UTF-8" ),
137- mediaName = URLEncoder .encode(group.mediaName, " UTF-8" )
138- )
139- Log .d(" Navigation" , " 构建路由: $route " )
140- navController.navigateSingle(route)
141- Log .d(" Navigation" , " 导航完成: CloudFilesBackupDetailPage → MediumRestoreProcessingGraph" )
142- } else {
143- Log .e(" CloudFilesRestore" , " 云端文件恢复失败" )
157+ )
158+
159+ // 恢复按钮
160+ ProgressButton (
161+ modifier = Modifier .fillMaxWidth(),
162+ progress = currentProgress,
163+ currentIndex = currentIndex,
164+ totalCount = totalCount,
165+ speed = speed,
166+ progressSize = progressSize,
167+ enabled = restoreButtonEnabled,
168+ text = when {
169+ isRestoring -> {
170+ val currentDataType = getCurrentDataTypeName(group, currentIndex)
171+ " 正在恢复${currentDataType} 快照"
172+ }
173+ isCompleted -> " 云端文件恢复已完成"
174+ else -> " 恢复云端文件快照"
175+ },
176+ onClick = {
177+ if (! isRestoring && ! isCompleted && ! isDeleting) {
178+ coroutineScope.launch {
179+ try {
180+ Log .d(" CloudFilesRestore" , " 用户点击恢复按钮,开始云端文件恢复流程" )
181+ val success = viewModel.restoreFromCloudFileSnapshots(group)
182+ Log .d(" CloudFilesRestore" , " 云端文件恢复结果: $success " )
183+
184+ if (success) {
185+ Log .d(" CloudFilesRestore" , " 云端文件恢复成功,准备读取备份目录" )
186+ val backupDir = " ${context.localBackupSaveDir()} /restore/"
187+ Log .d(" CloudFilesRestore" , " 导航到文件恢复页面,备份目录: $backupDir " )
188+ viewModel.refreshLocalDatabase(backupDir)
189+
190+ viewModel.calculateSizesForActivatedMedia()
191+ val route = MainRoutes .MediumRestoreProcessingGraph .getRoute(
192+ cloudName = URLEncoder .encode(" " , " UTF-8" ),
193+ backupDir = URLEncoder .encode(backupDir, " UTF-8" ),
194+ mediaName = URLEncoder .encode(group.mediaName, " UTF-8" )
195+ )
196+ Log .d(" Navigation" , " 构建路由: $route " )
197+ navController.navigateSingle(route)
198+ Log .d(" Navigation" , " 导航完成: CloudFilesBackupDetailPage → MediumRestoreProcessingGraph" )
199+ } else {
200+ Log .e(" CloudFilesRestore" , " 云端文件恢复失败" )
201+ }
202+ } catch (e: Exception ) {
203+ Log .e(" CloudFilesRestore" , " 云端文件恢复流程异常: ${e.message} " , e)
144204 }
145- } catch (e: Exception ) {
146- Log .e(" CloudFilesRestore" , " 云端文件恢复流程异常: ${e.message} " , e)
147205 }
148206 }
149- } else {
150- Log .d(" CloudFilesRestore" , " 云端文件恢复正在进行中,忽略点击" )
151207 }
152- }
153- )
208+ )
209+ }
154210 }
155211 ) {
156212 Column (
0 commit comments