feat(web): 会话头像/名称可点击展开详情栏,移除"关于 MeetingIM"设置页

聊天窗口头部的头像和昵称此前只是静态展示,只有右侧"i"图标能展开
详情栏;现在点击头像或名称同样会触发 onToggleDetail,单聊群聊均
生效。

按产品决定移除设置里的"关于 MeetingIM"页面(桌面目录、移动端"我的"
二级设置列表两处入口一并去掉),该页面唯一内容是版本号和一个后端
本就不支持 platform=web 的检查更新按钮,删除后 AboutPage.tsx 和
仅被它使用的 lib/api/app.ts 一并清理为死代码。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-10 11:06:46 +08:00
co-authored by Claude Sonnet 5
parent 9271a0a9c1
commit 1826d2906f
5 changed files with 27 additions and 99 deletions
+20 -18
View File
@@ -546,24 +546,26 @@ export function ConversationView() {
<Link to="/messages" className="grid h-9.5 w-9.5 flex-none place-items-center text-text-heading md:hidden">
<Icon name="arrow_back_ios_new" />
</Link>
<span
className={`grid h-9.5 w-9.5 flex-none place-items-center rounded-lg text-sm font-medium text-white ${avatarBgClass(topicId)}`}
>
{avatarLetter(peerName)}
</span>
<div className="flex flex-col">
<strong className="text-base font-semibold text-text-heading">
{peerName}
{isGroup ? <span className="ml-1 font-normal text-text-tertiary-2">({groupMemberCount})</span> : null}
</strong>
{isGroup ? (
groupSublineParts.length ? <span className="text-xs text-text-tertiary-2">{groupSublineParts.join(' · ')}</span> : null
) : (
<span className={`text-xs ${contact?.online ? 'text-online' : 'text-text-tertiary-2'}`}>
{contact?.online ? '在线' : '离线'}
</span>
)}
</div>
<button type="button" onClick={onToggleDetail} className="flex items-center gap-2.5 text-left">
<span
className={`grid h-9.5 w-9.5 flex-none place-items-center rounded-lg text-sm font-medium text-white ${avatarBgClass(topicId)}`}
>
{avatarLetter(peerName)}
</span>
<div className="flex flex-col">
<strong className="text-base font-semibold text-text-heading">
{peerName}
{isGroup ? <span className="ml-1 font-normal text-text-tertiary-2">({groupMemberCount})</span> : null}
</strong>
{isGroup ? (
groupSublineParts.length ? <span className="text-xs text-text-tertiary-2">{groupSublineParts.join(' · ')}</span> : null
) : (
<span className={`text-xs ${contact?.online ? 'text-online' : 'text-text-tertiary-2'}`}>
{contact?.online ? '在线' : '离线'}
</span>
)}
</div>
</button>
</div>
<div className="flex items-center gap-1">
{isGroup ? null : (
-47
View File
@@ -1,47 +0,0 @@
import { useMutation } from '@tanstack/react-query';
import { getLatestRelease } from '@/lib/api/app';
const CURRENT_VERSION = __APP_VERSION__;
/**
* README §8.7's "v0.25 · 有新版本" row. Confirmed live (2026-09-08): `platform:"web"` is REJECTED
* outright -- `400 MALFORMED_REQUEST {"details":{"field":"platform"}}` -- the real backend only
* accepts the doc's own example values (`ios`/`android`), no web support at all. Passing a wrong
* platform to get SOME answer would be dishonest (it'd be checking updates for the wrong client),
* so this shows an honest "not supported" state instead of pretending the check succeeded.
*/
export function AboutPage() {
const checkMutation = useMutation({ mutationFn: () => getLatestRelease(CURRENT_VERSION) });
return (
<div className="mx-auto w-full max-w-[720px] px-5 py-8 md:px-10">
<h2 className="mb-4 text-xl font-semibold text-text-heading">关于 MeetingIM</h2>
<div className="rounded-xl bg-white text-sm">
<div className="flex items-center justify-between border-b border-border-list-item px-7 py-4">
<span className="text-text-body">当前版本</span>
<span className="text-text-tertiary-2">{CURRENT_VERSION}</span>
</div>
<button
type="button"
onClick={() => checkMutation.mutate()}
disabled={checkMutation.isPending}
className="flex w-full items-center justify-between px-7 py-4 text-left"
>
<span className="text-text-body">检查更新</span>
<span className="text-text-tertiary-2">
{checkMutation.isPending
? '检查中…'
: checkMutation.isError
? '暂不支持检查更新'
: checkMutation.data
? checkMutation.data.update_type === 'none'
? '已是最新版本'
: `发现新版本 ${checkMutation.data.latest_version}`
: '›'}
</span>
</button>
</div>
</div>
);
}
+7 -12
View File
@@ -15,7 +15,6 @@ const DIRECTORY = [
{ key: 'notifications', to: '/settings/notifications', icon: 'notifications', label: '消息通知' },
{ key: 'privacy', to: '/settings/privacy', icon: 'lock', label: '隐私' },
{ key: 'general', to: '/settings/general', icon: 'tune', label: '通用' },
{ key: 'about', to: '/settings/about', icon: 'info', label: '关于 MeetingIM' },
];
/**
@@ -183,14 +182,14 @@ export function SettingsLayout() {
</div>
{/* Mobile "设置" sub-list (mock `07/1e`) -- a second, DIFFERENT grouping from both the hub
above and the desktop directory: 清空缓存/意见反馈/关于 sit here directly, not nested
under 通用. 清空缓存 links through to 通用 rather than duplicating that action (and its
above and the desktop directory: 清空缓存/意见反馈 sit here directly, not nested under
通用. 清空缓存 links through to 通用 rather than duplicating that action (and its
already-established "no fake byte count" honesty) in a second place; 意见反馈 has no
generic post-login feedback endpoint anywhere in this protocol (the only feedback API,
`/tenant-entry-feedback`, is unauthenticated and pre-login-only per its own name) so this
is a real, recorded backend gap, not a missed wire-up. 关于 omits the mock's red-dot
"有新版本" -- already confirmed elsewhere that state can never be real (the update-check
endpoint always rejects `platform=web`), showing it would be lying about system state. */}
is a real, recorded backend gap, not a missed wire-up. 关于 MeetingIM removed entirely per
product decision -- its only real content was a version string and an update-check the
backend rejects for `platform=web`, not worth a dedicated page. */}
<div className={`flex-1 flex-col overflow-y-auto md:hidden ${mobileSubView ? 'flex' : 'hidden'}`}>
<div className="grid h-12 flex-none grid-cols-[44px_1fr_44px] items-center bg-white px-1">
<button type="button" onClick={() => setMobileSubView(false)} className="grid h-9 w-9 place-items-center text-text-heading">
@@ -201,7 +200,7 @@ export function SettingsLayout() {
</div>
<div className="flex flex-col gap-2.5 py-2.5">
<div className="flex flex-col bg-white">
{DIRECTORY.filter((item) => item.key !== 'profile' && item.key !== 'about').map((item, i, arr) => (
{DIRECTORY.filter((item) => item.key !== 'profile').map((item, i, arr) => (
<Link
key={item.key}
to={item.to}
@@ -217,14 +216,10 @@ export function SettingsLayout() {
<span>清空缓存</span>
<Icon name="chevron_right" className="text-xl text-icon-arrow" />
</Link>
<button type="button" onClick={notImplemented} className="flex items-center justify-between border-b border-border-list-item px-5 py-3.5 text-left text-base text-text-body">
<button type="button" onClick={notImplemented} className="flex items-center justify-between px-5 py-3.5 text-left text-base text-text-body">
<span>意见反馈</span>
<Icon name="chevron_right" className="text-xl text-icon-arrow" />
</button>
<Link to="/settings/about" className="flex items-center justify-between px-5 py-3.5 text-base text-text-body no-underline">
<span>关于 MeetingIM</span>
<Icon name="chevron_right" className="text-xl text-icon-arrow" />
</Link>
</div>
<button type="button" onClick={logout} disabled={loggingOut} className="bg-white py-3.5 text-center text-base text-danger-text disabled:opacity-50">
退出登录