Files
photo-live/docs/plans/2026-09-29-选图拦截硬封锁-设计方案.md
2026-09-29 14:14:06 +08:00

3.4 KiB
Raw Permalink Blame History

选图点选拦截 v2:硬封锁 + 仅本机判定(去服务器半场、去强制放行)

日期:2026-09-29 | 状态:用户拍板(方案 A:接受"服务端已删照片无法重传"限制)

背景与问题

v1(提交 7e5c550+0673f39)上线后两个实际问题:

  1. 选图不灵敏:selectPredicate 每次点选 await 判定,判定含服务器单项预检 (时间帽 2s)。弱网下每次点新照片勾选延迟 0.5~2s,用户以为没点上就反复点 (wechat_assets_picker selectAsset 源码:谓词返回前 provider.selectAsset 不执行——勾选必然等判定)。
  2. 拦截形同虚设:v1 设计了"二次点击强制选择"活口(escape hatch),配合上述 反复点击习惯,重复照片多点几次必然被强制选中——用户明确要求重复照片不能 被选择。

方案(v2)

1. 点选判定只查本机(治卡顿)

  • _judge 仅保留本机 TaskStore 半场(同账号+相册+completed,filename+bytes), 删除服务器单项预检及其 2s 时间帽——点选延迟从「最多 2s 网络」降为「毫秒级 本地查询」。
  • 服务器查重不消失:入队时刻统一弹窗(checkDuplicatesUnified,一次批量 ≤500 张)照旧——跨设备/重装场景的重复仍在点上传时拦,服务端 409 兜底不变。
  • iOS 注意:title 为空(需 FilterOption.needTitle)时本机半场无从匹配 → 放行;iOS 点选拦截实际不生效,跨设备判定依赖入队弹窗(与 v1 服务器半场 行为的差异登记于此)。

2. 硬封锁(去强制放行)

  • 删除 _forced 二次点击放行集:本机命中的重复照片每次点击都拒选, 判定缓存命中即秒拦,提示文案改为「这张已上传到该相册,无法重复选择」 (en: This photo has already been uploaded to this album),不再引导再点。
  • SnackBar clearSnackBars 防堆积行为保留。

3. 判定缓存升级为 in-flight Future 共享

  • _verdicts 从 Map<String, bool> 改为 Map<String, Future<bool>>, putIfAbsent 并发去重——同一照片双击/连点只发起一次判定(清偿 9-29 评审 登记 Minor 遗留)。_judge 内部全捕获不抛错,缓存 Future 无失败态。

已接受的限制(用户拍板 A)

  • 照片在后台被删除后想重传同一文件:本机历史仍记「已传」→ 永远拦死。 解决办法:清 App 数据或换设备(罕见场景,先接受;后续可加设置开关/服务端 存活性免疫,未排期)。

构造签名变化

PickerDuplicateGate 删除 client 与 serverCheckTimeout 入参(点选路径无 网络依赖);multiImagePickerProvider 相应不再注入 ApiClient。

测试(enqueue_test 拦截器组重写)

  • 本机命中 → 拒选;连续多次点击均拒选(无强制路径);新提示文案; SnackBar 不堆积(第二个重复资产仅一条)。
  • 不同 bytes / filename / 相册 / 账号 → 放行。
  • in-flight 共享:并发两次 decideFact,fileSize 闭包仅被调用一次。
  • title=null(iOS)→ 放行;fileSize 失败 → 放行;取消选择(selected=true) 恒放行且零查询(fileSize 计数为 0)。
  • v1 服务器相关用例(②④⑥)随服务器半场移除而删除。

影响面

enqueue.dart(gate + provider 注入)+ enqueue_test.dart + l10n 双语一处 文案。不涉及服务端、契约、其它页面。