活快照:只记当前状态,就地覆盖、不追加。逐功能×端状态以
../IMServer/docs/CLIENT_PARITY.md为唯一来源; 历史流水见current_task.archive.md(2026-10-02 瘦身前的全量快照在其顶部)+git log。关键约定见CLAUDE.md/ARCHITECTURE.md/CODING_STYLE.md。
- 注销账号 + 退出登录居中(2026-10-20,已提交本地 main,未 push;模拟器 iPhone 17 Pro Max 已逐项实测,设计
../IMServer/docs/design/DELETE_ACCOUNT_DESIGN.md+sketches/DELETE_ACCOUNT_UX_SKETCH.html,契约 PROTOCOL §6.16 已对账):设置页 destructive 行居中;「我的资料」只读态底部注销组;IMDeleteAccountViewController(警示头/后果/冷静期条/密码/红按钮/群主阻断+可点群名/二次确认);成功 →IMSessionTeardown.wipeLocalChatCacheThen:(整库 owner 行 + 下载/原件/待发暂存/图片缓存/看过/文件夹快照/已注销登记,后台队列做)→tearDownLocalSession→ 登录页提示条;冷静期登录弹恢复 →/account/restore→ 再/login。别的设备:WSerror{reason:account_deleted}→IMSocketManager+ErrorFrame.m(从主文件拆出)广播 →SceneDelegate.handleAccountDeletedElsewhere清缓存回登录页(离线错过该帧的设备不清缓存,只因续期被拒回登录页)。「已注销用户」:IMRemarkStore登记(isDeletedUser:,UserDefaults 按 owner 持久化,压过备注/群昵称);解析器只登记,撤销在权威端点收尾reconcileDeletedFlags:(batch/friends/users/{id}/会话列表/成员目录);头像(UILabel+IMAvatar/导航头像/详情头)走默认首字母圈;选人页、通话邀请排除;对端已注销单聊输入栏只读、详情页只留搜索/更多、副标题不显在线态;发消息 300003 →chat.reject.recipient_deleted。测试IMDeleteAccountTests、IMDeletedUserDisplayTests。限制:离线错过注销帧的设备不清缓存(上面已述);isDeletedUser:每次取一次 owner(与remarkForUser:同成本,未优化)。已注销者头像=灰底人形(IMDeletedUserAvatarImage,对齐 Android);转发条目作者经IMForwardOriginName(已注销发送者写「已注销用户」;只有快照昵称、拿不到 uid 的老转发链条目保持原文);聊天内「发送好友申请」恢复入口对已注销对端失效(dropFriendRequestNoteActions);300003 走灰字拒收行、无红❗重发。i18n 经gen-i18n.mjs --check无漂移(iOS.strings为生成物)。 code-review 收口(10-20):别设备注销清库期间被踢通路让路;清库前先断 WS;待发暂存只删本账号消息引用的文件(目录各账号共用);/account/*响应缺 code 不当成功;恢复弹窗无 delete_at 不显「-」;阻断态从群页返回自动解除。遗留:下载/视频原件目录各账号共用,注销会清空(缓存语义,同「清除缓存」);离线错过注销帧的设备不清缓存。 - 扫一扫「我的二维码」页签改嵌名片码页 + 群邀请链接页(2026-10-16,未提交,未真机目测):
IMQRScannerViewController的名片页签 = 嵌入IMQRCardViewController(updateMyProfile…补资料、reloadCodeIfNeeded切回重试、亮度由宿主 boost/restore);IMQRCardView.linkMode链接页(链接框替代二维码,按钮=分享链接/复制链接,底部「查看二维码」)。欠账:qr.card.group_link_hint_expiry/share_link/view_code只手写进 iOS.strings,须补进../IMServer/docs/i18n/strings.json再gen-i18n,否则下次生成会被覆盖;无 XCTest(纯 UI)。 - 置顶消息底部面板(2026-10-15,未提交,未真机目测;设计
../IMServer/docs/design/PINNED_PANEL_DESIGN.md+sketches/PINNED_PANEL_UX_SKETCH.html):横幅整条 / ≡ 恒开面板、恒显最新置顶(IMPinnedLatestItem)、kicker「· N 条」(chat.banner.pinned_count),轮转与UIAlertController旧列表 /chat.banner.unpin_current已删。新文件:Modules/Chat/IMPinnedPanelViewController(PageSheet medium+large + grabber + 自持液态栏,宿主协议IMPinnedPanelHost绝大多数是聊天页已有方法,编译期声明在 +PinnedBanner.m、运行期由单测兜)、IMPinnedPanelCellFactory(复用聊天页真 cell +readOnly、定位圆钮挂 cell 本身)、IMPinnedPanelLogic(兜底顺序 / 日期胶囊 / 菜单允许项 / 权限外框)、Common/IMLocateInChatIcon(UIBezierPath template 图)。IMMessageCell/IMBubbleCell加readOnly(contentView 不接触摸;文本 8 行尾截断)。网络:IMPinnedMessage.message(完整对象)、clearPinnedMessagesWithToken:(POST …/pinned/clear)、批量帧IMMsgOpPinTargetPayloads拆单(IMSocketManager+BatchDelete的applyBatchPinFrameOnQueue:);取消置顶命中集合本地先摘、pin 变化改走 300ms 尾沿重拉、msg_op 被拒也重拉。测试IMPinnedMessageTests+10 例(4 条核心已变异看红)。待真机:iOS 18 / 26 各看 medium / large、各消息类型置顶一条、长按菜单锚点、底栏胶囊(iOS 18 毛玻璃回退)、深色。 - iOS 26 会话列表上滑后 Tab 条被染灰(2026-10-15,未提交,未滚动实测):
IMConversationListViewController.m创建 tableView 处对topEdgeEffect.hidden = YES(@available(iOS 26.0, *))。根因判断:iOS 26 的 scroll edge effect 贴在表顶(搜索容器下沿),盖住吸顶的 Tab 条;Tab 条自身与搜索容器都是systemBackgroundColor,色值本无差异。已编译并装 iOS 26.3 模拟器,静止态正常;上滑态待你在真机/模拟器目测,若仍灰则改查IMChatFolderTabsView吸顶时是否被表格 header 背景材质包裹。 - 聊天文件夹(2026-10-14,已提交 2757f52;Tab 长按菜单锚定 5d47081;桌面/iOS 26·18 导航栏边缘待验):
IMChatFolder/IMChatFolderStore/IMChatFolderLogic/IMHTTPService+Folders、会话列表拆出IMConversationListViewController+Folders.m(Tab 条=首个 section header 吸顶、横滑与行滑动判定、长按菜单文件夹项第一位)、管理/编辑/选择三页;IMLiquidSegmentedControl改居中贴合内容 + Tab 角标;设计见 IMServerdocs/design/CHAT_FOLDERS_DESIGN.md。 - 失效媒体口径对齐(2026-10-14,已提交并推送 adf2d14,真机已装;iOS 界面未目测):服务端已清理即标失效,不看本机缓存(取代 2026-08-07「铁律 A」);
IMMediaExpiryRegistry探测与复验共用一段 ranged-GET(bytes=0-0,只认 404/410),在途请求会被复验等待、失败 30s 冷却。宫格/气泡:有本机副本的图不批量探,视频无原件才探,进查看器那一次复验,命中经IMMediaExpiryDidChangeNotification回刷。查看器失效页:黑底 + 八角 ✕、清掉底下真图/画面、无进度条/下载键,「更多」滤掉needsMediaBytes项(复制/收藏/转发/下载);长按菜单对失效图/视频隐藏复制图片/转发/收藏。三端对齐(2026-10-14,未提交):群资料/详情查看器「更多」补收藏/复制并与聊天页同序(定位用media.viewer.locate);详情 tab 与全屏媒体库长按「定位到聊天」第一位。欠账:探测去重/冷却/复验等待/菜单过滤缺 XCTest(需 NSURLProtocol 桩,见下一步);门控失效格点击仍会走到下载处理(不画下载 UI,但会起一个 404 的下载)。 - 2026-10-13 修复一批(未提交):① 合并转发详情/群公告副标题/搜索跳日期提示的日期不再写死 zh_CN「M月d日」,改走
IMTheme dateLabelForDate:+timeStringFromMillis:(英文界面实测Oct 6 21:27);② 会话列表群「待审」改为整行只显红字[入群申请 N](可带[有人@我]),不再接上一条消息,清零后恢复预览。文案conv.list.pending_tag/pending_badge已改、三端已重新生成。 - 单聊系统消息 friend_accepted(2026-10-13,未 commit):服务端在好友新建立时往单聊落
content_type=system、sender 空的系统消息。iOS 侧:IMSysEventFormatter事件表加friend_accepted(键sys.friend.accepted,0 人名槽位);会话列表单聊行预览改走lastPreviewTextForSelfUID:(按 sys_event 本地化,未知回退 lastContent;顺带让系统通知单聊列表首行也本地化);↓N 窗口计数 /countIncomingInConv:/ 标已读扣数(markConversation:readUpToConvSeq:)排除 system(此前 sender 空会被当「对方消息」)。核实无需改:落库/peer 由 convID 推(壳行建会话、unreadDelta排除 system)、IMAlertDecide对 system 全静默、通知扩展只处理服务端推送(不推)。测试:IMSysSegmentTests/IMSysEventFormatterTests新增。待真机:互加好友后单聊出现居中灰字、列表置顶且无红点/无提示音;会话列表原无该会话时 new_msg 到达后行名在下一次 /conversations 刷新前先显「未命名」(壳行不知昵称,见已知限制)。 - 群通知两行(2026-10-13,已真机验证):通知扩展
NotificationService.m群聊把群当「发送人」(群名 + 群头像走INPerson.image,不用speakableGroupName),修 iOS 26 群通知只显示 logo;bare_body不再使用。相册合并由服务端同 collapse-id 原地替换,扩展无需处理。 - 聊天相册选择器 iOS 自建(10-07,已合入、用户真机自测通过,细节见 archive)。
- iOS 单测欠账专项仍在进行(清单见
docs/TEST_DEBT.md;批 A/B、C1、C2 已做,剩 C3–C7 与批 D;测试由我逐个写,不派并行子代理改测试目标)。
- 置顶面板收尾:
../IMServer/docs/CLIENT_PARITY.md置顶面板 iOS 格待更新(本次按要求未改别的仓);真机清单见「当前焦点」。二期(设计 §2.2):图片 / 视频单条预览、语音就地播放。
-
相册选择器:用户 2026-10-07 真机自测通过,无待办。已知限制:体积来自
PHAssetResource的fileSize(KVC),取不到时不置灰也不显总大小;无 VoiceOver 标签;Android/Web/桌面文案已重新生成(2026-10-07)。 -
拆体量欠账(下次碰就必须先拆):
Network/IMSocketManager.m1589/1600(只准降不准升;方向按 CODING_STYLE §7 三档:帧编解码 / 重连退避 / 各业务 send-recv 分组各成协作对象或 category,新逻辑优先开 category);Database/IMDatabase.m1500/1500(已顶满,加列或新增前必须先拆),给im_conversation_local/im_message_local加列前先拆(参考IMDatabase+MuteState.m/IMDatabase+ClearFloor.m;writeCachedConversations:的整行 INSERT 是下一块该搬走的)。 -
IMChatViewController.m的peerDisplayName仍有fallback:peerID(会在聊天页标题露内部 uid 的边缘路径),按 UI.md「末级不是 uid」改。 -
小项:
setupUI抽IMComposerBar;遗留 P2(听筒切换/接力连播停止条/Web 转文字/语音发送接入IMMediaSendService常驻队列等,细节见 archive)。
-
置顶面板:图 / 视频按下载策略门控时显 ↓ 占位但点了是「定位」(只读,不下载);引用条不取被引用消息的缩略图(退回类型小图标);相册成员置顶按单张图渲染(非宫格);
IMSocketAckTests三条与IMMediaDownloadCoordinatorTests testImageNotGatedWhenPolicyOn在本机并发负载下全量跑偶发红、单类跑与重跑全绿(与本改动无关,未定位)。 -
新单聊壳行昵称/头像延后:会话列表原无该 conv 时 new_msg 只建壳行(peer 由 convID 推、昵称空),名片与头像等下次
/conversations(列表在屏 0.4s 内、不在屏则等回到列表)才补;IMDatabase.m恰 1500 行,该处不能再加行。 -
清空位点的取舍:① 老库回填(
migrateClearedUpToColumnDB:)按「synced 以内本地没有的那一截 = 当年清掉的」推位点,对「本来就没下载全」的老会话会误判成已清空(如游标在 1000、本地只有 300..1000 → 位点 299,之后 ≤299 永不再拉);与 Android 迁移 15→16 同规则,设计文档拍板的口径。误伤面更大的是 ranges 时代只下过窗口附近的会话(超级群 max_gap=0 尤甚):游标在 head、本地只有最近一两窗 → 位点被推到「本地最小 seq − 1」,窗口之下更早的历史此后一律当「用户清掉的」、不再拉;补列与回填同一事务(失败整体回滚、下次启动重试)。② 落库 / UI 投递 / 回执 / 提醒共用同一份保留集合:sync 页落库前先IMDropClearedMessages,实时先incomingIsCleared:,window 页跳过位点内的行(库里的落库闸是第二道防线)。③ 位点存独立小表im_conv_clear_floor_local(不随会话行删除;会话行被「删除会话」/ 列表不再返回删掉后重建,synced_conv_seq取 max(旧值, 位点),不会 since=0 重拉)。旧的im_conversation_local.cleared_up_to列(早期实现)只在迁移时拷一次,之后不再读写、没有 DROP。iOS 没有「清账号」路径(登出不抹库,靠 owner_uid 隔离)。④ 清空不动会话未读数 / 读位点(沿用旧行为)。⑤ iOS 本机没有独立的「隐藏/删除墓碑」表(本地删除是物理删行),所以「墓碑不动」在 iOS 退化为「只动该会话的消息 / 区间 / 位点」。 -
冷启动通知路由极端情况:全新会话的推送点击可能落空。
-
会话列表左滑「免打扰」 在
done(YES)之前 presentIMMuteDurationMenu、通知横幅点击进会话 与自身 dismiss 动画并行:真机若两个动画叠加突兀,把 present/路由挪到done(YES)/ dismiss 完成回调里即可(一行改动)。 -
通讯录
reload不防重入:好友事件与切入请求并发时后发先至会让applyFriends:覆盖成较旧名单(短暂,下次刷新自愈);补法是在途时只记「待重跑」。 -
IMProgramUITests/IMContactsPerfUITests对 2000 好友账号会卡住(XCUITest 给整棵无障碍树拍快照,cells.count超时重试,App 本身不卡):重跑前改成不查大表,效果看contacts_index_applied/contacts_cache_persist日志与 simctl 截图。 -
撤回消息的「重新编辑」可能在重拉后消失:服务端撤回/删除正文不再随
sync_resp/window_resp下发,writeIncomingMessage的content=?无条件覆盖,重拉后本地正文可能被空串盖掉(优雅降级,不崩溃)。 -
IMMediaPlaceholderTests testFrostedLandscapeScalesLongestSideTo48高负载偶发失败(scripts/test.sh的-only-testing:IMProgramTests+ 关并行基本规避,根因未定位)。 -
runAfterKeyboardHidden:兜底待测:依赖resignFirstResponder后必然收到UIKeyboardDidHideNotification;外接键盘场景引用跳转不触发就加dispatch_after超时兜底。 -
相册导出期杀 App 消息消失(PHPicker 句柄一次性,预期);Files <8MB 小文件、相机拍照、粘贴图仍是 VC 锚定一次性上传;iOS 无双向分页(进会话全量载入本地 DB);presence/typing 仅聊天页标题生效。
-
dev-login 建的账号无法再走密码登录(测密码登录用「注册并登录」或清
imserver.db)。 -
查看器「正在播放中」视频 404 未接失效占位(窄路径可接受);失效标记是进程内 Set、冷启动首帧重探(刻意);原图路径 JPEG 字节戴
.heic帽子(Web 靠嗅探已能显示,暂不改);系统按钮文案靠CFBundleLocalizations,自有 UI 硬编码中文。 -
测试只跑
-only-testing:IMProgramTests;改后端协议后需重启后端再测。体量门禁扫整个IMProgram/(测试 target 是兄弟目录,不在范围)。
- 后端
/Users/dev/IOSProject/im-client/IMServer;Web/Users/dev/IOSProject/im-client/im-web;Android/Users/dev/IOSProject/im-client/im-android。 - 构建:
xcodebuild -workspace IMProgram.xcworkspace -scheme IMProgram -sdk iphonesimulator -destination 'generic/platform=iOS Simulator' build CODE_SIGNING_ALLOWED=NO - 装真机(iPhoneWork
00008120-000131121E50C01E):xcodebuild … -destination 'id=<udid>' -derivedDataPath <dir> -allowProvisioningUpdates build→xcrun devicectl device install app --device <udid> <dir>/Build/Products/Debug-iphoneos/IMProgram.app。首次连后端要允许「查找并连接本地网络设备」,登录页填 Mac 当前 LAN IP。 - 测试:唯一入口
./scripts/test.sh(体量门禁 + 编译 +IMProgramTests;BUILD_ONLY=1/ONLY=<Class>/ONLY=<Class>/<test>,三个坑见CLAUDE.md「构建 / 测试」)。 - 真机日志:
xcrun devicectl device copy from --device iPhoneWork --domain-type appDataContainer --domain-identifier com.libeyond.IMProgram --source "Library/Caches/Logs/<file>.log" --destination <dst>;通知扩展日志idevicesyslog -u <udid>grep IMNotificationService。 - 完成定义 / 编码规范:见
CLAUDE.md、CODING_STYLE.md。