change previous instance dialog navigation to use main dialog container

This commit is contained in:
pa
2026-01-21 23:07:17 +09:00
committed by Natsumi
parent 91deb37c62
commit 60b49c71e1
10 changed files with 462 additions and 252 deletions

View File

@@ -1109,7 +1109,6 @@
</TabsUnderline>
</div>
<GroupPostEditDialog :dialog-data="groupPostEditDialog" :selected-gallery-file="selectedGalleryFile" />
<PreviousInstancesGroupDialog v-model:previous-instances-group-dialog="previousInstancesGroupDialog" />
</div>
</template>
@@ -1137,7 +1136,7 @@
XCircle
} from 'lucide-vue-next';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { computed, nextTick, reactive, ref, watch } from 'vue';
import { computed, reactive, ref, watch } from 'vue';
import { DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
@@ -1171,6 +1170,7 @@
useAppearanceSettingsStore,
useGalleryStore,
useGroupStore,
useInstanceStore,
useLocationStore,
useModalStore,
useUserStore
@@ -1190,8 +1190,6 @@
import GroupCalendarEventCard from '../../../views/Tools/components/GroupCalendarEventCard.vue';
import GroupPostEditDialog from './GroupPostEditDialog.vue';
import InstanceActionBar from '../../InstanceActionBar.vue';
import PreviousInstancesGroupDialog from '../PreviousInstancesDialog/PreviousInstancesGroupDialog.vue';
import * as workerTimers from 'worker-timers';
const { t } = useI18n();
@@ -1210,6 +1208,7 @@
);
const modalStore = useModalStore();
const instanceStore = useInstanceStore();
const { showUserDialog } = useUserStore();
const { currentUser } = storeToRefs(useUserStore());
@@ -1326,12 +1325,6 @@
groupId: ''
});
const previousInstancesGroupDialog = ref({
visible: false,
openFlg: false,
groupRef: {}
});
let loadMoreGroupMembersParams = ref({
n: 100,
offset: 0,
@@ -1382,11 +1375,7 @@
}
function showPreviousInstancesGroupDialog(groupRef) {
const D = previousInstancesGroupDialog.value;
D.groupRef = groupRef;
D.visible = true;
D.openFlg = true;
nextTick(() => (D.openFlg = false));
instanceStore.showPreviousInstancesGroupDialog(groupRef);
}
function setGroupRepresentation(groupId) {

View File

@@ -8,7 +8,7 @@
BreadcrumbPage,
BreadcrumbSeparator
} from '@/components/ui/breadcrumb';
import { useAvatarStore, useGroupStore, useUiStore, useUserStore, useWorldStore } from '@/stores';
import { useAvatarStore, useGroupStore, useInstanceStore, useUiStore, useUserStore, useWorldStore } from '@/stores';
import {
DropdownMenu,
DropdownMenuContent,
@@ -17,30 +17,48 @@
} from '@/components/ui/dropdown-menu';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { computed } from 'vue';
import { storeToRefs } from 'pinia';
import AvatarDialog from './AvatarDialog/AvatarDialog.vue';
import GroupDialog from './GroupDialog/GroupDialog.vue';
import UserDialog from './UserDialog/UserDialog.vue';
import WorldDialog from './WorldDialog/WorldDialog.vue';
import PreviousInstancesGroupDialog from './PreviousInstancesDialog/PreviousInstancesGroupDialog.vue';
import PreviousInstancesInfoDialog from './PreviousInstancesDialog/PreviousInstancesInfoDialog.vue';
import PreviousInstancesUserDialog from './UserDialog/PreviousInstancesUserDialog.vue';
import PreviousInstancesWorldDialog from './PreviousInstancesDialog/PreviousInstancesWorldDialog.vue';
const avatarStore = useAvatarStore();
const groupStore = useGroupStore();
const instanceStore = useInstanceStore();
const uiStore = useUiStore();
const userStore = useUserStore();
const worldStore = useWorldStore();
const {
previousInstancesInfoDialogVisible,
previousInstancesUserDialog,
previousInstancesWorldDialog,
previousInstancesGroupDialog
} = storeToRefs(instanceStore);
const isOpen = computed({
get: () =>
userStore.userDialog.visible ||
worldStore.worldDialog.visible ||
avatarStore.avatarDialog.visible ||
groupStore.groupDialog.visible,
groupStore.groupDialog.visible ||
previousInstancesInfoDialogVisible.value ||
previousInstancesUserDialog.value.visible ||
previousInstancesWorldDialog.value.visible ||
previousInstancesGroupDialog.value.visible,
set: (value) => {
if (!value) {
userStore.userDialog.visible = false;
worldStore.worldDialog.visible = false;
avatarStore.avatarDialog.visible = false;
groupStore.groupDialog.visible = false;
instanceStore.hidePreviousInstancesDialogs();
uiStore.clearDialogCrumbs();
}
}
@@ -64,6 +82,18 @@
if (groupStore.groupDialog.visible) {
return 'group';
}
if (previousInstancesInfoDialogVisible.value) {
return 'previous-instances-info';
}
if (previousInstancesUserDialog.value.visible) {
return 'previous-instances-user';
}
if (previousInstancesWorldDialog.value.visible) {
return 'previous-instances-world';
}
if (previousInstancesGroupDialog.value.visible) {
return 'previous-instances-group';
}
return null;
});
const activeComponent = computed(() => {
@@ -76,6 +106,14 @@
return AvatarDialog;
case 'group':
return GroupDialog;
case 'previous-instances-info':
return PreviousInstancesInfoDialog;
case 'previous-instances-user':
return PreviousInstancesUserDialog;
case 'previous-instances-world':
return PreviousInstancesWorldDialog;
case 'previous-instances-group':
return PreviousInstancesGroupDialog;
default:
return null;
}
@@ -88,6 +126,11 @@
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 'previous-instances-info':
case 'previous-instances-user':
case 'previous-instances-world':
case 'previous-instances-group':
return 'x-dialog translate-y-0 sm:max-w-250';
case 'user':
default:
return 'x-dialog x-user-dialog sm:max-w-235 translate-y-0';
@@ -95,7 +138,7 @@
});
const shouldShowBreadcrumbs = computed(() => dialogCrumbs.value.length > 1);
const shouldCollapseBreadcrumbs = computed(() => dialogCrumbs.value.length > 4);
const shouldCollapseBreadcrumbs = computed(() => dialogCrumbs.value.length > 5);
const middleBreadcrumbs = computed(() => {
if (!shouldCollapseBreadcrumbs.value) {
return [];
@@ -110,19 +153,39 @@
}
uiStore.jumpDialogCrumb(index);
if (item.type === 'user') {
instanceStore.hidePreviousInstancesDialogs();
userStore.showUserDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'world') {
instanceStore.hidePreviousInstancesDialogs();
worldStore.showWorldDialog(item.id, null, { skipBreadcrumb: true });
return;
}
if (item.type === 'avatar') {
instanceStore.hidePreviousInstancesDialogs();
avatarStore.showAvatarDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'group') {
instanceStore.hidePreviousInstancesDialogs();
groupStore.showGroupDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'previous-instances-user') {
instanceStore.showPreviousInstancesUserDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'previous-instances-world') {
instanceStore.showPreviousInstancesWorldDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'previous-instances-group') {
instanceStore.showPreviousInstancesGroupDialog(item.id, { skipBreadcrumb: true });
return;
}
if (item.type === 'previous-instances-info') {
instanceStore.showPreviousInstancesInfoDialog(item.id, { skipBreadcrumb: true });
}
};
</script>

View File

@@ -1,35 +1,33 @@
<template>
<Dialog v-model:open="isVisible">
<DialogContent class="sm:max-w-250">
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<div>
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesGroupDialog.groupRef.name"></span>
<InputGroupField
class="w-1/3"
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable />
</div>
</template>
</DataTableLayout>
</DialogContent>
</Dialog>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesGroupDialog.groupRef.name"></span>
<InputGroupField
class="w-1/3"
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable />
</div>
</template>
</DataTableLayout>
</div>
</template>
<script setup>
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { computed, ref, watch } from 'vue';
import { InputGroupField } from '@/components/ui/input-group';
import { storeToRefs } from 'pinia';
@@ -48,7 +46,9 @@
import { database } from '../../../service/database';
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
const { showPreviousInstancesInfoDialog } = useInstanceStore();
const instanceStore = useInstanceStore();
const { showPreviousInstancesInfoDialog } = instanceStore;
const { previousInstancesGroupDialog } = storeToRefs(instanceStore);
const { shiftHeld } = useUiStore();
const { stringComparer } = storeToRefs(useSearchStore());
const { t } = useI18n();
@@ -64,21 +64,6 @@
const pageSize = ref(10);
const tableStyle = { maxHeight: '400px' };
const props = defineProps({
previousInstancesGroupDialog: { type: Object, required: true }
});
const emit = defineEmits(['update:previousInstancesGroupDialog']);
const isVisible = computed({
get: () => props.previousInstancesGroupDialog.visible,
set: (value) => {
emit('update:previousInstancesGroupDialog', {
...props.previousInstancesGroupDialog,
visible: value
});
}
});
const displayRows = computed(() => {
const q = String(search.value ?? '')
.trim()
@@ -137,9 +122,19 @@
};
watch(
() => props.previousInstancesGroupDialog.openFlg,
() => previousInstancesGroupDialog.value.visible,
(visible) => {
if (visible) {
refreshPreviousInstancesGroupTable();
}
},
{ immediate: true }
);
watch(
() => previousInstancesGroupDialog.value.openFlg,
() => {
if (props.previousInstancesGroupDialog.visible) {
if (previousInstancesGroupDialog.value.visible) {
refreshPreviousInstancesGroupTable();
}
}
@@ -147,7 +142,7 @@
function refreshPreviousInstancesGroupTable() {
loading.value = true;
const D = props.previousInstancesGroupDialog;
const D = previousInstancesGroupDialog.value;
database.getPreviousInstancesByGroupId(D.groupRef.id).then((data) => {
const array = [];
for (const ref of data.values()) {

View File

@@ -1,41 +1,33 @@
<template>
<Dialog
:open="previousInstancesInfoDialogVisible"
@update:open="
(open) => {
if (!open) closeDialog();
}
">
<DialogContent class="sm:max-w-200">
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.info') }}</DialogTitle>
</DialogHeader>
<div>
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.info') }}</DialogTitle>
</DialogHeader>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<Location :location="location.tag" style="font-size: 14px" />
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
style="width: 150px"
clearable />
</div>
</template>
</DataTableLayout>
</DialogContent>
</Dialog>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<Location :location="location.tag" style="font-size: 14px" />
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
style="width: 150px"
clearable />
</div>
</template>
</DataTableLayout>
</div>
</template>
<script setup>
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { computed, nextTick, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
@@ -146,7 +138,8 @@
refreshPreviousInstancesInfoTable();
});
}
}
},
{ immediate: true }
);
function init() {
@@ -169,7 +162,4 @@
});
}
function closeDialog() {
previousInstancesInfoDialogVisible.value = false;
}
</script>

View File

@@ -1,36 +1,34 @@
<template>
<Dialog v-model:open="isVisible">
<DialogContent class="sm:max-w-250">
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<div>
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesWorldDialog.worldRef.name"></span>
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable
class="w-1/3"
style="display: block" />
</div>
</template>
</DataTableLayout>
</DialogContent>
</Dialog>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesWorldDialog.worldRef.name"></span>
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable
class="w-1/3"
style="display: block" />
</div>
</template>
</DataTableLayout>
</div>
</template>
<script setup>
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { computed, ref, watch } from 'vue';
import { InputGroupField } from '@/components/ui/input-group';
import { storeToRefs } from 'pinia';
@@ -60,15 +58,9 @@
const modalStore = useModalStore();
const props = defineProps({
previousInstancesWorldDialog: {
type: Object,
required: true
}
});
const emit = defineEmits(['update:previous-instances-world-dialog']);
const { showPreviousInstancesInfoDialog } = useInstanceStore();
const instanceStore = useInstanceStore();
const { showPreviousInstancesInfoDialog } = instanceStore;
const { previousInstancesWorldDialog } = storeToRefs(instanceStore);
const { shiftHeld } = storeToRefs(useUiStore());
const { currentUser } = storeToRefs(useUserStore());
const { stringComparer } = storeToRefs(useSearchStore());
@@ -81,16 +73,6 @@
const tableStyle = { maxHeight: '400px' };
const loading = ref(false);
const isVisible = computed({
get: () => props.previousInstancesWorldDialog.visible,
set: (value) => {
emit('update:previous-instances-world-dialog', {
...props.previousInstancesWorldDialog,
visible: value
});
}
});
const displayRows = computed(() => {
const q = String(search.value ?? '')
.trim()
@@ -110,7 +92,7 @@
createColumns({
shiftHeld,
currentUserId: currentUser.value?.id,
forceUpdateKey: props.previousInstancesWorldDialog?.forceUpdate,
forceUpdateKey: previousInstancesWorldDialog.value?.forceUpdate,
onShowInfo: showPreviousInstancesInfoDialog,
onDelete: deleteGameLogWorldInstance,
onDeletePrompt: deleteGameLogWorldInstancePrompt
@@ -152,7 +134,7 @@
function refreshPreviousInstancesWorldTable() {
loading.value = true;
const D = props.previousInstancesWorldDialog;
const D = previousInstancesWorldDialog.value;
database.getPreviousInstancesByWorldId(D.worldRef).then((data) => {
const array = [];
for (const ref of data.values()) {
@@ -185,9 +167,19 @@
}
watch(
() => props.previousInstancesWorldDialog.openFlg,
() => previousInstancesWorldDialog.value.visible,
(visible) => {
if (visible) {
refreshPreviousInstancesWorldTable();
}
},
{ immediate: true }
);
watch(
() => previousInstancesWorldDialog.value.openFlg,
() => {
if (props.previousInstancesWorldDialog.visible) {
if (previousInstancesWorldDialog.value.visible) {
refreshPreviousInstancesWorldTable();
}
}

View File

@@ -1,36 +1,34 @@
<template>
<Dialog v-model:open="isVisible">
<DialogContent class="sm:max-w-250">
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<div>
<DialogHeader>
<DialogTitle>{{ t('dialog.previous_instances.header') }}</DialogTitle>
</DialogHeader>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesUserDialog.userRef.displayName"></span>
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable
class="w-1/3"
style="display: block" />
</div>
</template>
</DataTableLayout>
</DialogContent>
</Dialog>
<DataTableLayout
class="min-w-0 w-full"
:table="table"
:loading="loading"
:table-style="tableStyle"
:page-sizes="pageSizes"
:total-items="totalItems"
:on-page-size-change="handlePageSizeChange">
<template #toolbar>
<div style="display: flex; align-items: center; justify-content: space-between">
<span style="font-size: 14px" v-text="previousInstancesUserDialog.userRef.displayName"></span>
<InputGroupField
v-model="search"
:placeholder="t('dialog.previous_instances.search_placeholder')"
clearable
class="w-1/3"
style="display: block" />
</div>
</template>
</DataTableLayout>
</div>
</template>
<script setup>
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { computed, ref, watch } from 'vue';
import { InputGroupField } from '@/components/ui/input-group';
import { storeToRefs } from 'pinia';
@@ -56,25 +54,6 @@
import { database } from '../../../service/database';
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
const props = defineProps({
previousInstancesUserDialog: {
type: Object,
default: () => ({
visible: false,
userRef: {},
loading: false,
forceUpdate: 0,
previousInstances: [],
previousInstancesTable: {
data: [],
filters: [{ prop: 'displayName', value: '' }]
}
})
}
});
const emit = defineEmits(['update:previous-instances-user-dialog']);
const modalStore = useModalStore();
const loading = ref(false);
const rawRows = ref([]);
@@ -84,22 +63,14 @@
const tableStyle = { maxHeight: '400px' };
const { showLaunchDialog } = useLaunchStore();
const { showPreviousInstancesInfoDialog } = useInstanceStore();
const instanceStore = useInstanceStore();
const { showPreviousInstancesInfoDialog } = instanceStore;
const { previousInstancesUserDialog } = storeToRefs(instanceStore);
const { shiftHeld } = storeToRefs(useUiStore());
const { stringComparer } = storeToRefs(useSearchStore());
const vrcxStore = useVrcxStore();
const { t } = useI18n();
const isVisible = computed({
get: () => props.previousInstancesUserDialog.visible,
set: (value) => {
emit('update:previous-instances-user-dialog', {
...props.previousInstancesUserDialog,
visible: value
});
}
});
const displayRows = computed(() => {
const q = String(search.value ?? '')
.trim()
@@ -160,7 +131,7 @@
const refreshPreviousInstancesUserTable = async () => {
loading.value = true;
const data = await database.getPreviousInstancesByUserId(props.previousInstancesUserDialog.userRef);
const data = await database.getPreviousInstancesByUserId(previousInstancesUserDialog.value.userRef);
const array = [];
for (const item of data.values()) {
item.$location = parseLocation(item.location);
@@ -173,9 +144,19 @@
};
watch(
() => props.previousInstancesUserDialog.openFlg,
() => previousInstancesUserDialog.value.visible,
(visible) => {
if (visible) {
refreshPreviousInstancesUserTable();
}
},
{ immediate: true }
);
watch(
() => previousInstancesUserDialog.value.openFlg,
() => {
if (props.previousInstancesUserDialog.visible) {
if (previousInstancesUserDialog.value.visible) {
refreshPreviousInstancesUserTable();
}
}
@@ -183,8 +164,8 @@
function deleteGameLogUserInstance(row) {
database.deleteGameLogInstance({
id: props.previousInstancesUserDialog.userRef.id,
displayName: props.previousInstancesUserDialog.userRef.displayName,
id: previousInstancesUserDialog.value.userRef.id,
displayName: previousInstancesUserDialog.value.userRef.displayName,
location: row.location,
events: row.events
});

View File

@@ -1176,7 +1176,6 @@
v-model:sendInviteRequestDialogVisible="sendInviteRequestDialogVisible"
v-model:sendInviteDialog="sendInviteDialog"
@closeInviteDialog="closeInviteDialog" />
<PreviousInstancesUserDialog v-model:previous-instances-user-dialog="previousInstancesUserDialog" />
<SocialStatusDialog
:social-status-dialog="socialStatusDialog"
:social-status-history-table="socialStatusHistoryTable" />
@@ -1256,6 +1255,7 @@
useFriendStore,
useGalleryStore,
useGroupStore,
useInstanceStore,
useInviteStore,
useLocationStore,
useModalStore,
@@ -1285,7 +1285,6 @@
const BioDialog = defineAsyncComponent(() => import('./BioDialog.vue'));
const LanguageDialog = defineAsyncComponent(() => import('./LanguageDialog.vue'));
const PreviousInstancesUserDialog = defineAsyncComponent(() => import('./PreviousInstancesUserDialog.vue'));
const PronounsDialog = defineAsyncComponent(() => import('./PronounsDialog.vue'));
const SendInviteRequestDialog = defineAsyncComponent(() => import('./SendInviteRequestDialog.vue'));
const SocialStatusDialog = defineAsyncComponent(() => import('./SocialStatusDialog.vue'));
@@ -1315,6 +1314,7 @@
);
const modalStore = useModalStore();
const instanceStore = useInstanceStore();
const { hideUserNotes, hideUserMemos, isDarkMode } = storeToRefs(useAppearanceSettingsStore());
const { bioLanguage, avatarRemoteDatabase, translationApi, translationApiType } =
@@ -1402,12 +1402,6 @@
});
const sendInviteRequestDialogVisible = ref(false);
const previousInstancesUserDialog = ref({
visible: false,
openFlg: false,
userRef: {}
});
const socialStatusDialog = ref({
visible: false,
loading: false,
@@ -2314,12 +2308,7 @@
}
function showPreviousInstancesUserDialog(userRef) {
const D = previousInstancesUserDialog.value;
D.userRef = userRef;
D.visible = true;
// trigger watcher
D.openFlg = true;
nextTick(() => (D.openFlg = false));
instanceStore.showPreviousInstancesUserDialog(userRef);
}
function toggleAvatarCopying() {

View File

@@ -683,7 +683,6 @@
:old-tags="worldDialog.ref?.tags"
:world-id="worldDialog.id"
:is-world-dialog-visible="worldDialog.visible" />
<PreviousInstancesWorldDialog v-model:previous-instances-world-dialog="previousInstancesWorldDialog" />
<NewInstanceDialog
:new-instance-dialog-location-tag="newInstanceDialogLocationTag"
:last-location="lastLocation" />
@@ -773,9 +772,6 @@
const modalStore = useModalStore();
const NewInstanceDialog = defineAsyncComponent(() => import('../NewInstanceDialog.vue'));
const PreviousInstancesWorldDialog = defineAsyncComponent(
() => import('../PreviousInstancesDialog/PreviousInstancesWorldDialog.vue')
);
const ChangeWorldImageDialog = defineAsyncComponent(() => import('./ChangeWorldImageDialog.vue'));
const SetWorldTagsDialog = defineAsyncComponent(() => import('./SetWorldTagsDialog.vue'));
const WorldAllowedDomainsDialog = defineAsyncComponent(() => import('./WorldAllowedDomainsDialog.vue'));
@@ -788,7 +784,10 @@
const { lastLocation } = storeToRefs(useLocationStore());
const { newInstanceSelfInvite, canOpenInstanceInGame } = useInviteStore();
const { showFavoriteDialog } = useFavoriteStore();
const { showPreviousInstancesInfoDialog } = useInstanceStore();
const {
showPreviousInstancesInfoDialog,
showPreviousInstancesWorldDialog: openPreviousInstancesWorldDialog
} = useInstanceStore();
const { instanceJoinHistory } = storeToRefs(useInstanceStore());
const { isGameRunning } = storeToRefs(useGameStore());
const { showFullscreenImageDialog } = useGalleryStore();
@@ -806,11 +805,6 @@
urlList: []
});
const isSetWorldTagsDialogVisible = ref(false);
const previousInstancesWorldDialog = ref({
visible: false,
openFlg: false,
worldRef: {}
});
const newInstanceDialogLocationTag = ref('');
const changeWorldImageDialogVisible = ref(false);
const previousImageUrl = ref('');
@@ -1268,12 +1262,7 @@
}
}
function showPreviousInstancesWorldDialog(worldRef) {
const D = previousInstancesWorldDialog.value;
D.worldRef = worldRef;
D.visible = true;
// trigger watcher
D.openFlg = true;
nextTick(() => (D.openFlg = false));
openPreviousInstancesWorldDialog(worldRef);
}
function refreshWorldDialogTreeData() {
treeData.value = formatJsonVars(worldDialog.value.ref);

View File

@@ -1,4 +1,4 @@
import { reactive, ref, watch } from 'vue';
import { nextTick, reactive, ref, watch } from 'vue';
import { defineStore } from 'pinia';
import { toast } from 'vue-sonner';
import { useI18n } from 'vue-i18n';
@@ -18,9 +18,14 @@ import {
parseLocation,
replaceBioSymbols
} from '../shared/utils';
import { instanceRequest, userRequest, worldRequest } from '../api';
import {
groupRequest,
instanceRequest,
userRequest,
worldRequest
} from '../api';
import { database } from '../service/database';
import { instanceContentSettings } from '../shared/constants';
import { accessTypeLocaleKeyMap, instanceContentSettings } from '../shared/constants';
import { useAppearanceSettingsStore } from './settings/appearance';
import { useFriendStore } from './friend';
import { useGroupStore } from './group';
@@ -106,6 +111,33 @@ export const useInstanceStore = defineStore('Instance', () => {
const previousInstancesInfoDialogInstanceId = ref('');
const previousInstancesUserDialog = ref({
visible: false,
openFlg: false,
userRef: {
id: '',
displayName: ''
}
});
const previousInstancesWorldDialog = ref({
visible: false,
openFlg: false,
worldRef: {
id: '',
name: ''
}
});
const previousInstancesGroupDialog = ref({
visible: false,
openFlg: false,
groupRef: {
id: '',
name: ''
}
});
const instanceJoinHistory = reactive(new Map());
const currentInstanceUsersData = ref([]);
@@ -116,6 +148,9 @@ export const useInstanceStore = defineStore('Instance', () => {
currentInstanceUsersData.value = [];
instanceJoinHistory.clear();
previousInstancesInfoDialogVisible.value = false;
previousInstancesUserDialog.value.visible = false;
previousInstancesWorldDialog.value.visible = false;
previousInstancesGroupDialog.value.visible = false;
cachedInstances.clear();
queuedInstances.clear();
if (isLoggedIn) {
@@ -150,9 +185,192 @@ export const useInstanceStore = defineStore('Instance', () => {
instanceJoinHistory.set(location, epoch);
}
function showPreviousInstancesInfoDialog(instanceId) {
function hidePreviousInstancesDialogs() {
previousInstancesInfoDialogVisible.value = false;
previousInstancesUserDialog.value.visible = false;
previousInstancesUserDialog.value.openFlg = false;
previousInstancesWorldDialog.value.visible = false;
previousInstancesWorldDialog.value.openFlg = false;
previousInstancesGroupDialog.value.visible = false;
previousInstancesGroupDialog.value.openFlg = false;
}
async function resolveUserRef(input) {
if (!input) {
return { id: '', displayName: '' };
}
if (typeof input === 'string') {
input = { id: input, displayName: '' };
}
const id = input.id || input.userId || '';
let displayName = input.displayName || '';
if (id && !displayName) {
try {
const args = await userRequest.getCachedUser({ userId: id });
displayName = args?.ref?.displayName || displayName;
return { ...args.ref, id, displayName };
} catch {
return { ...input, id, displayName };
}
}
return { ...input, id, displayName };
}
async function resolveWorldRef(input) {
if (!input) {
return { id: '', name: '' };
}
if (typeof input === 'string') {
input = { id: input, name: '' };
}
const id = input.id || input.worldId || '';
let name = input.name || '';
if (id && !name) {
try {
const args = await worldRequest.getCachedWorld({ worldId: id });
name = args?.ref?.name || name;
return { ...args.ref, id, name };
} catch {
return { ...input, id, name };
}
}
return { ...input, id, name };
}
async function resolveGroupRef(input) {
if (!input) {
return { id: '', name: '' };
}
if (typeof input === 'string') {
input = { id: input, name: '' };
}
const id = input.id || input.groupId || '';
let name = input.name || '';
if (id && !name) {
try {
const args = await groupRequest.getCachedGroup({ groupId: id });
name = args?.ref?.name || name;
return { ...args.ref, id, name };
} catch {
return { ...input, id, name };
}
}
return { ...input, id, name };
}
function translateAccessType(accessTypeNameRaw) {
const key = accessTypeLocaleKeyMap[accessTypeNameRaw];
if (!key) {
return accessTypeNameRaw;
}
if (
accessTypeNameRaw === 'groupPublic' ||
accessTypeNameRaw === 'groupPlus'
) {
const groupKey = accessTypeLocaleKeyMap.group;
return `${t(groupKey)} ${t(key)}`;
}
return t(key);
}
function formatPreviousInstancesInfoLabel(
instanceId,
worldNameOverride = ''
) {
const location = parseLocation(instanceId);
const worldId = location.worldId;
const worldName =
worldNameOverride ||
(worldId ? worldStore.cachedWorlds.get(worldId)?.name : '') ||
'';
const baseLabel = worldName || worldId || instanceId || '';
const accessTypeLabel = translateAccessType(
location.accessTypeName || ''
);
if (!accessTypeLabel || !location.instanceId) {
return baseLabel;
}
return `${baseLabel} · ${accessTypeLabel}`;
}
function showPreviousInstancesInfoDialog(instanceId, options = {}) {
hidePreviousInstancesDialogs();
previousInstancesInfoDialogVisible.value = true;
previousInstancesInfoDialogInstanceId.value = instanceId;
if (!options.skipBreadcrumb && instanceId) {
uiStore.pushDialogCrumb(
'previous-instances-info',
instanceId,
formatPreviousInstancesInfoLabel(instanceId)
);
const location = parseLocation(instanceId);
if (
location.worldId &&
!worldStore.cachedWorlds.get(location.worldId)?.name
) {
worldRequest
.getCachedWorld({ worldId: location.worldId })
.then((args) => {
uiStore.setDialogCrumbLabel(
'previous-instances-info',
instanceId,
formatPreviousInstancesInfoLabel(
instanceId,
args?.ref?.name || ''
)
);
})
.catch(() => {});
}
}
}
async function showPreviousInstancesUserDialog(userRef, options = {}) {
hidePreviousInstancesDialogs();
const resolved = await resolveUserRef(userRef);
previousInstancesUserDialog.value.userRef = resolved;
previousInstancesUserDialog.value.visible = true;
previousInstancesUserDialog.value.openFlg = true;
nextTick(() => (previousInstancesUserDialog.value.openFlg = false));
if (!options.skipBreadcrumb && resolved.id) {
uiStore.pushDialogCrumb(
'previous-instances-user',
resolved.id,
resolved.displayName || resolved.id
);
}
}
async function showPreviousInstancesWorldDialog(worldRef, options = {}) {
hidePreviousInstancesDialogs();
const resolved = await resolveWorldRef(worldRef);
previousInstancesWorldDialog.value.worldRef = resolved;
previousInstancesWorldDialog.value.visible = true;
previousInstancesWorldDialog.value.openFlg = true;
nextTick(() => (previousInstancesWorldDialog.value.openFlg = false));
if (!options.skipBreadcrumb && resolved.id) {
uiStore.pushDialogCrumb(
'previous-instances-world',
resolved.id,
resolved.name || resolved.id
);
}
}
async function showPreviousInstancesGroupDialog(groupRef, options = {}) {
hidePreviousInstancesDialogs();
const resolved = await resolveGroupRef(groupRef);
previousInstancesGroupDialog.value.groupRef = resolved;
previousInstancesGroupDialog.value.visible = true;
previousInstancesGroupDialog.value.openFlg = true;
nextTick(() => (previousInstancesGroupDialog.value.openFlg = false));
if (!options.skipBreadcrumb && resolved.id) {
uiStore.pushDialogCrumb(
'previous-instances-group',
resolved.id,
resolved.name || resolved.id
);
}
}
function updateCurrentInstanceWorld() {
@@ -1238,6 +1456,9 @@ export const useInstanceStore = defineStore('Instance', () => {
queuedInstances,
previousInstancesInfoDialogVisible,
previousInstancesInfoDialogInstanceId,
previousInstancesUserDialog,
previousInstancesWorldDialog,
previousInstancesGroupDialog,
instanceJoinHistory,
currentInstanceUsersData,
@@ -1251,7 +1472,11 @@ export const useInstanceStore = defineStore('Instance', () => {
applyQueuedInstance,
instanceQueueReady,
instanceQueueUpdate,
hidePreviousInstancesDialogs,
showPreviousInstancesInfoDialog,
showPreviousInstancesUserDialog,
showPreviousInstancesWorldDialog,
showPreviousInstancesGroupDialog,
addInstanceJoinHistory,
getCurrentInstanceUserList,
getInstanceJoinHistory,

View File

@@ -62,8 +62,6 @@
<FullscreenImagePreview></FullscreenImagePreview>
<PreviousInstancesInfoDialog></PreviousInstancesInfoDialog>
<LaunchDialog></LaunchDialog>
<LaunchOptionsDialog></LaunchOptionsDialog>
@@ -108,7 +106,6 @@
import LaunchDialog from '../../components/dialogs/LaunchDialog.vue';
import LaunchOptionsDialog from '../Settings/dialogs/LaunchOptionsDialog.vue';
import NavMenu from '../../components/NavMenu.vue';
import PreviousInstancesInfoDialog from '../../components/dialogs/PreviousInstancesDialog/PreviousInstancesInfoDialog.vue';
import PrimaryPasswordDialog from '../Settings/dialogs/PrimaryPasswordDialog.vue';
import SendBoopDialog from '../../components/dialogs/SendBoopDialog.vue';
import Sidebar from '../Sidebar/Sidebar.vue';