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,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isAvatarProviderDialogVisible"
:model-value="isAvatarProviderDialogVisible"
:title="t('dialog.avatar_database_provider.header')"
width="600px"
@close="closeDialog">
@@ -13,19 +13,20 @@
size="small"
style="margin-top: 5px"
@change="saveAvatarProviderList">
<el-button slot="append" icon="el-icon-delete" @click="removeAvatarProvider(provider)"></el-button>
<el-button :icon="Delete" @click="removeAvatarProvider(provider)"></el-button>
</el-input>
<el-button size="mini" style="margin-top: 5px" @click="avatarRemoteDatabaseProviderList.push('')">
<el-button size="small" style="margin-top: 5px" @click="avatarRemoteDatabaseProviderList.push('')">
{{ t('dialog.avatar_database_provider.add_provider') }}
</el-button>
</div>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { Delete } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { useAvatarProviderStore } from '../../../stores';
const { t } = useI18n();

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="changeLogDialog.visible"
:model-value="changeLogDialog.visible"
:title="t('dialog.change_log.header')"
width="800px"
append-to-body
@@ -13,32 +13,35 @@
<a class="x-link" @click="openExternalLink('https://www.patreon.com/Natsumi_VRCX')">Patreon</a>,
<a class="x-link" @click="openExternalLink('https://ko-fi.com/natsumi_sama')">Ko-fi</a>.
</span>
<vue-markdown
:source="changeLogDialog.changeLog"
:linkify="false"
style="height: 62vh; overflow-y: auto; margin-top: 10px"></vue-markdown>
<VueShowdown
:markdown="changeLogDialog.changeLog"
flavor="github"
:options="showdownOptions"
@click="handleLinkClick"
style="height: 62vh; overflow-y: auto; margin-top: 10px" />
</div>
<template #footer>
<el-button type="small" @click="openExternalLink('https://github.com/vrcx-team/VRCX/releases')">
<el-button @click="openExternalLink('https://github.com/vrcx-team/VRCX/releases')">
{{ t('dialog.change_log.github') }}
</el-button>
<el-button type="small" @click="openExternalLink('https://patreon.com/Natsumi_VRCX')">
<el-button @click="openExternalLink('https://patreon.com/Natsumi_VRCX')">
{{ t('dialog.change_log.donate') }}
</el-button>
<el-button type="small" @click="closeDialog">
<el-button @click="closeDialog">
{{ t('dialog.change_log.close') }}
</el-button>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { openExternalLink } from '../../../shared/utils';
import { useVRCXUpdaterStore } from '../../../stores';
import { defineAsyncComponent } from 'vue';
const VueMarkdown = () => import('vue-markdown');
const VueShowdown = defineAsyncComponent(() => import('vue-showdown').then((module) => module.VueShowdown));
const VRCXUpdaterStore = useVRCXUpdaterStore();
@@ -46,9 +49,32 @@
const { t } = useI18n();
const showdownOptions = {
emoji: true,
openLinksInNewWindow: false,
simplifiedAutoLink: true,
excludeTrailingPunctuationFromURLs: true,
literalMidWordUnderscores: true,
strikethrough: true,
tables: true,
tablesHeaderId: false,
ghCodeBlocks: true,
tasklists: true
};
function closeDialog() {
changeLogDialog.value.visible = false;
}
function handleLinkClick(event) {
const target = event.target.closest('a');
if (target && target.href) {
event.preventDefault();
event.stopPropagation();
openExternalLink(target.href);
}
}
</script>
<style>

View File

