mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-17 13:53:52 +02:00
refactor: split settings tab components into smaller components
This commit is contained in:
File diff suppressed because it is too large
Load Diff
519
src/views/Settings/components/Tabs/AdvancedTab.vue
Normal file
519
src/views/Settings/components/Tabs/AdvancedTab.vue
Normal file
@@ -0,0 +1,519 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="options-container" style="margin-top: 0">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.header') }}</span>
|
||||
<div class="options-container-item" style="margin-top: 15px">
|
||||
<el-button-group>
|
||||
<el-button size="small" :icon="Operation" @click="showVRChatConfig()">VRChat config.json</el-button>
|
||||
<el-button size="small" :icon="Operation" @click="showLaunchOptions()">{{
|
||||
t('view.settings.advanced.advanced.launch_options')
|
||||
}}</el-button>
|
||||
<el-button size="small" :icon="Goods" @click="showRegistryBackupDialog()">{{
|
||||
t('view.settings.advanced.advanced.vrc_registry_backup')
|
||||
}}</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.common_folders') }}</span>
|
||||
<div class="options-container-item" style="margin-top: 15px">
|
||||
<el-button-group>
|
||||
<el-button size="small" :icon="Folder" @click="openVrcxAppDataFolder()">VRCX Data</el-button>
|
||||
<el-button size="small" :icon="Folder" @click="openVrcAppDataFolder()">VRChat Data</el-button>
|
||||
<el-button size="small" :icon="Folder" @click="openCrashVrcCrashDumps()">Crash Dumps</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.primary_password.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.primary_password.description')"
|
||||
:value="enablePrimaryPassword"
|
||||
:disabled="!enablePrimaryPassword"
|
||||
:long-label="true"
|
||||
@change="enablePrimaryPasswordChange" />
|
||||
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.relaunch_vrchat.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.relaunch_vrchat.description')"
|
||||
:value="relaunchVRChatAfterCrash"
|
||||
:long-label="true"
|
||||
@change="
|
||||
setRelaunchVRChatAfterCrash();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.vrchat_quit_fix.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.vrchat_quit_fix.description')"
|
||||
:value="vrcQuitFix"
|
||||
:long-label="true"
|
||||
@change="
|
||||
setVrcQuitFix();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.auto_cache_management.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.auto_cache_management.description')"
|
||||
:value="autoSweepVRChatCache"
|
||||
:long-label="true"
|
||||
@change="
|
||||
setAutoSweepVRChatCache();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.self_invite.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.self_invite.description')"
|
||||
:value="selfInviteOverride"
|
||||
:long-label="true"
|
||||
@change="
|
||||
setSelfInviteOverride();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
|
||||
<div v-if="branch === 'Nightly'">
|
||||
<span class="sub-header">Anonymous Error Reporting (Nightly Only)</span>
|
||||
<simple-switch
|
||||
label="Help improve VRCX by sending anonymous error reports. Only collects crash and error information, no personal data or VRChat information is collected."
|
||||
:value="sentryErrorReporting"
|
||||
:long-label="true"
|
||||
@change="setSentryErrorReporting()" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.remote_database.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.remote_database.enable')"
|
||||
:value="avatarRemoteDatabase"
|
||||
:long-label="true"
|
||||
@change="
|
||||
setAvatarRemoteDatabase(!avatarRemoteDatabase);
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="User" @click="showAvatarProviderDialog">{{
|
||||
t('view.settings.advanced.advanced.remote_database.avatar_database_provider')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!isLinux">
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.app_launcher.header') }}</span>
|
||||
<br />
|
||||
<el-button size="small" :icon="Folder" style="margin-top: 5px" @click="openShortcutFolder()">{{
|
||||
t('view.settings.advanced.advanced.app_launcher.folder')
|
||||
}}</el-button>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.remote_database.enable')"
|
||||
:value="enableAppLauncher"
|
||||
:tooltip="t('view.settings.advanced.advanced.app_launcher.folder_tooltip')"
|
||||
:long-label="true"
|
||||
@change="setEnableAppLauncher" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.app_launcher.auto_close')"
|
||||
:value="enableAppLauncherAutoClose"
|
||||
:long-label="true"
|
||||
@change="setEnableAppLauncherAutoClose" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.app_launcher.run_process_once')"
|
||||
:value="enableAppLauncherRunProcessOnce"
|
||||
:long-label="true"
|
||||
@change="setEnableAppLauncherRunProcessOnce" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.youtube_api.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.youtube_api.enable')"
|
||||
:value="youTubeApi"
|
||||
:tooltip="t('view.settings.advanced.advanced.youtube_api.enable_tooltip')"
|
||||
:long-label="true"
|
||||
@change="changeYouTubeApi('VRCX_youtubeAPI')" />
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="CaretRight" @click="showYouTubeApiDialog">{{
|
||||
t('view.settings.advanced.advanced.youtube_api.youtube_api_key')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.video_progress_pie.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.video_progress_pie.enable')"
|
||||
:value="progressPie"
|
||||
:disabled="!openVR"
|
||||
:tooltip="t('view.settings.advanced.advanced.video_progress_pie.enable_tooltip')"
|
||||
:long-label="true"
|
||||
@change="changeYouTubeApi('VRCX_progressPie')" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.video_progress_pie.dance_world_only')"
|
||||
:value="progressPieFilter"
|
||||
:disabled="!openVR"
|
||||
:long-label="true"
|
||||
@change="changeYouTubeApi('VRCX_progressPieFilter')" />
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.launch_commands.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.launch_commands.show_confirmation_on_switch_avatar_enable')"
|
||||
:value="showConfirmationOnSwitchAvatar"
|
||||
:tooltip="
|
||||
t('view.settings.advanced.advanced.launch_commands.show_confirmation_on_switch_avatar_tooltip')
|
||||
"
|
||||
:long-label="true"
|
||||
@change="setShowConfirmationOnSwitchAvatar" />
|
||||
<div class="options-container-item">
|
||||
<el-button
|
||||
size="small"
|
||||
:icon="Paperclip"
|
||||
@click="openExternalLink('https://github.com/vrcx-team/VRCX/wiki/Launch-parameters-&-VRCX.json')"
|
||||
>{{ t('view.settings.advanced.advanced.launch_commands.docs') }}</el-button
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
:icon="Paperclip"
|
||||
@click="openExternalLink('https://github.com/Myrkie/open-in-vrcx')"
|
||||
>{{ t('view.settings.advanced.advanced.launch_commands.website_userscript') }}</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.advanced.advanced.cache_debug.header') }}</span>
|
||||
<br />
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="DeleteFilled" @click="clearVRCXCache">{{
|
||||
t('view.settings.advanced.advanced.cache_debug.clear_cache')
|
||||
}}</el-button>
|
||||
<el-button size="small" :icon="Timer" @click="promptAutoClearVRCXCacheFrequency">{{
|
||||
t('view.settings.advanced.advanced.cache_debug.auto_clear_cache')
|
||||
}}</el-button>
|
||||
<el-button size="small" :icon="Refresh" @click="refreshCacheSize">{{
|
||||
t('view.settings.advanced.advanced.cache_debug.refresh_cache')
|
||||
}}</el-button>
|
||||
</div>
|
||||
|
||||
<simple-switch
|
||||
:label="`${t('view.settings.advanced.advanced.cache_debug.disable_gamelog')} ${t('view.settings.advanced.advanced.cache_debug.disable_gamelog_notice')}`"
|
||||
:value="gameLogDisabled"
|
||||
:long-label="true"
|
||||
@change="disableGameLogDialog()" />
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.user_cache') }}
|
||||
<span v-text="cacheSize.cachedUsers"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.world_cache') }}
|
||||
<span v-text="cacheSize.cachedWorlds"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.avatar_cache') }}
|
||||
<span v-text="cacheSize.cachedAvatars"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.group_cache') }}
|
||||
<span v-text="cacheSize.cachedGroups"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.avatar_name_cache') }}
|
||||
<span v-text="cacheSize.cachedAvatarNames"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.cache_debug.instance_cache') }}
|
||||
<span v-text="cacheSize.cachedInstances"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="Tickets" @click="showConsole">{{
|
||||
t('view.settings.advanced.advanced.cache_debug.show_console')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="sub-header">{{ t('view.settings.advanced.advanced.sqlite_table_size.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="Refresh" @click="getSqliteTableSizes">{{
|
||||
t('view.settings.advanced.advanced.sqlite_table_size.refresh')
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.gps') }}
|
||||
<span v-text="sqliteTableSizes.gps"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.status') }}
|
||||
<span v-text="sqliteTableSizes.status"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.bio') }}
|
||||
<span v-text="sqliteTableSizes.bio"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.avatar') }}
|
||||
<span v-text="sqliteTableSizes.avatar"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.online_offline') }}
|
||||
<span v-text="sqliteTableSizes.onlineOffline"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.friend_log_history') }}
|
||||
<span v-text="sqliteTableSizes.friendLogHistory"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.notification') }}
|
||||
<span v-text="sqliteTableSizes.notification"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.location') }}
|
||||
<span v-text="sqliteTableSizes.location"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.join_leave') }}
|
||||
<span v-text="sqliteTableSizes.joinLeave"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.portal_spawn') }}
|
||||
<span v-text="sqliteTableSizes.portalSpawn"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.video_play') }}
|
||||
<span v-text="sqliteTableSizes.videoPlay"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">
|
||||
{{ t('view.settings.advanced.advanced.sqlite_table_size.event') }}
|
||||
<span v-text="sqliteTableSizes.event"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RegistryBackupDialog />
|
||||
<YouTubeApiDialog v-model:isYouTubeApiDialogVisible="isYouTubeApiDialogVisible" />
|
||||
<AvatarProviderDialog v-model:isAvatarProviderDialogVisible="isAvatarProviderDialogVisible" />
|
||||
<PhotonSettings v-if="photonLoggingEnabled" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
CaretRight,
|
||||
DeleteFilled,
|
||||
Folder,
|
||||
Goods,
|
||||
Operation,
|
||||
Paperclip,
|
||||
Refresh,
|
||||
Tickets,
|
||||
Timer,
|
||||
User
|
||||
} from '@element-plus/icons-vue';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import {
|
||||
useAdvancedSettingsStore,
|
||||
useAuthStore,
|
||||
useAvatarProviderStore,
|
||||
useAvatarStore,
|
||||
useGroupStore,
|
||||
useInstanceStore,
|
||||
useLaunchStore,
|
||||
useNotificationsSettingsStore,
|
||||
usePhotonStore,
|
||||
useUserStore,
|
||||
useVRCXUpdaterStore,
|
||||
useVrStore,
|
||||
useVrcxStore,
|
||||
useWorldStore
|
||||
} from '../../../../stores';
|
||||
import { openExternalLink } from '../../../../shared/utils';
|
||||
|
||||
import AvatarProviderDialog from '../../dialogs/AvatarProviderDialog.vue';
|
||||
import PhotonSettings from '../PhotonSettings.vue';
|
||||
import RegistryBackupDialog from '../../dialogs/RegistryBackupDialog.vue';
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
import YouTubeApiDialog from '../../dialogs/YouTubeApiDialog.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||
const notificationsSettingsStore = useNotificationsSettingsStore();
|
||||
const { saveOpenVROption, updateVRLastLocation, updateOpenVR } = useVrStore();
|
||||
const { showLaunchOptions } = useLaunchStore();
|
||||
const { enablePrimaryPasswordChange } = useAuthStore();
|
||||
const { showConsole, clearVRCXCache, showRegistryBackupDialog } = useVrcxStore();
|
||||
|
||||
const { cachedUsers } = useUserStore();
|
||||
const { cachedWorlds } = useWorldStore();
|
||||
const { cachedAvatars, cachedAvatarNames } = useAvatarStore();
|
||||
const { cachedGroups } = useGroupStore();
|
||||
const { cachedInstances } = useInstanceStore();
|
||||
|
||||
const { photonLoggingEnabled } = storeToRefs(usePhotonStore());
|
||||
const { branch } = storeToRefs(useVRCXUpdaterStore());
|
||||
const { openVR } = storeToRefs(notificationsSettingsStore);
|
||||
|
||||
const {
|
||||
enablePrimaryPassword,
|
||||
relaunchVRChatAfterCrash,
|
||||
vrcQuitFix,
|
||||
autoSweepVRChatCache,
|
||||
selfInviteOverride,
|
||||
avatarRemoteDatabase,
|
||||
enableAppLauncher,
|
||||
enableAppLauncherAutoClose,
|
||||
enableAppLauncherRunProcessOnce,
|
||||
youTubeApi,
|
||||
progressPie,
|
||||
progressPieFilter,
|
||||
showConfirmationOnSwitchAvatar,
|
||||
gameLogDisabled,
|
||||
sqliteTableSizes,
|
||||
sentryErrorReporting
|
||||
} = storeToRefs(advancedSettingsStore);
|
||||
|
||||
const {
|
||||
setRelaunchVRChatAfterCrash,
|
||||
setVrcQuitFix,
|
||||
setAutoSweepVRChatCache,
|
||||
setSelfInviteOverride,
|
||||
setAvatarRemoteDatabase,
|
||||
setEnableAppLauncher,
|
||||
setEnableAppLauncherAutoClose,
|
||||
setEnableAppLauncherRunProcessOnce,
|
||||
setShowConfirmationOnSwitchAvatar,
|
||||
getSqliteTableSizes,
|
||||
showVRChatConfig,
|
||||
promptAutoClearVRCXCacheFrequency,
|
||||
setSentryErrorReporting
|
||||
} = advancedSettingsStore;
|
||||
|
||||
const { isAvatarProviderDialogVisible } = storeToRefs(useAvatarProviderStore());
|
||||
const { showAvatarProviderDialog } = useAvatarProviderStore();
|
||||
|
||||
const isYouTubeApiDialogVisible = ref(false);
|
||||
|
||||
const cacheSize = reactive({
|
||||
cachedUsers: 0,
|
||||
cachedWorlds: 0,
|
||||
cachedAvatars: 0,
|
||||
cachedGroups: 0,
|
||||
cachedAvatarNames: 0,
|
||||
cachedInstances: 0
|
||||
});
|
||||
|
||||
const isLinux = computed(() => LINUX);
|
||||
|
||||
function openVrcxAppDataFolder() {
|
||||
AppApi.OpenVrcxAppDataFolder().then((result) => {
|
||||
if (result) {
|
||||
ElMessage({
|
||||
message: 'Folder opened',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
ElMessage({
|
||||
message: "Folder dosn't exist",
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openVrcAppDataFolder() {
|
||||
AppApi.OpenVrcAppDataFolder().then((result) => {
|
||||
if (result) {
|
||||
ElMessage({
|
||||
message: 'Folder opened',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
ElMessage({
|
||||
message: "Folder dosn't exist",
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openCrashVrcCrashDumps() {
|
||||
AppApi.OpenCrashVrcCrashDumps().then((result) => {
|
||||
if (result) {
|
||||
ElMessage({
|
||||
message: 'Folder opened',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
ElMessage({
|
||||
message: "Folder dosn't exist",
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function openShortcutFolder() {
|
||||
AppApi.OpenShortcutFolder();
|
||||
}
|
||||
|
||||
function showYouTubeApiDialog() {
|
||||
isYouTubeApiDialogVisible.value = true;
|
||||
}
|
||||
|
||||
function refreshCacheSize() {
|
||||
cacheSize.cachedUsers = cachedUsers.size;
|
||||
cacheSize.cachedWorlds = cachedWorlds.size;
|
||||
cacheSize.cachedAvatars = cachedAvatars.size;
|
||||
cacheSize.cachedGroups = cachedGroups.size;
|
||||
cacheSize.cachedAvatarNames = cachedAvatarNames.size;
|
||||
cacheSize.cachedInstances = cachedInstances.size;
|
||||
}
|
||||
|
||||
async function changeYouTubeApi(configKey = '') {
|
||||
if (configKey === 'VRCX_youtubeAPI') {
|
||||
advancedSettingsStore.setYouTubeApi();
|
||||
} else if (configKey === 'VRCX_progressPie') {
|
||||
advancedSettingsStore.setProgressPie();
|
||||
} else if (configKey === 'VRCX_progressPieFilter') {
|
||||
advancedSettingsStore.setProgressPieFilter();
|
||||
}
|
||||
updateVRLastLocation();
|
||||
updateOpenVR();
|
||||
}
|
||||
</script>
|
||||
447
src/views/Settings/components/Tabs/AppearanceTab.vue
Normal file
447
src/views/Settings/components/Tabs/AppearanceTab.vue
Normal file
@@ -0,0 +1,447 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="options-container" style="margin-top: 0">
|
||||
<span class="header">{{ t('view.settings.appearance.appearance.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.language') }}</span>
|
||||
<el-dropdown trigger="click" size="small" @click.stop>
|
||||
<el-button size="small">
|
||||
<span
|
||||
>{{ messages[appLanguage]?.language }}
|
||||
<el-icon class="el-icon--right"><ArrowDown /></el-icon
|
||||
></span>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="(obj, language) in messages"
|
||||
:key="language"
|
||||
:class="{ 'is-active': appLanguage === language }"
|
||||
@click="changeAppLanguage(language)"
|
||||
v-text="obj.language" />
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.theme_mode') }}</span>
|
||||
<el-dropdown trigger="click" size="small" @click.stop>
|
||||
<el-button size="small">
|
||||
<span
|
||||
>{{ t(`view.settings.appearance.appearance.theme_mode_${themeMode}`) }}
|
||||
<el-icon class="el-icon--right"><ArrowDown /></el-icon
|
||||
></span>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="(config, themeKey) in THEME_CONFIG"
|
||||
:key="themeKey"
|
||||
@click="saveThemeMode(themeKey)"
|
||||
:class="{ 'is-active': themeMode === themeKey }">
|
||||
{{ t(`view.settings.appearance.appearance.theme_mode_${themeKey}`) }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div v-if="!isLinux" class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.zoom') }}</span>
|
||||
<el-input-number
|
||||
v-model="zoomLevel"
|
||||
size="small"
|
||||
:precision="0"
|
||||
style="width: 128px"
|
||||
@change="setZoomLevel" />
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.appearance.vrcplus_profile_icons')"
|
||||
:value="displayVRCPlusIconsAsAvatar"
|
||||
@change="
|
||||
setDisplayVRCPlusIconsAsAvatar();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.appearance.nicknames')"
|
||||
:value="!hideNicknames"
|
||||
@change="
|
||||
setHideNicknames();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.appearance.age_gated_instances')"
|
||||
:value="isAgeGatedInstancesVisible"
|
||||
@change="setIsAgeGatedInstancesVisible" />
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.sort_favorite_by') }}</span>
|
||||
<el-radio-group :model-value="sortFavorites" @change="saveSortFavoritesOption">
|
||||
<el-radio :label="false">{{
|
||||
t('view.settings.appearance.appearance.sort_favorite_by_name')
|
||||
}}</el-radio>
|
||||
<el-radio :label="true">{{
|
||||
t('view.settings.appearance.appearance.sort_favorite_by_date')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.sort_instance_users_by') }}</span>
|
||||
<el-radio-group :model-value="instanceUsersSortAlphabetical" @change="setInstanceUsersSortAlphabetical">
|
||||
<el-radio :label="false">{{
|
||||
t('view.settings.appearance.appearance.sort_instance_users_by_time')
|
||||
}}</el-radio>
|
||||
<el-radio :label="true">{{
|
||||
t('view.settings.appearance.appearance.sort_instance_users_by_alphabet')
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="Notebook" style="margin-right: 10px" @click="promptMaxTableSizeDialog">{{
|
||||
t('view.settings.appearance.appearance.table_max_size')
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="options-container-item" />
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.appearance.timedate.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.timedate.time_format') }}</span>
|
||||
<el-radio-group
|
||||
:model-value="dtHour12"
|
||||
@change="
|
||||
setDtHour12();
|
||||
updateVRConfigVars();
|
||||
">
|
||||
<el-radio :label="true">{{ t('view.settings.appearance.timedate.time_format_12') }}</el-radio>
|
||||
<el-radio :label="false">{{ t('view.settings.appearance.timedate.time_format_24') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.timedate.force_iso_date_format')"
|
||||
:value="dtIsoFormat"
|
||||
@change="setDtIsoFormat" />
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.appearance.side_panel.header') }}</span>
|
||||
<br />
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.side_panel.sorting.header') }}</span>
|
||||
<el-select
|
||||
:model-value="sidebarSortMethod1"
|
||||
style="width: 170px"
|
||||
:placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')"
|
||||
@change="setSidebarSortMethod1($event)">
|
||||
<el-option-group :label="t('view.settings.appearance.side_panel.sorting.dropdown_header')">
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.alphabetical')"
|
||||
value="Sort Alphabetically"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.status')"
|
||||
value="Sort by Status"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.private_to_bottom')"
|
||||
value="Sort Private to Bottom"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_active')"
|
||||
value="Sort by Last Active"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_seen')"
|
||||
value="Sort by Last Seen"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.time_in_instance')"
|
||||
value="Sort by Time in Instance"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.location')"
|
||||
value="Sort by Location"></el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<el-icon style="padding: 5px"><ArrowRight /></el-icon>
|
||||
<el-select
|
||||
:model-value="sidebarSortMethod2"
|
||||
:disabled="!sidebarSortMethod1"
|
||||
style="width: 170px"
|
||||
clearable
|
||||
:placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')"
|
||||
@change="setSidebarSortMethod2($event)">
|
||||
<el-option-group :label="t('view.settings.appearance.side_panel.sorting.dropdown_header')">
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.alphabetical')"
|
||||
value="Sort Alphabetically"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.status')"
|
||||
value="Sort by Status"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.private_to_bottom')"
|
||||
value="Sort Private to Bottom"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_active')"
|
||||
value="Sort by Last Active"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_seen')"
|
||||
value="Sort by Last Seen"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.time_in_instance')"
|
||||
value="Sort by Time in Instance"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.location')"
|
||||
value="Sort by Location"></el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<el-icon style="padding: 5px"><ArrowRight /></el-icon>
|
||||
<el-select
|
||||
:model-value="sidebarSortMethod3"
|
||||
:disabled="!sidebarSortMethod2"
|
||||
style="width: 170px"
|
||||
clearable
|
||||
:placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')"
|
||||
@change="setSidebarSortMethod3($event)">
|
||||
<el-option-group :label="t('view.settings.appearance.side_panel.sorting.dropdown_header')">
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.alphabetical')"
|
||||
value="Sort Alphabetically"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.status')"
|
||||
value="Sort by Status"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.private_to_bottom')"
|
||||
value="Sort Private to Bottom"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_active')"
|
||||
value="Sort by Last Active"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.last_seen')"
|
||||
value="Sort by Last Seen"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.time_in_instance')"
|
||||
value="Sort by Time in Instance"></el-option>
|
||||
<el-option
|
||||
class="x-friend-item"
|
||||
:label="t('view.settings.appearance.side_panel.sorting.location')"
|
||||
value="Sort by Location"></el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.side_panel.group_by_instance')"
|
||||
:value="isSidebarGroupByInstance"
|
||||
:tooltip="t('view.settings.appearance.side_panel.group_by_instance_tooltip')"
|
||||
@change="setIsSidebarGroupByInstance"></simple-switch>
|
||||
<simple-switch
|
||||
v-if="isSidebarGroupByInstance"
|
||||
:label="t('view.settings.appearance.side_panel.hide_friends_in_same_instance')"
|
||||
:value="isHideFriendsInSameInstance"
|
||||
:tooltip="t('view.settings.appearance.side_panel.hide_friends_in_same_instance_tooltip')"
|
||||
@change="setIsHideFriendsInSameInstance"></simple-switch>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.side_panel.split_favorite_friends')"
|
||||
:value="isSidebarDivideByFriendGroup"
|
||||
:tooltip="t('view.settings.appearance.side_panel.split_favorite_friends_tooltip')"
|
||||
@change="setIsSidebarDivideByFriendGroup"></simple-switch>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.appearance.user_dialog.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.user_dialog.vrchat_notes')"
|
||||
:value="!hideUserNotes"
|
||||
@change="setHideUserNotes" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.user_dialog.vrcx_memos')"
|
||||
:value="!hideUserMemos"
|
||||
@change="setHideUserMemos" />
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{
|
||||
t('view.settings.appearance.user_dialog.export_vrcx_memos_into_vrchat_notes')
|
||||
}}</span>
|
||||
<br />
|
||||
<el-button size="small" :icon="DocumentCopy" style="margin-top: 5px" @click="redirectToToolsTab">{{
|
||||
t('view.settings.appearance.user_dialog.export_notes')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.appearance.friend_log.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.friend_log.hide_unfriends')"
|
||||
:value="hideUnfriends"
|
||||
@change="setHideUnfriends"></simple-switch>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.appearance.user_colors.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.user_colors.random_colors_from_user_id')"
|
||||
:value="randomUserColours"
|
||||
@change="updateTrustColor('', '', true)"></simple-switch>
|
||||
<div class="options-container-item">
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.untrusted"
|
||||
size="small"
|
||||
:predefine="['#CCCCCC']"
|
||||
@change="updateTrustColor('untrusted', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-untrusted">Visitor</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.basic"
|
||||
size="small"
|
||||
:predefine="['#1778ff']"
|
||||
@change="updateTrustColor('basic', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-basic">New User</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.known"
|
||||
size="small"
|
||||
:predefine="['#2bcf5c']"
|
||||
@change="updateTrustColor('known', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-known">User</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.trusted"
|
||||
size="small"
|
||||
:predefine="['#ff7b42']"
|
||||
@change="updateTrustColor('trusted', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-trusted">Known User</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.veteran"
|
||||
size="small"
|
||||
:predefine="['#b18fff', '#8143e6', '#ff69b4', '#b52626', '#ffd000', '#abcdef']"
|
||||
@change="updateTrustColor('veteran', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-veteran">Trusted User</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.vip"
|
||||
size="small"
|
||||
:predefine="['#ff2626']"
|
||||
@change="updateTrustColor('vip', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-vip">VRChat Team</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-color-picker
|
||||
:model-value="trustColor.troll"
|
||||
size="small"
|
||||
:predefine="['#782f2f']"
|
||||
@change="updateTrustColor('troll', $event)">
|
||||
</el-color-picker>
|
||||
<span class="color-picker x-tag-troll">Nuisance</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ArrowDown, ArrowRight, DocumentCopy, Notebook } from '@element-plus/icons-vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useAppearanceSettingsStore, useFavoriteStore, useVrStore } from '../../../../stores';
|
||||
import { THEME_CONFIG } from '../../../../shared/constants';
|
||||
import { redirectToToolsTab } from '../../../../shared/utils/base/ui';
|
||||
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { messages, t } = useI18n();
|
||||
|
||||
const appearanceSettingsStore = useAppearanceSettingsStore();
|
||||
const { saveOpenVROption, updateVRConfigVars } = useVrStore();
|
||||
|
||||
const {
|
||||
appLanguage,
|
||||
themeMode,
|
||||
displayVRCPlusIconsAsAvatar,
|
||||
hideNicknames,
|
||||
isAgeGatedInstancesVisible,
|
||||
sortFavorites,
|
||||
instanceUsersSortAlphabetical,
|
||||
dtHour12,
|
||||
dtIsoFormat,
|
||||
sidebarSortMethod1,
|
||||
sidebarSortMethod2,
|
||||
sidebarSortMethod3,
|
||||
isSidebarGroupByInstance,
|
||||
isHideFriendsInSameInstance,
|
||||
isSidebarDivideByFriendGroup,
|
||||
hideUserNotes,
|
||||
hideUserMemos,
|
||||
hideUnfriends,
|
||||
randomUserColours,
|
||||
trustColor
|
||||
} = storeToRefs(appearanceSettingsStore);
|
||||
|
||||
const { saveSortFavoritesOption } = useFavoriteStore();
|
||||
|
||||
const {
|
||||
setDisplayVRCPlusIconsAsAvatar,
|
||||
setHideNicknames,
|
||||
setIsAgeGatedInstancesVisible,
|
||||
setInstanceUsersSortAlphabetical,
|
||||
setDtHour12,
|
||||
setDtIsoFormat,
|
||||
setSidebarSortMethod1,
|
||||
setSidebarSortMethod2,
|
||||
setSidebarSortMethod3,
|
||||
setIsSidebarGroupByInstance,
|
||||
setIsHideFriendsInSameInstance,
|
||||
setIsSidebarDivideByFriendGroup,
|
||||
setHideUserNotes,
|
||||
setHideUserMemos,
|
||||
setHideUnfriends,
|
||||
updateTrustColor,
|
||||
saveThemeMode,
|
||||
changeAppLanguage,
|
||||
promptMaxTableSizeDialog
|
||||
} = appearanceSettingsStore;
|
||||
|
||||
const zoomLevel = ref(100);
|
||||
const isLinux = computed(() => LINUX);
|
||||
|
||||
initGetZoomLevel();
|
||||
|
||||
async function initGetZoomLevel() {
|
||||
addEventListener('wheel', (event) => {
|
||||
if (event.ctrlKey) {
|
||||
getZoomLevel();
|
||||
}
|
||||
});
|
||||
getZoomLevel();
|
||||
}
|
||||
|
||||
async function getZoomLevel() {
|
||||
zoomLevel.value = ((await AppApi.GetZoom()) + 10) * 10;
|
||||
}
|
||||
|
||||
function setZoomLevel() {
|
||||
AppApi.SetZoom(zoomLevel.value / 10 - 10);
|
||||
}
|
||||
</script>
|
||||
@@ -79,9 +79,9 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useAdvancedSettingsStore, useDiscordPresenceSettingsStore } from '../../../stores';
|
||||
import { useAdvancedSettingsStore, useDiscordPresenceSettingsStore } from '../../../../stores';
|
||||
|
||||
import SimpleSwitch from './SimpleSwitch.vue';
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
375
src/views/Settings/components/Tabs/GeneralTab.vue
Normal file
375
src/views/Settings/components/Tabs/GeneralTab.vue
Normal file
@@ -0,0 +1,375 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="options-container" style="margin-top: 0">
|
||||
<span class="header">{{ t('view.settings.general.general.header') }}</span>
|
||||
<div class="x-friend-list" style="margin-top: 10px">
|
||||
<div class="x-friend-item" style="cursor: default">
|
||||
<div class="detail">
|
||||
<span class="name">{{ t('view.settings.general.general.version') }}</span>
|
||||
<span class="extra" v-text="appVersion"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" @click="checkForVRCXUpdate">
|
||||
<div class="detail">
|
||||
<span class="name">{{ t('view.settings.general.general.latest_app_version') }}</span>
|
||||
<span v-if="latestAppVersion" class="extra" v-text="latestAppVersion"></span>
|
||||
<span v-else class="extra">{{
|
||||
t('view.settings.general.general.latest_app_version_refresh')
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" @click="openExternalLink('https://github.com/vrcx-team/VRCX')">
|
||||
<div class="detail">
|
||||
<span class="name">{{ t('view.settings.general.general.repository_url') }}</span>
|
||||
<span v-once class="extra">https://github.com/vrcx-team/VRCX</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="x-friend-item" @click="openExternalLink('https://vrcx.app/discord')">
|
||||
<div class="detail">
|
||||
<span class="name">{{ t('view.settings.general.general.support') }}</span>
|
||||
<span v-once class="extra">https://vrcx.app/discord</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.vrcx_updater.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="Document" @click="showChangeLogDialog">{{
|
||||
t('view.settings.general.vrcx_updater.change_log')
|
||||
}}</el-button>
|
||||
<el-button size="small" :icon="Upload" @click="showVRCXUpdateDialog()">{{
|
||||
t('view.settings.general.vrcx_updater.change_build')
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.vrcx_updater.update_action') }}</span>
|
||||
<br />
|
||||
<el-radio-group
|
||||
:model-value="autoUpdateVRCX"
|
||||
size="small"
|
||||
style="margin-top: 5px"
|
||||
@change="setAutoUpdateVRCX">
|
||||
<el-radio-button label="Off">{{
|
||||
t('view.settings.general.vrcx_updater.auto_update_off')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Notify">{{
|
||||
t('view.settings.general.vrcx_updater.auto_update_notify')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Auto Download">{{
|
||||
t('view.settings.general.vrcx_updater.auto_update_download')
|
||||
}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.application.header') }}</span>
|
||||
<simple-switch
|
||||
v-if="!isLinux"
|
||||
:label="t('view.settings.general.application.startup')"
|
||||
:value="isStartAtWindowsStartup"
|
||||
@change="setIsStartAtWindowsStartup" />
|
||||
<simple-switch
|
||||
v-if="!isLinux"
|
||||
:label="t('view.settings.general.application.minimized')"
|
||||
:value="isStartAsMinimizedState"
|
||||
@change="setIsStartAsMinimizedState" />
|
||||
<simple-switch
|
||||
v-else
|
||||
:label="t('view.settings.general.application.minimized')"
|
||||
:value="isStartAsMinimizedState"
|
||||
:tooltip="t('view.settings.general.application.startup_linux')"
|
||||
@change="setIsStartAsMinimizedState" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.general.application.tray')"
|
||||
:value="isCloseToTray"
|
||||
@change="setIsCloseToTray" />
|
||||
<simple-switch
|
||||
v-if="!isLinux"
|
||||
:label="t('view.settings.general.application.disable_gpu_acceleration')"
|
||||
:value="disableGpuAcceleration"
|
||||
:tooltip="t('view.settings.general.application.disable_gpu_acceleration_tooltip')"
|
||||
@change="setDisableGpuAcceleration" />
|
||||
<simple-switch
|
||||
v-if="!isLinux"
|
||||
:label="t('view.settings.general.application.disable_vr_overlay_gpu_acceleration')"
|
||||
:value="disableVrOverlayGpuAcceleration"
|
||||
:tooltip="t('view.settings.general.application.disable_gpu_acceleration_tooltip')"
|
||||
@change="setDisableVrOverlayGpuAcceleration" />
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="Connection" @click="promptProxySettings">{{
|
||||
t('view.settings.general.application.proxy')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.favorites.header') }}</span>
|
||||
<br />
|
||||
<el-select
|
||||
:model-value="localFavoriteFriendsGroups"
|
||||
multiple
|
||||
clearable
|
||||
:placeholder="t('view.settings.general.favorites.group_placeholder')"
|
||||
style="margin-top: 8px"
|
||||
@change="setLocalFavoriteFriendsGroups">
|
||||
<el-option-group :label="t('view.settings.general.favorites.group_placeholder')">
|
||||
<el-option
|
||||
v-for="group in favoriteFriendGroups"
|
||||
:key="group.key"
|
||||
:label="group.displayName"
|
||||
:value="group.key"
|
||||
class="x-friend-item">
|
||||
<div class="detail">
|
||||
<span class="name" v-text="group.displayName"></span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.logging.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.advanced.advanced.cache_debug.udon_exception_logging')"
|
||||
:value="udonExceptionLogging"
|
||||
@change="
|
||||
setUdonExceptionLogging();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.general.logging.resource_load')"
|
||||
:value="logResourceLoad"
|
||||
@change="setLogResourceLoad" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.general.logging.empty_avatar')"
|
||||
:value="logEmptyAvatars"
|
||||
@change="setLogEmptyAvatars" />
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.automation.header') }}</span>
|
||||
<simple-switch
|
||||
:label="t('view.settings.general.automation.auto_change_status')"
|
||||
:value="autoStateChangeEnabled"
|
||||
:tooltip="t('view.settings.general.automation.auto_state_change_tooltip')"
|
||||
@change="setAutoStateChangeEnabled" />
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.alone_status') }}</span>
|
||||
<el-select
|
||||
:model-value="autoStateChangeAloneStatus"
|
||||
:disabled="!autoStateChangeEnabled"
|
||||
style="margin-top: 8px"
|
||||
size="small"
|
||||
@change="setAutoStateChangeAloneStatus">
|
||||
<el-option :label="t('dialog.user.status.join_me')" value="join me">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.online')" value="active">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.ask_me')" value="ask me">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.busy')" value="busy">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.company_status') }}</span>
|
||||
<el-select
|
||||
:model-value="autoStateChangeCompanyStatus"
|
||||
:disabled="!autoStateChangeEnabled"
|
||||
style="margin-top: 8px"
|
||||
size="small"
|
||||
@change="setAutoStateChangeCompanyStatus">
|
||||
<el-option :label="t('dialog.user.status.join_me')" value="join me">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.online')" value="active">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.ask_me')" value="ask me">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</el-option>
|
||||
<el-option :label="t('dialog.user.status.busy')" value="busy">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.allowed_instance_types') }}</span>
|
||||
<el-select
|
||||
:model-value="autoStateChangeInstanceTypes"
|
||||
:disabled="!autoStateChangeEnabled"
|
||||
multiple
|
||||
clearable
|
||||
:placeholder="t('view.settings.general.automation.instance_type_placeholder')"
|
||||
style="margin-top: 8px"
|
||||
size="small"
|
||||
@change="setAutoStateChangeInstanceTypes">
|
||||
<el-option-group :label="t('view.settings.general.automation.allowed_instance_types')">
|
||||
<el-option
|
||||
v-for="instanceType in instanceTypes"
|
||||
:key="instanceType"
|
||||
:label="instanceType"
|
||||
:value="instanceType"
|
||||
class="x-friend-item">
|
||||
<div class="detail">
|
||||
<span class="name" v-text="instanceType"></span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.alone_condition') }}</span>
|
||||
<el-radio-group
|
||||
:model-value="autoStateChangeNoFriends"
|
||||
:disabled="!autoStateChangeEnabled"
|
||||
@change="setAutoStateChangeNoFriends">
|
||||
<el-radio :label="false">{{ t('view.settings.general.automation.alone') }}</el-radio>
|
||||
<el-radio :label="true">{{ t('view.settings.general.automation.no_friends') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name"
|
||||
>{{ t('view.settings.general.automation.auto_invite_request_accept') }}
|
||||
<el-tooltip
|
||||
placement="top"
|
||||
style="margin-left: 5px"
|
||||
:content="t('view.settings.general.automation.auto_invite_request_accept_tooltip')">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<br />
|
||||
<el-radio-group
|
||||
:model-value="autoAcceptInviteRequests"
|
||||
size="small"
|
||||
style="margin-top: 5px"
|
||||
@change="setAutoAcceptInviteRequests">
|
||||
<el-radio-button label="Off">{{
|
||||
t('view.settings.general.automation.auto_invite_request_accept_off')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="All Favorites">{{
|
||||
t('view.settings.general.automation.auto_invite_request_accept_favs')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Selected Favorites">{{
|
||||
t('view.settings.general.automation.auto_invite_request_accept_selected_favs')
|
||||
}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.contributors.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<img
|
||||
src="https://contrib.rocks/image?repo=vrcx-team/VRCX"
|
||||
alt="Contributors"
|
||||
style="cursor: pointer"
|
||||
@click="openExternalLink('https://github.com/vrcx-team/VRCX/graphs/contributors')" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container" style="margin-top: 45px; border-top: 1px solid #eee; padding-top: 30px">
|
||||
<span class="header">{{ t('view.settings.general.legal_notice.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<p>
|
||||
© 2019-2025
|
||||
<a class="x-link" @click="openExternalLink('https://github.com/pypy-vrc')">pypy</a> &
|
||||
<a class="x-link" @click="openExternalLink('https://github.com/Natsumi-sama')">Natsumi</a>
|
||||
</p>
|
||||
<p>{{ t('view.settings.general.legal_notice.info') }}</p>
|
||||
<p>{{ t('view.settings.general.legal_notice.disclaimer1') }}</p>
|
||||
<p>{{ t('view.settings.general.legal_notice.disclaimer2') }}</p>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" @click="openOSSDialog">{{
|
||||
t('view.settings.general.legal_notice.open_source_software_notice')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<OpenSourceSoftwareNoticeDialog v-if="ossDialog" v-model:ossDialog="ossDialog" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Connection, Document, InfoFilled, Upload } from '@element-plus/icons-vue';
|
||||
import { computed, defineAsyncComponent, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useFavoriteStore, useGeneralSettingsStore, useVRCXUpdaterStore, useVrStore } from '../../../../stores';
|
||||
import { openExternalLink } from '../../../../shared/utils';
|
||||
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const generalSettingsStore = useGeneralSettingsStore();
|
||||
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
||||
const favoriteStore = useFavoriteStore();
|
||||
|
||||
const { saveOpenVROption } = useVrStore();
|
||||
|
||||
const {
|
||||
isStartAtWindowsStartup,
|
||||
isStartAsMinimizedState,
|
||||
isCloseToTray,
|
||||
disableGpuAcceleration,
|
||||
disableVrOverlayGpuAcceleration,
|
||||
localFavoriteFriendsGroups,
|
||||
udonExceptionLogging,
|
||||
logResourceLoad,
|
||||
logEmptyAvatars,
|
||||
autoStateChangeEnabled,
|
||||
autoStateChangeAloneStatus,
|
||||
autoStateChangeCompanyStatus,
|
||||
autoStateChangeInstanceTypes,
|
||||
autoStateChangeNoFriends,
|
||||
autoAcceptInviteRequests
|
||||
} = storeToRefs(generalSettingsStore);
|
||||
|
||||
const {
|
||||
setIsStartAtWindowsStartup,
|
||||
setIsStartAsMinimizedState,
|
||||
setIsCloseToTray,
|
||||
setDisableGpuAcceleration,
|
||||
setDisableVrOverlayGpuAcceleration,
|
||||
setUdonExceptionLogging,
|
||||
setLogResourceLoad,
|
||||
setLogEmptyAvatars,
|
||||
setAutoStateChangeEnabled,
|
||||
setAutoStateChangeAloneStatus,
|
||||
setAutoStateChangeCompanyStatus,
|
||||
setAutoStateChangeInstanceTypes,
|
||||
setAutoStateChangeNoFriends,
|
||||
setAutoAcceptInviteRequests,
|
||||
setLocalFavoriteFriendsGroups,
|
||||
promptProxySettings
|
||||
} = generalSettingsStore;
|
||||
|
||||
const { favoriteFriendGroups } = storeToRefs(favoriteStore);
|
||||
|
||||
const { appVersion, autoUpdateVRCX, latestAppVersion } = storeToRefs(vrcxUpdaterStore);
|
||||
const { setAutoUpdateVRCX, checkForVRCXUpdate, showVRCXUpdateDialog, showChangeLogDialog } = vrcxUpdaterStore;
|
||||
|
||||
const instanceTypes = ref([
|
||||
'invite',
|
||||
'invite+',
|
||||
'friends',
|
||||
'friends+',
|
||||
'public',
|
||||
'groupPublic',
|
||||
'groupPlus',
|
||||
'groupOnly'
|
||||
]);
|
||||
|
||||
const ossDialog = ref(false);
|
||||
const isLinux = computed(() => LINUX);
|
||||
|
||||
const OpenSourceSoftwareNoticeDialog = defineAsyncComponent(
|
||||
() => import('../../dialogs/OpenSourceSoftwareNoticeDialog.vue')
|
||||
);
|
||||
|
||||
function openOSSDialog() {
|
||||
ossDialog.value = true;
|
||||
}
|
||||
</script>
|
||||
347
src/views/Settings/components/Tabs/NotificationsTab.vue
Normal file
347
src/views/Settings/components/Tabs/NotificationsTab.vue
Normal file
@@ -0,0 +1,347 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="options-container" style="margin-top: 0">
|
||||
<span class="header">{{ t('view.settings.notifications.notifications.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<el-button size="small" :icon="ChatSquare" @click="showNotyFeedFiltersDialog">{{
|
||||
t('view.settings.notifications.notifications.notification_filter')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="sub-header">{{
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.header')
|
||||
}}</span>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{
|
||||
t('view.settings.notifications.notifications.desktop_notifications.when_to_display')
|
||||
}}</span>
|
||||
<br />
|
||||
<el-radio-group
|
||||
:model-value="overlayToast"
|
||||
size="small"
|
||||
:disabled="
|
||||
(!overlayNotifications || !openVR) &&
|
||||
!xsNotifications &&
|
||||
!ovrtHudNotifications &&
|
||||
!ovrtWristNotifications
|
||||
"
|
||||
style="margin-top: 5px"
|
||||
@change="
|
||||
setOverlayToast($event);
|
||||
saveOpenVROption();
|
||||
">
|
||||
<el-radio-button label="Never">{{
|
||||
t('view.settings.notifications.notifications.conditions.never')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Running">{{
|
||||
t('view.settings.notifications.notifications.conditions.inside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Closed">{{
|
||||
t('view.settings.notifications.notifications.conditions.outside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Always">{{
|
||||
t('view.settings.notifications.notifications.conditions.always')
|
||||
}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.notifications.notifications.steamvr_notifications.steamvr_overlay')"
|
||||
:value="openVR"
|
||||
@change="
|
||||
setOpenVR();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<template v-if="openVR">
|
||||
<simple-switch
|
||||
:label="t('view.settings.notifications.notifications.steamvr_notifications.overlay_notifications')"
|
||||
:value="overlayNotifications"
|
||||
:disabled="!openVR"
|
||||
@change="
|
||||
setOverlayNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<div class="options-container-item">
|
||||
<el-button
|
||||
size="small"
|
||||
:icon="Rank"
|
||||
:disabled="!overlayNotifications || !openVR"
|
||||
@click="showNotificationPositionDialog"
|
||||
>{{
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.notification_position')
|
||||
}}</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name" style="vertical-align: top; padding-top: 10px">{{
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.notification_opacity')
|
||||
}}</span>
|
||||
<el-slider
|
||||
:model-value="notificationOpacity"
|
||||
@input="setNotificationOpacity"
|
||||
:min="0"
|
||||
:max="100"
|
||||
style="display: inline-block; width: 300px; padding-top: 16px" />
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<el-button
|
||||
size="small"
|
||||
:icon="Timer"
|
||||
:disabled="(!overlayNotifications || !openVR) && !xsNotifications"
|
||||
@click="promptNotificationTimeout"
|
||||
>{{
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.notification_timeout')
|
||||
}}</el-button
|
||||
>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.notifications.notifications.steamvr_notifications.user_images')"
|
||||
:value="imageNotifications"
|
||||
@change="
|
||||
setImageNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
</template>
|
||||
<template v-if="!isLinux">
|
||||
<simple-switch
|
||||
:label="
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.xsoverlay_notifications')
|
||||
"
|
||||
:value="xsNotifications"
|
||||
@change="
|
||||
setXsNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<simple-switch
|
||||
:label="
|
||||
t('view.settings.notifications.notifications.steamvr_notifications.wlxoverlay_notifications')
|
||||
"
|
||||
:value="xsNotifications"
|
||||
@change="
|
||||
setXsNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
</template>
|
||||
<template v-if="!isLinux">
|
||||
<simple-switch
|
||||
:label="
|
||||
t(
|
||||
'view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_hud_notifications'
|
||||
)
|
||||
"
|
||||
:value="ovrtHudNotifications"
|
||||
@change="
|
||||
setOvrtHudNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<simple-switch
|
||||
:label="
|
||||
t(
|
||||
'view.settings.notifications.notifications.steamvr_notifications.ovrtoolkit_wrist_notifications'
|
||||
)
|
||||
"
|
||||
:value="ovrtWristNotifications"
|
||||
@change="
|
||||
setOvrtWristNotifications();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="sub-header">{{
|
||||
t('view.settings.notifications.notifications.desktop_notifications.header')
|
||||
}}</span>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{
|
||||
t('view.settings.notifications.notifications.desktop_notifications.when_to_display')
|
||||
}}</span>
|
||||
<br />
|
||||
<el-radio-group
|
||||
:model-value="desktopToast"
|
||||
size="small"
|
||||
style="margin-top: 5px"
|
||||
@change="
|
||||
setDesktopToast($event);
|
||||
saveOpenVROption();
|
||||
">
|
||||
<el-radio-button label="Never">{{
|
||||
t('view.settings.notifications.notifications.conditions.never')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Desktop Mode">{{
|
||||
t('view.settings.notifications.notifications.conditions.desktop')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Inside VR">{{
|
||||
t('view.settings.notifications.notifications.conditions.inside_vr')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Outside VR">{{
|
||||
t('view.settings.notifications.notifications.conditions.outside_vr')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Running">{{
|
||||
t('view.settings.notifications.notifications.conditions.inside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Closed">{{
|
||||
t('view.settings.notifications.notifications.conditions.outside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Always">{{
|
||||
t('view.settings.notifications.notifications.conditions.always')
|
||||
}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="
|
||||
t('view.settings.notifications.notifications.desktop_notifications.desktop_notification_while_afk')
|
||||
"
|
||||
:value="afkDesktopToast"
|
||||
@change="
|
||||
setAfkDesktopToast();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="sub-header">{{ t('view.settings.notifications.notifications.text_to_speech.header') }}</span>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{
|
||||
t('view.settings.notifications.notifications.text_to_speech.when_to_play')
|
||||
}}</span>
|
||||
<br />
|
||||
<el-radio-group
|
||||
:model-value="notificationTTS"
|
||||
size="small"
|
||||
style="margin-top: 5px"
|
||||
@change="saveNotificationTTS">
|
||||
<el-radio-button label="Never">{{
|
||||
t('view.settings.notifications.notifications.conditions.never')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Inside VR">{{
|
||||
t('view.settings.notifications.notifications.conditions.inside_vr')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Running">{{
|
||||
t('view.settings.notifications.notifications.conditions.inside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Game Closed">{{
|
||||
t('view.settings.notifications.notifications.conditions.outside_vrchat')
|
||||
}}</el-radio-button>
|
||||
<el-radio-button label="Always">{{
|
||||
t('view.settings.notifications.notifications.conditions.always')
|
||||
}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.notifications.notifications.text_to_speech.tts_voice') }}</span>
|
||||
<el-dropdown trigger="click" size="small" @command="(voice) => changeTTSVoice(voice)">
|
||||
<el-button size="small" :disabled="notificationTTS === 'Never'">
|
||||
<span
|
||||
>{{ getTTSVoiceName() }} <el-icon style="margin-left: 5px"><ArrowDown /></el-icon
|
||||
></span>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="(voice, index) in TTSvoices"
|
||||
:key="index"
|
||||
:command="index"
|
||||
v-text="voice.name" />
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.notifications.notifications.text_to_speech.use_memo_nicknames')"
|
||||
:value="notificationTTSNickName"
|
||||
:disabled="notificationTTS === 'Never'"
|
||||
@change="
|
||||
setNotificationTTSNickName();
|
||||
saveOpenVROption();
|
||||
" />
|
||||
<simple-switch
|
||||
:label="t('view.settings.notifications.notifications.text_to_speech.tts_test_placeholder')"
|
||||
:value="isTestTTSVisible"
|
||||
@change="isTestTTSVisible = !isTestTTSVisible" />
|
||||
<div v-if="isTestTTSVisible" style="margin-top: 5px">
|
||||
<el-input
|
||||
v-model="notificationTTSTest"
|
||||
type="textarea"
|
||||
:placeholder="t('view.settings.notifications.notifications.text_to_speech.tts_test_placeholder')"
|
||||
:rows="1"
|
||||
style="width: 175px; display: inline-block"></el-input>
|
||||
<el-button size="small" :icon="VideoPlay" style="margin-left: 10px" @click="testNotificationTTS">{{
|
||||
t('view.settings.notifications.notifications.text_to_speech.play')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<NotificationPositionDialog v-model:isNotificationPositionDialogVisible="isNotificationPositionDialogVisible" />
|
||||
<FeedFiltersDialog v-model:feedFiltersDialogMode="feedFiltersDialogMode" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ArrowDown, ChatSquare, Rank, Timer, VideoPlay } from '@element-plus/icons-vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useAdvancedSettingsStore, useNotificationsSettingsStore, useVrStore } from '../../../../stores';
|
||||
|
||||
import FeedFiltersDialog from '../../dialogs/FeedFiltersDialog.vue';
|
||||
import NotificationPositionDialog from '../../dialogs/NotificationPositionDialog.vue';
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const notificationsSettingsStore = useNotificationsSettingsStore();
|
||||
const advancedSettingsStore = useAdvancedSettingsStore();
|
||||
const { saveOpenVROption } = useVrStore();
|
||||
|
||||
const {
|
||||
overlayToast,
|
||||
openVR,
|
||||
overlayNotifications,
|
||||
xsNotifications,
|
||||
ovrtHudNotifications,
|
||||
ovrtWristNotifications,
|
||||
imageNotifications,
|
||||
desktopToast,
|
||||
afkDesktopToast,
|
||||
notificationTTS,
|
||||
notificationTTSNickName,
|
||||
isTestTTSVisible,
|
||||
notificationTTSTest,
|
||||
TTSvoices
|
||||
} = storeToRefs(notificationsSettingsStore);
|
||||
|
||||
const { notificationOpacity } = storeToRefs(advancedSettingsStore);
|
||||
|
||||
const {
|
||||
setOverlayToast,
|
||||
setOpenVR,
|
||||
setOverlayNotifications,
|
||||
setXsNotifications,
|
||||
setOvrtHudNotifications,
|
||||
setOvrtWristNotifications,
|
||||
setImageNotifications,
|
||||
setDesktopToast,
|
||||
setAfkDesktopToast,
|
||||
setNotificationTTSNickName,
|
||||
getTTSVoiceName,
|
||||
changeTTSVoice,
|
||||
saveNotificationTTS,
|
||||
testNotificationTTS,
|
||||
promptNotificationTimeout
|
||||
} = notificationsSettingsStore;
|
||||
|
||||
const { setNotificationOpacity } = advancedSettingsStore;
|
||||
|
||||
const feedFiltersDialogMode = ref('');
|
||||
const isNotificationPositionDialogVisible = ref(false);
|
||||
const isLinux = computed(() => LINUX);
|
||||
|
||||
function showNotyFeedFiltersDialog() {
|
||||
feedFiltersDialogMode.value = 'noty';
|
||||
}
|
||||
|
||||
function showNotificationPositionDialog() {
|
||||
isNotificationPositionDialogVisible.value = true;
|
||||
}
|
||||
</script>
|
||||
@@ -132,10 +132,10 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { redirectToToolsTab } from '../../../shared/utils/base/ui';
|
||||
import { useAdvancedSettingsStore } from '../../../stores';
|
||||
import { redirectToToolsTab } from '../../../../shared/utils/base/ui';
|
||||
import { useAdvancedSettingsStore } from '../../../../stores';
|
||||
|
||||
import SimpleSwitch from './SimpleSwitch.vue';
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
19
src/views/Settings/components/Tabs/WristOverlayTab.vue
Normal file
19
src/views/Settings/components/Tabs/WristOverlayTab.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<WristOverlaySettings @open-feed-filters="showWristFeedFiltersDialog" />
|
||||
<FeedFiltersDialog v-model:feedFiltersDialogMode="feedFiltersDialogMode" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import FeedFiltersDialog from '../../dialogs/FeedFiltersDialog.vue';
|
||||
import WristOverlaySettings from '../WristOverlaySettings.vue';
|
||||
|
||||
const feedFiltersDialogMode = ref('');
|
||||
|
||||
function showWristFeedFiltersDialog() {
|
||||
feedFiltersDialogMode.value = 'wrist';
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user