feat(mobile): upload queue ui and continuous capture page
Task 9 (P3 plan): queue tab replaces the stub, continuous capture page enqueues per shot, album detail gains an upload FAB, and the upload engine lifecycle is now bound to the login session. - Engine scope: session account drives UploadEngine start/stop; wired from app boot, login success, logout, and 401 eviction. Tasks stay in the store across logout (accountId hard isolation). - Queue tab: album x state x time filter bar, task rows with thumbnail, state chip, localized error copy, attempt count, per-row progress via a broadcast progress hub, state-dependent actions (re-pick retry, retryNow, cancel, delete), batch retry bar, 200ms-debounced live refresh from drift table updates. - Capture page: camera preview via injected CaptureSource, one enqueue per shutter press, persistent album/category/badges overlay with a switch-only-affects-new-shots hint, gallery multi-pick, exit confirm while uploads are pending, permission-denied and init-failure views. - POST_NOTIFICATIONS runtime permission via a small MethodChannel (photolive/permissions) + PermissionPlugin.kt: single runtime permission need, avoids permission_handler dependency; requested once on first enqueue, silent degradation when denied or unavailable. - Album detail FAB: capture-and-upload / pick-from-gallery sheet. - l10n: ~50 new keys in zh/en arbs; tests: +45 (filter matrix, engine scope lifecycle, permission gate, queue tab, capture page, FAB entry); existing page tests updated to inject session/task-store fakes. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -361,4 +361,164 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get thisDevice => '本设备';
|
||||
|
||||
@override
|
||||
String get queueAlbumFilterAll => '全部相册';
|
||||
|
||||
@override
|
||||
String get queueStateAll => '全部';
|
||||
|
||||
@override
|
||||
String get queueStatePreparing => '准备中';
|
||||
|
||||
@override
|
||||
String get queueStateQueued => '待传';
|
||||
|
||||
@override
|
||||
String get queueStateUploading => '上传中';
|
||||
|
||||
@override
|
||||
String get queueStateWaitingNetwork => '等待网络';
|
||||
|
||||
@override
|
||||
String get queueStateFailed => '失败';
|
||||
|
||||
@override
|
||||
String get queueStateCompleted => '已完成';
|
||||
|
||||
@override
|
||||
String get queueTimeAll => '全部时间';
|
||||
|
||||
@override
|
||||
String get queueTimeToday => '今天';
|
||||
|
||||
@override
|
||||
String get queueTimeLast7Days => '近7天';
|
||||
|
||||
@override
|
||||
String get queueTimeLast30Days => '近30天';
|
||||
|
||||
@override
|
||||
String get queueEmpty => '暂无上传任务';
|
||||
|
||||
@override
|
||||
String get queueRetryAllFailed => '一键重试全部失败';
|
||||
|
||||
@override
|
||||
String queueAttemptCount(int count) {
|
||||
return '已尝试 $count 次';
|
||||
}
|
||||
|
||||
@override
|
||||
String get taskStatePreparing => '准备中';
|
||||
|
||||
@override
|
||||
String get taskStatePreparationFailed => '准备失败';
|
||||
|
||||
@override
|
||||
String get taskStateQueued => '待上传';
|
||||
|
||||
@override
|
||||
String get taskStateUploading => '上传中';
|
||||
|
||||
@override
|
||||
String get taskStateUploadedConfirming => '确认中';
|
||||
|
||||
@override
|
||||
String get taskStateCompleted => '已完成';
|
||||
|
||||
@override
|
||||
String get taskStateWaitingNetwork => '等待网络';
|
||||
|
||||
@override
|
||||
String get taskStateRetryableFailed => '上传失败';
|
||||
|
||||
@override
|
||||
String get taskStateCancelled => '已取消';
|
||||
|
||||
@override
|
||||
String get errorPrepSourceUnreadable => '无法读取所选图片,请重新选择';
|
||||
|
||||
@override
|
||||
String get errorPrepUnsupportedType => '仅支持 JPG/PNG/HEIC 图片';
|
||||
|
||||
@override
|
||||
String get errorPrepTooLarge => '图片超过 50MB 上限';
|
||||
|
||||
@override
|
||||
String get errorPrepCopyFailed => '保存图片副本失败,请重试';
|
||||
|
||||
@override
|
||||
String get errorUploadSourceMissing => '源文件已缺失,请重新选择';
|
||||
|
||||
@override
|
||||
String get errorAlbumUploadDisabled => '相册已关闭上传';
|
||||
|
||||
@override
|
||||
String get errorUploadSessionConflict => '上传会话冲突,请重试';
|
||||
|
||||
@override
|
||||
String get errorUploadVerifyFailed => '上传核验失败,将自动重试';
|
||||
|
||||
@override
|
||||
String get captureTitle => '连拍上传';
|
||||
|
||||
@override
|
||||
String get captureCategoryDefault => '默认分类';
|
||||
|
||||
@override
|
||||
String get captureSwitchHint => '切换分类仅影响之后拍摄的照片';
|
||||
|
||||
@override
|
||||
String capturePendingBadge(int count) {
|
||||
return '待传 $count';
|
||||
}
|
||||
|
||||
@override
|
||||
String captureFailedBadge(int count) {
|
||||
return '失败 $count';
|
||||
}
|
||||
|
||||
@override
|
||||
String get capturePickFromGallery => '从相册选择';
|
||||
|
||||
@override
|
||||
String get captureShutter => '拍摄';
|
||||
|
||||
@override
|
||||
String get captureExitTitle => '退出拍摄?';
|
||||
|
||||
@override
|
||||
String captureExitBody(int count) {
|
||||
return '还有 $count 张照片未上传,退出后任务将在后台继续。';
|
||||
}
|
||||
|
||||
@override
|
||||
String get captureKeepShooting => '继续拍摄';
|
||||
|
||||
@override
|
||||
String get captureExitConfirm => '退出';
|
||||
|
||||
@override
|
||||
String get cameraPermissionDenied => '无法访问相机,请在系统设置中允许相机权限';
|
||||
|
||||
@override
|
||||
String get cameraInitFailed => '相机初始化失败';
|
||||
|
||||
@override
|
||||
String get uploadActionCapture => '拍照上传';
|
||||
|
||||
@override
|
||||
String get uploadActionPick => '从相册选择';
|
||||
|
||||
@override
|
||||
String get uploadAction => '上传';
|
||||
|
||||
@override
|
||||
String uploadEnqueuedCount(int count) {
|
||||
return '已加入 $count 张上传队列';
|
||||
}
|
||||
|
||||
@override
|
||||
String get uploadPickNone => '未选择照片';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user