@@ -1,6 +1,6 @@
<template>
<safe-dialog
:visible="!!feedFiltersDialogMode"
<el-dialog
:model-value="!!feedFiltersDialogMode"
:title="dialogTitle"
width="550px"
destroy-on-close
@@ -14,12 +14,14 @@
placement="top"
style="margin-left: 5px"
:content="setting.tooltip">
<i :class="setting.tooltipIcon || 'el-icon-info'"></i> </el-tooltip
></span>
<el-icon v-if="setting.tooltipWarning"><Warning /></el-icon>
<el-icon v-else><InfoFilled /></el-icon>
</el-tooltip>
</span>
<el-radio-group
v-model="currentSharedFeedFilters[setting.key]"
size="mini"
size="small"
@change="saveSharedFeedFilters">
<el-radio-button v-for="option in setting.options" :key="option.label" :label="option.label">
{{ t(option.textKey) }}
@@ -36,7 +38,7 @@
<span class="toggle-name">{{ setting.name }}</span>
<el-radio-group
v-model="currentSharedFeedFilters[setting.key]"
size="mini"
size="small"
@change="saveSharedFeedFilters">
<el-radio-button v-for="option in setting.options" :key="option.label" :label="option.label">
{{ t(option.textKey) }}
@@ -54,13 +56,14 @@
t('dialog.shared_feed_filters.close')
}}</el-button>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { InfoFilled, Warning } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import configRepository from '../../../service/config';
import { feedFiltersOptions, sharedFeedFiltersDefaults } from '../../../shared/constants';
import { useNotificationsSettingsStore, usePhotonStore, useSharedFeedStore } from '../../../stores';

View File

