diff --git a/client/electron/src/App.tsx b/client/electron/src/App.tsx index cf04c23..882a652 100644 --- a/client/electron/src/App.tsx +++ b/client/electron/src/App.tsx @@ -9,6 +9,7 @@ import { useSessionStore } from './stores/sessionStore'; import { useContactStore } from './stores/contactStore'; import { useUIStore } from './stores/uiStore'; import Sidebar from './components/Sidebar'; +import CommTabs, { ComposeFab } from './components/CommTabs'; import MailList from './components/MailList'; import PermissionList from './components/PermissionList'; import ContactPanel from './components/ContactPanel'; @@ -39,6 +40,26 @@ export default function App() { const resetUI = useUIStore(s => s.reset); const narrowPane = useUIStore(s => s.narrowPane); const narrow = useIsNarrow(); + const commTab = useUIStore(s => s.commTab); + + /* + * 视图切换动画的触发器(2026-09-14 用户:「页面极度缺少动画,所有页面都是直接出现」)。 + * + * 为什么不用 key 重挂载:面板是 flex 链上的一环,套 wrapper 会改变 flex 传递, + * 窄屏覆盖层最先坏。这里改成在外壳上挂一个短命类,由 CSS 给直接子面板加一次 + * 入场动画 —— DOM 结构一个字节都不动。 + * + * 必须先 remove + 强制重排再 add:同一个类连着挂两次,浏览器不会重放动画。 + */ + useEffect(() => { + const root = document.documentElement; + root.classList.remove('view-switch'); + // 读一次布局,强制样式失效(否则 remove/add 在同一帧里会被合并,动画不重放) + void root.offsetWidth; + root.classList.add('view-switch'); + const t = window.setTimeout(() => root.classList.remove('view-switch'), 400); + return () => window.clearTimeout(t); + }, [viewMode, commTab, narrowPane, composing]); const fetchInbox = useMailStore(s => s.fetchInbox); const fetchSent = useMailStore(s => s.fetchSent); @@ -156,7 +177,8 @@ export default function App() { ); // 列表(中栏):收发件箱、授权、联系人视图有 - const list = + const isComm = viewMode === 'inbox' || viewMode === 'sent' || viewMode === 'permissions'; + const listBody = viewMode === 'contacts' ? ( ) : viewMode === 'permissions' ? ( @@ -165,6 +187,23 @@ export default function App() { ) : null; + /* + * 「通信」的内部导航(收件箱 / 发件箱 / 授权)与悬浮加号都挂在中栏上。 + * + * 放在这里而不是各个子页面里,是为了"只有一套":三个页签各写一遍的话, + * 切换时的选中态、徽标口径迟早会分叉。 + * 外层 `relative` 是给悬浮加号定位用的 —— 窄屏时它正好落在底部导航之上。 + */ + const list = isComm && listBody ? ( +
+ 创建/停用账号、查看配额与密钥。只有管理员看得到这一栏。 +