[Refactor] Async load all setting panels (#3604)

This commit is contained in:
Chenlei Hu
2025-04-24 13:00:42 -04:00
committed by GitHub
parent fcbdee54ec
commit 26f98d24fb
2 changed files with 89 additions and 73 deletions

View File

@@ -47,27 +47,10 @@
<SettingsPanel :setting-groups="sortedGroups(category)" /> <SettingsPanel :setting-groups="sortedGroups(category)" />
</PanelTemplate> </PanelTemplate>
<AboutPanel /> <Suspense v-for="panel in panels" :key="panel.node.key">
<UserPanel /> <component :is="panel.component" />
<CreditsPanel />
<Suspense>
<KeybindingPanel />
<template #fallback> <template #fallback>
<div>Loading keybinding panel...</div> <div>Loading {{ panel.node.label }} panel...</div>
</template>
</Suspense>
<Suspense>
<ExtensionPanel />
<template #fallback>
<div>Loading extension panel...</div>
</template>
</Suspense>
<Suspense>
<ServerConfigPanel />
<template #fallback>
<div>Loading server config panel...</div>
</template> </template>
</Suspense> </Suspense>
</TabPanels> </TabPanels>
@@ -81,7 +64,7 @@ import Listbox from 'primevue/listbox'
import ScrollPanel from 'primevue/scrollpanel' import ScrollPanel from 'primevue/scrollpanel'
import TabPanels from 'primevue/tabpanels' import TabPanels from 'primevue/tabpanels'
import Tabs from 'primevue/tabs' import Tabs from 'primevue/tabs'
import { computed, defineAsyncComponent, watch } from 'vue' import { computed, watch } from 'vue'
import SearchBox from '@/components/common/SearchBox.vue' import SearchBox from '@/components/common/SearchBox.vue'
import { useSettingSearch } from '@/composables/setting/useSettingSearch' import { useSettingSearch } from '@/composables/setting/useSettingSearch'
@@ -91,14 +74,11 @@ import { SettingTreeNode } from '@/stores/settingStore'
import { ISettingGroup, SettingParams } from '@/types/settingTypes' import { ISettingGroup, SettingParams } from '@/types/settingTypes'
import { flattenTree } from '@/utils/treeUtil' import { flattenTree } from '@/utils/treeUtil'
import AboutPanel from './setting/AboutPanel.vue'
import ColorPaletteMessage from './setting/ColorPaletteMessage.vue' import ColorPaletteMessage from './setting/ColorPaletteMessage.vue'
import CreditsPanel from './setting/CreditsPanel.vue'
import CurrentUserMessage from './setting/CurrentUserMessage.vue' import CurrentUserMessage from './setting/CurrentUserMessage.vue'
import FirstTimeUIMessage from './setting/FirstTimeUIMessage.vue' import FirstTimeUIMessage from './setting/FirstTimeUIMessage.vue'
import PanelTemplate from './setting/PanelTemplate.vue' import PanelTemplate from './setting/PanelTemplate.vue'
import SettingsPanel from './setting/SettingsPanel.vue' import SettingsPanel from './setting/SettingsPanel.vue'
import UserPanel from './setting/UserPanel.vue'
const { defaultPanel } = defineProps<{ const { defaultPanel } = defineProps<{
defaultPanel?: defaultPanel?:
@@ -110,21 +90,12 @@ const { defaultPanel } = defineProps<{
| 'credits' | 'credits'
}>() }>()
const KeybindingPanel = defineAsyncComponent(
() => import('./setting/KeybindingPanel.vue')
)
const ExtensionPanel = defineAsyncComponent(
() => import('./setting/ExtensionPanel.vue')
)
const ServerConfigPanel = defineAsyncComponent(
() => import('./setting/ServerConfigPanel.vue')
)
const { const {
activeCategory, activeCategory,
defaultCategory, defaultCategory,
settingCategories, settingCategories,
groupedMenuTreeNodes groupedMenuTreeNodes,
panels
} = useSettingUI(defaultPanel) } = useSettingUI(defaultPanel)
const { const {

View File

@@ -1,4 +1,10 @@
import { computed, onMounted, ref } from 'vue' import {
type Component,
computed,
defineAsyncComponent,
onMounted,
ref
} from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
@@ -8,6 +14,11 @@ import { isElectron } from '@/utils/envUtil'
import { normalizeI18nKey } from '@/utils/formatUtil' import { normalizeI18nKey } from '@/utils/formatUtil'
import { buildTree } from '@/utils/treeUtil' import { buildTree } from '@/utils/treeUtil'
interface SettingPanelItem {
node: SettingTreeNode
component: Component
}
export function useSettingUI( export function useSettingUI(
defaultPanel?: defaultPanel?:
| 'about' | 'about'
@@ -48,49 +59,82 @@ export function useSettingUI(
() => settingRoot.value.children ?? [] () => settingRoot.value.children ?? []
) )
// Define panel nodes // Define panel items
const aboutPanelNode: SettingTreeNode = { const aboutPanel: SettingPanelItem = {
key: 'about', node: {
label: 'About', key: 'about',
children: [] label: 'About',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/AboutPanel.vue')
)
} }
const creditsPanelNode: SettingTreeNode = { const creditsPanel: SettingPanelItem = {
key: 'credits', node: {
label: 'Credits', key: 'credits',
children: [] label: 'Credits',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/CreditsPanel.vue')
)
} }
const userPanelNode: SettingTreeNode = { const userPanel: SettingPanelItem = {
key: 'user', node: {
label: 'User', key: 'user',
children: [] label: 'User',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/UserPanel.vue')
)
} }
const keybindingPanelNode: SettingTreeNode = { const keybindingPanel: SettingPanelItem = {
key: 'keybinding', node: {
label: 'Keybinding', key: 'keybinding',
children: [] label: 'Keybinding',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/KeybindingPanel.vue')
)
} }
const extensionPanelNode: SettingTreeNode = { const extensionPanel: SettingPanelItem = {
key: 'extension', node: {
label: 'Extension', key: 'extension',
children: [] label: 'Extension',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/ExtensionPanel.vue')
)
} }
const serverConfigPanelNode: SettingTreeNode = { const serverConfigPanel: SettingPanelItem = {
key: 'server-config', node: {
label: 'Server-Config', key: 'server-config',
children: [] label: 'Server-Config',
children: []
},
component: defineAsyncComponent(
() => import('@/components/dialog/content/setting/ServerConfigPanel.vue')
)
} }
/** const panels = computed<SettingPanelItem[]>(() =>
* Server config panel is only available in Electron [
*/ aboutPanel,
const serverConfigPanelNodeList = computed<SettingTreeNode[]>(() => { creditsPanel,
return isElectron() ? [serverConfigPanelNode] : [] userPanel,
}) keybindingPanel,
extensionPanel
].filter((panel) => panel.component)
)
/** /**
* The default category to show when the dialog is opened. * The default category to show when the dialog is opened.
@@ -119,8 +163,8 @@ export function useSettingUI(
key: 'account', key: 'account',
label: 'Account', label: 'Account',
children: [ children: [
userPanelNode, userPanel.node,
...(firebaseAuthStore.isAuthenticated ? [creditsPanelNode] : []) ...(firebaseAuthStore.isAuthenticated ? [creditsPanel.node] : [])
].map(translateCategory) ].map(translateCategory)
}, },
// Normal settings stored in the settingStore // Normal settings stored in the settingStore
@@ -134,10 +178,10 @@ export function useSettingUI(
key: 'specialSettings', key: 'specialSettings',
label: 'Special Settings', label: 'Special Settings',
children: [ children: [
keybindingPanelNode, keybindingPanel.node,
extensionPanelNode, extensionPanel.node,
aboutPanelNode, aboutPanel.node,
...serverConfigPanelNodeList.value ...(isElectron() ? [serverConfigPanel.node] : [])
].map(translateCategory) ].map(translateCategory)
} }
]) ])
@@ -147,6 +191,7 @@ export function useSettingUI(
}) })
return { return {
panels,
activeCategory, activeCategory,
defaultCategory, defaultCategory,
groupedMenuTreeNodes, groupedMenuTreeNodes,