@@ -1,14 +1,14 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isLaunchOptionsDialogVisible"
:model-value="isLaunchOptionsDialogVisible"
:title="t('dialog.launch_options.header')"
width="600px"
@close="closeDialog">
<div style="font-size: 12px">
{{ t('dialog.launch_options.description') }} <br />
{{ t('dialog.launch_options.example') }}
<el-tag size="mini"
<el-tag size="small"
>--fps=144 --enable-debug-gui --enable-sdk-log-levels --enable-udon-debug-logging
</el-tag>
</div>
@@ -16,7 +16,7 @@
<el-input
v-model="launchOptionsDialog.launchArguments"
type="textarea"
size="mini"
size="small"
show-word-limit
:autosize="{ minRows: 2, maxRows: 5 }"
placeholder=""
@@ -52,22 +52,20 @@
</el-button>
</div>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { computed, getCurrentInstance, ref } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import configRepository from '../../../service/config';
import { openExternalLink } from '../../../shared/utils';
import { useLaunchStore } from '../../../stores';
const { t } = useI18n();
const instance = getCurrentInstance();
const $message = instance.proxy.$message;
const launchStore = useLaunchStore();
const { isLaunchOptionsDialogVisible } = storeToRefs(launchStore);
@@ -105,14 +103,14 @@
D.vrcLaunchPathOverride.endsWith('.exe') &&
!D.vrcLaunchPathOverride.endsWith('launch.exe')
) {
$message({
ElMessage({
message: 'Invalid path, you must enter VRChat folder or launch.exe',
type: 'error'
});
return;
}
configRepository.setString('vrcLaunchPathOverride', D.vrcLaunchPathOverride);
$message({
ElMessage({
message: 'Updated launch options',
type: 'success'
});

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isNotificationPositionDialogVisible"
:model-value="isNotificationPositionDialogVisible"
:title="t('dialog.notification_position.header')"
width="400px"
@close="closeDialog">
@@ -23,7 +23,7 @@
d="M291.89,5A3.11,3.11,0,0,1,295,8.11V160.64a3.11,3.11,0,0,1-3.11,3.11H8.11A3.11,3.11,0,0,1,5,160.64V8.11A3.11,3.11,0,0,1,8.11,5H291.89m0-5H8.11A8.11,8.11,0,0,0,0,8.11V160.64a8.11,8.11,0,0,0,8.11,8.11H291.89a8.11,8.11,0,0,0,8.11-8.11V8.11A8.11,8.11,0,0,0,291.89,0Z" />
<rect style="fill: #c4c4c4" x="5" y="5" width="290" height="158.75" rx="2.5" />
</svg>
<el-radio-group :value="notificationPosition" size="mini" @input="changeNotificationPosition">
<el-radio-group :model-value="notificationPosition" size="small" @change="changeNotificationPosition">
<el-radio label="topLeft" style="margin: 0; position: absolute; left: 35px; top: 120px"></el-radio>
<el-radio label="top" style="margin: 0; position: absolute; left: 195px; top: 120px"></el-radio>
<el-radio label="topRight" style="margin: 0; position: absolute; right: 25px; top: 120px"></el-radio>
@@ -42,12 +42,12 @@
</el-button>
</div>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { useNotificationsSettingsStore } from '../../../stores';
const { t } = useI18n();

View File

@@ -1,10 +1,11 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="ossDialog"
:model-value="ossDialog"
:title="t('dialog.open_source.header')"
width="650px"
@close="closeDialog">
@close="closeDialog"
destroy-on-close>
<div v-once style="height: 350px; overflow: hidden scroll; word-break: break-all">
<div>
<span>{{ t('dialog.open_source.description') }}</span>
@@ -15,12 +16,12 @@
<pre style="font-size: 12px; white-space: pre-line">{{ lib.licenseText }}</pre>
</div>
</div>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { useI18n } from 'vue-i18n-bridge';
import { openSourceSoftwareLicenses } from '../../../shared/constants';
import { useI18n } from 'vue-i18n';
import { openSourceSoftwareLicenses } from '../../../shared/constants/ossLicenses';
const { t } = useI18n();

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible.sync="enablePrimaryPasswordDialog.visible"
v-model="enablePrimaryPasswordDialog.visible"
:before-close="enablePrimaryPasswordDialog.beforeClose"
:close-on-click-modal="false"
:title="t('dialog.primary_password.header')"
@@ -10,7 +10,7 @@
v-model="enablePrimaryPasswordDialog.password"
:placeholder="t('dialog.primary_password.password_placeholder')"
type="password"
size="mini"
size="small"
maxlength="32"
show-password
autofocus>
@@ -20,7 +20,7 @@
:placeholder="t('dialog.primary_password.re_input_placeholder')"
type="password"
style="margin-top: 5px"
size="mini"
size="small"
maxlength="32"
show-password>
</el-input>
@@ -36,12 +36,12 @@
{{ t('dialog.primary_password.ok') }}
</el-button>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { useAuthStore } from '../../../stores';
const { t } = useI18n();

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isRegistryBackupDialogVisible"
:model-value="isRegistryBackupDialogVisible"
:title="t('dialog.registry_backup.header')"
width="600px"
@close="closeDialog"
@@ -22,7 +22,7 @@
<span class="name" style="margin-right: 24px">{{ t('dialog.registry_backup.ask_to_restore') }}</span>
<el-switch v-model="vrcRegistryAskRestore" @change="setVrcRegistryAskRestore"></el-switch>
</div>
<data-tables v-bind="registryBackupTable" style="margin-top: 10px">
<DataTable v-bind="registryBackupTable" style="margin-top: 10px">
<el-table-column :label="t('dialog.registry_backup.name')" prop="name"></el-table-column>
<el-table-column :label="t('dialog.registry_backup.date')" prop="date">
<template #default="scope">
@@ -31,39 +31,33 @@
</el-table-column>
<el-table-column :label="t('dialog.registry_backup.action')" width="90" align="right">
<template #default="scope">
<el-tooltip
placement="top"
:content="t('dialog.registry_backup.restore')"
:disabled="hideTooltips">
<el-tooltip placement="top" :content="t('dialog.registry_backup.restore')">
<el-button
type="text"
icon="el-icon-upload2"
size="mini"
:icon="Upload"
size="small"
class="button-pd-0"
@click="restoreVrcRegistryBackup(scope.row)"></el-button>
</el-tooltip>
<el-tooltip
placement="top"
:content="t('dialog.registry_backup.save_to_file')"
:disabled="hideTooltips">
<el-tooltip placement="top" :content="t('dialog.registry_backup.save_to_file')">
<el-button
type="text"
icon="el-icon-download"
size="mini"
:icon="Download"
size="small"
class="button-pd-0"
@click="saveVrcRegistryBackupToFile(scope.row)"></el-button>
</el-tooltip>
<el-tooltip
placement="top"
:content="t('dialog.registry_backup.delete')"
:disabled="hideTooltips">
<el-tooltip placement="top" :content="t('dialog.registry_backup.delete')">
<el-button
type="text"
icon="el-icon-delete"
size="mini"
:icon="Delete"
size="small"
class="button-pd-0"
@click="deleteVrcRegistryBackup(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</data-tables>
</DataTable>
<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 10px">
<el-button type="danger" size="small" @click="deleteVrcRegistry">{{
t('dialog.registry_backup.reset')
@@ -78,19 +72,20 @@
</div>
</div>
</div>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { ElMessage, ElMessageBox } from 'element-plus';
import { Upload, Download, Delete } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { getCurrentInstance, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import configRepository from '../../../service/config';
import { downloadAndSaveJson, removeFromArray, formatDateFilter } from '../../../shared/utils';
import { useAppearanceSettingsStore, useVrcxStore, useAdvancedSettingsStore } from '../../../stores';
import { useVrcxStore, useAdvancedSettingsStore } from '../../../stores';
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { backupVrcRegistry } = useVrcxStore();
const { isRegistryBackupDialogVisible } = storeToRefs(useVrcxStore());
const { vrcRegistryAutoBackup, vrcRegistryAskRestore } = storeToRefs(useAdvancedSettingsStore());
@@ -98,14 +93,11 @@
const { t } = useI18n();
const instance = getCurrentInstance();
const { $confirm, $message, $prompt } = instance.proxy;
const registryBackupTable = ref({
data: [],
tableProps: {
stripe: true,
size: 'mini',
size: 'small',
defaultSort: {
prop: 'date',
order: 'descending'
@@ -129,31 +121,32 @@
}
function restoreVrcRegistryBackup(row) {
$confirm('Continue? Restore Backup', 'Confirm', {
ElMessageBox.confirm('Continue? Restore Backup', 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'warning',
callback: (action) => {
type: 'warning'
})
.then((action) => {
if (action !== 'confirm') {
return;
}
const data = JSON.stringify(row.data);
AppApi.SetVRChatRegistry(data)
.then(() => {
$message({
ElMessage({
message: 'VRC registry settings restored',
type: 'success'
});
})
.catch((e) => {
console.error(e);
$message({
ElMessage({
message: `Failed to restore VRC registry settings, check console for full error: ${e}`,
type: 'error'
});
});
}
});
})
.catch(() => {});
}
function saveVrcRegistryBackupToFile(row) {
@@ -168,22 +161,23 @@
}
function deleteVrcRegistry() {
$confirm('Continue? Delete VRC Registry Settings', 'Confirm', {
ElMessageBox.confirm('Continue? Delete VRC Registry Settings', 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'warning',
callback: (action) => {
type: 'warning'
})
.then((action) => {
if (action !== 'confirm') {
return;
}
AppApi.DeleteVRChatRegistryFolder().then(() => {
$message({
ElMessage({
message: 'VRC registry settings deleted',
type: 'success'
});
});
}
});
})
.catch(() => {});
}
async function handleBackupVrcRegistry(name) {
@@ -192,16 +186,16 @@
}
async function promptVrcRegistryBackupName() {
const name = await $prompt('Enter a name for the backup', 'Backup Name', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
inputPattern: /\S+/,
inputErrorMessage: 'Name is required',
inputValue: 'Backup'
});
if (name.action === 'confirm') {
await handleBackupVrcRegistry(name.value);
}
try {
const { value } = await ElMessageBox.prompt('Enter a name for the backup', 'Backup Name', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
inputPattern: /\S+/,
inputErrorMessage: 'Name is required',
inputValue: 'Backup'
});
await handleBackupVrcRegistry(value);
} catch (error) {}
}
async function openJsonFileSelectorDialogElectron() {
@@ -260,20 +254,20 @@
}
AppApi.SetVRChatRegistry(json)
.then(() => {
$message({
ElMessage({
message: 'VRC registry settings restored',
type: 'success'
});
})
.catch((e) => {
console.error(e);
$message({
ElMessage({
message: `Failed to restore VRC registry settings, check console for full error: ${e}`,
type: 'error'
});
});
} catch {
$message({
ElMessage({
message: 'Invalid JSON',
type: 'error'
});
@@ -288,3 +282,9 @@
isRegistryBackupDialogVisible.value = false;
}
</script>
<style scoped>
.button-pd-0 {
padding: 0;
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isVRChatConfigDialogVisible"
:model-value="isVRChatConfigDialogVisible"
:title="t('dialog.config_json.header')"
width="420px"
@close="closeDialog">
@@ -16,12 +16,12 @@
<span>/</span>
<span v-text="totalCacheSize"></span>
<span>GB</span>
<el-tooltip placement="top" :content="t('dialog.config_json.refresh')" :disabled="hideTooltips">
<el-tooltip placement="top" :content="t('dialog.config_json.refresh')">
<el-button
type="default"
:loading="VRChatCacheSizeLoading"
size="small"
icon="el-icon-refresh"
:icon="Refresh"
circle
style="margin-left: 5px"
@click="getVRChatCacheSize"></el-button>
@@ -32,7 +32,7 @@
<el-button
size="small"
style="margin-left: 5px"
icon="el-icon-delete"
:icon="Delete"
@click="showDeleteAllVRChatCacheConfirm"
>{{ t('dialog.config_json.delete_cache') }}</el-button
>
@@ -40,13 +40,9 @@
<div style="margin-top: 10px">
<span style="margin-right: 5px">{{ t('dialog.config_json.delete_old_cache') }}</span>
<el-button
size="small"
style="margin-left: 5px"
icon="el-icon-folder-delete"
@click="sweepVRChatCache"
>{{ t('dialog.config_json.sweep_cache') }}</el-button
>
<el-button size="small" style="margin-left: 5px" :icon="FolderDelete" @click="sweepVRChatCache">{{
t('dialog.config_json.sweep_cache')
}}</el-button>
</div>
<div v-for="(item, value) in VRChatConfigList" :key="value" style="display: block; margin-top: 10px">
@@ -55,19 +51,20 @@
<el-input
v-model="VRChatConfigFile[value]"
:placeholder="item.default"
size="mini"
size="small"
:type="item.type ? item.type : 'text'"
:min="item.min"
:max="item.max"
@input="refreshDialogValues"
style="flex: 1; margin-top: 5px"
><el-button
v-if="item.folderBrowser"
slot="append"
size="mini"
icon="el-icon-folder-opened"
@click="openConfigFolderBrowser(value)"></el-button
></el-input>
style="flex: 1; margin-top: 5px">
<template #append>
<el-button
v-if="item.folderBrowser"
size="small"
:icon="FolderOpened"
@click="openConfigFolderBrowser(value)"></el-button>
</template>
</el-input>
</div>
</div>
@@ -82,7 +79,7 @@
<el-button size="small">
<span>
<span v-text="getVRChatCameraResolution()"></span>
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<template #dropdown>
@@ -107,7 +104,7 @@
<el-button size="small">
<span>
<span v-text="getVRChatSpoutResolution()"></span>
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<template #dropdown>
@@ -135,7 +132,7 @@
<el-button size="small">
<span>
<span v-text="getVRChatScreenshotResolution()"></span>
<i class="el-icon-arrow-down el-icon--right"></i>
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</span>
</el-button>
<template #dropdown>
@@ -182,18 +179,19 @@
</div>
</div>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { ElMessage, ElMessageBox } from 'element-plus';
import { Refresh, Delete, FolderOpened, FolderDelete, ArrowDown } from '@element-plus/icons-vue';
import { storeToRefs } from 'pinia';
import { computed, getCurrentInstance, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { VRChatCameraResolutions, VRChatScreenshotResolutions } from '../../../shared/constants';
import { getVRChatResolution, openExternalLink } from '../../../shared/utils';
import { useAdvancedSettingsStore, useAppearanceSettingsStore, useGameStore } from '../../../stores';
import { useAdvancedSettingsStore, useGameStore } from '../../../stores';
const { hideTooltips } = storeToRefs(useAppearanceSettingsStore());
const { VRChatUsedCacheSize, VRChatTotalCacheSize, VRChatCacheSizeLoading } = storeToRefs(useGameStore());
const { sweepVRChatCache, getVRChatCacheSize } = useGameStore();
const { folderSelectorDialog } = useAdvancedSettingsStore();
@@ -201,10 +199,6 @@
const { t } = useI18n();
const instance = getCurrentInstance();
const $confirm = instance.proxy.$confirm;
const $message = instance.proxy.$message;
const VRChatConfigFile = ref({});
// it's a object
const VRChatConfigList = ref({
@@ -270,16 +264,17 @@
});
function showDeleteAllVRChatCacheConfirm() {
$confirm(`Continue? Delete all VRChat cache`, 'Confirm', {
ElMessageBox.confirm(`Continue? Delete all VRChat cache`, 'Confirm', {
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'info',
callback: (action) => {
type: 'info'
})
.then((action) => {
if (action === 'confirm') {
deleteAllVRChatCache();
}
}
});
})
.catch(() => {});
}
async function deleteAllVRChatCache() {
@@ -374,7 +369,7 @@
const parsedConfig = JSON.parse(config);
VRChatConfigFile.value = { ...VRChatConfigFile.value, ...parsedConfig };
} catch {
$message({
ElMessage({
message: 'Invalid JSON in config.json',
type: 'error'
});

View File

@@ -1,7 +1,7 @@
<template>
<safe-dialog
<el-dialog
class="x-dialog"
:visible="isYouTubeApiDialogVisible"
:model-value="isYouTubeApiDialogVisible"
:title="t('dialog.youtube_api.header')"
width="400px"
@close="closeDialog">
@@ -28,13 +28,13 @@
</el-button>
</div>
</template>
</safe-dialog>
</el-dialog>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia';
import { getCurrentInstance } from 'vue';
import { useI18n } from 'vue-i18n-bridge';
import { useI18n } from 'vue-i18n';
import { openExternalLink } from '../../../shared/utils';
import { useAdvancedSettingsStore } from '../../../stores';
@@ -46,10 +46,7 @@
const { t } = useI18n();
const instance = getCurrentInstance();
const $message = instance.proxy.$message;
const props = defineProps({
defineProps({
isYouTubeApiDialogVisible: {
type: Boolean,
default: false
@@ -61,7 +58,7 @@
async function testYouTubeApiKey() {
const previousKey = youTubeApiKey.value;
if (!youTubeApiKey.value) {
$message({
ElMessage({
message: 'YouTube API key removed',
type: 'success'
});
@@ -71,13 +68,13 @@
const data = await lookupYouTubeVideo('dQw4w9WgXcQ');
if (!data) {
setYouTubeApiKey(previousKey);
$message({
ElMessage({
message: 'Invalid YouTube API key',
type: 'error'
});
} else {
setYouTubeApiKey(youTubeApiKey.value);
$message({
ElMessage({
message: 'YouTube API key valid!',
type: 'success'
});