mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-16 21:33:51 +02:00
314 lines
12 KiB
Vue
314 lines
12 KiB
Vue
<template>
|
|
<el-dialog :z-index="launchDialogIndex" v-model="isVisible" :title="t('dialog.launch.header')" width="450px">
|
|
<el-form :model="launchDialog" label-width="100px">
|
|
<el-form-item :label="t('dialog.launch.url')">
|
|
<el-input
|
|
v-model="launchDialog.url"
|
|
size="small"
|
|
style="width: 230px"
|
|
@click="$event.target.tagName === 'INPUT' && $event.target.select()" />
|
|
<el-tooltip placement="right" :content="t('dialog.launch.copy_tooltip')">
|
|
<el-button
|
|
size="small"
|
|
:icon="CopyDocument"
|
|
style="margin-left: 5px"
|
|
circle
|
|
@click="copyInstanceMessage(launchDialog.url)" />
|
|
</el-tooltip>
|
|
</el-form-item>
|
|
<el-form-item v-if="launchDialog.shortUrl">
|
|
<template #label>
|
|
<span>{{ t('dialog.launch.short_url') }}</span>
|
|
<el-tooltip placement="top" :content="t('dialog.launch.short_url_notice')">
|
|
<el-icon style="display: inline-block; margin-left: 5px"><Warning /></el-icon>
|
|
</el-tooltip>
|
|
</template>
|
|
<el-input
|
|
v-model="launchDialog.shortUrl"
|
|
size="small"
|
|
style="width: 230px"
|
|
@click="$event.target.tagName === 'INPUT' && $event.target.select()" />
|
|
<el-tooltip placement="right" :content="t('dialog.launch.copy_tooltip')">
|
|
<el-button
|
|
size="small"
|
|
:icon="CopyDocument"
|
|
style="display: inline-block; margin-left: 5px"
|
|
circle
|
|
@click="copyInstanceMessage(launchDialog.shortUrl)" />
|
|
</el-tooltip>
|
|
</el-form-item>
|
|
<el-form-item :label="t('dialog.launch.location')">
|
|
<el-input
|
|
v-model="launchDialog.location"
|
|
size="small"
|
|
style="width: 230px"
|
|
@click="$event.target.tagName === 'INPUT' && $event.target.select()" />
|
|
<el-tooltip placement="right" :content="t('dialog.launch.copy_tooltip')">
|
|
<el-button
|
|
size="small"
|
|
:icon="CopyDocument"
|
|
style="display: inline-block; margin-left: 5px"
|
|
circle
|
|
@click="copyInstanceMessage(launchDialog.location)" />
|
|
</el-tooltip>
|
|
</el-form-item>
|
|
</el-form>
|
|
<el-checkbox
|
|
v-model="launchDialog.desktop"
|
|
style="display: inline-flex; align-items: center; margin-top: 5px"
|
|
@change="saveLaunchDialog">
|
|
{{ t('dialog.launch.start_as_desktop') }}
|
|
</el-checkbox>
|
|
<template #footer>
|
|
<el-button
|
|
:disabled="!checkCanInvite(launchDialog.location)"
|
|
@click="showInviteDialog(launchDialog.location)">
|
|
{{ t('dialog.launch.invite') }}
|
|
</el-button>
|
|
<template v-if="canOpenInstanceInGame()">
|
|
<el-button
|
|
:disabled="!launchDialog.secureOrShortName"
|
|
@click="handleLaunchGame(launchDialog.location, launchDialog.shortName, launchDialog.desktop)">
|
|
{{ t('dialog.launch.launch') }}
|
|
</el-button>
|
|
<el-button
|
|
type="primary"
|
|
:disabled="!launchDialog.secureOrShortName"
|
|
@click="handleAttachGame(launchDialog.location, launchDialog.shortName)">
|
|
{{ t('dialog.launch.open_ingame') }}
|
|
</el-button>
|
|
</template>
|
|
<template v-else>
|
|
<el-button
|
|
:disabled="!launchDialog.secureOrShortName"
|
|
@click="selfInvite(launchDialog.location, launchDialog.shortName)">
|
|
{{ t('dialog.launch.self_invite') }}
|
|
</el-button>
|
|
<el-button
|
|
type="primary"
|
|
:disabled="!launchDialog.secureOrShortName"
|
|
@click="handleLaunchGame(launchDialog.location, launchDialog.shortName, launchDialog.desktop)">
|
|
{{ t('dialog.launch.launch') }}
|
|
</el-button>
|
|
</template>
|
|
</template>
|
|
<InviteDialog :invite-dialog="inviteDialog" @closeInviteDialog="closeInviteDialog" />
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { CopyDocument, Warning } from '@element-plus/icons-vue';
|
|
|
|
import { ref, computed, nextTick, watch } from 'vue';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import { storeToRefs } from 'pinia';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { instanceRequest, worldRequest } from '../../api';
|
|
import configRepository from '../../service/config';
|
|
import { checkCanInvite, getLaunchURL, isRealInstance, parseLocation } from '../../shared/utils';
|
|
import { getNextDialogIndex } from '../../shared/utils/base/ui';
|
|
import {
|
|
useFriendStore,
|
|
useInviteStore,
|
|
useInstanceStore,
|
|
useLaunchStore,
|
|
useLocationStore,
|
|
useGameStore
|
|
} from '../../stores';
|
|
import InviteDialog from './InviteDialog/InviteDialog.vue';
|
|
|
|
const { t } = useI18n();
|
|
|
|
const { friends } = storeToRefs(useFriendStore());
|
|
const { lastLocation } = storeToRefs(useLocationStore());
|
|
const { launchGame, tryOpenInstanceInVrc } = useLaunchStore();
|
|
const { launchDialogData } = storeToRefs(useLaunchStore());
|
|
|
|
const { showPreviousInstancesInfoDialog } = useInstanceStore();
|
|
const { canOpenInstanceInGame } = useInviteStore();
|
|
const { isGameRunning } = storeToRefs(useGameStore());
|
|
|
|
const launchDialogIndex = ref(2000);
|
|
|
|
const launchDialog = ref({
|
|
loading: false,
|
|
desktop: false,
|
|
tag: '',
|
|
location: '',
|
|
url: '',
|
|
shortName: '',
|
|
shortUrl: '',
|
|
secureOrShortName: ''
|
|
});
|
|
|
|
const inviteDialog = ref({
|
|
visible: false,
|
|
loading: false,
|
|
worldId: '',
|
|
worldName: '',
|
|
userIds: [],
|
|
friendsInInstance: []
|
|
});
|
|
|
|
const isVisible = computed({
|
|
get() {
|
|
return launchDialogData.value.visible;
|
|
},
|
|
set(value) {
|
|
launchDialogData.value.visible = value;
|
|
}
|
|
});
|
|
|
|
watch(
|
|
() => launchDialogData.value.loading,
|
|
(loading) => {
|
|
if (loading) {
|
|
getConfig();
|
|
initLaunchDialog();
|
|
}
|
|
}
|
|
);
|
|
|
|
getConfig();
|
|
|
|
function closeInviteDialog() {
|
|
inviteDialog.value.visible = false;
|
|
}
|
|
function showInviteDialog(tag) {
|
|
if (!isRealInstance(tag)) {
|
|
return;
|
|
}
|
|
const L = parseLocation(tag);
|
|
worldRequest
|
|
.getCachedWorld({
|
|
worldId: L.worldId
|
|
})
|
|
.then((args) => {
|
|
const D = inviteDialog.value;
|
|
D.userIds = [];
|
|
D.worldId = L.tag;
|
|
D.worldName = args.ref.name;
|
|
D.friendsInInstance = [];
|
|
const friendsInCurrentInstance = lastLocation.value.friendList;
|
|
for (const friend of friendsInCurrentInstance.values()) {
|
|
const ctx = friends.value.get(friend.userId);
|
|
if (typeof ctx.ref === 'undefined') {
|
|
continue;
|
|
}
|
|
D.friendsInInstance.push(ctx);
|
|
}
|
|
D.visible = true;
|
|
});
|
|
}
|
|
function handleLaunchGame(location, shortName, desktop) {
|
|
if (isGameRunning.value) {
|
|
ElMessageBox.confirm(t('dialog.launch.game_running_warning'), t('dialog.launch.header'), {
|
|
confirmButtonText: t('dialog.launch.confirm_yes'),
|
|
cancelButtonText: t('dialog.launch.confirm_no'),
|
|
type: 'warning'
|
|
})
|
|
.then((action) => {
|
|
if (action === 'confirm') {
|
|
launchGame(location, shortName, desktop);
|
|
isVisible.value = false;
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
return;
|
|
}
|
|
launchGame(location, shortName, desktop);
|
|
isVisible.value = false;
|
|
}
|
|
function handleAttachGame(location, shortName) {
|
|
tryOpenInstanceInVrc(location, shortName);
|
|
isVisible.value = false;
|
|
}
|
|
function selfInvite(location, shortName) {
|
|
const L = parseLocation(location);
|
|
if (!L.isRealInstance) {
|
|
return;
|
|
}
|
|
instanceRequest
|
|
.selfInvite({
|
|
instanceId: L.instanceId,
|
|
worldId: L.worldId,
|
|
shortName
|
|
})
|
|
.then((args) => {
|
|
ElMessage({
|
|
message: 'Self invite sent',
|
|
type: 'success'
|
|
});
|
|
return args;
|
|
});
|
|
}
|
|
function getConfig() {
|
|
configRepository.getBool('launchAsDesktop').then((value) => (launchDialog.value.desktop = value));
|
|
}
|
|
function saveLaunchDialog() {
|
|
configRepository.setBool('launchAsDesktop', launchDialog.value.desktop);
|
|
}
|
|
async function initLaunchDialog() {
|
|
const { tag, shortName } = launchDialogData.value;
|
|
if (!isRealInstance(tag)) {
|
|
return;
|
|
}
|
|
nextTick(() => {
|
|
launchDialogIndex.value = getNextDialogIndex();
|
|
});
|
|
const D = launchDialog.value;
|
|
D.tag = tag;
|
|
D.secureOrShortName = shortName;
|
|
D.shortUrl = '';
|
|
D.shortName = shortName;
|
|
const L = parseLocation(tag);
|
|
L.shortName = shortName;
|
|
if (shortName) {
|
|
D.shortUrl = `https://vrch.at/${shortName}`;
|
|
}
|
|
if (L.instanceId) {
|
|
D.location = `${L.worldId}:${L.instanceId}`;
|
|
} else {
|
|
D.location = L.worldId;
|
|
}
|
|
D.url = getLaunchURL(L);
|
|
if (!shortName) {
|
|
const res = await instanceRequest.getInstanceShortName({
|
|
worldId: L.worldId,
|
|
instanceId: L.instanceId
|
|
});
|
|
if (!res.json) {
|
|
return;
|
|
}
|
|
const resLocation = `${res.instance.worldId}:${res.instance.instanceId}`;
|
|
if (resLocation === launchDialog.value.tag) {
|
|
const resShortName = res.json.shortName;
|
|
const secureOrShortName = res.json.shortName || res.json.secureName;
|
|
const parsedL = parseLocation(resLocation);
|
|
parsedL.shortName = resShortName;
|
|
launchDialog.value.shortName = resShortName;
|
|
launchDialog.value.secureOrShortName = secureOrShortName;
|
|
if (resShortName) {
|
|
launchDialog.value.shortUrl = `https://vrch.at/${resShortName}`;
|
|
}
|
|
launchDialog.value.url = getLaunchURL(parsedL);
|
|
}
|
|
}
|
|
}
|
|
async function copyInstanceMessage(input) {
|
|
try {
|
|
await navigator.clipboard.writeText(input);
|
|
ElMessage({
|
|
message: 'Instance copied to clipboard',
|
|
type: 'success'
|
|
});
|
|
} catch (error) {
|
|
ElMessage({
|
|
message: 'Instance copied failed',
|
|
type: 'error'
|
|
});
|
|
console.error(error.message);
|
|
}
|
|
}
|
|
</script>
|