Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fc91f2ed9 | |||
| c482e5b896 | |||
| 07e62e9c2d | |||
| 5797b472d9 | |||
| 3caee11e38 |
@@ -0,0 +1,6 @@
|
||||
- 写信发送拆分按钮统一使用 Gmail 风格蓝色主操作,浅色与暗色模式都保持清晰白字及一致悬停状态。
|
||||
- 修复“定时发送”菜单按左侧展开导致右边框越过写信窗口的问题,菜单改为右对齐并增加边缘避让和垂直间距。
|
||||
- 将默认主操作按钮从通用强调色中拆分,暗色主题下后台、个人设置、规则、弹窗确认、登录注册等页面统一使用深灰底白字;勾选框、进度条、选中态等仍保留清晰的强调色。
|
||||
- 已保存的浅色或暗色主题现在会在应用启动时统一恢复,切换到后台、登录及其他页面后不再丢失主题状态。
|
||||
|
||||
**完整更新日志**:[v1.2.37...v1.2.38](https://github.com/zxyszx/NewSzxcn-Email/compare/v1.2.37...v1.2.38)
|
||||
@@ -0,0 +1,4 @@
|
||||
- 修复桌面端文件夹或标签较多时侧栏被内容撑出视口、底部项目无法访问的问题;账号、邮箱切换和写信入口保持固定,邮件导航区域独立滚动。
|
||||
- 同步包含 v1.2.38 的暗色主按钮与 Gmail 蓝色发送按钮修复,更新完成后写信发送按钮在浅色和暗色模式下均为蓝底白字。
|
||||
|
||||
**完整更新日志**:[v1.2.38...v1.2.39](https://github.com/zxyszx/NewSzxcn-Email/compare/v1.2.38...v1.2.39)
|
||||
@@ -0,0 +1,6 @@
|
||||
- 修复桌面端文件夹或标签较多时侧栏被内容撑出视口、底部项目无法访问的问题;账号、邮箱切换和写信入口保持固定,邮件导航区域独立滚动。
|
||||
- 写信发送按钮在浅色和暗色模式下统一为 Gmail 风格蓝底白字,定时发送菜单在桌面和手机端均不会越过写信窗口。
|
||||
- 暗色主题默认主操作按钮改为深灰底白字,并与勾选框、进度条、危险按钮等语义颜色分离;进入后台或登录页后也会保持已选择的主题。
|
||||
- 修复备份后台任务测试结束过早导致发布流程偶发失败的问题。
|
||||
|
||||
**完整更新日志**:[v1.2.39...v1.2.40](https://github.com/zxyszx/NewSzxcn-Email/compare/v1.2.39...v1.2.40)
|
||||
@@ -0,0 +1,3 @@
|
||||
- 调整写信页定时发送菜单宽度,使其与“发送 + 下拉箭头”组合按钮左右边缘完全对齐,同时保留桌面和手机端边界避让。
|
||||
|
||||
**完整更新日志**:[v1.2.40...v1.2.41](https://github.com/zxyszx/NewSzxcn-Email/compare/v1.2.40...v1.2.41)
|
||||
@@ -316,6 +316,19 @@ func TestManualBackupReusesSavedPassword(t *testing.T) {
|
||||
if err != nil || password != "SharedBackupPassword9" {
|
||||
t.Fatalf("saved password changed: %q, %v", password, err)
|
||||
}
|
||||
deadline := time.Now().Add(10 * time.Second)
|
||||
for {
|
||||
a.backupMu.Lock()
|
||||
status := a.backupJob.Status
|
||||
a.backupMu.Unlock()
|
||||
if status != "running" {
|
||||
break
|
||||
}
|
||||
if time.Now().After(deadline) {
|
||||
t.Fatal("manual backup did not finish before timeout")
|
||||
}
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicServerIPValidation(t *testing.T) {
|
||||
|
||||
@@ -10,7 +10,7 @@ const buttonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
"bg-[hsl(var(--action-primary))] text-[hsl(var(--action-primary-foreground))] hover:bg-[hsl(var(--action-primary)/0.9)]",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
--popover-foreground: 0 0% 9%;
|
||||
--primary: 0 0% 12%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--action-primary: 0 0% 12%;
|
||||
--action-primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 12%;
|
||||
--muted: 0 0% 96.1%;
|
||||
@@ -33,6 +35,8 @@
|
||||
--sidebar-accent-foreground: 0 0% 12%;
|
||||
--sidebar-border: 0 0% 89.8%;
|
||||
--sidebar-ring: 0 0% 42%;
|
||||
--compose-send: 217 89% 43%;
|
||||
--compose-send-hover: 216 94% 32%;
|
||||
}
|
||||
|
||||
* { @apply border-border; }
|
||||
@@ -61,6 +65,8 @@
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--action-primary: 240 4% 24%;
|
||||
--action-primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
@@ -80,10 +86,22 @@
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--compose-send: 217 89% 52%;
|
||||
--compose-send-hover: 214 94% 60%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.compose-send-button.compose-send-button {
|
||||
background: hsl(var(--compose-send));
|
||||
color: white;
|
||||
}
|
||||
|
||||
.compose-send-button.compose-send-button:hover {
|
||||
background: hsl(var(--compose-send-hover));
|
||||
color: white;
|
||||
}
|
||||
|
||||
.mail-shell-grid {
|
||||
display: grid;
|
||||
grid-template-columns: var(--app-sidebar-width, 18rem) minmax(0, 1fr);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
||||
import { Navigate, RouterProvider, createBrowserRouter } from "react-router-dom"
|
||||
import { Toaster } from "@/components/ui/toaster"
|
||||
import { LanguageDomSync } from "@/lib/language"
|
||||
import { applyTheme, getInitialTheme } from "@/lib/theme"
|
||||
import { ProtectedLayout } from "@/components/protected-layout"
|
||||
import { AdminOnly } from "@/components/admin-only"
|
||||
import "./index.css"
|
||||
@@ -15,6 +16,8 @@ const AdminPage = React.lazy(() => import("@/pages/admin").then((module) => ({ d
|
||||
const ProfilePage = React.lazy(() => import("@/pages/profile").then((module) => ({ default: module.ProfilePage })))
|
||||
const NotFoundPage = React.lazy(() => import("@/pages/not-found").then((module) => ({ default: module.NotFoundPage })))
|
||||
|
||||
applyTheme(getInitialTheme())
|
||||
|
||||
const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false, staleTime: 10_000 } } })
|
||||
const router = createBrowserRouter([
|
||||
{ path: "/login", element: <LoginPage /> },
|
||||
|
||||
@@ -1307,8 +1307,8 @@ export function MailPage() {
|
||||
setAdvancedSearchOpen(false)
|
||||
}
|
||||
const sidebarContent = (
|
||||
<Sidebar collapsible="none" className="h-full w-full border-r border-border bg-sidebar text-sidebar-foreground">
|
||||
<SidebarHeader className={cn("pb-2 pt-3", sidebarCollapsed ? "px-2" : "px-3")}>
|
||||
<Sidebar collapsible="none" className="h-full min-h-0 w-full overflow-hidden border-r border-border bg-sidebar text-sidebar-foreground">
|
||||
<SidebarHeader className={cn("shrink-0 pb-2 pt-3", sidebarCollapsed ? "px-2" : "px-3")}>
|
||||
<AccountHeader
|
||||
collapsed={sidebarCollapsed}
|
||||
name={me.data?.user.displayName || selectedMailbox?.address || "NewSzxcn"}
|
||||
@@ -1352,7 +1352,7 @@ export function MailPage() {
|
||||
</Button>
|
||||
)}
|
||||
</SidebarHeader>
|
||||
<SidebarContent className="px-1">
|
||||
<SidebarContent className="min-h-0 overflow-x-hidden overflow-y-auto overscroll-contain px-1 pb-4">
|
||||
{!sidebarCollapsed && publicSettings.isError && <SidebarQueryFailure label="邮箱设置读取失败" onRetry={() => { void publicSettings.refetch() }} />}
|
||||
<SidebarGroup>
|
||||
{!sidebarCollapsed && (
|
||||
@@ -1884,7 +1884,7 @@ export function MailPage() {
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="w-[86vw] max-w-80 p-0 [&>button]:hidden" aria-describedby={undefined}>
|
||||
<SheetTitle className="sr-only">邮箱导航</SheetTitle>
|
||||
<div className="h-svh">{sidebarContent}</div>
|
||||
<div className="h-svh min-h-0 overflow-hidden">{sidebarContent}</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<div className="min-w-0 flex-1 text-sm font-semibold">{mailView === "label" && selectedLabel ? <Badge variant="outline" className="gap-1.5 rounded-md font-normal"><span className="h-2 w-2 shrink-0 rounded-full" style={{ backgroundColor: labelDotColor(selectedLabel) }} />{selectedLabel.name}</Badge> : viewTitle}</div>
|
||||
@@ -1900,7 +1900,7 @@ export function MailPage() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="mail-shell-grid h-full min-h-0 w-full min-w-0 overflow-hidden">
|
||||
<div className="min-w-0">
|
||||
<div className="h-full min-h-0 min-w-0 overflow-hidden">
|
||||
{sidebarContent}
|
||||
</div>
|
||||
<section className="flex h-full min-h-0 min-w-0 flex-col">
|
||||
@@ -4286,15 +4286,15 @@ function ComposeDialog({ mailboxes, mailbox, open, draft, limits, canSend, canMa
|
||||
<DialogFooter className="flex flex-row items-center justify-between gap-3 border-t bg-muted/15 px-4 py-3 sm:px-5">
|
||||
{canSend && (
|
||||
<div className="flex min-w-0 items-center">
|
||||
<Button className={cn("min-h-10 px-4", canSchedule && "rounded-r-none")} disabled={send.isPending || !senderMailbox}><Send className="h-4 w-4" />{send.isPending ? "发送中..." : "发送"}</Button>
|
||||
<Button className={cn("compose-send-button min-h-10 px-4", canSchedule && "rounded-r-none")} disabled={send.isPending || !senderMailbox}><Send className="h-4 w-4" />{send.isPending ? "发送中..." : "发送"}</Button>
|
||||
{canSchedule && (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button type="button" size="icon" className="h-10 w-9 shrink-0 rounded-l-none border-l border-primary-foreground/25 px-0" title="发送选项" aria-label="发送选项" disabled={send.isPending || scheduleSend.isPending || !senderMailbox}>
|
||||
<Button type="button" size="icon" className="compose-send-button h-10 w-9 shrink-0 rounded-l-none border-l border-white/30 px-0" title="发送选项" aria-label="发送选项" disabled={send.isPending || scheduleSend.isPending || !senderMailbox}>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" side="top" className="w-40">
|
||||
<DropdownMenuContent align="end" side="top" sideOffset={8} collisionPadding={12} className="w-[120px] min-w-[120px]">
|
||||
<DropdownMenuItem className={composerMenuItemClass} onSelect={() => setScheduleDialogOpen(true)}><Clock3 className="h-4 w-4" />定时发送</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
Reference in New Issue
Block a user