Support custom instance names

This commit is contained in:
Natsumi
2025-09-28 11:35:49 +13:00
parent 81a51ad2fa
commit da3c12c15b
10 changed files with 148 additions and 50 deletions

View File

@@ -21,6 +21,35 @@ const instanceReq = {
}); });
}, },
/**
* @param {{worldId: string, instanceId: string}} params
* @returns {Promise<{json: any, ref: any, cache?: boolean, params}>}
*/
getCachedInstance(params) {
const instanceStore = useInstanceStore();
return new Promise((resolve, reject) => {
const ref = instanceStore.cachedInstances.get(
`${params.worldId}:${params.instanceId}`
);
if (typeof ref === 'undefined') {
instanceReq
.getInstance(params)
.then((args) => {
args.ref = instanceStore.applyInstance(args.json);
resolve(args);
})
.catch(reject);
} else {
resolve({
cache: true,
json: ref,
params,
ref
});
}
});
},
/** /**
* @type {import('../types/api/instance').CreateInstance} * @type {import('../types/api/instance').CreateInstance}
*/ */

View File

@@ -45,11 +45,11 @@ const userReq = {
if (typeof ref === 'undefined') { if (typeof ref === 'undefined') {
userReq userReq
.getUser(params) .getUser(params)
.catch(reject)
.then((args) => { .then((args) => {
args.ref = userStore.applyUser(args.json); args.ref = userStore.applyUser(args.json);
resolve(args); resolve(args);
}); })
.catch(reject);
} else { } else {
resolve({ resolve({
cache: true, cache: true,

View File

@@ -30,11 +30,11 @@ const worldReq = {
if (typeof ref === 'undefined') { if (typeof ref === 'undefined') {
worldReq worldReq
.getWorld(params) .getWorld(params)
.catch(reject)
.then((args) => { .then((args) => {
args.ref = worldStore.applyWorld(args.json); args.ref = worldStore.applyWorld(args.json);
resolve(args); resolve(args);
}); })
.catch(reject);
} else { } else {
resolve({ resolve({
cache: true, cache: true,

View File

@@ -25,7 +25,7 @@
const { cachedWorlds, showWorldDialog } = useWorldStore(); const { cachedWorlds, showWorldDialog } = useWorldStore();
const { showGroupDialog } = useGroupStore(); const { showGroupDialog } = useGroupStore();
const { showPreviousInstancesInfoDialog } = useInstanceStore(); const { getInstanceName, showPreviousInstancesInfoDialog } = useInstanceStore();
const { verifyShortName } = useSearchStore(); const { verifyShortName } = useSearchStore();
const props = defineProps({ const props = defineProps({
@@ -65,45 +65,30 @@
isTraveling.value = true; isTraveling.value = true;
} }
const L = parseLocation(instanceId); const L = parseLocation(instanceId);
if (L.isOffline) { setText(L, L.instanceName);
text.value = 'Offline'; getInstanceName(instanceId)
} else if (L.isPrivate) { .then((name) => {
text.value = 'Private'; if (name && props.location === L.tag) {
} else if (L.isTraveling) { setText(L, name);
text.value = 'Traveling'; }
} else if (typeof props.hint === 'string' && props.hint !== '') { })
if (L.instanceId) { .catch((e) => {
text.value = `${props.hint} #${L.instanceName} ${L.accessTypeName}`; console.error(e);
} else { });
text.value = props.hint;
}
} else if (L.worldId) {
const ref = cachedWorlds.get(L.worldId);
if (typeof ref === 'undefined') {
getWorldName(L.worldId).then((worldName) => {
if (L.tag === instanceId) {
if (L.instanceId) {
text.value = `${worldName} #${L.instanceName} ${L.accessTypeName}`;
} else {
text.value = worldName;
}
}
});
} else if (L.instanceId) {
text.value = `${ref.name} #${L.instanceName} ${L.accessTypeName}`;
} else {
text.value = ref.name;
}
}
if (props.grouphint) { if (props.grouphint) {
groupName.value = props.grouphint; groupName.value = props.grouphint;
} else if (L.groupId) { } else if (L.groupId) {
groupName.value = L.groupId; groupName.value = L.groupId;
getGroupName(instanceId).then((name) => { getGroupName(instanceId)
if (L.tag === instanceId) { .then((name) => {
groupName.value = name; if (name && props.location === L.tag) {
} groupName.value = name;
}); }
})
.catch((e) => {
console.error(e);
});
} }
region.value = ''; region.value = '';
if (!L.isOffline && !L.isPrivate && !L.isTraveling) { if (!L.isOffline && !L.isPrivate && !L.isTraveling) {
@@ -115,6 +100,49 @@
strict.value = L.strict; strict.value = L.strict;
} }
function setText(L, instanceName) {
if (L.isOffline) {
text.value = 'Offline';
} else if (L.isPrivate) {
text.value = 'Private';
} else if (L.isTraveling) {
text.value = 'Traveling';
} else if (typeof props.hint === 'string' && props.hint !== '') {
if (L.instanceId) {
text.value = `${props.hint} #${instanceName} ${L.accessTypeName}`;
} else {
text.value = props.hint;
}
} else if (L.worldId) {
const ref = cachedWorlds.get(L.worldId);
if (typeof ref === 'undefined') {
const worldName = L.worldId;
if (L.instanceId) {
text.value = `${worldName} #${instanceName} ${L.accessTypeName}`;
} else {
text.value = worldName;
}
getWorldName(L.worldId)
.then((name) => {
if (name && props.location === L.tag) {
if (L.instanceId) {
text.value = `${name} #${instanceName} ${L.accessTypeName}`;
} else {
text.value = name;
}
}
})
.catch((e) => {
console.error(e);
});
} else if (L.instanceId) {
text.value = `${ref.name} #${instanceName} ${L.accessTypeName}`;
} else {
text.value = ref.name;
}
}
}
function handleShowWorldDialog() { function handleShowWorldDialog() {
if (props.link) { if (props.link) {
let instanceId = props.location; let instanceId = props.location;

View File

@@ -14,10 +14,11 @@
import { Lock, Unlock } from '@element-plus/icons-vue'; import { Lock, Unlock } from '@element-plus/icons-vue';
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { getGroupName, parseLocation } from '../shared/utils'; import { getGroupName, parseLocation } from '../shared/utils';
import { useGroupStore, useLaunchStore } from '../stores'; import { useGroupStore, useLaunchStore, useInstanceStore } from '../stores';
const launchStore = useLaunchStore(); const launchStore = useLaunchStore();
const groupStore = useGroupStore(); const groupStore = useGroupStore();
const { getInstanceName } = useInstanceStore();
const props = defineProps({ const props = defineProps({
locationobject: Object, locationobject: Object,
@@ -41,7 +42,6 @@
function parse() { function parse() {
const locObj = props.locationobject; const locObj = props.locationobject;
location.value = locObj.tag; location.value = locObj.tag;
instanceName.value = locObj.instanceName;
accessTypeName.value = locObj.accessTypeName; accessTypeName.value = locObj.accessTypeName;
strict.value = locObj.strict; strict.value = locObj.strict;
shortName.value = locObj.shortName; shortName.value = locObj.shortName;
@@ -52,17 +52,29 @@
region.value = locObj.region || 'us'; region.value = locObj.region || 'us';
instanceName.value = locObj.instanceName;
getInstanceName(locObj.tag)
.then((name) => {
if (name && props.locationobject.tag === locObj.tag) {
instanceName.value = name;
}
})
.catch((e) => {
console.error(e);
});
if (props.grouphint) { if (props.grouphint) {
groupName.value = props.grouphint; groupName.value = props.grouphint;
} else if (locObj.groupId) { } else if (locObj.groupId) {
groupName.value = locObj.groupId; groupName.value = locObj.groupId;
getGroupName(locObj.groupId) getGroupName(locObj.groupId)
.then((name) => { .then((name) => {
groupName.value = name; if (name && props.locationobject.tag === locObj.tag) {
groupName.value = name;
}
}) })
.catch((error) => { .catch((e) => {
console.error('Failed to get group name:', error); console.error(e);
groupName.value = '';
}); });
} else { } else {
groupName.value = ''; groupName.value = '';

View File

@@ -84,14 +84,14 @@
" "
@change="buildInstance"></el-checkbox> @change="buildInstance"></el-checkbox>
</el-form-item> </el-form-item>
<!-- <el-form-item :label="t('dialog.new_instance.display_name')"> <el-form-item :label="t('dialog.new_instance.display_name')">
<el-input <el-input
:disabled="!isLocalUserVrcplusSupporter" :disabled="!isLocalUserVrcplusSupporter"
v-model="newInstanceDialog.displayName" v-model="newInstanceDialog.displayName"
size="small" size="small"
@click="$event.target.tagName === 'INPUT' && $event.target.select()" @click="$event.target.tagName === 'INPUT' && $event.target.select()"
@change="buildInstance"></el-input> @change="buildInstance"></el-input>
</el-form-item> --> </el-form-item>
<el-form-item <el-form-item
v-if="newInstanceDialog.accessType === 'group'" v-if="newInstanceDialog.accessType === 'group'"
:label="t('dialog.new_instance.group_id')"> :label="t('dialog.new_instance.group_id')">

View File

@@ -290,6 +290,12 @@ export function $throw(code, error, endpoint) {
) { ) {
ignoreError = true; ignoreError = true;
} }
if (
(code === 403 || code === 404 || code === -1) &&
endpoint.startsWith('instances/')
) {
ignoreError = true;
}
if (endpoint.startsWith('analysis/')) { if (endpoint.startsWith('analysis/')) {
ignoreError = true; ignoreError = true;
} }

View File

@@ -32,9 +32,11 @@ function isRealInstance(instanceId) {
case 'private:private': case 'private:private':
case 'traveling': case 'traveling':
case 'traveling:traveling': case 'traveling:traveling':
case instanceId.startsWith('local'):
return false; return false;
} }
if (instanceId.startsWith('local')) {
return false;
}
return true; return true;
} }

View File

@@ -416,6 +416,21 @@ export const useInstanceStore = defineStore('Instance', () => {
return ref; return ref;
} }
async function getInstanceName(location) {
let instanceName = '';
const L = parseLocation(location);
if (L.isRealInstance && L.worldId && L.instanceId) {
const args = await instanceRequest.getCachedInstance({
worldId: L.worldId,
instanceId: L.instanceId
});
instanceName = args.ref.displayName;
}
return instanceName;
}
/** /**
* *
* @param {string} worldId * @param {string} worldId
@@ -1229,6 +1244,7 @@ export const useInstanceStore = defineStore('Instance', () => {
showPreviousInstancesInfoDialog, showPreviousInstancesInfoDialog,
addInstanceJoinHistory, addInstanceJoinHistory,
getCurrentInstanceUserList, getCurrentInstanceUserList,
getInstanceJoinHistory getInstanceJoinHistory,
getInstanceName
}; };
}); });

View File

@@ -316,6 +316,11 @@ export const useVrcxStore = defineStore('Vrcx', () => {
} }
}); });
instanceStore.cachedInstances.forEach((ref, id) => { instanceStore.cachedInstances.forEach((ref, id) => {
if (
friendStore.friends.values().some((f) => f.$location.tag === id)
) {
return;
}
// delete instances over an hour old // delete instances over an hour old
if (Date.parse(ref.$fetchedAt) < Date.now() - 3600000) { if (Date.parse(ref.$fetchedAt) < Date.now() - 3600000) {
instanceStore.cachedInstances.delete(id); instanceStore.cachedInstances.delete(id);