Skip to content

Commit 502a1e2

Browse files
author
Fastace
committed
Fix:完成修复Restic文件备份逻辑,Todo:增加恢复页文件恢复逻辑
1 parent 1a4e5de commit 502a1e2

6 files changed

Lines changed: 107 additions & 141 deletions

File tree

source/.kotlin/errors/errors-1765956190512.log

Lines changed: 0 additions & 4 deletions
This file was deleted.

source/.kotlin/errors/errors-1766237645626.log

Lines changed: 0 additions & 4 deletions
This file was deleted.

source/app/src/main/kotlin/com/xayah/databackup/MainActivity.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import com.xayah.core.ui.route.MainRoutes
2020
import com.xayah.core.ui.theme.DataBackupTheme
2121
import com.xayah.core.ui.util.LocalNavController
2222
import com.xayah.core.util.command.BaseUtil
23+
import com.xayah.core.model.database.MediaEntity
24+
import com.xayah.core.model.File
2325
import com.xayah.feature.main.cloud.PageCloud
2426
import com.xayah.feature.main.cloud.add.PageCloudAddAccount
2527
import com.xayah.feature.main.cloud.add.PageFTPSetup
@@ -158,18 +160,18 @@ class MainActivity : AppCompatActivity() {
158160
)
159161
) { backStackEntry ->
160162
val groupJsonEncoded = backStackEntry.arguments?.getString(MainRoutes.ARG_GROUP)
161-
val group = groupJsonEncoded?.let { encodedJson ->
163+
val selectedFiles = groupJsonEncoded?.let { encodedJson ->
162164
try {
163165
val groupJsonDecoded = URLDecoder.decode(encodedJson, "UTF-8")
164-
Json.decodeFromString<ResticMediaBackupGroup>(groupJsonDecoded)
166+
Json.decodeFromString<List<File>>(groupJsonDecoded)
165167
} catch (e: Exception) {
166-
Log.e("MainActivity", "Failed to decode ResticMediaBackupGroup: ${e.message}", e)
168+
Log.e("MainActivity", "Failed to decode MediaEntity list: ${e.message}", e)
167169
null
168170
}
169171
}
170172

171-
group?.let {
172-
ResticMediaBackupDetailPage(navController = navController, selectedFiles = emptyList()) // 需要传递文件列表
173+
selectedFiles?.let {
174+
ResticMediaBackupDetailPage(navController = navController, selectedFiles = it)
173175
} ?: run {
174176
navController.popBackStack()
175177
}

source/feature/main/processing/src/main/kotlin/com/xayah/feature/main/processing/medium/backup/Setup.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fun PageMediumBackupProcessingSetup(localNavController: NavHostController, viewM
9595
Button(
9696
enabled = uiState.storageType == StorageMode.Local || (uiState.cloudEntity != null && isTesting.not()),
9797
onClick = {
98-
viewModel.emitIntentOnIO(FinishSetup(navController = localNavController))
98+
viewModel.emitIntentOnIO(FinishSetup(navController = navController))
9999
}) {
100100
Text(text = stringResource(id = R.string._continue))
101101
}

source/feature/main/restore/src/main/kotlin/com/xayah/feature/main/restore/ResticMediaBackupDetailPage.kt

Lines changed: 91 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package com.xayah.feature.main.restore
22

3-
import java.io.File
4-
import android.util.Log
53
import androidx.compose.animation.ExperimentalAnimationApi
4+
import androidx.compose.foundation.ExperimentalFoundationApi
65
import androidx.compose.foundation.layout.Arrangement
76
import androidx.compose.foundation.layout.Column
87
import androidx.compose.foundation.layout.Row
@@ -14,9 +13,13 @@ import androidx.compose.foundation.layout.padding
1413
import androidx.compose.foundation.layout.size
1514
import androidx.compose.foundation.lazy.LazyColumn
1615
import androidx.compose.foundation.lazy.items
16+
import androidx.compose.material.icons.Icons
17+
import androidx.compose.material.icons.outlined.Description
18+
import androidx.compose.material3.Button
1719
import androidx.compose.material3.CircularProgressIndicator
1820
import androidx.compose.material3.ExperimentalMaterial3Api
1921
import androidx.compose.material3.HorizontalDivider
22+
import androidx.compose.material3.Icon
2023
import androidx.compose.material3.LinearProgressIndicator
2124
import androidx.compose.material3.MaterialTheme
2225
import androidx.compose.material3.Text
@@ -25,47 +28,34 @@ import androidx.compose.material3.rememberTopAppBarState
2528
import androidx.compose.runtime.Composable
2629
import androidx.compose.runtime.LaunchedEffect
2730
import androidx.compose.runtime.getValue
31+
import androidx.compose.runtime.rememberCoroutineScope
2832
import androidx.compose.ui.Alignment
2933
import androidx.compose.ui.Modifier
3034
import androidx.compose.ui.text.style.TextOverflow
3135
import androidx.compose.ui.unit.dp
32-
import androidx.compose.foundation.ExperimentalFoundationApi
33-
import androidx.compose.foundation.rememberScrollState
34-
import androidx.compose.foundation.verticalScroll
3536
import androidx.hilt.navigation.compose.hiltViewModel
3637
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3738
import androidx.navigation.NavController
38-
import androidx.compose.foundation.layout.IntrinsicSize
39-
import androidx.compose.ui.platform.LocalContext
39+
import com.xayah.core.model.File
4040
import com.xayah.core.ui.component.BodyMediumText
41+
import com.xayah.core.ui.component.Title
4142
import com.xayah.core.ui.component.TitleLargeText
42-
import com.xayah.core.ui.route.MainRoutes
4343
import com.xayah.core.ui.theme.ThemedColorSchemeKeyTokens
4444
import com.xayah.core.ui.theme.value
4545
import com.xayah.core.ui.token.SizeTokens
46-
import com.xayah.core.util.DateUtil
47-
import com.xayah.core.util.navigateSingle
48-
import com.xayah.core.model.database.MediaEntity
49-
import com.xayah.core.ui.component.ProgressButton
50-
import com.xayah.core.ui.component.Title
51-
import androidx.compose.runtime.rememberCoroutineScope
5246
import kotlinx.coroutines.launch
53-
import kotlinx.serialization.encodeToString
54-
import kotlinx.serialization.json.Json
55-
import java.net.URLEncoder
56-
import androidx.compose.material.icons.Icons
57-
import androidx.compose.material.icons.outlined.Description
5847

5948
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class, ExperimentalAnimationApi::class)
6049
@Composable
6150
fun ResticMediaBackupDetailPage(
6251
navController: NavController,
63-
selectedFiles: List<MediaEntity>,
52+
selectedFiles: List<File>,
6453
viewModel: ResticMediaBackupViewModel = hiltViewModel()
6554
) {
6655
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
6756
val coroutineScope = rememberCoroutineScope()
6857

58+
// 初始进入页面时启动备份
6959
LaunchedEffect(Unit) {
7060
viewModel.startDirectBackup(selectedFiles)
7161
}
@@ -74,86 +64,80 @@ fun ResticMediaBackupDetailPage(
7464
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()),
7565
title = "文件Restic备份"
7666
) {
77-
Column(
67+
// 使用单一 LazyColumn 替代嵌套滚动
68+
LazyColumn(
7869
modifier = Modifier
7970
.fillMaxSize()
80-
.padding(SizeTokens.Level16)
81-
.verticalScroll(rememberScrollState())
71+
.padding(horizontal = SizeTokens.Level16),
72+
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level8)
8273
) {
83-
// 显示选中的文件列表
84-
Title(title = "备份文件列表") {
85-
LazyColumn(
86-
modifier = Modifier.fillMaxWidth(),
87-
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level8)
74+
// 列表头部:间隔和标题
75+
item {
76+
Spacer(modifier = Modifier.height(SizeTokens.Level16))
77+
TitleLargeText(text = "备份文件列表")
78+
Spacer(modifier = Modifier.height(SizeTokens.Level8))
79+
}
80+
81+
// 文件列表内容
82+
items(selectedFiles) { file ->
83+
Row(
84+
modifier = Modifier
85+
.fillMaxWidth()
86+
.padding(vertical = SizeTokens.Level8),
87+
verticalAlignment = Alignment.CenterVertically,
88+
horizontalArrangement = Arrangement.spacedBy(SizeTokens.Level12)
8889
) {
89-
items(selectedFiles) { file ->
90-
Row(
91-
modifier = Modifier
92-
.fillMaxWidth()
93-
.padding(SizeTokens.Level8),
94-
verticalAlignment = Alignment.CenterVertically,
95-
horizontalArrangement = Arrangement.spacedBy(SizeTokens.Level12)
96-
) {
97-
androidx.compose.material3.Icon(
98-
imageVector = Icons.Outlined.Description,
99-
contentDescription = null,
100-
modifier = Modifier.size(32.dp),
101-
tint = ThemedColorSchemeKeyTokens.Primary.value
102-
)
90+
Icon(
91+
imageVector = Icons.Outlined.Description,
92+
contentDescription = null,
93+
modifier = Modifier.size(32.dp),
94+
tint = ThemedColorSchemeKeyTokens.Primary.value
95+
)
10396

104-
Column(
105-
modifier = Modifier.weight(1f)
106-
) {
107-
TitleLargeText(
108-
text = file.name,
109-
maxLines = 1,
110-
overflow = TextOverflow.Ellipsis
111-
)
112-
BodyMediumText(
113-
text = file.path,
114-
color = ThemedColorSchemeKeyTokens.Outline.value,
115-
maxLines = 2,
116-
overflow = TextOverflow.Ellipsis
117-
)
118-
}
119-
}
120-
HorizontalDivider()
97+
Column(modifier = Modifier.weight(1f)) {
98+
TitleLargeText(
99+
text = file.name,
100+
maxLines = 1,
101+
overflow = TextOverflow.Ellipsis
102+
)
103+
BodyMediumText(
104+
text = file.path,
105+
color = ThemedColorSchemeKeyTokens.Outline.value,
106+
maxLines = 2,
107+
overflow = TextOverflow.Ellipsis
108+
)
121109
}
122110
}
111+
HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp))
123112
}
124113

125-
Spacer(modifier = Modifier.height(SizeTokens.Level24))
114+
// 列表尾部:备份状态显示
115+
item {
116+
Spacer(modifier = Modifier.height(SizeTokens.Level16))
126117

127-
// 备份进度显示
128-
when (val state = uiState) {
129-
is BackupUiState.Loading -> {
130-
Column(
131-
modifier = Modifier.fillMaxWidth(),
132-
horizontalAlignment = Alignment.CenterHorizontally,
133-
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)
134-
) {
135-
CircularProgressIndicator()
136-
Text("正在准备备份...")
118+
when (val state = uiState) {
119+
is BackupUiState.Loading -> {
120+
Column(
121+
modifier = Modifier.fillMaxWidth().padding(vertical = SizeTokens.Level24),
122+
horizontalAlignment = Alignment.CenterHorizontally,
123+
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)
124+
) {
125+
CircularProgressIndicator()
126+
Text("正在准备备份...")
127+
}
137128
}
138-
}
139129

140-
is BackupUiState.Progress -> {
141-
Column(
142-
modifier = Modifier.fillMaxWidth(),
143-
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)
144-
) {
130+
is BackupUiState.Progress -> {
145131
Title(title = "备份进度") {
146-
Column {
132+
Column(verticalArrangement = Arrangement.spacedBy(SizeTokens.Level8)) {
147133
Text(
148134
text = "当前文件: ${state.currentFileName}",
149135
style = MaterialTheme.typography.bodyMedium
150136
)
151-
Spacer(modifier = Modifier.height(SizeTokens.Level8))
152137
LinearProgressIndicator(
153-
progress = state.progress,
138+
progress = { state.progress },
154139
modifier = Modifier.fillMaxWidth()
155140
)
156-
Spacer(modifier = Modifier.height(SizeTokens.Level8))
157141
Row(
158142
modifier = Modifier.fillMaxWidth(),
159143
horizontalArrangement = Arrangement.SpaceBetween
@@ -170,15 +154,10 @@ fun ResticMediaBackupDetailPage(
170154
}
171155
}
172156
}
173-
}
174157

175-
is BackupUiState.Success -> {
176-
Column(
177-
modifier = Modifier.fillMaxWidth(),
178-
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)
179-
) {
158+
is BackupUiState.Success -> {
180159
Title(title = "备份完成") {
181-
Column {
160+
Column(verticalArrangement = Arrangement.spacedBy(SizeTokens.Level4)) {
182161
Text(
183162
text = "成功备份 ${state.results.size} 个文件",
184163
style = MaterialTheme.typography.bodyMedium
@@ -190,47 +169,40 @@ fun ResticMediaBackupDetailPage(
190169
color = ThemedColorSchemeKeyTokens.Primary.value
191170
)
192171
}
172+
Spacer(modifier = Modifier.height(SizeTokens.Level16))
173+
Button(
174+
onClick = { navController.popBackStack() },
175+
modifier = Modifier.fillMaxWidth()
176+
) {
177+
Text("返回")
178+
}
193179
}
194180
}
195-
196-
// 返回按钮
197-
androidx.compose.material3.Button(
198-
onClick = {
199-
navController.popBackStack()
200-
},
201-
modifier = Modifier.fillMaxWidth()
202-
) {
203-
Text("返回")
204-
}
205181
}
206-
}
207182

208-
is BackupUiState.Error -> {
209-
Column(
210-
modifier = Modifier.fillMaxWidth(),
211-
verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)
212-
) {
183+
is BackupUiState.Error -> {
213184
Title(title = "备份失败") {
214-
Text(
215-
text = state.message,
216-
style = MaterialTheme.typography.bodyMedium,
217-
color = MaterialTheme.colorScheme.error
218-
)
219-
}
220-
221-
// 重试按钮
222-
androidx.compose.material3.Button(
223-
onClick = {
224-
coroutineScope.launch {
225-
viewModel.startDirectBackup(selectedFiles)
185+
Column(verticalArrangement = Arrangement.spacedBy(SizeTokens.Level16)) {
186+
Text(
187+
text = state.message,
188+
style = MaterialTheme.typography.bodyMedium,
189+
color = MaterialTheme.colorScheme.error
190+
)
191+
Button(
192+
onClick = {
193+
coroutineScope.launch {
194+
viewModel.startDirectBackup(selectedFiles)
195+
}
196+
},
197+
modifier = Modifier.fillMaxWidth()
198+
) {
199+
Text("重试")
226200
}
227-
},
228-
modifier = Modifier.fillMaxWidth()
229-
) {
230-
Text("重试")
201+
}
231202
}
232203
}
233204
}
205+
Spacer(modifier = Modifier.height(SizeTokens.Level32))
234206
}
235207
}
236208
}

0 commit comments

Comments
 (0)