mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-30 04:03:48 +02:00
use reka splitter config api
This commit is contained in:
@@ -1,173 +1,43 @@
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { useAppearanceSettingsStore } from '../stores';
|
||||
|
||||
export function useMainLayoutResizable() {
|
||||
const asideMaxPx = 700;
|
||||
const mainMinPx = 320;
|
||||
|
||||
const appearanceStore = useAppearanceSettingsStore();
|
||||
const { setAsideWidth } = appearanceStore;
|
||||
const { asideWidth, isSideBarTabShow, isNavCollapsed } =
|
||||
storeToRefs(appearanceStore);
|
||||
const { isSideBarTabShow } = storeToRefs(appearanceStore);
|
||||
|
||||
const fallbackWidth =
|
||||
typeof window !== 'undefined' && window.innerWidth
|
||||
? window.innerWidth
|
||||
: 1200;
|
||||
const asideDefaultSize = 25;
|
||||
const mainDefaultSize = 75;
|
||||
const asideMinSize = 12;
|
||||
const asideMaxPx = 700;
|
||||
|
||||
const panelGroupRef = ref(null);
|
||||
const asidePanelRef = ref(null);
|
||||
const groupWidth = ref(fallbackWidth);
|
||||
let resizeObserver = null;
|
||||
|
||||
// size helpers: panelGroupRef, groupWidth, fallbackWidth
|
||||
const getGroupWidthRaw = () => {
|
||||
const element = panelGroupRef.value?.$el ?? panelGroupRef.value;
|
||||
const width = element?.getBoundingClientRect?.().width;
|
||||
return Number.isFinite(width) ? width : null;
|
||||
};
|
||||
|
||||
const getGroupWidth = () => {
|
||||
const width = getGroupWidthRaw();
|
||||
return Number.isFinite(width) && width > 0 ? width : fallbackWidth;
|
||||
};
|
||||
|
||||
const pxToPercent = (px, width, min = 1) => {
|
||||
const w = Number.isFinite(width) && width > 0 ? width : getGroupWidth();
|
||||
return Math.min(100, Math.max(min, (px / w) * 100));
|
||||
};
|
||||
|
||||
const percentToPx = (percent, groupWidth) => (percent / 100) * groupWidth;
|
||||
|
||||
const getMaxAsidePx = (width) =>
|
||||
Math.min(asideMaxPx, Math.max(0, width - mainMinPx));
|
||||
|
||||
const clampAsidePx = (px, width) =>
|
||||
Math.min(getMaxAsidePx(width), Math.max(0, px));
|
||||
|
||||
// layout state: isAsideCollapsed, asideMaxSize, asideDefaultSize, mainDefaultSize
|
||||
const isAsideCollapsed = (layout) =>
|
||||
Array.isArray(layout) &&
|
||||
layout.length >= 2 &&
|
||||
layout[layout.length - 1] <= 1;
|
||||
|
||||
const asideMaxSize = computed(() =>
|
||||
pxToPercent(getMaxAsidePx(groupWidth.value), groupWidth.value, 0)
|
||||
);
|
||||
|
||||
const asideDefaultSize = computed(() => {
|
||||
if (!isSideBarTabShow.value) {
|
||||
return 0;
|
||||
}
|
||||
const percent = pxToPercent(asideWidth.value, groupWidth.value, 0);
|
||||
return Math.min(asideMaxSize.value, percent);
|
||||
});
|
||||
|
||||
const mainDefaultSize = computed(
|
||||
() => 100 - (isSideBarTabShow.value ? asideDefaultSize.value : 0)
|
||||
);
|
||||
|
||||
// drag -> store: handleLayout, asideWidth
|
||||
const isAsideCollapsedState = ref(false);
|
||||
const handleLayout = (sizes) => {
|
||||
if (!Array.isArray(sizes) || sizes.length < 1) {
|
||||
if (!Array.isArray(sizes) || sizes.length < 2) {
|
||||
isAsideCollapsedState.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSideBarTabShow.value || sizes.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rawWidth = getGroupWidthRaw();
|
||||
if (!Number.isFinite(rawWidth) || rawWidth <= 0) {
|
||||
return;
|
||||
}
|
||||
const width = rawWidth;
|
||||
|
||||
const asideSize = sizes[sizes.length - 1];
|
||||
if (!Number.isFinite(asideSize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextAsidePx =
|
||||
asideSize <= 1
|
||||
? 0
|
||||
: clampAsidePx(
|
||||
Math.round(percentToPx(asideSize, width)),
|
||||
width
|
||||
);
|
||||
if (nextAsidePx === asideWidth.value) {
|
||||
return;
|
||||
}
|
||||
setAsideWidth(nextAsidePx);
|
||||
isAsideCollapsedState.value = isAsideCollapsed(sizes);
|
||||
};
|
||||
|
||||
// sync store -> panel: resizeAsidePanel, syncAsidePanelSize
|
||||
const resizeAsidePanel = (targetSize) =>
|
||||
asidePanelRef.value?.resize?.(targetSize);
|
||||
|
||||
const syncAsidePanelSize = (width) => {
|
||||
if (!isSideBarTabShow.value) {
|
||||
return;
|
||||
}
|
||||
const maxAsidePx = getMaxAsidePx(width);
|
||||
const clampedAsidePx = Math.min(
|
||||
maxAsidePx,
|
||||
Math.max(0, asideWidth.value)
|
||||
);
|
||||
if (maxAsidePx > 0 && clampedAsidePx !== asideWidth.value) {
|
||||
setAsideWidth(clampedAsidePx);
|
||||
}
|
||||
const asideTargetSize =
|
||||
maxAsidePx > 0 && clampedAsidePx > 0
|
||||
? pxToPercent(clampedAsidePx, width, 0)
|
||||
: 0;
|
||||
resizeAsidePanel(asideTargetSize);
|
||||
};
|
||||
|
||||
// window resize: updateGroupWidth, resizeObserver
|
||||
const updateGroupWidth = () => {
|
||||
const width = getGroupWidth();
|
||||
groupWidth.value = width;
|
||||
syncAsidePanelSize(width);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
updateGroupWidth();
|
||||
|
||||
const element = panelGroupRef.value?.$el ?? panelGroupRef.value;
|
||||
if (element && typeof ResizeObserver !== 'undefined') {
|
||||
resizeObserver = new ResizeObserver(updateGroupWidth);
|
||||
resizeObserver.observe(element);
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [isSideBarTabShow.value, asideWidth.value],
|
||||
() => {
|
||||
syncAsidePanelSize(groupWidth.value);
|
||||
}
|
||||
const isAsideCollapsedStatic = computed(
|
||||
() => !isSideBarTabShow.value || isAsideCollapsedState.value
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
resizeObserver = null;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
panelGroupRef,
|
||||
asidePanelRef,
|
||||
asideDefaultSize,
|
||||
asideMaxSize,
|
||||
asideMinSize,
|
||||
asideMaxPx,
|
||||
mainDefaultSize,
|
||||
handleLayout,
|
||||
isAsideCollapsed,
|
||||
isNavCollapsed,
|
||||
isAsideCollapsedStatic,
|
||||
isSideBarTabShow
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
'Sort by Time in Instance',
|
||||
'Sort by Last Active'
|
||||
]);
|
||||
const asideWidth = ref(300);
|
||||
const navWidth = ref(240);
|
||||
const isSidebarGroupByInstance = ref(true);
|
||||
const isHideFriendsInSameInstance = ref(false);
|
||||
@@ -145,7 +144,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
dtHour12Config,
|
||||
dtIsoFormatConfig,
|
||||
sidebarSortMethodsConfig,
|
||||
asideWidthConfig,
|
||||
navWidthConfig,
|
||||
isSidebarGroupByInstanceConfig,
|
||||
isHideFriendsInSameInstanceConfig,
|
||||
@@ -195,7 +193,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
'Sort by Last Active'
|
||||
])
|
||||
),
|
||||
configRepository.getInt('VRCX_sidePanelWidth', 300),
|
||||
configRepository.getInt('VRCX_navPanelWidth', 240),
|
||||
configRepository.getBool('VRCX_sidebarGroupByInstance', true),
|
||||
configRepository.getBool(
|
||||
@@ -288,7 +285,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
);
|
||||
}
|
||||
trustColor.value = { ...TRUST_COLOR_DEFAULTS };
|
||||
asideWidth.value = asideWidthConfig;
|
||||
navWidth.value = clampInt(navWidthConfig, 64, 480);
|
||||
isSidebarGroupByInstance.value = isSidebarGroupByInstanceConfig;
|
||||
isHideFriendsInSameInstance.value =
|
||||
@@ -680,22 +676,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
});
|
||||
}
|
||||
}
|
||||
function setAsideWidth(widthOrArray) {
|
||||
let width = null;
|
||||
if (Array.isArray(widthOrArray) && widthOrArray.length) {
|
||||
width = widthOrArray[widthOrArray.length - 1];
|
||||
} else if (typeof widthOrArray === 'number') {
|
||||
width = widthOrArray;
|
||||
}
|
||||
if (!Number.isFinite(width) || width === null) {
|
||||
return;
|
||||
}
|
||||
const normalized = Math.max(0, Math.round(width));
|
||||
requestAnimationFrame(() => {
|
||||
asideWidth.value = normalized;
|
||||
configRepository.setInt('VRCX_sidePanelWidth', normalized);
|
||||
});
|
||||
}
|
||||
function setIsSidebarGroupByInstance() {
|
||||
isSidebarGroupByInstance.value = !isSidebarGroupByInstance.value;
|
||||
configRepository.setBool(
|
||||
@@ -972,7 +952,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
sidebarSortMethod2,
|
||||
sidebarSortMethod3,
|
||||
sidebarSortMethods,
|
||||
asideWidth,
|
||||
navWidth,
|
||||
isSidebarGroupByInstance,
|
||||
isHideFriendsInSameInstance,
|
||||
@@ -1011,7 +990,6 @@ export const useAppearanceSettingsStore = defineStore(
|
||||
setSidebarSortMethod3,
|
||||
setSidebarSortMethods,
|
||||
setNavWidth,
|
||||
setAsideWidth,
|
||||
setIsSidebarGroupByInstance,
|
||||
setIsHideFriendsInSameInstance,
|
||||
setIsSidebarDivideByFriendGroup,
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
<SidebarInset class="min-w-0 bg-sidebar">
|
||||
<ResizablePanelGroup
|
||||
ref="panelGroupRef"
|
||||
direction="horizontal"
|
||||
auto-save-id="vrcx-main-layout-right-sidebar"
|
||||
:class="['group/main-layout flex-1 h-full min-w-0', { 'aside-collapsed': isAsideCollapsedStatic }]"
|
||||
@layout="handleLayout">
|
||||
<template #default="{ layout }">
|
||||
@@ -37,9 +37,8 @@
|
||||
'z-20 [&>div]:-translate-x-1/2'
|
||||
]"></ResizableHandle>
|
||||
<ResizablePanel
|
||||
ref="asidePanelRef"
|
||||
:default-size="asideDefaultSize"
|
||||
:max-size="asideMaxSize"
|
||||
:min-size="asideMinSize"
|
||||
:collapsed-size="0"
|
||||
collapsible
|
||||
:order="2"
|
||||
@@ -114,7 +113,7 @@
|
||||
const router = useRouter();
|
||||
|
||||
const appearanceSettingsStore = useAppearanceSettingsStore();
|
||||
const { navWidth, isNavCollapsed, asideWidth } = storeToRefs(appearanceSettingsStore);
|
||||
const { navWidth, isNavCollapsed } = storeToRefs(appearanceSettingsStore);
|
||||
|
||||
const sidebarOpen = computed(() => !isNavCollapsed.value);
|
||||
|
||||
@@ -163,18 +162,16 @@
|
||||
});
|
||||
|
||||
const {
|
||||
panelGroupRef,
|
||||
asideDefaultSize,
|
||||
asideMaxSize,
|
||||
asideMinSize,
|
||||
asideMaxPx,
|
||||
mainDefaultSize,
|
||||
handleLayout,
|
||||
isAsideCollapsed,
|
||||
isAsideCollapsedStatic,
|
||||
isSideBarTabShow
|
||||
} = useMainLayoutResizable();
|
||||
|
||||
const isAsideCollapsedStatic = computed(() => !isSideBarTabShow.value || asideWidth.value === 0);
|
||||
|
||||
watch(
|
||||
() => watchState.isLoggedIn,
|
||||
(isLoggedIn) => {
|
||||
|
||||
Reference in New Issue
Block a user