improve settings ui

This commit is contained in:
pa
2026-03-23 20:20:59 +09:00
parent e6ec7e6150
commit 296e254718
7 changed files with 271 additions and 264 deletions

View File

@@ -15,7 +15,9 @@
"delete": "Delete",
"remove": "Remove",
"reset": "Reset",
"view_details": "View Details"
"view_details": "View Details",
"configure": "Configure",
"refresh": "Refresh"
},
"sort_by": "Sort by:",
"time_units": {
@@ -920,7 +922,7 @@
"vrcx_memos_description": "Shows notes saved locally in VRCX",
"recent_action_cooldown": "Recent Action Indicator",
"recent_action_cooldown_description": "Show a clock icon on invite/request actions that were recently performed",
"recent_action_cooldown_minutes": "Cooldown (minutes)"
"recent_action_cooldown_minutes": "Cooldown (Minutes)"
},
"user_colors": {
"header": "User Colors",
@@ -974,7 +976,7 @@
},
"text_to_speech": {
"header": "Text-To-Speech",
"when_to_play": "Notification TTS. When to Play",
"when_to_play": "Notification TTS",
"tts_voice": "TTS Voice",
"use_memo_nicknames": "Use Memo Nicknames",
"play": "Play",

View File

@@ -410,6 +410,20 @@ export const useNotificationsSettingsStore = defineStore(
speechSynthesis.speak(tts);
}
/**
* @param {number} seconds - timeout in seconds
*/
function setNotificationTimeout(seconds) {
const ms = Math.trunc(Number(seconds) * 1000);
if (isNaN(ms) || ms < 0) return;
notificationTimeout.value = ms;
configRepository.setString(
'VRCX_notificationTimeout',
ms.toString()
);
vrStore.updateVRConfigVars();
}
function promptNotificationTimeout() {
modalStore
.prompt({
@@ -474,6 +488,7 @@ export const useNotificationsSettingsStore = defineStore(
testNotificationTTS,
speak,
changeNotificationPosition,
setNotificationTimeout,
promptNotificationTimeout
};
}

View File

@@ -227,7 +227,9 @@
<span v-text="sqliteTableSizes.event"></span
></span>
</div>
</SettingsGroup>
<SettingsGroup :title="t('view.settings.advanced.advanced.database_cleanup.header')">
<SettingsItem
:label="t('view.settings.advanced.advanced.database_cleanup.auto_cleanup')"
:description="t('view.settings.advanced.advanced.database_cleanup.auto_cleanup_description')">
@@ -329,45 +331,38 @@
</Dialog>
<SettingsGroup :title="t('view.settings.advanced_groups.diagnostics.header')">
<SettingsGroup :title="t('view.profile.game_info.header')">
<div class="px-1 py-1">
<div class="flex-1 cursor-pointer" @click="getVisits">
<span class="block truncate font-medium text-sm leading-[18px]">{{
t('view.profile.game_info.online_users')
}}</span>
<span v-if="visits" class="block truncate text-xs text-muted-foreground">{{
t('view.profile.game_info.user_online', { count: visits })
}}</span>
<span v-else class="block truncate text-xs text-muted-foreground">{{
t('view.profile.game_info.refresh')
}}</span>
</div>
</div>
</SettingsGroup>
<SettingsGroup :title="t('view.profile.config_json')">
<SettingsItem :label="t('view.profile.game_info.online_users')">
<div class="flex items-center gap-2">
<TooltipWrapper side="top" :content="t('view.profile.refresh_tooltip')">
<Button class="rounded-full" size="icon-sm" variant="outline" @click="refreshConfigTreeData()">
<RefreshCcw />
</Button>
</TooltipWrapper>
<TooltipWrapper side="top" :content="t('view.profile.clear_results_tooltip')">
<Button class="rounded-full" size="icon-sm" variant="outline" @click="configTreeData = {}">
<Trash2 />
</Button>
</TooltipWrapper>
<span v-if="visits !== null" class="text-sm text-muted-foreground">{{
t('view.profile.game_info.user_online', { count: visits })
}}</span>
<Button size="sm" variant="outline" @click="getVisits">{{ t('common.actions.refresh') }}</Button>
</div>
<vue-json-pretty
v-if="Object.keys(configTreeData).length > 0"
:data="configTreeData"
:deep="2"
:theme="isDarkMode ? 'dark' : 'light'"
:height="800"
:dynamic-height="false"
virtual
show-icon />
</SettingsGroup>
</SettingsItem>
<SettingsItem :label="t('view.profile.config_json')">
<div class="flex items-center gap-2">
<Button size="sm" variant="outline" @click="refreshConfigTreeData()">{{
t('common.actions.refresh')
}}</Button>
<Button
v-if="Object.keys(configTreeData).length > 0"
size="sm"
variant="outline"
@click="configTreeData = {}"
>{{ t('common.actions.clear') }}</Button
>
</div>
</SettingsItem>
<vue-json-pretty
v-if="Object.keys(configTreeData).length > 0"
:data="configTreeData"
:deep="2"
:theme="isDarkMode ? 'dark' : 'light'"
:height="800"
:dynamic-height="false"
virtual
show-icon />
</SettingsGroup>
<template v-if="branch === 'Nightly'">
@@ -386,7 +381,7 @@
</template>
<script setup>
import { RefreshCcw, Trash2, TriangleAlert } from 'lucide-vue-next';
import { Trash2, TriangleAlert } from 'lucide-vue-next';
import { computed, reactive, ref } from 'vue';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
@@ -421,7 +416,6 @@
import RegistryBackupDialog from '../../../Tools/dialogs/RegistryBackupDialog.vue';
import SettingsGroup from '../SettingsGroup.vue';
import SettingsItem from '../SettingsItem.vue';
import { TooltipWrapper } from '@/components/ui/tooltip';
const { t } = useI18n();
@@ -486,7 +480,7 @@
} = advancedSettingsStore;
const configTreeData = ref({});
const visits = ref(0);
const visits = ref(null);
const selectedPurgePeriod = ref('180');
const isPurgeDialogVisible = ref(false);

View File

@@ -156,97 +156,120 @@
<SettingsGroup :title="t('view.settings.interface.lists_tables.header')">
<SettingsItem :label="t('view.settings.appearance.appearance.sort_favorite_by')">
<RadioGroup
<ToggleGroup
type="single"
required
variant="outline"
size="sm"
:model-value="sortFavorites ? 'true' : 'false'"
class="gap-2 flex"
@update:modelValue="handleSortFavoritesRadio">
<div class="flex items-center space-x-2">
<RadioGroupItem id="sortFavorites-false" value="false" />
<label for="sortFavorites-false">
{{ t('view.settings.appearance.appearance.sort_favorite_by_name') }}
</label>
</div>
<div class="flex items-center space-x-2">
<RadioGroupItem id="sortFavorites-true" value="true" />
<label for="sortFavorites-true">
{{ t('view.settings.appearance.appearance.sort_favorite_by_date') }}
</label>
</div>
</RadioGroup>
@update:model-value="handleSortFavoritesRadio">
<ToggleGroupItem value="false">{{
t('view.settings.appearance.appearance.sort_favorite_by_name')
}}</ToggleGroupItem>
<ToggleGroupItem value="true">{{
t('view.settings.appearance.appearance.sort_favorite_by_date')
}}</ToggleGroupItem>
</ToggleGroup>
</SettingsItem>
<SettingsItem :label="t('view.settings.appearance.appearance.sort_instance_users_by')">
<RadioGroup
<ToggleGroup
type="single"
required
variant="outline"
size="sm"
:model-value="instanceUsersSortAlphabetical ? 'true' : 'false'"
class="gap-2 flex"
@update:modelValue="handleInstanceUsersSortAlphabeticalRadio">
<div class="flex items-center space-x-2">
<RadioGroupItem id="instanceUsersSortAlphabetical-false" value="false" />
<label for="instanceUsersSortAlphabetical-false">
{{ t('view.settings.appearance.appearance.sort_instance_users_by_time') }}
</label>
</div>
<div class="flex items-center space-x-2">
<RadioGroupItem id="instanceUsersSortAlphabetical-true" value="true" />
<label for="instanceUsersSortAlphabetical-true">
{{ t('view.settings.appearance.appearance.sort_instance_users_by_alphabet') }}
</label>
</div>
</RadioGroup>
@update:model-value="handleInstanceUsersSortAlphabeticalRadio">
<ToggleGroupItem value="false">{{
t('view.settings.appearance.appearance.sort_instance_users_by_time')
}}</ToggleGroupItem>
<ToggleGroupItem value="true">{{
t('view.settings.appearance.appearance.sort_instance_users_by_alphabet')
}}</ToggleGroupItem>
</ToggleGroup>
</SettingsItem>
<SettingsItem :label="t('view.settings.appearance.appearance.table_page_sizes')">
<Popover v-model:open="tablePageSizesOpen">
<ListboxRoot v-model="tablePageSizesModel" highlight-on-hover multiple>
<PopoverAnchor class="inline-flex w-75">
<TagsInput v-slot="{ modelValue: tags }" v-model="tablePageSizesModel" class="w-full">
<TagsInputItem v-for="item in tags" :key="item.toString()" :value="item.toString()">
<TagsInputItemText />
<TagsInputItemDelete />
</TagsInputItem>
<Button size="sm" variant="outline" @click="tablePageSizesDialogOpen = true">{{
t('common.actions.configure')
}}</Button>
<ListboxFilter v-model="tablePageSizesSearchTerm" as-child>
<TagsInputInput
:placeholder="t('view.settings.appearance.appearance.table_page_sizes')"
@keydown.enter.prevent="addTablePageSizeFromInput"
@keydown.down="tablePageSizesOpen = true" />
</ListboxFilter>
<Dialog v-model:open="tablePageSizesDialogOpen">
<DialogContent class="sm:max-w-md">
<DialogHeader>
<DialogTitle>{{ t('view.settings.appearance.appearance.table_page_sizes') }}</DialogTitle>
</DialogHeader>
<PopoverTrigger as-child>
<Button size="icon-sm" variant="ghost" class="order-last self-start ml-auto">
<ChevronDown class="size-3.5" />
</Button>
</PopoverTrigger>
</TagsInput>
</PopoverAnchor>
<Popover v-model:open="tablePageSizesOpen">
<ListboxRoot v-model="tablePageSizesModel" highlight-on-hover multiple>
<PopoverAnchor class="inline-flex w-full">
<TagsInput
v-slot="{ modelValue: tags }"
v-model="tablePageSizesModel"
class="w-full">
<TagsInputItem
v-for="item in tags"
:key="item.toString()"
:value="item.toString()">
<TagsInputItemText />
<TagsInputItemDelete />
</TagsInputItem>
<PopoverContent class="p-1" @open-auto-focus.prevent>
<ListboxContent
class="max-h-75 scroll-py-1 overflow-x-hidden overflow-y-auto empty:after:content-['No_options'] empty:p-1 empty:after:block"
tabindex="0">
<ListboxItem
v-for="size in filteredTablePageSizeOptions"
:key="size"
class="data-highlighted:bg-accent data-highlighted:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
:value="size"
@select="tablePageSizesSearchTerm = ''">
<span>{{ size }}</span>
<ListboxFilter v-model="tablePageSizesSearchTerm" as-child>
<TagsInputInput
:placeholder="t('view.settings.appearance.appearance.table_page_sizes')"
@keydown.down="tablePageSizesOpen = true" />
</ListboxFilter>
<ListboxItemIndicator class="ml-auto inline-flex items-center justify-center">
<CheckIcon />
</ListboxItemIndicator>
</ListboxItem>
</ListboxContent>
</PopoverContent>
</ListboxRoot>
</Popover>
<PopoverTrigger as-child>
<Button
size="icon-sm"
variant="ghost"
class="order-last ml-auto self-start">
<ChevronDown class="size-3.5" />
</Button>
</PopoverTrigger>
</TagsInput>
</PopoverAnchor>
<PopoverContent
class="w-[var(--reka-popover-trigger-width)] p-1"
@open-auto-focus.prevent>
<ListboxContent
class="max-h-75 scroll-py-1 overflow-x-hidden overflow-y-auto empty:after:block empty:after:content-['No_options'] empty:p-1"
tabindex="0">
<ListboxItem
v-for="size in filteredTablePageSizeOptions"
:key="size"
class="data-highlighted:bg-accent data-highlighted:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
:value="size"
@select="tablePageSizesSearchTerm = ''">
<span>{{ size }}</span>
<ListboxItemIndicator
class="ml-auto inline-flex items-center justify-center">
<CheckIcon />
</ListboxItemIndicator>
</ListboxItem>
</ListboxContent>
</PopoverContent>
</ListboxRoot>
</Popover>
<DialogFooter>
<Button variant="outline" @click="tablePageSizesDialogOpen = false">{{
t('dialog.alertdialog.ok')
}}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</SettingsItem>
<SettingsItem
:label="t('view.settings.appearance.appearance.table_entries_settings')"
:description="t('view.settings.appearance.appearance.table_entries_settings_description')">
<Button size="sm" variant="outline" @click="showTableLimitsDialog">{{
t('view.settings.appearance.appearance.table_entries_settings')
t('common.actions.configure')
}}</Button>
</SettingsItem>
</SettingsGroup>
@@ -254,23 +277,20 @@
<SettingsGroup :title="t('view.settings.appearance.timedate.header')">
<SettingsItem :label="t('view.settings.appearance.timedate.time_format')">
<RadioGroup
<ToggleGroup
type="single"
required
variant="outline"
size="sm"
:model-value="dtHour12 ? 'true' : 'false'"
class="gap-2 flex"
@update:modelValue="handleDtHour12Radio">
<div class="flex items-center space-x-2">
<RadioGroupItem id="dtHour12-true" value="true" />
<label for="dtHour12-true">
{{ t('view.settings.appearance.timedate.time_format_12') }}
</label>
</div>
<div class="flex items-center space-x-2">
<RadioGroupItem id="dtHour12-false" value="false" />
<label for="dtHour12-false">
{{ t('view.settings.appearance.timedate.time_format_24') }}
</label>
</div>
</RadioGroup>
@update:model-value="handleDtHour12Radio">
<ToggleGroupItem value="true">{{
t('view.settings.appearance.timedate.time_format_12')
}}</ToggleGroupItem>
<ToggleGroupItem value="false">{{
t('view.settings.appearance.timedate.time_format_24')
}}</ToggleGroupItem>
</ToggleGroup>
</SettingsItem>
<SettingsItem :label="t('view.settings.appearance.timedate.force_iso_date_format')">
@@ -366,11 +386,13 @@
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { computed, onBeforeUnmount, ref, watch } from 'vue';
import { CheckIcon, ChevronDown } from 'lucide-vue-next';
import { useAppearanceSettingsStore, useFavoriteStore, useVrStore } from '@/stores';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { useAppearanceSettingsStore, useVrStore } from '@/stores';
import { Switch } from '@/components/ui/switch';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import { getLanguageName, languageCodes } from '@/localization';
import { APP_CJK_FONT_PACKS, APP_FONT_CONFIG, APP_FONT_DEFAULT_KEY, APP_FONT_FAMILIES } from '@/shared/constants';
import { Button } from '@/components/ui/button';
@@ -626,6 +648,7 @@
const TABLE_PAGE_SIZE_SUGGESTIONS = Object.freeze([5, 10, 15, 20, 25, 30, 50, 75, 100, 150, 200, 250, 500, 1000]);
const tablePageSizesDialogOpen = ref(false);
const tablePageSizesOpen = ref(false);
const tablePageSizesSearchTerm = ref('');
@@ -650,22 +673,6 @@
}
});
/**
*
*/
function addTablePageSizeFromInput() {
const raw = String(tablePageSizesSearchTerm.value ?? '').trim();
if (!raw) {
return;
}
if (!Array.isArray(tablePageSizesModel.value)) {
tablePageSizesModel.value = [raw];
} else if (!tablePageSizesModel.value.includes(raw)) {
tablePageSizesModel.value = [...tablePageSizesModel.value, raw];
}
tablePageSizesSearchTerm.value = '';
}
/**
*
*/

