yumi-flutter/需求进度.md
2026-06-02 19:57:41 +08:00

1058 lines
184 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 首充弹窗需求进度2026-05-21
- [ ] 2026-05-22 新增问题:后台首充已配置,但前端未显示首充弹窗,房间礼物面板也未显示首充悬浮板;本轮需用 iPhone 17 Pro 模拟器实际排查并修复。
- [x] 2026-05-22 用户反馈:礼物弹窗在 iPhone 17 Pro Max 仍报 `A Stack requires bounded constraints from its parent`;本轮已实际运行 iPhone 17 Pro Max 复现,并依据运行日志修到不再报错。
- [x] 2026-05-22 已确认 iPhone 17 Pro Max 模拟器在线,设备 ID`8D2D87EB-4769-43B7-8DC2-580D46A76B6C`
- [x] 2026-05-22 已在 iPhone 17 Pro Max 启动主 App控制台先出现 SmartDialog overlay 运行期异常:`RenderAnimatedOpacity ... SmartDialogWidget ... size: MISSING`,说明问题发生在弹窗 overlay 内容尺寸约束层。
- [!] 2026-05-22 主 App 运行时有自动签到弹窗/页面跳转干扰,直接从首页进入房间礼物面板不稳定;改为创建只用于验证的礼物弹窗 debug 入口,复用真实 `GiftPage``SmartDialog.show(tag: showGiftControl)` 路径在 iPhone 17 Pro Max 直接复现。
- [x] 2026-05-22 已新增 `lib/debug/gift_page_preview.dart`,用于在 iPhone 17 Pro Max 直接运行真实 `GiftPage` 礼物弹窗,避免主 App 自动弹窗和导航干扰。
- [x] 2026-05-22 已执行 `dart format lib/debug/gift_page_preview.dart``flutter analyze lib/debug/gift_page_preview.dart lib/modules/gift/gift_page.dart`结果No issues found。
- [!] 2026-05-22 首次运行 debug 礼物弹窗入口成功进入 Flutter但入口自身有两个干扰mock `balance()` 在 build 中通知 provider、`AppConfig` 未初始化;先修入口,避免干扰礼物弹窗约束验证。
- [x] 2026-05-22 已修正 debug 礼物弹窗入口:补 `AppConfig.initialize()` / `DataPersistence.initialize()`mock `balance()` 改为 no-op复跑 format/analyze结果 No issues found。
- [x] 2026-05-22 已在 iPhone 17 Pro Max 礼物弹窗 debug 入口稳定复现用户报错;运行日志明确定位到 `lib/ui_kit/widgets/gift/sc_gift_combo_send_button.dart:80``Stack`,约束为 `BoxConstraints(w=112.6, 0.0<=h<=Infinity)`
- [x] 2026-05-22 已修复真正报错点:`SCGiftComboSendButton` 原本只有宽度没有高度,导致内部 `Stack` 在 Row/Column 中获得无界高度;现补 `height: 32.w`,不改礼物悬浮板、头像、列表样式。
- [x] 2026-05-22 已在 iPhone 17 Pro Max 礼物弹窗 debug 入口热重启验证:等待 5 秒未再出现 `A Stack requires bounded constraints` 或连锁 layout 错误。
- [x] 2026-05-22 已保存验证截图:`build/gift_page_verification/ios17promax_gift_panel_no_stack_error.png`
- [x] 2026-05-22 已继续观察 iPhone 17 Pro Max 礼物弹窗预览 10 秒,控制台无新增 `Stack requires bounded constraints`
- [x] 2026-05-22 已执行 `dart format lib/ui_kit/widgets/gift/sc_gift_combo_send_button.dart lib/modules/gift/gift_page.dart lib/debug/gift_page_preview.dart` 与对应 `flutter analyze`结果No issues found。
- [x] 2026-05-22 已退出 iPhone 17 Pro Max 礼物弹窗预览 `flutter run` 会话,未保留运行进程。
- [x] 2026-05-22 用户反馈:礼物弹窗仍报 `A Stack requires bounded constraints`;上轮不应改头像/loading 原有样式,本轮已还原无关样式改动,并按 CP 悬浮板方式把首充悬浮板放到上方。
- [x] 2026-05-22 已还原上轮无关样式改动:麦位头像、指定用户头像、礼物 tab loading skeleton 恢复原本写法;本轮不再动这些原有样式。
- [x] 2026-05-22 已将 `lib/modules/gift/gift_tab_page.dart` 恢复到仓库原样,避免上轮 loading skeleton 改动残留。
- [x] 2026-05-22 已按 CP 悬浮板方式最小调整首充悬浮板:外层边距改为 `10.w`,卡片尺寸改为 `355.w × 46.w`,仍放在礼物主体 `ClipRRect` 上方。
- [x] 2026-05-22 已执行 `dart format lib/modules/gift/gift_page.dart``flutter analyze lib/modules/gift/gift_page.dart`结果No issues found。
- [x] 2026-05-22 已补充礼物弹窗根宽度约束:`SafeArea` 内新增 `SizedBox(width: ScreenUtil().screenWidth)` 包裹原 `Column`,只解决 SmartDialog 松约束下内部 `Stack/TabBarView` 无界问题不改头像、列表、loading 等原有样式。
- [x] 2026-05-22 已在根宽度约束修复后复跑 `dart format lib/modules/gift/gift_page.dart``flutter analyze lib/modules/gift/gift_page.dart`结果No issues found。
- [x] 2026-05-22 根据 iPhone 17 Pro Max 实际日志确认根因是发送按钮高度无界,不是弹窗根宽度;已撤回 `SafeArea` 内新增的根 `SizedBox(width: ScreenUtil().screenWidth)`,继续保持原本弹窗布局。
- [x] 2026-05-22 撤回根宽度约束后,已重新执行 format/analyze`lib/modules/gift/gift_page.dart``lib/ui_kit/widgets/gift/sc_gift_combo_send_button.dart``lib/debug/gift_page_preview.dart` 均 No issues found。
- [x] 2026-05-22 已重新冷启动 iPhone 17 Pro Max 礼物弹窗预览入口,启动完成后观察 10 秒,控制台无 `A Stack requires bounded constraints` 报错。
- [x] 2026-05-22 已覆盖保存最终验证截图:`build/gift_page_verification/ios17promax_gift_panel_no_stack_error.png`
- [x] 2026-05-22 已退出最终 iPhone 17 Pro Max 礼物弹窗预览 `flutter run` 会话。
- [x] 2026-05-22 新增问题:礼物弹窗弹起时报 `A Stack requires bounded constraints from its parent`,已定位并修复礼物弹窗内无界约束的 `Stack`
- [x] 2026-05-22 已定位礼物弹窗内高风险 `Stack`:麦位头像 `_maiHead()` 与指定用户头像叠选中角标时,处在 `Row/SingleChildScrollView` 的松约束链路中,需要补固定尺寸。
- [x] 2026-05-22 已修复礼物弹窗头像叠层约束:指定用户头像 `Stack` 包裹 `30.w × 30.w`,麦位头像外层 `Stack` 包裹 `32.w × 32.w`、内层头像叠层包裹 `30.w × 30.w`
- [x] 2026-05-22 已执行 `dart format lib/modules/gift/gift_page.dart``flutter analyze lib/modules/gift/gift_page.dart`结果No issues found。
- [x] 2026-05-22 已修复礼物 tab loading skeleton`_buildGiftPageSkeleton()` 改为显式接收高度,并用有限宽高 `SizedBox` 包裹 `Stack`;空数据 loading 使用 `kGiftTabPageHeight.w`,分页 loading 使用 `_kGiftGridHeight.w`
- [x] 2026-05-22 已执行 `dart format lib/modules/gift/gift_page.dart lib/modules/gift/gift_tab_page.dart``flutter analyze lib/modules/gift/gift_page.dart lib/modules/gift/gift_tab_page.dart`结果No issues found。
- [x] 2026-05-22 已完成本次报错修复收尾核对:本轮实际修复文件为 `lib/modules/gift/gift_page.dart``lib/modules/gift/gift_tab_page.dart` 与本进度文档;未改动其它业务逻辑。
- [x] 2026-05-22 新增需求用户未首充时房间礼物弹窗上方新增首充悬浮板CP 礼物 tab 保持特殊 CP 悬浮板,其它礼物 tab 展示 Figma 节点 `191:388` 样式;点击悬浮板打开首充弹窗。
- [x] 2026-05-22 已开始定位礼物弹窗:`lib/modules/gift/gift_page.dart` 包含旧首充入口逻辑、CP 礼物 tab 判断与 `_buildCpGiftCloseFriendEntry()` 特殊 CP 悬浮板。
- [x] 2026-05-22 已确认现有 CP 悬浮板实现:`_buildCpGiftCloseFriendEntry()` 使用 `sc_images/room/cp_profile/sc_cp_profile_gift_entry_card.png`,尺寸 `355.w × 46.w`,位于礼物弹窗主体上方。
- [x] 2026-05-22 已通过本机 Figma Desktop MCP 读取节点 `191:388` 的结构化设计信息和截图。
- [!] 2026-05-22 本机 Python 未安装 `requests`,改用 `curl` 直接访问 `http://127.0.0.1:3845/mcp`
- [x] 2026-05-22 已完成 Figma Desktop MCP 初始化握手,服务返回 `Figma Dev Mode MCP Server`
- [x] 2026-05-22 已读取 Figma 节点 `191:388` metadata节点名 `Group 2090056029`,尺寸 `343 × 50`,主体由多层图片/遮罩组成。
- [x] 2026-05-22 已读取 Figma 节点 `191:388` design context样式依赖多张 PNG/SVG 资源和 mask为保证 Flutter 还原度,本轮采用节点截图作为悬浮板资源。
- [x] 2026-05-22 已通过 Figma Desktop MCP 获取节点 `191:388` screenshot。
- [x] 2026-05-22 已将 Figma 节点 `191:388` 截图落地为项目资源:`sc_images/first_recharge/room_gift_entry_card.png`,尺寸 `343 × 50`
- [x] 2026-05-22 已完成礼物弹窗改造:移除旧顶部小首充 tag在非 CP 礼物 tab、用户未首充、非审核状态下展示新的横向首充悬浮板。
- [x] 2026-05-22 已更新 `GiftPage`:新增 `sc_images/first_recharge/room_gift_entry_card.png` 资源引用,普通礼物 tab 按 `firstRecharge=true` 显示横向悬浮板。
- [x] 2026-05-22 已移除礼物弹窗顶部旧的小首充 tag避免与新横向悬浮板重复展示。
- [x] 2026-05-22 已新增 `_buildFirstRechargeGiftEntry()`,尺寸 `343.w × 50.w`,水平边距 `16.w`,位置与 CP 悬浮板同为礼物主体上方。
- [x] 2026-05-22 已新增 `_openFirstRechargeDialog()`:点击首充悬浮板先关闭 `showGiftControl` 礼物面板,再延迟打开现有首充弹窗。
- [x] 2026-05-22 已清理旧首充 tag 删除后不再使用的 `CountdownTimer` import。
- [!] 2026-05-22 首次分析发现 `_openFirstRechargeDialog()` 延迟后使用 `BuildContext` 触发 lint已改为延迟后重新获取 `navigatorKey.currentState` 并检查 `mounted`
- [x] 2026-05-22 已复跑 `dart format lib/modules/gift/gift_page.dart``flutter analyze lib/modules/gift/gift_page.dart`结果No issues found。
- [x] 2026-05-22 已目检新增资源 `room_gift_entry_card.png`:显示 `Newcomer Special Offer`、金币和礼盒,符合 Figma 节点 `191:388` 悬浮板视觉。
- [x] 2026-05-22 已完成收尾核对:当前工作区存在多项此前/并行任务改动,本轮新增悬浮板核心变更为 `GiftPage`、新增首充悬浮板图片与本进度文档;未回退无关改动。
- [x] 2026-05-22 用户反馈 3第二档金额 tab 右侧仍离选择器边框有间距;需要继续微调第二档选中态贴边,并说明当前首充弹窗逻辑。
- [x] 2026-05-22 已定位第二档右侧留白根因:选择器总宽 `240`,第二档选中态仍按 `left=120,width=110` 渲染,因此右侧天然剩 `10px`
- [x] 2026-05-22 已将第二档选中态改为 `left=120,width=120`,右侧直接铺到选择器边框;第二档文字改为 `left=125,width=110`,保持在右半区居中。
- [x] 2026-05-22 已针对第二档贴边修正执行 `dart format` 和定向 `flutter analyze`结果No issues found。
- [x] 2026-05-22 已重新运行 iPhone 17 Pro 预览,点击第二档并截图:`build/first_recharge_verification/ios17pro_first_recharge_tab2_flush_v1.png`;另生成 375x812 图 `ios17pro_first_recharge_tab2_flush_v1_375w.png`
- [x] 2026-05-22 已目检新版截图:第二档橙色选中态右侧已顶到选择器右边框,原先 10px 浅底留白已消失。
- [x] 2026-05-22 已退出本轮 `flutter run` session未保留运行命令占用。
- [x] 2026-05-22 用户反馈 2第二个金额 tab 选中态仍未对齐;首充奖励接口文档已提供,需要对接接口;点击 `Buy Now` 需要直接拉起对应 Google 支付。
- [x] 2026-05-22 已读取 `/Users/nigger/Desktop/首充奖励-Flutter接口对接文档.md`,确认首充奖励首页接口为 `GET /go/app/first-recharge-reward/home`,金额档位和奖励列表由 `levelConfigs/rewardItems` 返回。
- [x] 2026-05-22 已定位现有入口:主页首充浮层和礼物页均调用 `SCDialogUtils.showFirstRechargeDialog`;后续将该入口切到新版首充弹窗并接接口。
- [x] 2026-05-22 已检查现有网络层和支付链路:`NetworkClient` 自动注入鉴权/语言/来源请求头并解析 `body``AndroidPaymentProcessor` 已由根 `Provider` 注册,现有 Google 内购商品配置来自 `/order/product-config`
- [x] 2026-05-22 正在新增首充奖励接口模型、仓库方法、弹窗数据转换和 `Buy Now` 直拉 Google 支付能力。
- [x] 2026-05-22 已新增首充奖励接口响应模型 `SCFirstRechargeRewardHomeRes/LevelConfig/RewardItem`,兼容金额、折扣、总价值、非金币天数角标和金币奖励识别。
- [x] 2026-05-22 已在 `SocialChatConfigRepository` / `SCConfigRepositoryImp` 增加 `firstRechargeRewardHome()`,请求 `GET /go/app/first-recharge-reward/home`
- [x] 2026-05-22 已将 `SCDialogUtils.showFirstRechargeDialog` 切换到新版 `FirstRechargeDialog.showFromRemote`,旧入口调用保持不变,主页/礼物页点击会走新接口弹窗。
- [x] 2026-05-22 已为 `FirstRechargeDialogData` 增加接口数据转换:金额 tab、奖励卡、金币/非金币样式、折扣角标、总价值文案均来自接口字段或兼容扩展字段。
- [x] 2026-05-22 已为 `AndroidPaymentProcessor` 增加 `processFirstRechargePurchase`:优先按接口返回的 `productPackage` 匹配 Google 商品,否则按 `rechargeAmountCents` 匹配价格并直接拉起 Google 支付。
- [x] 2026-05-22 已调整第二个金额 tab 的选中贴图裁切:第二档使用右侧负偏移裁切镜像纹理,避免切换到第二档时贴图与边框错位。
- [!] 2026-05-22 首次格式化误将 `需求进度.md` 传给 `dart format`Dart 文件已格式化Markdown 格式化报错不影响代码;下一步重新仅格式化 Dart 文件。
- [!] 2026-05-22 首次定向分析发现支付文件存在若干历史 lint本轮已清理未使用调试循环、空 `catch`、异步后使用 `BuildContext` 的写法,并将已直接导入的 `in_app_purchase_android` 补为显式依赖。
- [x] 2026-05-22 已执行 `flutter pub get``in_app_purchase_android` 从传递依赖变为显式直接依赖。
- [!] 2026-05-22 第二次格式化误将 `pubspec.yaml` 传给 `dart format``pub get` 与 Dart 文件格式化已成功;下一步仅对 Dart 文件执行格式化/分析。
- [x] 2026-05-22 已重新仅格式化 Dart 文件,并执行定向 `flutter analyze`结果No issues found。
- [x] 2026-05-22 准备在 iPhone 17 Pro 预览中切换到第二个金额 tab 截图,验证本轮对齐调整。
- [x] 2026-05-22 已启动 `lib/debug/first_recharge_dialog_preview.dart` 到 iPhone 17 Pro 模拟器,应用进入 Flutter debug 运行状态。
- [!] 2026-05-22 `simctl screenshot` 使用相对路径仍会被 iOS 工具误判目录不存在,改用绝对路径重新截图。
- [x] 2026-05-22 已保存 iPhone 17 Pro 预览截图:`build/first_recharge_verification/ios17pro_first_recharge_api_tab1.png`
- [x] 2026-05-22 已在 Simulator 中点击 `$2.99` 第二档并保存截图:`build/first_recharge_verification/ios17pro_first_recharge_api_tab2.png`;另生成 375x812 对比图 `ios17pro_first_recharge_api_tab2_375w.png`
- [x] 2026-05-22 目检第二档金额区域:`$2.99` 文案居中,橙色选中态左侧与中间分割线对齐、右侧裁切贴合外边框,较上一版错位已修正。
- [x] 2026-05-22 已退出本轮 `flutter run` session未保留运行命令占用。
- [x] 2026-05-22 已补充远程弹窗加载流程:首充接口返回并完成数据判定后先关闭 loading再展示首充弹窗避免 loading 遮住弹窗。
- [x] 2026-05-22 已在加载流程修正后复跑 `dart format` 与定向 `flutter analyze`结果No issues found。
- [x] 2026-05-22 已处理接口档位数量边界:当前 Figma 弹窗为两个金额 tab接口映射时仅取前两个可用档位避免第三档数据与两个 tab UI 状态不一致。
- [x] 2026-05-22 已在档位数量边界修正后再次复跑 `dart format` 与定向 `flutter analyze`结果No issues found。
- [x] 2026-05-22 用户反馈:顶部金额文字未居中,选中态没有和选择器边框对齐;本轮开始针对金额选择器做细微调整。
- [x] 2026-05-22 已定位当前实现:金额区域在 `_PriceSelector` 中,选中态使用 `ClipRRect` 圆角裁剪,和 Figma 异形遮罩/边框咬合不够贴合。
- [x] 2026-05-22 已将金额选中态改为 Figma SVG 同款自定义裁剪路径:选中第一档时右侧平直对齐中间边界,选中第二档时镜像处理;同时金额文字按 Figma 的 `top=7 height=16` 放回视觉中心。
- [!] 2026-05-22 首次复跑分析发现 `Matrix4.scale` 为新版 Flutter 废弃 API已改为 `Matrix4.diagonal3Values`
- [x] 2026-05-22 已复跑 `dart format` 和定向 `flutter analyze`结果No issues found。
- [x] 2026-05-22 已在 iPhone 17 Pro 重新运行预览并截图:`build/first_recharge_verification/ios17pro_first_recharge_price_tuned.png`;另生成 375x812 对比图 `ios17pro_first_recharge_price_tuned_375w.png`
- [x] 2026-05-22 复查金额区域:`$0.99` / `$2.99` 已回到各自 tab 中心,橙色选中态右侧平直边已和中间分割边对齐,整体比上一版贴近 Figma。
- [x] 2026-05-22 已退出本轮 `flutter run` session未保留运行命令占用。
- [x] 已确认本轮目标:按 Figma `<首充弹窗>` 先实现 UI数据后续由接口决定金额选项切换后下方奖励、折扣文案随数据变化。
- [x] 已确认工作目录:`/Users/nigger/Documents/GitHub/chatapp3-flutter`
- [x] 已开始按“每一步同步更新本文件”的要求记录本轮进度,历史进度不覆盖。
- [x] 已初步扫描项目文件,确认存在每日签到弹窗 `lib/ui_kit/widgets/daily_sign_in/daily_sign_in_dialog.dart`,本轮将优先复用其弹窗写法和项目 UI 规范。
- [!] 内置 Figma app 读取节点 `144:1183` 返回重新认证提示;按本轮要求不走 Remote/OAuth改为直接访问本机 Figma Desktop MCP`http://127.0.0.1:3845/mcp`
- [x] 已确认本机 Figma Desktop MCP 服务在线;未初始化 session 的请求返回 `Invalid sessionId`,下一步执行 MCP 初始化握手。
- [x] 已完成 Figma Desktop MCP 初始化握手,服务返回 `Figma Dev Mode MCP Server`
- [x] 已通过 Desktop MCP 列出可用工具:`get_metadata``get_design_context``get_screenshot``get_variable_defs` 等。
- [x] 已通过 Desktop MCP 读取节点 `144:1183` metadata该节点本身即目标 frame `首充弹窗`,尺寸 `375x812`;弹窗主体 `340x528`,位置 `x=18 y=153`
- [x] 已通过 Desktop MCP 读取节点 `144:1183` design context关键图层包括背景遮罩、弹窗三段背景、顶部标题图、金额切换条、6 个奖励卡片、`Buy Now` 按钮和折扣角标。
- [x] 已通过 Desktop MCP 读取节点 `144:1183` screenshot并保存为 `build/first_recharge_verification/figma_reference.png` 作为视觉基准。
- [ ] 正在检查 Flutter 项目主题、组件、资源注册方式和每日签到弹窗实现细节。
- [x] 已检查 `pubspec.yaml`:资源按目录注册,现有 `daily_sign_in/``register_reward/` 均通过 `sc_images/...` 目录管理。
- [x] 已检查每日签到弹窗:采用 `SmartDialog.show``ScreenUtil``Stack + Image.asset` 叠图层,并在弹窗内部定义数据模型与 mock 数据。
- [x] 已确认奖励图标策略可复用:金币样式复用 `sc_images/register_reward/yumi_coin.png`;非金币样式支持接口图片 URL 或本地占位。
- [x] 已检查当前 git 状态:除本轮 `需求进度.md` 外,已有无关改动 `lib/shared/data_sources/sources/local/floating_screen_manager.dart`,本轮不会回退。
- [x] 已下载 Figma 首充弹窗素材到 `sc_images/first_recharge/`,包含弹窗三段背景、标题图、金额切换条、奖励卡、按钮、关闭按钮和折扣角标。
- [x] 已按展示尺寸将关闭按钮、标题、按钮、折扣角标和奖励小图压缩到约 3x 资源尺寸,避免 Figma 小图超大分辨率直接进包。
- [x] 已在 `pubspec.yaml` 注册 `sc_images/first_recharge/` 资源目录。
- [x] 已新增 `lib/ui_kit/widgets/first_recharge/first_recharge_dialog.dart`:包含首充套餐数据模型、金额切换、奖励列表、金币/非金币两种奖励样式、折扣角标和 Buy Now 点击回调。
- [x] 已新增 `lib/debug/first_recharge_dialog_preview.dart`:使用 Figma 背景图和 `SmartDialog` 遮罩展示首充弹窗,供 iOS 模拟器截图验证。
- [x] 已执行 `dart format lib/ui_kit/widgets/first_recharge/first_recharge_dialog.dart lib/debug/first_recharge_dialog_preview.dart`,格式化完成。
- [!] 首次定向 `flutter analyze` 发现 `previewBackground` 私有常量未使用,已删除。
- [x] 已复跑 `flutter analyze lib/ui_kit/widgets/first_recharge/first_recharge_dialog.dart lib/debug/first_recharge_dialog_preview.dart`结果No issues found。
- [x] 已确认 iPhone 17 Pro 模拟器已启动,设备 ID`49E28192-AC58-4EE3-BF9E-0363C4A47536`
- [ ] 正在运行 `lib/debug/first_recharge_dialog_preview.dart` 到 iPhone 17 Pro 模拟器。
- [!] iOS 构建遇到 Xcode concurrent builds 重试;已确认冲突来自另一个正在编译 `lib/main.dart` 的 iPhone 17 Pro Max 构建,本轮暂不主动终止无关运行进程。
- [!] 已截取第一张 iPhone 17 Pro 图,但前台显示为既有主 App 每日签到弹窗,不是本轮 preview判断为同一模拟器已有 Runner/debug session 抢占前台,需终止 Runner 后干净重跑。
- [x] 已退出本轮 `flutter run` session并确认 iPhone 17 Pro 上当前没有正在运行的 `com.org.yumiparty`
- [ ] 正在干净重跑首充弹窗 debug 预览入口。
- [x] 已重新截图 `build/first_recharge_verification/ios17pro_first_recharge_v2.png`,首充弹窗可见,主体布局接近 Figma。
- [!] 视觉复查发现 debug 预览背景自带状态栏,同时模拟器真实状态栏又叠加一层;已在 debug 预览入口隐藏系统 UI准备重新截图。
- [x] 已重新截图 `build/first_recharge_verification/ios17pro_first_recharge_v3.png`,状态栏重复问题已解决;另生成 375x812 缩放对比图 `ios17pro_first_recharge_v3_375w.png`
- [!] 缩放对比发现金额切换条价格文字整体右偏,`$0.99``$2.99` 坐标不符合 Figma已按 price tab 内部相对坐标修正。
- [x] 已在价格文字修正后复跑 `dart format` 与定向 `flutter analyze`结果No issues found。
- [x] 已热重启 iPhone 17 Pro 预览并截取最终图:`build/first_recharge_verification/ios17pro_first_recharge_final.png`;另生成 375x812 对比图 `ios17pro_first_recharge_final_375w.png`
- [x] 最终视觉复查:弹窗主体位置、三段背景、标题、倒计时、金额 tab、6 个奖励卡、总价值文案、Buy Now 按钮和折扣角标已贴近 Figma金额切换状态的数据结构已支持选择不同金额显示不同奖励。
- [!] 剩余客观差异iPhone 17 Pro 模拟器会显示 Dynamic Island 黑区,而 Figma 截图尺寸为 `375x812` 的静态状态栏背景;这属于设备壳层差异,不影响弹窗主体。
- [x] 已退出首充弹窗 `flutter run` session未保留本轮运行命令占用。
- [x] 已完成最终 git 状态检查:本轮新增/修改集中在首充弹窗组件、debug 入口、`sc_images/first_recharge/``pubspec.yaml` 和本进度文件;工作区仍存在其他房间/动效相关改动,判断为本轮之外的既有改动,未回退。
- [x] 已复查资源体积:将仅用于 debug 预览的背景图压到 `375x812`,并删除未使用的 `price_selected_mask.svg`
- [x] 已在资源整理后最终复跑定向 `flutter analyze`结果No issues found。
- [ ] 待检查 Flutter 项目主题、组件、资源注册方式和每日签到弹窗实现细节。
- [ ] 待实现首充弹窗 UI、预览入口与占位数据模型。
- [ ] 待启动 iOS 模拟器截图并与 Figma 截图对比迭代。
---
# 语音房内动画开关需求进度2026-05-21
- [x] 2026-05-22 收到第三次反馈:菜单特效图标需改用 `/Users/nigger/Desktop/app素材/figma-20260522-120235.png`,并且外层要和其它菜单图标一样用 `Container` 包裹。
- [x] 2026-05-22 已检查本地图片:`figma-20260522-120235.png` 为 45×45 PNG可直接作为房间菜单图标资源。
- [x] 2026-05-22 已用本地图片覆盖项目资源 `sc_images/room/sc_icon_room_animation_effects_menu.png`
- [x] 2026-05-22 已修改菜单特效入口:外层改为和音乐/红包一致的 45×45 圆形 `Container`,内部居中渲染图标。
- [x] 2026-05-22 已执行 `dart format lib/ui_kit/widgets/room/room_menu_dialog.dart`
- [x] 2026-05-22 已执行 `flutter analyze --no-fatal-warnings --no-fatal-infos lib/ui_kit/widgets/room/room_menu_dialog.dart`,结果 `No issues found`
- [x] 2026-05-22 已检查最终状态:图标资源已为 45×45 PNG菜单特效入口代码已引用该资源并包裹 45×45 圆形 `Container`;工作区仍有大量既有/并行改动,本轮仅处理菜单图标和进度记录。
- [x] 2026-05-22 收到二次反馈:当前功能效果正确,但弹窗 UI 样式不对;需要重新尝试连接 Figma Lalu 节点 `171:264`,并将菜单栏 UI 图标换成节点 `171:261` 对应样式。
- [x] 2026-05-22 已重新连接本机 Figma Desktop MCP`http://127.0.0.1:3845/mcp`session 为 `177330e2-d0e2-4cdb-9429-febe997ba070`,服务为 `Figma Dev Mode MCP Server`
- [x] 2026-05-22 已通过 Desktop MCP 读取节点 `171:264` metadata / design context目标为 375×812 整屏,底部弹层从 y=661 起,高 151背景 `#072121`,顶部圆角 12标题 `Animation` 18px中间两行文字 14px开关尺寸 32×14。
- [x] 2026-05-22 已通过 Desktop MCP 读取节点 `171:261` metadata / design context菜单图标为 26×26 vector素材地址由本机 Figma assets 服务返回。
- [x] 2026-05-22 已获取 `171:264` / `171:261` 截图数据Figma screenshot 以 MCP 内联 PNG 返回,后续从本地 SSE 文件落盘用于视觉对照。
- [x] 2026-05-22 已检查当前实现:旧弹窗为居中 330 宽卡片,和 Figma 底部 375×151 半屏面板不一致;菜单仍使用旧 `sc_icon_room_special_effects.png` 资源,不是节点 `171:261` 的 26×26 vector。
- [x] 2026-05-22 已将 Figma 截图落盘:`build/voice_room_animation_switch_verification/figma_171_264_animation_switch.png``build/voice_room_animation_switch_verification/figma_171_261_menu_icon.png`
- [x] 2026-05-22 已将节点 `171:261` 菜单图标导出到项目资源:`sc_images/room/sc_icon_room_animation_effects_menu.png`,尺寸 26×26。
- [x] 2026-05-22 已目检 Figma 截图:弹窗应为底部全宽面板,不是居中卡片;标题为 `Animation` 且无左侧图标/关闭按钮;行文本分别为 `Gift Animation``Vehicle Animation`;开关为 32×14 小胶囊。
- [x] 2026-05-22 已确认 Figma 开关素材:开启态为 `#18F2B1` 描边与右侧 10px 圆点,关闭态为 `#999999` 描边与左侧 10px 圆点;当前用 Flutter 自绘,避免 SVG CSS 变量兼容问题。
- [x] 2026-05-22 已完成编码:弹窗改为底部 151 高面板、自绘 32×14 开关;菜单图标改为 `sc_icon_room_animation_effects_menu.png` 并按 26×26 渲染。
- [x] 2026-05-22 已执行 `dart format` 格式化 `room_animation_switch_dialog.dart``room_menu_dialog.dart`
- [x] 2026-05-22 已执行 `flutter analyze --no-fatal-warnings --no-fatal-infos lib/ui_kit/widgets/room/room_animation_switch_dialog.dart lib/ui_kit/widgets/room/room_menu_dialog.dart lib/debug/room_animation_switch_dialog_preview.dart`,结果 `No issues found`
- [x] 2026-05-22 已调整 debug preview`RoomAnimationSwitchDialog` 在预览中同样贴底展示,不再居中。
- [x] 2026-05-22 已确认 iPhone 17 Pro Max 模拟器在线,设备 ID `8D2D87EB-4769-43B7-8DC2-580D46A76B6C`
- [x] 2026-05-22 已复跑 `flutter analyze --no-fatal-warnings --no-fatal-infos`,结果 `No issues found`
- [x] 2026-05-22 已重新运行 iPhone 17 Pro Max 预览Flutter run 已进入热重载状态。
- [!] 2026-05-22 首次 `simctl screenshot` 使用相对路径时被 iOS 工具误判目录不存在,已改用绝对路径重新截图。
- [x] 2026-05-22 已保存新版弹窗预览截图:`build/voice_room_animation_switch_verification/ios17promax_animation_switch_dialog_figma_style_v1.png`
- [!] 2026-05-22 已目检新版预览截图:底部位置/高度/颜色/标题结构与 Figma 对齐,但 debug preview 因全局默认值让第二个开关显示开启Figma 基准为关闭;准备仅调整 debug preview 初始状态后复截。
- [x] 2026-05-22 已调整 debug preview 初始状态:礼物开关开启、进场开关关闭,仅用于视觉对比;生产弹窗仍读取用户真实偏好。
- [x] 2026-05-22 已再次分析 debug preview 与弹窗文件,结果 `No issues found`
- [!] 2026-05-22 尝试对当前 `flutter run` 会话发送热重启时发现 stdin 已关闭,改为重新拉起预览目标后复截。
- [x] 2026-05-22 已清理旧的 iPhone 17 Pro Max 预览 `flutter run` / Runner 进程。
- [x] 2026-05-22 已重新启动预览并进入热重载状态。
- [x] 2026-05-22 已保存第二版对比截图:`build/voice_room_animation_switch_verification/ios17promax_animation_switch_dialog_figma_style_v2.png`
- [x] 2026-05-22 已目检第二版截图:底部面板位置/高度/圆角/背景色、标题与两行开关状态已贴近 Figma 171:264截图保存为 `ios17promax_animation_switch_dialog_figma_style_v2.png`
- [!] 2026-05-22 停止预览时工具侧 stdin 再次关闭,已改用进程清理方式结束本次 `flutter run` / Runner。
- [x] 2026-05-22 已确认 iPhone 17 Pro Max 预览相关 `flutter run` / Runner 进程已退出。
- [x] 2026-05-22 已检查最终工作区状态:本轮新增 `sc_images/room/sc_icon_room_animation_effects_menu.png`,并更新动画开关弹窗、房间菜单与 debug preview工作区仍存在首充弹窗、`floating_screen_manager.dart``pubspec.yaml` 等既有/并行改动,本轮不回退。
- [x] 已确认工作目录为 `/Users/nigger/Documents/GitHub/chatapp3-flutter`,并开始按“每一步同步更新本文件”的要求记录本轮进度。
- [x] 已完成初步仓库巡检:项目为 Flutter 工程,资源通过 `pubspec.yaml` 注册,当前存在既有未提交改动 `lib/shared/data_sources/sources/local/floating_screen_manager.dart`,本轮不会回退无关改动。
- [x] 已初读现有进度文档、`pubspec.yaml` 与房间/礼物/特效关键字,确认已有全局礼物特效配置、房间动效调度与语音房菜单相关实现需要继续定位。
- [!] 已尝试使用内置 Figma app 读取节点 `171:264`,但该连接要求重新认证;按本轮要求不走 Remote/OAuth改为直接访问本机 Figma Desktop MCP`http://127.0.0.1:3845/mcp`
- [x] 已成功与 Figma Desktop MCP 完成初始化握手,服务返回 `Figma Dev Mode MCP Server`,后续节点读取将使用该本机 session。
- [!] 已通过 Desktop MCP 调用 `get_metadata(nodeId: 171:264)`,当前 Figma active tab 返回未找到该节点;继续读取当前文件顶层结构以定位目标 frame。
- [x] 已读取当前 Figma Desktop 文件顶层页面:`0:1 lalu``3:15367 yumi`,确认 Desktop MCP 当前连接的是目标 Lalu 文件上下文。
- [x] 已扫描两页 metadata`首充弹窗``yumi` 页定位到 frame `144:1183`本轮“Entry Effect / Mic Animation”开关稿在 `yumi` 页房间弹窗区域出现,继续锁定具体 frame。
- [x] 已通过 Desktop MCP 获取 `144:1183` 的 design context 与 screenshot并保存视觉基准到 `build/voice_room_animation_switch_verification/figma_144_1183_first_recharge.png`
- [x] 已通过 Desktop MCP 获取当前可定位的房间设置页 `7:6301` 的 design context 与 screenshot并保存到 `build/voice_room_animation_switch_verification/figma_7_6301_room_setup.png`;原链接节点 `171:259/171:264` 在当前 Desktop 文件中仍不可直接访问。
- [x] 已完成第一轮代码定位:语音房菜单入口在 `lib/ui_kit/widgets/room/room_menu_dialog.dart`;房间可视特效总可见性来自 `RtcProvider.shouldShowRoomVisualEffects`;礼物特效开关已有 `SCGlobalConfig.isGiftSpecialEffects`,进场/座驾开关已有 `SCGlobalConfig.isEntryVehicleAnimation` 但当前播放链路仍需补齐独立判断。
- [x] 已确认可复用素材:菜单新图标使用现有 `sc_images/room/sc_icon_room_special_effects.png`,开关控件复用 `sc_images/general/sc_icon_switch_on.png` / `sc_icon_switch_off.png`;无需新增资源目录。
- [x] 已完成首轮编码:新增 `RoomAnimationSwitchDialog`,菜单中移除原 Settings 入口并替换为 `sc_icon_room_special_effects.png` 特效管理入口;弹窗内提供“礼物特效 / 进场特效”两个本地持久化开关。
- [x] 已补齐播放链路判断:关闭礼物开关时同步关闭普通礼物与幸运礼物特效偏好;关闭进场开关时阻断高成本进场播放、低性能进场兜底与房间进场横幅队列。
- [x] 已执行 `dart format`,格式化目标文件通过。
- [!] 已执行定向 `flutter analyze`,结果无 error`rtc_manager.dart` / `rtm_manager.dart` 既有 warning/info 让命令按 1 退出;继续使用 `--no-fatal-warnings --no-fatal-infos` 复核 error 口径。
- [x] 已执行 `flutter analyze --no-fatal-warnings --no-fatal-infos ...`,退出码 0确认本轮改动无 error剩余 27 条 warning/info 均来自既有 `rtc_manager.dart` / `rtm_manager.dart` 风格问题。
- [x] 已检查 iOS 模拟器设备:`iPhone 17 Pro Max` 已在线,设备 ID `8D2D87EB-4769-43B7-8DC2-580D46A76B6C`
- [x] 已启动 iPhone 17 Pro Max 运行当前 AppFlutter run 已进入可热重载状态,控制台确认 `lowPerformance=false``allowsHighCost=true`
- [x] 已通过模拟器 UI 进入语音房 `room12345678` 并打开底部菜单,确认原 Settings 入口已替换为 `Special effects management` 新图标入口。
- [x] 已保存菜单验证截图:`build/voice_room_animation_switch_verification/ios17promax_room_menu_special_effects.png`
- [!] 继续点击新入口时 Computer Use 失去 Simulator 窗口句柄(`cgWindowNotFound`),无法继续通过 GUI 点开弹窗;已保留真实房间菜单验证截图,改用项目现有 debug preview 方式对同一个弹窗组件做 iPhone 17 Pro Max 截图验证。
- [x] 已新增 `lib/debug/room_animation_switch_dialog_preview.dart`,复用同一个 `RoomAnimationSwitchDialog` 组件渲染 375x812 房间背景预览。
- [x] 已分析弹窗预览入口,`flutter analyze --no-fatal-warnings --no-fatal-infos` 退出码 0仍仅有既有 `rtc_manager.dart` / `rtm_manager.dart` warning/info。
- [x] 已切换 iPhone 17 Pro Max 到弹窗预览入口,用于截图验证。
- [!] 已截取首版弹窗预览图,发现英文标题在 375 宽下被截断为省略号;正在调整标题为两行可容纳布局并复截。
- [x] 已热重载修正标题布局并复截弹窗图:`build/voice_room_animation_switch_verification/ios17promax_animation_switch_dialog_preview_v2.png`,标题、两行开关、按钮均未溢出。
- [x] 已单独执行 `flutter analyze --no-fatal-warnings --no-fatal-infos lib/ui_kit/widgets/room/room_animation_switch_dialog.dart lib/debug/room_animation_switch_dialog_preview.dart`,结果 No issues found。
- [x] 已退出弹窗预览运行,避免留下 `flutter run` 会话。
- [x] 已检查最终变更范围:本轮核心改动集中在房间菜单、动画开关弹窗、礼物/进场特效播放判断与 debug 预览;工作区仍存在非本轮的 `floating_screen_manager.dart``pubspec.yaml`、首充弹窗相关文件改动,本轮不回退。
---
# CP 进度弹窗 Desktop MCP 复核进度
- [x] 2026-05-15 本轮重新执行语音房 Agora -> TRTC 迁移:确认 Flutter RTC 口径改为 TRTC `strRoomId = roomProfile.roomAccount``userId = 业务 userId`,不再使用 Agora `roomProfile.id` 频道号和数字 uid。
- [x] 2026-05-15 已移除 Flutter Agora 依赖并接入腾讯官方 `tencent_rtc_sdk: ^13.2.2``flutter pub get` 已刷新 `pubspec.lock``.flutter-plugins-dependencies`
- [x] 2026-05-15 已新增房间 RTC 业务抽象:`RoomRtcSessionIdentity``RoomRtcEngineAdapter``TrtcRoomRtcEngineAdapter`,将入房、角色切换、远端静音、音量回调、音乐混音统一收口到 TRTC 适配层。
- [x] 2026-05-15 已重构 `rtc_manager.dart` 核心 RTC 链路:入房改为 `TRTCCloud.enterRoom(TRTCParams(... strRoomId ...), TRTCAppScene.voiceChatRoom)`;上麦/下麦改为 `switchRole(anchor/audience)` + `startLocalAudio/stopLocalAudio/muteLocalAudio`;音量回调改为按 TRTC `userId` 映射麦位。
- [x] 2026-05-15 已移除 Agora token/续签链路:删除 `/external/im-trtc/tmp/agora/sig` 调用、`SCRtcTokenRes``getRtcToken` 仓储接口TRTC 入房凭证统一复用登录态 `userSig`
- [x] 2026-05-15 已将房间音乐从 Agora `startAudioMixing/pause/resume/seek/volume` 切到 TRTC `TXAudioEffectManager`保留本地播放、上麦发布、暂停恢复、seek 和音量能力。
- [x] 2026-05-15 已更新配置口径:`agoraRtcAppid` 替换为 `trtcSdkAppId`,默认使用 `20036101`,支持 `--dart-define=TRTC_SDK_APP_ID=...` 覆盖。
- [x] 2026-05-15 已更新原生侧Android 移除 Agora 屏幕共享覆盖声明并改为 TRTC 屏幕采集组件移除,补 `BLUETOOTH_CONNECT` 与 Tencent ProGuard 规则iOS `pod install` 已移除 Agora pods 并新增 `TXLiteAVSDK_Professional`
- [x] 2026-05-15 已补单测:覆盖 `roomAccount -> strRoomId`、业务 `userId`、TRTC 入房参数、角色切换、音乐混音参数;`flutter test test/room_rtc_types_test.dart test/trtc_room_rtc_engine_adapter_test.dart` 通过。
- [x] 2026-05-15 已执行迁移残留扫描:`lib/android/ios/pubspec/test` 中无 `agora_rtc_engine`、Agora API、旧 token 接口残留;历史进度文档中的旧记录不作为代码残留。
- [x] 2026-05-15 Android 打包链路已继续收口:`pag-1.0.7` 原包缺 Android namespace、Kotlin JVM target 不一致且仍引用 Flutter v1 embedding已切为本地 patched package 并补齐 `namespace/jvmTarget/v2 embedding` 兼容,避免火箭 PAG 接入后阻断 APK 构建。
- [x] 2026-05-15 已执行 `flutter build apk --debug`,结果通过,产物为 `build/app/outputs/flutter-apk/app-debug.apk`
- [x] 2026-05-15 复跑迁移单测通过;同时修复火箭奖励记录模型 `rocketIconUrl` getter 缺失导致的测试编译错误。
- [x] 2026-05-15 已修复杀进程后跨房间上麦残留:启动和进入新房间前不再直接清空 `last_time_room_id`,会先静默调用旧房间 `quitRoom`,成功后再清理本地标记,避免 A/B 房间同时展示同一用户麦位。
- [x] 2026-05-15 已验证异常退出残留修复相关改动:定向 `flutter analyze --no-fatal-infos --no-fatal-warnings` 无 errorTRTC 迁移单测 `flutter test test/room_rtc_types_test.dart test/trtc_room_rtc_engine_adapter_test.dart` 通过。
---
- [x] 2026-05-14 用户确认Figma 背景图、具体头像等仅用于截图校验,测试完成后不能留在包资源中
- [x] 2026-05-14 已删除校验专用资源:`sc_cp_progress_preview_bg.png``sc_cp_progress_sample_avatar.png`
- [x] 2026-05-14 已移除 `RoomCpProgressDialogUser.avatarAsset` 以及预览入口对本地示例头像/背景图的引用
- [x] 2026-05-14 已执行 `dart format`,格式化通过
- [x] 2026-05-14 已执行 `flutter analyze lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart lib/debug/room_cp_progress_dialog_preview.dart`结果No issues found
- [x] 2026-05-14 已检查残留引用:代码和资源目录无校验背景/示例头像引用,相关字符串仅保留在 `需求进度.md` 历史记录
- [x] 2026-05-14 已收尾检查 git 状态和 CP 进度资源目录;`cp_progress` 目录仅保留弹窗生产所需 6 个素材
---
# CP 进度弹窗 Desktop MCP 复核进度2026-05-13
- [x] 2026-05-13 用户已切换要求:本轮优先使用 Figma Desktop MCP`127.0.0.1:3845/mcp`),不再使用 Remote MCP
- [x] 2026-05-13 已重新读取 `figma-implement-design` 工作流,确认先 metadata、design context、screenshot再进入编码修正
- [x] 2026-05-13 已通过 Figma Desktop MCP 读取 `7:1088` metadata该节点本身为 375x812 framename: `关系邀请4`),内容匹配 `<语音房-cp进度弹窗>`
- [x] 2026-05-13 已通过 Figma Desktop MCP 读取 `7:1088` design context 与 screenshot关键尺寸弹窗背景 340x275、中心图标 114x87、头像框 59x69、按钮 115x36、进度条背景 260x26
- [x] 2026-05-13 已下载 Figma 头像框资产到 `sc_images/room/cp_progress/sc_cp_progress_avatar_frame.png`
- [x] 2026-05-13 已按 Figma Desktop design context 重构 `RoomCpProgressDialog` 布局:中心天数卡 114x87、头像框 59x69、进度条/按钮按 Figma 位置复原
- [x] 2026-05-13 已下载 Figma 预览背景 `sc_cp_progress_preview_bg.png` 与示例头像 `sc_cp_progress_sample_avatar.png`
- [x] 2026-05-13 已更新预览入口为 Figma 背景/遮罩/示例头像;组件新增 `avatarAsset` 兜底字段,接口头像 URL 仍优先
- [x] 2026-05-13 已执行 `dart format`,格式化通过
- [x] 2026-05-13 已执行 `flutter analyze lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart lib/debug/room_cp_progress_dialog_preview.dart`结果No issues found
- [x] 2026-05-13 已在 iPhone 17 Pro 模拟器运行 `lib/debug/room_cp_progress_dialog_preview.dart`
- [x] 2026-05-13 已截取 iPhone 17 Pro 运行图:`build/cp_progress_verification/ios17pro_cp_progress_desktop_mcp_v1.png`
- [!] 2026-05-13 与 Figma screenshot 对比:整体位置/背景/中心天数卡/进度条/按钮接近,示例头像裁切仍偏离 Figma
- [x] 2026-05-13 已按 Figma mask 偏移修正 `avatarAsset` 预览裁切
- [x] 2026-05-13 已重新截图:`build/cp_progress_verification/ios17pro_cp_progress_desktop_mcp_v2.png`;视觉复查整体位置、比例、头像裁切、层级、文字和按钮接近 Desktop MCP 截图
- [x] 2026-05-13 已执行最终 `flutter analyze lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart lib/debug/room_cp_progress_dialog_preview.dart`结果No issues found
- [x] 2026-05-13 已退出 iPhone 17 Pro 运行 session
- [x] 2026-05-13 已收尾检查 git 状态和本轮修改文件;当前仍存在既有未跟踪 CP 邀请相关文件,最终回复中单独说明
---
# CP 进度弹窗需求进度
- [x] 2026-05-13 已确认工作目录:`/Users/nigger/Documents/GitHub/chatapp3-flutter`
- [x] 2026-05-13 已定位 Figma 实现相关 skill 文件,准备读取 workflow 约束
- [x] 2026-05-13 已读取 `figma-implement-design` 工作流,确认需先获取结构化设计信息与截图
- [x] 2026-05-13 已尝试读取 Figma 节点结构化设计信息与截图fileKey: `L2A45c2lm8Gt0VHS3beS4o`, nodeId: `636:849`
- [!] 2026-05-13 Figma MCP 返回 Starter plan 调用次数上限,当前不是 Remote MCP 未加载,也不是 OAuth 失效;本次实现将继续以本地设计图为最终视觉基准
- [x] 2026-05-13 已初步检查项目结构Flutter 项目,入口在 `lib/main.dart`,资源通过 `pubspec.yaml` 声明 `sc_images/...`
- [x] 2026-05-13 已确认现有弹窗依赖:`flutter_smart_dialog`;房间相关 UI 位于 `lib/ui_kit/widgets/room/...`
- [x] 2026-05-13 已找到本地设计素材:`/Users/nigger/Desktop/app素材/cp/cp进度弹窗`5 个 PNG
- [x] 2026-05-13 已读取本地素材尺寸:弹窗背景 680x550、内图标 456x348、进度条背景 520x52、进度条 484x32、取消按钮 230x72
- [x] 2026-05-13 已查看本地设计素材视觉内容,确认按 2x 逻辑尺寸实现:弹窗 340x275、进度槽 260x26、进度条 242x16、按钮 115x36、内图标 228x174
- [x] 2026-05-13 已检查现有 CP 邀请弹窗:`RoomCpInviteDialog` 使用 `SmartDialog.show``ScreenUtil``SCDebounceWidget`
- [x] 2026-05-13 已检查头像/图片组件:复用 `head()` / `netImage()`,默认头像资源为 `sc_images/general/sc_icon_avar_defalt.png`
- [x] 2026-05-13 已补充检查 CP 邀请弹窗尾部实现:按钮图片叠文字、关闭按钮使用 `SCDebounceWidget`
- [x] 2026-05-13 已确认现有 CP 资产命名位于 `sc_images/room/cp_invite/`
- [x] 2026-05-13 已检查 git 状态:当前已有 `pubspec.yaml``需求进度.md` 修改,以及未跟踪的 CP 邀请弹窗/素材目录
- [x] 2026-05-13 已复制 CP 进度弹窗素材到 `sc_images/room/cp_progress/`
- [x] 2026-05-13 已新增独立组件:`lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart`
- [x] 2026-05-13 已新增浏览器验证入口:`lib/debug/room_cp_progress_dialog_preview.dart`
- [x] 2026-05-13 已格式化新增 Dart 文件
- [x] 2026-05-13 已执行 `flutter analyze lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart lib/debug/room_cp_progress_dialog_preview.dart`结果No issues found
- [x] 2026-05-13 已读取 browser-use 本地验证说明;当前将使用 Flutter web-server + 浏览器截图验证
- [!] 2026-05-13 已尝试启动 Flutter web-server 预览,但项目当前 web 编译被既有 `image_cropper_for_web` / `image_cropper_platform_interface` 依赖错误阻塞
- [x] 2026-05-13 已检查设备iPhone 17 Pro Max 模拟器已启动(`8D2D87EB-4769-43B7-8DC2-580D46A76B6C`
- [!] 2026-05-13 iOS 预览已启动,但新增 `sc_images/room/cp_progress/` 未被 asset bundle 收录,需要追加到 `pubspec.yaml`
- [x] 2026-05-13 已在 `pubspec.yaml` 追加 `sc_images/room/cp_progress/` 资源声明
- [x] 2026-05-13 已重新运行 iPhone 17 Pro Max 模拟器预览,资源加载无缺失异常
- [x] 2026-05-13 已截图 iPhone 17 Pro Max 预览:`build/cp_progress_verification/ios_cp_progress_preview.png`
- [!] 2026-05-13 视觉检查发现用户信息行与顶部心形标题条重叠,需要下移用户区并调整标题等级胶囊
- [x] 2026-05-13 已调整用户区、时间、进度条和按钮纵向位置
- [!] 2026-05-13 热重载时 Flutter session 断开,需要重新启动预览入口
- [x] 2026-05-13 已重新截图:`build/cp_progress_verification/ios_cp_progress_preview_v2.png`
- [!] 2026-05-13 复查发现 ID 字段空间偏窄,长 ID 过早截断,需要扩展用户信息位
- [x] 2026-05-13 已扩展用户信息位并缩小头像到 40.w
- [!] 2026-05-13 热重载再次断开,改用重新启动预览入口完成最终截图
- [x] 2026-05-13 已重新启动预览入口并截最终图:`build/cp_progress_verification/ios_cp_progress_preview_final.png`
- [x] 2026-05-13 最终视觉复查头像、ID、时间、等级、进度条、按钮无明显重叠长 ID 可完整展示
- [x] 2026-05-13 最终执行 `flutter analyze lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart lib/debug/room_cp_progress_dialog_preview.dart`结果No issues found
- [x] 2026-05-13 已退出 Flutter run session未留下后台命令占用
- [x] 2026-05-13 已检查最终变更范围并准备汇总
- [x] 2026-05-13 已实现语音房内 CP 进度弹窗独立组件
- [x] 2026-05-13 已接入头像、ID、时间、等级等接口数据预留位与占位数据
- [x] 2026-05-13 已启动 iPhone 17 Pro Max 模拟器并完成截图验证
- [x] 2026-05-13 已按本地设计素材视觉基准迭代修正布局
- [x] 2026-05-13 待最终回复汇总修改文件、运行方式和待确认差异
- [x] 2026-05-13 已复查最终 git 状态:`tool/room_cp_invite_preview.dart``room_cp_invite_dialog.dart``sc_images/room/cp_invite/` 为既有 CP 邀请相关未跟踪项,不计入本次 CP 进度弹窗修改
---
# 需求进度
## 当前总目标
- 控制当前 Flutter Android 发包体积,持续定位冗余组件、超大资源和不合理构建配置,并把每一步处理结果落盘记录。
- 按桌面《Android音乐添加流程.md》在 Android 语言房内补齐本地 MP3 音乐功能,并持续记录素材接入、扫描添加、列表管理、播放器和房间播放链路进度。
## 本轮语音房红包功能(进行中)
- 已完成第一轮只读摸底:项目内已有房间红包接口声明与实现、`ROOM_RED_PACKET` RTM 收包、红包飘屏、`RtcProvider.redPacketList` 房间红包列表缓存、以及被注释的房间菜单红包入口;当前缺口集中在语音房内完整 UI、发送入口、聊天红包消息展示、打开/领取弹层和进入房间后自动打开红包的消费逻辑。
- 已确认 `expireMinutes` 业务语义为“多久后可领取”,不是过期时间;本轮在 UI 层会按 `In 5 Minutes / Claim Now` 作为领取等待时间选择,后端接口文档出来后再正式对接请求字段。
- 第一步已先落 UI 层:导入桌面 `/Users/nigger/Desktop/app素材/红包` 中的红包菜单、底部发送弹窗、选中态按钮、金币/数量/倒计时、历史、规则、发送按钮、小红包和打开弹层相关 PNG统一放入 `sc_images/room/red_packet/`,并在 `pubspec.yaml` 注册资源目录。
- 第一步已新增语音房红包发送底部弹窗 `RoomRedPacketSendPanel`:当前支持金币档位、红包数量、领取等待时间三组本地选择态,底部展示当前缓存金币余额,规则/历史/发送按钮先保留 UI 占位提示,暂不调用后端。
- 第一步已恢复房间菜单红包入口:语音房底部菜单新增 `Red Envelope` 图标,点击后打开红包发送底部弹窗;后续继续补聊天区红包消息、打开/领取状态弹层、飘屏样式替换和接口对接。
- 已按 2026-05-07 截图反馈修正第一版 UI菜单红包入口补齐与 Music 一致的圆形半透明容器;红包发送弹窗把贴图层级改为“主背景 -> 底部余额栏 -> 顶部红包 -> 内容区”,避免底部红条盖住发送按钮;弹窗高度、背景高度、顶部红包尺寸、内容区位置、选项行高、底部余额栏高度已集中成带注释常量,方便后续继续微调;底部金额旁已补方向箭头,并新增 `en/ar/tr/bn` 多语言文案与 RTL 方向兼容。
- 已按 2026-05-07 15:53 截图反馈继续修正:底部余额栏金币字体缩小、历史图标右侧间距收窄;右上角规则按钮已进入静态规则页,底部历史按钮已进入静态红包发送历史页;两页先使用本地模拟文案/数据,并补齐 `en/ar/tr/bn` 多语言与 RTL 导航方向兼容。
- 已开始第二阶段 UI 层:新增房间红包 UI 数据模型,聊天区 `ROOM_RED_PACKET` 消息可渲染设计图同款红色红包气泡并点击打开弹层;新增打开/领取弹层 UI先支持本地模拟的可打开、已领取、等待、抢完、过期状态红包飘屏已替换为新素材风格的红色横幅 + `GO` 按钮,并在当前房间内点击时直接弹出红包打开层。
- 已修复红包发送底部弹窗规则/历史图标跳转:改为使用全局导航键,并扩大图标热区;同时在房间游戏入口左侧新增 `TEST` 测试按钮,点击后本地模拟发送一条房间红包消息并触发红包飘屏,方便先查看发送后的 UI 效果。
- 已按 2026-05-07 16:47/16:52 截图反馈继续对齐:补入新素材 `未打开红包背景.png` 作为未打开态弹层背景;红包飘窗调整为头像、双行文案、右侧红包图标和 `GO` 图标的设计图层级;聊天红包气泡放宽并降低字号,避免英文提示被截断;领取成功弹层内容整体上移,并去掉压到红包口袋上的冗余提示。
- 已按后端《语音房红包 Flutter 接口对接文档》开始接口对接:发送/领取/详情/配置/发包记录切到 `/app/voice-room/red-packet/*`TIM 登录后拉取当前用户语区红包 IM 群并加入,`0/10013` 都按成功处理,红包飘屏只从全服广播群或当前语区红包群解析,并按 `regionCode` 做同语区过滤;进入房间后每 30 秒上报红包 presence离开/切房时调用 leave发送面板、领取弹层和历史页已接真实接口错误码先映射为多语言提示。
- 已按 2026-05-07 17:55 截图反馈微调Rules 页面顶部导航栏改为满宽安全区布局,返回按钮回到左侧并保留 RTL 方向;红包飘窗重算红条、头像、小红包和 `GO` 图层位置/尺寸,文本禁用系统缩放并使用 `FittedBox` 避免 bottom overflow未打开红包弹层按 472x602 素材比例收窄,并把头像、昵称、说明、金额和 `OPEN` 整体上移,定位常量已集中注释方便继续对稿。
- 已按要求移除房间游戏图标左侧的临时 `TEST` 红包 UI 测试按钮,同时删除本地模拟发送红包消息/飘屏的测试方法,保留真实红包消息链路。
- 已为红包接口排查补充 debug 日志:所有 `/app/voice-room/red-packet/*` 请求都会在控制台输出 `[RoomRedPacket][API]` 请求 path、query/data、耗时、失败 response 和 resolved URL语区 IM 群同步输出 `[RoomRedPacket][IM]`;进入房间红包 presence 心跳输出 `[RoomRedPacket][Presence]`,方便定位 `the path was not found` 具体来自哪条接口。
- 已根据当前测试环境 404 排查结果,把红包新接口统一试切为 `/go/app/voice-room/red-packet/*` 前缀;旧的房间红包列表加密 path 暂不改动,便于对比新旧链路。
- 已根据 Go 后端 400 日志修正请求字段类型:`presence``roomId`、发送红包的 `roomId/totalAmount/totalCount` 改为数字 JSON 提交,避免 `cannot unmarshal string into Go struct field ... int64`;同时发送按钮暂不再用配置接口返回的 `enabled=false` 拦截,方便继续联调真实发送接口。
- 已补齐发送成功后的本地兜底 UI如果后端发送接口成功但语区 IM 群暂未推送 `ROOM_RED_PACKET`,前端会用 send 返回的 `packetId/packetNo` 立即插入一条可点击的聊天红包气泡并触发红包飘窗RTM 消息列表已按红包 packetId 去重,避免后续后端推送恢复后重复展示。
## 本轮个人资料页改版(分步重做)
- 已按 2026-05-06 最新反馈回到旧版个人资料页结构上分步处理,不再一次性重做整页。
- 第一步已去掉个人资料页加载阶段的骨架屏:`ref.userProfile` 或拉黑状态还没返回时,正文区域改为空占位,不再展示灰色骨架块;资料返回后仍按原来的 `Header + About/Giftwall Tab` 结构渲染。
- 第二步已将个人资料页上方默认背景图从旧的 `sc_images/person/sc_icon_my_head_bg_defalt.png` 切换为新素材 `sc_images/person/sc_icon_profile_card_default_bg.png`;用户已有可用 `backgroundPhotos` 时仍优先展示用户自定义背景。
- 第三步已调整头部资料区对齐:深绿资料区去掉顶部圆角改为矩形;头像/头像框移动到中间用户名居中单独一行ID、复制按钮、性别年龄和国旗收成同一行居中展示复制按钮点击后仍写入剪贴板并提示 copied。
- 第四步已继续对齐设计稿ID 行下方新增一行徽章预留占位;用户 `autograph/bio` 已前移到徽章占位下方并按 `Introduction:` 展示Visitor/Follow/Fans 统计块改为 `355*51`、圆角 `8` 的纵向渐隐绿色描边,中间分割线改为高度 `28` 的白色纵向渐隐线。
- 第五步已把个人资料页大背景切到 `#072121`Visitor/Follow/Fans 渐变卡内部保持 `#08251E`;下方 `About me / Gift wall` tab 结构已移除,改为设计图同款纵向 `Wall Of Honors` + `Gift Wall` section。`Wall Of Honors` 现用语音房 music 空态图做占位;两个 section 的 item 统一为 `76*76`、圆角 `8`、纵向渐隐绿色描边,`Gift Wall` 继续复用原礼物墙接口数据。
- 第六步已继续对稿:`Wall Of Honors``Gift Wall` 标题改为图片资源渲染,新增 `sc_icon_profile_wall_of_honors_title.png``sc_icon_profile_gift_wall_title.png`;荣誉/礼物 item 的描边底部透明度提高,解决下边线不明显的问题;非本人资料页底部操作区改为设计稿样式,`Follow``104*36``Chat``215*36`,同为 `#0A342D` 背景、`#18F2B1` 1px 边框、22 圆角和 28 图标;在房间用户会额外显示悬浮 `343*38` 房间入口,左侧头像昵称,右侧 `69*27` Enter 按钮,和底部按钮行保持 43 间距。
- 第七步已按 2026-05-07 最新反馈微调:重新覆盖 `Wall Of Honors / Gift Wall` 标题 PNG 风格Visitor/Follow/Fans 统计卡底部描边透明度提高;荣誉/礼物 item 底部描边透明度继续提高;底部按钮区增加 `#072121`、高度 `93` 的背景;`Follow` 宽度增至 `154``Chat` 宽度缩至 `165`Chat 图标改回旧图标 `sc_icon_person_tochat.png`Following 状态新增并使用 `sc_icon_profile_following.png`
- 第八步已继续按 2026-05-07 最新反馈收口:确认 `Wall Of Honors / Gift Wall` 标题直接使用用户替换后的 PNG 素材,不再自绘标题;非本人资料页底部按钮整体上移并扩大底部安全留白,减少被系统 Home Indicator 遮挡;`Gift Wall` 标题点击已进入新的独立礼物墙页面页面包含返回栏、头像头像框、昵称、Received/Total Value 统计卡、三列礼物列表和底部 `No Further Data Available~` 文案。
- 第九步已修正 Gift Wall 详情页初版问题:顶部导航栏补齐满屏宽度,避免返回箭头挤进标题;头像缩小到 `104`,昵称字号改为正常单次缩放;金币展示改用现有单枚金币动效素材;礼物数据模型兼容 `giftConfig/name/amount/price/value/coins/giftQuantity` 等接口字段,避免礼物名和金额接口有值但页面显示 `-- / 0`
- 第十步已为 Gift Wall 详情页补齐礼物名称/金额解析链路:礼物墙接口返回后会再用全局 `/gift/list` 配置表按 `standardId / id / giftCode / giftPhoto` 做二次匹配,补齐缺失的 `giftName / giftCandy / giftIntegral / giftPhoto`,用于单个礼物卡片和 `Total Value` 统计。
- 第十一步已补齐 Gift Wall 礼物动效预览:礼物卡点击时如果礼物 `giftSourceUrl``.svga`,会在当前页面全屏播放一次 SVGA 动效;播放期间使用页面状态锁防止重复叠加,播放完成或加载失败后自动清理 overlay 状态。
- 第十二步已补 Wall Of Honors 独立页面骨架:个人主页 `Wall Of Honors` 标题点击进入 `/main/person/wallOfHonors`;新页面先按无数据状态只展示满宽顶部返回栏、`My Achievements(0)` 标题、`Honors(0) / Event(0)` 两个 tab 和底部空态文案,顶部栏沿用满宽 `Stack` 写法避免返回箭头挤压标题。
- 第十三步已把个人主页里的墙模块改为预览态:`Gift Wall` 只保留前 9 个礼物用于主页预览,`Wall Of Honors` 当前无数据时也固定展示 9 个占位;进入独立 `Gift Wall / Wall Of Honors` 页面后再走详情页完整数据/页面逻辑。
- 验证进度:`dart format lib/modules/user/profile/person_detail_page.dart` 已执行;`flutter analyze --no-fatal-infos lib/modules/user/profile/person_detail_page.dart lib/modules/user/profile/profile_wall_of_honors_page.dart lib/modules/user/profile/profile_gift_wall_detail_page.dart lib/shared/business_logic/models/res/gift_res.dart lib/modules/index/main_route.dart` 无 error/warning仅保留旧文件原有的 info 级代码风格提示。下一步再继续逐项对齐资料页 UI。
## 本轮 Android 语言房音乐功能(进行中)
- 已查阅桌面《Android音乐添加流程.md》并产出可执行方案文档 `docs/android-room-music-execution-plan.md`覆盖功能范围、模块拆分、Android 权限、声网混音链路、UI 流程、风险点和 GPT 5.5 预估开发工时。
- 已导入桌面 `音乐素材` 文件夹内的 12 张音乐相关 PNG并统一落到 `sc_images/room/sc_music_material_*`,当前用于房间菜单入口、播放器按钮、模式切换、音量、文件夹、更多、删除和编辑等 UI 位。
- 已恢复并接入 Android 本地音频扫描能力:`pubspec.yaml` 新增本地 `on_audio_query` 依赖Android 清单补齐 `READ_MEDIA_AUDIO`,旧版 Android 继续兼容 `READ_EXTERNAL_STORAGE`;权限申请已统一收口到 `SCUtils.checkAudioPermission()`
- 已扩展音乐数据结构:`SCMusicMode` 已从旧的简单歌曲字段扩展为可持久化的本地歌曲模型,新增 `SCMusicFolderMode`;同时新增本地扫描器与仓库层,支持扫描 MP3、按文件夹分组、去重保存、排序归一、删除和本地 JSON 持久化。
- 已新增语言房音乐全局管理器 `RoomMusicManager`,统一管理播放列表、当前歌曲、播放/暂停/停止、上一首/下一首、播放进度、音量、顺序播放/随机播放/单曲循环,并根据麦上/麦下状态切换声网混音的 `loopback` 行为:麦下仅本地播放,麦上可推送到房间。
- 已在声网管理层补齐房间音乐专用封装:新增音乐混音状态回调、麦上状态变化回调,以及开始播放、暂停、恢复、停止、设置进度、读取进度、设置本地和远端混音音量等方法,供房间音乐管理器调用。
- 已完成首版页面链路:新增音乐主页、文件夹列表页、文件夹歌曲选择页、底部播放器和房间内悬浮音乐入口;当前支持空态、扫描添加、批量选择、已添加状态识别、搜索、左滑删除、编辑排序、播放器进度条、音量条、模式切换、暂停/播放和上下首切换。
- 已接入语言房入口:房间底部菜单已恢复 `Music` 入口并跳转音乐页;语音房页面已挂载音乐悬浮入口,离开房间时会主动停止当前房间音乐,避免混音残留到房外页面。
- 已按最新反馈调整房间菜单位置:`Music` 不再单独占用菜单第一行,而是并入常规菜单网格,紧跟在 `Background` 图标之后;背景入口功能开关保持打开状态。
- 已修正本地音乐扫描器的兼容性风险:扫描 MP3 时不再直接读取 `SongModel.fileExtension/displayName/title` 等可能因 Android MediaStore 返回空值而触发异常的 getter改为从插件原始 map 安全取值,并对文件存在性检查和扫描失败做兜底。
- 已按最新音乐页与房间播放器设计继续对稿:音乐管理页右上角只保留添加按钮,排序/编辑按钮移到 `Total songs` 行末;空态不再展示搜索框,搜索框圆角收到 `17`;歌曲 item 改为 `#08251E` 背景和纵向渐隐描边,播放/暂停按钮移到右侧;左滑删除改为固定 `60` 宽删除按钮,需要点击删除按钮后才删除;音乐相关页面点击波浪反馈已收口移除。
- 已重做房间内音乐入口与播放器:右侧音乐浮标不再旋转,并移动到游戏图标上方;点击浮标改为在房间内打开/隐藏播放器,不再直接进入歌曲管理页;房间播放器使用新增的关闭、最小化、上一首、下一首、进入管理页等素材;当前用户在麦上推送音乐时,自己麦位头像左下角会显示并旋转 `用户正在播放bgm` 标识。
- 已继续修正音乐管理页交互细节:歌曲删除按钮现改为与 item 同一行滑出,不再作为底层背景露出;排序拖拽时使用透明 proxy去掉默认白边音乐管理页底部播放器去掉进度条上方多余当前时间和右侧关闭按钮音乐管理页、文件夹页和歌曲选择页的路由切换改为深色 route减少进入/添加音乐时的白屏闪烁。
- 已顺带收口背景相关页面的路由白屏问题:背景选择页、背景上传页和背景预览页现统一走深色 route避免切换瞬间露出默认白底。
- 已补齐 `en/ar/tr/bn` 四套现有多语言文案;当前项目声明支持 `zh`,但仓库里暂无 `assets/l10n/intl_zh.json`,因此中文兜底仍由页面内 fallback 文案承担。
- 验证进度:`flutter pub get` 已通过;音乐相关目录与房间接线文件的定向 `flutter analyze` 无 error/warning当前仅 `rtc_manager.dart``sc_seat_item.dart` 保留项目原有 info 级别风格/废弃 API 提示;全量 `flutter analyze` 仍被仓库既有测试依赖缺失和测试 API 问题阻断;`flutter build apk --debug` 已通过并生成 `build/app/outputs/flutter-apk/app-debug.apk`
## 本轮语言房进房加载逻辑优化(已完成)
- 已按竞品加载思路梳理当前语言房进房链路:当前业务 `entryRoom` 成功后会先进入房间页IM 加群、声网入会、麦位与在线用户刷新在房间页展示后继续进行这与“IM 和声网都完成后才进入完整房间”的体验存在差异。
- 已把语言房进房过程改造为“先进入房间骨架页,再完成关键启动任务”的状态机:新增房间启动态,进入房间页后显示房内 loadingIM 加群和声网入会成功后才切到 ready任一关键步骤失败则进入 failed。
- 已将 IM 加群失败和声网入会失败统一收口到房间页阻断弹窗:失败后不再分散 toast 或静默失败,用户点击确认后会清理 IM 群、声网频道、心跳、轮询与本地房间状态,并返回上一级页面。
- 已为进房失败与语音连接失败提示补齐 `en/ar/tr/bn` 多语言文案,避免新失败弹窗出现硬编码中文。
- 当前麦位与在线用户仍保持分批加载策略:进入房间页后会继续拉麦位、在线用户并启动轮询,头像框、礼物、火箭、红包、榜单等非关键资源仍放在房间进入后的异步补齐链路,避免阻塞首屏骨架。
## 本轮语言房背景页框架(进行中)
- 已按 2026-04-22 当前最新需求先落第一版页面骨架:新增两个独立路由,分别用于“背景选择页”和“自定义背景上传页”;其中语音房底部菜单里的 `Background` 图标入口,现已从旧的房间主题页切到新的背景选择页。
- 背景选择页已按“接近项目商店页”的结构先搭好导航和内容骨架:顶部为返回键、`官方 / 我的` 两个 tab 和右侧 `自定义` 文本按钮;点击右侧 `自定义` 会跳转到新的上传页。当前页内已先补上双列背景卡片栅格、选中高亮和“使用中”状态角标,便于后续继续接后台数据。
- 自定义背景上传页也已完成首版 UI 骨架:顶部为返回键和纯文本标题 `自定义背景图`,中间包含上传框、提示文案、示例区和底部 `Save` 按钮。当前已先接上本地相册选图和回传路径,保存后会把刚选的本地图先带回背景选择页,并插入到 `我的` tab 里做本地预览,先把交互骨架跑通。
- 已按 2026-04-22 最新页面微调继续收口交互细节:背景选择页底部新增了和上传页 `Save` 同风格的悬浮 `add` 按钮,但当前只会在 `Mine` tab 下显示,点击效果与右上角 `Custom` 一致,都会进入上传页;同时 `Official / Mine` tab 的点击波浪反馈已去掉,避免和目标稿风格不一致。
- 已继续统一两页正文区底色:当前背景选择页和背景上传页除顶部导航栏外的正文区域,都固定使用 `#0F0F0F`,不再透出全页背景图;顶部导航区域仍保留现有视觉,以便后续继续微调头部样式。
- 已按最新反馈重做 `RoomBackgroundPreviewPage`:背景选择页点击背景卡片会进入独立预览页,底层显示当前卡片背景图,上层改为复用/贴近现有语音房头部、在线用户条、底部操作栏的真实 UI 骨架;麦位区固定为现有语音房同款 10 麦位布局,并省略礼物/SVGA 等动效层,避免预览页出现布局溢出。底部继续提供 `End Preview``Select again` 两个按钮;`End Preview` 返回后会把当前卡片标记为使用中,`Select again` 则仅返回选择页继续挑选。
- 已继续把语音房消息区的 `All / Chat / Gift` 三个图片 tab 补进背景预览页:当前使用正式房间里的 `sc_icon_room_chat_tab_*` 选中/未选中素材,默认选中 `All`,点击可在预览页内切换 tab 高亮,但不接真实消息列表数据,避免预览页触发房间聊天逻辑。
- 当前这一步仍是“框架版”,还没有正式接入背景后台列表、我的背景接口、上传审核接口和房间背景实际应用逻辑;下一步会在现有骨架上继续把真实数据源、选中态持久化和房内背景切换接进来。
## 本轮靓号动效替换(已完成)
- 已按 2026-04-21 最新靓号动效需求,把桌面“靓号动效”里的 `room_id / room_id_custom / user_id / user_id_4` 四套 `SVGA` 素材导入 Flutter 工程,并新增统一的靓号 ID 展示组件;当前会按 `ownSpecialId != null && expiredTime > now` 判定是否仍为有效靓号,过期靓号会自动回退到原始账号展示。
- 已完成 4 个指定场景的首轮替换接线:`room_id` 现用于房间详情里的房间号,`user_id` 现用于房间在线列表和房间个人卡片,`user_id_4` 现用于个人主页和 `Me` 页;`room_id_custom` 也已同步导入工程并完成资源校验,后续又按最新规则把房内二级页的“个人 ID”统一收口到小号 `user_id.svga`。命中靓号时当前展示为“`SVGA` 徽章 + 靓号文本”同一行,未命中时保持原始 `ID:` 文本样式。
- 已按 2026-04-21 最新视觉反馈继续微调靓号展示:个人主页的靓号行已改回原来的左对齐位置,不再额外居中;同时 `SVGA` 徽章与靓号文本的间距已整体收窄,并已再次核对 `sc_images/general/room_id_custom.svga` 已实际导入工程,避免后续把素材缺失和样式问题混在一起。
- 已按 2026-04-21 最新补充要求继续统一房内二级页的个人 ID 展示:`SVGA` 与靓号文本间距现已进一步收敛到 `0`;房间成员列表、黑名单、贡献榜、房间个人卡片、房间在线列表以及房间详情里的房主个人 ID命中靓号时都会统一改成“小号 `user_id.svga + 靓号文本`”样式,普通账号则继续沿用原始 `ID:` 文本。
- 已按 2026-04-22 当前 UI 对稿需求,临时把这套靓号展示判定整体反转:当前个人主页、`Me` 页、房间在线列表、房间个人卡片、贡献榜、成员列表、黑名单、房间详情里的房主 ID以及房间详情里的 `room id`,都会在“非靓号”时先显示对应 `SVGA` 徽章,便于集中校对尺寸与排版;这一步仅用于临时验 UI后续确认完会再切回正式的“只有靓号才替换”逻辑。
- 已补上“靓号且 VIP 时 ID 数字显示炫彩渐变字”的组件能力预留:当前统一在靓号 ID 组件里支持渐变文字渲染,并新增 `shouldShowColoredSpecialIdText()` 判断;现阶段先复用 `useProps` 里的 `NOBLE_VIP` 做兼容判断,等后端正式 VIP 字段稳定后可直接切到独立接口,不用再逐页返工。
- 已按 2026-04-22 当前 UI 验收需求,临时把炫彩字展示条件整体放开:现阶段这些靓号 ID 展示位无论是否命中靓号/VIP 判断,都会先直接显示炫彩渐变字,专门用于集中验收字号、渐变配色和与 `SVGA` 徽章的搭配;后续确认完视觉稿后,再统一收回到正式条件判断。
- 已于 2026-04-22 UI 验收完成后收回到正式逻辑:当前只有命中靓号时才会用 `SVGA` 替换原来的 `ID` 标识;而具体的账号数字或靓号数字,只有命中 VIP 条件时才会显示炫彩渐变文本。现阶段 VIP 判断先复用 `useProps` 里的 `NOBLE_VIP`,后端独立字段就绪后可继续无痛切换。
## 本轮房间动效优化(进行中)
- 已按 2026-04-21 当前房间卡顿优化方案先落第一步“统一调度层”:新增房间特效调度器,在全屏 `VAP/SVGA` 高成本特效播放或排队期间,暂缓低优先级的房间进场动画、全局飘屏和座位飞屏入队,待高成本特效清空后按小间隔续播,先减少多条动画链路同一时刻抢主线程的情况。
- 本步只处理“调度时机”,没有改动现有动画内部逻辑:礼物/飞屏/飘屏的现有倍率触发规则、现有上限截断、`customAnimationCount` 现有循环方式和当前视觉表现均保持原样,避免第一步就引入联动回归。
- 已继续落第二步“局部重建/重绘隔离”:房间礼物播报条已从整层 `Consumer` 重建改成每个动画槽位独立 `Selector` 订阅,并把运行态数据拍平成快照,减少 `notifyListeners()` 时 4 个槽位整层一起重建;同时为礼物播报条、进场动画、座位飞屏和全局飘屏 overlay 补充 `RepaintBoundary`,先把高频位移动画和底层页面绘制隔离开,降低同屏重绘面积。
- 第二步同样没有改动任何动画业务规则:礼物播报条合并策略、幸运礼物奖励展示、现有队列时长、`customAnimationCount` 的逐个入队方式、现有上限和触发条件都保持原样,这一步只收敛 rebuild / repaint 成本。
- 已顺手补上高成本特效资源预热接线:当前全屏 `VAP/SVGA` 任务一入队就会触发已有的 preload 逻辑,让排队中的特效在前一个播放期间优先完成 `svga decode / 网络文件落缓存`,减少切到下一段时的首帧等待;这一步复用现有预热能力,不改变任何播放顺序和触发条件。
- 已继续补上图片链路的“按展示尺寸解码 + 排队阶段预热”:`buildCachedImageProvider` 现已支持 `network/file/asset` 三类资源统一按逻辑尺寸生成 provider并通过 `ResizeImage` 把解码尺寸压到实际展示大小;同时房间礼物播报条、进场动画、全局飘屏与座位飞屏在入队时会对头像/礼物图做异步预热,减少正式播到该条动画时首次解码和图片闪一下的概率。
- 这一轮同样没有改动任何动画规则或队列行为:只补资源命中率和解码尺寸控制,不变更现有播放次数、上限、倍率阈值、`customAnimationCount` 逐个飞行方式和当前视觉逻辑。
- 已继续收口座位飞屏的图片命中链路:当前在真正批量入队逐个飞行前,会先按飞行动画的大图尺寸预热一次礼物图;同时飞屏 overlay 内部会复用同路径同尺寸的 `ImageProvider`,减少 burst 场景里同一张礼物图连续多次构造 provider 和重复命中解析链路的开销。
- 已继续专项收口“顶部礼物信息播报”的连击卡顿:当前已把礼物播报条的“整条入场动画”和“右侧 `xN` 数量脉冲/续命”拆成独立状态,连击到来时不再通过重启整条 5 秒控制器来硬续播,而是只刷新数量脉冲并延长当前播报条的空闲存活时间;同时右侧数量已改为从当前显示值平滑补间到目标值,减少高频连击或本地批量合并时出现的数字跳变、断档和忽大忽小。
- 这一轮同样没有改礼物业务判断口径:未调整礼物连击的触发条件、上限、截断、倍率门槛和 `customAnimationCount` 等既有规则,只优化顶部播报条自身的显示状态机与数量刷新方式。
- 已继续修正连击播报条“单点送 1 个却直接跳 `+5`”的问题:顶部礼物播报条现已接入 `customAnimationCount` 的点击粒度信息,数量动画不再只按合并后的总量做补间,而是按“单次点击对应的数量步长”逐步递进;例如连续点击 5 次、每次送 1 个时,会按 `+1 +1 +1 +1 +1` 的视觉节奏补齐,而不是直接把右侧数量跳成 `+5`
- 已继续修正连击档位特效偶发“不播”的问题:当前连击 `SVGA` 触发已改为只命中仓库里真实存在资源的档位集合,不再把 `20/88/200...` 这类当前工程里没有对应特效文件的档位当成可播放资源;同时命中判断会按“本次新增后跨过的最高有效资源档位”来触发,避免因为本地批量窗口把多次点击合成一包后,先命中到空资源路径而看起来像整段特效都没播。
- 已按 2026-04-21 最新回归继续修正“飞向麦位的自制动画”缺失问题:座位飞屏现已从房间统一调度器的延后队列中移出,恢复为收到礼物消息后直接入队到全局 `RoomGiftSeatFlightOverlay`;保留既有的图片预热、同会话队列上限和 `customAnimationCount` 逐个飞行逻辑,只撤回此前对这一核心反馈动画的延迟调度,避免用户在礼物命中全屏特效或调度状态未及时清空时误以为飞屏动画消失。
- 已继续加固座位飞屏退出房间后的残留风险:全局 `RoomGiftSeatFlightOverlay` 现已和房间可视特效开关绑定,离开房间后不会再继续挂在首页/探索/消息/我的等页面上显示;同时 overlay 内部的 `postFrame / delayed retry / image precache` 回调已补上会话 token 校验,避免房间退出后旧动画任务把屏幕中央的静态礼物图再次拉起并长期悬挂。
- 已继续修正“房间飘屏在首页/探索/消息/我的也会刷到”的问题:根层房间礼物特效层现已统一改为依据 `RtcProvider.shouldShowRoomVisualEffects` 判断显示,而不再只看偏松的 `roomVisualEffectsEnabled`;同时 `OverlayManager` 在播放房间礼物/幸运礼物飘屏前会再次校验“当前仍在房间可视态且消息房间号与当前房间一致”,房间最小化或退出时也会主动清掉正在播和排队中的房间飘屏,避免房间内的 `5 times`、礼物飘屏等效果溢出到首页等非房间页面。
## 本轮启动优化(非网络)
- 已补回启动页正式展示逻辑:当前 `Weekly Star / Last Weekly CP` 两套自定义启动页都改为“本地有缓存才展示、无缓存不展示”;由于现阶段周榜与 CP 榜接口链路都还未 ready缓存刷新逻辑已先关闭所以当前启动阶段会直接回退到默认 splash不再展示这两套定制视觉稿。相关恢复入口已在缓存类里用 `api-ready-launch-splash` 注释标记,后续接口 ready 后可直接搜索接回。
- 已将启动页展示时间收敛为 `3` 秒,并在右上角新增通用 `skip 倒计时` 按钮:当前按钮会按秒级动态展示剩余时间,点击可立即跳过;文案已补齐 `en/ar/tr/bn` 多语言翻译,并按 locale 输出倒计时文本,便于后续继续做 RTL 语言验收。
- 已按 2026-04-20 最新截图反馈重新校准 `Last Weekly CP` 启动页的头像与昵称区域,并在 `SplashPage` 中单独抽出 `_LastWeeklyCpLayout` 手动微调区;后续如果还要继续挪位置,直接改榜一/榜二/榜三的 `frame/avatar/label Rect` 即可,不用再翻布局层级。
- 已按 2026-04-20 最新确认把 `Last Weekly CP` 启动页临时切到“通用头像占位”模式:由于当前 CP 榜正式接口还未就绪,启动页不再读取本地 `cpList` 或当前用户头像,现统一使用默认头像占位与通用昵称,专门用于先校对双人头像位和昵称区域的 UI 位置;后续接口 ready 后再切回真实数据源。
- 已继续扩展启动页方案:桌面 `启动页_cp榜` 的背景图与 CP 榜一/榜二/榜三素材已导入工程,并新增 `Last Weekly CP` 启动页;当前 `SplashPage` 会在 `Weekly Star``Last Weekly CP` 两套视觉稿之间随机选一张展示,便于一起校对两套 UI 样式。
- 已为 `Last Weekly CP` 启动页补齐本地缓存骨架:新增独立的 CP 榜缓存结构,当前会先把默认占位头像与通用昵称写入本地缓存,后续若改成正式的“有相关缓存才启用”或切到独立榜单来源,只需要替换数据入口,不用重做随机展示和布局层。
- 已按 2026-04-20 新需求在 Flutter 启动页接入 `Weekly Star` 周榜视觉稿:桌面 `启动页_周榜` 的背景图与榜一/榜二/榜三翅膀框素材已导入工程,并替换了原先仅展示静态 logo 的 `SplashPage`,当前会按参考图在启动阶段叠加 3 个头像位和用户名描边文案,便于先校对 UI 样式。
- 已为 `Weekly Star` 启动页补齐本地缓存读写骨架:新增独立缓存辅助类,支持把 `/ranking/top-four-with-reward` 返回的榜单前三头像/昵称写入本地,并在启动时优先读取缓存数据渲染;后续只需要把“当前固定启用”切回“缓存存在时才启用”即可,不用重做布局层。
- 已将 Firebase / Crashlytics 从 `runApp` 前阻塞初始化改为首帧后后台预热,并补充“未就绪时仅本地打印”的异常兜底,减少首屏前平台初始化阻塞。
- 已将 `SocialChatAuthenticationManager``SocialChatUserProfileManager` 改为按需创建,避免 splash 阶段就提前触发 Google Sign-In / Firebase 会话检查。
- 已将 deep link、设备信息、缓存目录创建等非首帧必需动作延后到首帧后执行降低首屏竞争。
- 已优化本地语言初始化:启动时不再重复写入 `SharedPreferences` 并触发一次无意义的 `notifyListeners`
- 已优化首页容器与 Home 首屏:去掉首次进入时“先 loading 再建 tab”的本地跳变并将首页 page 列表、底部导航项从 `build` 阶段的重复重建改为复用。
- 本轮按需求暂未处理网络链路上的启动等待,例如审核态检查或远端启动页配置请求。
## 已完成模块
- 已按 2026-04-20 最新首页视觉需求,为 Party 房间列表前 3 个房卡接入新的本地排名边框 SVGA桌面“房间排序前三的框”中的 3 份素材已导入工程并挂到首页房卡最上层,仅作用于当前列表前 3 项,其余房卡保持原样;后续又继续为前三房卡底部信息区补了横向与底部安全区,避免外扩边框直接压住国旗、房名和在线人数。同时 `Me` 板块里的 `Recent / Followed` tab 已继续对齐上方首页 tab 的斜体字样式,并移除了点击时的波浪反馈。
- 已按 2026-04-20 最新房间联调继续修正房主在自己房间里的麦位操作回归:当前房主/管理员点击自己所在麦位时,不再被“直接打开资料卡”逻辑短路,会重新回到底部麦位菜单,从而正常看到自己可用的上下麦/禁麦操作;同时上麦、下麦、禁麦、解禁、锁麦、解锁这些动作在接口成功后会立即回写本地麦位状态,并主动补拉一次最新麦位列表,减少房主端自己操作后 UI 状态延迟或短暂错乱。最新已继续收紧“换麦”场景:当前会先本地顺滑切到目标麦位,再在短保护窗内拦住把自己打回旧麦位的旧轮询/旧广播快照;同时补修 `MicRes.copyWith(user: null)` 实际不会清空用户的问题,避免切麦时出现双占位或 `1 -> 4 -> 1 -> 4` 这类来回闪动。
- 已按 2026-04-20 最新调整撤掉 `Wallet -> Recharge` 中新增的 MiFaPay 第三方支付 UI 与页面逻辑:当前充值页仅保留原生 `Google Pay / Apple Pay` 入口与商品列表,`Recharge methods` 区域也已收敛为单一原生支付卡片;此前接入的 MiFaPay 方法选择、底部弹窗、H5 收银台页以及对应页面级状态管理已从现有充值链路移除,避免继续对当前版本产生影响。
- 已按 2026-04-18 联调要求继续收口幸运礼物链路:项目默认 API host 已临时切到 `http://192.168.110.43:1100/` 方便直连测试环境;`/gift/give/lucky-gift` 请求体也已补齐为最新结构,除原有 `giftId/quantity/roomId/acceptUserIds/checkCombo` 外,会稳定携带 `gameId: null``accepts: []``dynamicContentId: null``songId: null` 这几组字段,便于和当前后端参数定义保持一致。
- 已继续补齐 `GAME_LUCKY_GIFT` 的 socket 播报与中奖动效:房间群消息收到该类型后,现在会统一落聊天室中奖消息、奖励弹层队列与发送者余额回写,不再只在 `3x+` 时才触发顶部奖励动画;同时全局飘窗已改为按服务端 `globalNews` 字段决定是否展示,避免再用前端本地倍率硬编码去猜。
- 已按最新 UI 口径重排幸运礼物中奖展示:顶部 `LuckGiftNomorAnimWidget` 不再叠加大头像、倍率和奖励框,只在“单个礼物倍率 `>= 10x`”或“单次中奖金币 `> 5000`”时负责播全屏 `luck_gift_reward_burst.svga`;原本的 `luck_gift_reward_frame.svga` 已改挂到房间礼物播报条最右侧,并在框内显示 `+formattedAwardAmount`,金额文案直接复用此前大头像下方那一份中奖金币额。
- 已按最新确认撤掉播报条里的 lucky combo 特殊样式:房间礼物播报条右侧的 `xN` 数字现已恢复普通礼物样式,不再在这里做幸运礼物 10/20/50/100... 的特殊放大/描边展示;这些 `lucky_gift_combo_count_xxx.svga` 资源仍保留在幸运礼物倍率/数量命中时走全屏特效链,不再和播报条 UI 混在一起。
- 已继续修正幸运礼物中奖播报条右侧奖励框不显示的问题:根因是 `pubspec.yaml` 之前只显式收录了 `sc_images/room/anim/gift/`,但没有把新的 `sc_images/room/anim/luck_gift/` 子目录单独打进 Flutter 资源清单,导致 `luck_gift_reward_frame.svga` 在运行时可引用但未被实际打包;当前已补齐资源目录声明,并为播报条奖励框增加本地 fallback避免资源异常时再次只剩金额裸字。
- 已按最新文案口径继续收紧幸运礼物中奖消息:聊天室里高倍率幸运礼物提示不再显示冗长的 `Coins / a lucky(magic) gift` 文字,当前已改为直接展示“中奖金额 + 金币图标 + 对应礼物图”,和房间礼物播报条的视觉表达保持一致。
- 已继续微调幸运礼物中奖视觉:房间礼物播报条右侧的 `luck_gift_reward_frame.svga` 已进一步放大,并给右侧区域和主条正文预留了更宽的排版空间,避免资源已经正常显示但因为画布比例和透明边距看起来过小;同时聊天室高亮中奖消息与房间顶部幸运礼物横幅现已统一改成“中奖金额 + 金币图标 + from + 礼物图”的表达,去掉原先 `Coins / a lucky(magic) gift` 这类冗长英文文案;另外全屏 `luck_gift_reward_burst.svga` 也已补上中部金额文案,避免播发时只见特效不见本次实际中奖金币数。
- 已按 2026-04-20 最新联调继续收口幸运礼物播报噪音:顶部幸运礼物飘屏现在会对同一房间、同一送礼人、同一接收人、同一礼物的连续中奖做队列内聚合,不再每来一条都重新追加一个新飘屏;当前展示中的那一条也会直接叠加金币额并刷新,避免“刷礼过快时飘屏一条接一条排队刷过去”。同时飘屏中奖文案已强制收为单行显示,防止金额、`from` 和礼物图被挤成上下两行。
- 已继续修复房间礼物播报条偶发出现两条一模一样内容的问题:此前 `GiftAnimationManager` 只会和“正在播放”的同 `labelId` 项做合并,等待队列里的同类播报不会提前去重,因此高频情况下仍可能排出两条完全一样的条目;当前已改为在入队时同时检查“正在播”和“待播”两侧,命中相同播报键时直接原地合并,不再把重复项继续塞进队列。
- 已按 2026-04-20 最新确认继续调整幸运礼物展示逻辑:房间播报条最右侧的中奖金币现已按同一条播报累计值展示,不再每次中奖只用最后一笔金额覆盖前一笔;幸运礼物顶部飘屏则撤回此前的聚合策略,恢复为每条都单独展示,但仅当服务端倍率达到 `5x` 及以上时才触发飘屏,避免低倍率也持续刷屏;同时 `luck_gift_reward_burst.svga` 的触发链路已补上“当前房间广播兜底 + 事件去重”,即便只收到广播消息也能进队列播放,而同一事件不会因为广播/群消息双到达而重复播发。
- 已继续修正幸运礼物 `burst` 的倍率边界判断:`LuckGiftNomorAnimWidget` 内部此前仍使用旧的“倍率 `> 10x`”严格大于判断,导致刚好命中 `10x` 的中奖虽然会走飘屏链路,但不会实际触发 `luck_gift_reward_burst.svga`;当前已统一改为“倍率 `>= 10x` 或单次中奖金币 `> 5000`”。
- 已继续修正幸运礼物 `burst` 的实际播放链路:此前 `currentPlayingLuckGift` 队列会把所有幸运礼物中奖事件都排进去,哪怕只是低倍率、根本不需要播 `luck_gift_reward_burst.svga` 的那类消息,也会先占掉每次 3 秒的播放时段;这样在刷得比较密时,真正命中 `10x+``>5000` 金币的事件只是被压在队列后面,视觉上就会像“明明达标了却没触发”。当前已把队列入口改成只接收真正命中 `burst` 条件的事件,并把命中判断收口到同一处,避免顶部飘屏和 `burst` 各自走不同口径。
- 已继续调整幸运礼物播报条的连刷表现:带右侧中奖奖励框的幸运礼物播报现在会固定在各自的坑位上显示,不再跟随普通礼物滚屏那套纵向位移动画反复“刷新整条”;用户连续送同一条幸运礼物时,前端只会在原位更新右侧 `xN` 数量和累计金币,直到连刷停止后再按既有时长自然消失。
- 已继续微调幸运礼物 `burst` 中央金额文案的定位:此前这层 `+金币` 文字仍使用固定 `top` 绝对定位,实际在不同画布比例下会整体偏上,容易跑出 `luck_gift_reward_burst.svga` 中央的金额承载区;当前已改成基于整层居中后再轻微下移的相对锚点,确保金额文案稳定落在特效中间那块 `+****` 的视觉区域内。
- 已继续细调幸运礼物 `burst` 中央金额文案的纵向位置:上一版相对锚点虽然已经回到特效主体内部,但仍略偏下;当前已把对齐点和下移量一起往中间收回一档,让 `+金币` 更接近 `luck_gift_reward_burst.svga` 中央的视觉中线。
- 已继续修正幸运礼物 `burst` 中央金额文案的细节对位:当前已再上移 `2` 个单位,并给金额文本左侧补出额外留白,避免斜体 `+` 号因为字形外扩而贴边或被裁掉,确保 `+金币` 能完整落在特效中部。
- 已继续按最新联调口径修正幸运礼物 `burst` 中央金额文案:当前已去掉文本里的 `+` 字符,仅保留金币数本身显示;同时维持上一版向上微调后的纵向位置,让金额落点保持在特效中部偏上的稳定区域。
- 已继续收口幸运礼物 `burst` 金额文案与 `svga` 本体的时机同步:此前中央金币文本直接跟外层中奖数据显隐,而 `svga` 自身还存在资源加载和单次播放完成的生命周期,所以两者在出现/消失时会有肉眼可见的前后差;当前已给 `SCSvgaAssetWidget` 补上播放开始/结束回调,并让 `burst` 中央金额只在 `svga` 真正开始播时显示、在它播完清帧时一并隐藏。
- 已按 2026-04-21 最新联调继续细调幸运礼物 `burst` 中央金币文案:当前已在现有基础上再向上微调 `4` 个单位、向右微调 `5` 个单位,让金额更贴近特效中部的目标槽位;同时 `burst` 的整体展示时长也已再缩短 `1` 秒,避免命中后在屏上停留过久。
- 已继续修复幸运礼物顶部横幅 `from` 后礼物图标偶发显示不出来的问题:此前这条紫色 lucky gift 横幅只直接使用 socket 下发的 `giftCover/giftUrl` 渲染礼物图,一旦服务端该字段为空或图片加载失败,就只会退回默认占位;当前已把 `giftId` 一并挂进 `SCFloatingMessage`,并在 `FloatingLuckGiftScreenWidget` 内增加“优先用 `giftUrl`,失败时再回退到本地礼物列表缓存中的 `giftPhoto`”的双重兜底,避免横幅末尾再出现空白占位块。
- 已继续补齐幸运礼物横幅礼物图标的“晚到数据”刷新:此前 `from` 后面的礼物图只在横幅首次 build 时用 `listen: false` 读取一次本地礼物列表,若 `giftList` 之后才加载完成,这条 overlay 生命周期内也不会再更新,最终仍会留下空白图标;当前已改为通过 `Selector<SCAppGeneralManager, String>` 监听 `giftId -> giftPhoto` 回退图,并在 socket 未携带 `giftUrl` 时主动补拉一次 `giftList`,让礼物列表就绪后能把幸运礼物横幅末尾图标自动补出来。
- 已继续修正幸运礼物紫色横幅里 `from` 后礼物图“闪一下又空白”的问题:排查后发现这条横幅把礼物图标塞在 `Text.rich` 末尾,而正文又开启了单行省略,导致尾部 `WidgetSpan` 在最终排版溢出时可能被直接不绘制;当前已把礼物图标从内联文本里拆到正文右侧单独布局,保持正文自己省略、礼物图标固定显示,不再因为文本溢出把尾部礼物图一起吃掉。
- 已按 2026-04-21 最新回归把紫色幸运礼物横幅的礼物图取值收口到和其它飘屏同一来源:当前 `RTM` 在构造幸运礼物 `SCFloatingMessage` 前,会优先按 `giftId/standardId` 从本地礼物列表拿同款 `giftPhoto`,拿不到时才退回服务端下发的 `giftCover`;同时紫色横幅组件本身不再额外做自己的礼物图回退和二次解析,只直接显示已统一好的 `message.giftUrl`,避免和其它飘屏走出两套不同的取值链路。
- 已按 2026-04-21 最新排障请求给紫色幸运礼物横幅补齐定向日志:当前会在 `RTM` 解析 `GAME_LUCKY_GIFT` 时输出 `giftId / giftCover / 本地 id 命中 / 本地 standardId 命中 / resolvedUrl`,同时横幅组件自身也会记录一次 `init``gift icon render``gift icon url empty``gift icon load failed`,方便直接判断是服务端字段为空、本地映射错位,还是图片请求本身失败。
- 已根据 2026-04-21 最新日志结论继续收口幸运礼物紫色横幅:日志已确认这条横幅实际拿到的 `giftUrl` 正常且组件已进入渲染分支,因此当前继续把礼物图标的绘制方式直接对齐到其它飘屏的朴素路径,改为更大的 `netImage(url, width)` 直出并使用 `BoxFit.contain`,不再叠加此前那套更特殊的小图标 `borderRadius/noDefaultImg` 参数,优先排除该组件私有渲染参数导致的异常显示。
- 已继续绕开幸运礼物紫色横幅里可疑的小图 `ExtendedImage` 渲染链:当前礼物图标已改为在 `initState` 里先构建 `buildCachedImageProvider`,再通过基础 `Image(image: provider)` 直接绘制,并额外输出一次 `gift icon frame ready` 日志,用于确认这张图是否真的完成首帧解码显示;这样可以把问题进一步收敛为“图片 provider/解码”还是“组件布局/视觉观感”。
- 已按 2026-04-21 最新联调请求,把紫色幸运礼物横幅 `from` 后的图标临时替换为金币图标:这一步只用于快速验证该图标位本身的布局和可见性是否正常,不再受当前礼物图资源链路影响;如果金币图标能稳定显示,就说明问题仍集中在礼物图渲染链,而不是这个位置被遮挡或根本没画出来。
- 已按 2026-04-21 最新回归把 [floating_luck_gift_screen_widget] 的样式撤回到最初实现,不再继续在幸运礼物飘屏横幅上做偏题调试;同时已定位到真正缺图的是消息栏里的 `gameLuckyGift_5` 高亮消息,这条消息此前只写入了 `awardAmount/user/msg`,没有把 `gift` 一并塞进去,导致 `room_msg_item.dart` 读取 `widget.msg.gift?.giftPhoto` 时天然为空。当前已在 `RTM` 构造高亮 lucky 消息时补回 `giftPhoto`,让消息栏里的紫色 lucky message 能和其它消息一样拿到礼物图。
- 已按 2026-04-23 最新横幅替换需求,把房间顶部幸运礼物飘屏横幅的背景层从静态 `sc_icon_luck_gift_float_n_bg.png` 切到本地 `sc_images/room/anim/luck_gift/kojuyee_reback_banner.svga`,并补上 `SVGA` 预热,尽量减少首次出现时先闪旧底图或首帧等待的体感。
- 已在 2026-04-23 继续把这份 `SVGA` 做到可用级“解包”排查:当前已确认它属于 `zlib + protobuf` 结构,不是传统 zip 包;已从运行时结构里定位出 `Avatar``test` 两个可替换图片层,其中 `Avatar` 可直接承载头像,`test` 可承载主文案位。现已把幸运礼物顶部横幅改为优先把头像和主文案直接同步进这两个 `SVGA` 图层,避免外层 Flutter 叠加内容与 `SVGA` 自身位移不同步而越播越偏;同时保留旧版 `png + Row` 作为失败兜底,方便继续联调与回退。
- 已按 2026-04-23 最新验收反馈继续收口幸运礼物顶部横幅:当前已彻底移除这条横幅里的旧静态 `png` 兜底,不再在 `SVGA` 加载期或失败时回落显示原版静态图;同时已把 `test` 文案层的绘制尺寸、字号和内边距重新放大,避免文案缩成左侧一小条,后续继续围绕 `SVGA` 动态层本身微调,不再回退到外层静态叠图方案。
- 已按 2026-04-23 最新联调继续补齐幸运礼物顶部横幅的动态层内容:当前 `test` 图层不再只画主文案,而是会一起合成 `用户名 + get 金额 + from + 礼物图标 + 右侧倍数`;同时 `SVGA` 播放组件改回复用预热后的缓存实体,并在同一实例上重置/重灌动态层,减少每次重解整份 `SVGA` 带来的短暂空白,尽量让横幅保持“触发即播”的体感。
- 已按 2026-04-23 最新验收继续放大幸运礼物顶部横幅的动态文案层:当前 `test` 图层的主文案字号、礼物图标尺寸、右侧倍数字号以及整体承载高度都已继续上调,优先解决“能看见但看不清”的问题;本轮不改触发链路和数据口径,只做可读性增强。
- 已按 2026-04-23 最新验收继续微调幸运礼物顶部横幅尾部区域:当前礼物图标已继续放大,右侧倍数与 `times` 文案也同步加大,并整体右贴到横幅可用区域的最末端,优先吃掉此前尾部残留空位,让右侧视觉重心更贴稿。
- 已按 2026-04-23 最新验收把幸运礼物顶部横幅的右侧倍数从 `test` 文案图层里独立出来,改挂到整条横幅的全宽动态图层上单独绘制:这样右侧倍数不再受原文案层宽度限制,可以真正贴到横幅最末端;同时 `from` 后面的礼物图标也继续加大并缩短与文案的间距,优先解决“图标仍偏小、尾部空位仍过多”的问题。
- 已按 2026-04-23 最新验收继续修正幸运礼物顶部横幅右侧倍数“飞位”问题:当前已撤回那套不稳定的全宽动态图层定位,改为把倍数作为横幅容器内的独立右贴叠层直接固定到末端,优先确保位置稳定;同时 `from` 后面的礼物图标已按最新要求继续放大到更接近 `36` 的视觉尺寸,并进一步压缩与主文案的间距。
- 已按 2026-04-23 最新验收继续收口幸运礼物顶部横幅倍数的“时机不同步”问题:当前已撤回外层独立叠层做法,重新把倍数挂回 `SVGA` 主体条带自身的动态图层坐标系里,优先保证它和横幅本体共用同一条进场/位移时间轴,不再出现横幅在飘、倍数单独漂在上方的现象;礼物图标则继续维持 `36` 视觉尺寸并贴近 `from` 后侧。
- 已按 2026-04-23 最新验收继续微调幸运礼物顶部横幅右侧倍数的排版对齐:当前不再让上方数字和下方 `times` 各自按右边缘贴齐,而是改为共用同一条水平中心线绘制,优先修正“数字偏右、和下方文案看起来不在一列”的问题。
- 已按 2026-04-23 验收收尾要求移除房间右侧的幸运礼物临时验收入口:此前仅用于本地预览顶部 lucky gift 横幅的“测”按钮和本地造消息逻辑已从 `room_play_widget.dart / room_game_bottom_sheet.dart` 删除,房间侧边区恢复只保留正式游戏入口;幸运礼物横幅本身的 `SVGA`、动态头像/文案/倍数链路不做回退或改动。
- 已按 2026-04-24 最新验收需求把幸运礼物 `luck_gift_reward_burst.svga` 拆到可接动态层:当前确认 `avatar / digit01 / digit02` 分别是头像、金币数额、倍数的透明占位层,并已改为在 `SVGA` 自身时间轴内同步注入当前中奖头像、金币数额和 `x倍数`,同时移除此前外层 Flutter 叠加的头像/金额/倍数,避免与 `burst` 动画不同步;验收完成后,房间右侧临时“测”按钮、本地 preview 事件和 RTM 临时 preview 方法已删除,正式幸运礼物触发链路保持不变。
- 已按 2026-04-21 最新特效需求继续调整幸运礼物 `burst`:在 `luck_gift_reward_burst.svga` 下方那块淡色圆角矩形区域,补上了与 `SVGA` 同步进场/消失的中奖倍数文案;当前会和中央金额文本共用同一显隐时机,并在 `multiple > 0` 时展示为 `xN`,避免出现 `x0` 这类无效信息。
- 已继续按 2026-04-21 最新特效稿给幸运礼物 `burst` 补上中奖发送者头像:当前头像会出现在你标的黑块位置附近,并和 `SVGA` 使用同一套开始/结束显隐时机同步出现与消失;头像显示只读取当前中奖事件的 `userAvatar`,不改现有 `burst` 触发条件和播放时长。
- 已优化语言房麦位/头像的二次确认交互:普通用户点击可上麦的空麦位时,当前会直接执行上麦,不再先弹出只有 `Take the mic / Cancel` 的确认层;普通用户点击房间头像或已占麦位上的用户头像时,也会直接打开个人卡片,不再额外弹出仅含 `Open user profile card / Cancel` 的底部确认。房主/管理员仍保留原有带禁麦、锁麦、邀请上麦等管理动作的底部菜单,避免误删管理能力。
- 已继续收窄语言房个人卡片前的“确认意义”弹层:当前用户在麦位上点击自己的头像时,也会直接打开自己的个人卡片,不再先弹出仅包含 `Leave the mic / Open user profile card / Cancel` 的底部菜单;同时个人卡片内的“离开麦位”入口已替换为新的 `leave` 视觉素材,和最新房间交互稿保持一致。
- 已继续微调语言房个人卡片与送礼 UI个人卡片底部动作文案现已支持两行居中展示避免 `Leave the mic` 这类英文按钮被硬截断;房间底部礼物入口也已切换为新的本地 `SVGA` 资源 `room_bottom_gift_button.svga`,保持房间底栏视觉和最新动效稿一致。
- 已按最新要求调整普通静态礼物的自制飞向麦位动画:当前不再对队列里的每一份礼物都重复播放一整段“中央停留 + 飞行”流程,而是改为屏幕中央持续保留一张静态礼物图作为母体;队列中每累积 `1` 个请求,就从中央额外发射 `1` 次飞向目标麦位的动画,同时整体仍维持最多 `5` 个待播/在播请求的上限,避免高频赠送时中央动画反复闪动。
- 已继续优化幸运/CP 礼物连击体验:房间 `Gift/All` 消息面板现在会对短时间内同一发送者、同一目标、同一礼物的连续赠送做聚合更新,不再每点一次就追加一条新消息,而是复用同一条礼物播报并持续刷新成 `xN`同时礼物页底部发送按钮已补上本地连击反馈Lucky/CP/Magic 类礼物连续点击时会显示一条从右向左收缩的浅色倒计时渐变条,并同步累加当前连击数量,用户能更直观看到连击窗口是否还在持续。
- 已继续给发送端补齐连击请求聚合:礼物页当前会对 Lucky/CP/Magic 这类连击型礼物启用约 `200ms` 的本地批量窗口,用户在短时间内连续点击 `Send` 时,前端会先把同一礼物、同一目标集合、同一房间的点击数量累加到同一批次里,再统一发一次接口和一次房间 RTM 消息;这样高连击时不再按点击次数直冲 `/gift/batch``/gift/give/lucky-gift`,同时也避免本地回显和房间消息量被线性放大。
- 已按最新确认回调幸运礼物的“自制飞向麦位动画”策略:不再等整轮连击结束后只飞一次,而是改回按点击次数触发;为兼顾连击体感和队列安全,当前会通过 RTM 额外携带本批次对应的点击次数,让房间端按点击数补齐自制动画,同时同一轮幸运礼物连击的飞行动画队列最多只保留 `5` 个;当连击在 `3s` 内停止后,如果队列里还有待播动画,则只再给 `3s` 消化时间,超时后剩余待播动画会直接清掉。
- 已继续收敛幸运礼物高连击时的播放策略:房间内幸运礼物仍按 3 秒连击会话累计总次数,用来判断当前命中的最高有效档位特效;但自制飞向麦位动画已改回按点击次数触发,并通过“同会话最多保留 5 个待播/在播动画 + 连击结束后额外 3 秒清尾”的方式限制队列膨胀,不再让 `1000` 连击把静态礼物飞行动画排成超长队列;同时幸运礼物的档位特效仍保持只命中当前会话累计数量对应的最高有效档位,不再把中间跨过的 `10/20/30/...` 全部补播一遍。
- 已定位到幸运礼物“中奖通知”使用的是房间页顶层 `LuckGiftNomorAnimWidget`,此前背景一直是静态 `sc_icon_luck_gift_nomore.webp`;当前已改为优先播放本地 `sc_images/room/anim/luck_gift/luck_gift_reward_frame.svga`,而旧 `webp` 实际已不在当前仓库资源内,因此兜底已改为空白占位,避免在 SVGA 初始加载阶段反向触发 `Unable to load asset` 异常。
- 已开始接入幸运礼物连击档位的新动效资源:桌面“幸运礼物相关”目录下的 SVGA 已统一导入到 `sc_images/room/anim/luck_gift/`,并按规范重命名为 `luck_gift_combo_count_10.svga / luck_gift_combo_count_666.svga / luck_gift_combo_count_10000.svga` 这一类统一英文命名;当前连击阈值触发仍复用 `GiftSystemManager.playVisualEffect()`,命中已提供素材的档位时优先播放新的本地 SVGA未提供素材的档位继续保留旧兜底逻辑避免影响现有幸运礼物连击链路。
- 已将语言房送礼链路接入新的“中心停留后飞向目标麦位”组件,但只对无自带特效的静态 PNG 礼物生效:当前带自身 `SVGA/MP4/VAP` 动画或被识别为全屏礼物特效的礼物保持原有播放逻辑不变;只有普通 PNG 礼物会额外触发“屏幕中央停留 -> 三连残影飞向被赠送麦位”的补充动效,避免和自带礼物特效重复叠播。
- 已继续收敛语言房送礼飞行动效的命中条件:上一版对普通礼物的过滤过严,既依赖 `giftPhoto` 必须显式以 `.png` 结尾,也会被部分礼物的 `special` 标记误伤,导致不少实际没有自带动画的礼物被提前跳过;当前已改为只排除真实带 `SVGA/MP4/VAP` 动画源的礼物,普通静态封面礼物即使是带 query 的图片 URL、或不是严格 `.png` 后缀,也会正常触发“中心停留 -> 飞向目标麦位”的补充动画。
- 已将语言房送礼飞行动画从房间页内部 `Stack` 提升到应用根层,挂载方式对齐现有 `SVGA/VAP` 礼物特效层:当前该动画会和 `VapPlusSvgaPlayer` 一样在 `main.dart` 的顶层 builder 中全屏绘制,因此不会再被房间内部聊天区、局部动效或页面层级压住,视觉上更靠前、更容易被用户看到。
- 已修复礼物页幸运礼物发送链路:当前 `gift_page` 会按礼物类型分流,普通礼物继续走 `/gift/batch``LUCKY_GIFT/LUCK/MAGIC` 改走已存在的 `/gift/give/lucky-gift`;幸运/魔法礼物成功后不再本地伪造普通 `GIFT` 消息,而是改发房间内 `LUCK_GIFT_ANIM_OTHER` 动画消息,避免和后端幸运礼物开奖/补发逻辑打架;同时送礼失败已补用户提示,且对 `standardId` 缺失的幸运礼物增加了前置拦截,避免继续点发送却只有日志没有反馈。
- 已继续补齐幸运礼物前端可见反馈:根据真机日志确认 `giveLuckyGift` 和腾讯 IM 房间消息发送都已成功,当前问题收敛为发送端没有本地回显、且 `LUCK_GIFT_ANIM_OTHER` 收到后未真正接入房间礼物动画;现已在发送成功后先本地触发一轮房间礼物上飘反馈,并把收到的 `LUCK_GIFT_ANIM_OTHER` 直接接入现有房间礼物动画 listener确保发送端和房间内其它端都能看到即时反应。排障期间临时加过的发送并发锁已在后续需求确认后撤回不再限制幸运礼物连点。
- 已按最新确认调整幸运礼物点击策略:撤回前一轮为排障临时加上的发送并发锁,恢复幸运礼物可连续点击;当前连点时每次请求仍走 `/gift/give/lucky-gift`,并继续通过本地回显 + `LUCK_GIFT_ANIM_OTHER` 接入现有房间礼物动画 listener 的方式提供与普通礼物一致的即时播报体验。
- 已继续优化房间礼物播报 UI礼物上飘条目高度与内部约束已重新收紧修复底部 `bottom overflow`;同时为幸运礼物新增 10/20/50/100/200/300 连击特殊样式,这些档位的连击数字会以更大的“霸气金”渐变字显示,普通礼物与非里程碑连击保持原样式。
- 已修复 `Me -> Friends/Fans 列表 -> 他人主页 -> 返回 Me` 后个人资料串号的问题:`MePage2` 现只读取当前登录用户资料,`SocialChatUserProfileManager.userProfile` 继续只承载“当前查看中的详情页用户”,同时移除了 `syncCurrentUserProfile()` 对详情态的覆盖,避免查看他人资料后把 `Me` 页错误渲染成对方信息。
- 已按本轮动效替换需求完成首页底部 tab 动效接入,并同步将本轮新增本地 `.svga` 资源统一改成项目命名风格:当前 `Home / Explore / Message / Me` 已分别使用 `sc_icon_home_anim.svga / sc_icon_explore_anim.svga / sc_icon_message_anim.svga / sc_icon_me_anim.svga`,并继续保留原有 png 作为失败兜底;后续新增本地动效资源默认也按 `sc_icon_*_anim` 规则命名。
- 已将语言房右侧 `game` 悬浮入口从 emoji 占位替换为本地动效资源,并按最新反馈移除外层圆形 `container`:当前直接使用 `sc_icon_room_game_entry_anim.svga` 本体作为入口展示,尺寸与原入口占位一致;若 SVGA 加载失败,会自动回退到项目原有 `sc_icon_botton_game.png`
- 已按最新反馈撤回语言房房间麦位声波的 SVGA 替换当前已恢复为项目原有展示VIP3/4/5/6 继续使用原先的 `webp` 声波资源,普通麦位回到原来的纯色圆形扩散效果;说话触发阈值与错峰扩散逻辑保持不变。
- 已修复语言房顶部左侧房间榜单入口出现 `right overflowed` 的问题:当前贡献值区域已改为约束宽度 + 自适应缩放文本,不再因为积分位数变长把右箭头顶出容器。
- 已根据最新确认回退首页 Party 区的 `recommend_rank_top` 三个素材替换:财富榜、房间榜、魅力榜前三头像现已恢复为原先版本,不再在该位置叠加 `recommend_rank_top` 动态头像框;相关素材仍保留在工程内并已按规范重命名,后续待确认真正使用位置。
- 已新增通用本地 SVGA 资源组件 `lib/ui_kit/widgets/svga/sc_svga_asset_widget.dart`,用于统一处理本地 assets 解码、内存缓存、单次播放/循环播放和失败兜底;当前首页底部 tab 和语言房 game 按钮已复用这套实现,便于后续继续接入其它本地动效资源。
- 已按最新语言房底部栏视觉需求完成 UI 重构:底部 5 个入口现改为同一水平基线布局,移除礼物按钮原先的中间悬浮 `Stack` 结构,并按最新顺序调整为“输入入口、礼物、麦克风、菜单、消息”;其中消息入口已移动到最右侧,且在麦克风隐藏时,礼物、菜单、消息 3 个入口会自动向右收拢成一组,避免中间留空。
- 已将语言房左侧输入入口改为独立组件:当前已撤回自绘聊天气泡图标方案,直接恢复使用项目原有的 `sc_images/room/icon_room_input_t.png` 资源作为左侧输入 icon并继续放入约三分之一屏宽的圆角矩形中右侧保留多语言问候文案 `roomBottomGreeting`,避免继续在自绘气泡尾巴形态上反复调整。
- 已将语言房礼物入口拆成独立组件:礼物图标缩小后当前尺寸只略大于右侧 3 个圆按钮,并保留常驻轻量摇晃动画;根据最新反馈,当前已移除礼物按钮的粒子特效,并进一步去掉礼物入口外层 `container`,直接使用与原先按钮壳同尺寸的礼物图片本体作为可点击 UI避免额外底壳干扰观感。
- 已统一语言房其余四个入口的按钮壳样式:输入入口、消息、菜单、麦克风现统一使用淡色半透明背景 container消息红点计数、菜单弹窗、消息跳转和麦克风开关等原有功能逻辑保持不变本轮只调整 UI 展示与布局层。
- 已继续强化语言房右侧消息与麦克风入口的识别度:消息图标已替换为项目内更明显的信封样式资源 `sc_icon_send_user_message.png`,麦克风图标则在不改变按钮壳尺寸的前提下放大到更接近其它入口的可视大小,减少“图标偏小、不够醒目”的问题。
- 已按最新交互要求调整麦克风隐藏态布局:当第 4 个图标(麦克风)可见时,底部栏保持当前 5 个槽位的位置不变;当麦克风隐藏时,不再为其保留空槽位,礼物、消息、菜单 3 个入口会自动向右收拢成一组,避免右侧中间出现空位。
- 已排查语言房“双设备、不同账号进入同一房间,上麦后无声”的直接原因:当前 RTC 进房时统一以 Agora `Audience` 身份加入频道,见 `lib/services/audio/rtc_manager.dart``joinChannel()``clientRoleType: clientRoleAudience`;而本地麦克风开关 `isMic` 默认值为 `true`(当前语义实际是“闭麦”),上麦 `shangMai()` 后只有在 `!isMic` 时才会切到 `Broadcaster` 并取消本地静音,所以“只上麦、不点底部麦克风按钮”时不会发声。
- 已补充语言房当前真实交互结论:现有实现里“上麦”和“开麦”是两个动作。用户点空麦位后只是占麦;还需要再点击底部麦克风按钮,触发 `lib/ui_kit/widgets/room/room_bottom_widget.dart` 中的角色切换,才能真正开始向房间发送音频。
- 已同步补充该需求的后续决策点:如果产品预期是“上麦即能说话”,则需要单独改需求并调整实现为“上麦成功后自动切 `Broadcaster` 且自动开麦”;如果继续保留当前双步骤交互,则至少要补一条明确提示文案/引导,并把“双设备不同账号同房,上麦后需手动开麦才能互听”加入验收用例,避免测试误判为 RTC 故障。
- 已重新收敛语言房无声修复方案:撤回上一轮会影响进房的较大改动后,当前改为只做最小行为修补,不触碰进房和 token/join 链路;已在“底部麦克风点开”和“麦位解除静音且本人处于开麦态”两条路径上补齐 `muteLocalAudioStream(false)`,修正 UI 显示已开麦但 Agora 本地音频流仍保持静音的问题。
- 已按测试收尾要求移除语言房 RTC 诊断面板:该组件仅用于当前无声问题的真机排查,现已从房间页和相关临时诊断代码中整体删除,不作为正式功能保留。
- 已为语言房页面补充右下方 `game` 悬浮入口:入口位于聊天区右下侧、距右侧约 `15.w`、位于底部操作栏上方约 `100.w`,当前先使用代码绘制的 `🎮` 占位图标,并已在实现处标注后续替换为正式 UI 图片资源。
- 已新增语言房游戏底部弹窗:点击 `game` 入口后会从底部弹出约三分之一屏高的面板,采用房间页现有半透明磨砂风格,便于后续继续沿用当前视觉体系。
- 已补齐语言房游戏列表占位结构:弹窗内部先用静态游戏数据驱动,并按“`ListView` 可上下滑动 + 每行 `5` 个图标位”的方式实现,后续只需替换入口图、列表图标和真实接口数据即可继续开发。
- 已排查语言房游戏 H5 无法正常加载的直接原因:当前房内 BAISHUN 游戏页把“加载完成”几乎完全绑定在 H5 主动回调 `gameLoaded` 上,同时 `window.NativeBridge` 又是在 WebView `onPageFinished` 后才注入;真实 H5 若在更早的启动阶段就尝试读取桥接配置或判定 NativeBridge 是否存在,就会错过这次注入,表现为页面一直停留在 `Waiting for gameLoaded...`因此问题核心更接近“App 与 H5 的桥接初始化时序不稳 + 加载态过度依赖 H5 回调”,而不只是单纯的页面 URL 无法访问。
- 已对语言房游戏 H5 链路补齐客户端兜底:房内游戏页现在会在页面启动阶段提前并重复尝试注入 BAISHUN bridge不再只等首个 `onPageFinished`;同时加载遮罩已增加超时收口,不会因为 H5 没有及时回调 `gameLoaded` 就无限卡住。桥接侧也已补充 `getConfigSync`、全局配置缓存和 `baishunBridgeReady/baishunConfig` 事件分发,降低 H5 初始化阶段拿不到配置的概率,便于继续和 H5 联调确认其最终采用的接入方式。
- 已按《BAISHUN 游戏对接文档 1.3.2》重新核对客户端桥接协议:文档里的核心要求并不只是 `NativeBridge` 存在,还包括 `getConfig` 入参携带 `jsCallback`、客户端回调指定 JS 函数、以及 Flutter 章节单独列出的 `getConfig / destroy / gameRecharge / gameLoaded` 四个通道名;当前房内游戏桥接已补充这些文档协议的兼容层,便于直接验证真实 H5 当前到底走的是哪一条调用路径。
- 已新增 BAISHUN 临时调试面板,并封装为独立组件 `lib/modules/room_game/views/baishun_debug_panel.dart`:面板会展示 `entryUrl`、桥接注入次数、最近一次 `jsCallback`、最后一条桥接消息及日志列表,并提供 `Reload / Inject / ReplayConfig / Wallet / ClearLogs` 操作,专门用于这次房内游戏 H5 真机联调;该面板不是正式功能,后续调试完成后需要整块删除。
- 已根据 BAISHUN 文档中“`code` 为一次性参数且唯一”的约束继续收紧客户端下发策略:当前房内游戏页在 bootstrap / `pageFinished` 阶段只注入桥接方法,不再主动把完整配置反复推给 H5真正含 `code` 的配置现在只会在 H5 明确调用 `getConfig` 后回一次,避免因为重复下发一次性 `code` 导致 BAISHUN 后续拉取 `sstoken / user_info` 失败。调试面板也已补充 `ConfigSend` 计数和最近一次配置摘要,便于真机确认是否存在重复下发。
- 已继续增强 BAISHUN 临时调试面板的排障能力:当前已在 H5 侧临时注入 `fetch / XMLHttpRequest / window.onerror / unhandledrejection` 日志回传,相关失败请求、状态码和响应片段会直接显示在 `Recent Logs`,专门用于继续定位当前 `get user info failed` 是否发生在百顺后续拉取 `sstoken / user_info` 的网络链路;这同样只是联调用临时能力,后续调试完成后需要删除。
- 已根据《BAISHUN 游戏对接文档 1.3.2》补齐 `language` 字段兼容:文档表 3 要求传给游戏的语言值是字符串数字枚举(如英文 `2`、阿语 `7`、土耳其语 `10`),而当前客户端真实下发值曾是 `en`;现已在房内游戏页发送配置前统一转换为 BAISHUN 约定值,并把 `raw -> normalized` 结果记录进调试日志,便于继续确认 `get user info failed` 是否由协议字段不匹配导致。
- 已根据最新真机日志继续收敛 BAISHUN 问题边界:当前调试面板已确认 `ConfigSend=1``language=2(raw=en)``getConfig_1_complete``gameLoaded_1_complete` 都已正常走通,说明 Flutter 侧桥接、语言字段和“一次性 code 重复下发”目前都不是主要矛盾;同时 `Recent Logs` 里未出现浏览器侧 `fetch/XHR` 失败,但仍出现 `get user info failed` 弹窗与 H5 内部 `InvalidStateError`,因此当前更倾向于 BAISHUN 服务端继续调用商户侧 `/v1/api/get_sstoken` / `/v1/api/get_user_info` 的链路失败或其返回内容不符合文档要求H5 页面里的报错更像后续症状而非首因。
- 已继续增强 BAISHUN 临时调试能力用于下一轮真机排障:当前除了原有 `fetch/XHR/window.onerror/unhandledrejection` 外,还会额外回传 H5 的 `console.log/info/warn/error` 与资源加载失败信息,并把本地日志保留条数放宽到 `80` 条、面板日志区适当加高;这些都只服务当前联调,不属于正式功能,问题定位完成后需要一并删除。
- 已通过 2026-04-16 真机最新控制台日志拿到更直接的证据H5 侧明确打印了 `{"msgId":"Connect","errCode":1015,"errMsg":"1015-SSToken接口错误","data":null}`,并伴随 `WebSocket Error / WebSocket Close / Reconnect` 日志,说明当前问题已可进一步收敛为百顺游戏在建立长连接前获取 `SSToken` 失败;这表明主要矛盾已经不在 Flutter 容器桥接,而在百顺服务端访问商户侧 `/v1/api/get_sstoken` 的链路、该接口的业务结果、或其返回格式与文档约定不一致。
- 已继续定位“游戏画面可见但触摸无响应”的 Flutter 侧原因:当前实现此前一直把 BAISHUN H5 页面放在 `showGeneralDialog` 底部弹层里承载,同时 App 启动时又全局锁定了 `portraitUp`;对于 `FishingStar` 这类横版游戏,这会叠加出“平台视图在弹层容器中的命中不稳定 + iPhone 端实际不支持横屏”的问题。现已改为用独立路由承载 BAISHUN 游戏页,并按启动数据里的 `orientation` 动态切换横竖屏;同时 iOS `Info.plist` 已补充手机横屏支持,便于继续验证横版游戏触摸是否恢复。上述调整仍属于本轮 BAISHUN 联调修正,不是新的正式产品交互。
- 已按最新联调反馈回撤 BAISHUN 页面的横屏适配:当前后续不会接横屏游戏,因此已去掉游戏页按 `orientation` 切换系统方向的逻辑,并撤回 iPhone 端新增的横屏声明,只保留独立路由承载 BAISHUN 页面这一项 Flutter 容器修正。同时已继续增强临时调试,在 H5 侧补充 `pointerdown / touchstart / mousedown / click` 事件回传,用于下一轮真机直接确认“点击是否真的进到了 H5 DOM”这些输入事件日志依旧只用于本轮排障后续需要删除。
- 已按当前收尾需求移除 BAISHUN 临时调试面板:`BS DEBUG` 组件和相关调试入口现已从游戏页删除,不再作为正式功能保留;同时游戏页展示高度已恢复为接近半屏的底部弹出样式,回到最初设定的房内游戏视觉形态。
- 已继续微调 BAISHUN 游戏页高度:由于真实 H5 内容本身就是接近半屏,且顶部还需要预留拖拽条和标题栏空间,当前底部游戏页容器高度已从上一版的 `0.56` 屏高上调到 `0.62`,避免视觉上看起来比预期半屏更矮。
- 已按 2026-04-22 最新后端协议把语言房游戏数据层切到 `provider` 通用接口:当前会先拉 `/app/game/providers`,再按每个 `provider` 分别请求房间游戏列表,并在点击启动时改走 `/app/game/providers/{provider}/launch`、退出时改走 `/app/game/providers/{provider}/close`;列表项里的 `provider / gameType / launchParams` 也已补进 Flutter 模型,并在启动请求里把 `launchParams` 原样透传回后端。现阶段二级游戏页仍只接 BAISHUN bridge其余厂商先保留“未接线”分流提示避免影响现有百顺逻辑。
- 已继续补上新合作商的前端二级游戏壳子:当前语言房游戏列表点击后,除 BAISHUN 继续走原有 `BaishunGamePage` 外,命中 `provider/gameType=LEADER` 时会进入新增的 `LeaderGamePage`;该页已先具备独立 WebView 容器、底部弹窗样式、`pay / closeGame / loadComplete` 三个 H5 -> Flutter bridge 动作监听,以及充值返回后调用 `updateCoin()` 的 Flutter -> H5 回调。现阶段它仍属于前端预埋壳子,待后端 Leader 启动地址和真实 H5 ready 后再继续补联调细节。
- 创建并持续维护进度跟踪文件。
- 已继续排查语言房 gift 动画链路:确认送礼后会同时走本地房间消息、滚屏礼物条和大额礼物全局飘屏三条路径,并修复动画管理器在控制器尚未绑定完成时提前消费队列导致后续动画不再播放的问题。
- 已定位并修复语言房礼物飘屏资源引用错误:代码里误写 `sc_icon_gift_flosc_bg` / `sc_icon_luck_gift_flosc_*`,实际资源文件名为 `float`,导致点击送礼后飘屏背景图加载失败,相关动画无法正常显示。
- 已继续定位语言房礼物特效不播放的根因:后端礼物配置返回的特效标记为 `ANIMATION`,而前端历史代码只识别拼写错误的 `ANIMSCION`,导致送礼后直接跳过全屏/半屏特效播放;现已改为同时兼容两种标记。
- 已继续优化语言房礼物特效播放性能:将礼物资源预热改为“后台串行预加载 + 选中礼物高优先级预加载 + 播放阶段复用同一解码/下载任务”,避免送礼时重复下载或重复解码同一个 `.svga/.mp4`;同时为全屏播放器增加 `RepaintBoundary`,并改为按原始比例渲染、关闭越界绘制,减少整页重绘和过度放大带来的卡顿。
- 已继续优化礼物二级页首屏与翻页加载体验:礼物配置改为会话内复用,避免每次打开礼物面板都重新拉列表;首屏与翻页页卡增加整页骨架态,页面图片预热改为“当前页并发预热 + 下一页提前预热”,并增加“最短可感知骨架时长 + 最长骨架保护窗口”,避免整页骨架一闪而过;超过上限后再切换到真实卡片,并让单个礼物继续使用小 `loading` 占位补齐,整体交互对齐常见直播 app 的礼物面板体验。
- 已修复首页房间封面显示链路:兼容接口 `roomCover/cover` 双字段,并补齐编辑房间成功后的封面内存回写。
- 已继续修复房间设置保存封面后丢失的问题:房间保存接口改为兼容提交 `id/roomId``roomCover/cover`,并在保存成功后优先保留刚提交的封面、名称、公告,避免被空响应覆盖。
- 已新增按房间 ID 的本地房间资料缓存兜底:首页、我的房间、历史/关注、搜索和再次进入房间都会优先回填最近一次本地保存的封面;同时已将房间封面空态图替换为新的 `sc_no_data.png`
- 已确认房间封面上传接口与 `PUT /room/profile` 保存接口都返回了正确图片地址,并修正首页/重进房间的取值优先级,避免被列表接口短时间返回的旧封面或无效封面重新覆盖。
- 已继续完善个人主页头像与滚动表现:顶部小头像保持纯头像,主头像恢复头像框叠加;同时将个人主页背景并入可滚动 header修复滑动时内容与背景不同步的问题。
- 已进一步统一头像框方案:共享头像组件改为“头像居中 + 头像框包边”结构,并对这类静态头像框资源增加白底去除处理,不再简单把头像框整张盖在头像上;个人主页主头像与房间麦位头像现已同步采用这一展示方式。
- 已修复静态头像框透明区域误变黑的问题:调整头像框白底透明化公式后,进入房间时不再出现只有头像附近有颜色、其余房间背景被黑块覆盖的现象。
- 已修复个人主页首屏黑屏与内容区多余圆角问题:为个人页补充稳定的底图/底色占位,避免进入页面时先出现黑屏;同时移除资料内容区顶部多余圆角。
- 已将个人主页首屏占位升级为骨架屏进入个人页时会先按真实版式展示头像、昵称、计数区、Tab 和资料内容的骨架块,不再先露默认背景等待约 1 秒。
- 已为首页 Party 页补齐首屏骨架屏:顶部 H5 榜单现按三列奖杯卡位展示头像/标题骨架,下方房间区改为双列房卡骨架,并采用深绿底 + 金色描边的项目内风格;同时拆分榜单与房间列表加载态,仅在“首屏无内容加载”时展示骨架,避免下拉刷新时整页闪烁。
- 已为首页 My 板块补齐首屏骨架屏:`My room` 顶部房间卡片改为独立加载态,避免首屏把“正在加载我的房间”误显示成“去创建房间”;`Recent/Followed` 两个子页也已改成同风格双列房卡骨架,进入 tab 时会先展示完整结构占位,再按真实数据切换。
- 已为 `Me` 入口下的 `Store / Bag` 页面补齐首屏骨架屏:四类 `store` 商品页和四类 `bag` 物品页在“首屏空数据加载”阶段都会先展示同风格的三列卡片骨架,不再只显示小菊花;同时已为商品/物品名称补齐宽度约束与省略号处理,避免超长文案顶出卡片。
- 已将通用图片加载占位从静态 `loading` 图片升级为代码绘制的环形转点组件:礼物二级页单卡封面、`Store / Bag` 商品图以及复用共享图片组件的网络图,在“加载中”阶段都会显示动态转圈效果;而图片失败或 `no data` 时仍保持原有占位图,不混淆加载态与空态。
- 已继续细化首页房卡体验:`My` 板块房卡骨架数量已从 `4` 个补齐到 `6` 个,与首页 Party 首屏保持一致;同时将房卡右下角原本的静态绿色“直播中”图片替换为代码驱动的三段式动态音频条,首页、我的、搜索结果和房间浮窗现都会展示跳动效果,不再依赖静态资源图;最新已把动效调整为“单周期完整峰谷 + A/B/C 错峰起伏”的连续波形,观感更接近直播音频电平。
- 已继续微调首页房卡信息密度:房卡底部房名与在线人数字号已统一调小,和动态音频条更协调;同时已移除 `My` 板块顶部 `my room` 标题及其占位,让房间卡片整体上移,对齐更紧凑。
- 已继续微调首页视觉细节房卡底栏房名再次缩小并轻微上移和国旗、动态音频条、人数的中线更一致首页顶部排行骨架也已简化为“3 个圆形头像 + 1 根文本条”,更贴近真实卡片结构。
- 已补回首页 Party 顶部 banner 展示链路:顶部现优先显示原有 `explore` banner并在该分组为空时自动兜底使用首页 `home` banner避免整块区域消失同时首屏 banner 空数据加载阶段已补充同风格骨架占位,不再直接塌陷为零高度。
- 已继续微调首页 Party 顶部 banner 体验banner 与下方排行组件之间已补齐接近房卡区的纵向间距;当 banner 只有 `1` 张时,会关闭无限轮播与横向回弹,左右滑动不再弹回中间。
- 已继续收窄首页 Party 顶部 banner 骨架样式banner 骨架现改为更干净的整块占位,不再在中间叠加长方形白条,首屏观感更接近真实 banner 的整体加载。
- 已优化语言房顶部成员入口的点击范围:右上角在线成员区域现已将左侧头像堆叠区与右侧成员图标统一为同一点击热区,用户点击头像区也可直接打开成员列表页。
- 已继续修复房间封面跨用户不同步问题:当列表或进房返回空封面时,客户端会自动补拉 `room/profile/specific` 详情并缓存真实封面;同时房主保存房间资料后会向房间内其他用户派发资料刷新消息,避免只有自己能看到新封面、其他用户仍显示 `no data`
- 已修复个人主页编辑页头像上传后无变化的问题:上传成功后会先本地回写新头像地址并立即提交;资料更新接口现同时兼容 `userAvatar/avatar` 字段,且不再被紧接着的旧资料回拉覆盖,返回个人主页后头像会即时更新。
- 已进一步定位图片 `no data` 根因并修复客户端加载链:日志确认房间封面详情接口可返回正确公网 `media...` 地址,但用户头像接口会返回 `jvapi.../external/oss/local/...` 这类受保护资源地址;共享图片组件现已对这类地址自动补齐鉴权请求头,避免其它用户侧加载时直接失败为 `no data`
- 已直接校验头像异常地址的服务端返回:`jvapi.../external/oss/local/...` 当前会返回 `500 local disk file does not exist`,并非单纯鉴权缺失;前端现已在编辑资料成功后与本人资料回拉时优先保留刚上传成功的公网头像,避免再次被这类坏地址覆盖,同时修复了房间消息用户资料缓存未真正失效的笔误。
- 已继续修正个人资料更新接口的提交结构:排查发现注册接口使用嵌套 `profile`,而资料更新接口此前只发扁平字段;现已改为同时提交 `id + 扁平字段 + profile`,并在 `profile` 内同步带上 `userAvatar/avatar`,用于兼容后端可能按嵌套对象取值的情况。
- 已按最新联调结果再次收窄个人资料更新参数:日志已证明后端能收到请求但会忽略新头像地址,当前已改为头像相关只提交单一 `userAvatar` 字段,并移除 `avatar/profile` 冗余结构,便于继续验证后端是否对字段名或重复参数敏感。
- 已继续将个人页头像上传链路与通用资料提交拆开:上传成功后当前会单独触发一次仅含 `userAvatar` 的更新请求,不再混带昵称、性别、年龄、国家等字段,便于排除其它参数对头像更新接口的干扰。
- 已继续收敛个人主页资料编辑页提交行为:当前已移除资料列表页中的 `country` 条目及对应跳转/提交逻辑并将昵称、性别、生日、Bio、Hobby、头像改为“改哪项只提交哪项”的增量更新同时修正生日弹窗只会在确认且日期真实变更后才触发提交避免取消或未改动时误发请求。
- 完成仓库结构、依赖引用、资源体积和 APK 组成的第一轮排查。
- 移除 4 个当前未在业务层直接使用的插件依赖:`loading_indicator_view_plus``social_sharing_plus``flutter_foreground_task``on_audio_query`,并清理相关平台声明。
- 修补 `image_cropper 5.0.1` Android 兼容问题,切换到本地 path 依赖以恢复构建。
- 完成 Android release 签名回退配置,解决仓库缺少 `yumi.jks` / `yumi_debug.jks` 时无法继续本地构建分析的问题。
- 完成 release 包体分析,确认 universal APK 过大主要由多 ABI 与 Agora/Tencent 原生 so 导致。
- 去除 Gradle 中与 Flutter 冲突的硬编码 `abiFilters`,确认 `--split-per-abi` 可以正常产出分架构 APK。
- 完成 TinyPNG 环境核查,并接入可执行的 Ruby 批量压缩脚本。
- 已完成 TinyPNG 第一轮批量压缩,`sc_images + assets` 总量已从 `47.25 MB` 降到 `22.54 MB`
- 已增强 TinyPNG 脚本,支持断点续跑、单文件目标和失败项重试。
- 已完成 TinyPNG 网络失败项补跑6 张 `SSL_connect` 异常图片已全部压缩成功。
- 已完成图片压缩后的 release 复测,确认分 ABI APK 体积继续显著下降。
- 已切换 Android `release` 为真正的瘦身模式:开启 `minify``shrinkResources``zipAlign`
- 已完成开启瘦身配置后的 Android release 复测,并接入 `split-debug-info` 保存 Dart symbols。
- 已生成统一的 Python 打包脚本 `scripts/build_release.py`,开始接管 `AAB`、分 ABI APK 与 iOS 包流程。
- 已完成 `scripts/build_release.py` 的 Android / iOS 真机冒烟验证,产物归档目录与 manifest 均已生成。
- 已按当前需求再次完成正式 `AAB` 出包。
- 已定位 Google Play 上传阻塞点:当前 `AAB` 使用的是 `Android Debug` 证书签名,不是正式 upload key。
- 已确认当前项目属于“首次上架的新应用”,后续应走 Play App Signing 首发流程,而不是兼容老签名迁移流程。
- 已梳理 Google Play 首次上架所需的 `Play App Signing``upload key`、重新打包与提审步骤。
- 已澄清首次生成 `upload keystore` 时的“密钥库口令”是本地自行设置的密码,与 Google 提供的 `deployment_cert.der` 证书文件无关。
- 已为新应用生成正式 `upload keystore`,并接入工程的 release 签名配置。
- 已重新打出正式 `AAB`,并确认其签名已经从 `Android Debug` 切换到新的 upload key。
- 已定位 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 的来源为 Agora `full-screen-sharing` 依赖,并开始从主 Manifest 覆盖移除。
- 已移除 `FOREGROUND_SERVICE_MEDIA_PROJECTION` 相关声明并重新打出正式 `AAB`
- 已按当前需求打出正式 `arm64-v8a` 单架构 `APK`
- 已将新的 `google-services.json` 替换进工程,准备重新打包验证。
## 进行中模块
- 评估 iOS 正式签名参数接入后导出 `.ipa` 的流程。
- 继续评估 Agora 扩展 so 与 release shrink 策略是否还能进一步裁剪。
- 评估 12 张 TinyPNG 不支持解码的特殊 `webp` 是否需要改格式或换工具处理。
## 关键技术决策
- 先做高置信度瘦身优先清理未使用插件、ABI 配置和超大图片,暂不贸然删除核心业务能力。
- 避开仓库中用户已有未提交改动,只改必要文件并持续把结果写入本文件。
- 包体分析聚焦 release 产物,不被 `build/`、iOS 中间产物等本地缓存误导。
- Android 架构裁剪交给 Flutter 构建命令驱动,不再在 Gradle 中硬编码 `abiFilters`
-`image_cropper` 采用本地 path 依赖加最小补丁策略,避免升级带来的业务回归面。
- Android 签名配置采用条件回退:正式 keystore 不存在时自动回退到 debug 签名,仅用于本地分析验证。
- 图片压缩优先走 TinyPNG以尽量保持画质稳定失败项按原因分流处理。
- TinyPNG 的 `SSL_connect` 视为可重试网络抖动;`Image could not be decoded` 视为 TinyPNG 对特殊/动图 WebP 的能力边界,先记录不阻塞其余压缩。
## 已改动文件
- `需求进度.md`
- `lib/main.dart`
- `lib/modules/wallet/recharge/recharge_page.dart`
- `lib/shared/business_logic/models/res/sc_mifa_pay_res.dart`
- `lib/shared/business_logic/repositories/config_repository.dart`
- `lib/shared/data_sources/sources/repositories/sc_config_repository_imp.dart`
- `lib/shared/data_sources/models/enum/sc_gift_type.dart`
- `lib/shared/tools/sc_network_image_utils.dart`
- `lib/shared/tools/sc_gift_vap_svga_manager.dart`
- `lib/shared/tools/sc_room_effect_scheduler.dart`
- `lib/services/general/sc_app_general_manager.dart`
- `lib/shared/data_sources/sources/local/floating_screen_manager.dart`
- `lib/ui_kit/widgets/room/floating/floating_gift_screen_widget.dart`
- `lib/ui_kit/widgets/room/floating/floating_luck_gift_screen_widget.dart`
- `lib/services/room/rc_room_manager.dart`
- `lib/services/gift/gift_animation_manager.dart`
- `lib/services/audio/rtc_manager.dart`
- `lib/modules/room/voice_room_page.dart`
- `lib/modules/room/voice_room_route.dart`
- `lib/modules/room/background/room_background_select_page.dart`
- `lib/modules/room/background/room_background_preview_page.dart`
- `lib/modules/room/background/room_background_upload_page.dart`
- `lib/ui_kit/widgets/room/anim/l_gift_animal_view.dart`
- `lib/ui_kit/widgets/room/room_menu_dialog.dart`
- `lib/ui_kit/widgets/room/anim/room_entrance_screen.dart`
- `lib/ui_kit/widgets/room/anim/room_gift_seat_flight_overlay.dart`
- `lib/modules/room/edit/room_edit_page.dart`
- `lib/modules/user/edit/edit_user_info_page2.dart`
- `lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart`
- `lib/shared/data_sources/sources/repositories/sc_room_repository_imp.dart`
- `lib/modules/splash/splash_page.dart`
- `lib/modules/splash/last_weekly_cp_splash_cache.dart`
- `lib/modules/splash/weekly_star_splash_cache.dart`
- `lib/shared/tools/sc_room_profile_cache.dart`
- `lib/shared/business_logic/models/res/room_res.dart`
- `lib/shared/business_logic/models/res/follow_room_res.dart`
- `lib/shared/business_logic/models/res/my_room_res.dart`
- `lib/shared/business_logic/models/res/sc_edit_room_info_res.dart`
- `lib/shared/business_logic/models/res/join_room_res.dart`
- `lib/ui_kit/components/sc_compontent.dart`
- `lib/ui_kit/components/sc_float_ichart.dart`
- `lib/modules/index/index_page.dart`
- `lib/modules/room/seat/sc_seat_item.dart`
- `lib/ui_kit/widgets/room/room_head_widget.dart`
- `lib/ui_kit/widgets/room/room_game_bottom_sheet.dart`
- `lib/ui_kit/widgets/svga/sc_svga_asset_widget.dart`
- `lib/modules/room/detail/room_detail_page.dart`
- `lib/modules/room/online/room_online_page.dart`
- `lib/modules/user/me_page2.dart`
- `lib/modules/user/profile/person_detail_page.dart`
- `lib/shared/business_logic/models/res/login_res.dart`
- `lib/app_localizations.dart`
- `assets/l10n/intl_en.json`
- `assets/l10n/intl_ar.json`
- `assets/l10n/intl_bn.json`
- `assets/l10n/intl_tr.json`
- `lib/ui_kit/widgets/id/sc_special_id_badge.dart`
- `lib/ui_kit/widgets/room/room_user_info_card.dart`
- `lib/modules/home/popular/party/sc_home_party_page.dart`
- `lib/modules/home/popular/mine/sc_home_mine_skeleton.dart`
- `lib/modules/home/popular/follow/sc_room_follow_page.dart`
- `lib/modules/home/popular/history/sc_room_history_page.dart`
- `lib/modules/home/popular/mine/sc_home_mine_page.dart`
- `lib/ui_kit/widgets/room/room_live_audio_indicator.dart`
- `lib/modules/search/sc_search_page.dart`
- `sc_images/index/sc_icon_home_room_rank_border_1.svga`
- `sc_images/index/sc_icon_home_room_rank_border_2.svga`
- `sc_images/index/sc_icon_home_room_rank_border_3.svga`
- `lib/modules/store/headdress/store_headdress_page.dart`
- `lib/modules/store/mountains/store_mountains_page.dart`
- `lib/modules/store/theme/store_theme_page.dart`
- `lib/modules/store/chatbox/store_chatbox_page.dart`
- `lib/modules/user/my_items/headdress/bags_headdress_page.dart`
- `lib/modules/user/my_items/mountains/bags_mountains_page.dart`
- `lib/modules/user/my_items/chatbox/bags_chatbox_page.dart`
- `lib/modules/user/my_items/theme/bags_theme_page.dart`
- `lib/ui_kit/widgets/store/store_bag_page_helpers.dart`
- `sc_images/general/sc_no_data.png`
- `sc_images/general/room_id.svga`
- `sc_images/general/room_id_custom.svga`
- `sc_images/general/user_id.svga`
- `sc_images/general/user_id_4.svga`
- `sc_images/splash/sc_weekly_star_bg.png`
- `sc_images/splash/sc_icon_weekly_star_rank_1.png`
- `sc_images/splash/sc_icon_weekly_star_rank_2.png`
- `sc_images/splash/sc_icon_weekly_star_rank_3.png`
- `sc_images/splash/sc_last_weekly_cp_bg.png`
- `sc_images/splash/sc_icon_last_weekly_cp_rank_1.png`
- `sc_images/splash/sc_icon_last_weekly_cp_rank_2.png`
- `sc_images/splash/sc_icon_last_weekly_cp_rank_3.png`
- `.gitignore`
- `android/key.properties`
- `pubspec.yaml`
- `pubspec.lock`
- `lib/ui_kit/components/dialog/dialog.dart`
- `android/app/src/main/AndroidManifest.xml`
- `android/app/google-services.json`
- `ios/Runner/Info.plist`
- `scripts/tinypng_batch.rb`
- `scripts/build_release.py`
- `tinypng-progress.json`
- `tinypng-report.json`
- `local_packages/image_cropper-5.0.1-patched/android/src/main/java/vn/hunghd/flutter/plugins/imagecropper/ImageCropperPlugin.java`
- `local_packages/image_cropper-5.0.1-patched/`
- `android/app/build.gradle.kts`
- `android/app/upload-keystore.jks`
- `android/app/upload_certificate.pem`
- `build/symbols/android/`
- `build/symbols/ios/`
- `dist/release/smoke-android/`
- `dist/release/smoke-ios/`
- `sc_images/`
- `assets/`
## 已验证结果
- 已通过代码与资源目录交叉核对确认:房内礼物飘屏当前报错 `Unable to load asset: "sc_images/room/sc_icon_gift_flosc_bg.png"` 的根因是资源名拼写错误,而不是消息未下发;工程内实际存在的资源文件为 `sc_icon_gift_float_bg.png``sc_icon_luck_gift_float_bg1~5.png``sc_icon_luck_gift_float_n_bg.png`
- 已确认当前“点击赠送没有动画”至少包含一类前端资源问题:大额礼物/幸运礼物飘屏 widget 已进入渲染,但因为背景图 asset 路径写错而无法显示;全屏 `SVGA/VAP` 特效是否播放仍取决于具体礼物是否带有 `giftSourceUrl`,且 `special` 包含 `ANIMSCION/ANIMATION/GLOBAL_GIFT` 之一。
- 已完成一轮针对卡顿的代码级优化:礼物列表现在只会对真正需要全屏特效的礼物做受控预热;用户选中礼物时会立即高优先级预热该礼物;播放器播放时优先复用内存里的 `MovieEntity` 或同一路径的在途任务,不再重复发起网络下载/重复解码;渲染层也已改为独立重绘边界以减少房间整页跟随重绘。
- 已通过 GiftFX 调试日志确认:示例礼物 `阿拉伯舞蹈` 实际返回 `giftSourceUrl=.svga``special=ANIMATION`,此前前端因为不识别该标记而输出 `skip local play because special does not include ANIMSCION/GLOBAL_GIFT`;本轮已补齐 `ANIMATION` 兼容判断。
- 礼物二级页当前已按“整页骨架 + 当前页并发预热 + 下一页提前预热 + 单卡小 loading 占位”的方式重构首屏加载策略:首次进入和翻页时不会再直接暴露 `noData` 图,且整页骨架会保留一个可感知时长,不再一闪而过;当前页礼物封面会并发预热而不是等每个格子各自串行体感加载。
- 当前工作区存在用户已有未提交改动,后续处理均避开覆盖。
- 首页 `party/follow/history/mine` 以及房间详情使用的房间封面模型已兼容 `roomCover``cover` 两种返回字段,上传封面后不会再因为字段名不一致掉回空占位。
- 房间设置保存封面时,前端现在会同时兼容提交和读取两套字段,并在 `PUT /room/profile` 响应或紧接着的房间详情刷新返回空封面时保留刚上传的封面,不再被空值冲掉。
- 已新增本地房间封面兜底缓存:即使服务端短时间仍返回空封面,首页列表、我的房间、搜索结果、房间头部、房间详情和再次进入房间也会继续显示最近一次本地成功保存的封面。
- 已通过实际请求日志确认:`POST /external/oss/upload``PUT /room/profile` 和随后 `GET /room/profile/specific` 都已返回正确封面 URL本轮问题的根因已收敛为首页/列表链路仍可能使用接口短时间回传的旧值,因此本地成功保存的封面现已提升为更高优先级。
- 房间封面空态图已切换为新的 `sc_images/general/sc_no_data.png`,其资源尺寸为 `288x288`
- 房间资料卡与个人主页使用的用户资料链路已重新对齐:个人页现兼容 `avatar` 别名;顶部小头像不叠加头像框,但主头像会继续叠加头像框资源,且个人页背景已随 header 一起滚动,不再出现内容先滑动、背景停留不动的现象。
- 头像框显示逻辑已改为“框在外、头像在内”的常见样式;针对当前这类带白底的静态头像框资源,已增加白底透明化处理,因此个人主页主头像与房间麦位头像都不会再留下明显白边。
- 静态头像框的透明区域现已保持透明,不会再被错误算成黑色;房间麦位头像、个人主页主头像和其它复用 `head()` 的头像组件进入房间后不会再出现大块黑底遮罩。
- 个人主页现在在数据加载前也会先展示默认背景和底色不会再闪黑“About me / Giftwall” 内容区顶部边缘已改为直角,不再额外出现一个圆角缺口。
- 个人主页当前已接入贴合页面结构的骨架屏,占位期间不会先看到背景图单独显示;资料接口返回后再无缝切到真实内容,首屏观感更平滑。
- 首页 Party 页当前已接入贴合真实版式的骨架屏:进入首页首屏时会先看到三张排行卡位与双列房卡占位,骨架配色已跟随页面深绿+鎏金主视觉,不再只显示居中的白色 `loading`;且排行榜与房间区会按各自请求结果独立切换,先返回的区域会先显示真实内容。
- 首页 My 板块当前已接入贴合真实版式的骨架屏:顶部 `My room` 现区分“首次加载中”和“确实未创建房间”,不会再先闪出创建房间卡;`Recent/Followed` 在首屏空数据加载时也会先展示双列房卡骨架,不再只显示小菊花或局部空白。
- `Me` 入口下的 `Store / Bag` 页面当前也已接入深绿主题的三列卡片骨架:首次进入并且列表尚未返回时,会先显示与正式卡片比例一致的占位;接口返回后再切到真实商品/物品卡片。`store``bag` 卡片标题现都带宽度约束和单行省略,类似截图里的长名称不会再横向撑破布局。
- 图片加载态与空态当前已拆分:共享网络图组件和礼物二级页单卡封面加载时会显示代码绘制的环形转点,不再继续复用 `sc_icon_loading.png`;若图片失败或确实无数据,仍旧保留原先那张占位图,避免把 `loading``no data` 看成同一种状态。
- 首页与搜索等房卡右下角的在线状态图标当前已改为代码绘制的动态音频条:三根绿条会按不同相位走完整的波峰波谷周期,错峰连续起伏,视觉上更接近直播/语聊房的实时状态;`My` 板块骨架数量也已与 Party 页对齐为 `6` 个。
- 首页房卡底部信息当前已进一步收紧:房名和人数文字比上一版更小,底栏与动态音频条的视觉重心更一致;`My` 页顶部 `my room` 标题也已移除,下方卡片和 tab 会自然上移填充。
- 首页顶部排行骨架当前已进一步收窄为单条标题占位,不再保留两条文本骨架;房卡底栏房名也已再次缩一号并做轻微上移,对齐更贴近设计稿观感。
- 目录体积排查显示:`build/``4.7G``.dart_tool/``347M``ios/``250M``sc_images/``48M``local_packages/``6.1M`
- 当前包体过大的主要原因已经确认:
- universal APK 带入了 `arm64-v8a``armeabi-v7a``x86_64` 三套 ABI。
- Agora 与腾讯 IM 原生 so 很大,其中 `libagora-rtc-sdk.so` 合计约 `79.4MB``libImSDK.so` 合计约 `10.2MB`
- 资源目录中 `sc_images/index``sc_images/room``sc_images/person``sc_images/splash` 是最主要的大图来源。
- `flutter build apk --release --target-platform android-arm64 --analyze-size` 已成功执行,当前 universal release APK 约 `271MB`
- `flutter build apk --release --split-per-abi` 已成功执行,压缩前分架构 APK 约为:
- `app-arm64-v8a-release.apk``161.4MB`
- `app-armeabi-v7a-release.apk``138.8MB`
- `app-x86_64-release.apk``148.6MB`
- `loading_indicator_view_plus``social_sharing_plus``flutter_foreground_task``on_audio_query` 已从当前依赖链路中移除。
- 当前图片资源统计为 `412`TinyPNG 两轮处理后总量已从 `47.25 MB` 降到 `22.27 MB`,累计节省约 `24.99 MB`
- 当前 TinyPNG 已成功压缩 `400` 张图片,剩余失败 `12` 张。
- 当前压缩收益最大的图片包括:
- `sc_images/person/sc_icon_edit_userinfo_bg.png``2640776 -> 436823`,节省约 `2.10 MB`
- `sc_images/splash/sc_splash.png``2373335 -> 379804`,节省约 `1.90 MB`
- `sc_images/room/sc_icon_room_defaut_bg.png``2243222 -> 704696`,节省约 `1.47 MB`
- `sc_images/index/sc_icon_index_bg.png``1422169 -> 420635`,节省约 `0.96 MB`
- 失败项已分型:
- `12` 张为 TinyPNG 无法解码的特殊/动图 `webp`
- 当前 TinyPNG 进度与统计文件已落盘:`tinypng-progress.json``tinypng-report.json`
- 图片压缩后再次执行 `flutter build apk --release --split-per-abi`,当前分架构 APK 已下降到:
- `app-arm64-v8a-release.apk``135.2MB`,比压缩前少 `26.2MB`
- `app-armeabi-v7a-release.apk``112.6MB`,比压缩前少 `26.2MB`
- `app-x86_64-release.apk``122.4MB`,比压缩前少 `26.2MB`
- 可以确认:这轮图片压缩带来的资源收益已经真实反映到最终 APK 体积中。
- 在开启 `minify``shrinkResources``zipAlign` 并追加 `--split-debug-info=build/symbols/android`Android release 继续下降为:
- `app-release.aab``181.8MB`
- `app-arm64-v8a-release.apk``128.7MB`,比上一轮 `135.2MB` 再少 `6.5MB`
- `app-armeabi-v7a-release.apk``105.8MB`,比上一轮 `112.6MB` 再少 `6.8MB`
- `app-x86_64-release.apk``115.8MB`,比上一轮 `122.4MB` 再少 `6.6MB`
- `build/symbols/android` 已生成 3 份符号文件,总计约 `14MB`,后续可用于 Dart 堆栈还原。
- `scripts/build_release.py --platform android --output-dir dist/release/smoke-android` 已验证通过,归档结果为:
- `android/google-play/` 下输出 `yumi-v1.0.0-b1-google-play.aab` 与 Dart symbols
- `android/local/` 下输出 `arm64-v8a.apk``armeabi-v7a.apk`
- `android/testing/` 下单独输出 `x86_64-test.apk`
- 同时生成 `build_manifest.json`,已记录产物路径、大小和 `sha256`
- `scripts/build_release.py --platform ios --output-dir dist/release/smoke-ios` 已验证通过,当前无签名模式下输出:
- `ios/archive/yumi-v1.0.0-b1.xcarchive`
- `ios/symbols/app.ios-arm64.symbols`
- 当前 iOS 无签名构建会跳过 `.ipa` 导出;如需正式 `.ipa`,脚本需追加 `--ios-codesign`
- 已将 `dist/` 加入 `.gitignore`,避免打包产物持续污染工作区状态
- 本轮按需执行 `flutter build appbundle --release --split-debug-info=build/symbols/android` 已成功,产物为:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积约 `181.8MB`
- 本地校验 `app-release.aab` 证书后确认:
- 证书所有者为 `C=US, O=Android, CN=Android Debug`
- 当前 AAB 的 `SHA1``6B:72:BF:6F:D1:7A:F2:99:CD:F3:14:EE:18:A6:29:67:F8:05:E6:B4`
- 这说明当前 release 构建仍在回退使用 debug signing无法直接作为 Google Play 正式发布包
- 已生成新的 upload 证书文件:
- `android/app/upload-keystore.jks`
- `android/app/upload_certificate.pem`
- 新 upload key 当前指纹为:
- `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3`
- `SHA256: 81:D6:3A:43:31:FA:83:87:0E:C3:5B:52:B8:C1:05:7C:3A:32:EC:24:37:0B:11:E4:2F:8C:62:4E:D4:AC:0C:3B`
- release 构建已改为从 `android/key.properties` 读取正式 upload keystore不再依赖当前的 debug 回退配置
- `flutter build appbundle --release --split-debug-info=build/symbols/android` 已重新执行,当前正式产物仍为:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积约 `181.8MB`
- 重新校验该 AAB 后,签名者已变为:
- `CN=Yumi Upload, OU=Mobile, O=Yumi, L=Shanghai, ST=Shanghai, C=CN`
- `deployment_cert.der` 已核实为 Google 侧 app signing 证书,指纹为:
- `SHA1: 3F:E1:78:DC:C3:29:4F:74:20:DF:27:54:CF:AF:46:46:D6:A1:94:78`
- `SHA256: F9:BF:D0:89:F9:D7:FD:B2:53:24:A7:DB:59:E1:52:6F:54:A3:93:95:4E:88:7F:1C:4B:D6:03:66:E7:1A:1F:85`
- 已确认当前存在两套不同证书:
- 本地 `upload key`:用于你上传 AAB 到 Google Play
- Google `app signing key`:用于 Google Play 最终给用户分发签名包
- `FOREGROUND_SERVICE_MEDIA_PROJECTION` 在当前 release 合并报告中的来源已确认是 `io.agora.rtc:full-screen-sharing:4.5.2`
- 该依赖同时还带入了:
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService`
- 主 Manifest 已添加 `tools:node="remove"` 覆盖规则,准备重新打包验证最终合并结果
- 重新打包后release manifest merger 报告已显示:
- `uses-permission#android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION`
- `REJECTED from [io.agora.rtc:full-screen-sharing:4.5.2]`
- 当前 release 中已不再检测到以下声明:
- `android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity`
- `io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenSharingService`
- 新的正式产物已重新生成:
- `build/app/outputs/bundle/release/app-release.aab`
- 当前 AAB 体积仍约 `181.8MB`
- 新 AAB 证书仍为本地 upload key
- `SHA1: C1:80:AF:BF:6E:1F:F2:F4:49:58:72:87:A2:BC:54:07:E7:D2:D9:A3`
- 本轮按需执行 `flutter build apk --release --split-per-abi --target-platform android-arm64 --split-debug-info=build/symbols/android` 已成功,产物为:
- `build/app/outputs/flutter-apk/app-arm64-v8a-release.apk`
- 当前 `arm64-v8a` APK 体积约 `128.7MB`
- 已核对新旧 `google-services.json`
- 原文件与新文件都匹配包名 `com.org.yumi`
- 下载文件已成功覆盖到 `android/app/google-services.json`
- 当前工程内文件 `SHA256` 为:
- `a1706496a01f74d27e6c60598144cecc978934b02a87567e1ced887b5b0185d5`
## 语音房区域飘屏
- 已开始按《语音房区域飘屏-Flutter接口对接文档》落地继续复用当前 `/go/app/voice-room/red-packet/im-group` 加入语区 IM 群,红包 `ROOM_RED_PACKET` 和大额礼物 `SEND_GIFT` 都从语区群接收;红包区域过滤仍尊重后端语区群,同时保留前端 `regionCode` 兜底校验。
- 已给 `SCFloatingMessage` 增加 `broadcastScope=region` 作用域,`OverlayManager` 会把区域飘屏限制为“当前房间同房红包可展示”或“退出房间后首页四个一级 Tab 可展示”,避免在二级页、非当前房间页继续刷区域飘屏。
- 已让首页主框架 `SCIndexPage` 接入 `RouteAware`,在首页/探索/消息/我的四个一级 Tab 位于栈顶时开启区域飘屏展示,进入房间页或其它二级页面时关闭并清理排队中的区域飘屏。
- 已新增区域群 `SEND_GIFT` 处理:当前房间同房礼物会跳过以避免和房间 IM 礼物飘屏重复;非当前房间礼物会优先用本地礼物列表解析 `giftPhoto`,缺失时回退后端 payload 图片,点击仍复用现有礼物飘屏的 `SCRoomUtils.goRoom(...)` 进房逻辑。
- 已继续处理红包领取入口和多红包交互:领取弹层支持多个红包横向滑动,未领取/倒计时态都会显示红包总金额;倒计时从后端 `claimStartTime``countdown` 折算成本地目标时间并每秒刷新,倒计时归零后自动切到可打开态并刷新房间红包列表;房间右侧游戏图标下方新增红包入口,有可展示红包时出现,点击进入红包领取弹层。
- 已按 2026-05-08 最新截图继续修正领取层:`PageView` 关闭裁剪并加高承载区域,避免已领取态头像被顶部裁掉;聊天红包/飘屏红包点开时会自动合并当前房间红包列表,保证两个及以上红包可左右滑动并露出左右卡片;倒计时文案移到 `OPEN` 按钮下方;房间右侧红包入口改到音乐图标上方,显示条件改为“未领取、未过期、且服务端未明确 sold/finished”避免缺失 `remainCount` 时入口被误隐藏。
- 已继续修正房间右侧红包入口和已领取态:右侧入口现在同时合并后端房间红包列表与聊天区 `ROOM_RED_PACKET` 消息,避免列表接口未及时刷新时入口不出现;领取成功后会记录本机已领状态,聊天红包点击前也会拉取红包详情,已领取红包会提示“已领取过”并进入已领取结果态,不再显示可 `OPEN` 的领取态。
- 已按新设计补充红包发送历史样式:历史列表先改为“发送红包头部 + 领取人明细”分组展示,头部展示发包金额/退款金额,明细展示领取人头像、昵称、领取时间和领取金额;发送记录若未直接返回领取明细,会用红包详情接口补拉 `records`Rules/History 顶部返回按钮统一向左贴齐。
- 已继续按反馈拆分历史详情:红包历史页现在只展示用户发出的红包记录,点击某条红包后进入独立的领取记录页;领取记录页按需调用红包详情接口拉取该红包的领取人列表,避免历史页直接展开导致视觉拥挤和一次性请求过多。
- 已按 2026-05-08 16:21/16:24/16:29 截图继续修正红包领取弹层:红包详情缺少头像/昵称时会保留聊天消息或飘窗 payload 的用户资料,避免过期/抢完态顶部回退成默认红包图;多红包横向滑动的 `viewportFraction` 调大,拉开左右卡片间距;已领取成功态补强昵称展示,昵称改为红色大字,`You Get` 与金额字号、颜色、金币图标尺寸按设计稿重新微调。
- 已修正发送红包后的飘屏兜底策略:发送成功后本地立即插入聊天红包消息并触发一次红包飘屏,`OverlayManager` 再按 `packetId` 做 30 分钟红包飘屏去重,避免后端语区 IM 回推后重复飘;同时把历史页和领取记录页顶部导航栏改为满宽布局,返回按钮真正贴齐左侧。
- 已修正倒计时红包从聊天气泡进入被误判“已抢完”的问题:红包详情缺少 `remainCount/countdown/claimStartTime` 或状态字段不一致时,会合并聊天/房间列表里的倒计时与余量数据,未来可领取时间优先于抢完状态判断,保证聊天气泡入口和右侧红包入口展示一致。
- 已补齐房间外区域红包飘屏进房后的领取入口:同语区 IM 收到 `ROOM_RED_PACKET` 时会按 `roomId + packetId` 缓存一份待领取红包;用户在房间外点飘屏进房后,右侧红包入口会合并接口列表、聊天红包消息和这份区域飘屏缓存,避免列表接口未及时返回时没有红包图标;领取成功或切账号登出会清理对应缓存。
- 已补齐普通进房/重进房的红包入口刷新:正常进入房间不会回放 AVChatRoom 历史红包消息,所以右侧红包入口主链路仍依赖房间红包列表接口;进房后现在会在 0s/2s/6s 连续刷新红包列表,覆盖“刚发延时红包后用户马上进房、列表短暂未同步”的情况。
- 已修正右侧多个红包入口领取后的残留:本机已领取状态现在会通知右侧红包入口重建,领取成功会同步移除待领取缓存并过滤列表/聊天来源里的已领红包;入口点击前也会重新计算最新可领列表,避免继续打开最后一个已领取红包。
- 已补齐房间内同语区即时红包的主动弹层:当前房间收到 `ROOM_RED_PACKET` 时会写入缓存、刷新列表、插入聊天消息,并在非本人发送且红包已可领取时立即打开领取弹层;延时红包仍保留右侧入口和聊天入口,不强制弹等待层。
- 已给红包历史页和领取记录页加上房间特效屏蔽:进入页面时会立即清掉当前飘屏队列、停止并暂停礼物 `VAP/SVGA` 播放和延迟特效任务;从历史页继续进入领取记录页时保持屏蔽状态,直到两个页面都退出后才恢复,避免房间里的飘屏或 SVGA 漏到红包二级页。
- 已修正红包历史页和领取记录页的 RTL 排版:列表主文本列改回 `start` 对齐以跟随 RTL 靠右,金额列跟随 `end` 靠外侧;金额和时间强制按 LTR 渲染,避免阿语环境下时间顺序错乱或负号跑到数字后面。
- 已按最新接口文档接入红包领取记录新接口:领取记录页优先调用 `GET /go/app/voice-room/red-packet/claim-records?packetNo=...` 拉取领取人列表,失败时再兜底旧 detail records同时历史页和领取记录页跳转改为深色无默认转场 route避免进入页面时先闪一下白屏。
- 已将红包规则页替换为正式规则文案,并同步更新 `en/ar/bn/tr` 多语言;第 4 条每日房间红包发送上限不再写死,进入规则页时调用红包配置接口读取 `dailySendLimit` 后填入 `%1$s` 占位。
- 已补齐红包领取记录页的发包摘要:从发红包记录页点击进入后,顶部固定展示该红包图标、红包数量、发送时间、发出金额和退款金额;即使领取列表为空仍展示红包金额,空态只作为领取人列表区域提示。
- 已新增红包发送余额不足充值引导:发送接口返回 `voice_room_red_packet_insufficient_balance` 时关闭红包发送面板,改为弹出约半屏高度的底部充值弹窗,展示当前金币余额和充值按钮;点击充值复用 `me/wallet``WalletRoute.recharge` 进入充值页,返回后刷新用户余额。
- 已按反馈统一红包入口图标:房间右侧待领红包入口去掉黑底和金色外圈,直接展示放大的红包图标,尺寸与游戏入口接近;房间菜单内红包项也从白色线性图标改为同一张红包图标。
- 已继续修正红包跨房间与消息链路:同语区区域红包飘屏现在允许在其它语音房内展示;首页点击红包飘屏 `GO` 会直接进房,不再先弹确认或自动弹领取层;进房加入 IM 群后会拉取最近至少 10 条、当前按 20 条房间历史自定义消息并补入红包聊天记录;红包领取成功后,领取者会自动发送一条“从某用户 Lucky Pack 领取多少金币”的多语言房内 IM 文本消息。
- 已继续修正红包入口状态刷新:房间右侧红包入口现在每秒清理过期缓存、每 5 秒刷新当前房间红包列表,并以后端列表里“已领/过期/抢完”的 packetId 作为权威隐藏来源;连续两次成功刷新后,若某红包曾在后端列表出现、但已不在后端可领列表中,也会过滤旧聊天消息或区域飘屏缓存,领取时遇到“已过期/已抢完”也会立刻本地隐藏入口,避免已不可领红包重新显示;同语区红包飘屏仍可跨房间展示,但即时红包领取弹层只会在 payload `roomId` 等于当前语音房时自动打开。
- 已调整红包余额不足充值链路:`voice_room_red_packet_insufficient_balance` 不再只是展示“去充值”二次入口,底部弹窗内直接复用钱包页的 Google/Apple Pay 初始化、商品档位选择、余额刷新和支付发起逻辑;钱包页原本的充值确认弹窗保留,红包弹窗内点击充值会直接调起系统支付。
- 已修正两个红包联调问题:当前房间点击红包飘窗 `GO` 打开领取层时会合并房间缓存中的完整红包 payload避免限时红包丢失 `claimStartTime/countdown`;领取成功后发送的房内 IM 文本会附带不展示的唯一业务 key避免同一用户连续领取同一发包人的多个红包时公屏只保留一条领取记录。
- 已收口红包发送记录页状态展示:不再显示 `Pending/等待中`,后端 `ACTIVE/PENDING` 等中间态统一展示为已发出;只保留已退回、已领完、已发出三类状态,并补齐多语言的“已领完”文案。
- 已收口房间外红包领取层触发:红包飘屏 `GO` 只有在目标房间页面当前可见时才直接打开领取层,否则先进房;同语区或房间 IM 收到即时红包时,也只有当前可见房间匹配目标 `roomId` 才自动弹领取层,避免首页、房间列表、我的页直接弹抢红包。
- 已按最新反馈修正领取记录头像和跨房进房:领取记录空头像不再回退成红包图标,统一走项目默认头像;红包飘窗 `GO` 跨房点击直接进目标房间,不再弹进入房间二次确认。
- 已修正延时红包多入口数据不一致:公屏红包消息会同步写入待领缓存,右侧入口和领取弹层遇到同一 `packetId` 会合并接口列表、缓存和聊天 payload 的倒计时字段,避免飘屏 `GO`/右侧入口丢失倒计时;领取成功后右侧入口会优先按本地已领状态隐藏,避免接口刷新滞后导致残留。
- 已补齐红包发送后的 IM 广播:发送成功后除本机兜底展示外,会把 `{type: ROOM_RED_PACKET, data: payload}` 发送到当前房间 IM 群和当前语区 IM 群;同房用户通过房间群看到公屏/飘屏,房外或其它房同语区用户通过语区群看到飘屏,并继续依赖 `packetId` 去重避免重复展示。
- 已修正红包领取成功公屏消息的多语言问题:领取后不再发送已翻译好的普通文本,改为 `ROOM_RED_PACKET_CLAIM` 结构化房间 IM只传领取金额、红包发送人名和 `packetId`,公屏渲染时按当前客户端语言生成文案,避免英文用户看到阿语消息。
- 已补强房外延时红包飘屏和领取通知去重:首页四个一级 Tab 可见/回到前台时会重新同步当前语区红包 IM 群;语区红包飘屏在首页 Tab 中不再受“只看房间飘屏”设置影响;领取成功公屏通知按 `packetId + 领取人ID` 生成稳定去重键,避免本地插入和 IM 回包/历史拉取造成两条一模一样的领取消息。
- 已定位并修复公屏上滑历史反复弹 `user info not found`:历史消息 item 重建时会重复调用用户资料接口,缺失用户返回错误后被网络层 toast现在房间公屏补拉用户资料改为静默请求并对同一 userId 的请求/失败结果做缓存5 分钟内不再反复请求同一个不存在用户。
- 已继续排查房外/跨房红包飘屏缺失IM 重登成功后会立即重新同步当前语区红包群;收到未登记但内容为 `ROOM_RED_PACKET` 的群消息时会按语区红包飘屏兜底处理,避免语区群 id 尚未写入时被普通群消息分支吞掉;区域红包在首页 Tab 暂不可见时不再直接从飘屏队列丢弃,而是挂起后在回到首页 Tab 时恢复播放;发送红包 payload 也会补齐当前房间 `regionCode`,便于日志核对和前端兜底过滤。
## 已知问题
- 已接入语音房表情包素材第一版:桌面 `表情素材` 中的 `fluent_emoji``monkey` gif 已纳入项目资源,底部聊天入口改为图稿里的短白色胶囊并移除内部输入图标,右侧新增独立表情按钮;同一个房间输入弹层现在可从表情按钮直接打开表情包面板,原 unicode emoji 面板已替换为本地 gif 表情。发送逻辑同步按最新规则分流:用户在麦上发表情时只在自己麦位播放,不进入聊天列表;用户未上麦发表情时进入房间聊天框展示,不触发麦位动画。
- 已按最新截图回调把语音房底部聊天胶囊底色改回原先的灰色半透明风格,同时保留短胶囊和右侧独立表情按钮;针对 gif 表情在选择栏、聊天框、麦位展示中偶发闪烁的问题,新增统一的房间表情 asset 展示组件,复用 `AssetImage`、提前预热本地 gif、用 `RepaintBoundary` 隔离重绘,并让 GridView 表情 item 保持状态,减少父组件刷新时 gif 重建和首帧跳动。
- 已继续针对黄脸 `fluent_emoji` 表情闪烁做素材侧处理:这组 150x150 透明 GIF 的帧处置方式更容易在 Flutter 解码/循环时露底闪烁,当前已批量转成 animated WebP 并切换选择栏引用;猴子表情保持原 GIF不改变已验证稳定的素材。
- `ios/Podfile.lock` 还保留旧插件记录,因为本轮未执行 `pod install`;但 Flutter 当前依赖链路已经不再包含已移除插件。
- universal APK 仍然会非常大;当前正确发包方式应优先使用 `--split-per-abi` 或直接产出 `aab`
- 仍有 `12``webp` 被 TinyPNG 拒绝解码,推测是动画或特殊编码格式,不能继续直接走 TinyPNG 常规压缩。
- `split-debug-info` 会把 Dart symbols 额外落到构建目录,发包时需要和正式包一起留档,不能丢。
- iOS 当前验证走的是 `--no-codesign`,因此只产出 `.xcarchive`,不会自动导出可直接分发的 `.ipa`
- Flutter/Xcode 当前给出两条 iOS 提醒:
- 未来 iOS 版本将要求 `UIScene` 生命周期支持
- Launch image 仍是默认占位资源,提交前建议替换
- `android/key.properties` 保存了本地 upload keystore 口令,必须自行妥善备份,且不要提交到仓库
- 由于已显式移除 Agora 本地屏幕共享相关组件,如果业务后续要启用“屏幕共享/录屏推流”,需要再单独恢复相关 manifest 声明
- `burst` 特效叠加层已停止用 `Align + translate` 猜偏移,改为按 `luck_gift_reward_burst.svga` 拆出的参考图层比例重排头像、中奖金额、倍数,重点对齐头像黑色占位圈和底部倍数圆角块
- 根据最新真机截图,`burst` 叠加层已整体继续向右下微调,先修正“整体偏左上”的问题,不改头像和文案尺寸
- 按最新口头要求,`burst` 叠加层又整体额外向下平移 `40` 个设计单位,继续保持头像、金额、倍数三者相对位置不变
- `burst` 头像已按最新要求缩到原来的 `80%`,并同步补偿左上坐标,保持头像中心点仍然对准原坑位
- `burst` 头像继续按最新口头要求单独微调:向下 `10` 个设计单位、向左 `2` 个设计单位,其余金额和倍数位置不动
- `burst` 头像又继续单独向下补移 `8` 个设计单位,当前累计为向下 `18`、向左 `2`
- 飞向麦位动画补了统一的“中心图空闲同步”逻辑:目标坐标重试失败放弃、队列被清空、上一段飞行结束后,都会把中心静态礼物图切到队列头或直接清空,避免残留卡死在屏幕中央
- 房间游戏 Leader 二级页已补齐新 provider 化接口下的 `launchConfig` 注入链路:前端现在会保留后端原始 `launchConfig` 字段,并在 WebView 内注入 `leaderLaunchConfig/getConfig()` 供 H5 读取,便于后端完成后直接联调
## 下一步要做什么
- 将新的 `AAB` 上传到 Play Console并在首发流程中继续使用 Google 管理的 app signing key。
- 在需要配置 Google 登录、Firebase、支付等生产环境指纹时优先登记 Google 的 `deployment_cert.der` 指纹;如平台要求上传者证书,再额外登记本地 upload key 指纹。
- 如果需要正式 iOS 分发包,为 `scripts/build_release.py` 补入 `--ios-codesign` 所需签名参数并导出 `.ipa`
- 继续评估 Agora 扩展库是否都需要,优先核查 `lip sync``spatial audio``clear vision``segmentation``face capture` 等扩展 so 能否裁剪。
- 决定是否处理剩余 12 张特殊 `webp`:改格式、换压缩工具,或维持现状。
- [ ] 2026-05-22 16:08:31 已确认 iPhone 17 Pro 模拟器在线,并开始检查首充弹窗/礼物悬浮板显示条件。
- [ ] 2026-05-22 16:08:53 已读取首充接口模型、弹窗加载逻辑、礼物面板悬浮板条件和首页首充入口,准备定位显示断点。
- [ ] 2026-05-22 16:09:12 已确认礼物面板悬浮板仍依赖登录资料 firstRecharge本地还需接入首充奖励 home 接口状态。
- [ ] 2026-05-22 16:12:00 已确认首页入场弹层队列目前只串注册奖励、运营弹窗、每日签到,没有首充弹窗主动展示步骤。
- [ ] 2026-05-22 16:12:44 准备用 iPhone 17 Pro 启动当前工程现状,复现首充弹窗和礼物面板悬浮板不显示问题。
- [ ] 2026-05-22 16:15:24 iPhone 17 Pro 当前正在编译启动 lib/main.dart等待进入应用后对比现状。
- [ ] 2026-05-22 16:16:56 已截取 iPhone 17 Pro 修复前首页截图,用于确认当前没有首充弹窗。
- [ ] 2026-05-22 16:17:15 iPhone 17 Pro 修复前截图显示每日签到弹窗正常展示,但没有首充弹窗,运行日志也未出现首充 home 接口请求。
- [ ] 2026-05-22 16:17:34 开始读取首充奖励 Flutter 接口文档,核对 configured/enabled/activityStatus/rewarded 等字段含义。
- [ ] 2026-05-22 16:18:13 准备修改首页入场弹层队列和礼物面板首充悬浮板判断,统一由 first-recharge-reward/home 接口驱动。
- [ ] 2026-05-22 16:19:01 已完成首充入口代码修改:首页入场队列新增首充远程弹窗,礼物面板悬浮板改为读取首充 home 接口状态。
- [ ] 2026-05-22 16:19:18 开始格式化本轮修改的 gift_page.dart 和 index_page.dart。
- [ ] 2026-05-22 16:19:28 开始对首充相关修改文件执行 flutter analyze。
- [ ] 2026-05-22 16:20:32 flutter analyze 发现 index_page.dart 缺少 AccountStorage 导入,准备补齐后复查。
- [ ] 2026-05-22 16:21:15 已补齐 AccountStorage 导入,重新格式化并执行 flutter analyze。
- [ ] 2026-05-22 16:22:10 flutter analyze 通过,首充入口修改当前无静态错误。
- [ ] 2026-05-22 16:22:37 准备对 iPhone 17 Pro 当前 flutter run 会话执行 hot restart 验证首页首充弹窗。
- [ ] 2026-05-22 16:23:24 已截取 iPhone 17 Pro 首页热重启后截图,检查首充弹窗是否展示。
- [ ] 2026-05-22 16:24:03 iPhone 17 Pro 热重启后已看到首充弹窗,首页入场首充接口展示链路验证通过;继续验证房间礼物面板悬浮板。
- [ ] 2026-05-22 16:26:26 已在 iPhone 17 Pro 进入房间并打开礼物面板,非 CP 礼物 tab 上方已显示首充悬浮板并完成截图。
- [ ] 2026-05-22 16:27:08 已切到 CP tab确认顶部为 CP 专属悬浮板,不显示首充悬浮板,并保存截图。
- [ ] 2026-05-22 16:30:42 已点击礼物面板首充悬浮板,确认会关闭礼物面板并打开首充弹窗,已保存截图。
- [ ] 2026-05-22 16:31:26 验证礼物悬浮板点击可打开首充弹窗;同时发现进房时有既有 Provider build 期 notify 异常,开始确认是否需一并修复。
- [ ] 2026-05-22 16:33:39 准备修复 voice_room_page 在 build 阶段同步通知 RtcProvider 导致的 setState/markNeedsBuild 异常。
- [ ] 2026-05-22 16:34:37 已将房间页 Provider 通知延后到首帧后,开始格式化并重新执行 flutter analyze。
- [ ] 2026-05-22 16:36:03 flutter analyze 再次通过,包含首充入口和房间页 Provider 通知修复。
- [ ] 2026-05-22 16:36:23 准备再次 hot restart iPhone 17 Pro用干净日志复验首页弹窗、进房、礼物悬浮板和 CP 悬浮板。
- [ ] 2026-05-22 16:38:24 最终复验iPhone 17 Pro hot restart 后首页首充弹窗再次正常显示并截图。
- [ ] 2026-05-22 16:40:39 新增反馈:首充奖励 item 不能固定占六个,空数据不显示;启动需补接口决定的进场弹窗;弹窗顺序调整为注册奖励 > 每日签到 > 进场弹窗 > 首充弹窗。
- [ ] 2026-05-22 16:41:07 开始读取 APP 进场弹窗接口文档、首页启动弹窗队列、进场弹窗 coordinator 和响应模型。
- [ ] 2026-05-22 16:41:43 已定位进场弹窗路径和启动顺序问题,继续检查首充弹窗 rewards grid 是否固定占位。
- [ ] 2026-05-22 16:44:01 准备修改进场接口路径、首页启动弹窗顺序,以及首充奖励 item 的空数据过滤/动态数量渲染。
- [ ] 2026-05-22 16:46:18 已修改首充 rewards 过滤/动态渲染、首页弹窗顺序和进场弹窗接口路径。
- [ ] 2026-05-22 16:46:39 开始格式化并分析首充弹窗、首页启动队列、进场接口仓库和相关页面。
- [ ] 2026-05-22 16:48:20 flutter analyze 通过,首充动态 item、进场接口路径和弹窗顺序修改无静态错误。
- [ ] 2026-05-22 16:48:51 准备为进场弹窗 coordinator 开启 debug 日志,便于模拟器验证接口队列和本地 limit 判断。
- [ ] 2026-05-22 16:49:39 已开启 EntryPopup debug 日志,开始格式化并重新分析相关文件。
- [ ] 2026-05-22 16:50:21 flutter analyze 发现 entry popup coordinator 存在空 catch info准备改为 debug 日志。
- [ ] 2026-05-22 16:50:51 已补齐 entry popup 异常 debug 日志,重新执行格式化和分析。
- [ ] 2026-05-22 16:51:45 flutter analyze 最终通过,进场弹窗 debug 日志改动无静态问题。
- [ ] 2026-05-22 16:52:50 已复查代码:启动顺序为注册奖励 > 每日签到 > 进场弹窗 > 首充弹窗,首充奖励只生成有效 item进场接口路径已对齐文档。
- [ ] 2026-05-22 16:53:25 准备用 iPhone 17 Pro 重新启动验证:检查弹窗顺序、进场弹窗接口和首充动态 item 显示。
- [ ] 2026-05-22 16:54:59 iPhone 17 Pro 正在编译启动 lib/main.dart等待进入首页验证弹窗顺序。
- [ ] 2026-05-22 16:55:57 已截取 iPhone 17 Pro 启动后第一阶段弹窗截图。
- [ ] 2026-05-22 16:56:28 iPhone 17 Pro 启动第一阶段确认展示每日签到弹窗,符合注册奖励之后、进场弹窗之前的顺序要求。
- [ ] 2026-05-22 17:01:20 iPhone 17 Pro 日志显示 /app/popups/entry 当前环境返回 404准备增加 /go/app/popups/entry 兼容降级。
- [ ] 2026-05-22 17:03:08 已为进场弹窗接口增加 404 降级到 /go/app/popups/entry开始格式化并分析。
- [ ] 2026-05-22 17:04:34 flutter analyze 通过,进场弹窗接口降级兼容无静态问题。
- [ ] 2026-05-22 17:05:08 准备 hot restart iPhone 17 Pro复验进场接口兼容降级和弹窗队列。
- [ ] 2026-05-22 17:07:03 hot restart 后已重新截取启动队列第一阶段截图。
- [ ] 2026-05-22 17:13:01 EntryPopup 日志确认接口已返回 queue=[invite, game],但当前 invite 图片为 cdn.example.com 示例地址,预加载失败所以按规则跳过展示;准备修正金币 item 过滤。
- [ ] 2026-05-22 17:14:16 已放宽金币奖励有效判断,金币金额在 content/displayTitle 时也保留;开始格式化和分析。
- [ ] 2026-05-22 17:15:21 flutter analyze 通过,金币奖励 content/displayTitle 保留逻辑无静态错误。
- [ ] 2026-05-22 17:15:52 准备再次 hot restart 验证首充弹窗:金币奖励应保留,空 item 不显示。
- [ ] 2026-05-22 17:18:02 已等待启动队列推进并截取首充弹窗动态 item 截图。
- [ ] 2026-05-22 17:19:23 hot restart 后 9 秒仍停留在每日签到,确认启动队列会等待前一个弹窗结束再继续。
- [ ] 2026-05-22 17:20:46 已截取最终首充弹窗截图:金币奖励保留,两个空占位 item 已不显示。
- [ ] 2026-05-22 17:22:05 准备优化进场弹窗候选选择:队列中某个弹窗图片预加载失败时,继续尝试下一个可展示候选。
- [ ] 2026-05-22 17:23:10 已让进场弹窗图片失败时继续尝试下一个候选,开始格式化并分析。
- [ ] 2026-05-22 17:24:18 flutter analyze 通过,进场弹窗候选兜底逻辑无静态问题。
- [ ] 2026-05-22 17:26:58 准备热加载进场弹窗候选兜底逻辑,并通过前后台切换触发一次 entry popup 验证日志。
- [ ] 2026-05-22 17:31:21 当前 iPhone 17 Pro flutter run 会话已停止,避免后台继续占用;候选兜底逻辑已通过 flutter analyze未再做前后台日志复验。
- [x] 2026-05-22 17:32:46 本轮完成:首充奖励按有效接口 item 动态渲染;启动弹窗顺序调整为注册奖励 > 每日签到 > 进场弹窗 > 首充弹窗;进场弹窗接口已接入并支持路径降级与候选图片兜底。
- [ ] 2026-05-22 17:52:18 新增性能问题:礼物弹窗每次打开都会请求首充 home 接口导致慢和卡;需要改为进房预请求缓存,房内充值成功后再刷新状态。
- [ ] 2026-05-22 17:52:43 开始检查礼物面板首充请求、房间进入生命周期和支付成功刷新入口。
- [ ] 2026-05-22 17:55:06 新增方案确认:启动时首充弹窗请求结果缓存到全局状态;礼物弹窗只读缓存不再请求;用户充值成功后刷新该状态。
- [ ] 2026-05-22 17:55:29 开始读取首充远程弹窗、礼物弹窗缓存读取点和支付成功刷新点。
- [ ] 2026-05-22 17:56:21 准备在 SCAppGeneralManager 增加首充 home 全局缓存,礼物面板改为只读缓存,支付成功后强制刷新。
- [ ] 2026-05-22 17:57:23 开始编码:新增 SCAppGeneralManager 首充缓存,移除 GiftPage 首充接口请求,支付成功后刷新缓存。
- [ ] 18:00:55 继续处理首充状态缓存:复核当前改动,并补充支付成功后刷新全局首充状态。
- [x] 18:01:20 已确认 GiftPage 打开时的首充接口请求已移除,当前只需要补齐支付成功后的全局状态刷新。
- [ ] 18:01:37 开始修改支付成功回调Google/iOS 验证成功后强制刷新全局首充弹窗状态。
- [x] 18:01:59 已补充 Google/iOS 支付成功后的首充全局状态强制刷新。
- [ ] 18:02:37 调整首充弹窗入口App 进场时强制请求并写入缓存,礼物悬浮板打开时复用缓存。
- [x] 18:02:59 已区分首充弹窗请求来源:首页进场强刷缓存,礼物入口打开复用缓存。
- [ ] 18:03:29 开始格式化本次涉及的首充缓存、弹窗入口、礼物面板与支付文件。
- [x] 18:03:41 已完成 Dart 格式化。
- [ ] 18:03:50 开始静态检查本次变更文件,确认首充缓存和支付刷新逻辑无编译错误。
- [ ] 18:04:31 静态检查发现支付文件 lint开始收紧 iOS/Google 支付刷新实现并移除 iOS 未使用空方法。
- [x] 18:05:31 已收紧支付刷新实现:异步前缓存 Provider 引用iOS 支付文件移除未使用空方法并修复 forEach lint。
- [x] 18:06:11 静态检查通过:本次涉及的 7 个 Dart 文件 flutter analyze 无问题。
- [ ] 18:06:26 检查 iOS 模拟器设备,准备进行运行验证。
- [x] 18:06:55 已确认本机可用 iPhone 17 Pro 与 iPhone 17 Pro Max 模拟器,开始用 iPhone 17 Pro 编译运行验证。
- [ ] 20:27:16 新增调整:首充弹窗非金币奖励文本改用类型名称,左上角天数显示为 Xd缺省 1d。
- [ ] 20:27:44 已定位当前实现:非金币标题取 name角标取 badgeText/Days开始确认接口字段并调整模型。
- [ ] 20:28:12 接口文档示例未包含 typeName按兼容字段解析类型名称并保留 type 可读兜底。
- [x] 20:29:02 已修改首充奖励模型与 UI 映射:非金币标题优先类型名称,角标统一 Xd 且默认 1d。
- [ ] 20:29:12 开始格式化并检查首充奖励模型与弹窗文件。
- [ ] 20:29:34 静态检查发现旧的 _firstInt 已无引用,开始移除死代码。
- [x] 20:29:56 已完成格式化与静态检查:首充奖励模型、弹窗文件 flutter analyze 无问题。
- [ ] 20:38:55 反馈修正:金币类型标题必须显示金币金额,非金币才显示类型名称;开始调整解析兜底。
- [ ] 20:39:21 已确认金币 quantity 为空时会误用类型兜底;开始新增 coinAmount 并限制金币 item 只显示金额。
- [x] 20:39:46 已修正金币标题逻辑:金币只显示解析出的金额 Coins非金币才走类型名称。
- [ ] 20:39:56 开始格式化并静态检查金币金额显示修正。
- [x] 20:41:16 金币金额显示修正已通过格式化与 flutter analyze 检查。
- [ ] 16:40:00 新增识别规则:首充非金币奖励不能泛化显示 Props需要前端兜底识别 Frames / Vehicles / VIP。
- [ ] 16:40:32 开始编码:增加 Frames/Vehicles/VIP 文本识别,并给这些类型补本地图标兜底。
- [x] 16:41:04 已增加 Frames/Vehicles/VIP 文本识别与本地图标兜底,避免泛化显示 Props 和黄色占位图。
- [ ] 16:41:11 开始格式化并静态检查首充类型识别与兜底图标改动。
- [x] 16:41:33 类型识别与兜底图标改动已通过 dart format 和 flutter analyze。
- [ ] 2026-06-02 房间表情反馈:公屏 GIF 不循环,表情弹窗格子应展示动画预览而不是静态封面;开始定位面板资源字段和公屏渲染组件。
- [x] 2026-06-02 已定位:表情弹窗格子当前使用 `displayResource/coverUrl`,发送与公屏使用 `sendResource/sourceUrl`;若 cover 为 PNG 会导致面板静态,公屏 GIF 需要在首次加载完成后主动重建来重播有限循环资源。
- [x] 2026-06-02 按最新反馈收窄范围:表情面板继续使用 `displayResource` 不改;仅调整 GIF 媒体组件在首次加载完成后重建播放,修复公屏 GIF 停在最后一帧。
- [x] 2026-06-02 继续优化公屏 GIF 循环闪 loading网络 GIF 重播时不再销毁整个 widget加载下一轮期间复用上一帧画面避免循环间隙出现转圈。
- [x] 2026-06-02 复核发现不销毁 key 会导致 GIF 解码器不重启并停在最后一帧;改为前景层用新 key 重播、背景层保留上一轮画面,兼顾循环播放和不显示 loading。
- [x] 2026-06-02 按接口文档恢复 `have` 权限判断:`/material/emoji/all` 返回的表情包仅 `have == true` 且非空时展示,`have=false/null` 计入 `filteredNoAccess` 日志。