feat: add breadcrumb components and main dialog layout functionality

This commit is contained in:
pa
2026-01-20 17:30:23 +09:00
committed by Natsumi
parent 0b636df330
commit b2bd7693bb
21 changed files with 3768 additions and 3471 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
<script setup>
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator
} from '@/components/ui/breadcrumb';
import { useAvatarStore, useGroupStore, useUiStore, useUserStore, useWorldStore } from '@/stores';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { computed } from 'vue';
import AvatarDialog from './AvatarDialog/AvatarDialog.vue';
import GroupDialog from './GroupDialog/GroupDialog.vue';
import UserDialog from './UserDialog/UserDialog.vue';
import WorldDialog from './WorldDialog/WorldDialog.vue';
const avatarStore = useAvatarStore();
const groupStore = useGroupStore();
const uiStore = useUiStore();
const userStore = useUserStore();
const worldStore = useWorldStore();
const isOpen = computed({
get: () =>
userStore.userDialog.visible ||
worldStore.worldDialog.visible ||
avatarStore.avatarDialog.visible ||
groupStore.groupDialog.visible,
set: (value) => {
if (!value) {
userStore.userDialog.visible = false;
worldStore.worldDialog.visible = false;
avatarStore.avatarDialog.visible = false;
groupStore.groupDialog.visible = false;
uiStore.clearDialogCrumbs();
}
}
});
const dialogCrumbs = computed(() => uiStore.dialogCrumbs);
const activeCrumb = computed(() => dialogCrumbs.value[dialogCrumbs.value.length - 1] || null);
const activeType = computed(() => {
if (activeCrumb.value?.type) {
return activeCrumb.value.type;
}
if (userStore.userDialog.visible) {
return 'user';
}
if (worldStore.worldDialog.visible) {
return 'world';
}
if (avatarStore.avatarDialog.visible) {
return 'avatar';
}
if (groupStore.groupDialog.visible) {
return 'group';
}
return null;
});
const activeComponent = computed(() => {
switch (activeType.value) {
case 'user':
return UserDialog;
case 'world':
return WorldDialog;
case 'avatar':
return AvatarDialog;
case 'group':
return GroupDialog;
default:
return null;
}
});
const dialogClass = computed(() => {
switch (activeType.value) {
case 'world':
return 'x-dialog x-world-dialog translate-y-0 sm:max-w-235';
case 'avatar':
return 'x-dialog x-avatar-dialog sm:max-w-235 translate-y-0';
case 'group':
return 'x-dialog x-group-dialog group-body translate-y-0 sm:max-w-235';
case 'user':
default:
return 'x-dialog x-user-dialog sm:max-w-235 translate-y-0';
}
});
const shouldShowBreadcrumbs = computed(() => dialogCrumbs.value.length > 1);
const shouldCollapseBreadcrumbs = computed(() => dialogCrumbs.value.length > 4);
const middleBreadcrumbs = computed(() => {
if (!shouldCollapseBreadcrumbs.value) {
return [];
}
return dialogCrumbs.value.slice(1, -2);
});
const handleBreadcrumbClick = (index) => {
const item = dialogCrumbs.value[index];
if (!item) {
return;
}
uiStore.jumpDialogCrumb(index);
if (item.type === 'user') {
userStore.showUserDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'world') {
worldStore.showWorldDialog(item.id, null, { skipBreadcrumb: true });
return;
}
if (item.type === 'avatar') {
avatarStore.showAvatarDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'group') {
groupStore.showGroupDialog(item.id, { skipBreadcrumb: true });
}
};
</script>
<template>
<Dialog v-model:open="isOpen">
<DialogContent :class="dialogClass" style="top: 10vh" :show-close-button="false">
<Breadcrumb v-if="shouldShowBreadcrumbs" class="mb-2">
<BreadcrumbList>
<template v-if="shouldCollapseBreadcrumbs">
<BreadcrumbItem>
<BreadcrumbLink as-child>
<button
type="button"
class="max-w-40 truncate text-left"
@click="handleBreadcrumbClick(0)">
{{ dialogCrumbs[0]?.label || dialogCrumbs[0]?.id }}
</button>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger class="flex items-center gap-1">
<BreadcrumbEllipsis class="h-4 w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuItem
v-for="(crumb, index) in middleBreadcrumbs"
:key="`${crumb.type}-${crumb.id}`"
@click="handleBreadcrumbClick(index + 1)">
{{ crumb.label || crumb.id }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink as-child>
<button
type="button"
class="max-w-40 truncate text-left"
@click="handleBreadcrumbClick(dialogCrumbs.length - 2)">
{{
dialogCrumbs[dialogCrumbs.length - 2]?.label ||
dialogCrumbs[dialogCrumbs.length - 2]?.id
}}
</button>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage class="max-w-40 truncate">
{{
dialogCrumbs[dialogCrumbs.length - 1]?.label ||
dialogCrumbs[dialogCrumbs.length - 1]?.id
}}
</BreadcrumbPage>
</BreadcrumbItem>
</template>
<template v-else>
<template v-for="(crumb, index) in dialogCrumbs" :key="`${crumb.type}-${crumb.id}`">
<BreadcrumbItem>
<BreadcrumbLink v-if="index < dialogCrumbs.length - 1" as-child>
<button
type="button"
class="max-w-40 truncate text-left"
@click="handleBreadcrumbClick(index)">
{{ crumb.label || crumb.id }}
</button>
</BreadcrumbLink>
<BreadcrumbPage v-else class="max-w-40 truncate">
{{ crumb.label || crumb.id }}
</BreadcrumbPage>
</BreadcrumbItem>
<BreadcrumbSeparator v-if="index < dialogCrumbs.length - 1" />
</template>
</template>
</BreadcrumbList>
</Breadcrumb>
<component :is="activeComponent" v-if="activeComponent" />
</DialogContent>
</Dialog>
</template>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<script setup>
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<nav aria-label="breadcrumb" data-slot="breadcrumb" :class="props.class">
<slot />
</nav>
</template>

View File

@@ -0,0 +1,21 @@
<script setup>
import { MoreHorizontal } from 'lucide-vue-next';
import { cn } from '@/lib/utils';
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<span
data-slot="breadcrumb-ellipsis"
role="presentation"
aria-hidden="true"
:class="cn('flex size-9 items-center justify-center', props.class)">
<slot>
<MoreHorizontal class="size-4" />
</slot>
<span class="sr-only">More</span>
</span>
</template>

View File

@@ -0,0 +1,13 @@
<script setup>
import { cn } from '@/lib/utils';
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<li data-slot="breadcrumb-item" :class="cn('inline-flex items-center gap-1.5', props.class)">
<slot />
</li>
</template>

View File

@@ -0,0 +1,20 @@
<script setup>
import { Primitive } from 'reka-ui';
import { cn } from '@/lib/utils';
const props = defineProps({
asChild: { type: Boolean, required: false },
as: { type: null, required: false, default: 'a' },
class: { type: null, required: false }
});
</script>
<template>
<Primitive
data-slot="breadcrumb-link"
:as="as"
:as-child="asChild"
:class="cn('hover:text-foreground transition-colors', props.class)">
<slot />
</Primitive>
</template>

View File

@@ -0,0 +1,17 @@
<script setup>
import { cn } from '@/lib/utils';
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<ol
data-slot="breadcrumb-list"
:class="
cn('text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5', props.class)
">
<slot />
</ol>
</template>

View File

@@ -0,0 +1,18 @@
<script setup>
import { cn } from '@/lib/utils';
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<span
data-slot="breadcrumb-page"
role="link"
aria-disabled="true"
aria-current="page"
:class="cn('text-foreground font-normal', props.class)">
<slot />
</span>
</template>

View File

@@ -0,0 +1,20 @@
<script setup>
import { ChevronRight } from 'lucide-vue-next';
import { cn } from '@/lib/utils';
const props = defineProps({
class: { type: null, required: false }
});
</script>
<template>
<li
data-slot="breadcrumb-separator"
role="presentation"
aria-hidden="true"
:class="cn('[&>svg]:size-3.5', props.class)">
<slot>
<ChevronRight />
</slot>
</li>
</template>

View File

@@ -0,0 +1,7 @@
export { default as Breadcrumb } from './Breadcrumb.vue';
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue';
export { default as BreadcrumbItem } from './BreadcrumbItem.vue';
export { default as BreadcrumbLink } from './BreadcrumbLink.vue';
export { default as BreadcrumbList } from './BreadcrumbList.vue';
export { default as BreadcrumbPage } from './BreadcrumbPage.vue';
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue';

View File

@@ -5,12 +5,13 @@ import { useAppearanceSettingsStore } from '../stores';
import configRepository from '../service/config';
export function useAuthenticatedLayoutResizable() {
export function useMainLayoutResizable() {
const asideMaxPx = 500;
const appearanceStore = useAppearanceSettingsStore();
const { setAsideWidth } = appearanceStore;
const { asideWidth, isSideBarTabShow, isNavCollapsed } = storeToRefs(appearanceStore);
const { asideWidth, isSideBarTabShow, isNavCollapsed } =
storeToRefs(appearanceStore);
const fallbackWidth =
typeof window !== 'undefined' && window.innerWidth
@@ -63,7 +64,9 @@ export function useAuthenticatedLayoutResizable() {
const percentToPx = (percent, groupWidth) => (percent / 100) * groupWidth;
const isAsideCollapsed = (layout) =>
Array.isArray(layout) && layout.length >= 2 && layout[layout.length - 1] <= 1;
Array.isArray(layout) &&
layout.length >= 2 &&
layout[layout.length - 1] <= 1;
const asideDefaultSize = computed(() =>
pxToPercent(asideWidth.value, undefined, 0)
@@ -170,6 +173,7 @@ export function useAuthenticatedLayoutResizable() {
asidePanelRef,
asideDefaultSize,
asideMaxSize,
asideMaxPx,
mainDefaultSize,
handleLayout,
setIsDragging,

View File

@@ -2,7 +2,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
import { watchState } from './../service/watchState';
import AuthenticatedLayout from '../views/Layout/AuthenticatedLayout.vue';
import MainLayout from '../views/Layout/MainLayout.vue';
import Charts from './../views/Charts/Charts.vue';
import FavoritesAvatar from './../views/Favorites/FavoritesAvatar.vue';
import FavoritesFriend from './../views/Favorites/FavoritesFriend.vue';
@@ -31,7 +31,7 @@ const routes = [
},
{
path: '/',
component: AuthenticatedLayout,
component: MainLayout,
meta: { requiresAuth: true },
children: [
{ path: '', redirect: { name: 'feed' } },

View File

@@ -18,9 +18,12 @@ import { database } from '../service/database';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useAvatarProviderStore } from './avatarProvider';
import { useFavoriteStore } from './favorite';
import { useGroupStore } from './group';
import { useModalStore } from './modal';
import { useUiStore } from './ui';
import { useUserStore } from './user';
import { useVRCXUpdaterStore } from './vrcxUpdater';
import { useWorldStore } from './world';
import { watchState } from '../service/watchState';
import webApiService from '../service/webapi';
@@ -31,7 +34,10 @@ export const useAvatarStore = defineStore('Avatar', () => {
const vrcxUpdaterStore = useVRCXUpdaterStore();
const advancedSettingsStore = useAdvancedSettingsStore();
const userStore = useUserStore();
const worldStore = useWorldStore();
const groupStore = useGroupStore();
const modalStore = useModalStore();
const uiStore = useUiStore();
const { t } = useI18n();
let cachedAvatarModerations = new Map();
@@ -172,8 +178,22 @@ export const useAvatarStore = defineStore('Avatar', () => {
* @param {string} avatarId
* @returns
*/
function showAvatarDialog(avatarId) {
function showAvatarDialog(avatarId, options = {}) {
const D = avatarDialog.value;
if (
!avatarDialog.value.visible &&
!userStore.userDialog.visible &&
!worldStore.worldDialog.visible &&
!groupStore.groupDialog.visible
) {
uiStore.clearDialogCrumbs();
}
if (!options.skipBreadcrumb) {
uiStore.pushDialogCrumb('avatar', avatarId);
}
userStore.userDialog.visible = false;
worldStore.worldDialog.visible = false;
groupStore.groupDialog.visible = false;
D.visible = true;
D.loading = true;
D.id = avatarId;
@@ -201,6 +221,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
const ref2 = cachedAvatars.get(avatarId);
if (typeof ref2 !== 'undefined') {
D.ref = ref2;
uiStore.setDialogCrumbLabel('avatar', D.id, D.ref?.name || D.id);
updateVRChatAvatarCache();
if (
ref2.releaseStatus !== 'public' &&
@@ -215,6 +236,11 @@ export const useAvatarStore = defineStore('Avatar', () => {
.then((args) => {
const ref = applyAvatar(args.json);
D.ref = ref;
uiStore.setDialogCrumbLabel(
'avatar',
D.id,
D.ref?.name || D.id
);
getAvatarGallery(avatarId);
updateVRChatAvatarCache();
if (/quest/.test(ref.tags)) {

View File

@@ -16,11 +16,14 @@ import {
} from '../shared/utils';
import { database } from '../service/database.js';
import { groupDialogFilterOptions } from '../shared/constants/';
import { useAvatarStore } from './avatar';
import { useGameStore } from './game';
import { useInstanceStore } from './instance';
import { useModalStore } from './modal';
import { useNotificationStore } from './notification';
import { useUiStore } from './ui';
import { useUserStore } from './user';
import { useWorldStore } from './world';
import { watchState } from '../service/watchState';
import configRepository from '../service/config';
@@ -31,8 +34,11 @@ export const useGroupStore = defineStore('Group', () => {
const instanceStore = useInstanceStore();
const gameStore = useGameStore();
const userStore = useUserStore();
const worldStore = useWorldStore();
const avatarStore = useAvatarStore();
const notificationStore = useNotificationStore();
const modalStore = useModalStore();
const uiStore = useUiStore();
const { t } = useI18n();
let cachedGroups = new Map();
@@ -124,10 +130,24 @@ export const useGroupStore = defineStore('Group', () => {
{ flush: 'sync' }
);
function showGroupDialog(groupId) {
function showGroupDialog(groupId, options = {}) {
if (!groupId) {
return;
}
if (
!groupDialog.value.visible &&
!userStore.userDialog.visible &&
!worldStore.worldDialog.visible &&
!avatarStore.avatarDialog.visible
) {
uiStore.clearDialogCrumbs();
}
if (!options.skipBreadcrumb) {
uiStore.pushDialogCrumb('group', groupId);
}
userStore.userDialog.visible = false;
worldStore.worldDialog.visible = false;
avatarStore.avatarDialog.visible = false;
const D = groupDialog.value;
D.visible = true;
D.loading = true;
@@ -161,6 +181,11 @@ export const useGroupStore = defineStore('Group', () => {
if (groupId === args.ref.id) {
D.loading = false;
D.ref = args.ref;
uiStore.setDialogCrumbLabel(
'group',
D.id,
D.ref?.name || D.id
);
D.inGroup = args.ref.membershipStatus === 'member';
D.ownerDisplayName = args.ref.ownerId;
userRequest

View File

@@ -27,6 +27,7 @@ export const useUiStore = defineStore('Ui', () => {
const notifiedMenus = ref([]);
const shiftHeld = ref(false);
const trayIconNotify = ref(false);
const dialogCrumbs = ref([]);
watch(ctrlR, (isPressed) => {
if (isPressed) {
@@ -58,6 +59,54 @@ export const useUiStore = defineStore('Ui', () => {
}
});
function pushDialogCrumb(type, id, label = '') {
if (!type || !id) {
return;
}
const items = dialogCrumbs.value;
const last = items[items.length - 1];
if (last && last.type === type && last.id === id) {
if (label && last.label !== label) {
last.label = label;
}
return;
}
const existingIndex = items.findIndex(
(item) => item.type === type && item.id === id
);
if (existingIndex !== -1) {
items.splice(existingIndex + 1);
if (label) {
items[existingIndex].label = label;
}
return;
}
items.push({ type, id, label: label || id });
}
function setDialogCrumbLabel(type, id, label) {
if (!type || !id || !label) {
return;
}
const item = dialogCrumbs.value.find(
(entry) => entry.type === type && entry.id === id
);
if (item) {
item.label = label;
}
}
function jumpDialogCrumb(index) {
if (index < 0 || index >= dialogCrumbs.value.length) {
return;
}
dialogCrumbs.value.splice(index + 1);
}
function clearDialogCrumbs() {
dialogCrumbs.value = [];
}
// Make sure file drops outside of the screenshot manager don't navigate to the file path dropped.
// This issue persists on prompts created with prompt(), unfortunately. Not sure how to fix that.
document.body.addEventListener('drop', function (e) {
@@ -133,10 +182,15 @@ export const useUiStore = defineStore('Ui', () => {
return {
notifiedMenus,
shiftHeld,
dialogCrumbs,
notifyMenu,
removeNotify,
showConsole,
updateTrayIconNotify
updateTrayIconNotify,
pushDialogCrumb,
setDialogCrumbLabel,
jumpDialogCrumb,
clearDialogCrumbs
};
});

View File

@@ -48,6 +48,7 @@ import { useNotificationStore } from './notification';
import { usePhotonStore } from './photon';
import { useSearchStore } from './search';
import { useSharedFeedStore } from './sharedFeed';
import { useUiStore } from './ui';
import { useWorldStore } from './world';
import { watchState } from '../service/watchState';
@@ -68,6 +69,7 @@ export const useUserStore = defineStore('User', () => {
const groupStore = useGroupStore();
const feedStore = useFeedStore();
const worldStore = useWorldStore();
const uiStore = useUiStore();
const moderationStore = useModerationStore();
const photonStore = usePhotonStore();
const sharedFeedStore = useSharedFeedStore();
@@ -310,6 +312,7 @@ export const useUserStore = defineStore('User', () => {
customUserTags.clear();
state.notes.clear();
subsetOfLanguages.value = [];
uiStore.clearDialogCrumbs();
}
},
{ flush: 'sync' }
@@ -755,7 +758,7 @@ export const useUserStore = defineStore('User', () => {
*
* @param {string} userId
*/
function showUserDialog(userId) {
function showUserDialog(userId, options = {}) {
if (
!userId ||
typeof userId !== 'string' ||
@@ -763,6 +766,20 @@ export const useUserStore = defineStore('User', () => {
) {
return;
}
if (
!userDialog.value.visible &&
!worldStore.worldDialog.visible &&
!avatarStore.avatarDialog.visible &&
!groupStore.groupDialog.visible
) {
uiStore.clearDialogCrumbs();
}
if (!options.skipBreadcrumb) {
uiStore.pushDialogCrumb('user', userId);
}
worldStore.worldDialog.visible = false;
avatarStore.avatarDialog.visible = false;
groupStore.groupDialog.visible = false;
const D = userDialog.value;
D.id = userId;
D.treeData = {};
@@ -846,6 +863,11 @@ export const useUserStore = defineStore('User', () => {
if (args.ref.id === D.id) {
requestAnimationFrame(() => {
D.ref = args.ref;
uiStore.setDialogCrumbLabel(
'user',
D.id,
D.ref?.displayName || D.id
);
D.friend = friendStore.friends.get(D.id);
D.isFriend = Boolean(D.friend);
D.note = String(D.ref.note || '');

View File

@@ -14,9 +14,12 @@ import {
} from '../shared/utils';
import { instanceRequest, miscRequest, worldRequest } from '../api';
import { database } from '../service/database';
import { useAvatarStore } from './avatar';
import { useFavoriteStore } from './favorite';
import { useGroupStore } from './group';
import { useInstanceStore } from './instance';
import { useLocationStore } from './location';
import { useUiStore } from './ui';
import { useUserStore } from './user';
import { watchState } from '../service/watchState';
@@ -25,6 +28,9 @@ export const useWorldStore = defineStore('World', () => {
const favoriteStore = useFavoriteStore();
const instanceStore = useInstanceStore();
const userStore = useUserStore();
const avatarStore = useAvatarStore();
const groupStore = useGroupStore();
const uiStore = useUiStore();
const { t } = useI18n();
const worldDialog = reactive({
@@ -71,12 +77,26 @@ export const useWorldStore = defineStore('World', () => {
* @param {string} tag
* @param {string} shortName
*/
function showWorldDialog(tag, shortName = null) {
function showWorldDialog(tag, shortName = null, options = {}) {
const D = worldDialog;
const L = parseLocation(tag);
if (L.worldId === '') {
return;
}
if (
!worldDialog.visible &&
!userStore.userDialog.visible &&
!avatarStore.avatarDialog.visible &&
!groupStore.groupDialog.visible
) {
uiStore.clearDialogCrumbs();
}
if (!options.skipBreadcrumb) {
uiStore.pushDialogCrumb('world', L.worldId);
}
userStore.userDialog.visible = false;
avatarStore.avatarDialog.visible = false;
groupStore.groupDialog.visible = false;
L.shortName = shortName;
D.id = L.worldId;
D.$location = L;
@@ -141,6 +161,11 @@ export const useWorldStore = defineStore('World', () => {
if (D.id === args.ref.id) {
D.loading = false;
D.ref = args.ref;
uiStore.setDialogCrumbLabel(
'world',
D.id,
D.ref?.name || D.id
);
D.isFavorite = favoriteStore.getCachedFavoritesByObjectId(
D.id
);

View File

@@ -18,10 +18,7 @@
<ResizablePanelGroup
ref="panelGroupRef"
direction="horizontal"
:class="[
'group/main-layout flex-1 h-full min-w-0',
{ 'aside-collapsed': isAsideCollapsedStatic }
]"
:class="['group/main-layout flex-1 h-full min-w-0', { 'aside-collapsed': isAsideCollapsedStatic }]"
@layout="handleLayout">
<template #default="{ layout }">
<ResizablePanel :default-size="mainDefaultSize" :order="1">
@@ -46,7 +43,8 @@
:max-size="asideMaxSize"
:collapsed-size="0"
collapsible
:order="2">
:order="2"
:style="{ maxWidth: `${asideMaxPx}px` }">
<Sidebar></Sidebar>
</ResizablePanel>
</template>
@@ -56,13 +54,7 @@
</SidebarProvider>
<!-- ## Dialogs ## -->
<UserDialog></UserDialog>
<WorldDialog></WorldDialog>
<AvatarDialog></AvatarDialog>
<GroupDialog></GroupDialog>
<MainDialogContainer></MainDialogContainer>
<GroupMemberModerationDialog></GroupMemberModerationDialog>
@@ -102,16 +94,15 @@
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '../../components/ui/resizable';
import { SidebarInset, SidebarProvider } from '../../components/ui/sidebar';
import { useAppearanceSettingsStore } from '../../stores';
import { useAuthenticatedLayoutResizable } from '../../composables/useAuthenticatedLayoutResizable';
import { useMainLayoutResizable } from '../../composables/useMainLayoutResizable';
import { watchState } from '../../service/watchState';
import AvatarDialog from '../../components/dialogs/AvatarDialog/AvatarDialog.vue';
import AvatarImportDialog from '../Favorites/dialogs/AvatarImportDialog.vue';
import ChangelogDialog from '../Settings/dialogs/ChangelogDialog.vue';
import ChooseFavoriteGroupDialog from '../../components/dialogs/ChooseFavoriteGroupDialog.vue';
import MainDialogContainer from '../../components/dialogs/MainDialogContainer.vue';
import FriendImportDialog from '../Favorites/dialogs/FriendImportDialog.vue';
import FullscreenImagePreview from '../../components/FullscreenImagePreview.vue';
import GroupDialog from '../../components/dialogs/GroupDialog/GroupDialog.vue';
import GroupMemberModerationDialog from '../../components/dialogs/GroupDialog/GroupMemberModerationDialog.vue';
import InviteGroupDialog from '../../components/dialogs/InviteGroupDialog.vue';
import LaunchDialog from '../../components/dialogs/LaunchDialog.vue';
@@ -121,9 +112,7 @@
import PrimaryPasswordDialog from '../Settings/dialogs/PrimaryPasswordDialog.vue';
import SendBoopDialog from '../../components/dialogs/SendBoopDialog.vue';
import Sidebar from '../Sidebar/Sidebar.vue';
import UserDialog from '../../components/dialogs/UserDialog/UserDialog.vue';
import VRChatConfigDialog from '../Settings/dialogs/VRChatConfigDialog.vue';
import WorldDialog from '../../components/dialogs/WorldDialog/WorldDialog.vue';
import WorldImportDialog from '../Favorites/dialogs/WorldImportDialog.vue';
const router = useRouter();
@@ -180,16 +169,15 @@
const {
asideDefaultSize,
asideMaxSize,
asideMaxPx,
mainDefaultSize,
handleLayout,
setIsDragging,
isAsideCollapsed,
isSideBarTabShow
} = useAuthenticatedLayoutResizable();
} = useMainLayoutResizable();
const isAsideCollapsedStatic = computed(
() => !isSideBarTabShow.value || asideWidth.value === 0
);
const isAsideCollapsedStatic = computed(() => !isSideBarTabShow.value || asideWidth.value === 0);
watch(
() => watchState.isLoggedIn,