View File

@@ -15,7 +15,10 @@
<span class="block truncate font-medium text-sm leading-[18px]">{{
t('view.settings.general.general.latest_app_version')
}}</span>
<span v-if="latestAppVersion" class="block truncate text-xs text-muted-foreground" v-text="latestAppVersion"></span>
<span
v-if="latestAppVersion"
class="block truncate text-xs text-muted-foreground"
v-text="latestAppVersion"></span>
<span v-else class="block truncate text-xs text-muted-foreground">{{
t('view.settings.general.general.latest_app_version_refresh')
}}</span>
@@ -53,23 +56,22 @@
<template v-if="!noUpdater">
<SettingsItem :label="t('view.settings.general.vrcx_updater.update_action')">
<ToggleGroup
type="single"
required
variant="outline"
size="sm"
:model-value="autoUpdateVRCX"
@update:model-value="setAutoUpdateVRCX">
<ToggleGroupItem value="Off">{{
t('view.settings.general.vrcx_updater.auto_update_off')
}}</ToggleGroupItem>
<ToggleGroupItem value="Notify">{{
t('view.settings.general.vrcx_updater.auto_update_notify')
}}</ToggleGroupItem>
<ToggleGroupItem value="Auto Download">{{
t('view.settings.general.vrcx_updater.auto_update_download')
}}</ToggleGroupItem>
</ToggleGroup>
<Select :model-value="autoUpdateVRCX" @update:model-value="setAutoUpdateVRCX">
<SelectTrigger size="sm">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="Off">{{
t('view.settings.general.vrcx_updater.auto_update_off')
}}</SelectItem>
<SelectItem value="Notify">{{
t('view.settings.general.vrcx_updater.auto_update_notify')
}}</SelectItem>
<SelectItem value="Auto Download">{{
t('view.settings.general.vrcx_updater.auto_update_download')
}}</SelectItem>
</SelectContent>
</Select>
</SettingsItem>
</template>
<div v-else class="text-sm text-muted-foreground">
@@ -82,9 +84,7 @@
<Switch :model-value="isStartAtWindowsStartup" @update:modelValue="setIsStartAtWindowsStartup" />
</SettingsItem>
<SettingsItem
v-if="!isLinux"
:label="t('view.settings.general.application.minimized')">
<SettingsItem v-if="!isLinux" :label="t('view.settings.general.application.minimized')">
<Switch :model-value="isStartAsMinimizedState" @update:modelValue="setIsStartAsMinimizedState" />
</SettingsItem>
<SettingsItem
@@ -132,7 +132,7 @@
</SettingsGroup>
<SettingsGroup :title="t('view.settings.general.legal_notice.header')">
<div class="flex flex-col gap-2 text-sm text-muted-foreground">
<div class="flex flex-col gap-2 text-sm text-muted-foreground mb-2">
<p class="m-0">
&copy; 2019-2026
<a class="cursor-pointer" @click="openExternalLink('https://github.com/pypy-vrc')">pypy</a> &amp;
@@ -163,7 +163,7 @@
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { useGeneralSettingsStore, useVRCXUpdaterStore } from '@/stores';
import { links } from '@/shared/constants';
import { openExternalLink } from '@/shared/utils';

