Upgrade to Vue3 and Element Plus (#1374)

* Update Vue devtools

* upgrade vue pinia element-plus vue-i18n, add vite

* fix: i18n

* global components

* change v-deep

* upgrade vue-lazyload

* data table

* update enlint and safe-dialog

* package.json and vite.config.js

* el-icon

* el-message

* vue 2 -> vue3 migration changes

* $pinia

* dialog

* el-popover slot

* lint

* chore

* slot

* scss

* remote state access

* misc

* jsconfig

* el-button size mini -> small

* :model-value

* ElMessageBox

* datatable

* remove v-lazyload

* template #dropdown

* mini -> small

* css

* byebye hideTooltips

* use sass-embedded

* Update SQLite, remove unneeded libraries

* Fix shift remove local avatar favorites

* Electron arm64

* arm64 support

* bye pug

* f-word vite hah

* misc

* remove safe dialog component

* Add self invite to launch dialog

* Fix errors

* Icons 1

* improve localfavorite loading performance

* improve favorites world item performance

* dialog visibility changes for Element Plus

* clear element plus error

* import performance

* revert App.vue hah

* hah

* Revert "Add self invite to launch dialog"

This reverts commit 4801cfad58.

* Toggle self invite/open in-game

* Self invite on launch dialog

* el-button icon

* el-icon

* fix user dialog tab switching logic

* fix PlayerList

* Formatting changes

* More icons

* Fix friend log table

* loading margin

* fix markdown

* fix world dialog tab switching issue

* Fixes and formatting

* fix: global i18n.t export

* fix favorites world tab not working

* Create instance, displayName

* Remove group members sort by userId

* Fix loading dialog tabs on swtich

* Star

* charts console.warn

* wip: fix charts

* wip: fix charts

* wip: charts composables

* fix favorite item tooltip warning

* Fixes and formatting

* Clean up image dialogs

* Remove unused method

* Fix platform/size border

* Fix platform/size border

* $vr

* fix friendExportDialogVisible binding

* ElMessageBox and Settings

* Login formatting

* Rename VR overlay query

* Fix image popover and userdialog badges

* Formatting

* Big buttons

* Fixes, update Cef

* Fix gameLog table nav buttons jumping around while using nav buttons

* Fix z-index

* vr overlay

* vite input add theme

* defineAsyncComponent

* ISO 639-1

* fix i18n

* clean t

* Formatting, fix calendar, rotate arrows

* Show user status when user is offline

* Fix VR overlay

* fix theme and clean up

* split InstanceActivity

* tweak

* Fix VR overlay formatting

* fix scss var

* AppDebug hahahaha

* Years

* remove reactive

* improve perf

* state hah…

* fix user rendering poblems when user object is not yet loaded

* improve perf

* Update avatar/world image uploader, licenses, remove previous images dialog (old images are now deleted)

* improve perf 1

* Suppress stray errors

* fix traveling location display issue

* Fix empty instance creator

* improve friend list refresh performance

* fix main charts

* fix chart

* Fix darkmode

* Fix avatar dialog tags

---------

Co-authored-by: pa <maplenagisa@gmail.com>
This commit is contained in:
Natsumi
2025-09-12 10:45:24 +12:00
committed by GitHub
parent b233bbc299
commit 3324d0d279
249 changed files with 12948 additions and 19815 deletions

View File

@@ -1,15 +1,15 @@
<template>
<safe-dialog
ref="newInstanceDialogRef"
:visible.sync="newInstanceDialog.visible"
<el-dialog
:z-index="newInstanceDialogIndex"
v-model="newInstanceDialog.visible"
:title="t('dialog.new_instance.header')"
width="650px"
append-to-body>
<el-tabs v-model="newInstanceDialog.selectedTab" type="card" @tab-click="newInstanceTabClick">
<el-tab-pane :label="t('dialog.new_instance.normal')">
<el-tab-pane name="Normal" :label="t('dialog.new_instance.normal')">
<el-form :model="newInstanceDialog" label-width="150px">
<el-form-item :label="t('dialog.new_instance.access_type')">
<el-radio-group v-model="newInstanceDialog.accessType" size="mini" @change="buildInstance">
<el-radio-group v-model="newInstanceDialog.accessType" size="small" @change="buildInstance">
<el-radio-button label="public">{{
t('dialog.new_instance.access_type_public')
}}</el-radio-button>
@@ -33,7 +33,10 @@
<el-form-item
v-if="newInstanceDialog.accessType === 'group'"
:label="t('dialog.new_instance.group_access_type')">
<el-radio-group v-model="newInstanceDialog.groupAccessType" size="mini" @change="buildInstance">
<el-radio-group
v-model="newInstanceDialog.groupAccessType"
size="small"
@change="buildInstance">
<el-radio-button
label="members"
:disabled="
@@ -59,7 +62,7 @@
</el-radio-group>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.region')">
<el-radio-group v-model="newInstanceDialog.region" size="mini" @change="buildInstance">
<el-radio-group v-model="newInstanceDialog.region" size="small" @change="buildInstance">
<el-radio-button label="US West">{{ t('dialog.new_instance.region_usw') }}</el-radio-button>
<el-radio-button label="US East">{{ t('dialog.new_instance.region_use') }}</el-radio-button>
<el-radio-button label="Europe">{{ t('dialog.new_instance.region_eu') }}</el-radio-button>
@@ -84,8 +87,16 @@
<el-form-item :label="t('dialog.new_instance.world_id')">
<el-input
v-model="newInstanceDialog.worldId"
size="mini"
@click.native="$event.target.tagName === 'INPUT' && $event.target.select()"
size="small"
@click="$event.target.tagName === 'INPUT' && $event.target.select()"
@change="buildInstance"></el-input>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.display_name')">
<el-input
:disabled="!isLocalUserVrcplusSupporter"
v-model="newInstanceDialog.displayName"
size="small"
@click="$event.target.tagName === 'INPUT' && $event.target.select()"
@change="buildInstance"></el-input>
</el-form-item>
<el-form-item
@@ -114,7 +125,7 @@
hasGroupPermission(group, 'group-instance-open-create'))
">
<div class="avatar">
<img v-lazy="group.iconUrl" />
<img :src="group.iconUrl" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="group.name"></span>
@@ -155,22 +166,22 @@
<el-form-item :label="t('dialog.new_instance.location')">
<el-input
v-model="newInstanceDialog.location"
size="mini"
size="small"
readonly
@click.native="$event.target.tagName === 'INPUT' && $event.target.select()"></el-input>
@click="$event.target.tagName === 'INPUT' && $event.target.select()"></el-input>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.url')">
<el-input v-model="newInstanceDialog.url" size="mini" readonly></el-input>
<el-input v-model="newInstanceDialog.url" size="small" readonly></el-input>
</el-form-item>
</template>
</el-form>
</el-tab-pane>
<el-tab-pane :label="t('dialog.new_instance.legacy')">
<el-tab-pane name="Legacy" :label="t('dialog.new_instance.legacy')">
<el-form :model="newInstanceDialog" label-width="150px">
<el-form-item :label="t('dialog.new_instance.access_type')">
<el-radio-group
v-model="newInstanceDialog.accessType"
size="mini"
size="small"
@change="buildLegacyInstance">
<el-radio-button label="public">{{
t('dialog.new_instance.access_type_public')
@@ -197,7 +208,7 @@
:label="t('dialog.new_instance.group_access_type')">
<el-radio-group
v-model="newInstanceDialog.groupAccessType"
size="mini"
size="small"
@change="buildLegacyInstance">
<el-radio-button label="members">{{
t('dialog.new_instance.group_access_type_members')
@@ -211,7 +222,7 @@
</el-radio-group>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.region')">
<el-radio-group v-model="newInstanceDialog.region" size="mini" @change="buildLegacyInstance">
<el-radio-group v-model="newInstanceDialog.region" size="small" @change="buildLegacyInstance">
<el-radio-button label="US West">{{ t('dialog.new_instance.region_usw') }}</el-radio-button>
<el-radio-button label="US East">{{ t('dialog.new_instance.region_use') }}</el-radio-button>
<el-radio-button label="Europe">{{ t('dialog.new_instance.region_eu') }}</el-radio-button>
@@ -226,15 +237,15 @@
<el-form-item :label="t('dialog.new_instance.world_id')">
<el-input
v-model="newInstanceDialog.worldId"
size="mini"
@click.native="$event.target.tagName === 'INPUT' && $event.target.select()"
size="small"
@click="$event.target.tagName === 'INPUT' && $event.target.select()"
@change="buildLegacyInstance"></el-input>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.instance_id')">
<el-input
v-model="newInstanceDialog.instanceName"
:placeholder="t('dialog.new_instance.instance_id_placeholder')"
size="mini"
size="small"
@change="buildLegacyInstance"></el-input>
</el-form-item>
<el-form-item
@@ -254,7 +265,7 @@
:value="currentUser.id"
style="height: auto">
<div class="avatar" :class="userStatusClass(currentUser)">
<img v-lazy="userImage(currentUser)" />
<img :src="userImage(currentUser)" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="currentUser.displayName"></span>
@@ -271,7 +282,7 @@
style="height: auto">
<template v-if="friend.ref">
<div class="avatar" :class="userStatusClass(friend.ref)">
<img v-lazy="userImage(friend.ref)" />
<img :src="userImage(friend.ref)" loading="lazy" />
</div>
<div class="detail">
<span
@@ -293,7 +304,7 @@
style="height: auto">
<template v-if="friend.ref">
<div class="avatar" :class="userStatusClass(friend.ref)">
<img v-lazy="userImage(friend.ref)" />
<img :src="userImage(friend.ref)" loading="lazy" />
</div>
<div class="detail">
<span
@@ -315,7 +326,7 @@
style="height: auto">
<template v-if="friend.ref">
<div class="avatar">
<img v-lazy="userImage(friend.ref)" />
<img :src="userImage(friend.ref)" loading="lazy" />
</div>
<div class="detail">
<span
@@ -337,7 +348,7 @@
style="height: auto">
<template v-if="friend.ref">
<div class="avatar">
<img v-lazy="userImage(friend.ref)" />
<img :src="userImage(friend.ref)" loading="lazy" />
</div>
<div class="detail">
<span
@@ -371,7 +382,7 @@
style="height: auto; width: 478px">
<template v-if="group">
<div class="avatar">
<img v-lazy="group.iconUrl" />
<img :src="group.iconUrl" loading="lazy" />
</div>
<div class="detail">
<span class="name" v-text="group.name"></span></div
@@ -383,17 +394,17 @@
<el-form-item :label="t('dialog.new_instance.location')">
<el-input
v-model="newInstanceDialog.location"
size="mini"
size="small"
readonly
@click.native="$event.target.tagName === 'INPUT' && $event.target.select()"></el-input>
@click="$event.target.tagName === 'INPUT' && $event.target.select()"></el-input>
</el-form-item>
<el-form-item :label="t('dialog.new_instance.url')">
<el-input v-model="newInstanceDialog.url" size="mini" readonly></el-input>
<el-input v-model="newInstanceDialog.url" size="small" readonly></el-input>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<template v-if="newInstanceDialog.selectedTab === '0'" #footer>
<template v-if="newInstanceDialog.selectedTab === 'Normal'" #footer>
<template v-if="newInstanceDialog.instanceCreated">
<el-button size="small" @click="copyInstanceUrl(newInstanceDialog.location)">{{
t('dialog.new_instance.copy_url')
@@ -412,13 +423,11 @@
>
<template v-if="canOpenInstanceInGame()">
<el-button
type="default"
size="small"
@click="showLaunchDialog(newInstanceDialog.location, newInstanceDialog.shortName)"
>{{ t('dialog.new_instance.launch') }}</el-button
>
<el-button
type="primary"
size="small"
@click="handleAttachGame(newInstanceDialog.location, newInstanceDialog.shortName)">
{{ t('dialog.new_instance.open_ingame') }}
@@ -439,7 +448,7 @@
}}</el-button>
</template>
</template>
<template v-else-if="newInstanceDialog.selectedTab === '1'" #footer>
<template v-else-if="newInstanceDialog.selectedTab === 'Legacy'" #footer>
<el-button size="small" @click="copyInstanceUrl(newInstanceDialog.location)">{{
t('dialog.new_instance.copy_url')
}}</el-button>
@@ -457,7 +466,6 @@
>
<template v-if="canOpenInstanceInGame()">
<el-button
type="default"
size="small"
@click="showLaunchDialog(newInstanceDialog.location, newInstanceDialog.shortName)"
>{{ t('dialog.new_instance.launch') }}</el-button
@@ -479,17 +487,18 @@
</template>
</template>
<InviteDialog :invite-dialog="inviteDialog" @closeInviteDialog="closeInviteDialog" />
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { ref, watch, nextTick, getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { ref, watch, nextTick, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { groupRequest, instanceRequest, worldRequest } from '../../api';
import configRepository from '../../service/config';
import {
adjustDialogZ,
getNextDialogIndex,
copyToClipboard,
getLaunchURL,
hasGroupPermission,
@@ -518,11 +527,9 @@
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const { friends, vipFriends, onlineFriends, activeFriends, offlineFriends } = storeToRefs(useFriendStore());
const { currentUserGroups, cachedGroups } = storeToRefs(useGroupStore());
const { handleGroupPermissions } = useGroupStore();
const { currentUserGroups } = storeToRefs(useGroupStore());
const { cachedGroups, handleGroupPermissions } = useGroupStore();
const { lastLocation } = storeToRefs(useLocationStore());
const { showLaunchDialog } = useLaunchStore();
const { createNewInstance } = useInstanceStore();
@@ -530,12 +537,12 @@
const { tryOpenInstanceInVrc } = useLaunchStore();
const { canOpenInstanceInGame } = useInviteStore();
const newInstanceDialogRef = ref(null);
const newInstanceDialogIndex = ref(2000);
const newInstanceDialog = ref({
visible: false,
// loading: false,
selectedTab: '0',
selectedTab: 'Normal',
instanceCreated: false,
queueEnabled: false,
worldId: '',
@@ -551,6 +558,7 @@
strict: false,
location: '',
shortName: '',
displayName: '',
url: '',
secureOrShortName: '',
lastSelectedGroupId: '',
@@ -575,6 +583,8 @@
}
);
const isLocalUserVrcplusSupporter = computed(() => currentUser.value.$isVRCPlus);
initializeNewInstanceDialog();
function closeInviteDialog() {
@@ -617,7 +627,9 @@
if (!isRealInstance(tag)) {
return;
}
nextTick(() => adjustDialogZ(newInstanceDialogRef.value.$el));
nextTick(() => {
newInstanceDialogIndex.value = getNextDialogIndex();
});
const D = newInstanceDialog.value;
const L = parseLocation(tag);
if (D.worldId === L.worldId) {
@@ -634,6 +646,9 @@
D.strict = false;
D.shortName = '';
D.secureOrShortName = '';
if (!isLocalUserVrcplusSupporter.value) {
D.displayName = '';
}
const args = await groupRequest.getGroupPermissions({ userId: currentUser.value.id });
handleGroupPermissions(args);
buildInstance();
@@ -673,10 +688,23 @@
configRepository
.getBool('instanceDialogAgeGate', false)
.then((value) => (newInstanceDialog.value.ageGate = value));
configRepository
.getString('instanceDialogDisplayName', '')
.then((value) => (newInstanceDialog.value.displayName = value));
}
function saveNewInstanceDialog() {
const { accessType, region, instanceName, userId, groupId, groupAccessType, queueEnabled, ageGate } =
newInstanceDialog.value;
const {
accessType,
region,
instanceName,
userId,
groupId,
groupAccessType,
queueEnabled,
ageGate,
displayName
} = newInstanceDialog.value;
configRepository.setString('instanceDialogAccessType', accessType);
configRepository.setString('instanceRegion', region);
@@ -686,9 +714,10 @@
configRepository.setString('instanceDialogGroupAccessType', groupAccessType);
configRepository.setBool('instanceDialogQueueEnabled', queueEnabled);
configRepository.setBool('instanceDialogAgeGate', ageGate);
configRepository.setString('instanceDialogDisplayName', displayName);
}
function newInstanceTabClick(tab) {
if (tab === '1') {
function newInstanceTabClick(obj) {
if (obj.props.name === 'Normal') {
buildInstance();
} else {
buildLegacyInstance();
@@ -720,7 +749,7 @@
worldId: L.worldId
})
.then((args) => {
proxy.$message({
ElMessage({
message: 'Self invite sent',
type: 'success'
});
@@ -749,7 +778,7 @@
}
if (D.groupId && D.groupId !== D.lastSelectedGroupId) {
D.roleIds = [];
const ref = cachedGroups.value.get(D.groupId);
const ref = cachedGroups.get(D.groupId);
if (typeof ref !== 'undefined') {
D.groupRef = ref;
D.selectedGroupRoles = ref.roles;
@@ -824,7 +853,7 @@
}
if (D.groupId && D.groupId !== D.lastSelectedGroupId) {
D.roleIds = [];
const ref = cachedGroups.value.get(D.groupId);
const ref = cachedGroups.get(D.groupId);
if (typeof ref !== 'undefined') {
D.groupRef = ref;
D.selectedGroupRoles = ref.roles;