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:
Your Name
2026-09-09 20:16:33 +08:00
co-authored by Claude Sonnet 5
parent 72b7b79caf
commit 5c3f3b7653
89 changed files with 10158 additions and 442 deletions
+50 -7
View File
@@ -3,16 +3,32 @@ import { Navigate, createBrowserRouter, RouterProvider } from 'react-router-dom'
import { AppShell } from '@/app/AppShell';
import { RequireAuth } from '@/app/RequireAuth';
import { SectionPlaceholder } from '@/app/SectionPlaceholder';
import { EnterpriseRegisterPage } from '@/features/auth/EnterpriseRegisterPage';
import { LoginPage } from '@/features/auth/LoginPage';
import { RegisterPage } from '@/features/auth/RegisterPage';
import { ResetPasswordPage } from '@/features/auth/ResetPasswordPage';
import { TenantEntryPage } from '@/features/auth/TenantEntryPage';
import { TenantFeedbackPage } from '@/features/auth/TenantFeedbackPage';
import { CallHistoryView } from '@/features/calls/CallHistoryView';
import { BlocklistView } from '@/features/contacts/BlocklistView';
import { ContactsLayout } from '@/features/contacts/ContactsLayout';
import { EmptyContactsMain } from '@/features/contacts/EmptyContactsMain';
import { FriendProfileView } from '@/features/contacts/FriendProfileView';
import { GroupListView } from '@/features/contacts/GroupListView';
import { NewFriendsView } from '@/features/contacts/NewFriendsView';
import { FavoritesLayout } from '@/features/favorites/FavoritesLayout';
import { ConversationView } from '@/features/messages/ConversationView';
import { EmptyMain } from '@/features/messages/EmptyMain';
import { MessagesLayout } from '@/features/messages/MessagesLayout';
import { AboutPage } from '@/features/settings/AboutPage';
import { GeneralSettingsPage } from '@/features/settings/GeneralSettingsPage';
import { NotificationsSettingsPage } from '@/features/settings/NotificationsSettingsPage';
import { PrivacySettingsPage } from '@/features/settings/PrivacySettingsPage';
import { ProfileSettingsPage } from '@/features/settings/ProfileSettingsPage';
import { SecuritySettingsPage } from '@/features/settings/SecuritySettingsPage';
import { SettingsHome } from '@/features/settings/SettingsHome';
import { SettingsLayout } from '@/features/settings/SettingsLayout';
import { SystemMessagesView } from '@/features/system/SystemMessagesView';
const queryClient = new QueryClient();
@@ -35,15 +51,42 @@ const router = createBrowserRouter([
element: <MessagesLayout />,
children: [
{ index: true, element: <EmptyMain /> },
{ path: 'system', element: <SystemMessagesView /> },
{ path: ':topicId', element: <ConversationView /> },
],
},
{ path: 'contacts', element: <SectionPlaceholder title="通讯录" /> },
{ path: 'favorites', element: <SectionPlaceholder title="我的收藏" /> },
{ path: 'files', element: <SectionPlaceholder title="文件助手" /> },
{ path: 'chat/system', element: <SectionPlaceholder title="系统消息" /> },
{ path: 'calls', element: <SectionPlaceholder title="通话记录" /> },
{ path: 'settings', element: <SectionPlaceholder title="设置" /> },
{
path: 'contacts',
element: <ContactsLayout />,
children: [
{ index: true, element: <EmptyContactsMain /> },
{ path: 'requests', element: <NewFriendsView /> },
{ path: 'groups', element: <GroupListView /> },
{ path: 'blocklist', element: <BlocklistView /> },
{ path: ':userId', element: <FriendProfileView /> },
],
},
{ path: 'favorites', element: <FavoritesLayout /> },
// README §9.2's dedicated file-assistant browser (categories, storage quota, upload
// progress) has NO backing REST API at all (confirmed via a research pass -- the design
// spec's own state-management notes admit reuse of existing APIs, i.e. reading the `slf`
// topic's messages, same as any other conversation) -- redirecting into the real
// conversation on that topic is honest; a fake quota card with invented numbers isn't.
{ path: 'files', element: <Navigate to="/messages/slf" replace /> },
{ path: 'calls', element: <CallHistoryView /> },
{
path: 'settings',
element: <SettingsLayout />,
children: [
{ index: true, element: <SettingsHome /> },
{ path: 'profile', element: <ProfileSettingsPage /> },
{ path: 'security', element: <SecuritySettingsPage /> },
{ path: 'notifications', element: <NotificationsSettingsPage /> },
{ path: 'privacy', element: <PrivacySettingsPage /> },
{ path: 'general', element: <GeneralSettingsPage /> },
{ path: 'about', element: <AboutPage /> },
],
},
],
},
],