View File

@@ -2,8 +2,7 @@
<div class="flex flex-col gap-10 py-2">
<!-- VR Core -->
<SettingsGroup :title="t('view.settings.vr.vr_core.header')">
<SettingsItem
:label="t('view.settings.notifications.notifications.steamvr_notifications.steamvr_overlay')">
<SettingsItem :label="t('view.settings.notifications.notifications.steamvr_notifications.steamvr_overlay')">
<Switch
:model-value="openVR"
@update:modelValue="
@@ -12,22 +11,19 @@
" />
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.start_overlay_with')">
<RadioGroup
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.start_overlay_with')">
<Select
:model-value="openVRAlways ? 'true' : 'false'"
:disabled="!openVR"
class="gap-2 flex"
@update:modelValue="handleOpenVRAlwaysRadio">
<div class="flex items-center space-x-2">
<RadioGroupItem id="openVRAlways-false" value="false" />
<label for="openVRAlways-false">{{ 'VRChat' }}</label>
</div>
<div class="flex items-center space-x-2">
<RadioGroupItem id="openVRAlways-true" value="true" />
<label for="openVRAlways-true">{{ 'SteamVR' }}</label>
</div>
</RadioGroup>
<SelectTrigger size="sm">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="false">{{ 'VRChat' }}</SelectItem>
<SelectItem value="true">{{ 'SteamVR' }}</SelectItem>
</SelectContent>
</Select>
</SettingsItem>
<template v-if="!isLinux">
@@ -45,9 +41,7 @@
</template>
<template v-else>
<SettingsItem
:label="
t('view.settings.notifications.notifications.steamvr_notifications.wayvr_notifications')
">
:label="t('view.settings.notifications.notifications.steamvr_notifications.wayvr_notifications')">
<Switch
:model-value="xsNotifications"
@update:modelValue="
@@ -90,8 +84,7 @@
<!-- VR Notifications -->
<SettingsGroup :title="t('view.settings.vr.vr_notifications.header')">
<SettingsItem
:label="t('view.settings.notifications.notifications.desktop_notifications.when_to_display')">
<SettingsItem :label="t('view.settings.notifications.notifications.desktop_notifications.when_to_display')">
<ToggleGroup
type="single"
required
@@ -124,9 +117,7 @@
</SettingsItem>
<SettingsItem
:label="
t('view.settings.notifications.notifications.steamvr_notifications.overlay_notifications')
">
:label="t('view.settings.notifications.notifications.steamvr_notifications.overlay_notifications')">
<Switch
:model-value="overlayNotifications"
:disabled="!openVR"
@@ -137,9 +128,7 @@
</SettingsItem>
<SettingsItem
:label="
t('view.settings.notifications.notifications.steamvr_notifications.notification_position')
">
:label="t('view.settings.notifications.notifications.steamvr_notifications.notification_position')">
<Button
size="sm"
variant="outline"
@@ -152,31 +141,31 @@
</SettingsItem>
<SettingsItem
:label="
t('view.settings.notifications.notifications.steamvr_notifications.notification_opacity')
">
:label="t('view.settings.notifications.notifications.steamvr_notifications.notification_opacity')">
<div class="w-75 max-w-full pt-1">
<Slider v-model="notificationOpacityValue" :min="0" :max="100" />
</div>
</SettingsItem>
<SettingsItem
:label="
t('view.settings.notifications.notifications.steamvr_notifications.notification_timeout')
">
<Button
size="sm"
variant="outline"
:label="t('view.settings.notifications.notifications.steamvr_notifications.notification_timeout')">
<NumberField
:model-value="notificationTimeoutSeconds"
:min="0"
:step="1"
:format-options="{ maximumFractionDigits: 0 }"
:disabled="(!overlayNotifications || !openVR) && !xsNotifications"
@click="promptNotificationTimeout"
>{{
t('view.settings.notifications.notifications.steamvr_notifications.notification_timeout')
}}</Button
>
class="w-32"
@update:modelValue="setNotificationTimeout">
<NumberFieldContent>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldContent>
</NumberField>
</SettingsItem>
<SettingsItem
:label="t('view.settings.notifications.notifications.steamvr_notifications.user_images')">
<SettingsItem :label="t('view.settings.notifications.notifications.steamvr_notifications.user_images')">
<Switch
:model-value="imageNotifications"
@update:modelValue="
@@ -191,7 +180,8 @@
<!-- VR Extras -->
<SettingsGroup :title="t('view.settings.vr.vr_extras.header')">
<SettingsItem :label="t('view.settings.advanced.advanced.video_progress_pie.header')"
<SettingsItem
:label="t('view.settings.advanced.advanced.video_progress_pie.header')"
:description="t('view.settings.advanced.advanced.video_progress_pie.enable_tooltip')">
<Switch
:model-value="progressPie"
@@ -214,10 +204,17 @@
<script setup>
import { computed, ref } from 'vue';
import {
NumberField,
NumberFieldContent,
NumberFieldDecrement,
NumberFieldIncrement,
NumberFieldInput
} from '@/components/ui/number-field';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Slider } from '@/components/ui/slider';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
@@ -250,7 +247,8 @@
xsNotifications,
ovrtHudNotifications,
ovrtWristNotifications,
imageNotifications
imageNotifications,
notificationTimeout
} = storeToRefs(notificationsSettingsStore);
const { notificationOpacity } = storeToRefs(advancedSettingsStore);
@@ -258,10 +256,7 @@
const { openVRAlways } = storeToRefs(wristOverlaySettingsStore);
const { setOpenVRAlways } = wristOverlaySettingsStore;
const {
progressPie,
progressPieFilter
} = storeToRefs(advancedSettingsStore);
const { progressPie, progressPieFilter } = storeToRefs(advancedSettingsStore);
const {
setOverlayToast,
@@ -271,9 +266,11 @@
setOvrtHudNotifications,
setOvrtWristNotifications,
setImageNotifications,
promptNotificationTimeout
setNotificationTimeout
} = notificationsSettingsStore;
const notificationTimeoutSeconds = computed(() => notificationTimeout.value / 1000);
const { setNotificationOpacity } = advancedSettingsStore;
const isNotificationPositionDialogVisible = ref(false);

