mirror of
https://github.com/vrcx-team/VRCX.git
synced 2026-04-06 00:32:02 +02:00
replace some el-select with Select component
This commit is contained in:
@@ -3,58 +3,73 @@
|
||||
ref="setAvatarStylesDialog"
|
||||
class="x-dialog"
|
||||
:model-value="setAvatarStylesDialog.visible"
|
||||
@close="closeSetAvatarStylesDialog"
|
||||
:title="t('dialog.set_avatar_styles.header')"
|
||||
width="400px"
|
||||
append-to-body>
|
||||
append-to-body
|
||||
@close="closeSetAvatarStylesDialog">
|
||||
<template v-if="setAvatarStylesDialog.visible">
|
||||
<div>
|
||||
<span>{{ t('dialog.set_avatar_styles.primary_style') }}</span>
|
||||
<el-select
|
||||
v-model="setAvatarStylesDialog.primaryStyle"
|
||||
:placeholder="t('dialog.set_avatar_styles.select_style')"
|
||||
size="small"
|
||||
clearable
|
||||
style="display: inline-block">
|
||||
<el-option
|
||||
v-for="(style, index) in setAvatarStylesDialog.availableAvatarStyles"
|
||||
:key="index"
|
||||
:label="style"
|
||||
:value="style"></el-option>
|
||||
</el-select>
|
||||
<Select
|
||||
:model-value="setAvatarStylesDialog.primaryStyle"
|
||||
@update:modelValue="(v) => updateDialog({ primaryStyle: v === SELECT_CLEAR_VALUE ? '' : v })">
|
||||
<SelectTrigger size="sm" style="display: inline-flex">
|
||||
<SelectValue :placeholder="t('dialog.set_avatar_styles.select_style')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="SELECT_CLEAR_VALUE">{{ t('dialog.gallery_select.none') }}</SelectItem>
|
||||
<SelectItem
|
||||
v-for="(style, index) in setAvatarStylesDialog.availableAvatarStyles"
|
||||
:key="index"
|
||||
:value="style">
|
||||
{{ style }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div>
|
||||
<span>{{ t('dialog.set_avatar_styles.secondary_style') }}</span>
|
||||
<el-select
|
||||
v-model="setAvatarStylesDialog.secondaryStyle"
|
||||
:placeholder="t('dialog.set_avatar_styles.select_style')"
|
||||
size="small"
|
||||
clearable
|
||||
style="display: inline-block">
|
||||
<el-option
|
||||
v-for="(style, index) in setAvatarStylesDialog.availableAvatarStyles"
|
||||
:key="index"
|
||||
:label="style"
|
||||
:value="style"></el-option>
|
||||
</el-select>
|
||||
<Select
|
||||
:model-value="setAvatarStylesDialog.secondaryStyle"
|
||||
@update:modelValue="(v) => updateDialog({ secondaryStyle: v === SELECT_CLEAR_VALUE ? '' : v })">
|
||||
<SelectTrigger size="sm" style="display: inline-flex">
|
||||
<SelectValue :placeholder="t('dialog.set_avatar_styles.select_style')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="SELECT_CLEAR_VALUE">{{ t('dialog.gallery_select.none') }}</SelectItem>
|
||||
<SelectItem
|
||||
v-for="(style, index) in setAvatarStylesDialog.availableAvatarStyles"
|
||||
:key="index"
|
||||
:value="style">
|
||||
{{ style }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div style="font-size: 12px; margin-top: 10px">{{ t('dialog.set_world_tags.author_tags') }}<br /></div>
|
||||
|
||||
<el-input
|
||||
v-model="setAvatarStylesDialog.authorTags"
|
||||
:model-value="setAvatarStylesDialog.authorTags"
|
||||
type="textarea"
|
||||
size="small"
|
||||
show-word-limit
|
||||
:autosize="{ minRows: 2, maxRows: 5 }"
|
||||
placeholder=""
|
||||
style="margin-top: 10px"></el-input>
|
||||
style="margin-top: 10px"
|
||||
@update:modelValue="(v) => updateDialog({ authorTags: v })" />
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="closeSetAvatarStylesDialog">{{ t('dialog.set_avatar_styles.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="saveSetAvatarStylesDialog">{{
|
||||
t('dialog.set_avatar_styles.save')
|
||||
}}</el-button>
|
||||
<el-button type="primary" @click="saveSetAvatarStylesDialog">
|
||||
{{ t('dialog.set_avatar_styles.save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -64,13 +79,11 @@
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { watch } from 'vue';
|
||||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
||||
import { arraysMatch } from '../../../shared/utils';
|
||||
import { avatarRequest } from '../../../api';
|
||||
import { useAvatarStore } from '../../../stores';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { applyAvatar } = useAvatarStore();
|
||||
|
||||
const props = defineProps({
|
||||
setAvatarStylesDialog: {
|
||||
type: Object,
|
||||
@@ -80,6 +93,11 @@
|
||||
|
||||
const emit = defineEmits(['update:setAvatarStylesDialog']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { applyAvatar } = useAvatarStore();
|
||||
|
||||
const SELECT_CLEAR_VALUE = '__clear__';
|
||||
|
||||
watch(
|
||||
() => props.setAvatarStylesDialog.visible,
|
||||
(newVal) => {
|
||||
@@ -89,23 +107,34 @@
|
||||
}
|
||||
);
|
||||
|
||||
function updateDialog(patch) {
|
||||
emit('update:setAvatarStylesDialog', {
|
||||
...props.setAvatarStylesDialog,
|
||||
...patch
|
||||
});
|
||||
}
|
||||
|
||||
async function getAvatarStyles() {
|
||||
const ref = await avatarRequest.getAvailableAvatarStyles();
|
||||
const styles = [];
|
||||
const stylesMap = new Map();
|
||||
for (const style of ref.json) {
|
||||
styles.push(style.styleName);
|
||||
stylesMap.set(style.styleName, style.id);
|
||||
try {
|
||||
const ref = await avatarRequest.getAvailableAvatarStyles();
|
||||
const styles = [];
|
||||
const stylesMap = new Map();
|
||||
for (const style of ref.json) {
|
||||
styles.push(style.styleName);
|
||||
stylesMap.set(style.styleName, style.id);
|
||||
}
|
||||
|
||||
updateDialog({
|
||||
availableAvatarStyles: styles,
|
||||
availableAvatarStylesMap: stylesMap
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error loading avatar styles:', error);
|
||||
}
|
||||
props.setAvatarStylesDialog.availableAvatarStyles = styles;
|
||||
props.setAvatarStylesDialog.availableAvatarStylesMap = stylesMap;
|
||||
}
|
||||
|
||||
function closeSetAvatarStylesDialog() {
|
||||
emit('update:setAvatarStylesDialog', {
|
||||
...props.setAvatarStylesDialog,
|
||||
visible: false
|
||||
});
|
||||
updateDialog({ visible: false });
|
||||
}
|
||||
|
||||
function saveSetAvatarStylesDialog() {
|
||||
@@ -114,18 +143,19 @@
|
||||
const secondaryStyleId =
|
||||
props.setAvatarStylesDialog.availableAvatarStylesMap.get(props.setAvatarStylesDialog.secondaryStyle) || '';
|
||||
|
||||
let tags = [];
|
||||
const tags = [];
|
||||
for (const tag of props.setAvatarStylesDialog.initialTags) {
|
||||
if (!tag.startsWith('author_tag_')) {
|
||||
tags.push(tag);
|
||||
}
|
||||
}
|
||||
|
||||
const authorTagsArray = props.setAvatarStylesDialog.authorTags.split(',');
|
||||
for (const tag of authorTagsArray) {
|
||||
if (!tag.trim()) {
|
||||
continue;
|
||||
}
|
||||
let tagName = `author_tag_${tag}`;
|
||||
const tagName = `author_tag_${tag}`;
|
||||
if (!tags.includes(tagName)) {
|
||||
tags.push(tagName);
|
||||
}
|
||||
@@ -146,6 +176,7 @@
|
||||
secondaryStyle: secondaryStyleId,
|
||||
tags
|
||||
};
|
||||
|
||||
avatarRequest
|
||||
.saveAvatar(params)
|
||||
.then((args) => {
|
||||
|
||||
@@ -623,25 +623,19 @@
|
||||
<br />
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div>
|
||||
<el-select
|
||||
v-model="selectedAuditLogTypes"
|
||||
multiple
|
||||
collapse-tags
|
||||
:placeholder="t('dialog.group_member_moderation.filter_type')"
|
||||
style="margin: 10px 0; width: 250px">
|
||||
<el-option-group :label="t('dialog.group_member_moderation.select_type')">
|
||||
<el-option
|
||||
<Select v-model="selectedAuditLogTypes" multiple>
|
||||
<SelectTrigger style="margin: 10px 0; width: 250px">
|
||||
<SelectValue :placeholder="t('dialog.group_member_moderation.filter_type')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem
|
||||
v-for="type in groupMemberModeration.auditLogTypes"
|
||||
:key="type"
|
||||
class="x-friend-item"
|
||||
:label="getAuditLogTypeName(type)"
|
||||
:value="type">
|
||||
<div class="detail">
|
||||
<span class="name" v-text="getAuditLogTypeName(type)"></span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
{{ getAuditLogTypeName(type) }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<el-input
|
||||
v-model="groupLogsModerationTable.filters[0].value"
|
||||
:placeholder="t('dialog.group_member_moderation.search_placeholder')"
|
||||
@@ -781,27 +775,16 @@
|
||||
<br />
|
||||
<span class="name">{{ t('dialog.group_member_moderation.selected_roles') }}</span>
|
||||
<br />
|
||||
<el-select
|
||||
v-model="selectedRoles"
|
||||
clearable
|
||||
multiple
|
||||
:placeholder="t('dialog.group_member_moderation.choose_roles_placeholder')"
|
||||
filterable
|
||||
style="margin-top: 5px">
|
||||
<el-option-group :label="t('dialog.group_member_moderation.roles')">
|
||||
<el-option
|
||||
v-for="role in groupMemberModeration.groupRef.roles"
|
||||
:key="role.id"
|
||||
class="x-friend-item"
|
||||
:label="role.name"
|
||||
:value="role.id"
|
||||
style="height: auto">
|
||||
<div class="detail">
|
||||
<span class="name" v-text="role.name"></span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
<Select v-model="selectedRoles" multiple>
|
||||
<SelectTrigger style="margin-top: 5px">
|
||||
<SelectValue :placeholder="t('dialog.group_member_moderation.choose_roles_placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="role in groupMemberModeration.groupRef.roles" :key="role.id" :value="role.id">
|
||||
{{ role.name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<br />
|
||||
<br />
|
||||
<span class="name">{{ t('dialog.group_member_moderation.actions') }}</span>
|
||||
@@ -881,6 +864,7 @@
|
||||
import { toast } from 'vue-sonner';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
||||
import { debounce, formatDateFilter, hasGroupPermission, userImage, userImageFull } from '../../../shared/utils';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../../ui/dropdown-menu';
|
||||
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
|
||||
|
||||
@@ -17,20 +17,33 @@
|
||||
<br />
|
||||
<span>{{ t('dialog.vrcx_updater.ready_for_update') }}</span>
|
||||
</div>
|
||||
<el-select
|
||||
v-model="branch"
|
||||
style="display: inline-block; width: 150px; margin-right: 15px"
|
||||
@change="loadBranchVersions">
|
||||
<el-option v-for="b in branches" :key="b.name" :label="b.name" :value="b.name"> </el-option>
|
||||
</el-select>
|
||||
<el-select v-model="VRCXUpdateDialog.release" style="display: inline-block; width: 150px">
|
||||
<el-option
|
||||
v-for="item in VRCXUpdateDialog.releases"
|
||||
:key="item.name"
|
||||
:label="item.tag_name"
|
||||
:value="item.name">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<Select
|
||||
:model-value="branch"
|
||||
@update:modelValue="
|
||||
(v) => {
|
||||
branch = v;
|
||||
loadBranchVersions();
|
||||
}
|
||||
">
|
||||
<SelectTrigger style="display: inline-flex; width: 150px; margin-right: 15px">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="b in branches" :key="b.name" :value="b.name">{{ b.name }}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
:model-value="VRCXUpdateDialog.release"
|
||||
@update:modelValue="(v) => (VRCXUpdateDialog.release = v)">
|
||||
<SelectTrigger style="display: inline-flex; width: 150px">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="item in VRCXUpdateDialog.releases" :key="item.name" :value="item.name">
|
||||
{{ item.tag_name }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div
|
||||
v-if="!VRCXUpdateDialog.updatePending && VRCXUpdateDialog.release === appVersion"
|
||||
style="margin-top: 15px">
|
||||
@@ -62,6 +75,7 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
|
||||
import { branches } from '../../shared/constants';
|
||||
import { getNextDialogIndex } from '../../shared/utils/base/ui';
|
||||
import { useVRCXUpdaterStore } from '../../stores';
|
||||
|
||||
47
src/components/ui/tags-input/TagsInput.vue
Normal file
47
src/components/ui/tags-input/TagsInput.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
import { TagsInputRoot, useForwardPropsEmits } from 'reka-ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: [Array, null], required: false },
|
||||
defaultValue: { type: Array, required: false },
|
||||
addOnPaste: { type: Boolean, required: false },
|
||||
addOnTab: { type: Boolean, required: false },
|
||||
addOnBlur: { type: Boolean, required: false },
|
||||
duplicate: { type: Boolean, required: false },
|
||||
disabled: { type: Boolean, required: false },
|
||||
delimiter: { type: null, required: false },
|
||||
dir: { type: String, required: false },
|
||||
max: { type: Number, required: false },
|
||||
id: { type: String, required: false },
|
||||
convertValue: { type: Function, required: false },
|
||||
displayValue: { type: Function, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
name: { type: String, required: false },
|
||||
required: { type: Boolean, required: false },
|
||||
class: { type: null, required: false }
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue', 'invalid', 'addTag', 'removeTag']);
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TagsInputRoot
|
||||
v-slot="slotProps"
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-wrap gap-2 items-center rounded-md border border-input bg-background px-2 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none',
|
||||
'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]',
|
||||
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
||||
props.class
|
||||
)
|
||||
">
|
||||
<slot v-bind="slotProps" />
|
||||
</TagsInputRoot>
|
||||
</template>
|
||||
24
src/components/ui/tags-input/TagsInputInput.vue
Normal file
24
src/components/ui/tags-input/TagsInputInput.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
import { TagsInputInput, useForwardProps } from 'reka-ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: { type: String, required: false },
|
||||
autoFocus: { type: Boolean, required: false },
|
||||
maxLength: { type: Number, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false }
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TagsInputInput
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('text-sm min-h-5 focus:outline-none flex-1 bg-transparent px-1', props.class)" />
|
||||
</template>
|
||||
30
src/components/ui/tags-input/TagsInputItem.vue
Normal file
30
src/components/ui/tags-input/TagsInputItem.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
import { TagsInputItem, useForwardProps } from 'reka-ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
|
||||
const props = defineProps({
|
||||
value: { type: null, required: true },
|
||||
disabled: { type: Boolean, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false }
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TagsInputItem
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn(
|
||||
'flex h-5 items-center rounded-md bg-secondary data-[state=active]:ring-ring data-[state=active]:ring-2 data-[state=active]:ring-offset-2 ring-offset-background',
|
||||
props.class
|
||||
)
|
||||
">
|
||||
<slot />
|
||||
</TagsInputItem>
|
||||
</template>
|
||||
24
src/components/ui/tags-input/TagsInputItemDelete.vue
Normal file
24
src/components/ui/tags-input/TagsInputItemDelete.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script setup>
|
||||
import { TagsInputItemDelete, useForwardProps } from 'reka-ui';
|
||||
import { X } from 'lucide-vue-next';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false }
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TagsInputItemDelete v-bind="forwardedProps" :class="cn('flex rounded bg-transparent mr-1', props.class)">
|
||||
<slot>
|
||||
<X class="w-4 h-4" />
|
||||
</slot>
|
||||
</TagsInputItemDelete>
|
||||
</template>
|
||||
19
src/components/ui/tags-input/TagsInputItemText.vue
Normal file
19
src/components/ui/tags-input/TagsInputItemText.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
import { TagsInputItemText, useForwardProps } from 'reka-ui';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { reactiveOmit } from '@vueuse/core';
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false }
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, 'class');
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TagsInputItemText v-bind="forwardedProps" :class="cn('py-0.5 px-2 text-sm rounded bg-transparent', props.class)" />
|
||||
</template>
|
||||
5
src/components/ui/tags-input/index.js
Normal file
5
src/components/ui/tags-input/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export { default as TagsInput } from './TagsInput.vue';
|
||||
export { default as TagsInputInput } from './TagsInputInput.vue';
|
||||
export { default as TagsInputItem } from './TagsInputItem.vue';
|
||||
export { default as TagsInputItemDelete } from './TagsInputItemDelete.vue';
|
||||
export { default as TagsInputItemText } from './TagsInputItemText.vue';
|
||||
@@ -62,7 +62,7 @@ const languageNames = import.meta.glob('./*.json', {
|
||||
});
|
||||
|
||||
function getLanguageName(code) {
|
||||
return languageNames[`./${code}.json`];
|
||||
return String(languageNames[`./${code}.json`] ?? code);
|
||||
}
|
||||
|
||||
export * from './locales';
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
<template>
|
||||
<div class="photon-event-table">
|
||||
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap">
|
||||
<el-select
|
||||
v-model="photonEventTableTypeFilter"
|
||||
<Select
|
||||
:model-value="photonEventTableTypeFilter"
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
style="width: 220px"
|
||||
:placeholder="t('view.player_list.photon.filter_placeholder')"
|
||||
@change="photonEventTableFilterChange">
|
||||
<el-option
|
||||
v-for="type in photonEventTableTypeFilterList"
|
||||
:key="type"
|
||||
:label="type"
|
||||
:value="type"></el-option>
|
||||
</el-select>
|
||||
@update:modelValue="
|
||||
(v) => {
|
||||
photonEventTableTypeFilter = v;
|
||||
photonEventTableFilterChange();
|
||||
}
|
||||
">
|
||||
<SelectTrigger style="width: 220px">
|
||||
<SelectValue :placeholder="t('view.player_list.photon.filter_placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="type in photonEventTableTypeFilterList" :key="type" :value="type">{{
|
||||
type
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<el-input
|
||||
v-model="photonEventTableFilter"
|
||||
:placeholder="t('view.player_list.photon.search_placeholder')"
|
||||
@@ -397,6 +401,7 @@
|
||||
useVrcxStore,
|
||||
useWorldStore
|
||||
} from '../../../stores';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../components/ui/select';
|
||||
import { formatDateFilter, statusClass } from '../../../shared/utils';
|
||||
import { photonEventTableTypeFilterList } from '../../../shared/constants/photon';
|
||||
|
||||
|
||||
@@ -40,23 +40,24 @@
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<el-select
|
||||
<Select
|
||||
:model-value="photonEventTableTypeOverlayFilter"
|
||||
multiple
|
||||
clearable
|
||||
collapse-tags
|
||||
style="flex: 1"
|
||||
placeholder="Filter"
|
||||
@change="
|
||||
setPhotonEventTableTypeOverlayFilter($event);
|
||||
photonEventTableFilterChange();
|
||||
@update:modelValue="
|
||||
(v) => {
|
||||
setPhotonEventTableTypeOverlayFilter(v);
|
||||
photonEventTableFilterChange();
|
||||
}
|
||||
">
|
||||
<el-option
|
||||
v-for="type in photonEventTableTypeFilterList"
|
||||
:key="type"
|
||||
:label="type"
|
||||
:value="type"></el-option>
|
||||
</el-select>
|
||||
<SelectTrigger style="flex: 1">
|
||||
<SelectValue placeholder="Filter" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="type in photonEventTableTypeFilterList" :key="type" :value="type">{{
|
||||
type
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<br />
|
||||
<span class="sub-header">{{ t('view.settings.advanced.photon.timeout_hud.header') }}</span>
|
||||
@@ -103,9 +104,10 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../components/ui/select';
|
||||
import { ToggleGroup, ToggleGroupItem } from '../../../components/ui/toggle-group';
|
||||
import { useNotificationsSettingsStore, usePhotonStore } from '../../../stores';
|
||||
import { photonEventTableTypeFilterList } from '../../../shared/constants/photon';
|
||||
import { ToggleGroup, ToggleGroupItem } from '../../../components/ui/toggle-group';
|
||||
|
||||
import SimpleSwitch from './SimpleSwitch.vue';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.language') }}</span>
|
||||
<Select :model-value="appLanguage" @update:modelValue="changeAppLanguage">
|
||||
<SelectTrigger size="sm">
|
||||
<SelectValue :placeholder="getLanguageName(appLanguage)" />
|
||||
<SelectValue :placeholder="appLanguageDisplayName" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
@@ -95,17 +95,50 @@
|
||||
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.appearance.appearance.table_page_sizes') }}</span>
|
||||
<el-select
|
||||
v-model="tablePageSizesModel"
|
||||
multiple
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
collapse-tags
|
||||
:max-collapse-tags="3"
|
||||
style="width: 300px">
|
||||
<el-option v-for="size in tablePageSizes" :key="size" :label="String(size)" :value="String(size)" />
|
||||
</el-select>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<ListboxItemIndicator class="ml-auto inline-flex items-center justify-center">
|
||||
<CheckIcon />
|
||||
</ListboxItemIndicator>
|
||||
</ListboxItem>
|
||||
</ListboxContent>
|
||||
</PopoverContent>
|
||||
</ListboxRoot>
|
||||
</Popover>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.appearance.compact_table_mode')"
|
||||
@@ -141,120 +174,100 @@
|
||||
<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>
|
||||
<Select :model-value="sidebarSortMethod1" @update:modelValue="setSidebarSortMethod1">
|
||||
<SelectTrigger style="width: 170px" size="sm">
|
||||
<SelectValue :placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="Sort Alphabetically">{{
|
||||
t('view.settings.appearance.side_panel.sorting.alphabetical')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Status">{{
|
||||
t('view.settings.appearance.side_panel.sorting.status')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort Private to Bottom">{{
|
||||
t('view.settings.appearance.side_panel.sorting.private_to_bottom')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Active">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_active')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Seen">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_seen')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Time in Instance">{{
|
||||
t('view.settings.appearance.side_panel.sorting.time_in_instance')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Location">{{
|
||||
t('view.settings.appearance.side_panel.sorting.location')
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<el-icon style="padding: 5px"><ArrowRight /></el-icon>
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="(v) => setSidebarSortMethod2(v === SELECT_CLEAR_VALUE ? '' : v)">
|
||||
<SelectTrigger style="width: 170px" size="sm">
|
||||
<SelectValue :placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="SELECT_CLEAR_VALUE">{{ t('dialog.gallery_select.none') }}</SelectItem>
|
||||
<SelectItem value="Sort Alphabetically">{{
|
||||
t('view.settings.appearance.side_panel.sorting.alphabetical')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Status">{{
|
||||
t('view.settings.appearance.side_panel.sorting.status')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort Private to Bottom">{{
|
||||
t('view.settings.appearance.side_panel.sorting.private_to_bottom')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Active">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_active')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Seen">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_seen')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Time in Instance">{{
|
||||
t('view.settings.appearance.side_panel.sorting.time_in_instance')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Location">{{
|
||||
t('view.settings.appearance.side_panel.sorting.location')
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<el-icon style="padding: 5px"><ArrowRight /></el-icon>
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="(v) => setSidebarSortMethod3(v === SELECT_CLEAR_VALUE ? '' : v)">
|
||||
<SelectTrigger style="width: 170px" size="sm">
|
||||
<SelectValue :placeholder="t('view.settings.appearance.side_panel.sorting.placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="SELECT_CLEAR_VALUE">{{ t('dialog.gallery_select.none') }}</SelectItem>
|
||||
<SelectItem value="Sort Alphabetically">{{
|
||||
t('view.settings.appearance.side_panel.sorting.alphabetical')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Status">{{
|
||||
t('view.settings.appearance.side_panel.sorting.status')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort Private to Bottom">{{
|
||||
t('view.settings.appearance.side_panel.sorting.private_to_bottom')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Active">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_active')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Last Seen">{{
|
||||
t('view.settings.appearance.side_panel.sorting.last_seen')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Time in Instance">{{
|
||||
t('view.settings.appearance.side_panel.sorting.time_in_instance')
|
||||
}}</SelectItem>
|
||||
<SelectItem value="Sort by Location">{{
|
||||
t('view.settings.appearance.side_panel.sorting.location')
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<simple-switch
|
||||
:label="t('view.settings.appearance.side_panel.group_by_instance')"
|
||||
@@ -372,9 +385,20 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ListboxContent, ListboxFilter, ListboxItem, ListboxItemIndicator, ListboxRoot, useFilter } from 'reka-ui';
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { computed, onBeforeUnmount, ref } from 'vue';
|
||||
import {
|
||||
TagsInput,
|
||||
TagsInputInput,
|
||||
TagsInputItem,
|
||||
TagsInputItemDelete,
|
||||
TagsInputItemText
|
||||
} from '@/components/ui/tags-input';
|
||||
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
||||
import { ArrowRight, Notebook } from '@element-plus/icons-vue';
|
||||
import { CheckIcon, ChevronDown } from 'lucide-vue-next';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { toast } from 'vue-sonner';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -417,6 +441,8 @@
|
||||
compactTableMode
|
||||
} = storeToRefs(appearanceSettingsStore);
|
||||
|
||||
const appLanguageDisplayName = computed(() => getLanguageName(String(appLanguage.value)));
|
||||
|
||||
const { saveSortFavoritesOption } = useFavoriteStore();
|
||||
|
||||
const {
|
||||
@@ -468,6 +494,47 @@
|
||||
}
|
||||
});
|
||||
|
||||
const SELECT_CLEAR_VALUE = '__clear__';
|
||||
|
||||
const TABLE_PAGE_SIZE_SUGGESTIONS = Object.freeze([5, 10, 15, 20, 25, 30, 50, 75, 100, 150, 200, 250, 500, 1000]);
|
||||
|
||||
const tablePageSizesOpen = ref(false);
|
||||
const tablePageSizesSearchTerm = ref('');
|
||||
|
||||
const { contains } = useFilter({ sensitivity: 'base' });
|
||||
|
||||
const tablePageSizeOptions = computed(() => {
|
||||
const current = Array.isArray(tablePageSizes.value) ? tablePageSizes.value : [];
|
||||
const merged = new Set([...TABLE_PAGE_SIZE_SUGGESTIONS, ...current].map((v) => String(v)));
|
||||
return Array.from(merged).sort((a, b) => Number(a) - Number(b));
|
||||
});
|
||||
|
||||
const filteredTablePageSizeOptions = computed(() => {
|
||||
if (tablePageSizesSearchTerm.value === '') {
|
||||
return tablePageSizeOptions.value;
|
||||
}
|
||||
return tablePageSizeOptions.value.filter((option) => contains(option, tablePageSizesSearchTerm.value));
|
||||
});
|
||||
|
||||
watch(tablePageSizesSearchTerm, (value) => {
|
||||
if (value) {
|
||||
tablePageSizesOpen.value = true;
|
||||
}
|
||||
});
|
||||
|
||||
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 = '';
|
||||
}
|
||||
|
||||
async function initGetZoomLevel() {
|
||||
const handleWheel = (event) => {
|
||||
if (event.ctrlKey) {
|
||||
|
||||
@@ -112,26 +112,19 @@
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.favorites.header') }}</span>
|
||||
<br />
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="setLocalFavoriteFriendsGroups">
|
||||
<SelectTrigger style="margin-top: 8px">
|
||||
<SelectValue :placeholder="t('view.settings.general.favorites.group_placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="group in favoriteFriendGroups" :key="group.key" :value="group.key">
|
||||
{{ group.displayName }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="options-container">
|
||||
<span class="header">{{ t('view.settings.general.logging.header') }}</span>
|
||||
@@ -157,72 +150,70 @@
|
||||
@change="setAutoStateChangeEnabled" />
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.alone_status') }}</span>
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="setAutoStateChangeAloneStatus">
|
||||
<SelectTrigger style="margin-top: 8px" size="sm">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="join me">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="active">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="ask me">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="busy">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.company_status') }}</span>
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="setAutoStateChangeCompanyStatus">
|
||||
<SelectTrigger style="margin-top: 8px" size="sm">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="join me">
|
||||
<i class="x-user-status joinme"></i> {{ t('dialog.user.status.join_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="active">
|
||||
<i class="x-user-status online"></i> {{ t('dialog.user.status.online') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="ask me">
|
||||
<i class="x-user-status askme"></i> {{ t('dialog.user.status.ask_me') }}
|
||||
</SelectItem>
|
||||
<SelectItem value="busy">
|
||||
<i class="x-user-status busy"></i> {{ t('dialog.user.status.busy') }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.allowed_instance_types') }}</span>
|
||||
<el-select
|
||||
<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>
|
||||
@update:modelValue="setAutoStateChangeInstanceTypes">
|
||||
<SelectTrigger style="margin-top: 8px" size="sm">
|
||||
<SelectValue :placeholder="t('view.settings.general.automation.instance_type_placeholder')" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="instanceType in instanceTypes" :key="instanceType" :value="instanceType">
|
||||
{{ instanceType }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="options-container-item">
|
||||
<span class="name">{{ t('view.settings.general.automation.alone_condition') }}</span>
|
||||
@@ -303,12 +294,12 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useFavoriteStore, useGeneralSettingsStore, useVRCXUpdaterStore, useVrStore } from '../../../../stores';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../../components/ui/select';
|
||||
import { useFavoriteStore, useGeneralSettingsStore, useVRCXUpdaterStore } from '../../../../stores';
|
||||
import { ToggleGroup, ToggleGroupItem } from '../../../../components/ui/toggle-group';
|
||||
import { links } from '../../../../shared/constants';
|
||||
import { openExternalLink } from '../../../../shared/utils';
|
||||
|
||||
import { ToggleGroup, ToggleGroupItem } from '../../../../components/ui/toggle-group';
|
||||
|
||||
import SimpleSwitch from '../SimpleSwitch.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
@@ -317,8 +308,6 @@
|
||||
const vrcxUpdaterStore = useVRCXUpdaterStore();
|
||||
const favoriteStore = useFavoriteStore();
|
||||
|
||||
const { saveOpenVROption } = useVrStore();
|
||||
|
||||
const {
|
||||
isStartAtWindowsStartup,
|
||||
isStartAsMinimizedState,
|
||||
|
||||
Reference in New Issue
Block a user