Skip to content

Commit 345100f

Browse files
authored
feat(web): polish cloud panel footer and style UI (#1677)
Unify sync footer metadata via useSyncFooterMeta, collapse mobile footer actions into an overflow menu, replace style panel toggles with switches, extract CloudPanelInfoRows, and simplify the account dialog.
1 parent 5ea9902 commit 345100f

7 files changed

Lines changed: 254 additions & 201 deletions

File tree

apps/web/src/components/editor/Footer.vue

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { StateEffect } from '@codemirror/state'
33
import { EditorView } from '@codemirror/view'
4-
import { ArrowUpDown, BookOpen, ChevronRight, ChevronsUpDown, Clock, Cloud, CloudAlert, CloudCheck, CloudOff, Columns2, Eye, FileText, Keyboard, ListTree, Loader2, LogIn, Monitor, Moon, PenLine, Pilcrow, Search, Share2, Smartphone, Sun, Type, User } from '@lucide/vue'
4+
import { ArrowUpDown, BookOpen, ChevronRight, ChevronsUpDown, Clock, Columns2, Ellipsis, Eye, FileText, Keyboard, ListTree, LogIn, Monitor, Moon, PenLine, Pilcrow, Search, Share2, Smartphone, Sun, Type, User } from '@lucide/vue'
55
import {
66
Popover,
77
PopoverContent,
@@ -13,23 +13,21 @@ import {
1313
TooltipProvider,
1414
TooltipTrigger,
1515
} from '@/components/ui/tooltip'
16-
import { useSyncStatusMeta } from '@/composables/useSyncStatusMeta'
16+
import { useSyncFooterMeta } from '@/composables/useSyncStatusMeta'
1717
import { isAccountUiEnabled } from '@/services/account/config'
1818
import { isShareUiEnabled } from '@/services/share/client'
1919
import { isSyncUiEnabled } from '@/services/sync/client'
2020
import { useAuthStore } from '@/stores/auth'
2121
import { useEditorStore } from '@/stores/editor'
2222
import { usePostStore } from '@/stores/post'
2323
import { useRenderStore } from '@/stores/render'
24-
import { useSyncStore } from '@/stores/sync'
2524
import { useUIStore } from '@/stores/ui'
2625
2726
const renderStore = useRenderStore()
2827
const editorStore = useEditorStore()
2928
const postStore = usePostStore()
3029
const uiStore = useUIStore()
3130
const authStore = useAuthStore()
32-
const syncStore = useSyncStore()
3331
const { readingTime } = storeToRefs(renderStore)
3432
const { editor } = storeToRefs(editorStore)
3533
const { currentPost } = storeToRefs(postStore)
@@ -39,35 +37,35 @@ const { isLoggedIn } = storeToRefs(authStore)
3937
const showAccountUi = isAccountUiEnabled()
4038
const showSyncUi = isSyncUiEnabled()
4139
const showShareUi = isShareUiEnabled()
42-
const { isSyncing, syncState } = storeToRefs(syncStore)
43-
const { syncStatusMeta, syncTooltip } = useSyncStatusMeta()
40+
const { syncFooterIcon, syncFooterIconClass, syncTooltip } = useSyncFooterMeta()
41+
42+
const isMoreOpen = ref(false)
4443
4544
const accountTooltip = computed(() => {
4645
if (!isLoggedIn.value)
4746
return `登录账户`
4847
return `账户 @${authStore.user?.login ?? ''}`
4948
})
5049
51-
const syncFooterIcon = computed(() => {
52-
if (!isLoggedIn.value)
53-
return Cloud
54-
if (isSyncing.value || syncState.value === `syncing`)
55-
return Loader2
56-
switch (syncState.value) {
57-
case `synced`:
58-
return CloudCheck
59-
case `error`:
60-
return CloudAlert
61-
default:
62-
return CloudOff
63-
}
64-
})
50+
function openAccountDialog() {
51+
isMoreOpen.value = false
52+
uiStore.toggleShowAccountDialog(true)
53+
}
6554
66-
const syncFooterIconClass = computed(() => {
67-
if (!isLoggedIn.value)
68-
return ``
69-
return syncStatusMeta.value.footerIconClass
70-
})
55+
function openSyncDialog() {
56+
isMoreOpen.value = false
57+
uiStore.toggleShowSyncDialog(true)
58+
}
59+
60+
function openShareDialog() {
61+
isMoreOpen.value = false
62+
uiStore.openShareDialog()
63+
}
64+
65+
function toggleTheme() {
66+
isMoreOpen.value = false
67+
uiStore.toggleDark()
68+
}
7169
7270
// 相对时间格式化(复用)
7371
function formatRelativeTime(date: Date | string) {
@@ -655,16 +653,16 @@ const showDeviceToggle = computed(() => viewMode.value !== `edit` && !isMobile.v
655653

656654
<span class="hidden text-border sm:block">·</span>
657655

658-
<!-- 账户 & 同步 & 分享 & 主题 -->
659-
<div class="flex items-center gap-0.5">
656+
<!-- 账户 & 同步 & 分享 & 主题(桌面端) -->
657+
<div class="hidden items-center gap-0.5 sm:flex">
660658
<template v-if="showAccountUi">
661659
<Tooltip>
662660
<TooltipTrigger as-child>
663661
<button
664662
aria-label="账户"
665663
class="flex cursor-pointer items-center rounded-md p-1.5 transition-colors hover:bg-accent hover:text-foreground"
666664
:class="isLoggedIn ? 'text-primary' : ''"
667-
@click="uiStore.toggleShowAccountDialog(true)"
665+
@click="openAccountDialog"
668666
>
669667
<img
670668
v-if="isLoggedIn && authStore.user?.avatar"
@@ -688,8 +686,7 @@ const showDeviceToggle = computed(() => viewMode.value !== `edit` && !isMobile.v
688686
<button
689687
aria-label="云同步"
690688
class="flex cursor-pointer items-center rounded-md p-1.5 transition-colors hover:bg-accent hover:text-foreground"
691-
:class="isLoggedIn ? 'text-primary' : ''"
692-
@click="uiStore.toggleShowSyncDialog(true)"
689+
@click="openSyncDialog"
693690
>
694691
<component
695692
:is="syncFooterIcon"
@@ -710,7 +707,7 @@ const showDeviceToggle = computed(() => viewMode.value !== `edit` && !isMobile.v
710707
<button
711708
aria-label="分享预览"
712709
class="flex cursor-pointer items-center rounded-md p-1.5 transition-colors hover:bg-accent hover:text-foreground"
713-
@click="uiStore.openShareDialog()"
710+
@click="openShareDialog"
714711
>
715712
<Share2 class="size-4" />
716713
</button>
@@ -724,9 +721,10 @@ const showDeviceToggle = computed(() => viewMode.value !== `edit` && !isMobile.v
724721
<Tooltip>
725722
<TooltipTrigger as-child>
726723
<button
724+
aria-label="切换深色模式"
727725
class="flex cursor-pointer items-center rounded-md p-1.5 transition-colors hover:bg-accent hover:text-foreground"
728726
:class="isDark ? 'text-foreground' : ''"
729-
@click="uiStore.toggleDark()"
727+
@click="toggleTheme"
730728
>
731729
<Moon v-if="isDark" class="size-4" />
732730
<Sun v-else class="size-4" />
@@ -737,6 +735,63 @@ const showDeviceToggle = computed(() => viewMode.value !== `edit` && !isMobile.v
737735
</TooltipContent>
738736
</Tooltip>
739737
</div>
738+
739+
<!-- 移动端:更多操作 -->
740+
<Popover v-model:open="isMoreOpen">
741+
<PopoverTriggerPrimitive as-child>
742+
<button
743+
aria-label="更多操作"
744+
class="flex cursor-pointer items-center rounded-md p-1.5 transition-colors hover:bg-accent hover:text-foreground sm:hidden"
745+
>
746+
<Ellipsis class="size-4" />
747+
</button>
748+
</PopoverTriggerPrimitive>
749+
<PopoverContent side="top" :side-offset="8" align="end" class="w-48 p-1">
750+
<button
751+
v-if="showAccountUi"
752+
class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2.5 py-2 text-left text-xs transition-colors hover:bg-accent"
753+
@click="openAccountDialog"
754+
>
755+
<img
756+
v-if="isLoggedIn && authStore.user?.avatar"
757+
:src="authStore.user.avatar"
758+
:alt="authStore.user.login"
759+
class="size-4 rounded-full"
760+
>
761+
<User v-else-if="isLoggedIn" class="size-4 shrink-0" />
762+
<LogIn v-else class="size-4 shrink-0" />
763+
<span class="min-w-0 flex-1 truncate">{{ accountTooltip }}</span>
764+
</button>
765+
<button
766+
v-if="showSyncUi"
767+
class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2.5 py-2 text-left text-xs transition-colors hover:bg-accent"
768+
@click="openSyncDialog"
769+
>
770+
<component
771+
:is="syncFooterIcon"
772+
class="size-4 shrink-0"
773+
:class="syncFooterIconClass"
774+
/>
775+
<span>{{ isLoggedIn ? syncTooltip : '云同步' }}</span>
776+
</button>
777+
<button
778+
v-if="showShareUi"
779+
class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2.5 py-2 text-left text-xs transition-colors hover:bg-accent"
780+
@click="openShareDialog"
781+
>
782+
<Share2 class="size-4 shrink-0" />
783+
<span>分享预览</span>
784+
</button>
785+
<button
786+
class="flex w-full cursor-pointer items-center gap-2 rounded-md px-2.5 py-2 text-left text-xs transition-colors hover:bg-accent"
787+
@click="toggleTheme"
788+
>
789+
<Moon v-if="isDark" class="size-4 shrink-0" />
790+
<Sun v-else class="size-4 shrink-0" />
791+
<span>{{ isDark ? '浅色模式' : '深色模式' }}</span>
792+
</button>
793+
</PopoverContent>
794+
</Popover>
740795
</div>
741796
</TooltipProvider>
742797
</footer>

0 commit comments

Comments
 (0)