View File

@@ -27,8 +27,7 @@
" />
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_private_worlds')">
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.hide_private_worlds')">
<Switch
:model-value="hidePrivateFromFeed"
@update:modelValue="
@@ -38,52 +37,49 @@
</SettingsItem>
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button')">
<RadioGroup
<Select
:model-value="overlaybutton ? 'true' : 'false'"
:disabled="!openVR || !overlayWrist"
class="gap-2 flex"
@update:modelValue="handleOverlayButtonRadio">
<div class="flex items-center space-x-2">
<RadioGroupItem id="overlaybutton-false" value="false" />
<label for="overlaybutton-false">{{
<SelectTrigger size="sm">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="false">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button_grip')
}}</label>
</div>
<div class="flex items-center space-x-2">
<RadioGroupItem id="overlaybutton-true" value="true" />
<label for="overlaybutton-true">{{
}}</SelectItem>
<SelectItem value="true">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.overlay_button_menu')
}}</label>
</div>
</RadioGroup>
}}</SelectItem>
</SelectContent>
</Select>
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on')">
<ToggleGroup
type="single"
required
variant="outline"
size="sm"
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on')">
<Select
:model-value="overlayHand"
@update:model-value="
setOverlayHand($event);
saveOpenVROption();
">
<ToggleGroupItem value="1">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_left')
}}</ToggleGroupItem>
<ToggleGroupItem value="2">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_right')
}}</ToggleGroupItem>
<ToggleGroupItem value="0">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_both')
}}</ToggleGroupItem>
</ToggleGroup>
<SelectTrigger size="sm">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_left')
}}</SelectItem>
<SelectItem value="2">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_right')
}}</SelectItem>
<SelectItem value="0">{{
t('view.settings.wrist_overlay.steamvr_wrist_overlay.display_overlay_on_both')
}}</SelectItem>
</SelectContent>
</Select>
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.grey_background')">
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.grey_background')">
<Switch
:model-value="vrBackgroundEnabled"
:disabled="!openVR || !overlayWrist"
@@ -93,8 +89,7 @@
" />
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.minimal_feed_icons')">
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.minimal_feed_icons')">
<Switch
:model-value="minimalFeed"
:disabled="!openVR || !overlayWrist"
@@ -124,8 +119,7 @@
" />
</SettingsItem>
<SettingsItem
:label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_game_uptime')">
<SettingsItem :label="t('view.settings.wrist_overlay.steamvr_wrist_overlay.show_game_uptime')">
<Switch
:model-value="!hideUptimeFromFeed"
:disabled="!openVR || !overlayWrist"
@@ -151,8 +145,7 @@
<script setup>
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n';
@@ -169,7 +162,6 @@
const { openVR } = storeToRefs(notificationsSettingsStore);
const {
overlayWrist,
hidePrivateFromFeed,