{children}
{action}
@@ -1983,7 +2084,7 @@ function MailBodyComposer({ defaultValue, defaultHtml, files, signatureText, onC
content: composerInitialHtml(defaultValue, defaultHtml),
editorProps: {
attributes: {
- class: "mail-html min-h-[280px] overflow-y-auto px-6 py-5 text-base leading-7 outline-none",
+ class: "mail-html min-h-[260px] overflow-y-auto px-4 py-4 text-base leading-7 outline-none sm:min-h-[280px] sm:px-6 sm:py-5",
"aria-label": "正文",
},
handlePaste(view, event) {
@@ -2105,9 +2206,9 @@ function MailBodyComposer({ defaultValue, defaultHtml, files, signatureText, onC
}
return (
-
+
-
+
editor?.chain().focus().undo().run()}>
editor?.chain().focus().redo().run()}>
@@ -2151,7 +2252,7 @@ function MailBodyComposer({ defaultValue, defaultHtml, files, signatureText, onC
{formatOpen && (
-
+
editor?.chain().focus().unsetAllMarks().clearNodes().run()}>
@@ -2234,7 +2335,7 @@ function MailBodyComposer({ defaultValue, defaultHtml, files, signatureText, onC
)}
{files.length > 0 && (
-
+
{files.map((file, index) => (
diff --git a/apps/web/src/pages/profile.tsx b/apps/web/src/pages/profile.tsx
index 9933acf..8c200f7 100644
--- a/apps/web/src/pages/profile.tsx
+++ b/apps/web/src/pages/profile.tsx
@@ -10,6 +10,7 @@ import { applyTheme, getInitialTheme } from "@/lib/theme"
import { DisplayMode, useDisplayMode } from "@/lib/display-mode"
import { useMe } from "@/hooks/use-me"
import { useLogout } from "@/hooks/use-logout"
+import { useIsMobile } from "@/hooks/use-mobile"
import { validatePasswordConfirm } from "@/lib/validation"
import { Button } from "@/components/ui/button"
import { PasswordInput } from "@/components/ui/password-input"
@@ -21,6 +22,7 @@ import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Checkbox } from "@/components/ui/checkbox"
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
+import { Sheet, SheetContent, SheetTitle, SheetTrigger } from "@/components/ui/sheet"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Separator } from "@/components/ui/separator"
import { ScrollArea } from "@/components/ui/scroll-area"
@@ -60,6 +62,8 @@ export function ProfilePage() {
const [displayMode, setDisplayMode] = useDisplayMode()
const [blockedMailboxId, setBlockedMailboxId] = React.useState("all")
const [ruleDialogOpen, setRuleDialogOpen] = React.useState(false)
+ const [mobileSidebarOpen, setMobileSidebarOpen] = React.useState(false)
+ const isMobile = useIsMobile()
const themeMountedRef = React.useRef(false)
const rawTab = params.get("tab") as Tab | null
@@ -187,52 +191,78 @@ export function ProfilePage() {
const logout = useLogout()
async function copy(text: string) { await navigator.clipboard.writeText(text); toast({ title: "已复制" }) }
- function setTab(next: Tab) { setParams(next === "profile" ? {} : { tab: next }) }
+ function setTab(next: Tab) { setParams(next === "profile" ? {} : { tab: next }); setMobileSidebarOpen(false) }
function toggleSidebar() { sidebarCollapsed ? (sidebarPanelRef.current?.expand(14), setSidebarCollapsed(false)) : (sidebarPanelRef.current?.collapse(), setSidebarCollapsed(true)) }
if (me.isLoading) return 加载中...
if (me.isError || !user) return 登录状态已失效
+ const sidebarContent = (
+
+
+ setDarkMode((v) => !v)} onBack={() => navigate("/")} />
+
+
+
+ {!sidebarCollapsed && 个人中心}
+
+ {tabKeys.map((key) => setTab(key)}>{tabs[key].icon}{!sidebarCollapsed && {tabs[key].label}})}
+
+
+
+
+
+ {!isMobile && (
+ <>
+
+
+ >
+ )}
+
+
+ )
+
return (
-
+
-
- setSidebarCollapsed(true)} onExpand={() => setSidebarCollapsed(false)}>
-
-
- setDarkMode((v) => !v)} onBack={() => navigate("/")} />
-
-
-
- {!sidebarCollapsed && 个人中心}
-
- {tabKeys.map((key) => setTab(key)}>{tabs[key].icon}{!sidebarCollapsed && {tabs[key].label}})}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {isMobile ? (
+
+
+
+
+
+
+
+ 个人中心导航
+ {sidebarContent}
+
+
+ {tabs[tab].label}
+
+
+
{renderTab()}
+
+ ) : (
+
+ setSidebarCollapsed(true)} onExpand={() => setSidebarCollapsed(false)}>
+ {sidebarContent}
+
+
+
+
+
+
+ )}
)
-
function renderTab() {
if (tab === "mailboxes") return
{ setMailboxId(id); navigate("/") }} onApply={(payload) => applyMailbox.mutateAsync(payload).then(() => undefined)} />
if (tab === "clients") return
@@ -439,7 +469,7 @@ function ApplyMailboxDialog({ options, pending, onApply }: { options: MailboxApp
return (
-
+