feat(web): complete groups/contacts/favorites/settings/calls/system domains + extensive review-round fixes
Rounds out the full rewrite with the remaining feature domains: group management (admin panel, mute, files, announcements, QR-based invite/join), contacts (friend profile, add-friend, blocklist, new-friends), favorites (real media rendering across text/image/video/voice/file/link), settings (profile/security/privacy/general/about), calls (Agora-backed audio/video signaling + call history), and system messages/file assistant. Also folds in a large batch of live-verified fixes surfaced by repeated fresh code-review passes and hands-on E2E testing against the real backend, including: WS reconnect not resubscribing any topic after a disconnect, missing x-im-client-mid on every send path (protocol compliance for retry dedup), group mute/member-settings/self-profile endpoint corrections, relationship-state type fixes across search/QR/ friend-profile, tenant-switch logout gap, password-policy now read from the real per-tenant config instead of guessed, NavRail highlight/ aria-current desync, several call-state-machine races, and responsive layout fixes across all four breakpoints (mobile/tablet/laptop/desktop) including a full mobile rebuild of favorites, call UI, and the settings home/sub-list split. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
72b7b79caf
commit
5c3f3b7653
@@ -11,6 +11,15 @@ const CTRL_ERROR_TEXT_CN: Record<string, string> = {
|
||||
'policy violation': '当前操作不符合安全策略要求',
|
||||
'permission denied': '没有权限执行此操作,请重新登录',
|
||||
'internal error': '服务器繁忙,请稍后重试',
|
||||
// Confirmed live 2026-09-09: registering with a username or phone number that's already taken
|
||||
// returns this exact raw SDK text ("duplicate credential (409)") -- without this entry,
|
||||
// registerErrorMessage()'s fallback showed the raw English straight to a Chinese-language user.
|
||||
'duplicate credential': '该用户名或手机号已被注册,请更换后重试',
|
||||
// docs/IM-前后端对接文档.md's own worked example (`{"login":...,"secret":"其他租户 token"}` ->
|
||||
// `403 tenant mismatch`) -- without this entry, loginErrorMessage's generic `code===403` fallback
|
||||
// below shows "账号或密码错误" for what's actually a stale-token-from-a-different-tenant case, which
|
||||
// is a materially different, more confusing message (the password wasn't wrong at all).
|
||||
'tenant mismatch': '登录状态异常,请重新进入企业码',
|
||||
};
|
||||
|
||||
function translateCtrlError(err: unknown): string | null {
|
||||
@@ -20,6 +29,16 @@ function translateCtrlError(err: unknown): string | null {
|
||||
return CTRL_ERROR_TEXT_CN[normalized] || null;
|
||||
}
|
||||
|
||||
/** docs/IM-前后端对接文档.md: this specific reason means the client is holding a session token
|
||||
* issued by a DIFFERENT tenant than the one it's currently connected to -- the doc's own prescribed
|
||||
* recovery is "清 Token 并回企业码页" (clear the token and return to the tenant-code entry screen),
|
||||
* not just show an error and let the user retry the same broken state. */
|
||||
export function isTenantMismatch(err: unknown): boolean {
|
||||
const raw = (err as Error)?.message;
|
||||
if (!raw) return false;
|
||||
return raw.replace(/\s*\(\d+\)\s*$/, '').trim().toLowerCase() === 'tenant mismatch';
|
||||
}
|
||||
|
||||
export function loginErrorMessage(err: unknown): string {
|
||||
const known = translateCtrlError(err);
|
||||
if (known) return known;
|
||||
|
||||
Reference in New Issue
Block a user