b02daf1448
- 文件管理器分页加载、排序偏好、桌面表头排序、移动端排序菜单、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。
173 lines
4.7 KiB
Dart
173 lines
4.7 KiB
Dart
import '../../src/rust/api/ffi_types.dart' as ffi;
|
|
|
|
sealed class SyncEventModel {}
|
|
|
|
class SyncStateChanged extends SyncEventModel {
|
|
final String newState;
|
|
SyncStateChanged(this.newState);
|
|
}
|
|
|
|
class SyncProgress extends SyncEventModel {
|
|
final int synced;
|
|
final int total;
|
|
final String currentFile;
|
|
SyncProgress(this.synced, this.total, this.currentFile);
|
|
}
|
|
|
|
class SyncFileUploaded extends SyncEventModel {
|
|
final String localPath;
|
|
final String remoteUri;
|
|
SyncFileUploaded(this.localPath, this.remoteUri);
|
|
}
|
|
|
|
class SyncFileDownloaded extends SyncEventModel {
|
|
final String localPath;
|
|
final String remoteUri;
|
|
SyncFileDownloaded(this.localPath, this.remoteUri);
|
|
}
|
|
|
|
class SyncConflictDetected extends SyncEventModel {
|
|
final String localPath;
|
|
final String conflictType;
|
|
SyncConflictDetected(this.localPath, this.conflictType);
|
|
}
|
|
|
|
class SyncError extends SyncEventModel {
|
|
final String message;
|
|
final bool recoverable;
|
|
SyncError(this.message, this.recoverable);
|
|
}
|
|
|
|
class SyncTokenExpired extends SyncEventModel {}
|
|
|
|
class SyncDiskSpaceWarning extends SyncEventModel {
|
|
final int availableMb;
|
|
SyncDiskSpaceWarning(this.availableMb);
|
|
}
|
|
|
|
class SyncInitialSyncComplete extends SyncEventModel {
|
|
final SyncSummaryModel summary;
|
|
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;
|
|
final int renamed;
|
|
final int moved;
|
|
final int conflicts;
|
|
final int failed;
|
|
final int skipped;
|
|
final int deletedLocal;
|
|
final int deletedRemote;
|
|
final int durationMs;
|
|
|
|
const SyncSummaryModel({
|
|
this.uploaded = 0,
|
|
this.downloaded = 0,
|
|
this.renamed = 0,
|
|
this.moved = 0,
|
|
this.conflicts = 0,
|
|
this.failed = 0,
|
|
this.skipped = 0,
|
|
this.deletedLocal = 0,
|
|
this.deletedRemote = 0,
|
|
this.durationMs = 0,
|
|
});
|
|
|
|
static SyncSummaryModel fromFfi(ffi.SyncSummaryFfi f) {
|
|
return SyncSummaryModel(
|
|
uploaded: f.uploaded,
|
|
downloaded: f.downloaded,
|
|
renamed: f.renamed,
|
|
moved: f.moved,
|
|
conflicts: f.conflicts,
|
|
failed: f.failed,
|
|
skipped: f.skipped,
|
|
deletedLocal: f.deletedLocal,
|
|
deletedRemote: f.deletedRemote,
|
|
durationMs: f.durationMs.toInt(),
|
|
);
|
|
}
|
|
}
|