This commit is contained in:
2026-07-13 08:16:54 +08:00
parent 404d2a9140
commit fd3a204c81
9 changed files with 224 additions and 744 deletions
+11 -2
View File
@@ -147,11 +147,11 @@ class AddSyncItemDialog extends StatefulWidget {
const AddSyncItemDialog({super.key, this.editItemConfig});
static void show(BuildContext context) {
static void show(BuildContext context, [SyncItemConfig? config]) {
showDialog(
context: context,
builder: (context) => Dialog(
child: AddSyncItemDialog(),
child: AddSyncItemDialog(editItemConfig: config),
),
);
}
@@ -164,6 +164,15 @@ class _AddSyncItemDialogState extends State<AddSyncItemDialog> {
final TextEditingController nameCtl = TextEditingController();
final TextEditingController pathCtl = TextEditingController();
@override
void initState() {
if (widget.editItemConfig != null) {
nameCtl.text = widget.editItemConfig!.name;
pathCtl.text = widget.editItemConfig!.path;
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
+128 -119
View File
@@ -104,131 +104,140 @@ class _MyHomePageState extends State<MyHomePage> {
itemBuilder: (context, index) {
var (name, syncItemConfig, localModifiedTime, cloudArchives) = itemList[index];
var cloudModifiedTimeTs = cloudArchives.map((archive) => archive.mTime?.millisecondsSinceEpoch ?? 0).maxOrNull;
return Container(
margin: EdgeInsets.all(8),
padding: EdgeInsets.only(left: 10, right: 10, top: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(1, 1),
spreadRadius: 2,
blurRadius: 5,
),
],
),
height: 80,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
name,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, height: 1),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.videogame_asset_outlined, size: 18),
SizedBox(width: 4),
Flexible(child: Text(localModifiedTime?.strHm ?? '未同步')),
],
),
return GestureDetector(
onLongPress: () {
AddSyncItemDialog.show(context, syncItemConfig ?? SyncItemConfig(name: name, path: ''));
},
child: Container(
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
padding: EdgeInsets.only(left: 10, right: 10, top: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(1, 1),
spreadRadius: 2,
blurRadius: 5,
),
],
),
height: 80,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Tooltip(
message: syncItemConfig?.path ?? '',
child: Text(
name,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, height: 1),
),
Flexible(
child: Row(
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.videogame_asset_outlined, size: 18),
SizedBox(width: 4),
Flexible(child: Text(localModifiedTime?.strHm ?? '未同步')),
],
),
),
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.cloud_outlined, size: 18),
SizedBox(width: 4),
Flexible(
child: Text(
cloudModifiedTimeTs == null ? '未上传' : DateTime.fromMillisecondsSinceEpoch(cloudModifiedTimeTs).strHm,
),
),
],
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.cloud_outlined, size: 18),
SizedBox(width: 4),
Flexible(
child: Text(
cloudModifiedTimeTs == null ? '未上传' : DateTime.fromMillisecondsSinceEpoch(cloudModifiedTimeTs).strHm,
),
InkWell(
onTap: localModifiedTime == null
? null
: () {
if (syncItemConfig != null) {
upload(syncItemConfig, cloudModifiedTimeTs == null);
}
},
child: Icon(Icons.upload_rounded, size: 22),
),
SizedBox(width: 10),
Builder(
builder: (ctx) {
return InkWell(
onTap: cloudModifiedTimeTs == null
? null
: () {
if (syncItemConfig != null) {
download(syncItemConfig, cloudArchives.sorted.first);
}
},
onLongPress: cloudModifiedTimeTs == null
? null
: () {
var btn = (ctx.findRenderObject() as RenderBox);
var offset = btn.localToGlobal(Offset(btn.size.width, btn.size.height));
showMenu<dav.File>(
context: ctx,
position: RelativeRect.fromLTRB(offset.dx - 300, offset.dy, width - offset.dx, offset.dy + 200),
items: cloudArchives.sorted.map(
(file) {
var parts = basenameWithoutExtension(file.name ?? '').split('-');
parts.removeLast();
var client = parts.join('-');
return PopupMenuItem<dav.File>(
value: file,
onTap: () {
if (syncItemConfig != null) {
download(syncItemConfig, file);
}
},
child: SizedBox(
width: 300,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
client,
overflow: TextOverflow.ellipsis,
),
),
Text((file.mTime ?? file.cTime ?? DateTime(0)).strHms),
],
),
),
);
},
).toList(),
);
},
child: Icon(Icons.download_rounded, size: 22),
);
},
),
],
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: localModifiedTime == null
? null
: () {
if (syncItemConfig != null) {
upload(syncItemConfig, cloudModifiedTimeTs == null);
}
},
icon: Icon(Icons.upload_rounded, size: 22),
),
Builder(
builder: (ctx) {
return IconButton(
onPressed: cloudModifiedTimeTs == null
? null
: () {
if (syncItemConfig != null) {
download(syncItemConfig, cloudArchives.sorted.first);
}
},
onLongPress: cloudModifiedTimeTs == null
? null
: () {
var btn = (ctx.findRenderObject() as RenderBox);
var offset = btn.localToGlobal(Offset(btn.size.width, btn.size.height));
showMenu<dav.File>(
context: ctx,
position: RelativeRect.fromLTRB(offset.dx - 300, offset.dy, width - offset.dx, offset.dy + 200),
items: cloudArchives.sorted.map(
(file) {
var parts = basenameWithoutExtension(file.name ?? '').split('-');
parts.removeLast();
var client = parts.join('-');
return PopupMenuItem<dav.File>(
value: file,
onTap: () {
if (syncItemConfig != null) {
download(syncItemConfig, file);
}
},
child: SizedBox(
width: 300,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
client,
overflow: TextOverflow.ellipsis,
),
),
Text((file.mTime ?? file.cTime ?? DateTime(0)).strHms),
],
),
),
);
},
).toList(),
);
},
icon: Icon(Icons.download_rounded, size: 22),
);
},
),
],
),
],
),
],
],
),
],
),
),
);
},
+5 -1
View File
@@ -137,6 +137,7 @@ Future<void> upload(SyncItemConfig item, bool needCreateDir) async {
}
Future<void> download(SyncItemConfig item, dav.File cloudArchive) async {
print('Start download: ${cloudArchive.path}');
var cacheDir = await getApplicationCacheDirectory();
var zipPath = join(cacheDir.path, '${item.name}_${cloudArchive.name}');
await _client.read2File(cloudArchive.path!, zipPath);
@@ -144,8 +145,10 @@ Future<void> download(SyncItemConfig item, dav.File cloudArchive) async {
File(zipPath).delete();
var temp = File(join(cacheDir.path, basename(item.path)));
print('Temp path: ${temp.path}');
var fileSystemEntityType = temp.statSync().type;
switch (temp.statSync().type) {
switch (fileSystemEntityType) {
case FileSystemEntityType.directory:
var directory = Directory(item.path);
if (directory.existsSync()) {
@@ -160,6 +163,7 @@ Future<void> download(SyncItemConfig item, dav.File cloudArchive) async {
}
temp.renameSync(item.path);
default:
print('Failed: $fileSystemEntityType');
}
}