mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
refactor store
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { useUserStore } from '../stores';
|
import { handleConfig } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
const loginReq = {
|
const loginReq = {
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +63,7 @@ const loginReq = {
|
|||||||
const args = {
|
const args = {
|
||||||
json
|
json
|
||||||
};
|
};
|
||||||
useUserStore().handleConfig(args);
|
handleConfig(args);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { useUserStore } from '../stores';
|
import { useUserStore } from '../stores';
|
||||||
|
import { applyCurrentUser } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
const avatarReq = {
|
const avatarReq = {
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +66,7 @@ const avatarReq = {
|
|||||||
* @returns {Promise<{json: any, params}>}
|
* @returns {Promise<{json: any, params}>}
|
||||||
*/
|
*/
|
||||||
selectAvatar(params) {
|
selectAvatar(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`avatars/${params.avatarId}/select`, {
|
return request(`avatars/${params.avatarId}/select`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
params
|
params
|
||||||
@@ -74,7 +75,7 @@ const avatarReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
const ref = userStore.applyCurrentUser(json);
|
const ref = applyCurrentUser(json);
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.user(ref.id),
|
queryKey: queryKeys.user(ref.id),
|
||||||
nextData: {
|
nextData: {
|
||||||
@@ -97,7 +98,7 @@ const avatarReq = {
|
|||||||
* @returns { Promise<{json: any, params}> }
|
* @returns { Promise<{json: any, params}> }
|
||||||
*/
|
*/
|
||||||
selectFallbackAvatar(params) {
|
selectFallbackAvatar(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`avatars/${params.avatarId}/selectfallback`, {
|
return request(`avatars/${params.avatarId}/selectfallback`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
params
|
params
|
||||||
@@ -106,7 +107,7 @@ const avatarReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
const ref = userStore.applyCurrentUser(json);
|
const ref = applyCurrentUser(json);
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.user(ref.id),
|
queryKey: queryKeys.user(ref.id),
|
||||||
nextData: {
|
nextData: {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { queryClient } from '../queries';
|
import { queryClient } from '../queries';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { applyUser } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -22,7 +23,7 @@ const friendReq = {
|
|||||||
* @type {import('../types/api/friend').GetFriends}
|
* @type {import('../types/api/friend').GetFriends}
|
||||||
*/
|
*/
|
||||||
getFriends(params) {
|
getFriends(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request('auth/user/friends', {
|
return request('auth/user/friends', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
params
|
params
|
||||||
@@ -36,7 +37,7 @@ const friendReq = {
|
|||||||
console.error('/friends gave us garbage', user);
|
console.error('/friends gave us garbage', user);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
userStore.applyUser(user);
|
applyUser(user);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useGroupStore, useUserStore } from '../stores';
|
import { useUserStore } from '../stores';
|
||||||
|
import { applyGroup } from '../coordinators/groupCoordinator';
|
||||||
import { queryClient } from '../queries';
|
import { queryClient } from '../queries';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
|
|
||||||
@@ -89,12 +90,11 @@ const groupReq = {
|
|||||||
includeRoles: params.includeRoles || false
|
includeRoles: params.includeRoles || false
|
||||||
}
|
}
|
||||||
}).then((json) => {
|
}).then((json) => {
|
||||||
const groupStore = useGroupStore();
|
|
||||||
const args = {
|
const args = {
|
||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = groupStore.applyGroup(json);
|
args.ref = applyGroup(json);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useAvatarStore, useWorldStore } from '../stores';
|
import { useAvatarStore, useWorldStore } from '../stores';
|
||||||
|
import { applyWorld } from '../coordinators/worldCoordinator';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
|
|
||||||
const imageReq = {
|
const imageReq = {
|
||||||
@@ -267,7 +268,7 @@ const imageReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = worldStore.applyWorld(json);
|
args.ref = applyWorld(json);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { useUserStore } from '../stores';
|
import { useUserStore } from '../stores';
|
||||||
|
import { applyUser, applyCurrentUser } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
@@ -16,7 +17,7 @@ const userReq = {
|
|||||||
* @type {import('../types/api/user').GetUser}
|
* @type {import('../types/api/user').GetUser}
|
||||||
*/
|
*/
|
||||||
getUser(params) {
|
getUser(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`users/${params.userId}`, {
|
return request(`users/${params.userId}`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
}).then((json) => {
|
}).then((json) => {
|
||||||
@@ -29,7 +30,7 @@ const userReq = {
|
|||||||
const args = {
|
const args = {
|
||||||
json,
|
json,
|
||||||
params,
|
params,
|
||||||
ref: userStore.applyUser(json)
|
ref: applyUser(json)
|
||||||
};
|
};
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
@@ -56,7 +57,7 @@ const userReq = {
|
|||||||
* @returns {Promise<{json: any, params: {tags: string[]}}>}
|
* @returns {Promise<{json: any, params: {tags: string[]}}>}
|
||||||
*/
|
*/
|
||||||
addUserTags(params) {
|
addUserTags(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`users/${getCurrentUserId()}/addTags`, {
|
return request(`users/${getCurrentUserId()}/addTags`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
params
|
params
|
||||||
@@ -65,7 +66,7 @@ const userReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
userStore.applyCurrentUser(json);
|
applyCurrentUser(json);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -75,7 +76,7 @@ const userReq = {
|
|||||||
* @returns {Promise<{json: any, params: {tags: string[]}}>}
|
* @returns {Promise<{json: any, params: {tags: string[]}}>}
|
||||||
*/
|
*/
|
||||||
removeUserTags(params) {
|
removeUserTags(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`users/${getCurrentUserId()}/removeTags`, {
|
return request(`users/${getCurrentUserId()}/removeTags`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
params
|
params
|
||||||
@@ -84,7 +85,7 @@ const userReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
userStore.applyCurrentUser(json);
|
applyCurrentUser(json);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -113,7 +114,7 @@ const userReq = {
|
|||||||
* @type {import('../types/api/user').GetCurrentUser}
|
* @type {import('../types/api/user').GetCurrentUser}
|
||||||
*/
|
*/
|
||||||
saveCurrentUser(params) {
|
saveCurrentUser(params) {
|
||||||
const userStore = useUserStore();
|
|
||||||
return request(`users/${getCurrentUserId()}`, {
|
return request(`users/${getCurrentUserId()}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
params
|
params
|
||||||
@@ -121,7 +122,7 @@ const userReq = {
|
|||||||
const args = {
|
const args = {
|
||||||
json,
|
json,
|
||||||
params,
|
params,
|
||||||
ref: userStore.applyCurrentUser(json)
|
ref: applyCurrentUser(json)
|
||||||
};
|
};
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.user(args.ref.id),
|
queryKey: queryKeys.user(args.ref.id),
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { useWorldStore } from '../stores';
|
import { applyWorld } from '../coordinators/worldCoordinator';
|
||||||
|
|
||||||
const worldReq = {
|
const worldReq = {
|
||||||
/**
|
/**
|
||||||
* @type {import('../types/api/world').GetWorld}
|
* @type {import('../types/api/world').GetWorld}
|
||||||
*/
|
*/
|
||||||
getWorld(params) {
|
getWorld(params) {
|
||||||
const worldStore = useWorldStore();
|
|
||||||
return request(`worlds/${params.worldId}`, {
|
return request(`worlds/${params.worldId}`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
}).then((json) => {
|
}).then((json) => {
|
||||||
@@ -15,7 +14,7 @@ const worldReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = worldStore.applyWorld(json);
|
args.ref = applyWorld(json);
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -24,7 +23,6 @@ const worldReq = {
|
|||||||
* @type {import('../types/api/world').GetWorlds}
|
* @type {import('../types/api/world').GetWorlds}
|
||||||
*/
|
*/
|
||||||
getWorlds(params, option) {
|
getWorlds(params, option) {
|
||||||
const worldStore = useWorldStore();
|
|
||||||
let endpoint = 'worlds';
|
let endpoint = 'worlds';
|
||||||
if (typeof option !== 'undefined') {
|
if (typeof option !== 'undefined') {
|
||||||
endpoint = `worlds/${option}`;
|
endpoint = `worlds/${option}`;
|
||||||
@@ -39,7 +37,7 @@ const worldReq = {
|
|||||||
option
|
option
|
||||||
};
|
};
|
||||||
for (const json of args.json) {
|
for (const json of args.json) {
|
||||||
worldStore.applyWorld(json);
|
applyWorld(json);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
@@ -64,7 +62,6 @@ const worldReq = {
|
|||||||
* @type {import('../types/api/world').SaveWorld}
|
* @type {import('../types/api/world').SaveWorld}
|
||||||
*/
|
*/
|
||||||
saveWorld(params) {
|
saveWorld(params) {
|
||||||
const worldStore = useWorldStore();
|
|
||||||
return request(`worlds/${params.id}`, {
|
return request(`worlds/${params.id}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
params
|
params
|
||||||
@@ -73,7 +70,7 @@ const worldReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = worldStore.applyWorld(json);
|
args.ref = applyWorld(json);
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.world(args.ref.id),
|
queryKey: queryKeys.world(args.ref.id),
|
||||||
nextData: args
|
nextData: args
|
||||||
@@ -92,7 +89,6 @@ const worldReq = {
|
|||||||
* @returns {Promise<{json: any, params}>}
|
* @returns {Promise<{json: any, params}>}
|
||||||
*/
|
*/
|
||||||
publishWorld(params) {
|
publishWorld(params) {
|
||||||
const worldStore = useWorldStore();
|
|
||||||
return request(`worlds/${params.worldId}/publish`, {
|
return request(`worlds/${params.worldId}/publish`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
params
|
params
|
||||||
@@ -101,7 +97,7 @@ const worldReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = worldStore.applyWorld(json);
|
args.ref = applyWorld(json);
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.world(args.ref.id),
|
queryKey: queryKeys.world(args.ref.id),
|
||||||
nextData: args
|
nextData: args
|
||||||
@@ -120,7 +116,6 @@ const worldReq = {
|
|||||||
* @returns {Promise<{json: any, params}>}
|
* @returns {Promise<{json: any, params}>}
|
||||||
*/
|
*/
|
||||||
unpublishWorld(params) {
|
unpublishWorld(params) {
|
||||||
const worldStore = useWorldStore();
|
|
||||||
return request(`worlds/${params.worldId}/publish`, {
|
return request(`worlds/${params.worldId}/publish`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
params
|
params
|
||||||
@@ -129,7 +124,7 @@ const worldReq = {
|
|||||||
json,
|
json,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
args.ref = worldStore.applyWorld(json);
|
args.ref = applyWorld(json);
|
||||||
patchAndRefetchActiveQuery({
|
patchAndRefetchActiveQuery({
|
||||||
queryKey: queryKeys.world(args.ref.id),
|
queryKey: queryKeys.world(args.ref.id),
|
||||||
nextData: args
|
nextData: args
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
import { TooltipWrapper } from './ui/tooltip';
|
import { TooltipWrapper } from './ui/tooltip';
|
||||||
import { useAvatarStore } from '../stores';
|
import { useAvatarStore } from '../stores';
|
||||||
|
import { getAvatarName, showAvatarAuthorDialog } from '../coordinators/avatarCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const avatarStore = useAvatarStore();
|
const avatarStore = useAvatarStore();
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
ownerId = props.hintownerid;
|
ownerId = props.hintownerid;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const info = await avatarStore.getAvatarName(props.imageurl);
|
const info = await getAvatarName(props.imageurl);
|
||||||
avatarName.value = info.avatarName;
|
avatarName.value = info.avatarName;
|
||||||
ownerId = info.ownerId;
|
ownerId = info.ownerId;
|
||||||
} catch {
|
} catch {
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
if (!props.imageurl) return;
|
if (!props.imageurl) return;
|
||||||
avatarStore.showAvatarAuthorDialog(props.userid, ownerId, props.imageurl);
|
showAvatarAuthorDialog(props.userid, ownerId, props.imageurl);
|
||||||
};
|
};
|
||||||
|
|
||||||
watch([() => props.imageurl, () => props.userid, () => props.avatartags], parse, { immediate: true });
|
watch([() => props.imageurl, () => props.userid, () => props.avatartags], parse, { immediate: true });
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<span @click="showUserDialog" class="cursor-pointer">{{ username }}</span>
|
<span @click="openUserDialog" class="cursor-pointer">{{ username }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
import { queryRequest } from '../api';
|
import { queryRequest } from '../api';
|
||||||
import { useUserStore } from '../stores';
|
import { showUserDialog } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
userid: String,
|
userid: String,
|
||||||
@@ -40,9 +38,10 @@
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function showUserDialog() {
|
function openUserDialog() {
|
||||||
userStore.showUserDialog(props.userid);
|
showUserDialog(props.userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch([() => props.userid, () => props.location, () => props.forceUpdateKey], parse, { immediate: true });
|
watch([() => props.userid, () => props.location, () => props.forceUpdateKey], parse, { immediate: true });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@
|
|||||||
} from '../stores';
|
} from '../stores';
|
||||||
import { checkCanInviteSelf, formatDateFilter, hasGroupPermission, parseLocation } from '../shared/utils';
|
import { checkCanInviteSelf, formatDateFilter, hasGroupPermission, parseLocation } from '../shared/utils';
|
||||||
import { instanceRequest, miscRequest } from '../api';
|
import { instanceRequest, miscRequest } from '../api';
|
||||||
|
import { showUserDialog } from '../coordinators/userCoordinator';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false
|
inheritAttrs: false
|
||||||
@@ -352,9 +353,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showUserDialog = (userId) => {
|
|
||||||
userStore.showUserDialog(userId);
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeInstance = (location) => {
|
const closeInstance = (location) => {
|
||||||
modalStore
|
modalStore
|
||||||
|
|||||||
@@ -50,12 +50,13 @@
|
|||||||
useSearchStore,
|
useSearchStore,
|
||||||
useWorldStore
|
useWorldStore
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
|
import { showWorldDialog } from '../coordinators/worldCoordinator';
|
||||||
import { Spinner } from './ui/spinner';
|
import { Spinner } from './ui/spinner';
|
||||||
import { accessTypeLocaleKeyMap } from '../shared/constants';
|
import { accessTypeLocaleKeyMap } from '../shared/constants';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { cachedWorlds, showWorldDialog } = useWorldStore();
|
const { cachedWorlds } = useWorldStore();
|
||||||
const { showGroupDialog } = useGroupStore();
|
const { showGroupDialog } = useGroupStore();
|
||||||
const { showPreviousInstancesInfoDialog } = useInstanceStore();
|
const { showPreviousInstancesInfoDialog } = useInstanceStore();
|
||||||
const { verifyShortName } = useSearchStore();
|
const { verifyShortName } = useSearchStore();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<Unlock v-if="isUnlocked" :class="['inline-block', 'mr-1.25']" />
|
<Unlock v-if="isUnlocked" :class="['inline-block', 'mr-1.25']" />
|
||||||
<span> {{ accessTypeName }} #{{ instanceName }}</span>
|
<span> {{ accessTypeName }} #{{ instanceName }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="groupName" @click="showGroupDialog" class="cursor-pointer">({{ groupName }})</span>
|
<span v-if="groupName" @click="openLocationGroupDialog" class="cursor-pointer">({{ groupName }})</span>
|
||||||
<TooltipWrapper v-if="isClosed" :content="t('dialog.user.info.instance_closed')">
|
<TooltipWrapper v-if="isClosed" :content="t('dialog.user.info.instance_closed')">
|
||||||
<AlertTriangle :class="['inline-block', 'ml-1']" style="color: lightcoral" />
|
<AlertTriangle :class="['inline-block', 'ml-1']" style="color: lightcoral" />
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useGroupStore, useInstanceStore, useLaunchStore } from '../stores';
|
import { useGroupStore, useInstanceStore, useLaunchStore } from '../stores';
|
||||||
|
import { showGroupDialog } from '../coordinators/groupCoordinator';
|
||||||
import { getGroupName, parseLocation } from '../shared/utils';
|
import { getGroupName, parseLocation } from '../shared/utils';
|
||||||
import { accessTypeLocaleKeyMap } from '../shared/constants';
|
import { accessTypeLocaleKeyMap } from '../shared/constants';
|
||||||
|
|
||||||
@@ -135,10 +136,10 @@
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function showGroupDialog() {
|
function openLocationGroupDialog() {
|
||||||
if (!location.value) return;
|
if (!location.value) return;
|
||||||
const L = parseLocation(location.value);
|
const L = parseLocation(location.value);
|
||||||
if (!L.groupId) return;
|
if (!L.groupId) return;
|
||||||
groupStore.showGroupDialog(L.groupId);
|
showGroupDialog(L.groupId);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -601,20 +601,22 @@
|
|||||||
import { formatJsonVars } from '../../../shared/utils/base/ui';
|
import { formatJsonVars } from '../../../shared/utils/base/ui';
|
||||||
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
|
import { handleImageUploadInput } from '../../../shared/utils/imageUpload';
|
||||||
import { runDeleteVRChatCacheFlow as deleteVRChatCache } from '../../../coordinators/gameCoordinator';
|
import { runDeleteVRChatCacheFlow as deleteVRChatCache } from '../../../coordinators/gameCoordinator';
|
||||||
|
import { showAvatarDialog, applyAvatar, selectAvatarWithoutConfirmation } from '../../../coordinators/avatarCoordinator';
|
||||||
import { useAvatarDialogCommands } from './useAvatarDialogCommands';
|
import { useAvatarDialogCommands } from './useAvatarDialogCommands';
|
||||||
|
|
||||||
import DialogJsonTab from '../DialogJsonTab.vue';
|
import DialogJsonTab from '../DialogJsonTab.vue';
|
||||||
import ImageCropDialog from '../ImageCropDialog.vue';
|
import ImageCropDialog from '../ImageCropDialog.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const SetAvatarStylesDialog = defineAsyncComponent(() => import('./SetAvatarStylesDialog.vue'));
|
const SetAvatarStylesDialog = defineAsyncComponent(() => import('./SetAvatarStylesDialog.vue'));
|
||||||
const SetAvatarTagsDialog = defineAsyncComponent(() => import('./SetAvatarTagsDialog.vue'));
|
const SetAvatarTagsDialog = defineAsyncComponent(() => import('./SetAvatarTagsDialog.vue'));
|
||||||
|
|
||||||
const { showUserDialog, sortUserDialogAvatars } = useUserStore();
|
const { sortUserDialogAvatars } = useUserStore();
|
||||||
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
||||||
const avatarStore = useAvatarStore();
|
const avatarStore = useAvatarStore();
|
||||||
const { cachedAvatarModerations, cachedAvatars } = avatarStore;
|
const { cachedAvatarModerations, cachedAvatars } = avatarStore;
|
||||||
const { avatarDialog } = storeToRefs(avatarStore);
|
const { avatarDialog } = storeToRefs(avatarStore);
|
||||||
const { showAvatarDialog, getAvatarGallery, applyAvatarModeration, applyAvatar, selectAvatarWithoutConfirmation } =
|
const { getAvatarGallery, applyAvatarModeration } =
|
||||||
avatarStore;
|
avatarStore;
|
||||||
const { showFavoriteDialog } = useFavoriteStore();
|
const { showFavoriteDialog } = useFavoriteStore();
|
||||||
const { isGameRunning } = storeToRefs(useGameStore());
|
const { isGameRunning } = storeToRefs(useGameStore());
|
||||||
|
|||||||
@@ -93,6 +93,7 @@
|
|||||||
import { avatarRequest, queryRequest } from '../../../api';
|
import { avatarRequest, queryRequest } from '../../../api';
|
||||||
import { arraysMatch } from '../../../shared/utils';
|
import { arraysMatch } from '../../../shared/utils';
|
||||||
import { useAvatarStore } from '../../../stores';
|
import { useAvatarStore } from '../../../stores';
|
||||||
|
import { applyAvatar } from '../../../coordinators/avatarCoordinator';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
setAvatarStylesDialog: {
|
setAvatarStylesDialog: {
|
||||||
@@ -104,7 +105,6 @@
|
|||||||
const emit = defineEmits(['update:setAvatarStylesDialog']);
|
const emit = defineEmits(['update:setAvatarStylesDialog']);
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { applyAvatar } = useAvatarStore();
|
|
||||||
|
|
||||||
const SELECT_CLEAR_VALUE = '__clear__';
|
const SELECT_CLEAR_VALUE = '__clear__';
|
||||||
|
|
||||||
|
|||||||
@@ -128,8 +128,8 @@
|
|||||||
import { avatarRequest } from '../../../api';
|
import { avatarRequest } from '../../../api';
|
||||||
import { removeFromArray } from '../../../shared/utils';
|
import { removeFromArray } from '../../../shared/utils';
|
||||||
import { useAvatarStore } from '../../../stores';
|
import { useAvatarStore } from '../../../stores';
|
||||||
|
import { showAvatarDialog, applyAvatar } from '../../../coordinators/avatarCoordinator';
|
||||||
|
|
||||||
const { showAvatarDialog, applyAvatar } = useAvatarStore();
|
|
||||||
const { cachedAvatars } = useAvatarStore();
|
const { cachedAvatars } = useAvatarStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|||||||
@@ -407,6 +407,13 @@
|
|||||||
removeFromArray
|
removeFromArray
|
||||||
} from '../../../shared/utils';
|
} from '../../../shared/utils';
|
||||||
import { useGalleryStore, useGroupStore, useModalStore, useUserStore } from '../../../stores';
|
import { useGalleryStore, useGroupStore, useModalStore, useUserStore } from '../../../stores';
|
||||||
|
import {
|
||||||
|
getGroupDialogGroup,
|
||||||
|
showGroupDialog,
|
||||||
|
leaveGroupPrompt,
|
||||||
|
setGroupVisibility,
|
||||||
|
setGroupSubscription
|
||||||
|
} from '../../../coordinators/groupCoordinator';
|
||||||
import { groupRequest, queryRequest } from '../../../api';
|
import { groupRequest, queryRequest } from '../../../api';
|
||||||
import { queryKeys, refetchActiveEntityQuery } from '../../../queries';
|
import { queryKeys, refetchActiveEntityQuery } from '../../../queries';
|
||||||
import { Badge } from '../../ui/badge';
|
import { Badge } from '../../ui/badge';
|
||||||
@@ -419,6 +426,7 @@
|
|||||||
import GroupDialogPhotosTab from './GroupDialogPhotosTab.vue';
|
import GroupDialogPhotosTab from './GroupDialogPhotosTab.vue';
|
||||||
import GroupDialogPostsTab from './GroupDialogPostsTab.vue';
|
import GroupDialogPostsTab from './GroupDialogPostsTab.vue';
|
||||||
import GroupPostEditDialog from './GroupPostEditDialog.vue';
|
import GroupPostEditDialog from './GroupPostEditDialog.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const groupDialogTabs = computed(() => [
|
const groupDialogTabs = computed(() => [
|
||||||
@@ -431,16 +439,11 @@
|
|||||||
|
|
||||||
const modalStore = useModalStore();
|
const modalStore = useModalStore();
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
const { groupDialog, inviteGroupDialog } = storeToRefs(useGroupStore());
|
const { groupDialog, inviteGroupDialog } = storeToRefs(useGroupStore());
|
||||||
const {
|
const {
|
||||||
getGroupDialogGroup,
|
|
||||||
updateGroupPostSearch,
|
updateGroupPostSearch,
|
||||||
showGroupDialog,
|
|
||||||
leaveGroupPrompt,
|
|
||||||
setGroupVisibility,
|
|
||||||
setGroupSubscription,
|
|
||||||
showGroupMemberModerationDialog
|
showGroupMemberModerationDialog
|
||||||
} = useGroupStore();
|
} = useGroupStore();
|
||||||
|
|
||||||
|
|||||||
@@ -361,6 +361,7 @@
|
|||||||
|
|
||||||
import GroupCalendarEventCard from '../../../views/Tools/components/GroupCalendarEventCard.vue';
|
import GroupCalendarEventCard from '../../../views/Tools/components/GroupCalendarEventCard.vue';
|
||||||
import InstanceActionBar from '../../InstanceActionBar.vue';
|
import InstanceActionBar from '../../InstanceActionBar.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
showGroupPostEditDialog: {
|
showGroupPostEditDialog: {
|
||||||
@@ -375,7 +376,7 @@
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { groupDialog } = storeToRefs(useGroupStore());
|
const { groupDialog } = storeToRefs(useGroupStore());
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|||||||
@@ -212,15 +212,16 @@
|
|||||||
|
|
||||||
import { downloadAndSaveJson, hasGroupPermission, userImage } from '../../../shared/utils';
|
import { downloadAndSaveJson, hasGroupPermission, userImage } from '../../../shared/utils';
|
||||||
import { useGroupStore, useUserStore } from '../../../stores';
|
import { useGroupStore, useUserStore } from '../../../stores';
|
||||||
|
import { applyGroupMember, handleGroupMember } from '../../../coordinators/groupCoordinator';
|
||||||
import { groupDialogSortingOptions } from '../../../shared/constants';
|
import { groupDialogSortingOptions } from '../../../shared/constants';
|
||||||
import { useGroupMembers } from './useGroupMembers';
|
import { useGroupMembers } from './useGroupMembers';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
const { groupDialog } = storeToRefs(useGroupStore());
|
const { groupDialog } = storeToRefs(useGroupStore());
|
||||||
const { applyGroupMember, handleGroupMember } = useGroupStore();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isGroupMembersDone,
|
isGroupMembersDone,
|
||||||
|
|||||||
@@ -122,6 +122,7 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
|
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
|
||||||
|
import { applyGroupMember, handleGroupMember, handleGroupMemberProps } from '../../../coordinators/groupCoordinator';
|
||||||
import { hasGroupPermission, userImage, userImageFull } from '../../../shared/utils';
|
import { hasGroupPermission, userImage, userImageFull } from '../../../shared/utils';
|
||||||
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
|
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
|
||||||
import { groupRequest, userRequest } from '../../../api';
|
import { groupRequest, userRequest } from '../../../api';
|
||||||
@@ -138,14 +139,14 @@
|
|||||||
import GroupModerationInvitesTab from './GroupModerationInvitesTab.vue';
|
import GroupModerationInvitesTab from './GroupModerationInvitesTab.vue';
|
||||||
import GroupModerationLogsTab from './GroupModerationLogsTab.vue';
|
import GroupModerationLogsTab from './GroupModerationLogsTab.vue';
|
||||||
import GroupModerationMembersTab from './GroupModerationMembersTab.vue';
|
import GroupModerationMembersTab from './GroupModerationMembersTab.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
// ── Stores ───────────────────────────────────────────────────
|
// ── Stores ───────────────────────────────────────────────────
|
||||||
const appearanceSettingsStore = useAppearanceSettingsStore();
|
const appearanceSettingsStore = useAppearanceSettingsStore();
|
||||||
const { randomUserColours } = storeToRefs(appearanceSettingsStore);
|
const { randomUserColours } = storeToRefs(appearanceSettingsStore);
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
const { groupDialog, groupMemberModeration } = storeToRefs(useGroupStore());
|
const { groupDialog, groupMemberModeration } = storeToRefs(useGroupStore());
|
||||||
const { applyGroupMember, handleGroupMember, handleGroupMemberProps } = useGroupStore();
|
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,9 @@
|
|||||||
import { createColumns } from './previousInstancesInfoColumns.jsx';
|
import { createColumns } from './previousInstancesInfoColumns.jsx';
|
||||||
import { database } from '../../../service/database';
|
import { database } from '../../../service/database';
|
||||||
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
||||||
|
import { lookupUser } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { lookupUser } = useUserStore();
|
|
||||||
const { previousInstancesInfoDialog, previousInstancesInfoState } = storeToRefs(useInstanceStore());
|
const { previousInstancesInfoDialog, previousInstancesInfoState } = storeToRefs(useInstanceStore());
|
||||||
const { gameLogIsFriend, gameLogIsFavorite } = useGameLogStore();
|
const { gameLogIsFriend, gameLogIsFavorite } = useGameLogStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
useNotificationStore,
|
useNotificationStore,
|
||||||
useUserStore
|
useUserStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
|
import { showGroupDialog } from '../../../coordinators/groupCoordinator';
|
||||||
import { copyToClipboard } from '../../../shared/utils';
|
import { copyToClipboard } from '../../../shared/utils';
|
||||||
import { formatJsonVars } from '../../../shared/utils/base/ui';
|
import { formatJsonVars } from '../../../shared/utils/base/ui';
|
||||||
import { miscRequest } from '../../../api';
|
import { miscRequest } from '../../../api';
|
||||||
@@ -139,11 +140,12 @@
|
|||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
|
|
||||||
const { userDialog, languageDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
const { userDialog, languageDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
||||||
const { cachedUsers, showUserDialog, refreshUserDialogAvatars, showSendBoopDialog } = useUserStore();
|
const { cachedUsers, showSendBoopDialog } = useUserStore();
|
||||||
const { showFavoriteDialog } = useFavoriteStore();
|
const { showFavoriteDialog } = useFavoriteStore();
|
||||||
const { showAvatarDialog, showAvatarAuthorDialog } = useAvatarStore();
|
import { showAvatarDialog, showAvatarAuthorDialog } from '../../../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog, refreshUserDialogAvatars } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { showGroupDialog, showModerateGroupDialog } = useGroupStore();
|
const { showModerateGroupDialog } = useGroupStore();
|
||||||
const { inviteGroupDialog } = storeToRefs(useGroupStore());
|
const { inviteGroupDialog } = storeToRefs(useGroupStore());
|
||||||
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
||||||
const { refreshInviteMessageTableData } = useInviteStore();
|
const { refreshInviteMessageTableData } = useInviteStore();
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
const { userDialog, currentUser } = storeToRefs(userStore);
|
const { userDialog, currentUser } = storeToRefs(userStore);
|
||||||
const { sortUserDialogAvatars, refreshUserDialogAvatars } = userStore;
|
const { sortUserDialogAvatars, refreshUserDialogAvatars } = userStore;
|
||||||
|
|
||||||
const { showAvatarDialog, lookupAvatars } = useAvatarStore();
|
import { showAvatarDialog, lookupAvatars } from '../../../coordinators/avatarCoordinator';
|
||||||
const { cachedAvatars } = useAvatarStore();
|
const { cachedAvatars } = useAvatarStore();
|
||||||
|
|
||||||
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
import DeprecationAlert from '@/components/DeprecationAlert.vue';
|
import DeprecationAlert from '@/components/DeprecationAlert.vue';
|
||||||
|
|
||||||
import { useFavoriteStore, useUserStore, useWorldStore } from '../../../stores';
|
import { useFavoriteStore, useUserStore, useWorldStore } from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { handleFavoriteWorldList } from '../../../coordinators/favoriteCoordinator';
|
import { handleFavoriteWorldList } from '../../../coordinators/favoriteCoordinator';
|
||||||
import { favoriteRequest } from '../../../api';
|
import { favoriteRequest } from '../../../api';
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@
|
|||||||
|
|
||||||
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
||||||
const { favoriteLimits } = storeToRefs(useFavoriteStore());
|
const { favoriteLimits } = storeToRefs(useFavoriteStore());
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
|
|
||||||
const favoriteWorldsTab = ref('0');
|
const favoriteWorldsTab = ref('0');
|
||||||
const userDialogFavoriteWorldsRequestId = ref(0);
|
const userDialogFavoriteWorldsRequestId = ref(0);
|
||||||
|
|||||||
@@ -372,15 +372,7 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useAuthStore, useGroupStore, useUiStore, useUserStore } from '../../../stores';
|
import { useAuthStore, useGroupStore, useUiStore, useUserStore } from '../../../stores';
|
||||||
import { compareByMemberCount, compareByName } from '../../../shared/utils';
|
import {
|
||||||
import { groupRequest } from '../../../api';
|
|
||||||
import { useOptionKeySelect } from '../../../composables/useOptionKeySelect';
|
|
||||||
import { userDialogGroupSortingOptions } from '../../../shared/constants';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const { userDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
|
||||||
const {
|
|
||||||
showGroupDialog,
|
showGroupDialog,
|
||||||
applyGroup,
|
applyGroup,
|
||||||
saveCurrentUserGroups,
|
saveCurrentUserGroups,
|
||||||
@@ -389,7 +381,15 @@
|
|||||||
leaveGroupPrompt,
|
leaveGroupPrompt,
|
||||||
setGroupVisibility,
|
setGroupVisibility,
|
||||||
handleGroupList
|
handleGroupList
|
||||||
} = useGroupStore();
|
} from '../../../coordinators/groupCoordinator';
|
||||||
|
import { compareByMemberCount, compareByName } from '../../../shared/utils';
|
||||||
|
import { groupRequest } from '../../../api';
|
||||||
|
import { useOptionKeySelect } from '../../../composables/useOptionKeySelect';
|
||||||
|
import { userDialogGroupSortingOptions } from '../../../shared/constants';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const { userDialog, currentUser, isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
||||||
const { currentUserGroups, inGameGroupOrder } = storeToRefs(useGroupStore());
|
const { currentUserGroups, inGameGroupOrder } = storeToRefs(useGroupStore());
|
||||||
const { cachedConfig } = storeToRefs(useAuthStore());
|
const { cachedConfig } = storeToRefs(useAuthStore());
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
|
|||||||
@@ -501,9 +501,11 @@
|
|||||||
useUserStore,
|
useUserStore,
|
||||||
useWorldStore
|
useWorldStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { queryRequest, userRequest } from '../../../api';
|
import { queryRequest, userRequest } from '../../../api';
|
||||||
|
|
||||||
import InstanceActionBar from '../../InstanceActionBar.vue';
|
import InstanceActionBar from '../../InstanceActionBar.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const EditNoteAndMemoDialog = defineAsyncComponent(() => import('./EditNoteAndMemoDialog.vue'));
|
const EditNoteAndMemoDialog = defineAsyncComponent(() => import('./EditNoteAndMemoDialog.vue'));
|
||||||
|
|
||||||
@@ -518,8 +520,8 @@
|
|||||||
const { bioLanguage, translationApi, translationApiType } = storeToRefs(useAdvancedSettingsStore());
|
const { bioLanguage, translationApi, translationApiType } = storeToRefs(useAdvancedSettingsStore());
|
||||||
const { translateText } = useAdvancedSettingsStore();
|
const { translateText } = useAdvancedSettingsStore();
|
||||||
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
const { userDialog, currentUser } = storeToRefs(useUserStore());
|
||||||
const { showUserDialog, toggleSharedConnectionsOptOut, toggleDiscordFriendsOptOut } = useUserStore();
|
const { toggleSharedConnectionsOptOut, toggleDiscordFriendsOptOut } = useUserStore();
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
const { showGroupDialog } = useGroupStore();
|
const { showGroupDialog } = useGroupStore();
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|||||||
@@ -73,12 +73,13 @@
|
|||||||
import { useUserStore } from '../../../stores';
|
import { useUserStore } from '../../../stores';
|
||||||
import { userDialogMutualFriendSortingOptions } from '../../../shared/constants';
|
import { userDialogMutualFriendSortingOptions } from '../../../shared/constants';
|
||||||
import { userRequest } from '../../../api';
|
import { userRequest } from '../../../api';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { userDialog, currentUser } = storeToRefs(userStore);
|
const { userDialog, currentUser } = storeToRefs(userStore);
|
||||||
const { cachedUsers, showUserDialog } = userStore;
|
const { cachedUsers } = userStore;
|
||||||
|
|
||||||
const { selectedKey: userDialogMutualFriendSortingKey, selectByKey: setUserDialogMutualFriendSortingByKey } =
|
const { selectedKey: userDialogMutualFriendSortingKey, selectByKey: setUserDialogMutualFriendSortingByKey } =
|
||||||
useOptionKeySelect(
|
useOptionKeySelect(
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useUserStore, useWorldStore } from '../../../stores';
|
import { useUserStore, useWorldStore } from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/';
|
import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/';
|
||||||
import { queryRequest } from '../../../api';
|
import { queryRequest } from '../../../api';
|
||||||
import { useOptionKeySelect } from '../../../composables/useOptionKeySelect';
|
import { useOptionKeySelect } from '../../../composables/useOptionKeySelect';
|
||||||
@@ -94,7 +95,7 @@
|
|||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { userDialog, currentUser } = storeToRefs(userStore);
|
const { userDialog, currentUser } = storeToRefs(userStore);
|
||||||
const { cachedWorlds, showWorldDialog } = useWorldStore();
|
const { cachedWorlds } = useWorldStore();
|
||||||
|
|
||||||
const userDialogWorldsRequestId = ref(0);
|
const userDialogWorldsRequestId = ref(0);
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useWorldStore } from '../../../stores';
|
import { useWorldStore } from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { worldRequest } from '../../../api';
|
import { worldRequest } from '../../../api';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -133,7 +134,7 @@
|
|||||||
|
|
||||||
const emit = defineEmits(['update:isSetWorldTagsDialogVisible']);
|
const emit = defineEmits(['update:isSetWorldTagsDialogVisible']);
|
||||||
|
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|||||||
@@ -395,6 +395,7 @@
|
|||||||
useUserStore,
|
useUserStore,
|
||||||
useWorldStore
|
useWorldStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -412,15 +413,16 @@
|
|||||||
import ImageCropDialog from '../ImageCropDialog.vue';
|
import ImageCropDialog from '../ImageCropDialog.vue';
|
||||||
import WorldDialogInfoTab from './WorldDialogInfoTab.vue';
|
import WorldDialogInfoTab from './WorldDialogInfoTab.vue';
|
||||||
import WorldDialogInstancesTab from './WorldDialogInstancesTab.vue';
|
import WorldDialogInstancesTab from './WorldDialogInstancesTab.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const SetWorldTagsDialog = defineAsyncComponent(() => import('./SetWorldTagsDialog.vue'));
|
const SetWorldTagsDialog = defineAsyncComponent(() => import('./SetWorldTagsDialog.vue'));
|
||||||
const WorldAllowedDomainsDialog = defineAsyncComponent(() => import('./WorldAllowedDomainsDialog.vue'));
|
const WorldAllowedDomainsDialog = defineAsyncComponent(() => import('./WorldAllowedDomainsDialog.vue'));
|
||||||
const NewInstanceDialog = defineAsyncComponent(() => import('../NewInstanceDialog.vue'));
|
const NewInstanceDialog = defineAsyncComponent(() => import('../NewInstanceDialog.vue'));
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser, userDialog } = storeToRefs(useUserStore());
|
const { currentUser, userDialog } = storeToRefs(useUserStore());
|
||||||
const { worldDialog } = storeToRefs(useWorldStore());
|
const { worldDialog } = storeToRefs(useWorldStore());
|
||||||
const { cachedWorlds, showWorldDialog } = useWorldStore();
|
const { cachedWorlds } = useWorldStore();
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
const { canOpenInstanceInGame } = useInviteStore();
|
const { canOpenInstanceInGame } = useInviteStore();
|
||||||
const { showFavoriteDialog } = useFavoriteStore();
|
const { showFavoriteDialog } = useFavoriteStore();
|
||||||
|
|||||||
@@ -118,11 +118,12 @@
|
|||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
|
|
||||||
import InstanceActionBar from '../../InstanceActionBar.vue';
|
import InstanceActionBar from '../../InstanceActionBar.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { isAgeGatedInstancesVisible } = storeToRefs(useAppearanceSettingsStore());
|
const { isAgeGatedInstancesVisible } = storeToRefs(useAppearanceSettingsStore());
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
const { worldDialog } = storeToRefs(useWorldStore());
|
const { worldDialog } = storeToRefs(useWorldStore());
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
import { AppDebug } from '../service/appConfig';
|
import { AppDebug } from '../service/appConfig';
|
||||||
import { useAdvancedSettingsStore } from '../stores/settings/advanced';
|
import { useAdvancedSettingsStore } from '../stores/settings/advanced';
|
||||||
@@ -17,7 +17,7 @@ export async function runHandleAutoLoginFlow({
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const advancedSettingsStore = useAdvancedSettingsStore();
|
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||||
const { t } = useI18n();
|
const t = i18n.global.t;
|
||||||
|
|
||||||
if (authStore.attemptingAutoLogin) {
|
if (authStore.attemptingAutoLogin) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
import Noty from 'noty';
|
import Noty from 'noty';
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ import { useAuthStore } from '../stores/auth';
|
|||||||
import { useNotificationStore } from '../stores/notification';
|
import { useNotificationStore } from '../stores/notification';
|
||||||
import { useUpdateLoopStore } from '../stores/updateLoop';
|
import { useUpdateLoopStore } from '../stores/updateLoop';
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { applyCurrentUser } from './userCoordinator';
|
||||||
import { watchState } from '../service/watchState';
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
import configRepository from '../service/config';
|
import configRepository from '../service/config';
|
||||||
@@ -21,7 +22,7 @@ export async function runLogoutFlow() {
|
|||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const notificationStore = useNotificationStore();
|
const notificationStore = useNotificationStore();
|
||||||
const { t } = useI18n();
|
const t = i18n.global.t;
|
||||||
|
|
||||||
if (watchState.isLoggedIn) {
|
if (watchState.isLoggedIn) {
|
||||||
new Noty({
|
new Noty({
|
||||||
@@ -56,6 +57,6 @@ export function runLoginSuccessFlow(json) {
|
|||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
updateLoopStore.setNextCurrentUserRefresh(420); // 7mins
|
updateLoopStore.setNextCurrentUserRefresh(420); // 7mins
|
||||||
userStore.applyCurrentUser(json);
|
applyCurrentUser(json);
|
||||||
initWebsocket();
|
initWebsocket();
|
||||||
}
|
}
|
||||||
|
|||||||
649
src/coordinators/avatarCoordinator.js
Normal file
649
src/coordinators/avatarCoordinator.js
Normal file
@@ -0,0 +1,649 @@
|
|||||||
|
import { nextTick } from 'vue';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createDefaultAvatarRef,
|
||||||
|
extractFileId,
|
||||||
|
getAvailablePlatforms,
|
||||||
|
getBundleDateSize,
|
||||||
|
getPlatformInfo,
|
||||||
|
replaceBioSymbols,
|
||||||
|
sanitizeEntityJson,
|
||||||
|
storeAvatarImage
|
||||||
|
} from '../shared/utils';
|
||||||
|
import { avatarRequest, miscRequest, queryRequest } from '../api';
|
||||||
|
import { AppDebug } from '../service/appConfig';
|
||||||
|
import { database } from '../service/database';
|
||||||
|
import { patchAvatarFromEvent } from '../queries';
|
||||||
|
import { processBulk } from '../service/request';
|
||||||
|
import { applyFavorite } from './favoriteCoordinator';
|
||||||
|
import { refreshUserDialogAvatars, showUserDialog } from './userCoordinator';
|
||||||
|
import { useAdvancedSettingsStore } from '../stores/settings/advanced';
|
||||||
|
import { useAvatarProviderStore } from '../stores/avatarProvider';
|
||||||
|
import { useAvatarStore } from '../stores/avatar';
|
||||||
|
import { useFavoriteStore } from '../stores/favorite';
|
||||||
|
import { useModalStore } from '../stores/modal';
|
||||||
|
import { useUiStore } from '../stores/ui';
|
||||||
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { useVRCXUpdaterStore } from '../stores/vrcxUpdater';
|
||||||
|
|
||||||
|
import webApiService from '../service/webapi';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} json
|
||||||
|
* @returns {object} ref
|
||||||
|
*/
|
||||||
|
export function applyAvatar(json) {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const favoriteStore = useFavoriteStore();
|
||||||
|
|
||||||
|
sanitizeEntityJson(json, ['name', 'description']);
|
||||||
|
let ref = avatarStore.cachedAvatars.get(json.id);
|
||||||
|
if (typeof ref === 'undefined') {
|
||||||
|
ref = createDefaultAvatarRef(json);
|
||||||
|
avatarStore.cachedAvatars.set(ref.id, ref);
|
||||||
|
} else {
|
||||||
|
const { unityPackages } = ref;
|
||||||
|
Object.assign(ref, json);
|
||||||
|
if (
|
||||||
|
json.unityPackages?.length > 0 &&
|
||||||
|
unityPackages.length > 0 &&
|
||||||
|
!json.unityPackages[0].assetUrl
|
||||||
|
) {
|
||||||
|
ref.unityPackages = unityPackages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const listing of ref.publishedListings) {
|
||||||
|
listing.displayName = replaceBioSymbols(listing.displayName);
|
||||||
|
listing.description = replaceBioSymbols(listing.description);
|
||||||
|
}
|
||||||
|
applyFavorite('avatar', ref.id);
|
||||||
|
if (favoriteStore.localAvatarFavoritesList.includes(ref.id)) {
|
||||||
|
const avatarRef = ref;
|
||||||
|
favoriteStore.syncLocalAvatarFavoriteRef(avatarRef);
|
||||||
|
|
||||||
|
// update db cache
|
||||||
|
database.addAvatarToCache(avatarRef);
|
||||||
|
}
|
||||||
|
patchAvatarFromEvent(ref);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} avatarId
|
||||||
|
* @param options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function showAvatarDialog(avatarId, options = {}) {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const uiStore = useUiStore();
|
||||||
|
const favoriteStore = useFavoriteStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
const D = avatarStore.avatarDialog;
|
||||||
|
const forceRefresh = Boolean(options?.forceRefresh);
|
||||||
|
const isMainDialogOpen = uiStore.openDialog({
|
||||||
|
type: 'avatar',
|
||||||
|
id: avatarId
|
||||||
|
});
|
||||||
|
D.visible = true;
|
||||||
|
if (isMainDialogOpen && D.id === avatarId && !forceRefresh) {
|
||||||
|
uiStore.setDialogCrumbLabel('avatar', D.id, D.ref?.name || D.id);
|
||||||
|
nextTick(() => (D.loading = false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
D.loading = true;
|
||||||
|
D.id = avatarId;
|
||||||
|
D.inCache = false;
|
||||||
|
D.cacheSize = '';
|
||||||
|
D.cacheLocked = false;
|
||||||
|
D.cachePath = '';
|
||||||
|
D.fileAnalysis = {};
|
||||||
|
D.isQuestFallback = false;
|
||||||
|
D.isPC = false;
|
||||||
|
D.isQuest = false;
|
||||||
|
D.isIos = false;
|
||||||
|
D.hasImposter = false;
|
||||||
|
D.imposterVersion = '';
|
||||||
|
D.platformInfo = {};
|
||||||
|
D.galleryImages = [];
|
||||||
|
D.galleryLoading = true;
|
||||||
|
D.isFavorite =
|
||||||
|
favoriteStore.getCachedFavoritesByObjectId(avatarId) ||
|
||||||
|
(userStore.isLocalUserVrcPlusSupporter &&
|
||||||
|
favoriteStore.localAvatarFavoritesList.includes(avatarId));
|
||||||
|
D.isBlocked = avatarStore.cachedAvatarModerations.has(avatarId);
|
||||||
|
const ref2 = avatarStore.cachedAvatars.get(avatarId);
|
||||||
|
if (typeof ref2 !== 'undefined') {
|
||||||
|
D.ref = ref2;
|
||||||
|
uiStore.setDialogCrumbLabel('avatar', D.id, D.ref?.name || D.id);
|
||||||
|
nextTick(() => (D.loading = false));
|
||||||
|
}
|
||||||
|
const loadAvatarRequest = forceRefresh
|
||||||
|
? avatarRequest.getAvatar({ avatarId })
|
||||||
|
: queryRequest.fetch('avatar', { avatarId });
|
||||||
|
loadAvatarRequest
|
||||||
|
.then((args) => {
|
||||||
|
const ref = applyAvatar(args.json);
|
||||||
|
D.ref = ref;
|
||||||
|
uiStore.setDialogCrumbLabel(
|
||||||
|
'avatar',
|
||||||
|
D.id,
|
||||||
|
D.ref?.name || D.id
|
||||||
|
);
|
||||||
|
avatarStore.getAvatarGallery(avatarId);
|
||||||
|
avatarStore.updateVRChatAvatarCache();
|
||||||
|
if (/quest/.test(ref.tags)) {
|
||||||
|
D.isQuestFallback = true;
|
||||||
|
}
|
||||||
|
const { isPC, isQuest, isIos } = getAvailablePlatforms(
|
||||||
|
ref.unityPackages
|
||||||
|
);
|
||||||
|
D.isPC = isPC;
|
||||||
|
D.isQuest = isQuest;
|
||||||
|
D.isIos = isIos;
|
||||||
|
D.platformInfo = getPlatformInfo(ref.unityPackages);
|
||||||
|
for (let i = ref.unityPackages.length - 1; i > -1; i--) {
|
||||||
|
const unityPackage = ref.unityPackages[i];
|
||||||
|
if (unityPackage.variant === 'impostor') {
|
||||||
|
D.hasImposter = true;
|
||||||
|
D.imposterVersion = unityPackage.impostorizerVersion;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(D.fileAnalysis).length === 0) {
|
||||||
|
getBundleDateSize(ref);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
D.loading = false;
|
||||||
|
D.id = null;
|
||||||
|
D.visible = false;
|
||||||
|
uiStore.jumpBackDialogCrumb();
|
||||||
|
toast.error(t('message.api_handler.avatar_private_or_deleted'));
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
nextTick(() => (D.loading = false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function getAvatarHistory() {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const historyArray = await database.getAvatarHistory(
|
||||||
|
userStore.currentUser.id
|
||||||
|
);
|
||||||
|
for (let i = 0; i < historyArray.length; i++) {
|
||||||
|
const avatar = historyArray[i];
|
||||||
|
if (avatar.authorId === userStore.currentUser.id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
applyAvatar(avatar);
|
||||||
|
}
|
||||||
|
avatarStore.avatarHistory = historyArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} avatarId
|
||||||
|
*/
|
||||||
|
export function addAvatarToHistory(avatarId) {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
avatarRequest
|
||||||
|
.getAvatar({ avatarId })
|
||||||
|
.then((args) => {
|
||||||
|
const ref = applyAvatar(args.json);
|
||||||
|
|
||||||
|
database.addAvatarToCache(ref);
|
||||||
|
database.addAvatarToHistory(ref.id);
|
||||||
|
|
||||||
|
if (ref.authorId === userStore.currentUser.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const historyArray = avatarStore.avatarHistory;
|
||||||
|
for (let i = 0; i < historyArray.length; ++i) {
|
||||||
|
if (historyArray[i].id === ref.id) {
|
||||||
|
historyArray.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarStore.avatarHistory.unshift(ref);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Failed to add avatar to history:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function promptClearAvatarHistory() {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const modalStore = useModalStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
modalStore
|
||||||
|
.confirm({
|
||||||
|
description: t('confirm.clear_avatar_history'),
|
||||||
|
title: 'Confirm'
|
||||||
|
})
|
||||||
|
.then(({ ok }) => {
|
||||||
|
if (!ok) return;
|
||||||
|
avatarStore.clearAvatarHistory();
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} imageUrl
|
||||||
|
* @returns {Promise<object>}
|
||||||
|
*/
|
||||||
|
export async function getAvatarName(imageUrl) {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
|
||||||
|
const fileId = extractFileId(imageUrl);
|
||||||
|
if (!fileId) {
|
||||||
|
return {
|
||||||
|
ownerId: '',
|
||||||
|
avatarName: '-'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (avatarStore.cachedAvatarNames.has(fileId)) {
|
||||||
|
return avatarStore.cachedAvatarNames.get(fileId);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const args = await miscRequest.getFile({ fileId });
|
||||||
|
return storeAvatarImage(args, avatarStore.cachedAvatarNames);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to get avatar images:', error);
|
||||||
|
return {
|
||||||
|
ownerId: '',
|
||||||
|
avatarName: '-'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @param search
|
||||||
|
*/
|
||||||
|
export async function lookupAvatars(type, search) {
|
||||||
|
const avatarProviderStore = useAvatarProviderStore();
|
||||||
|
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
||||||
|
|
||||||
|
const avatars = new Map();
|
||||||
|
if (type === 'search') {
|
||||||
|
try {
|
||||||
|
const url = `${
|
||||||
|
avatarProviderStore.avatarRemoteDatabaseProvider
|
||||||
|
}?${type}=${encodeURIComponent(search)}&n=5000`;
|
||||||
|
const response = await webApiService.execute({
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Referer: 'https://vrcx.app',
|
||||||
|
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const json = JSON.parse(response.data);
|
||||||
|
if (AppDebug.debugWebRequests) {
|
||||||
|
console.log(url, json, response);
|
||||||
|
}
|
||||||
|
if (response.status === 200 && typeof json === 'object') {
|
||||||
|
json.forEach((avatar) => {
|
||||||
|
if (!avatars.has(avatar.Id)) {
|
||||||
|
const ref = {
|
||||||
|
authorId: '',
|
||||||
|
authorName: '',
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
id: '',
|
||||||
|
imageUrl: '',
|
||||||
|
thumbnailImageUrl: '',
|
||||||
|
created_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
updated_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
releaseStatus: 'public',
|
||||||
|
...avatar
|
||||||
|
};
|
||||||
|
avatars.set(ref.id, ref);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(`Error: ${response.data}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const msg = `Avatar search failed for ${search} with ${avatarProviderStore.avatarRemoteDatabaseProvider}\n${err}`;
|
||||||
|
console.error(msg);
|
||||||
|
toast.error(msg);
|
||||||
|
}
|
||||||
|
} else if (type === 'authorId') {
|
||||||
|
const length =
|
||||||
|
avatarProviderStore.avatarRemoteDatabaseProviderList.length;
|
||||||
|
for (let i = 0; i < length; ++i) {
|
||||||
|
const url =
|
||||||
|
avatarProviderStore.avatarRemoteDatabaseProviderList[i];
|
||||||
|
const avatarArray = await lookupAvatarsByAuthor(url, search);
|
||||||
|
avatarArray.forEach((avatar) => {
|
||||||
|
if (!avatars.has(avatar.id)) {
|
||||||
|
avatars.set(avatar.id, avatar);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return avatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param authorId
|
||||||
|
* @param fileId
|
||||||
|
*/
|
||||||
|
export async function lookupAvatarByImageFileId(authorId, fileId) {
|
||||||
|
const avatarProviderStore = useAvatarProviderStore();
|
||||||
|
|
||||||
|
for (const providerUrl of avatarProviderStore.avatarRemoteDatabaseProviderList) {
|
||||||
|
const avatar = await lookupAvatarByFileId(providerUrl, fileId);
|
||||||
|
if (avatar?.id) {
|
||||||
|
return avatar.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const providerUrl of avatarProviderStore.avatarRemoteDatabaseProviderList) {
|
||||||
|
const avatarArray = await lookupAvatarsByAuthor(
|
||||||
|
providerUrl,
|
||||||
|
authorId
|
||||||
|
);
|
||||||
|
for (const avatar of avatarArray) {
|
||||||
|
if (extractFileId(avatar.imageUrl) === fileId) {
|
||||||
|
return avatar.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param providerUrl
|
||||||
|
* @param fileId
|
||||||
|
*/
|
||||||
|
async function lookupAvatarByFileId(providerUrl, fileId) {
|
||||||
|
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = `${providerUrl}?fileId=${encodeURIComponent(fileId)}`;
|
||||||
|
const response = await webApiService.execute({
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Referer: 'https://vrcx.app',
|
||||||
|
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const json = JSON.parse(response.data);
|
||||||
|
if (AppDebug.debugWebRequests) {
|
||||||
|
console.log(url, json, response);
|
||||||
|
}
|
||||||
|
if (response.status === 200 && typeof json === 'object') {
|
||||||
|
const ref = {
|
||||||
|
authorId: '',
|
||||||
|
authorName: '',
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
id: '',
|
||||||
|
imageUrl: '',
|
||||||
|
thumbnailImageUrl: '',
|
||||||
|
created_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
updated_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
releaseStatus: 'public',
|
||||||
|
...json
|
||||||
|
};
|
||||||
|
return ref;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// ignore errors for now, not all providers support this lookup type
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param providerUrl
|
||||||
|
* @param authorId
|
||||||
|
*/
|
||||||
|
async function lookupAvatarsByAuthor(providerUrl, authorId) {
|
||||||
|
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
||||||
|
|
||||||
|
const avatars = [];
|
||||||
|
if (!providerUrl || !authorId) {
|
||||||
|
return avatars;
|
||||||
|
}
|
||||||
|
const url = `${providerUrl}?authorId=${encodeURIComponent(authorId)}`;
|
||||||
|
try {
|
||||||
|
const response = await webApiService.execute({
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Referer: 'https://vrcx.app',
|
||||||
|
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const json = JSON.parse(response.data);
|
||||||
|
if (AppDebug.debugWebRequests) {
|
||||||
|
console.log(url, json, response);
|
||||||
|
}
|
||||||
|
if (response.status === 200 && typeof json === 'object') {
|
||||||
|
json.forEach((avatar) => {
|
||||||
|
const ref = {
|
||||||
|
authorId: '',
|
||||||
|
authorName: '',
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
id: '',
|
||||||
|
imageUrl: '',
|
||||||
|
thumbnailImageUrl: '',
|
||||||
|
created_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
updated_at: '0001-01-01T00:00:00.0000000Z',
|
||||||
|
releaseStatus: 'public',
|
||||||
|
...avatar
|
||||||
|
};
|
||||||
|
avatars.push(ref);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(`Error: ${response.data}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const msg = `Avatar lookup failed for ${authorId} with ${url}\n${err}`;
|
||||||
|
console.error(msg);
|
||||||
|
toast.error(msg);
|
||||||
|
}
|
||||||
|
return avatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export function selectAvatarWithConfirmation(id) {
|
||||||
|
const modalStore = useModalStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
modalStore
|
||||||
|
.confirm({
|
||||||
|
description: t('confirm.select_avatar'),
|
||||||
|
title: 'Confirm'
|
||||||
|
})
|
||||||
|
.then(({ ok }) => {
|
||||||
|
if (!ok) return;
|
||||||
|
selectAvatarWithoutConfirmation(id);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
export async function selectAvatarWithoutConfirmation(id) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
if (userStore.currentUser.currentAvatar === id) {
|
||||||
|
toast.info('Avatar already selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return avatarRequest
|
||||||
|
.selectAvatar({
|
||||||
|
avatarId: id
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
toast.success('Avatar changed');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
*/
|
||||||
|
export function checkAvatarCache(fileId) {
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
|
||||||
|
let avatarId = '';
|
||||||
|
for (let ref of avatarStore.cachedAvatars.values()) {
|
||||||
|
if (extractFileId(ref.imageUrl) === fileId) {
|
||||||
|
avatarId = ref.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return avatarId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param fileId
|
||||||
|
* @param ownerUserId
|
||||||
|
*/
|
||||||
|
export async function checkAvatarCacheRemote(fileId, ownerUserId) {
|
||||||
|
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||||
|
const avatarStore = useAvatarStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
if (advancedSettingsStore.avatarRemoteDatabase) {
|
||||||
|
try {
|
||||||
|
toast.dismiss(avatarStore.loadingToastId);
|
||||||
|
avatarStore.loadingToastId = toast.loading(
|
||||||
|
t('message.avatar_lookup.loading')
|
||||||
|
);
|
||||||
|
const avatarId = await lookupAvatarByImageFileId(
|
||||||
|
ownerUserId,
|
||||||
|
fileId
|
||||||
|
);
|
||||||
|
return avatarId;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to lookup avatar by image file id:', err);
|
||||||
|
} finally {
|
||||||
|
toast.dismiss(avatarStore.loadingToastId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param refUserId
|
||||||
|
* @param ownerUserId
|
||||||
|
* @param currentAvatarImageUrl
|
||||||
|
*/
|
||||||
|
export async function showAvatarAuthorDialog(
|
||||||
|
refUserId,
|
||||||
|
ownerUserId,
|
||||||
|
currentAvatarImageUrl
|
||||||
|
) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
const fileId = extractFileId(currentAvatarImageUrl);
|
||||||
|
if (!fileId) {
|
||||||
|
toast.error(t('message.avatar_lookup.failed'));
|
||||||
|
} else if (refUserId === userStore.currentUser.id) {
|
||||||
|
showAvatarDialog(userStore.currentUser.currentAvatar);
|
||||||
|
} else {
|
||||||
|
let avatarId = checkAvatarCache(fileId);
|
||||||
|
let avatarInfo;
|
||||||
|
if (!avatarId) {
|
||||||
|
avatarInfo = await getAvatarName(currentAvatarImageUrl);
|
||||||
|
if (avatarInfo.ownerId === userStore.currentUser.id) {
|
||||||
|
await refreshUserDialogAvatars(fileId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!avatarId) {
|
||||||
|
avatarId = await checkAvatarCacheRemote(fileId, ownerUserId);
|
||||||
|
}
|
||||||
|
if (!avatarId) {
|
||||||
|
if (ownerUserId === refUserId) {
|
||||||
|
toast.warning(
|
||||||
|
t('message.avatar_lookup.private_or_not_found')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
toast.warning(t('message.avatar_lookup.not_found'));
|
||||||
|
showUserDialog(avatarInfo.ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (avatarId) {
|
||||||
|
showAvatarDialog(avatarId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param avatarId
|
||||||
|
*/
|
||||||
|
export function addAvatarWearTime(avatarId) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
if (!userStore.currentUser.$previousAvatarSwapTime || !avatarId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const timeSpent =
|
||||||
|
Date.now() - userStore.currentUser.$previousAvatarSwapTime;
|
||||||
|
database.addAvatarTimeSpent(avatarId, timeSpent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preload all own avatars into cache at startup for global search.
|
||||||
|
*/
|
||||||
|
export async function preloadOwnAvatars() {
|
||||||
|
const params = {
|
||||||
|
n: 50,
|
||||||
|
offset: 0,
|
||||||
|
sort: 'updated',
|
||||||
|
order: 'descending',
|
||||||
|
releaseStatus: 'all',
|
||||||
|
user: 'me'
|
||||||
|
};
|
||||||
|
await processBulk({
|
||||||
|
fn: avatarRequest.getAvatars,
|
||||||
|
N: -1,
|
||||||
|
params,
|
||||||
|
handle: (args) => {
|
||||||
|
for (const json of args.json) {
|
||||||
|
applyAvatar(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ import { toast } from 'vue-sonner';
|
|||||||
import { useFavoriteStore } from '../stores/favorite';
|
import { useFavoriteStore } from '../stores/favorite';
|
||||||
import { useAppearanceSettingsStore } from '../stores/settings/appearance';
|
import { useAppearanceSettingsStore } from '../stores/settings/appearance';
|
||||||
import { useAvatarStore } from '../stores/avatar';
|
import { useAvatarStore } from '../stores/avatar';
|
||||||
|
import { applyAvatar } from './avatarCoordinator';
|
||||||
import { useFriendStore } from '../stores/friend';
|
import { useFriendStore } from '../stores/friend';
|
||||||
import { useGeneralSettingsStore } from '../stores/settings/general';
|
import { useGeneralSettingsStore } from '../stores/settings/general';
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
import { useWorldStore } from '../stores/world';
|
import { useWorldStore } from '../stores/world';
|
||||||
|
import { applyWorld } from './worldCoordinator';
|
||||||
import { runUpdateFriendFlow } from './friendPresenceCoordinator';
|
import { runUpdateFriendFlow } from './friendPresenceCoordinator';
|
||||||
import { avatarRequest, favoriteRequest, queryRequest } from '../api';
|
import { avatarRequest, favoriteRequest, queryRequest } from '../api';
|
||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
@@ -177,7 +179,7 @@ export function handleFavoriteWorldList(args) {
|
|||||||
if (json.id === '???') {
|
if (json.id === '???') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
worldStore.applyWorld(json);
|
applyWorld(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ export function handleFavoriteAvatarList(args) {
|
|||||||
if (json.releaseStatus === 'hidden') {
|
if (json.releaseStatus === 'hidden') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
avatarStore.applyAvatar(json);
|
applyAvatar(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,7 +654,7 @@ export async function getLocalWorldFavorites() {
|
|||||||
for (let i = 0; i < worldCache.length; ++i) {
|
for (let i = 0; i < worldCache.length; ++i) {
|
||||||
const ref = worldCache[i];
|
const ref = worldCache[i];
|
||||||
if (!worldStore.cachedWorlds.has(ref.id)) {
|
if (!worldStore.cachedWorlds.has(ref.id)) {
|
||||||
worldStore.applyWorld(ref);
|
applyWorld(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,7 +911,7 @@ export async function getLocalAvatarFavorites() {
|
|||||||
for (let i = 0; i < avatarCache.length; ++i) {
|
for (let i = 0; i < avatarCache.length; ++i) {
|
||||||
const ref = avatarCache[i];
|
const ref = avatarCache[i];
|
||||||
if (!avatarStore.cachedAvatars.has(ref.id)) {
|
if (!avatarStore.cachedAvatars.has(ref.id)) {
|
||||||
avatarStore.applyAvatar(ref);
|
applyAvatar(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useAuthStore } from '../stores/auth';
|
|||||||
import { useFriendStore } from '../stores/friend';
|
import { useFriendStore } from '../stores/friend';
|
||||||
import { useUpdateLoopStore } from '../stores/updateLoop';
|
import { useUpdateLoopStore } from '../stores/updateLoop';
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { getCurrentUser } from './userCoordinator';
|
||||||
import { watchState } from '../service/watchState';
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
import configRepository from '../service/config';
|
import configRepository from '../service/config';
|
||||||
@@ -21,7 +22,7 @@ export async function runRefreshFriendsListFlow() {
|
|||||||
|
|
||||||
// If we just got user less then 2 min before code call, don't call it again
|
// If we just got user less then 2 min before code call, don't call it again
|
||||||
if (updateLoopStore.nextCurrentUserRefresh < 300) {
|
if (updateLoopStore.nextCurrentUserRefresh < 300) {
|
||||||
await userStore.getCurrentUser();
|
await getCurrentUser();
|
||||||
}
|
}
|
||||||
await friendStore.refreshFriends();
|
await friendStore.refreshFriends();
|
||||||
reconnectWebSocket();
|
reconnectWebSocket();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
import { useAdvancedSettingsStore } from '../stores/settings/advanced';
|
import { useAdvancedSettingsStore } from '../stores/settings/advanced';
|
||||||
import { useAvatarStore } from '../stores/avatar';
|
import { useAvatarStore } from '../stores/avatar';
|
||||||
|
import { addAvatarWearTime } from './avatarCoordinator';
|
||||||
import { useGameLogStore } from '../stores/gameLog';
|
import { useGameLogStore } from '../stores/gameLog';
|
||||||
import { useGameStore } from '../stores/game';
|
import { useGameStore } from '../stores/game';
|
||||||
import { useInstanceStore } from '../stores/instance';
|
import { useInstanceStore } from '../stores/instance';
|
||||||
@@ -47,7 +48,7 @@ export async function runGameRunningChangedFlow(isGameRunning) {
|
|||||||
runAutoVRChatCacheManagementFlow();
|
runAutoVRChatCacheManagementFlow();
|
||||||
runCheckIfGameCrashedFlow();
|
runCheckIfGameCrashedFlow();
|
||||||
updateLoopStore.setIpcTimeout(0);
|
updateLoopStore.setIpcTimeout(0);
|
||||||
avatarStore.addAvatarWearTime(userStore.currentUser.currentAvatar);
|
addAvatarWearTime(userStore.currentUser.currentAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
runLastLocationResetFlow();
|
runLastLocationResetFlow();
|
||||||
|
|||||||
957
src/coordinators/groupCoordinator.js
Normal file
957
src/coordinators/groupCoordinator.js
Normal file
@@ -0,0 +1,957 @@
|
|||||||
|
import { nextTick } from 'vue';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
|
import {
|
||||||
|
convertFileUrlToImageUrl,
|
||||||
|
createDefaultGroupRef,
|
||||||
|
sanitizeEntityJson,
|
||||||
|
replaceBioSymbols
|
||||||
|
} from '../shared/utils';
|
||||||
|
import { groupRequest, instanceRequest, queryRequest } from '../api';
|
||||||
|
import { database } from '../service/database';
|
||||||
|
import { groupDialogFilterOptions } from '../shared/constants/';
|
||||||
|
import { patchGroupFromEvent } from '../queries';
|
||||||
|
import { useGameStore } from '../stores/game';
|
||||||
|
import { useInstanceStore } from '../stores/instance';
|
||||||
|
import { useModalStore } from '../stores/modal';
|
||||||
|
import { useNotificationStore } from '../stores/notification';
|
||||||
|
import { useUiStore } from '../stores/ui';
|
||||||
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { useGroupStore } from '../stores/group';
|
||||||
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
|
import configRepository from '../service/config';
|
||||||
|
|
||||||
|
import * as workerTimers from 'worker-timers';
|
||||||
|
|
||||||
|
// ─── Internal helpers (not exported) ─────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ref
|
||||||
|
*/
|
||||||
|
function applyGroupLanguage(ref) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
ref.$languages = [];
|
||||||
|
const { languages } = ref;
|
||||||
|
if (!languages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const language of languages) {
|
||||||
|
const value = userStore.subsetOfLanguages[language];
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ref.$languages.push({
|
||||||
|
key: language,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Core entity application ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} json
|
||||||
|
* @returns {object} ref
|
||||||
|
*/
|
||||||
|
export function applyGroup(json) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
let ref = groupStore.cachedGroups.get(json.id);
|
||||||
|
sanitizeEntityJson(json, ['rules', 'name', 'description']);
|
||||||
|
if (typeof ref === 'undefined') {
|
||||||
|
ref = createDefaultGroupRef(json);
|
||||||
|
groupStore.cachedGroups.set(ref.id, ref);
|
||||||
|
} else {
|
||||||
|
if (groupStore.currentUserGroups.has(ref.id)) {
|
||||||
|
// compare group props
|
||||||
|
if (
|
||||||
|
ref.ownerId &&
|
||||||
|
json.ownerId &&
|
||||||
|
ref.ownerId !== json.ownerId
|
||||||
|
) {
|
||||||
|
// owner changed
|
||||||
|
groupOwnerChange(json, ref.ownerId, json.ownerId);
|
||||||
|
}
|
||||||
|
if (ref.name && json.name && ref.name !== json.name) {
|
||||||
|
// name changed
|
||||||
|
groupChange(
|
||||||
|
json,
|
||||||
|
`Name changed from ${ref.name} to ${json.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ref.myMember?.roleIds && json.myMember?.roleIds) {
|
||||||
|
const oldRoleIds = ref.myMember.roleIds;
|
||||||
|
const newRoleIds = json.myMember.roleIds;
|
||||||
|
if (
|
||||||
|
oldRoleIds.length !== newRoleIds.length ||
|
||||||
|
!oldRoleIds.every(
|
||||||
|
(value, index) => value === newRoleIds[index]
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// roleIds changed
|
||||||
|
groupRoleChange(
|
||||||
|
json,
|
||||||
|
ref.roles,
|
||||||
|
json.roles,
|
||||||
|
oldRoleIds,
|
||||||
|
newRoleIds
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.myMember) {
|
||||||
|
if (typeof json.myMember.roleIds === 'undefined') {
|
||||||
|
// keep roleIds
|
||||||
|
json.myMember.roleIds = ref.myMember.roleIds;
|
||||||
|
}
|
||||||
|
Object.assign(ref.myMember, json.myMember);
|
||||||
|
}
|
||||||
|
Object.assign(ref, json);
|
||||||
|
}
|
||||||
|
// update myMember without fetching member
|
||||||
|
if (typeof json.memberVisibility !== 'undefined') {
|
||||||
|
ref.myMember.visibility = json.memberVisibility;
|
||||||
|
}
|
||||||
|
if (typeof json.isRepresenting !== 'undefined') {
|
||||||
|
ref.myMember.isRepresenting = json.isRepresenting;
|
||||||
|
}
|
||||||
|
if (typeof json.membershipStatus !== 'undefined') {
|
||||||
|
ref.myMember.membershipStatus = json.membershipStatus;
|
||||||
|
}
|
||||||
|
if (typeof json.roleIds !== 'undefined') {
|
||||||
|
ref.myMember.roleIds = json.roleIds;
|
||||||
|
}
|
||||||
|
ref.$url = `https://vrc.group/${ref.shortCode}.${ref.discriminator}`;
|
||||||
|
applyGroupLanguage(ref);
|
||||||
|
|
||||||
|
const currentUserGroupRef = groupStore.currentUserGroups.get(ref.id);
|
||||||
|
if (currentUserGroupRef) {
|
||||||
|
groupStore.currentUserGroups.set(ref.id, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
const D = groupStore.groupDialog;
|
||||||
|
if (D.visible && D.id === ref.id) {
|
||||||
|
D.inGroup = ref.membershipStatus === 'member';
|
||||||
|
D.ref = ref;
|
||||||
|
}
|
||||||
|
patchGroupFromEvent(ref);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} json
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function applyGroupMember(json) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
let ref;
|
||||||
|
if (typeof json?.user !== 'undefined') {
|
||||||
|
if (json.userId === userStore.currentUser.id) {
|
||||||
|
json.user = userStore.currentUser;
|
||||||
|
json.$displayName = userStore.currentUser.displayName;
|
||||||
|
} else {
|
||||||
|
ref = userStore.cachedUsers.get(json.user.id);
|
||||||
|
if (typeof ref !== 'undefined') {
|
||||||
|
json.user = ref;
|
||||||
|
json.$displayName = ref.displayName;
|
||||||
|
} else {
|
||||||
|
json.$displayName = json.user?.displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update myMember without fetching member
|
||||||
|
if (json?.userId === userStore.currentUser.id) {
|
||||||
|
ref = groupStore.cachedGroups.get(json.groupId);
|
||||||
|
if (typeof ref !== 'undefined') {
|
||||||
|
const newJson = {
|
||||||
|
id: json.groupId,
|
||||||
|
memberVisibility: json.visibility,
|
||||||
|
isRepresenting: json.isRepresenting,
|
||||||
|
isSubscribedToAnnouncements:
|
||||||
|
json.isSubscribedToAnnouncements,
|
||||||
|
joinedAt: json.joinedAt,
|
||||||
|
roleIds: json.roleIds,
|
||||||
|
membershipStatus: json.membershipStatus
|
||||||
|
};
|
||||||
|
applyGroup(newJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Group change notifications ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param ref
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
function groupChange(ref, message) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const notificationStore = useNotificationStore();
|
||||||
|
if (!groupStore.currentUserGroupsInit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// oh the level of cursed for compibility
|
||||||
|
const json = {
|
||||||
|
id: Math.random().toString(36),
|
||||||
|
type: 'groupChange',
|
||||||
|
senderUserId: ref.id,
|
||||||
|
senderUsername: ref.name,
|
||||||
|
imageUrl: ref.iconUrl,
|
||||||
|
details: {
|
||||||
|
imageUrl: ref.iconUrl
|
||||||
|
},
|
||||||
|
message,
|
||||||
|
created_at: new Date().toJSON()
|
||||||
|
};
|
||||||
|
notificationStore.handleNotification({
|
||||||
|
json,
|
||||||
|
params: {
|
||||||
|
notificationId: json.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// delay to wait for json to be assigned to ref
|
||||||
|
workerTimers.setTimeout(() => saveCurrentUserGroups(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object }ref
|
||||||
|
* @param {string} oldUserId
|
||||||
|
* @param {string} newUserId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function groupOwnerChange(ref, oldUserId, newUserId) {
|
||||||
|
const oldUser = await queryRequest.fetch('user', {
|
||||||
|
userId: oldUserId
|
||||||
|
});
|
||||||
|
const newUser = await queryRequest.fetch('user', {
|
||||||
|
userId: newUserId
|
||||||
|
});
|
||||||
|
const oldDisplayName = oldUser?.ref?.displayName;
|
||||||
|
const newDisplayName = newUser?.ref?.displayName;
|
||||||
|
|
||||||
|
groupChange(
|
||||||
|
ref,
|
||||||
|
`Owner changed from ${oldDisplayName} to ${newDisplayName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} ref
|
||||||
|
* @param {Array} oldRoles
|
||||||
|
* @param {Array} newRoles
|
||||||
|
* @param {Array} oldRoleIds
|
||||||
|
* @param {Array} newRoleIds
|
||||||
|
*/
|
||||||
|
function groupRoleChange(ref, oldRoles, newRoles, oldRoleIds, newRoleIds) {
|
||||||
|
// check for removed/added roleIds
|
||||||
|
for (const roleId of oldRoleIds) {
|
||||||
|
if (!newRoleIds.includes(roleId)) {
|
||||||
|
let roleName = '';
|
||||||
|
const role = oldRoles.find(
|
||||||
|
(fineRole) => fineRole.id === roleId
|
||||||
|
);
|
||||||
|
if (role) {
|
||||||
|
roleName = role.name;
|
||||||
|
}
|
||||||
|
groupChange(ref, `Role ${roleName} removed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof newRoles !== 'undefined') {
|
||||||
|
for (const roleId of newRoleIds) {
|
||||||
|
if (!oldRoleIds.includes(roleId)) {
|
||||||
|
let roleName = '';
|
||||||
|
const role = newRoles.find(
|
||||||
|
(fineRole) => fineRole.id === roleId
|
||||||
|
);
|
||||||
|
if (role) {
|
||||||
|
roleName = role.name;
|
||||||
|
}
|
||||||
|
groupChange(ref, `Role ${roleName} added`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Dialog flows ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export function showGroupDialog(groupId, options = {}) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const uiStore = useUiStore();
|
||||||
|
const instanceStore = useInstanceStore();
|
||||||
|
if (!groupId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const forceRefresh = Boolean(options?.forceRefresh);
|
||||||
|
const isMainDialogOpen = uiStore.openDialog({
|
||||||
|
type: 'group',
|
||||||
|
id: groupId
|
||||||
|
});
|
||||||
|
const D = groupStore.groupDialog;
|
||||||
|
D.visible = true;
|
||||||
|
if (isMainDialogOpen && D.id === groupId && !forceRefresh) {
|
||||||
|
uiStore.setDialogCrumbLabel('group', D.id, D.ref?.name || D.id);
|
||||||
|
instanceStore.applyGroupDialogInstances();
|
||||||
|
D.loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
D.loading = true;
|
||||||
|
D.id = groupId;
|
||||||
|
D.inGroup = false;
|
||||||
|
D.ownerDisplayName = '';
|
||||||
|
D.announcement = {};
|
||||||
|
D.posts = [];
|
||||||
|
D.postsFiltered = [];
|
||||||
|
D.instances = [];
|
||||||
|
D.memberRoles = [];
|
||||||
|
D.lastVisit = '';
|
||||||
|
D.memberSearch = '';
|
||||||
|
D.memberSearchResults = [];
|
||||||
|
D.galleries = {};
|
||||||
|
D.members = [];
|
||||||
|
D.memberFilter = groupDialogFilterOptions.everyone;
|
||||||
|
D.calendar = [];
|
||||||
|
const loadGroupRequest = groupRequest.getGroup({
|
||||||
|
groupId,
|
||||||
|
includeRoles: true
|
||||||
|
});
|
||||||
|
|
||||||
|
loadGroupRequest
|
||||||
|
.catch((err) => {
|
||||||
|
D.loading = false;
|
||||||
|
D.id = null;
|
||||||
|
D.visible = false;
|
||||||
|
uiStore.jumpBackDialogCrumb();
|
||||||
|
toast.error(t('message.group.load_failed'));
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
const ref = args.ref || applyGroup(args.json);
|
||||||
|
if (groupId === ref.id) {
|
||||||
|
D.ref = ref;
|
||||||
|
uiStore.setDialogCrumbLabel(
|
||||||
|
'group',
|
||||||
|
D.id,
|
||||||
|
D.ref?.name || D.id
|
||||||
|
);
|
||||||
|
D.inGroup = ref.membershipStatus === 'member';
|
||||||
|
D.ownerDisplayName = ref.ownerId;
|
||||||
|
D.visible = true;
|
||||||
|
D.loading = false;
|
||||||
|
queryRequest
|
||||||
|
.fetch('user', {
|
||||||
|
userId: ref.ownerId
|
||||||
|
})
|
||||||
|
.then((args1) => {
|
||||||
|
D.ownerDisplayName = args1.ref.displayName;
|
||||||
|
});
|
||||||
|
database.getLastGroupVisit(D.ref.name).then((r) => {
|
||||||
|
if (D.id === ref.id) {
|
||||||
|
D.lastVisit = r.created_at;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
instanceStore.applyGroupDialogInstances();
|
||||||
|
getGroupDialogGroup(groupId, ref);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
* @param {object} [existingRef]
|
||||||
|
* @returns { Promise<object> }
|
||||||
|
*/
|
||||||
|
export function getGroupDialogGroup(groupId, existingRef) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const instanceStore = useInstanceStore();
|
||||||
|
const D = groupStore.groupDialog;
|
||||||
|
D.isGetGroupDialogGroupLoading = false;
|
||||||
|
|
||||||
|
const refPromise = existingRef
|
||||||
|
? Promise.resolve({ ref: existingRef })
|
||||||
|
: queryRequest
|
||||||
|
.fetch('group', { groupId, includeRoles: true })
|
||||||
|
.then((args) => ({ ref: applyGroup(args.json), args }));
|
||||||
|
|
||||||
|
return refPromise
|
||||||
|
.catch((err) => {
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
const ref = result.ref;
|
||||||
|
if (D.id === ref.id) {
|
||||||
|
D.loading = false;
|
||||||
|
D.ref = ref;
|
||||||
|
D.inGroup = ref.membershipStatus === 'member';
|
||||||
|
D.memberRoles = [];
|
||||||
|
for (const role of ref.roles) {
|
||||||
|
if (
|
||||||
|
D.ref &&
|
||||||
|
D.ref.myMember &&
|
||||||
|
Array.isArray(D.ref.myMember.roleIds) &&
|
||||||
|
D.ref.myMember.roleIds.includes(role.id)
|
||||||
|
) {
|
||||||
|
D.memberRoles.push(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupStore.getAllGroupPosts({
|
||||||
|
groupId
|
||||||
|
});
|
||||||
|
D.isGetGroupDialogGroupLoading = true;
|
||||||
|
groupRequest
|
||||||
|
.getGroupInstances({
|
||||||
|
groupId
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
if (groupStore.groupDialog.id === args.params.groupId) {
|
||||||
|
instanceStore.applyGroupDialogInstances(
|
||||||
|
args.json.instances
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (const json of args.json.instances) {
|
||||||
|
instanceStore.applyInstance(json);
|
||||||
|
queryRequest
|
||||||
|
.fetch('world', {
|
||||||
|
worldId: json.world.id
|
||||||
|
})
|
||||||
|
.then((args1) => {
|
||||||
|
json.world = args1.ref;
|
||||||
|
});
|
||||||
|
// get queue size etc
|
||||||
|
instanceRequest.getInstance({
|
||||||
|
worldId: json.worldId,
|
||||||
|
instanceId: json.instanceId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
queryRequest
|
||||||
|
.fetch('groupCalendar', { groupId })
|
||||||
|
.then((args) => {
|
||||||
|
if (groupStore.groupDialog.id === args.params.groupId) {
|
||||||
|
D.calendar = args.json.results;
|
||||||
|
for (const event of D.calendar) {
|
||||||
|
Object.assign(event, groupStore.applyGroupEvent(event));
|
||||||
|
// fetch again for isFollowing
|
||||||
|
queryRequest
|
||||||
|
.fetch('groupCalendarEvent', {
|
||||||
|
groupId,
|
||||||
|
eventId: event.id
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
Object.assign(
|
||||||
|
event,
|
||||||
|
groupStore.applyGroupEvent(args.json)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
nextTick(() => (D.isGetGroupDialogGroupLoading = false));
|
||||||
|
return result.args || result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Group lifecycle flows ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} ref
|
||||||
|
*/
|
||||||
|
export function applyPresenceGroups(ref) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
if (!groupStore.currentUserGroupsInit) {
|
||||||
|
// wait for init before diffing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const groups = ref.presence?.groups;
|
||||||
|
if (!groups) {
|
||||||
|
console.error('applyPresenceGroups: invalid groups', ref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (groups.length === 0) {
|
||||||
|
// as it turns out, this is not the most trust worthly source of info
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update group list
|
||||||
|
for (const groupId of groups) {
|
||||||
|
if (!groupStore.currentUserGroups.has(groupId)) {
|
||||||
|
onGroupJoined(groupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const groupId of groupStore.currentUserGroups.keys()) {
|
||||||
|
if (!groups.includes(groupId)) {
|
||||||
|
onGroupLeft(groupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} groupId
|
||||||
|
*/
|
||||||
|
export function onGroupJoined(groupId) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
if (!groupStore.currentUserGroups.has(groupId)) {
|
||||||
|
groupStore.currentUserGroups.set(groupId, {
|
||||||
|
id: groupId,
|
||||||
|
name: '',
|
||||||
|
iconUrl: ''
|
||||||
|
});
|
||||||
|
groupRequest
|
||||||
|
.getGroup({ groupId, includeRoles: true })
|
||||||
|
.then((args) => {
|
||||||
|
applyGroup(args.json);
|
||||||
|
saveCurrentUserGroups();
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} groupId
|
||||||
|
*/
|
||||||
|
export async function onGroupLeft(groupId) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const args = await groupRequest.getGroup({ groupId });
|
||||||
|
const ref = applyGroup(args.json);
|
||||||
|
if (ref.membershipStatus === 'member') {
|
||||||
|
// wtf, not trusting presence
|
||||||
|
console.error(
|
||||||
|
`onGroupLeft: presence lied, still a member of ${groupId}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (groupStore.groupDialog.visible && groupStore.groupDialog.id === groupId) {
|
||||||
|
showGroupDialog(groupId);
|
||||||
|
}
|
||||||
|
if (groupStore.currentUserGroups.has(groupId)) {
|
||||||
|
groupStore.currentUserGroups.delete(groupId);
|
||||||
|
groupChange(ref, 'Left group');
|
||||||
|
|
||||||
|
// delay to wait for json to be assigned to ref
|
||||||
|
workerTimers.setTimeout(() => saveCurrentUserGroups(), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── User group management ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function saveCurrentUserGroups() {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (!groupStore.currentUserGroupsInit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const groups = [];
|
||||||
|
for (const ref of groupStore.currentUserGroups.values()) {
|
||||||
|
groups.push({
|
||||||
|
id: ref.id,
|
||||||
|
name: ref.name,
|
||||||
|
ownerId: ref.ownerId,
|
||||||
|
iconUrl: ref.iconUrl,
|
||||||
|
roles: ref.roles,
|
||||||
|
roleIds: ref.myMember?.roleIds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
configRepository.setString(
|
||||||
|
`VRCX_currentUserGroups_${userStore.currentUser.id}`,
|
||||||
|
JSON.stringify(groups)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param groups
|
||||||
|
*/
|
||||||
|
export async function loadCurrentUserGroups(userId, groups) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const savedGroups = JSON.parse(
|
||||||
|
await configRepository.getString(
|
||||||
|
`VRCX_currentUserGroups_${userId}`,
|
||||||
|
'[]'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
groupStore.cachedGroups.clear();
|
||||||
|
groupStore.currentUserGroups.clear();
|
||||||
|
for (const group of savedGroups) {
|
||||||
|
const json = {
|
||||||
|
id: group.id,
|
||||||
|
name: group.name,
|
||||||
|
iconUrl: group.iconUrl,
|
||||||
|
ownerId: group.ownerId,
|
||||||
|
roles: group.roles,
|
||||||
|
myMember: {
|
||||||
|
roleIds: group.roleIds
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const ref = applyGroup(json);
|
||||||
|
groupStore.currentUserGroups.set(group.id, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groups) {
|
||||||
|
const promises = groups.map(async (groupId) => {
|
||||||
|
const groupRef = groupStore.cachedGroups.get(groupId);
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof groupRef !== 'undefined' &&
|
||||||
|
groupRef.roles?.length > 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`Fetching group with missing roles ${groupId}`);
|
||||||
|
const args = await groupRequest.getGroup({
|
||||||
|
groupId,
|
||||||
|
includeRoles: true
|
||||||
|
});
|
||||||
|
const ref = applyGroup(args.json);
|
||||||
|
groupStore.currentUserGroups.set(groupId, ref);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupStore.currentUserGroupsInit = true;
|
||||||
|
getCurrentUserGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export async function getCurrentUserGroups() {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const args = await groupRequest.getGroups({
|
||||||
|
userId: userStore.currentUser.id
|
||||||
|
});
|
||||||
|
handleGroupList(args);
|
||||||
|
groupStore.currentUserGroups.clear();
|
||||||
|
for (const group of args.json) {
|
||||||
|
const ref = applyGroup(group);
|
||||||
|
if (!groupStore.currentUserGroups.has(group.id)) {
|
||||||
|
groupStore.currentUserGroups.set(group.id, ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const args1 = await groupRequest.getGroupPermissions({
|
||||||
|
userId: userStore.currentUser.id
|
||||||
|
});
|
||||||
|
handleGroupPermissions(args1);
|
||||||
|
saveCurrentUserGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function getCurrentUserRepresentedGroup() {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
return groupRequest
|
||||||
|
.getRepresentedGroup({
|
||||||
|
userId: userStore.currentUser.id
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
handleGroupRepresented(args);
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export async function initUserGroups() {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
updateInGameGroupOrder();
|
||||||
|
loadCurrentUserGroups(
|
||||||
|
userStore.currentUser.id,
|
||||||
|
userStore.currentUser?.presence?.groups
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export async function updateInGameGroupOrder() {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const gameStore = useGameStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
groupStore.inGameGroupOrder = [];
|
||||||
|
try {
|
||||||
|
const json = await gameStore.getVRChatRegistryKey(
|
||||||
|
`VRC_GROUP_ORDER_${userStore.currentUser.id}`
|
||||||
|
);
|
||||||
|
if (!json) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
groupStore.inGameGroupOrder = JSON.parse(json);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Group actions ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
*/
|
||||||
|
export function leaveGroup(groupId) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
groupRequest
|
||||||
|
.leaveGroup({
|
||||||
|
groupId
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
const groupId = args.params.groupId;
|
||||||
|
if (
|
||||||
|
groupStore.groupDialog.visible &&
|
||||||
|
groupStore.groupDialog.id === groupId
|
||||||
|
) {
|
||||||
|
groupStore.groupDialog.inGroup = false;
|
||||||
|
getGroupDialogGroup(groupId);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
userStore.userDialog.visible &&
|
||||||
|
userStore.userDialog.id === userStore.currentUser.id &&
|
||||||
|
userStore.userDialog.representedGroup.id === groupId
|
||||||
|
) {
|
||||||
|
getCurrentUserRepresentedGroup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
*/
|
||||||
|
export function leaveGroupPrompt(groupId) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
const modalStore = useModalStore();
|
||||||
|
modalStore
|
||||||
|
.confirm({
|
||||||
|
description: t('confirm.leave_group'),
|
||||||
|
title: t('confirm.title')
|
||||||
|
})
|
||||||
|
.then(({ ok }) => {
|
||||||
|
if (!ok) return;
|
||||||
|
leaveGroup(groupId);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
* @param visibility
|
||||||
|
*/
|
||||||
|
export function setGroupVisibility(groupId, visibility) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
const userStore = useUserStore();
|
||||||
|
return groupRequest
|
||||||
|
.setGroupMemberProps(userStore.currentUser.id, groupId, {
|
||||||
|
visibility
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
handleGroupMemberProps(args);
|
||||||
|
toast.success(t('message.group.visibility_updated'));
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param groupId
|
||||||
|
* @param subscribe
|
||||||
|
*/
|
||||||
|
export function setGroupSubscription(groupId, subscribe) {
|
||||||
|
const t = i18n.global.t;
|
||||||
|
const userStore = useUserStore();
|
||||||
|
return groupRequest
|
||||||
|
.setGroupMemberProps(userStore.currentUser.id, groupId, {
|
||||||
|
isSubscribedToAnnouncements: subscribe
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
handleGroupMemberProps(args);
|
||||||
|
toast.success(t('message.group.subscription_updated'));
|
||||||
|
return args;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─── Event handlers ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export function handleGroupRepresented(args) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const D = userStore.userDialog;
|
||||||
|
const json = args.json;
|
||||||
|
D.representedGroup = json;
|
||||||
|
D.representedGroup.$thumbnailUrl = convertFileUrlToImageUrl(
|
||||||
|
json.iconUrl
|
||||||
|
);
|
||||||
|
if (!json || !json.isRepresenting) {
|
||||||
|
D.isRepresentedGroupLoading = false;
|
||||||
|
}
|
||||||
|
if (!json.groupId) {
|
||||||
|
// no group
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (args.params.userId !== userStore.currentUser.id) {
|
||||||
|
// not current user, don't apply someone elses myMember
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
json.$memberId = json.id;
|
||||||
|
json.id = json.groupId;
|
||||||
|
applyGroup(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export function handleGroupList(args) {
|
||||||
|
for (const json of args.json) {
|
||||||
|
json.$memberId = json.id;
|
||||||
|
json.id = json.groupId;
|
||||||
|
applyGroup(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export function handleGroupMemberProps(args) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (args.userId === userStore.currentUser.id) {
|
||||||
|
const json = args.json;
|
||||||
|
json.$memberId = json.id;
|
||||||
|
json.id = json.groupId;
|
||||||
|
if (
|
||||||
|
groupStore.groupDialog.visible &&
|
||||||
|
groupStore.groupDialog.id === json.groupId
|
||||||
|
) {
|
||||||
|
groupStore.groupDialog.ref.myMember.visibility = json.visibility;
|
||||||
|
groupStore.groupDialog.ref.myMember.isSubscribedToAnnouncements =
|
||||||
|
json.isSubscribedToAnnouncements;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
userStore.userDialog.visible &&
|
||||||
|
userStore.userDialog.id === userStore.currentUser.id
|
||||||
|
) {
|
||||||
|
getCurrentUserRepresentedGroup();
|
||||||
|
}
|
||||||
|
handleGroupMember({
|
||||||
|
json,
|
||||||
|
params: {
|
||||||
|
groupId: json.groupId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let member;
|
||||||
|
if (groupStore.groupDialog.id === args.json.groupId) {
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < groupStore.groupDialog.members.length; ++i) {
|
||||||
|
member = groupStore.groupDialog.members[i];
|
||||||
|
if (member.userId === args.json.userId) {
|
||||||
|
Object.assign(member, applyGroupMember(args.json));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < groupStore.groupDialog.memberSearchResults.length; ++i) {
|
||||||
|
member = groupStore.groupDialog.memberSearchResults[i];
|
||||||
|
if (member.userId === args.json.userId) {
|
||||||
|
Object.assign(member, applyGroupMember(args.json));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export function handleGroupPermissions(args) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (args.params.userId !== userStore.currentUser.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const json = args.json;
|
||||||
|
for (const groupId in json) {
|
||||||
|
const permissions = json[groupId];
|
||||||
|
const group = groupStore.cachedGroups.get(groupId);
|
||||||
|
if (group) {
|
||||||
|
group.myMember.permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export function handleGroupMember(args) {
|
||||||
|
args.ref = applyGroupMember(args.json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
|
export async function handleGroupUserInstances(args) {
|
||||||
|
const groupStore = useGroupStore();
|
||||||
|
const instanceStore = useInstanceStore();
|
||||||
|
groupStore.groupInstances = [];
|
||||||
|
for (const json of args.json.instances) {
|
||||||
|
if (args.json.fetchedAt) {
|
||||||
|
// tack on fetchedAt
|
||||||
|
json.$fetchedAt = args.json.fetchedAt;
|
||||||
|
}
|
||||||
|
const instanceRef = instanceStore.applyInstance(json);
|
||||||
|
const groupRef = groupStore.cachedGroups.get(json.ownerId);
|
||||||
|
if (typeof groupRef === 'undefined') {
|
||||||
|
if (watchState.isFriendsLoaded) {
|
||||||
|
const args = await groupRequest.getGroup({
|
||||||
|
groupId: json.ownerId
|
||||||
|
});
|
||||||
|
applyGroup(args.json);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
groupStore.groupInstances.push({
|
||||||
|
group: groupRef,
|
||||||
|
instance: instanceRef
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
import { instanceRequest } from '../api';
|
import { instanceRequest } from '../api';
|
||||||
import { parseLocation } from '../shared/utils';
|
import { parseLocation } from '../shared/utils';
|
||||||
@@ -16,7 +16,7 @@ export function runNewInstanceSelfInviteFlow(worldId) {
|
|||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
const launchStore = useLaunchStore();
|
const launchStore = useLaunchStore();
|
||||||
const inviteStore = useInviteStore();
|
const inviteStore = useInviteStore();
|
||||||
const { t } = useI18n();
|
const t = i18n.global.t;
|
||||||
|
|
||||||
instanceStore.createNewInstance(worldId).then((args) => {
|
instanceStore.createNewInstance(worldId).then((args) => {
|
||||||
const location = args?.json?.location;
|
const location = args?.json?.location;
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ export async function runRefreshPlayerModerationsFlow() {
|
|||||||
playerModerationRequest.getPlayerModerations(),
|
playerModerationRequest.getPlayerModerations(),
|
||||||
avatarModerationRequest.getAvatarModerations()
|
avatarModerationRequest.getAvatarModerations()
|
||||||
])
|
])
|
||||||
.finally(() => {
|
|
||||||
moderationStore.playerModerationTable.loading = false;
|
|
||||||
})
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
avatarStore.resetCachedAvatarModerations();
|
avatarStore.resetCachedAvatarModerations();
|
||||||
if (res[1]?.json) {
|
if (res[1]?.json) {
|
||||||
@@ -41,5 +38,8 @@ export async function runRefreshPlayerModerationsFlow() {
|
|||||||
'Failed to load player/avatar moderations:',
|
'Failed to load player/avatar moderations:',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
moderationStore.playerModerationTable.loading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
1070
src/coordinators/userCoordinator.js
Normal file
1070
src/coordinators/userCoordinator.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ import { getGroupName, getWorldName, parseLocation } from '../shared/utils';
|
|||||||
import { AppDebug } from '../service/appConfig';
|
import { AppDebug } from '../service/appConfig';
|
||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
import { useAvatarStore } from '../stores/avatar';
|
import { useAvatarStore } from '../stores/avatar';
|
||||||
|
import { getAvatarName } from './avatarCoordinator';
|
||||||
import { useFeedStore } from '../stores/feed';
|
import { useFeedStore } from '../stores/feed';
|
||||||
import { useFriendStore } from '../stores/friend';
|
import { useFriendStore } from '../stores/friend';
|
||||||
import { useGeneralSettingsStore } from '../stores/settings/general';
|
import { useGeneralSettingsStore } from '../stores/settings/general';
|
||||||
@@ -222,7 +223,7 @@ export async function runHandleUserUpdateFlow(
|
|||||||
avatarName: ''
|
avatarName: ''
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
avatarInfo = await avatarStore.getAvatarName(
|
avatarInfo = await getAvatarName(
|
||||||
currentAvatarImageUrl
|
currentAvatarImageUrl
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -233,7 +234,7 @@ export async function runHandleUserUpdateFlow(
|
|||||||
avatarName: ''
|
avatarName: ''
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
previousAvatarInfo = await avatarStore.getAvatarName(
|
previousAvatarInfo = await getAvatarName(
|
||||||
previousCurrentAvatarImageUrl
|
previousCurrentAvatarImageUrl
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { getWorldName, parseLocation } from '../shared/utils';
|
|||||||
import { runUpdateFriendshipsFlow } from './friendRelationshipCoordinator';
|
import { runUpdateFriendshipsFlow } from './friendRelationshipCoordinator';
|
||||||
import { useAuthStore } from '../stores/auth';
|
import { useAuthStore } from '../stores/auth';
|
||||||
import { useAvatarStore } from '../stores/avatar';
|
import { useAvatarStore } from '../stores/avatar';
|
||||||
|
import { addAvatarToHistory, addAvatarWearTime } from './avatarCoordinator';
|
||||||
import { useFriendStore } from '../stores/friend';
|
import { useFriendStore } from '../stores/friend';
|
||||||
import { useGameStore } from '../stores/game';
|
import { useGameStore } from '../stores/game';
|
||||||
import { useGroupStore } from '../stores/group';
|
import { useGroupStore } from '../stores/group';
|
||||||
|
import { applyPresenceGroups } from './groupCoordinator';
|
||||||
import { useInstanceStore } from '../stores/instance';
|
import { useInstanceStore } from '../stores/instance';
|
||||||
import { useUserStore } from '../stores/user';
|
import { useUserStore } from '../stores/user';
|
||||||
|
|
||||||
@@ -28,9 +30,9 @@ export function runAvatarSwapFlow(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (json.currentAvatar !== ref.currentAvatar) {
|
if (json.currentAvatar !== ref.currentAvatar) {
|
||||||
avatarStore.addAvatarToHistory(json.currentAvatar);
|
addAvatarToHistory(json.currentAvatar);
|
||||||
if (gameStore.isGameRunning) {
|
if (gameStore.isGameRunning) {
|
||||||
avatarStore.addAvatarWearTime(ref.currentAvatar);
|
addAvatarWearTime(ref.currentAvatar);
|
||||||
ref.$previousAvatarSwapTime = now();
|
ref.$previousAvatarSwapTime = now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +66,7 @@ export function runPostApplySyncFlow(ref) {
|
|||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
const friendStore = useFriendStore();
|
const friendStore = useFriendStore();
|
||||||
|
|
||||||
groupStore.applyPresenceGroups(ref);
|
applyPresenceGroups(ref);
|
||||||
instanceStore.applyQueuedInstance(ref.queuedInstance);
|
instanceStore.applyQueuedInstance(ref.queuedInstance);
|
||||||
friendStore.updateUserCurrentStatus(ref);
|
friendStore.updateUserCurrentStatus(ref);
|
||||||
if (typeof ref.friends !== 'undefined') {
|
if (typeof ref.friends !== 'undefined') {
|
||||||
|
|||||||
246
src/coordinators/worldCoordinator.js
Normal file
246
src/coordinators/worldCoordinator.js
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import { nextTick } from 'vue';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import { i18n } from '../plugin/i18n';
|
||||||
|
|
||||||
|
import {
|
||||||
|
checkVRChatCache,
|
||||||
|
createDefaultWorldRef,
|
||||||
|
evictMapCache,
|
||||||
|
getAvailablePlatforms,
|
||||||
|
getBundleDateSize,
|
||||||
|
getWorldMemo,
|
||||||
|
isRealInstance,
|
||||||
|
parseLocation,
|
||||||
|
sanitizeEntityJson
|
||||||
|
} from '../shared/utils';
|
||||||
|
import { instanceRequest, queryRequest, worldRequest } from '../api';
|
||||||
|
import { database } from '../service/database';
|
||||||
|
import { patchWorldFromEvent } from '../queries';
|
||||||
|
import { processBulk } from '../service/request';
|
||||||
|
import { applyFavorite } from './favoriteCoordinator';
|
||||||
|
import { useFavoriteStore } from '../stores/favorite';
|
||||||
|
import { useInstanceStore } from '../stores/instance';
|
||||||
|
import { useLocationStore } from '../stores/location';
|
||||||
|
import { useUiStore } from '../stores/ui';
|
||||||
|
import { useUserStore } from '../stores/user';
|
||||||
|
import { useWorldStore } from '../stores/world';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} tag
|
||||||
|
* @param {string} shortName
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export function showWorldDialog(tag, shortName = null, options = {}) {
|
||||||
|
const worldStore = useWorldStore();
|
||||||
|
const uiStore = useUiStore();
|
||||||
|
const instanceStore = useInstanceStore();
|
||||||
|
const favoriteStore = useFavoriteStore();
|
||||||
|
const locationStore = useLocationStore();
|
||||||
|
const t = i18n.global.t;
|
||||||
|
|
||||||
|
const D = worldStore.worldDialog;
|
||||||
|
const forceRefresh = Boolean(options?.forceRefresh);
|
||||||
|
const L = parseLocation(tag);
|
||||||
|
if (L.worldId === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isMainDialogOpen = uiStore.openDialog({
|
||||||
|
type: 'world',
|
||||||
|
id: L.worldId,
|
||||||
|
tag,
|
||||||
|
shortName
|
||||||
|
});
|
||||||
|
D.visible = true;
|
||||||
|
if (isMainDialogOpen && D.id === L.worldId && !forceRefresh) {
|
||||||
|
uiStore.setDialogCrumbLabel('world', D.id, D.ref?.name || D.id);
|
||||||
|
instanceStore.applyWorldDialogInstances();
|
||||||
|
nextTick(() => (D.loading = false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
L.shortName = shortName;
|
||||||
|
D.id = L.worldId;
|
||||||
|
D.$location = L;
|
||||||
|
D.loading = true;
|
||||||
|
D.inCache = false;
|
||||||
|
D.cacheSize = '';
|
||||||
|
D.cacheLocked = false;
|
||||||
|
D.cachePath = '';
|
||||||
|
D.fileAnalysis = {};
|
||||||
|
D.rooms = [];
|
||||||
|
D.lastVisit = '';
|
||||||
|
D.visitCount = 0;
|
||||||
|
D.timeSpent = 0;
|
||||||
|
D.isFavorite = false;
|
||||||
|
D.avatarScalingDisabled = false;
|
||||||
|
D.focusViewDisabled = false;
|
||||||
|
D.isPC = false;
|
||||||
|
D.isQuest = false;
|
||||||
|
D.isIos = false;
|
||||||
|
D.hasPersistData = false;
|
||||||
|
D.memo = '';
|
||||||
|
const LL = parseLocation(locationStore.lastLocation.location);
|
||||||
|
let currentWorldMatch = false;
|
||||||
|
if (LL.worldId === D.id) {
|
||||||
|
currentWorldMatch = true;
|
||||||
|
}
|
||||||
|
getWorldMemo(D.id).then((memo) => {
|
||||||
|
if (memo.worldId === D.id) {
|
||||||
|
D.memo = memo.memo;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
database.getLastVisit(D.id, currentWorldMatch).then((ref) => {
|
||||||
|
if (ref.worldId === D.id) {
|
||||||
|
D.lastVisit = ref.created_at;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
database.getVisitCount(D.id).then((ref) => {
|
||||||
|
if (ref.worldId === D.id) {
|
||||||
|
D.visitCount = ref.visitCount;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
database.getTimeSpentInWorld(D.id).then((ref) => {
|
||||||
|
if (ref.worldId === D.id) {
|
||||||
|
D.timeSpent = ref.timeSpent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const loadWorldRequest = worldRequest.getWorld({
|
||||||
|
worldId: L.worldId
|
||||||
|
});
|
||||||
|
loadWorldRequest
|
||||||
|
.catch((err) => {
|
||||||
|
nextTick(() => (D.loading = false));
|
||||||
|
D.id = null;
|
||||||
|
D.visible = false;
|
||||||
|
uiStore.jumpBackDialogCrumb();
|
||||||
|
toast.error(t('message.world.load_failed'));
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
if (D.id === args.ref.id) {
|
||||||
|
D.ref = args.ref;
|
||||||
|
uiStore.setDialogCrumbLabel(
|
||||||
|
'world',
|
||||||
|
D.id,
|
||||||
|
D.ref?.name || D.id
|
||||||
|
);
|
||||||
|
D.visible = true;
|
||||||
|
D.loading = false;
|
||||||
|
D.isFavorite = favoriteStore.getCachedFavoritesByObjectId(
|
||||||
|
D.id
|
||||||
|
);
|
||||||
|
if (!D.isFavorite) {
|
||||||
|
D.isFavorite =
|
||||||
|
favoriteStore.localWorldFavoritesList.includes(
|
||||||
|
D.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let { isPC, isQuest, isIos } = getAvailablePlatforms(
|
||||||
|
args.ref.unityPackages
|
||||||
|
);
|
||||||
|
D.avatarScalingDisabled = args.ref?.tags.includes(
|
||||||
|
'feature_avatar_scaling_disabled'
|
||||||
|
);
|
||||||
|
D.focusViewDisabled = args.ref?.tags.includes(
|
||||||
|
'feature_focus_view_disabled'
|
||||||
|
);
|
||||||
|
D.isPC = isPC;
|
||||||
|
D.isQuest = isQuest;
|
||||||
|
D.isIos = isIos;
|
||||||
|
worldStore.updateVRChatWorldCache();
|
||||||
|
queryRequest
|
||||||
|
.fetch('worldPersistData', {
|
||||||
|
worldId: D.id
|
||||||
|
})
|
||||||
|
.then((args) => {
|
||||||
|
if (
|
||||||
|
args.params.worldId === worldStore.worldDialog.id &&
|
||||||
|
worldStore.worldDialog.visible
|
||||||
|
) {
|
||||||
|
worldStore.worldDialog.hasPersistData =
|
||||||
|
args.json !== false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} json
|
||||||
|
* @returns {object} ref
|
||||||
|
*/
|
||||||
|
export function applyWorld(json) {
|
||||||
|
const worldStore = useWorldStore();
|
||||||
|
const favoriteStore = useFavoriteStore();
|
||||||
|
const instanceStore = useInstanceStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
sanitizeEntityJson(json, ['name', 'description']);
|
||||||
|
let ref = worldStore.cachedWorlds.get(json.id);
|
||||||
|
if (typeof ref === 'undefined') {
|
||||||
|
ref = createDefaultWorldRef(json);
|
||||||
|
evictMapCache(worldStore.cachedWorlds, 10000, () => false, {
|
||||||
|
logLabel: 'World cache cleanup'
|
||||||
|
});
|
||||||
|
worldStore.cachedWorlds.set(ref.id, ref);
|
||||||
|
} else {
|
||||||
|
Object.assign(ref, json);
|
||||||
|
}
|
||||||
|
ref.$isLabs = ref.tags.includes('system_labs');
|
||||||
|
applyFavorite('world', ref.id);
|
||||||
|
const userDialog = userStore.userDialog;
|
||||||
|
if (userDialog.visible && userDialog.$location.worldId === ref.id) {
|
||||||
|
userStore.applyUserDialogLocation();
|
||||||
|
}
|
||||||
|
const worldDialog = worldStore.worldDialog;
|
||||||
|
if (worldDialog.visible && worldDialog.id === ref.id) {
|
||||||
|
worldDialog.ref = ref;
|
||||||
|
worldDialog.avatarScalingDisabled = ref.tags?.includes(
|
||||||
|
'feature_avatar_scaling_disabled'
|
||||||
|
);
|
||||||
|
worldDialog.focusViewDisabled = ref.tags?.includes(
|
||||||
|
'feature_focus_view_disabled'
|
||||||
|
);
|
||||||
|
instanceStore.applyWorldDialogInstances();
|
||||||
|
for (const room of worldDialog.rooms) {
|
||||||
|
if (isRealInstance(room.tag)) {
|
||||||
|
instanceRequest.getInstance({
|
||||||
|
worldId: worldDialog.id,
|
||||||
|
instanceId: room.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(worldDialog.fileAnalysis).length === 0) {
|
||||||
|
getBundleDateSize(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (favoriteStore.localWorldFavoritesList.includes(ref.id)) {
|
||||||
|
// update db cache
|
||||||
|
database.addWorldToCache(ref);
|
||||||
|
}
|
||||||
|
patchWorldFromEvent(ref);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preload all own worlds into cache at startup for global search.
|
||||||
|
*/
|
||||||
|
export async function preloadOwnWorlds() {
|
||||||
|
const params = {
|
||||||
|
n: 50,
|
||||||
|
offset: 0,
|
||||||
|
sort: 'updated',
|
||||||
|
order: 'descending',
|
||||||
|
releaseStatus: 'all',
|
||||||
|
user: 'me'
|
||||||
|
};
|
||||||
|
await processBulk({
|
||||||
|
fn: (p) => worldRequest.getWorlds(p),
|
||||||
|
N: -1,
|
||||||
|
params,
|
||||||
|
handle: (args) => {
|
||||||
|
for (const json of args.json) {
|
||||||
|
applyWorld(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
useUpdateLoopStore,
|
useUpdateLoopStore,
|
||||||
useUserStore
|
useUserStore
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
|
import { getCurrentUser } from '../coordinators/userCoordinator';
|
||||||
import { AppDebug } from './appConfig.js';
|
import { AppDebug } from './appConfig.js';
|
||||||
import { escapeTag } from '../shared/utils';
|
import { escapeTag } from '../shared/utils';
|
||||||
import { i18n } from '../plugin/i18n';
|
import { i18n } from '../plugin/i18n';
|
||||||
@@ -207,7 +208,7 @@ export function request(endpoint, options) {
|
|||||||
) {
|
) {
|
||||||
// trigger 2FA dialog }
|
// trigger 2FA dialog }
|
||||||
if (!authStore.twoFactorAuthDialogVisible) {
|
if (!authStore.twoFactorAuthDialogVisible) {
|
||||||
userStore.getCurrentUser();
|
getCurrentUser();
|
||||||
}
|
}
|
||||||
$throw(401, t('api.status_code.401'), endpoint);
|
$throw(401, t('api.status_code.401'), endpoint);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ import {
|
|||||||
useUiStore,
|
useUiStore,
|
||||||
useUserStore
|
useUserStore
|
||||||
} from '../stores';
|
} from '../stores';
|
||||||
|
import { applyUser, applyCurrentUser } from '../coordinators/userCoordinator';
|
||||||
|
import {
|
||||||
|
onGroupLeft,
|
||||||
|
applyGroup,
|
||||||
|
getGroupDialogGroup,
|
||||||
|
handleGroupMember
|
||||||
|
} from '../coordinators/groupCoordinator';
|
||||||
import { escapeTag, parseLocation } from '../shared/utils';
|
import { escapeTag, parseLocation } from '../shared/utils';
|
||||||
import { AppDebug } from './appConfig';
|
import { AppDebug } from './appConfig';
|
||||||
import { groupRequest } from '../api';
|
import { groupRequest } from '../api';
|
||||||
@@ -260,7 +267,7 @@ function handlePipeline(args) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'friend-add':
|
case 'friend-add':
|
||||||
userStore.applyUser(content.user);
|
applyUser(content.user);
|
||||||
friendStore.handleFriendAdd({
|
friendStore.handleFriendAdd({
|
||||||
params: {
|
params: {
|
||||||
userId: content.userId
|
userId: content.userId
|
||||||
@@ -298,7 +305,7 @@ function handlePipeline(args) {
|
|||||||
|
|
||||||
...content.user
|
...content.user
|
||||||
};
|
};
|
||||||
userStore.applyUser(onlineJson);
|
applyUser(onlineJson);
|
||||||
} else {
|
} else {
|
||||||
console.error('friend-online missing user id', content);
|
console.error('friend-online missing user id', content);
|
||||||
runUpdateFriendFlow(content.userId, 'online');
|
runUpdateFriendFlow(content.userId, 'online');
|
||||||
@@ -321,7 +328,7 @@ function handlePipeline(args) {
|
|||||||
|
|
||||||
...content.user
|
...content.user
|
||||||
};
|
};
|
||||||
userStore.applyUser(activeJson);
|
applyUser(activeJson);
|
||||||
} else {
|
} else {
|
||||||
console.error('friend-active missing user id', content);
|
console.error('friend-active missing user id', content);
|
||||||
runUpdateFriendFlow(content.userId, 'active');
|
runUpdateFriendFlow(content.userId, 'active');
|
||||||
@@ -342,11 +349,11 @@ function handlePipeline(args) {
|
|||||||
travelingToWorld: 'offline',
|
travelingToWorld: 'offline',
|
||||||
travelingToInstance: 'offline'
|
travelingToInstance: 'offline'
|
||||||
};
|
};
|
||||||
userStore.applyUser(offlineJson);
|
applyUser(offlineJson);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'friend-update':
|
case 'friend-update':
|
||||||
userStore.applyUser(content.user);
|
applyUser(content.user);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'friend-location':
|
case 'friend-location':
|
||||||
@@ -365,7 +372,7 @@ function handlePipeline(args) {
|
|||||||
travelingToWorld: $travelingToLocation1.worldId,
|
travelingToWorld: $travelingToLocation1.worldId,
|
||||||
travelingToInstance: $travelingToLocation1.instanceId
|
travelingToInstance: $travelingToLocation1.instanceId
|
||||||
};
|
};
|
||||||
userStore.applyUser(jankLocationJson);
|
applyUser(jankLocationJson);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const locationJson = {
|
const locationJson = {
|
||||||
@@ -378,12 +385,12 @@ function handlePipeline(args) {
|
|||||||
...content.user,
|
...content.user,
|
||||||
state: 'online' // JANK
|
state: 'online' // JANK
|
||||||
};
|
};
|
||||||
userStore.applyUser(locationJson);
|
applyUser(locationJson);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'user-update':
|
case 'user-update':
|
||||||
userStore.applyCurrentUser(content.user);
|
applyCurrentUser(content.user);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'user-location':
|
case 'user-location':
|
||||||
@@ -410,14 +417,14 @@ function handlePipeline(args) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'group-left':
|
case 'group-left':
|
||||||
groupStore.onGroupLeft(content.groupId);
|
onGroupLeft(content.groupId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'group-role-updated':
|
case 'group-role-updated':
|
||||||
const groupId = content.role.groupId;
|
const groupId = content.role.groupId;
|
||||||
groupRequest
|
groupRequest
|
||||||
.getGroup({ groupId, includeRoles: true })
|
.getGroup({ groupId, includeRoles: true })
|
||||||
.then((args) => groupStore.applyGroup(args.json));
|
.then((args) => applyGroup(args.json));
|
||||||
console.log('group-role-updated', content);
|
console.log('group-role-updated', content);
|
||||||
|
|
||||||
// content {
|
// content {
|
||||||
@@ -446,9 +453,9 @@ function handlePipeline(args) {
|
|||||||
groupStore.groupDialog.visible &&
|
groupStore.groupDialog.visible &&
|
||||||
groupStore.groupDialog.id === groupId1
|
groupStore.groupDialog.id === groupId1
|
||||||
) {
|
) {
|
||||||
groupStore.getGroupDialogGroup(groupId1);
|
getGroupDialogGroup(groupId1);
|
||||||
}
|
}
|
||||||
groupStore.handleGroupMember({
|
handleGroupMember({
|
||||||
json: member,
|
json: member,
|
||||||
params: {
|
params: {
|
||||||
groupId: groupId1
|
groupId: groupId1
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { escapeTag } from '../shared/utils';
|
|||||||
import { initWebsocket } from '../service/websocket';
|
import { initWebsocket } from '../service/websocket';
|
||||||
import { request } from '../service/request';
|
import { request } from '../service/request';
|
||||||
import { runHandleAutoLoginFlow } from '../coordinators/authAutoLoginCoordinator';
|
import { runHandleAutoLoginFlow } from '../coordinators/authAutoLoginCoordinator';
|
||||||
|
import { getCurrentUser } from '../coordinators/userCoordinator';
|
||||||
import { useAdvancedSettingsStore } from './settings/advanced';
|
import { useAdvancedSettingsStore } from './settings/advanced';
|
||||||
import { useGeneralSettingsStore } from './settings/general';
|
import { useGeneralSettingsStore } from './settings/general';
|
||||||
import { useModalStore } from './modal';
|
import { useModalStore } from './modal';
|
||||||
@@ -197,8 +198,7 @@ export const useAuthStore = defineStore('Auth', () => {
|
|||||||
throw err;
|
throw err;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
userStore
|
getCurrentUser()
|
||||||
.getCurrentUser()
|
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loginForm.value.loading = false;
|
loginForm.value.loading = false;
|
||||||
})
|
})
|
||||||
@@ -671,7 +671,7 @@ export const useAuthStore = defineStore('Auth', () => {
|
|||||||
clearCookiesTryLogin();
|
clearCookiesTryLogin();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
userStore.getCurrentUser();
|
getCurrentUser();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -713,7 +713,7 @@ export const useAuthStore = defineStore('Auth', () => {
|
|||||||
clearCookiesTryLogin();
|
clearCookiesTryLogin();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
userStore.getCurrentUser();
|
getCurrentUser();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -756,7 +756,7 @@ export const useAuthStore = defineStore('Auth', () => {
|
|||||||
promptEmailOTP();
|
promptEmailOTP();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
userStore.getCurrentUser();
|
getCurrentUser();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -1,46 +1,13 @@
|
|||||||
import { nextTick, ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { toast } from 'vue-sonner';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkVRChatCache,
|
checkVRChatCache
|
||||||
createDefaultAvatarRef,
|
|
||||||
extractFileId,
|
|
||||||
getAvailablePlatforms,
|
|
||||||
getBundleDateSize,
|
|
||||||
getPlatformInfo,
|
|
||||||
replaceBioSymbols,
|
|
||||||
sanitizeEntityJson,
|
|
||||||
storeAvatarImage
|
|
||||||
} from '../shared/utils';
|
} from '../shared/utils';
|
||||||
import { avatarRequest, miscRequest, queryRequest } from '../api';
|
|
||||||
import { AppDebug } from '../service/appConfig';
|
|
||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
import { patchAvatarFromEvent } from '../queries';
|
|
||||||
import { processBulk } from '../service/request';
|
|
||||||
import { applyFavorite } from '../coordinators/favoriteCoordinator';
|
|
||||||
import { useAdvancedSettingsStore } from './settings/advanced';
|
|
||||||
import { useAvatarProviderStore } from './avatarProvider';
|
|
||||||
import { useFavoriteStore } from './favorite';
|
|
||||||
import { useModalStore } from './modal';
|
|
||||||
import { useUiStore } from './ui';
|
|
||||||
import { useUserStore } from './user';
|
|
||||||
import { useVRCXUpdaterStore } from './vrcxUpdater';
|
|
||||||
import { watchState } from '../service/watchState';
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
import webApiService from '../service/webapi';
|
|
||||||
|
|
||||||
export const useAvatarStore = defineStore('Avatar', () => {
|
export const useAvatarStore = defineStore('Avatar', () => {
|
||||||
const favoriteStore = useFavoriteStore();
|
|
||||||
const avatarProviderStore = useAvatarProviderStore();
|
|
||||||
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
|
||||||
const advancedSettingsStore = useAdvancedSettingsStore();
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const modalStore = useModalStore();
|
|
||||||
const uiStore = useUiStore();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
let cachedAvatarModerations = new Map();
|
let cachedAvatarModerations = new Map();
|
||||||
let cachedAvatars = new Map();
|
let cachedAvatars = new Map();
|
||||||
let cachedAvatarNames = new Map();
|
let cachedAvatarNames = new Map();
|
||||||
@@ -83,145 +50,17 @@ export const useAvatarStore = defineStore('Avatar', () => {
|
|||||||
cachedAvatarModerations.clear();
|
cachedAvatarModerations.clear();
|
||||||
avatarHistory.value = [];
|
avatarHistory.value = [];
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
getAvatarHistory();
|
import('../coordinators/avatarCoordinator').then(
|
||||||
preloadOwnAvatars();
|
({ getAvatarHistory, preloadOwnAvatars }) => {
|
||||||
|
getAvatarHistory();
|
||||||
|
preloadOwnAvatars();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ flush: 'sync' }
|
{ flush: 'sync' }
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {object} json
|
|
||||||
* @returns {object} ref
|
|
||||||
*/
|
|
||||||
function applyAvatar(json) {
|
|
||||||
sanitizeEntityJson(json, ['name', 'description']);
|
|
||||||
let ref = cachedAvatars.get(json.id);
|
|
||||||
if (typeof ref === 'undefined') {
|
|
||||||
ref = createDefaultAvatarRef(json);
|
|
||||||
cachedAvatars.set(ref.id, ref);
|
|
||||||
} else {
|
|
||||||
const { unityPackages } = ref;
|
|
||||||
Object.assign(ref, json);
|
|
||||||
if (
|
|
||||||
json.unityPackages?.length > 0 &&
|
|
||||||
unityPackages.length > 0 &&
|
|
||||||
!json.unityPackages[0].assetUrl
|
|
||||||
) {
|
|
||||||
ref.unityPackages = unityPackages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const listing of ref.publishedListings) {
|
|
||||||
listing.displayName = replaceBioSymbols(listing.displayName);
|
|
||||||
listing.description = replaceBioSymbols(listing.description);
|
|
||||||
}
|
|
||||||
applyFavorite('avatar', ref.id);
|
|
||||||
if (favoriteStore.localAvatarFavoritesList.includes(ref.id)) {
|
|
||||||
const avatarRef = ref;
|
|
||||||
favoriteStore.syncLocalAvatarFavoriteRef(avatarRef);
|
|
||||||
|
|
||||||
// update db cache
|
|
||||||
database.addAvatarToCache(avatarRef);
|
|
||||||
}
|
|
||||||
patchAvatarFromEvent(ref);
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} avatarId
|
|
||||||
* @param options
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function showAvatarDialog(avatarId, options = {}) {
|
|
||||||
const D = avatarDialog.value;
|
|
||||||
const forceRefresh = Boolean(options?.forceRefresh);
|
|
||||||
const isMainDialogOpen = uiStore.openDialog({
|
|
||||||
type: 'avatar',
|
|
||||||
id: avatarId
|
|
||||||
});
|
|
||||||
D.visible = true;
|
|
||||||
if (isMainDialogOpen && D.id === avatarId && !forceRefresh) {
|
|
||||||
uiStore.setDialogCrumbLabel('avatar', D.id, D.ref?.name || D.id);
|
|
||||||
nextTick(() => (D.loading = false));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
D.loading = true;
|
|
||||||
D.id = avatarId;
|
|
||||||
D.inCache = false;
|
|
||||||
D.cacheSize = '';
|
|
||||||
D.cacheLocked = false;
|
|
||||||
D.cachePath = '';
|
|
||||||
D.fileAnalysis = {};
|
|
||||||
D.isQuestFallback = false;
|
|
||||||
D.isPC = false;
|
|
||||||
D.isQuest = false;
|
|
||||||
D.isIos = false;
|
|
||||||
D.hasImposter = false;
|
|
||||||
D.imposterVersion = '';
|
|
||||||
D.platformInfo = {};
|
|
||||||
D.galleryImages = [];
|
|
||||||
D.galleryLoading = true;
|
|
||||||
D.isFavorite =
|
|
||||||
favoriteStore.getCachedFavoritesByObjectId(avatarId) ||
|
|
||||||
(userStore.isLocalUserVrcPlusSupporter &&
|
|
||||||
favoriteStore.localAvatarFavoritesList.includes(avatarId));
|
|
||||||
D.isBlocked = cachedAvatarModerations.has(avatarId);
|
|
||||||
const ref2 = cachedAvatars.get(avatarId);
|
|
||||||
if (typeof ref2 !== 'undefined') {
|
|
||||||
D.ref = ref2;
|
|
||||||
uiStore.setDialogCrumbLabel('avatar', D.id, D.ref?.name || D.id);
|
|
||||||
nextTick(() => (D.loading = false));
|
|
||||||
}
|
|
||||||
const loadAvatarRequest = forceRefresh
|
|
||||||
? avatarRequest.getAvatar({ avatarId })
|
|
||||||
: queryRequest.fetch('avatar', { avatarId });
|
|
||||||
loadAvatarRequest
|
|
||||||
.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)) {
|
|
||||||
D.isQuestFallback = true;
|
|
||||||
}
|
|
||||||
const { isPC, isQuest, isIos } = getAvailablePlatforms(
|
|
||||||
ref.unityPackages
|
|
||||||
);
|
|
||||||
D.isPC = isPC;
|
|
||||||
D.isQuest = isQuest;
|
|
||||||
D.isIos = isIos;
|
|
||||||
D.platformInfo = getPlatformInfo(ref.unityPackages);
|
|
||||||
for (let i = ref.unityPackages.length - 1; i > -1; i--) {
|
|
||||||
const unityPackage = ref.unityPackages[i];
|
|
||||||
if (unityPackage.variant === 'impostor') {
|
|
||||||
D.hasImposter = true;
|
|
||||||
D.imposterVersion = unityPackage.impostorizerVersion;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Object.keys(D.fileAnalysis).length === 0) {
|
|
||||||
getBundleDateSize(ref);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
D.loading = false;
|
|
||||||
D.id = null;
|
|
||||||
D.visible = false;
|
|
||||||
uiStore.jumpBackDialogCrumb();
|
|
||||||
toast.error(t('message.api_handler.avatar_private_or_deleted'));
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
nextTick(() => (D.loading = false));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {boolean} value
|
* @param {boolean} value
|
||||||
*/
|
*/
|
||||||
@@ -249,6 +88,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
|
|||||||
* @returns {Promise<string[]>}
|
* @returns {Promise<string[]>}
|
||||||
*/
|
*/
|
||||||
async function getAvatarGallery(avatarId) {
|
async function getAvatarGallery(avatarId) {
|
||||||
|
const { queryRequest } = await import('../api');
|
||||||
const D = avatarDialog.value;
|
const D = avatarDialog.value;
|
||||||
const args = await queryRequest
|
const args = await queryRequest
|
||||||
.fetch('avatarGallery', { avatarId })
|
.fetch('avatarGallery', { avatarId })
|
||||||
@@ -341,54 +181,6 @@ export const useAvatarStore = defineStore('Avatar', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
async function getAvatarHistory() {
|
|
||||||
const historyArray = await database.getAvatarHistory(
|
|
||||||
userStore.currentUser.id
|
|
||||||
);
|
|
||||||
for (let i = 0; i < historyArray.length; i++) {
|
|
||||||
const avatar = historyArray[i];
|
|
||||||
if (avatar.authorId === userStore.currentUser.id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
applyAvatar(avatar);
|
|
||||||
}
|
|
||||||
avatarHistory.value = historyArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} avatarId
|
|
||||||
*/
|
|
||||||
function addAvatarToHistory(avatarId) {
|
|
||||||
avatarRequest
|
|
||||||
.getAvatar({ avatarId })
|
|
||||||
.then((args) => {
|
|
||||||
const ref = applyAvatar(args.json);
|
|
||||||
|
|
||||||
database.addAvatarToCache(ref);
|
|
||||||
database.addAvatarToHistory(ref.id);
|
|
||||||
|
|
||||||
if (ref.authorId === userStore.currentUser.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const historyArray = avatarHistory.value;
|
|
||||||
for (let i = 0; i < historyArray.length; ++i) {
|
|
||||||
if (historyArray[i].id === ref.id) {
|
|
||||||
historyArray.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarHistory.value.unshift(ref);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('Failed to add avatar to history:', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -397,423 +189,21 @@ export const useAvatarStore = defineStore('Avatar', () => {
|
|||||||
database.clearAvatarHistory();
|
database.clearAvatarHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function promptClearAvatarHistory() {
|
|
||||||
modalStore
|
|
||||||
.confirm({
|
|
||||||
description: t('confirm.clear_avatar_history'),
|
|
||||||
title: 'Confirm'
|
|
||||||
})
|
|
||||||
.then(({ ok }) => {
|
|
||||||
if (!ok) return;
|
|
||||||
clearAvatarHistory();
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} imageUrl
|
|
||||||
* @returns {Promise<object>}
|
|
||||||
*/
|
|
||||||
async function getAvatarName(imageUrl) {
|
|
||||||
const fileId = extractFileId(imageUrl);
|
|
||||||
if (!fileId) {
|
|
||||||
return {
|
|
||||||
ownerId: '',
|
|
||||||
avatarName: '-'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (cachedAvatarNames.has(fileId)) {
|
|
||||||
return cachedAvatarNames.get(fileId);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const args = await miscRequest.getFile({ fileId });
|
|
||||||
return storeAvatarImage(args, cachedAvatarNames);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to get avatar images:', error);
|
|
||||||
return {
|
|
||||||
ownerId: '',
|
|
||||||
avatarName: '-'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @param search
|
|
||||||
*/
|
|
||||||
async function lookupAvatars(type, search) {
|
|
||||||
const avatars = new Map();
|
|
||||||
if (type === 'search') {
|
|
||||||
try {
|
|
||||||
const url = `${
|
|
||||||
avatarProviderStore.avatarRemoteDatabaseProvider
|
|
||||||
}?${type}=${encodeURIComponent(search)}&n=5000`;
|
|
||||||
const response = await webApiService.execute({
|
|
||||||
url,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
Referer: 'https://vrcx.app',
|
|
||||||
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const json = JSON.parse(response.data);
|
|
||||||
if (AppDebug.debugWebRequests) {
|
|
||||||
console.log(url, json, response);
|
|
||||||
}
|
|
||||||
if (response.status === 200 && typeof json === 'object') {
|
|
||||||
json.forEach((avatar) => {
|
|
||||||
if (!avatars.has(avatar.Id)) {
|
|
||||||
const ref = {
|
|
||||||
authorId: '',
|
|
||||||
authorName: '',
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
id: '',
|
|
||||||
imageUrl: '',
|
|
||||||
thumbnailImageUrl: '',
|
|
||||||
created_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
updated_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
releaseStatus: 'public',
|
|
||||||
...avatar
|
|
||||||
};
|
|
||||||
avatars.set(ref.id, ref);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new Error(`Error: ${response.data}`);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const msg = `Avatar search failed for ${search} with ${avatarProviderStore.avatarRemoteDatabaseProvider}\n${err}`;
|
|
||||||
console.error(msg);
|
|
||||||
toast.error(msg);
|
|
||||||
}
|
|
||||||
} else if (type === 'authorId') {
|
|
||||||
const length =
|
|
||||||
avatarProviderStore.avatarRemoteDatabaseProviderList.length;
|
|
||||||
for (let i = 0; i < length; ++i) {
|
|
||||||
const url =
|
|
||||||
avatarProviderStore.avatarRemoteDatabaseProviderList[i];
|
|
||||||
const avatarArray = await lookupAvatarsByAuthor(url, search);
|
|
||||||
avatarArray.forEach((avatar) => {
|
|
||||||
if (!avatars.has(avatar.id)) {
|
|
||||||
avatars.set(avatar.id, avatar);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return avatars;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param authorId
|
|
||||||
* @param fileId
|
|
||||||
*/
|
|
||||||
async function lookupAvatarByImageFileId(authorId, fileId) {
|
|
||||||
for (const providerUrl of avatarProviderStore.avatarRemoteDatabaseProviderList) {
|
|
||||||
const avatar = await lookupAvatarByFileId(providerUrl, fileId);
|
|
||||||
if (avatar?.id) {
|
|
||||||
return avatar.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const providerUrl of avatarProviderStore.avatarRemoteDatabaseProviderList) {
|
|
||||||
const avatarArray = await lookupAvatarsByAuthor(
|
|
||||||
providerUrl,
|
|
||||||
authorId
|
|
||||||
);
|
|
||||||
for (const avatar of avatarArray) {
|
|
||||||
if (extractFileId(avatar.imageUrl) === fileId) {
|
|
||||||
return avatar.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param providerUrl
|
|
||||||
* @param fileId
|
|
||||||
*/
|
|
||||||
async function lookupAvatarByFileId(providerUrl, fileId) {
|
|
||||||
try {
|
|
||||||
const url = `${providerUrl}?fileId=${encodeURIComponent(fileId)}`;
|
|
||||||
const response = await webApiService.execute({
|
|
||||||
url,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
Referer: 'https://vrcx.app',
|
|
||||||
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const json = JSON.parse(response.data);
|
|
||||||
if (AppDebug.debugWebRequests) {
|
|
||||||
console.log(url, json, response);
|
|
||||||
}
|
|
||||||
if (response.status === 200 && typeof json === 'object') {
|
|
||||||
const ref = {
|
|
||||||
authorId: '',
|
|
||||||
authorName: '',
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
id: '',
|
|
||||||
imageUrl: '',
|
|
||||||
thumbnailImageUrl: '',
|
|
||||||
created_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
updated_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
releaseStatus: 'public',
|
|
||||||
...json
|
|
||||||
};
|
|
||||||
return ref;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// ignore errors for now, not all providers support this lookup type
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param providerUrl
|
|
||||||
* @param authorId
|
|
||||||
*/
|
|
||||||
async function lookupAvatarsByAuthor(providerUrl, authorId) {
|
|
||||||
const avatars = [];
|
|
||||||
if (!providerUrl || !authorId) {
|
|
||||||
return avatars;
|
|
||||||
}
|
|
||||||
const url = `${providerUrl}?authorId=${encodeURIComponent(authorId)}`;
|
|
||||||
try {
|
|
||||||
const response = await webApiService.execute({
|
|
||||||
url,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
Referer: 'https://vrcx.app',
|
|
||||||
'VRCX-ID': vrcxUpdaterStore.vrcxId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const json = JSON.parse(response.data);
|
|
||||||
if (AppDebug.debugWebRequests) {
|
|
||||||
console.log(url, json, response);
|
|
||||||
}
|
|
||||||
if (response.status === 200 && typeof json === 'object') {
|
|
||||||
json.forEach((avatar) => {
|
|
||||||
const ref = {
|
|
||||||
authorId: '',
|
|
||||||
authorName: '',
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
id: '',
|
|
||||||
imageUrl: '',
|
|
||||||
thumbnailImageUrl: '',
|
|
||||||
created_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
updated_at: '0001-01-01T00:00:00.0000000Z',
|
|
||||||
releaseStatus: 'public',
|
|
||||||
...avatar
|
|
||||||
};
|
|
||||||
avatars.push(ref);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new Error(`Error: ${response.data}`);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const msg = `Avatar lookup failed for ${authorId} with ${url}\n${err}`;
|
|
||||||
console.error(msg);
|
|
||||||
toast.error(msg);
|
|
||||||
}
|
|
||||||
return avatars;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
function selectAvatarWithConfirmation(id) {
|
|
||||||
modalStore
|
|
||||||
.confirm({
|
|
||||||
description: t('confirm.select_avatar'),
|
|
||||||
title: 'Confirm'
|
|
||||||
})
|
|
||||||
.then(({ ok }) => {
|
|
||||||
if (!ok) return;
|
|
||||||
selectAvatarWithoutConfirmation(id);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
async function selectAvatarWithoutConfirmation(id) {
|
|
||||||
if (userStore.currentUser.currentAvatar === id) {
|
|
||||||
toast.info('Avatar already selected');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return avatarRequest
|
|
||||||
.selectAvatar({
|
|
||||||
avatarId: id
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
toast.success('Avatar changed');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param fileId
|
|
||||||
*/
|
|
||||||
function checkAvatarCache(fileId) {
|
|
||||||
let avatarId = '';
|
|
||||||
for (let ref of cachedAvatars.values()) {
|
|
||||||
if (extractFileId(ref.imageUrl) === fileId) {
|
|
||||||
avatarId = ref.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return avatarId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param fileId
|
|
||||||
* @param ownerUserId
|
|
||||||
*/
|
|
||||||
async function checkAvatarCacheRemote(fileId, ownerUserId) {
|
|
||||||
if (advancedSettingsStore.avatarRemoteDatabase) {
|
|
||||||
try {
|
|
||||||
toast.dismiss(loadingToastId.value);
|
|
||||||
loadingToastId.value = toast.loading(
|
|
||||||
t('message.avatar_lookup.loading')
|
|
||||||
);
|
|
||||||
const avatarId = await lookupAvatarByImageFileId(
|
|
||||||
ownerUserId,
|
|
||||||
fileId
|
|
||||||
);
|
|
||||||
return avatarId;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to lookup avatar by image file id:', err);
|
|
||||||
} finally {
|
|
||||||
toast.dismiss(loadingToastId.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param refUserId
|
|
||||||
* @param ownerUserId
|
|
||||||
* @param currentAvatarImageUrl
|
|
||||||
*/
|
|
||||||
async function showAvatarAuthorDialog(
|
|
||||||
refUserId,
|
|
||||||
ownerUserId,
|
|
||||||
currentAvatarImageUrl
|
|
||||||
) {
|
|
||||||
const fileId = extractFileId(currentAvatarImageUrl);
|
|
||||||
if (!fileId) {
|
|
||||||
toast.error(t('message.avatar_lookup.failed'));
|
|
||||||
} else if (refUserId === userStore.currentUser.id) {
|
|
||||||
showAvatarDialog(userStore.currentUser.currentAvatar);
|
|
||||||
} else {
|
|
||||||
let avatarId = checkAvatarCache(fileId);
|
|
||||||
let avatarInfo;
|
|
||||||
if (!avatarId) {
|
|
||||||
avatarInfo = await getAvatarName(currentAvatarImageUrl);
|
|
||||||
if (avatarInfo.ownerId === userStore.currentUser.id) {
|
|
||||||
await userStore.refreshUserDialogAvatars(fileId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!avatarId) {
|
|
||||||
avatarId = await checkAvatarCacheRemote(fileId, ownerUserId);
|
|
||||||
}
|
|
||||||
if (!avatarId) {
|
|
||||||
if (ownerUserId === refUserId) {
|
|
||||||
toast.warning(
|
|
||||||
t('message.avatar_lookup.private_or_not_found')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
toast.warning(t('message.avatar_lookup.not_found'));
|
|
||||||
userStore.showUserDialog(avatarInfo.ownerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (avatarId) {
|
|
||||||
showAvatarDialog(avatarId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avatarId
|
|
||||||
*/
|
|
||||||
function addAvatarWearTime(avatarId) {
|
|
||||||
if (!userStore.currentUser.$previousAvatarSwapTime || !avatarId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const timeSpent =
|
|
||||||
Date.now() - userStore.currentUser.$previousAvatarSwapTime;
|
|
||||||
database.addAvatarTimeSpent(avatarId, timeSpent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preload all own avatars into cache at startup for global search.
|
|
||||||
*/
|
|
||||||
async function preloadOwnAvatars() {
|
|
||||||
const params = {
|
|
||||||
n: 50,
|
|
||||||
offset: 0,
|
|
||||||
sort: 'updated',
|
|
||||||
order: 'descending',
|
|
||||||
releaseStatus: 'all',
|
|
||||||
user: 'me'
|
|
||||||
};
|
|
||||||
await processBulk({
|
|
||||||
fn: avatarRequest.getAvatars,
|
|
||||||
N: -1,
|
|
||||||
params,
|
|
||||||
handle: (args) => {
|
|
||||||
for (const json of args.json) {
|
|
||||||
applyAvatar(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
avatarDialog,
|
avatarDialog,
|
||||||
avatarHistory,
|
avatarHistory,
|
||||||
|
loadingToastId,
|
||||||
cachedAvatarModerations,
|
cachedAvatarModerations,
|
||||||
cachedAvatars,
|
cachedAvatars,
|
||||||
cachedAvatarNames,
|
cachedAvatarNames,
|
||||||
|
|
||||||
showAvatarDialog,
|
|
||||||
applyAvatarModeration,
|
applyAvatarModeration,
|
||||||
resetCachedAvatarModerations,
|
resetCachedAvatarModerations,
|
||||||
getAvatarGallery,
|
getAvatarGallery,
|
||||||
updateVRChatAvatarCache,
|
updateVRChatAvatarCache,
|
||||||
getAvatarHistory,
|
clearAvatarHistory,
|
||||||
addAvatarToHistory,
|
|
||||||
applyAvatar,
|
|
||||||
promptClearAvatarHistory,
|
|
||||||
getAvatarName,
|
|
||||||
lookupAvatars,
|
|
||||||
selectAvatarWithConfirmation,
|
|
||||||
selectAvatarWithoutConfirmation,
|
|
||||||
setAvatarDialogVisible,
|
setAvatarDialogVisible,
|
||||||
setAvatarDialogIsFavorite,
|
setAvatarDialogIsFavorite,
|
||||||
setAvatarDialogLoading,
|
setAvatarDialogLoading
|
||||||
showAvatarAuthorDialog,
|
|
||||||
addAvatarWearTime,
|
|
||||||
preloadOwnAvatars
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
runPendingOfflineTickFlow,
|
runPendingOfflineTickFlow,
|
||||||
runUpdateFriendFlow
|
runUpdateFriendFlow
|
||||||
} from '../coordinators/friendPresenceCoordinator';
|
} from '../coordinators/friendPresenceCoordinator';
|
||||||
|
import { applyUser } from '../coordinators/userCoordinator';
|
||||||
import { AppDebug } from '../service/appConfig';
|
import { AppDebug } from '../service/appConfig';
|
||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
import { useAppearanceSettingsStore } from './settings/appearance';
|
import { useAppearanceSettingsStore } from './settings/appearance';
|
||||||
@@ -981,7 +982,7 @@ export const useFriendStore = defineStore('Friend', () => {
|
|||||||
const sqlValues = [];
|
const sqlValues = [];
|
||||||
const friends = await refreshFriends();
|
const friends = await refreshFriends();
|
||||||
for (const friend of friends) {
|
for (const friend of friends) {
|
||||||
const ref = userStore.applyUser(friend);
|
const ref = applyUser(friend);
|
||||||
const row = {
|
const row = {
|
||||||
userId: ref.id,
|
userId: ref.id,
|
||||||
displayName: ref.displayName,
|
displayName: ref.displayName,
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import { useAvatarStore } from './avatar';
|
|||||||
import { useFavoriteStore } from './favorite';
|
import { useFavoriteStore } from './favorite';
|
||||||
import { useFriendStore } from './friend';
|
import { useFriendStore } from './friend';
|
||||||
import { useGroupStore } from './group';
|
import { useGroupStore } from './group';
|
||||||
|
import { showGroupDialog } from '../coordinators/groupCoordinator';
|
||||||
|
import { showWorldDialog } from '../coordinators/worldCoordinator';
|
||||||
|
import { showAvatarDialog } from '../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog } from '../coordinators/userCoordinator';
|
||||||
import { useUserStore } from './user';
|
import { useUserStore } from './user';
|
||||||
import { useWorldStore } from './world';
|
import { useWorldStore } from './world';
|
||||||
|
|
||||||
@@ -166,16 +170,16 @@ export const useGlobalSearchStore = defineStore('GlobalSearch', () => {
|
|||||||
|
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'friend':
|
case 'friend':
|
||||||
userStore.showUserDialog(item.id);
|
showUserDialog(item.id);
|
||||||
break;
|
break;
|
||||||
case 'avatar':
|
case 'avatar':
|
||||||
avatarStore.showAvatarDialog(item.id);
|
showAvatarDialog(item.id);
|
||||||
break;
|
break;
|
||||||
case 'world':
|
case 'world':
|
||||||
worldStore.showWorldDialog(item.id);
|
showWorldDialog(item.id);
|
||||||
break;
|
break;
|
||||||
case 'group':
|
case 'group':
|
||||||
groupStore.showGroupDialog(item.id);
|
showGroupDialog(item.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,8 @@ import { useFriendStore } from '../friend';
|
|||||||
import { useGameStore } from '../game';
|
import { useGameStore } from '../game';
|
||||||
import { useGeneralSettingsStore } from '../settings/general';
|
import { useGeneralSettingsStore } from '../settings/general';
|
||||||
import { useGroupStore } from '../group';
|
import { useGroupStore } from '../group';
|
||||||
|
import { showGroupDialog } from '../../coordinators/groupCoordinator';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
import { useInstanceStore } from '../instance';
|
import { useInstanceStore } from '../instance';
|
||||||
import { useLocationStore } from '../location';
|
import { useLocationStore } from '../location';
|
||||||
import { useModalStore } from '../modal';
|
import { useModalStore } from '../modal';
|
||||||
@@ -1415,10 +1417,10 @@ export const useNotificationStore = defineStore('Notification', () => {
|
|||||||
}
|
}
|
||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case 'group':
|
case 'group':
|
||||||
groupStore.showGroupDialog(data[1]);
|
showGroupDialog(data[1]);
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
userStore.showUserDialog(data[1]);
|
showUserDialog(data[1]);
|
||||||
break;
|
break;
|
||||||
case 'event':
|
case 'event':
|
||||||
const ids = data[1].split(',');
|
const ids = data[1].split(',');
|
||||||
@@ -1427,7 +1429,7 @@ export const useNotificationStore = defineStore('Notification', () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
groupStore.showGroupDialog(ids[0]);
|
showGroupDialog(ids[0]);
|
||||||
// ids[1] cal_ is the event id
|
// ids[1] cal_ is the event id
|
||||||
break;
|
break;
|
||||||
case 'openNotificationLink':
|
case 'openNotificationLink':
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import { photonEmojis, photonEventType } from '../shared/constants/photon';
|
|||||||
import { AppDebug } from '../service/appConfig';
|
import { AppDebug } from '../service/appConfig';
|
||||||
import { database } from '../service/database';
|
import { database } from '../service/database';
|
||||||
import { useAvatarStore } from './avatar';
|
import { useAvatarStore } from './avatar';
|
||||||
|
import { applyAvatar } from '../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog, lookupUser, applyUser } from '../coordinators/userCoordinator';
|
||||||
import { useFavoriteStore } from './favorite';
|
import { useFavoriteStore } from './favorite';
|
||||||
import { useFriendStore } from './friend';
|
import { useFriendStore } from './friend';
|
||||||
import { useGameLogStore } from './gameLog';
|
import { useGameLogStore } from './gameLog';
|
||||||
@@ -424,9 +426,9 @@ export const usePhotonStore = defineStore('Photon', () => {
|
|||||||
const ref = photonLobby.value.get(photonId);
|
const ref = photonLobby.value.get(photonId);
|
||||||
if (typeof ref !== 'undefined') {
|
if (typeof ref !== 'undefined') {
|
||||||
if (typeof ref.id !== 'undefined') {
|
if (typeof ref.id !== 'undefined') {
|
||||||
userStore.showUserDialog(ref.id);
|
showUserDialog(ref.id);
|
||||||
} else if (typeof ref.displayName !== 'undefined') {
|
} else if (typeof ref.displayName !== 'undefined') {
|
||||||
userStore.lookupUser(ref);
|
lookupUser(ref);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toast.error('No user info available');
|
toast.error('No user info available');
|
||||||
@@ -1475,7 +1477,7 @@ export const usePhotonStore = defineStore('Photon', () => {
|
|||||||
typeof ref.id !== 'undefined' &&
|
typeof ref.id !== 'undefined' &&
|
||||||
ref.currentAvatarImageUrl !== user.currentAvatarImageUrl
|
ref.currentAvatarImageUrl !== user.currentAvatarImageUrl
|
||||||
) {
|
) {
|
||||||
userStore.applyUser({
|
applyUser({
|
||||||
...ref,
|
...ref,
|
||||||
currentAvatarImageUrl: user.currentAvatarImageUrl,
|
currentAvatarImageUrl: user.currentAvatarImageUrl,
|
||||||
currentAvatarThumbnailImageUrl:
|
currentAvatarThumbnailImageUrl:
|
||||||
@@ -1803,7 +1805,7 @@ export const usePhotonStore = defineStore('Photon', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avatarStore.applyAvatar({
|
applyAvatar({
|
||||||
id: avatar.id,
|
id: avatar.id,
|
||||||
authorId: avatar.authorId,
|
authorId: avatar.authorId,
|
||||||
authorName: avatar.authorName,
|
authorName: avatar.authorName,
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import { useAppearanceSettingsStore } from './settings/appearance';
|
|||||||
import { useAvatarStore } from './avatar';
|
import { useAvatarStore } from './avatar';
|
||||||
import { useFriendStore } from './friend';
|
import { useFriendStore } from './friend';
|
||||||
import { useGroupStore } from './group';
|
import { useGroupStore } from './group';
|
||||||
|
import { showGroupDialog } from '../coordinators/groupCoordinator';
|
||||||
|
import { showWorldDialog } from '../coordinators/worldCoordinator';
|
||||||
|
import { showAvatarDialog } from '../coordinators/avatarCoordinator';
|
||||||
|
import { applyUser, showUserDialog, lookupUser } from '../coordinators/userCoordinator';
|
||||||
import { useModalStore } from './modal';
|
import { useModalStore } from './modal';
|
||||||
import { useUserStore } from './user';
|
import { useUserStore } from './user';
|
||||||
import { useWorldStore } from './world';
|
import { useWorldStore } from './world';
|
||||||
@@ -93,7 +97,7 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
console.error('getUsers gave us garbage', json);
|
console.error('getUsers gave us garbage', json);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
userStore.applyUser(json);
|
applyUser(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
@@ -210,10 +214,10 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
} else {
|
} else {
|
||||||
router.push({ name: 'search' });
|
router.push({ name: 'search' });
|
||||||
searchText.value = searchTerm;
|
searchText.value = searchTerm;
|
||||||
userStore.lookupUser({ displayName: searchTerm });
|
lookupUser({ displayName: searchTerm });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
userStore.showUserDialog(value);
|
showUserDialog(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,15 +277,15 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
const type = urlPathSplit[2];
|
const type = urlPathSplit[2];
|
||||||
if (type === 'user') {
|
if (type === 'user') {
|
||||||
const userId = urlPathSplit[3];
|
const userId = urlPathSplit[3];
|
||||||
userStore.showUserDialog(userId);
|
showUserDialog(userId);
|
||||||
return true;
|
return true;
|
||||||
} else if (type === 'avatar') {
|
} else if (type === 'avatar') {
|
||||||
const avatarId = urlPathSplit[3];
|
const avatarId = urlPathSplit[3];
|
||||||
avatarStore.showAvatarDialog(avatarId);
|
showAvatarDialog(avatarId);
|
||||||
return true;
|
return true;
|
||||||
} else if (type === 'group') {
|
} else if (type === 'group') {
|
||||||
const groupId = urlPathSplit[3];
|
const groupId = urlPathSplit[3];
|
||||||
groupStore.showGroupDialog(groupId);
|
showGroupDialog(groupId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (input.startsWith('https://vrc.group/')) {
|
} else if (input.startsWith('https://vrc.group/')) {
|
||||||
@@ -295,16 +299,16 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
input.substring(0, 4) === 'usr_' ||
|
input.substring(0, 4) === 'usr_' ||
|
||||||
/^[A-Za-z0-9]{10}$/g.test(input)
|
/^[A-Za-z0-9]{10}$/g.test(input)
|
||||||
) {
|
) {
|
||||||
userStore.showUserDialog(input);
|
showUserDialog(input);
|
||||||
return true;
|
return true;
|
||||||
} else if (
|
} else if (
|
||||||
input.substring(0, 5) === 'avtr_' ||
|
input.substring(0, 5) === 'avtr_' ||
|
||||||
input.substring(0, 2) === 'b_'
|
input.substring(0, 2) === 'b_'
|
||||||
) {
|
) {
|
||||||
avatarStore.showAvatarDialog(input);
|
showAvatarDialog(input);
|
||||||
return true;
|
return true;
|
||||||
} else if (input.substring(0, 4) === 'grp_') {
|
} else if (input.substring(0, 4) === 'grp_') {
|
||||||
groupStore.showGroupDialog(input);
|
showGroupDialog(input);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -331,7 +335,7 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
const urlPathSplit = urlPath.split('/');
|
const urlPathSplit = urlPath.split('/');
|
||||||
if (urlPathSplit.length >= 4 && urlPathSplit[2] === 'world') {
|
if (urlPathSplit.length >= 4 && urlPathSplit[2] === 'world') {
|
||||||
worldId = urlPathSplit[3];
|
worldId = urlPathSplit[3];
|
||||||
worldStore.showWorldDialog(worldId);
|
showWorldDialog(worldId);
|
||||||
return true;
|
return true;
|
||||||
} else if (urlPath.substring(5, 12) === '/launch') {
|
} else if (urlPath.substring(5, 12) === '/launch') {
|
||||||
const urlParams = new URLSearchParams(url.search);
|
const urlParams = new URLSearchParams(url.search);
|
||||||
@@ -343,10 +347,10 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
if (shortName) {
|
if (shortName) {
|
||||||
return verifyShortName(location, shortName);
|
return verifyShortName(location, shortName);
|
||||||
}
|
}
|
||||||
worldStore.showWorldDialog(location);
|
showWorldDialog(location);
|
||||||
return true;
|
return true;
|
||||||
} else if (worldId) {
|
} else if (worldId) {
|
||||||
worldStore.showWorldDialog(worldId);
|
showWorldDialog(worldId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -360,7 +364,7 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
input = `https://vrchat.com/home/launch?worldId=${input}`;
|
input = `https://vrchat.com/home/launch?worldId=${input}`;
|
||||||
return directAccessWorld(input);
|
return directAccessWorld(input);
|
||||||
}
|
}
|
||||||
worldStore.showWorldDialog(input.trim());
|
showWorldDialog(input.trim());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -399,7 +403,7 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
groupRequest.groupStrictsearch({ query: shortCode }).then((args) => {
|
groupRequest.groupStrictsearch({ query: shortCode }).then((args) => {
|
||||||
for (const group of args.json) {
|
for (const group of args.json) {
|
||||||
if (`${group.shortCode}.${group.discriminator}` === shortCode) {
|
if (`${group.shortCode}.${group.discriminator}` === shortCode) {
|
||||||
groupStore.showGroupDialog(group.id);
|
showGroupDialog(group.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,11 +418,11 @@ export const useSearchStore = defineStore('Search', () => {
|
|||||||
const newLocation = args.json.location;
|
const newLocation = args.json.location;
|
||||||
const newShortName = args.json.shortName;
|
const newShortName = args.json.shortName;
|
||||||
if (newShortName) {
|
if (newShortName) {
|
||||||
worldStore.showWorldDialog(newLocation, newShortName);
|
showWorldDialog(newLocation, newShortName);
|
||||||
} else if (newLocation) {
|
} else if (newLocation) {
|
||||||
worldStore.showWorldDialog(newLocation);
|
showWorldDialog(newLocation);
|
||||||
} else {
|
} else {
|
||||||
worldStore.showWorldDialog(location);
|
showWorldDialog(location);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import { updateLocalizedStrings } from '../plugin/i18n';
|
|||||||
import { useAppearanceSettingsStore } from './settings/appearance';
|
import { useAppearanceSettingsStore } from './settings/appearance';
|
||||||
import { useAvatarStore } from './avatar';
|
import { useAvatarStore } from './avatar';
|
||||||
import { useGroupStore } from './group';
|
import { useGroupStore } from './group';
|
||||||
|
import { showGroupDialog } from '../coordinators/groupCoordinator';
|
||||||
|
import { showWorldDialog } from '../coordinators/worldCoordinator';
|
||||||
|
import { showAvatarDialog } from '../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog } from '../coordinators/userCoordinator';
|
||||||
import { useInstanceStore } from './instance';
|
import { useInstanceStore } from './instance';
|
||||||
import { useNotificationStore } from './notification';
|
import { useNotificationStore } from './notification';
|
||||||
import { useSearchStore } from './search';
|
import { useSearchStore } from './search';
|
||||||
@@ -142,19 +146,19 @@ export const useUiStore = defineStore('Ui', () => {
|
|||||||
}
|
}
|
||||||
jumpDialogCrumb(index);
|
jumpDialogCrumb(index);
|
||||||
if (item.type === 'user') {
|
if (item.type === 'user') {
|
||||||
userStore.showUserDialog(item.id);
|
showUserDialog(item.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.type === 'world') {
|
if (item.type === 'world') {
|
||||||
worldStore.showWorldDialog(item.tag, item.shortName);
|
showWorldDialog(item.tag, item.shortName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.type === 'avatar') {
|
if (item.type === 'avatar') {
|
||||||
avatarStore.showAvatarDialog(item.id);
|
showAvatarDialog(item.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.type === 'group') {
|
if (item.type === 'group') {
|
||||||
groupStore.showGroupDialog(item.id);
|
showGroupDialog(item.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (item.type === 'previous-instances-user') {
|
if (item.type === 'previous-instances-user') {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { useFriendStore } from './friend';
|
|||||||
import { useGameLogStore } from './gameLog';
|
import { useGameLogStore } from './gameLog';
|
||||||
import { useGameStore } from './game';
|
import { useGameStore } from './game';
|
||||||
import { useGroupStore } from './group';
|
import { useGroupStore } from './group';
|
||||||
|
import { handleGroupUserInstances } from '../coordinators/groupCoordinator';
|
||||||
|
import { getCurrentUser, updateAutoStateChange } from '../coordinators/userCoordinator';
|
||||||
import { useModerationStore } from './moderation';
|
import { useModerationStore } from './moderation';
|
||||||
import { useUserStore } from './user';
|
import { useUserStore } from './user';
|
||||||
import { useVRCXUpdaterStore } from './vrcxUpdater';
|
import { useVRCXUpdaterStore } from './vrcxUpdater';
|
||||||
@@ -73,7 +75,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
|
|||||||
if (watchState.isLoggedIn) {
|
if (watchState.isLoggedIn) {
|
||||||
if (--state.nextCurrentUserRefresh <= 0) {
|
if (--state.nextCurrentUserRefresh <= 0) {
|
||||||
state.nextCurrentUserRefresh = 300; // 5min
|
state.nextCurrentUserRefresh = 300; // 5min
|
||||||
userStore.getCurrentUser();
|
getCurrentUser();
|
||||||
}
|
}
|
||||||
if (--state.nextFriendsRefresh <= 0) {
|
if (--state.nextFriendsRefresh <= 0) {
|
||||||
state.nextFriendsRefresh = 3600; // 1hour
|
state.nextFriendsRefresh = 3600; // 1hour
|
||||||
@@ -92,7 +94,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
|
|||||||
state.nextGroupInstanceRefresh = 300; // 5min
|
state.nextGroupInstanceRefresh = 300; // 5min
|
||||||
const args =
|
const args =
|
||||||
await groupRequest.getUsersGroupInstances();
|
await groupRequest.getUsersGroupInstances();
|
||||||
groupStore.handleGroupUserInstances(args);
|
handleGroupUserInstances(args);
|
||||||
}
|
}
|
||||||
AppApi.CheckGameRunning();
|
AppApi.CheckGameRunning();
|
||||||
}
|
}
|
||||||
@@ -122,7 +124,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
|
|||||||
}
|
}
|
||||||
if (--state.nextAutoStateChange <= 0) {
|
if (--state.nextAutoStateChange <= 0) {
|
||||||
state.nextAutoStateChange = 3;
|
state.nextAutoStateChange = 3;
|
||||||
userStore.updateAutoStateChange();
|
updateAutoStateChange();
|
||||||
}
|
}
|
||||||
if (LINUX && --state.nextGetLogCheck <= 0) {
|
if (LINUX && --state.nextGetLogCheck <= 0) {
|
||||||
state.nextGetLogCheck = 0.5;
|
state.nextGetLogCheck = 0.5;
|
||||||
|
|||||||
1069
src/stores/user.js
1069
src/stores/user.js
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,10 @@ import { useGalleryStore } from './gallery';
|
|||||||
import { useGameLogStore } from './gameLog';
|
import { useGameLogStore } from './gameLog';
|
||||||
import { useGameStore } from './game';
|
import { useGameStore } from './game';
|
||||||
import { useGroupStore } from './group';
|
import { useGroupStore } from './group';
|
||||||
|
import { showGroupDialog } from '../coordinators/groupCoordinator';
|
||||||
|
import { showWorldDialog } from '../coordinators/worldCoordinator';
|
||||||
|
import { showAvatarDialog, selectAvatarWithConfirmation, selectAvatarWithoutConfirmation } from '../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog, addCustomTag } from '../coordinators/userCoordinator';
|
||||||
import { useInstanceStore } from './instance';
|
import { useInstanceStore } from './instance';
|
||||||
import { useLocationStore } from './location';
|
import { useLocationStore } from './location';
|
||||||
import { useModalStore } from './modal';
|
import { useModalStore } from './modal';
|
||||||
@@ -335,7 +339,7 @@ export const useVrcxStore = defineStore('Vrcx', () => {
|
|||||||
let entry;
|
let entry;
|
||||||
switch (data.MsgType) {
|
switch (data.MsgType) {
|
||||||
case 'CustomTag':
|
case 'CustomTag':
|
||||||
userStore.addCustomTag(data);
|
addCustomTag(data);
|
||||||
break;
|
break;
|
||||||
case 'ClearCustomTags':
|
case 'ClearCustomTags':
|
||||||
userStore.customUserTags.forEach((value, key) => {
|
userStore.customUserTags.forEach((value, key) => {
|
||||||
@@ -669,17 +673,17 @@ export const useVrcxStore = defineStore('Vrcx', () => {
|
|||||||
!searchStore.directAccessWorld(input.replace('world/', ''))
|
!searchStore.directAccessWorld(input.replace('world/', ''))
|
||||||
) {
|
) {
|
||||||
// fallback for mangled world ids
|
// fallback for mangled world ids
|
||||||
worldStore.showWorldDialog(commandArg);
|
showWorldDialog(commandArg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'avatar':
|
case 'avatar':
|
||||||
avatarStore.showAvatarDialog(commandArg);
|
showAvatarDialog(commandArg);
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
userStore.showUserDialog(commandArg);
|
showUserDialog(commandArg);
|
||||||
break;
|
break;
|
||||||
case 'group':
|
case 'group':
|
||||||
groupStore.showGroupDialog(commandArg);
|
showGroupDialog(commandArg);
|
||||||
break;
|
break;
|
||||||
case 'local-favorite-world':
|
case 'local-favorite-world':
|
||||||
console.log('local-favorite-world', commandArg);
|
console.log('local-favorite-world', commandArg);
|
||||||
@@ -701,7 +705,7 @@ export const useVrcxStore = defineStore('Vrcx', () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
avatarRequest.getAvatar({ avatarId: avatarIdFav }).then(() => {
|
avatarRequest.getAvatar({ avatarId: avatarIdFav }).then(() => {
|
||||||
avatarStore.showAvatarDialog(avatarIdFav);
|
showAvatarDialog(avatarIdFav);
|
||||||
addLocalAvatarFavorite(
|
addLocalAvatarFavorite(
|
||||||
avatarIdFav,
|
avatarIdFav,
|
||||||
avatarGroup
|
avatarGroup
|
||||||
@@ -722,12 +726,11 @@ export const useVrcxStore = defineStore('Vrcx', () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (advancedSettingsStore.showConfirmationOnSwitchAvatar) {
|
if (advancedSettingsStore.showConfirmationOnSwitchAvatar) {
|
||||||
avatarStore.selectAvatarWithConfirmation(avatarId);
|
selectAvatarWithConfirmation(avatarId);
|
||||||
// Makes sure the window is focused
|
// Makes sure the window is focused
|
||||||
shouldFocusWindow = true;
|
shouldFocusWindow = true;
|
||||||
} else {
|
} else {
|
||||||
avatarStore
|
selectAvatarWithoutConfirmation(avatarId)
|
||||||
.selectAvatarWithoutConfirmation(avatarId)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success('Avatar changed via launch command');
|
toast.success('Avatar changed via launch command');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,39 +1,12 @@
|
|||||||
import { nextTick, reactive, shallowReactive, watch } from 'vue';
|
import { reactive, shallowReactive, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { toast } from 'vue-sonner';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkVRChatCache,
|
checkVRChatCache
|
||||||
createDefaultWorldRef,
|
|
||||||
evictMapCache,
|
|
||||||
getAvailablePlatforms,
|
|
||||||
getBundleDateSize,
|
|
||||||
getWorldMemo,
|
|
||||||
isRealInstance,
|
|
||||||
parseLocation,
|
|
||||||
sanitizeEntityJson
|
|
||||||
} from '../shared/utils';
|
} from '../shared/utils';
|
||||||
import { instanceRequest, queryRequest, worldRequest } from '../api';
|
|
||||||
import { database } from '../service/database';
|
|
||||||
import { patchWorldFromEvent } from '../queries';
|
|
||||||
import { processBulk } from '../service/request';
|
|
||||||
import { applyFavorite } from '../coordinators/favoriteCoordinator';
|
|
||||||
import { useFavoriteStore } from './favorite';
|
|
||||||
import { useInstanceStore } from './instance';
|
|
||||||
import { useLocationStore } from './location';
|
|
||||||
import { useUiStore } from './ui';
|
|
||||||
import { useUserStore } from './user';
|
|
||||||
import { watchState } from '../service/watchState';
|
import { watchState } from '../service/watchState';
|
||||||
|
|
||||||
export const useWorldStore = defineStore('World', () => {
|
export const useWorldStore = defineStore('World', () => {
|
||||||
const locationStore = useLocationStore();
|
|
||||||
const favoriteStore = useFavoriteStore();
|
|
||||||
const instanceStore = useInstanceStore();
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const uiStore = useUiStore();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const worldDialog = reactive({
|
const worldDialog = reactive({
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -69,145 +42,14 @@ export const useWorldStore = defineStore('World', () => {
|
|||||||
worldDialog.visible = false;
|
worldDialog.visible = false;
|
||||||
cachedWorlds.clear();
|
cachedWorlds.clear();
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
preloadOwnWorlds();
|
import('../coordinators/worldCoordinator').then(
|
||||||
|
({ preloadOwnWorlds }) => preloadOwnWorlds()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ flush: 'sync' }
|
{ flush: 'sync' }
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} tag
|
|
||||||
* @param {string} shortName
|
|
||||||
* @param options
|
|
||||||
*/
|
|
||||||
function showWorldDialog(tag, shortName = null, options = {}) {
|
|
||||||
const D = worldDialog;
|
|
||||||
const forceRefresh = Boolean(options?.forceRefresh);
|
|
||||||
const L = parseLocation(tag);
|
|
||||||
if (L.worldId === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const isMainDialogOpen = uiStore.openDialog({
|
|
||||||
type: 'world',
|
|
||||||
id: L.worldId,
|
|
||||||
tag,
|
|
||||||
shortName
|
|
||||||
});
|
|
||||||
D.visible = true;
|
|
||||||
if (isMainDialogOpen && D.id === L.worldId && !forceRefresh) {
|
|
||||||
uiStore.setDialogCrumbLabel('world', D.id, D.ref?.name || D.id);
|
|
||||||
instanceStore.applyWorldDialogInstances();
|
|
||||||
nextTick(() => (D.loading = false));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
L.shortName = shortName;
|
|
||||||
D.id = L.worldId;
|
|
||||||
D.$location = L;
|
|
||||||
D.loading = true;
|
|
||||||
D.inCache = false;
|
|
||||||
D.cacheSize = '';
|
|
||||||
D.cacheLocked = false;
|
|
||||||
D.cachePath = '';
|
|
||||||
D.fileAnalysis = {};
|
|
||||||
D.rooms = [];
|
|
||||||
D.lastVisit = '';
|
|
||||||
D.visitCount = 0;
|
|
||||||
D.timeSpent = 0;
|
|
||||||
D.isFavorite = false;
|
|
||||||
D.avatarScalingDisabled = false;
|
|
||||||
D.focusViewDisabled = false;
|
|
||||||
D.isPC = false;
|
|
||||||
D.isQuest = false;
|
|
||||||
D.isIos = false;
|
|
||||||
D.hasPersistData = false;
|
|
||||||
D.memo = '';
|
|
||||||
const LL = parseLocation(locationStore.lastLocation.location);
|
|
||||||
let currentWorldMatch = false;
|
|
||||||
if (LL.worldId === D.id) {
|
|
||||||
currentWorldMatch = true;
|
|
||||||
}
|
|
||||||
getWorldMemo(D.id).then((memo) => {
|
|
||||||
if (memo.worldId === D.id) {
|
|
||||||
D.memo = memo.memo;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
database.getLastVisit(D.id, currentWorldMatch).then((ref) => {
|
|
||||||
if (ref.worldId === D.id) {
|
|
||||||
D.lastVisit = ref.created_at;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
database.getVisitCount(D.id).then((ref) => {
|
|
||||||
if (ref.worldId === D.id) {
|
|
||||||
D.visitCount = ref.visitCount;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
database.getTimeSpentInWorld(D.id).then((ref) => {
|
|
||||||
if (ref.worldId === D.id) {
|
|
||||||
D.timeSpent = ref.timeSpent;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const loadWorldRequest = worldRequest.getWorld({
|
|
||||||
worldId: L.worldId
|
|
||||||
});
|
|
||||||
loadWorldRequest
|
|
||||||
.catch((err) => {
|
|
||||||
nextTick(() => (D.loading = false));
|
|
||||||
D.id = null;
|
|
||||||
D.visible = false;
|
|
||||||
uiStore.jumpBackDialogCrumb();
|
|
||||||
toast.error(t('message.world.load_failed'));
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
.then((args) => {
|
|
||||||
if (D.id === args.ref.id) {
|
|
||||||
D.ref = args.ref;
|
|
||||||
uiStore.setDialogCrumbLabel(
|
|
||||||
'world',
|
|
||||||
D.id,
|
|
||||||
D.ref?.name || D.id
|
|
||||||
);
|
|
||||||
D.visible = true;
|
|
||||||
D.loading = false;
|
|
||||||
D.isFavorite = favoriteStore.getCachedFavoritesByObjectId(
|
|
||||||
D.id
|
|
||||||
);
|
|
||||||
if (!D.isFavorite) {
|
|
||||||
D.isFavorite =
|
|
||||||
favoriteStore.localWorldFavoritesList.includes(
|
|
||||||
D.id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let { isPC, isQuest, isIos } = getAvailablePlatforms(
|
|
||||||
args.ref.unityPackages
|
|
||||||
);
|
|
||||||
D.avatarScalingDisabled = args.ref?.tags.includes(
|
|
||||||
'feature_avatar_scaling_disabled'
|
|
||||||
);
|
|
||||||
D.focusViewDisabled = args.ref?.tags.includes(
|
|
||||||
'feature_focus_view_disabled'
|
|
||||||
);
|
|
||||||
D.isPC = isPC;
|
|
||||||
D.isQuest = isQuest;
|
|
||||||
D.isIos = isIos;
|
|
||||||
updateVRChatWorldCache();
|
|
||||||
queryRequest
|
|
||||||
.fetch('worldPersistData', {
|
|
||||||
worldId: D.id
|
|
||||||
})
|
|
||||||
.then((args) => {
|
|
||||||
if (
|
|
||||||
args.params.worldId === worldDialog.id &&
|
|
||||||
worldDialog.visible
|
|
||||||
) {
|
|
||||||
worldDialog.hasPersistData =
|
|
||||||
args.json !== false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {boolean} value
|
* @param {boolean} value
|
||||||
*/
|
*/
|
||||||
@@ -250,99 +92,12 @@ export const useWorldStore = defineStore('World', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param WorldCache
|
|
||||||
*/
|
|
||||||
function cleanupWorldCache(WorldCache) {
|
|
||||||
evictMapCache(WorldCache, 10000, () => false, {
|
|
||||||
logLabel: 'World cache cleanup'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {object} json
|
|
||||||
* @returns {object} ref
|
|
||||||
*/
|
|
||||||
function applyWorld(json) {
|
|
||||||
sanitizeEntityJson(json, ['name', 'description']);
|
|
||||||
let ref = cachedWorlds.get(json.id);
|
|
||||||
if (typeof ref === 'undefined') {
|
|
||||||
ref = createDefaultWorldRef(json);
|
|
||||||
cleanupWorldCache(cachedWorlds);
|
|
||||||
cachedWorlds.set(ref.id, ref);
|
|
||||||
} else {
|
|
||||||
Object.assign(ref, json);
|
|
||||||
}
|
|
||||||
ref.$isLabs = ref.tags.includes('system_labs');
|
|
||||||
applyFavorite('world', ref.id);
|
|
||||||
const userDialog = userStore.userDialog;
|
|
||||||
if (userDialog.visible && userDialog.$location.worldId === ref.id) {
|
|
||||||
userStore.applyUserDialogLocation();
|
|
||||||
}
|
|
||||||
if (worldDialog.visible && worldDialog.id === ref.id) {
|
|
||||||
worldDialog.ref = ref;
|
|
||||||
worldDialog.avatarScalingDisabled = ref.tags?.includes(
|
|
||||||
'feature_avatar_scaling_disabled'
|
|
||||||
);
|
|
||||||
worldDialog.focusViewDisabled = ref.tags?.includes(
|
|
||||||
'feature_focus_view_disabled'
|
|
||||||
);
|
|
||||||
instanceStore.applyWorldDialogInstances();
|
|
||||||
for (const room of worldDialog.rooms) {
|
|
||||||
if (isRealInstance(room.tag)) {
|
|
||||||
instanceRequest.getInstance({
|
|
||||||
worldId: worldDialog.id,
|
|
||||||
instanceId: room.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Object.keys(worldDialog.fileAnalysis).length === 0) {
|
|
||||||
getBundleDateSize(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (favoriteStore.localWorldFavoritesList.includes(ref.id)) {
|
|
||||||
// update db cache
|
|
||||||
database.addWorldToCache(ref);
|
|
||||||
}
|
|
||||||
patchWorldFromEvent(ref);
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preload all own worlds into cache at startup for global search.
|
|
||||||
*/
|
|
||||||
async function preloadOwnWorlds() {
|
|
||||||
const params = {
|
|
||||||
n: 50,
|
|
||||||
offset: 0,
|
|
||||||
sort: 'updated',
|
|
||||||
order: 'descending',
|
|
||||||
releaseStatus: 'all',
|
|
||||||
user: 'me'
|
|
||||||
};
|
|
||||||
await processBulk({
|
|
||||||
fn: (p) => worldRequest.getWorlds(p),
|
|
||||||
N: -1,
|
|
||||||
params,
|
|
||||||
handle: (args) => {
|
|
||||||
for (const json of args.json) {
|
|
||||||
applyWorld(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
worldDialog,
|
worldDialog,
|
||||||
cachedWorlds,
|
cachedWorlds,
|
||||||
showWorldDialog,
|
|
||||||
setWorldDialogVisible,
|
setWorldDialogVisible,
|
||||||
setWorldDialogIsFavorite,
|
setWorldDialogIsFavorite,
|
||||||
setWorldDialogLoading,
|
setWorldDialogLoading,
|
||||||
updateVRChatWorldCache,
|
updateVRChatWorldCache
|
||||||
applyWorld,
|
|
||||||
preloadOwnWorlds
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,9 +28,10 @@
|
|||||||
import { timeToText } from '../../../shared/utils';
|
import { timeToText } from '../../../shared/utils';
|
||||||
|
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { isDarkMode, dtHour12 } = storeToRefs(useAppearanceSettingsStore());
|
const { isDarkMode, dtHour12 } = storeToRefs(useAppearanceSettingsStore());
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -275,6 +275,7 @@
|
|||||||
useUserStore
|
useUserStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
import { userImage, userStatusClass } from '../../../shared/utils';
|
import { userImage, userStatusClass } from '../../../shared/utils';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
import { database } from '../../../service/database';
|
import { database } from '../../../service/database';
|
||||||
import { watchState } from '../../../service/watchState';
|
import { watchState } from '../../../service/watchState';
|
||||||
|
|
||||||
@@ -290,7 +291,7 @@
|
|||||||
const { currentUser } = storeToRefs(userStore);
|
const { currentUser } = storeToRefs(userStore);
|
||||||
const { isDarkMode } = storeToRefs(appearanceStore);
|
const { isDarkMode } = storeToRefs(appearanceStore);
|
||||||
const cachedUsers = userStore.cachedUsers;
|
const cachedUsers = userStore.cachedUsers;
|
||||||
const showUserDialog = (userId) => userStore.showUserDialog(userId);
|
|
||||||
|
|
||||||
const fetchState = chartsStore.mutualGraphFetchState;
|
const fetchState = chartsStore.mutualGraphFetchState;
|
||||||
const status = chartsStore.mutualGraphStatus;
|
const status = chartsStore.mutualGraphStatus;
|
||||||
|
|||||||
@@ -519,7 +519,7 @@
|
|||||||
handleFavoriteGroup
|
handleFavoriteGroup
|
||||||
} = favoriteStore;
|
} = favoriteStore;
|
||||||
const { avatarHistory } = storeToRefs(useAvatarStore());
|
const { avatarHistory } = storeToRefs(useAvatarStore());
|
||||||
const { promptClearAvatarHistory, showAvatarDialog, applyAvatar } = useAvatarStore();
|
import { promptClearAvatarHistory, showAvatarDialog, applyAvatar } from '../../coordinators/avatarCoordinator';
|
||||||
const { isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
const { isLocalUserVrcPlusSupporter } = storeToRefs(useUserStore());
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|||||||
@@ -388,6 +388,7 @@
|
|||||||
DropdownMenuTrigger
|
DropdownMenuTrigger
|
||||||
} from '../../components/ui/dropdown-menu';
|
} from '../../components/ui/dropdown-menu';
|
||||||
import { useAppearanceSettingsStore, useFavoriteStore, useModalStore, useWorldStore } from '../../stores';
|
import { useAppearanceSettingsStore, useFavoriteStore, useModalStore, useWorldStore } from '../../stores';
|
||||||
|
import { showWorldDialog } from '../../coordinators/worldCoordinator';
|
||||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '../../components/ui/resizable';
|
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '../../components/ui/resizable';
|
||||||
import { favoriteRequest, worldRequest } from '../../api';
|
import { favoriteRequest, worldRequest } from '../../api';
|
||||||
import { debounce } from '../../shared/utils';
|
import { debounce } from '../../shared/utils';
|
||||||
@@ -436,7 +437,7 @@
|
|||||||
handleFavoriteGroup,
|
handleFavoriteGroup,
|
||||||
localWorldFavoritesList
|
localWorldFavoritesList
|
||||||
} = favoriteStore;
|
} = favoriteStore;
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
cardScale: worldCardScale,
|
cardScale: worldCardScale,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@
|
|||||||
|
|
||||||
const { favoriteAvatarGroups } = storeToRefs(useFavoriteStore());
|
const { favoriteAvatarGroups } = storeToRefs(useFavoriteStore());
|
||||||
const { showFavoriteDialog } = useFavoriteStore();
|
const { showFavoriteDialog } = useFavoriteStore();
|
||||||
const { selectAvatarWithConfirmation } = useAvatarStore();
|
import { selectAvatarWithConfirmation } from '../../../coordinators/avatarCoordinator';
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { showFavoriteDialog, getCachedFavoritesByObjectId } = useFavoriteStore();
|
const { showFavoriteDialog, getCachedFavoritesByObjectId } = useFavoriteStore();
|
||||||
const { selectAvatarWithConfirmation } = useAvatarStore();
|
import { selectAvatarWithConfirmation } from '../../../coordinators/avatarCoordinator';
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -131,11 +131,12 @@
|
|||||||
|
|
||||||
const emit = defineEmits(['update:avatarImportDialogInput']);
|
const emit = defineEmits(['update:avatarImportDialogInput']);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { favoriteAvatarGroups, avatarImportDialogInput, avatarImportDialogVisible, localAvatarFavoriteGroups } =
|
const { favoriteAvatarGroups, avatarImportDialogInput, avatarImportDialogVisible, localAvatarFavoriteGroups } =
|
||||||
storeToRefs(useFavoriteStore());
|
storeToRefs(useFavoriteStore());
|
||||||
const { localAvatarFavGroupLength, getCachedFavoritesByObjectId } = useFavoriteStore();
|
const { localAvatarFavGroupLength, getCachedFavoritesByObjectId } = useFavoriteStore();
|
||||||
const { showAvatarDialog, applyAvatar } = useAvatarStore();
|
import { showAvatarDialog, applyAvatar } from '../../../coordinators/avatarCoordinator';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|
||||||
const avatarImportDialog = ref({
|
const avatarImportDialog = ref({
|
||||||
|
|||||||
@@ -131,12 +131,13 @@
|
|||||||
import { favoriteRequest, userRequest } from '../../../api';
|
import { favoriteRequest, userRequest } from '../../../api';
|
||||||
import { createColumns } from './friendImportColumns.jsx';
|
import { createColumns } from './friendImportColumns.jsx';
|
||||||
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const emit = defineEmits(['update:friendImportDialogInput']);
|
const emit = defineEmits(['update:friendImportDialogInput']);
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { favoriteFriendGroups, friendImportDialogInput, friendImportDialogVisible, localFriendFavoriteGroups } =
|
const { favoriteFriendGroups, friendImportDialogInput, friendImportDialogVisible, localFriendFavoriteGroups } =
|
||||||
storeToRefs(useFavoriteStore());
|
storeToRefs(useFavoriteStore());
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|||||||
@@ -127,17 +127,19 @@
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { useFavoriteStore, useGalleryStore, useUserStore, useWorldStore } from '../../../stores';
|
import { useFavoriteStore, useGalleryStore, useUserStore, useWorldStore } from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { addLocalWorldFavorite } from '../../../coordinators/favoriteCoordinator';
|
import { addLocalWorldFavorite } from '../../../coordinators/favoriteCoordinator';
|
||||||
import { favoriteRequest, worldRequest } from '../../../api';
|
import { favoriteRequest, worldRequest } from '../../../api';
|
||||||
import { createColumns } from './worldImportColumns.jsx';
|
import { createColumns } from './worldImportColumns.jsx';
|
||||||
import { removeFromArray } from '../../../shared/utils';
|
import { removeFromArray } from '../../../shared/utils';
|
||||||
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { favoriteWorldGroups, worldImportDialogInput, worldImportDialogVisible, localWorldFavoriteGroups } =
|
const { favoriteWorldGroups, worldImportDialogInput, worldImportDialogVisible, localWorldFavoriteGroups } =
|
||||||
storeToRefs(useFavoriteStore());
|
storeToRefs(useFavoriteStore());
|
||||||
const { localWorldFavGroupLength, getCachedFavoritesByObjectId } = useFavoriteStore();
|
const { localWorldFavGroupLength, getCachedFavoritesByObjectId } = useFavoriteStore();
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|
||||||
const emit = defineEmits(['update:worldImportDialogInput']);
|
const emit = defineEmits(['update:worldImportDialogInput']);
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import {
|
|||||||
} from 'lucide-vue-next';
|
} from 'lucide-vue-next';
|
||||||
import { formatDateFilter, statusClass, timeToText } from '../../shared/utils';
|
import { formatDateFilter, statusClass, timeToText } from '../../shared/utils';
|
||||||
import { i18n } from '../../plugin';
|
import { i18n } from '../../plugin';
|
||||||
import { useUserStore, useGalleryStore } from '../../stores';
|
import { useGalleryStore } from '../../stores';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
|
|
||||||
@@ -276,7 +277,7 @@ export const columns = [
|
|||||||
header: () => t('table.feed.user'),
|
header: () => t('table.feed.user'),
|
||||||
meta: { label: () => t('table.feed.user') },
|
meta: { label: () => t('table.feed.user') },
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const original = row.original;
|
const original = row.original;
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -148,6 +148,7 @@
|
|||||||
import { router } from '../../plugin/router';
|
import { router } from '../../plugin/router';
|
||||||
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
import { useDataTableScrollHeight } from '../../composables/useDataTableScrollHeight';
|
||||||
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
import { useVrcxVueTable } from '../../lib/table/useVrcxVueTable';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@
|
|||||||
const { getAllUserStats, getAllUserMutualCount, confirmDeleteFriend, handleFriendDelete } = useFriendStore();
|
const { getAllUserStats, getAllUserMutualCount, confirmDeleteFriend, handleFriendDelete } = useFriendStore();
|
||||||
const appearanceSettingsStore = useAppearanceSettingsStore();
|
const appearanceSettingsStore = useAppearanceSettingsStore();
|
||||||
const { randomUserColours } = storeToRefs(appearanceSettingsStore);
|
const { randomUserColours } = storeToRefs(appearanceSettingsStore);
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { stringComparer, friendsListSearch } = storeToRefs(useSearchStore());
|
const { stringComparer, friendsListSearch } = storeToRefs(useSearchStore());
|
||||||
|
|
||||||
const friendsListSearchFilters = ref([]);
|
const friendsListSearchFilters = ref([]);
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ import { storeToRefs } from 'pinia';
|
|||||||
|
|
||||||
import { formatDateFilter } from '../../shared/utils';
|
import { formatDateFilter } from '../../shared/utils';
|
||||||
import { i18n } from '../../plugin';
|
import { i18n } from '../../plugin';
|
||||||
import { useUiStore, useUserStore } from '../../stores';
|
import { useUiStore } from '../../stores';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
|
|
||||||
export const createColumns = ({ onDelete, onDeletePrompt }) => {
|
export const createColumns = ({ onDelete, onDeletePrompt }) => {
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -81,9 +81,10 @@
|
|||||||
import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js';
|
import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js';
|
||||||
|
|
||||||
import Location from '../../../components/Location.vue';
|
import Location from '../../../components/Location.vue';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { showUserDialog, showSendBoopDialog } = useUserStore();
|
const { showSendBoopDialog } = useUserStore();
|
||||||
const launchStore = useLaunchStore();
|
const launchStore = useLaunchStore();
|
||||||
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
const { lastLocation, lastLocationDestination } = storeToRefs(useLocationStore());
|
||||||
const { isGameRunning } = storeToRefs(useGameStore());
|
const { isGameRunning } = storeToRefs(useGameStore());
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import { formatDateFilter, openExternalLink } from '../../shared/utils';
|
|||||||
import { i18n } from '../../plugin';
|
import { i18n } from '../../plugin';
|
||||||
import {
|
import {
|
||||||
useInstanceStore,
|
useInstanceStore,
|
||||||
useUiStore,
|
useUiStore
|
||||||
useUserStore,
|
|
||||||
useWorldStore
|
|
||||||
} from '../../stores';
|
} from '../../stores';
|
||||||
|
import { lookupUser } from '../../coordinators/userCoordinator';
|
||||||
|
import { showWorldDialog } from '../../coordinators/worldCoordinator';
|
||||||
|
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
|
|
||||||
@@ -24,8 +24,9 @@ const UNACTIONABLE_TYPES = new Set([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export const createColumns = ({ getCreatedAt, onDelete, onDeletePrompt }) => {
|
export const createColumns = ({ getCreatedAt, onDelete, onDeletePrompt }) => {
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
const { lookupUser } = useUserStore();
|
|
||||||
|
|
||||||
const { showPreviousInstancesInfoDialog } = useInstanceStore();
|
const { showPreviousInstancesInfoDialog } = useInstanceStore();
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ import { storeToRefs } from 'pinia';
|
|||||||
import { formatDateFilter } from '../../shared/utils';
|
import { formatDateFilter } from '../../shared/utils';
|
||||||
import { i18n } from '../../plugin';
|
import { i18n } from '../../plugin';
|
||||||
import { useUiStore, useUserStore } from '../../stores';
|
import { useUiStore, useUserStore } from '../../stores';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t, te } = i18n.global;
|
const { t, te } = i18n.global;
|
||||||
|
|
||||||
export const createColumns = ({ onDelete, onDeletePrompt }) => {
|
export const createColumns = ({ onDelete, onDeletePrompt }) => {
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
|
|
||||||
|
|||||||
@@ -347,12 +347,13 @@
|
|||||||
import ManageTagsDialog from './ManageTagsDialog.vue';
|
import ManageTagsDialog from './ManageTagsDialog.vue';
|
||||||
import MyAvatarCard from './components/MyAvatarCard.vue';
|
import MyAvatarCard from './components/MyAvatarCard.vue';
|
||||||
import configRepository from '../../service/config.js';
|
import configRepository from '../../service/config.js';
|
||||||
|
import { showAvatarDialog, selectAvatarWithoutConfirmation, applyAvatar } from '../../coordinators/avatarCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appearanceSettingsStore = useAppearanceSettingsStore();
|
const appearanceSettingsStore = useAppearanceSettingsStore();
|
||||||
const avatarStore = useAvatarStore();
|
const avatarStore = useAvatarStore();
|
||||||
const modalStore = useModalStore();
|
const modalStore = useModalStore();
|
||||||
const { showAvatarDialog, selectAvatarWithoutConfirmation, applyAvatar } = avatarStore;
|
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
|
|
||||||
const pageSizes = computed(() => appearanceSettingsStore.tablePageSizes);
|
const pageSizes = computed(() => appearanceSettingsStore.tablePageSizes);
|
||||||
|
|||||||
@@ -31,13 +31,14 @@ import { checkCanInvite, formatDateFilter } from '../../shared/utils';
|
|||||||
import { i18n } from '../../plugin';
|
import { i18n } from '../../plugin';
|
||||||
import {
|
import {
|
||||||
useGameStore,
|
useGameStore,
|
||||||
useGroupStore,
|
|
||||||
useLocationStore,
|
useLocationStore,
|
||||||
useUiStore,
|
useUiStore,
|
||||||
useUserStore,
|
useUserStore,
|
||||||
useWorldStore,
|
|
||||||
useNotificationStore
|
useNotificationStore
|
||||||
} from '../../stores';
|
} from '../../stores';
|
||||||
|
import { showUserDialog } from '../../coordinators/userCoordinator';
|
||||||
|
import { showWorldDialog } from '../../coordinators/worldCoordinator';
|
||||||
|
import { showGroupDialog } from '../../coordinators/groupCoordinator';
|
||||||
|
|
||||||
import Emoji from '../../components/Emoji.vue';
|
import Emoji from '../../components/Emoji.vue';
|
||||||
|
|
||||||
@@ -61,9 +62,8 @@ export const createColumns = ({
|
|||||||
deleteNotificationLog,
|
deleteNotificationLog,
|
||||||
deleteNotificationLogPrompt
|
deleteNotificationLogPrompt
|
||||||
}) => {
|
}) => {
|
||||||
const { showUserDialog, showSendBoopDialog } = useUserStore();
|
const { showSendBoopDialog } = useUserStore();
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
const { showGroupDialog } = useGroupStore();
|
|
||||||
const { shiftHeld } = storeToRefs(useUiStore());
|
const { shiftHeld } = storeToRefs(useUiStore());
|
||||||
const { currentUser } = storeToRefs(useUserStore());
|
const { currentUser } = storeToRefs(useUserStore());
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
|
|||||||
@@ -196,6 +196,7 @@
|
|||||||
|
|
||||||
import ChatboxBlacklistDialog from './dialogs/ChatboxBlacklistDialog.vue';
|
import ChatboxBlacklistDialog from './dialogs/ChatboxBlacklistDialog.vue';
|
||||||
import Timer from '../../components/Timer.vue';
|
import Timer from '../../components/Timer.vue';
|
||||||
|
import { showUserDialog, lookupUser } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const PhotonEventTable = defineAsyncComponent(() => import('./components/PhotonEventTable.vue'));
|
const PhotonEventTable = defineAsyncComponent(() => import('./components/PhotonEventTable.vue'));
|
||||||
|
|
||||||
@@ -203,7 +204,7 @@
|
|||||||
const photonStore = usePhotonStore();
|
const photonStore = usePhotonStore();
|
||||||
const { photonLoggingEnabled, chatboxUserBlacklist } = storeToRefs(photonStore);
|
const { photonLoggingEnabled, chatboxUserBlacklist } = storeToRefs(photonStore);
|
||||||
const { saveChatboxUserBlacklist } = photonStore;
|
const { saveChatboxUserBlacklist } = photonStore;
|
||||||
const { showUserDialog, lookupUser } = useUserStore();
|
|
||||||
const { showWorldDialog } = useWorldStore();
|
const { showWorldDialog } = useWorldStore();
|
||||||
const { lastLocation } = storeToRefs(useLocationStore());
|
const { lastLocation } = storeToRefs(useLocationStore());
|
||||||
const { currentInstanceLocation, currentInstanceWorld, currentInstanceUsersData } = storeToRefs(useInstanceStore());
|
const { currentInstanceLocation, currentInstanceWorld, currentInstanceUsersData } = storeToRefs(useInstanceStore());
|
||||||
|
|||||||
@@ -83,9 +83,11 @@
|
|||||||
useVrcxStore,
|
useVrcxStore,
|
||||||
useWorldStore
|
useWorldStore
|
||||||
} from '../../../stores';
|
} from '../../../stores';
|
||||||
|
import { showWorldDialog } from '../../../coordinators/worldCoordinator';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../components/ui/select';
|
||||||
import { createColumns } from './photonEventColumns.jsx';
|
import { createColumns } from './photonEventColumns.jsx';
|
||||||
import { photonEventTableTypeFilterList } from '../../../shared/constants/photon';
|
import { photonEventTableTypeFilterList } from '../../../shared/constants/photon';
|
||||||
|
import { lookupUser } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const emit = defineEmits(['show-chatbox-blacklist']);
|
const emit = defineEmits(['show-chatbox-blacklist']);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -106,9 +108,9 @@
|
|||||||
|
|
||||||
const { stringComparer } = storeToRefs(useSearchStore());
|
const { stringComparer } = storeToRefs(useSearchStore());
|
||||||
|
|
||||||
const { lookupUser } = useUserStore();
|
|
||||||
const { showAvatarDialog } = useAvatarStore();
|
const { showAvatarDialog } = useAvatarStore();
|
||||||
const { showWorldDialog } = useWorldStore();
|
|
||||||
const { showGroupDialog } = useGroupStore();
|
const { showGroupDialog } = useGroupStore();
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
const { ipcEnabled } = storeToRefs(useVrcxStore());
|
const { ipcEnabled } = storeToRefs(useVrcxStore());
|
||||||
|
|||||||
@@ -402,13 +402,14 @@
|
|||||||
userImage
|
userImage
|
||||||
} from '../../shared/utils';
|
} from '../../shared/utils';
|
||||||
import { groupRequest, worldRequest } from '../../api';
|
import { groupRequest, worldRequest } from '../../api';
|
||||||
|
import { showUserDialog, refreshUserDialogAvatars } from '../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { randomUserColours } = storeToRefs(useAppearanceSettingsStore());
|
const { randomUserColours } = storeToRefs(useAppearanceSettingsStore());
|
||||||
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
const { avatarRemoteDatabase } = storeToRefs(useAdvancedSettingsStore());
|
||||||
const { avatarRemoteDatabaseProviderList, avatarRemoteDatabaseProvider } = storeToRefs(useAvatarProviderStore());
|
const { avatarRemoteDatabaseProviderList, avatarRemoteDatabaseProvider } = storeToRefs(useAvatarProviderStore());
|
||||||
const { setAvatarProvider } = useAvatarProviderStore();
|
const { setAvatarProvider } = useAvatarProviderStore();
|
||||||
const { userDialog } = storeToRefs(useUserStore());
|
const { userDialog } = storeToRefs(useUserStore());
|
||||||
const { showUserDialog, refreshUserDialogAvatars } = useUserStore();
|
|
||||||
const { showAvatarDialog, lookupAvatars, cachedAvatars } = useAvatarStore();
|
const { showAvatarDialog, lookupAvatars, cachedAvatars } = useAvatarStore();
|
||||||
const { cachedWorlds, showWorldDialog } = useWorldStore();
|
const { cachedWorlds, showWorldDialog } = useWorldStore();
|
||||||
const { showGroupDialog } = useGroupStore();
|
const { showGroupDialog } = useGroupStore();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
import { userImage, userStatusClass } from '../../../shared/utils';
|
import { userImage, userStatusClass } from '../../../shared/utils';
|
||||||
|
|
||||||
import '@/styles/status-icon.css';
|
import '@/styles/status-icon.css';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
friend: { type: Object, required: true },
|
friend: { type: Object, required: true },
|
||||||
@@ -89,7 +90,7 @@
|
|||||||
const { hideNicknames } = storeToRefs(useAppearanceSettingsStore());
|
const { hideNicknames } = storeToRefs(useAppearanceSettingsStore());
|
||||||
const { isRefreshFriendsLoading, allFavoriteFriendIds } = storeToRefs(useFriendStore());
|
const { isRefreshFriendsLoading, allFavoriteFriendIds } = storeToRefs(useFriendStore());
|
||||||
const { confirmDeleteFriend } = useFriendStore();
|
const { confirmDeleteFriend } = useFriendStore();
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const isFriendTraveling = computed(() => props.friend.ref?.location === 'traveling');
|
const isFriendTraveling = computed(() => props.friend.ref?.location === 'traveling');
|
||||||
|
|||||||
@@ -216,6 +216,7 @@
|
|||||||
import configRepository from '../../../service/config';
|
import configRepository from '../../../service/config';
|
||||||
|
|
||||||
import '@/styles/status-icon.css';
|
import '@/styles/status-icon.css';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@@ -238,7 +239,7 @@
|
|||||||
sidebarSortMethods
|
sidebarSortMethods
|
||||||
} = storeToRefs(appearanceSettingsStore);
|
} = storeToRefs(appearanceSettingsStore);
|
||||||
const { gameLogDisabled } = storeToRefs(useAdvancedSettingsStore());
|
const { gameLogDisabled } = storeToRefs(useAdvancedSettingsStore());
|
||||||
const { showUserDialog, showSendBoopDialog } = useUserStore();
|
const { showSendBoopDialog } = useUserStore();
|
||||||
const launchStore = useLaunchStore();
|
const launchStore = useLaunchStore();
|
||||||
const { favoriteFriendGroups, groupedByGroupKeyFavoriteFriends, localFriendFavorites } =
|
const { favoriteFriendGroups, groupedByGroupKeyFavoriteFriends, localFriendFavorites } =
|
||||||
storeToRefs(useFavoriteStore());
|
storeToRefs(useFavoriteStore());
|
||||||
|
|||||||
@@ -255,6 +255,8 @@
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import { useGameStore, useGroupStore, useLocationStore, useNotificationStore, useUserStore } from '../../../stores';
|
import { useGameStore, useGroupStore, useLocationStore, useNotificationStore, useUserStore } from '../../../stores';
|
||||||
|
import { showGroupDialog } from '../../../coordinators/groupCoordinator';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
import { checkCanInvite, userImage } from '../../../shared/utils';
|
import { checkCanInvite, userImage } from '../../../shared/utils';
|
||||||
|
|
||||||
import Location from '../../../components/Location.vue';
|
import Location from '../../../components/Location.vue';
|
||||||
@@ -461,13 +463,13 @@
|
|||||||
if (userId.startsWith('grp_') || n.type?.startsWith('group.') || n.type === 'groupChange') {
|
if (userId.startsWith('grp_') || n.type?.startsWith('group.') || n.type === 'groupChange') {
|
||||||
const groupId = userId.startsWith('grp_') ? userId : n.data?.groupId || n.details?.groupId || '';
|
const groupId = userId.startsWith('grp_') ? userId : n.data?.groupId || n.details?.groupId || '';
|
||||||
if (groupId) {
|
if (groupId) {
|
||||||
groupStore.showGroupDialog(groupId);
|
showGroupDialog(groupId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
userStore.showUserDialog(userId);
|
showUserDialog(userId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,11 +66,12 @@
|
|||||||
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
import { useVrcxVueTable } from '../../../lib/table/useVrcxVueTable';
|
||||||
|
|
||||||
import * as workerTimers from 'worker-timers';
|
import * as workerTimers from 'worker-timers';
|
||||||
|
import { showUserDialog } from '../../../coordinators/userCoordinator';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { friends } = storeToRefs(useFriendStore());
|
const { friends } = storeToRefs(useFriendStore());
|
||||||
const { showUserDialog } = useUserStore();
|
|
||||||
const { showFullscreenImageDialog } = useGalleryStore();
|
const { showFullscreenImageDialog } = useGalleryStore();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
Reference in New Issue
Block a user