mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-21 15:53:50 +02:00
refactor custom nav dialog
This commit is contained in:
@@ -302,8 +302,9 @@
|
||||
<CustomNavDialog
|
||||
v-model:visible="customNavDialogVisible"
|
||||
:layout="navLayout"
|
||||
@save="handleCustomNavSave"
|
||||
@reset="handleCustomNavReset" />
|
||||
:hidden-keys="navHiddenKeys"
|
||||
:default-layout="defaultNavLayout"
|
||||
@save="handleCustomNavSave" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -346,7 +347,6 @@
|
||||
import {
|
||||
useAppearanceSettingsStore,
|
||||
useAuthStore,
|
||||
useModalStore,
|
||||
useSearchStore,
|
||||
useUiStore,
|
||||
useVRCXUpdaterStore
|
||||
@@ -360,7 +360,6 @@
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
const router = useRouter();
|
||||
const modalStore = useModalStore();
|
||||
|
||||
const createDefaultNavLayout = () => [
|
||||
{ type: 'item', key: 'feed' },
|
||||
@@ -399,7 +398,23 @@
|
||||
];
|
||||
|
||||
const navDefinitionMap = new Map(navDefinitions.map((item) => [item.key, item]));
|
||||
const DEFAULT_FOLDER_ICON = 'ri-menu-fold-line';
|
||||
const DEFAULT_FOLDER_ICON = 'ri-folder-line';
|
||||
|
||||
const normalizeHiddenKeys = (hiddenKeys = []) => {
|
||||
if (!Array.isArray(hiddenKeys)) {
|
||||
return [];
|
||||
}
|
||||
const seen = new Set();
|
||||
const normalized = [];
|
||||
hiddenKeys.forEach((key) => {
|
||||
if (!key || seen.has(key) || !navDefinitionMap.has(key)) {
|
||||
return;
|
||||
}
|
||||
seen.add(key);
|
||||
normalized.push(key);
|
||||
});
|
||||
return normalized;
|
||||
};
|
||||
|
||||
const VRCXUpdaterStore = useVRCXUpdaterStore();
|
||||
const { pendingVRCXUpdate, pendingVRCXInstall, appVersion } = storeToRefs(VRCXUpdaterStore);
|
||||
@@ -434,14 +449,7 @@
|
||||
if (entry.type === 'folder') {
|
||||
const folderDefinitions = (entry.items || []).map((key) => navDefinitionMap.get(key)).filter(Boolean);
|
||||
|
||||
if (folderDefinitions.length < 2) {
|
||||
folderDefinitions.forEach((definition) => {
|
||||
items.push({
|
||||
...definition,
|
||||
index: definition.key,
|
||||
titleIsCustom: false
|
||||
});
|
||||
});
|
||||
if (folderDefinitions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -518,10 +526,17 @@
|
||||
}
|
||||
);
|
||||
|
||||
const generateFolderId = () => `nav-folder-${dayjs().toISOString()}-${Math.random().toString().slice(2, 4)}`;
|
||||
const generateFolderId = () => {
|
||||
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
||||
return `nav-folder-${crypto.randomUUID()}`;
|
||||
}
|
||||
return `nav-folder-${dayjs().toISOString()}-${Math.random().toString().slice(2, 4)}`;
|
||||
};
|
||||
|
||||
const sanitizeLayout = (layout) => {
|
||||
const sanitizeLayout = (layout, hiddenKeys = []) => {
|
||||
const usedKeys = new Set();
|
||||
const normalizedHiddenKeys = normalizeHiddenKeys(hiddenKeys);
|
||||
const hiddenSet = new Set(normalizedHiddenKeys);
|
||||
const normalized = [];
|
||||
const chartsKeys = ['charts-instance', 'charts-mutual'];
|
||||
|
||||
@@ -572,7 +587,7 @@
|
||||
usedKeys.add(key);
|
||||
});
|
||||
|
||||
if (folderItems.length >= 2) {
|
||||
if (folderItems.length >= 1) {
|
||||
const folderNameKey = entry.nameKey || null;
|
||||
const folderName = folderNameKey ? t(folderNameKey) : entry.name || '';
|
||||
normalized.push({
|
||||
@@ -583,15 +598,13 @@
|
||||
icon: entry.icon || DEFAULT_FOLDER_ICON,
|
||||
items: folderItems
|
||||
});
|
||||
} else {
|
||||
folderItems.forEach((key) => appendItemEntry(key));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
navDefinitions.forEach((item) => {
|
||||
if (!usedKeys.has(item.key)) {
|
||||
if (!usedKeys.has(item.key) && !hiddenSet.has(item.key)) {
|
||||
if (chartsKeys.includes(item.key)) {
|
||||
return;
|
||||
}
|
||||
@@ -599,7 +612,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
if (!chartsKeys.some((key) => usedKeys.has(key))) {
|
||||
if (!chartsKeys.some((key) => usedKeys.has(key)) && !chartsKeys.some((key) => hiddenSet.has(key))) {
|
||||
appendChartsFolder();
|
||||
}
|
||||
|
||||
@@ -659,13 +672,17 @@
|
||||
};
|
||||
|
||||
const customNavDialogVisible = ref(false);
|
||||
const navHiddenKeys = ref([]);
|
||||
const defaultNavLayout = computed(() => sanitizeLayout(createDefaultNavLayout(), []));
|
||||
|
||||
const saveNavLayout = async (layout) => {
|
||||
const saveNavLayout = async (layout, hiddenKeys = []) => {
|
||||
const normalizedHiddenKeys = normalizeHiddenKeys(hiddenKeys);
|
||||
try {
|
||||
await configRepository.setString(
|
||||
'VRCX_customNavMenuLayoutList',
|
||||
JSON.stringify({
|
||||
layout
|
||||
layout,
|
||||
hiddenKeys: normalizedHiddenKeys
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -677,33 +694,18 @@
|
||||
customNavDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleCustomNavSave = async (layout) => {
|
||||
const sanitized = sanitizeLayout(layout);
|
||||
const handleCustomNavSave = async (layout, hiddenKeys = []) => {
|
||||
const normalizedHiddenKeys = normalizeHiddenKeys(hiddenKeys);
|
||||
const sanitized = sanitizeLayout(layout, normalizedHiddenKeys);
|
||||
navLayout.value = sanitized;
|
||||
await saveNavLayout(sanitized);
|
||||
navHiddenKeys.value = normalizedHiddenKeys;
|
||||
await saveNavLayout(sanitized, normalizedHiddenKeys);
|
||||
customNavDialogVisible.value = false;
|
||||
};
|
||||
|
||||
const handleCustomNavReset = () => {
|
||||
modalStore
|
||||
.confirm({
|
||||
description: t('nav_menu.custom_nav.restore_default_confirm'),
|
||||
title: t('confirm.title'),
|
||||
confirmText: t('nav_menu.custom_nav.restore_default'),
|
||||
cancelText: t('nav_menu.custom_nav.cancel')
|
||||
})
|
||||
.then(async ({ ok }) => {
|
||||
if (!ok) return;
|
||||
const defaults = sanitizeLayout(createDefaultNavLayout());
|
||||
navLayout.value = defaults;
|
||||
await saveNavLayout(defaults);
|
||||
customNavDialogVisible.value = false;
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const loadNavMenuConfig = async () => {
|
||||
let layoutData = null;
|
||||
let hiddenKeysData = [];
|
||||
try {
|
||||
const storedValue = await configRepository.getString('VRCX_customNavMenuLayoutList');
|
||||
if (storedValue) {
|
||||
@@ -712,16 +714,23 @@
|
||||
layoutData = parsed;
|
||||
} else if (Array.isArray(parsed?.layout)) {
|
||||
layoutData = parsed.layout;
|
||||
hiddenKeysData = Array.isArray(parsed.hiddenKeys) ? parsed.hiddenKeys : [];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom nav', error);
|
||||
} finally {
|
||||
const normalizedHiddenKeys = normalizeHiddenKeys(hiddenKeysData);
|
||||
const fallbackLayout = layoutData?.length ? layoutData : createDefaultNavLayout();
|
||||
const sanitized = sanitizeLayout(fallbackLayout);
|
||||
const sanitized = sanitizeLayout(fallbackLayout, normalizedHiddenKeys);
|
||||
navLayout.value = sanitized;
|
||||
if (layoutData?.length && JSON.stringify(sanitized) !== JSON.stringify(fallbackLayout)) {
|
||||
await saveNavLayout(sanitized);
|
||||
navHiddenKeys.value = normalizedHiddenKeys;
|
||||
if (
|
||||
layoutData?.length &&
|
||||
(JSON.stringify(sanitized) !== JSON.stringify(fallbackLayout) ||
|
||||
JSON.stringify(normalizedHiddenKeys) !== JSON.stringify(hiddenKeysData))
|
||||
) {
|
||||
await saveNavLayout(sanitized, normalizedHiddenKeys);
|
||||
}
|
||||
navLayoutReady.value = true;
|
||||
navigateToFirstNavEntry();
|
||||
|
||||
Reference in New Issue
Block a user