feat(app): 服务端历史行首缩略图 + 上传中心空态引导至服务端历史

- UploadSessionPhoto 解析可选 preview;历史行首有 thumb 渲染 PhotoThumbnail
 (SizedBox 定寸——Row 内裸 AspectRatio 无界约束),缺省回退中性占位
- 上传中心整体空态加「仅本机存储」说明 + 「查看服务端历史」tonal 按钮
 (与右上 History 同路由);「需关注」空态保持专属文案不加引导
- l10n 增 queueEmptyDeviceHint / queueViewServerHistory

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-29 12:04:06 +08:00
parent f1912998a8
commit 3728eb93d9
10 changed files with 141 additions and 18 deletions
+11 -1
View File
@@ -207,12 +207,15 @@ class UploadCompleteResponse {
/// 会话关联照片的当前状态(会话记录内嵌,客户端据此展示服务端进度)。
///
/// 契约 `components.schemas.UploadSessionPhoto`。
/// 契约 `components.schemas.UploadSessionPhoto`。[preview] 为可选缩略图
///(2026-09-29 增补):服务端在变体齐备且未隐藏/删除时现签(uploader
/// 本人视角);缺省(未处理/隐藏/删除)时 UI 回退中性占位。
class UploadSessionPhoto {
const UploadSessionPhoto({
required this.photoId,
required this.processingState,
required this.visibility,
this.preview,
});
factory UploadSessionPhoto.fromJson(Map<String, dynamic> json) =>
@@ -221,6 +224,9 @@ class UploadSessionPhoto {
processingState:
PhotoProcessingState.fromJson(json['processingState'] as String),
visibility: PhotoVisibility.fromJson(json['visibility'] as String),
preview: json['preview'] == null
? null
: PhotoPreview.fromJson(json['preview'] as Map<String, dynamic>),
);
/// 照片 ID。
@@ -232,10 +238,14 @@ class UploadSessionPhoto {
/// 对外可见性。
final PhotoVisibility visibility;
/// 短期签名预览 URL;null = 无(回退占位图标)。
final PhotoPreview? preview;
Map<String, dynamic> toJson() => {
'photoId': photoId,
'processingState': processingState.wire,
'visibility': visibility.wire,
if (preview != null) 'preview': preview!.toJson(),
};
}