perf(desktop): defer startup payloads

This commit is contained in:
t8y2
2026-05-18 23:19:30 +08:00
parent c29bd98d94
commit b6be8a74df
4 changed files with 87 additions and 21 deletions
@@ -18,12 +18,12 @@ import "splitpanes/dist/splitpanes.css";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import QueryEditor from "@/components/editor/QueryEditor.vue";
import DataGrid from "@/components/grid/DataGrid.vue";
import RedisKeyBrowser from "@/components/redis/RedisKeyBrowser.vue";
import MongoDocBrowser from "@/components/mongo/MongoDocBrowser.vue";
import ObjectBrowser from "@/components/objects/ObjectBrowser.vue";
import ColumnInfoPanel from "@/components/editor/ColumnInfoPanel.vue";
import type { ColumnInfo } from "@/components/editor/ColumnInfoPanel.vue";
const DataGrid = defineAsyncComponent(() => import("@/components/grid/DataGrid.vue"));
const RedisKeyBrowser = defineAsyncComponent(() => import("@/components/redis/RedisKeyBrowser.vue"));
const MongoDocBrowser = defineAsyncComponent(() => import("@/components/mongo/MongoDocBrowser.vue"));
const ObjectBrowser = defineAsyncComponent(() => import("@/components/objects/ObjectBrowser.vue"));
const ExplainPlanViewer = defineAsyncComponent(() => import("@/components/explain/ExplainPlanViewer.vue"));
const QueryChart = defineAsyncComponent(() => import("@/components/chart/QueryChart.vue"));
import { useQueryStore } from "@/stores/queryStore";
@@ -33,6 +33,24 @@ import { isTableDataEditable } from "@/lib/tableEditing";
import type { QueryTab, ConnectionConfig } from "@/types/database";
import type { SqlFormatDialect } from "@/lib/sqlFormatter";
type DataGridHandle = {
onToolbarRefresh: () => Promise<void> | void;
focusSearch: () => boolean;
visibleColumnCount: number;
displayableColumnCount: number;
hiddenColumnCount: number;
filteredColumnVisibilityOptions: (search: string) => Array<{ index: number; column: string }>;
isColumnVisible: (columnIndex: number) => boolean;
toggleColumnVisibility: (columnIndex: number) => void;
showAllColumns: () => void;
showDdl: boolean;
toggleDdl: () => void;
};
type SearchableBrowserHandle = {
focusSearch: () => boolean;
};
const props = defineProps<{
activeTab: QueryTab;
activeConnection?: ConnectionConfig;
@@ -71,13 +89,13 @@ const showColumnInfo = ref(false);
const columnInfoColumns = ref<ColumnInfo[]>([]);
const columnInfoLoading = ref(false);
const columnInfoError = ref<string | undefined>(undefined);
const dataGridRef = ref<InstanceType<typeof DataGrid>>();
const dataGridRef = ref<DataGridHandle>();
const columnVisibilitySearch = ref("");
const columnVisibilityOptions = computed(
() => dataGridRef.value?.filteredColumnVisibilityOptions(columnVisibilitySearch.value) ?? [],
);
const redisKeyBrowserRef = ref<InstanceType<typeof RedisKeyBrowser>>();
const objectBrowserRef = ref<InstanceType<typeof ObjectBrowser>>();
const redisKeyBrowserRef = ref<SearchableBrowserHandle>();
const objectBrowserRef = ref<SearchableBrowserHandle>();
const activeSqlFormatDialect = computed<SqlFormatDialect>(() => {
switch (props.activeConnection?.db_type) {
+29 -8
View File
@@ -1,12 +1,20 @@
import { createI18n } from "vue-i18n";
import en from "./locales/en";
import es from "./locales/es";
import zhCN from "./locales/zh-CN";
export type Locale = "en" | "es" | "zh-CN";
type LocaleMessages = Record<string, unknown>;
type I18nGlobal = {
locale: { value: Locale };
setLocaleMessage: (locale: Locale, messages: LocaleMessages) => void;
};
const supportedLocales: Locale[] = ["en", "es", "zh-CN"];
const defaultLocale: Locale = "zh-CN";
const loadedLocales = new Set<Locale>([defaultLocale]);
const localeLoaders: Record<Exclude<Locale, "zh-CN">, () => Promise<{ default: LocaleMessages }>> = {
en: () => import("./locales/en"),
es: () => import("./locales/es"),
};
function normalizeLocale(value: string | null): Locale {
if (value && supportedLocales.includes(value as Locale)) {
@@ -20,21 +28,34 @@ const savedLocale = normalizeLocale(localStorage.getItem("dbx-locale"));
const i18n = createI18n({
legacy: false,
locale: savedLocale,
fallbackLocale: "en",
fallbackLocale: defaultLocale,
messages: {
en,
es,
"zh-CN": zhCN,
},
});
const i18nGlobal = i18n.global as unknown as I18nGlobal;
export function setLocale(locale: Locale) {
i18n.global.locale.value = locale;
export async function loadLocaleMessages(locale: Locale) {
if (loadedLocales.has(locale)) return;
const loader = localeLoaders[locale as Exclude<Locale, "zh-CN">];
if (!loader) return;
const messages = await loader();
i18nGlobal.setLocaleMessage(locale, messages.default);
loadedLocales.add(locale);
}
export async function loadSavedLocale() {
await loadLocaleMessages(savedLocale);
}
export async function setLocale(locale: Locale) {
await loadLocaleMessages(locale);
i18nGlobal.locale.value = locale;
localStorage.setItem("dbx-locale", locale);
}
export function currentLocale(): Locale {
return i18n.global.locale.value as Locale;
return i18nGlobal.locale.value;
}
export function nextLocale(current: Locale): Locale {
+12 -6
View File
@@ -2,12 +2,18 @@ import { createApp } from "vue";
import { createPinia } from "pinia";
import VueVirtualScroller from "vue-virtual-scroller";
import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
import i18n from "./i18n";
import i18n, { loadSavedLocale } from "./i18n";
import App from "./App.vue";
import "./styles/globals.css";
const app = createApp(App);
app.use(createPinia());
app.use(i18n);
app.use(VueVirtualScroller);
app.mount("#root");
async function bootstrap() {
await loadSavedLocale();
const app = createApp(App);
app.use(createPinia());
app.use(i18n);
app.use(VueVirtualScroller);
app.mount("#root");
}
void bootstrap();