feat(portal): add light/dark theme sync and OA drive navigation
Memind CI / Test, build, and release guards (push) Successful in 4m31s
Memind CI / Test, build, and release guards (push) Successful in 4m31s
Unify chat and OA drive appearance with shared memind-theme storage, default light mode, and cross-frame sync so users can switch themes from chat or the drive shell. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import { WechatBindPrompt } from './WechatBindPrompt';
|
||||
import { WechatAccountButton } from './WechatAccountButton';
|
||||
import { ChatHeaderMoreMenu } from './ChatHeaderMoreMenu';
|
||||
import { NotificationCenter } from './NotificationCenter';
|
||||
import { ThemeToggle } from './ThemeToggle';
|
||||
import { GoalRunAwaitingBanner } from './GoalRunAwaitingBanner';
|
||||
import { HealthChannelBanner } from './HealthChannelBanner';
|
||||
import { HealthAlertsPanel } from './HealthAlertsPanel';
|
||||
@@ -173,6 +174,7 @@ export function ChatView({
|
||||
onGrantedSkillsUpdate,
|
||||
onLogout,
|
||||
onOpenSpace,
|
||||
onOpenOaDrive,
|
||||
onOpenPage,
|
||||
onOpenAdmin,
|
||||
onOpenFeedback,
|
||||
@@ -184,6 +186,7 @@ export function ChatView({
|
||||
onGrantedSkillsUpdate?: (skills: string[]) => void;
|
||||
onLogout?: () => void;
|
||||
onOpenSpace?: (target?: { categoryCode?: MindSpaceSaveCategory; pageId?: string }) => void;
|
||||
onOpenOaDrive?: () => void;
|
||||
onOpenPage?: (pageId: string) => void;
|
||||
onOpenAdmin?: () => void;
|
||||
onOpenFeedback?: () => void;
|
||||
@@ -327,6 +330,9 @@ export function ChatView({
|
||||
: pendingSessionTitle;
|
||||
|
||||
const moreMenuItems = [
|
||||
...(onOpenOaDrive
|
||||
? [{ id: 'oa-drive', label: 'OA 网盘', onClick: () => onOpenOaDrive() }]
|
||||
: []),
|
||||
...(onOpenAdmin
|
||||
? [{ id: 'admin', label: '管理', onClick: () => onOpenAdmin() }]
|
||||
: []),
|
||||
@@ -427,6 +433,16 @@ export function ChatView({
|
||||
管理
|
||||
</button>
|
||||
)}
|
||||
{onOpenOaDrive && (
|
||||
<button
|
||||
type="button"
|
||||
className="ghost-btn"
|
||||
data-analytics-action="open_oa_drive"
|
||||
onClick={() => onOpenOaDrive()}
|
||||
>
|
||||
OA 网盘
|
||||
</button>
|
||||
)}
|
||||
{onOpenSpace && (
|
||||
<button
|
||||
ref={spaceButtonRef}
|
||||
@@ -438,6 +454,7 @@ export function ChatView({
|
||||
我的空间
|
||||
</button>
|
||||
)}
|
||||
<ThemeToggle />
|
||||
{user && <WechatAccountButton returnTo={window.location.pathname} />}
|
||||
{onLogout && (
|
||||
<button type="button" className="ghost-btn logout-btn" data-analytics-action="logout" onClick={onLogout}>
|
||||
@@ -501,6 +518,7 @@ export function ChatView({
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
<ThemeToggle className="ghost-btn theme-toggle-btn theme-toggle-btn-mobile" />
|
||||
<ChatHeaderMoreMenu
|
||||
items={moreMenuItems}
|
||||
returnTo={window.location.pathname}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getStoredTheme, toggleTheme, type MemindTheme } from '../utils/theme';
|
||||
|
||||
export function ThemeToggle({
|
||||
className = 'ghost-btn theme-toggle-btn',
|
||||
}: {
|
||||
className?: string;
|
||||
}) {
|
||||
const [theme, setTheme] = useState<MemindTheme>(() => getStoredTheme());
|
||||
|
||||
useEffect(() => {
|
||||
const onChange = (event: Event) => {
|
||||
const detail = (event as CustomEvent<{ theme: MemindTheme }>).detail;
|
||||
if (detail?.theme) setTheme(detail.theme);
|
||||
};
|
||||
window.addEventListener('memind-theme-change', onChange);
|
||||
return () => window.removeEventListener('memind-theme-change', onChange);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={className}
|
||||
data-analytics-action="toggle_theme"
|
||||
aria-label={theme === 'light' ? '切换深色模式' : '切换浅色模式'}
|
||||
title={theme === 'light' ? '切换深色模式' : '切换浅色模式'}
|
||||
onClick={() => setTheme(toggleTheme())}
|
||||
>
|
||||
{theme === 'light' ? '深色' : '浅色'}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user