主要合入内容:

- 文件管理器分页加载、排序偏好、桌面表头排序、移动端排序菜单、Ctrl/Cmd+F搜索、Esc 关闭搜索、鼠标右滑返回上级。
- 移动端同步状态页、同步统计卡片、同步任务/累计统计事件、同步页布局更新。
- Android 相册同步默认路径改为 DCIM/Camera,下载路径改用 external_path。
- Rust sync-core 更新:Android 日志依赖、AlbumUpload/AlbumDownload、MirrorWcf 统计修复、Linux FUSE镜像挂载与读写同步支持。

- 依赖更新:external_path、fl_chart、pdfrx 升级,并修了 pdfrx 新版本的deprecated API。
- 新增文件包括:sort_options.dart、sync_page_android.dart、sync_stats_card.dart、platform/fuse.rs、sync_engine/fuse.rs。
This commit is contained in:
2026-06-04 07:11:43 +08:00
parent 5ee6ba1e28
commit b02daf1448
56 changed files with 7589 additions and 1200 deletions
+80
View File
@@ -50,6 +50,86 @@ class SyncInitialSyncComplete extends SyncEventModel {
SyncInitialSyncComplete(this.summary);
}
class SyncWorkerCompleted extends SyncEventModel {
final String taskId;
final int uploaded;
final int downloaded;
final int renamed;
final int moved;
final int failed;
final int durationMs;
SyncWorkerCompleted({
required this.taskId,
required this.uploaded,
required this.downloaded,
required this.renamed,
required this.moved,
required this.failed,
required this.durationMs,
});
}
class SyncWorkerFailed extends SyncEventModel {
final String taskId;
final String message;
SyncWorkerFailed({required this.taskId, required this.message});
}
class SyncTaskItemUpdated extends SyncEventModel {
final String taskId;
final String relativePath;
final String action;
final String status;
SyncTaskItemUpdated({
required this.taskId,
required this.relativePath,
required this.action,
required this.status,
});
}
/// 将 FFI 事件转换为 Dart 模型
SyncEventModel? syncEventFromFfi(ffi.SyncEventFfi event) {
return event.when(
stateChanged: (newState) => SyncStateChanged(newState),
progress: (synced, total, currentFile) =>
SyncProgress(synced.toInt(), total.toInt(), currentFile),
fileUploaded: (localPath, remoteUri) =>
SyncFileUploaded(localPath, remoteUri),
fileDownloaded: (localPath, remoteUri) =>
SyncFileDownloaded(localPath, remoteUri),
conflictDetected: (localPath, conflictType) =>
SyncConflictDetected(localPath, conflictType),
error: (message, recoverable) => SyncError(message, recoverable),
tokenExpired: () => SyncTokenExpired(),
diskSpaceWarning: (availableMb) =>
SyncDiskSpaceWarning(availableMb.toInt()),
initialSyncComplete: (summary) =>
SyncInitialSyncComplete(SyncSummaryModel.fromFfi(summary)),
workerStarted: (taskId, trigger, uploadCount, downloadCount) => null,
workerCompleted:
(taskId, uploaded, downloaded, renamed, moved, failed, durationMs) =>
SyncWorkerCompleted(
taskId: taskId,
uploaded: uploaded,
downloaded: downloaded,
renamed: renamed,
moved: moved,
failed: failed,
durationMs: durationMs.toInt(),
),
workerFailed: (taskId, message) =>
SyncWorkerFailed(taskId: taskId, message: message),
taskItemUpdated: (taskId, relativePath, action, status) =>
SyncTaskItemUpdated(
taskId: taskId,
relativePath: relativePath,
action: action,
status: status,
),
);
}
class SyncSummaryModel {
final int uploaded;
final int downloaded;