mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-30 07:06:38 +08:00
feat(web): 优化视频格式与虚拟键盘显示
This commit is contained in:
@@ -12,7 +12,7 @@ import { useWebRTC } from '@/composables/useWebRTC'
|
||||
import { useVideoSession } from '@/composables/useVideoSession'
|
||||
import { getUnifiedAudio } from '@/composables/useUnifiedAudio'
|
||||
import { streamApi, hidApi, atxApi, atxConfigApi, authApi } from '@/api'
|
||||
import { CanonicalKey } from '@/types/generated'
|
||||
import { CanonicalKey, HidBackend } from '@/types/generated'
|
||||
import type { HidKeyboardEvent, HidMouseEvent } from '@/types/hid'
|
||||
import { keyboardEventToCanonicalKey, updateModifierMaskForKey } from '@/lib/keyboardMappings'
|
||||
import { toast } from 'vue-sonner'
|
||||
@@ -156,6 +156,12 @@ function syncMouseModeFromConfig() {
|
||||
const virtualKeyboardVisible = ref(false)
|
||||
const virtualKeyboardAttached = ref(true)
|
||||
const statsSheetOpen = ref(false)
|
||||
const virtualKeyboardConsumerEnabled = computed(() => {
|
||||
const hid = configStore.hid
|
||||
if (!hid) return true
|
||||
if (hid.backend !== HidBackend.Otg) return true
|
||||
return hid.otg_functions?.consumer !== false
|
||||
})
|
||||
|
||||
// Change password dialog state
|
||||
const changePasswordDialogOpen = ref(false)
|
||||
@@ -2528,6 +2534,7 @@ onUnmounted(() => {
|
||||
v-model:attached="virtualKeyboardAttached"
|
||||
:caps-lock="keyboardLed.capsLock"
|
||||
:pressed-keys="pressedKeys"
|
||||
:consumer-enabled="virtualKeyboardConsumerEnabled"
|
||||
@key-down="handleVirtualKeyDown"
|
||||
@key-up="handleVirtualKeyUp"
|
||||
/>
|
||||
|
||||
@@ -39,6 +39,7 @@ import type {
|
||||
} from '@/types/generated'
|
||||
import { setLanguage } from '@/i18n'
|
||||
import { useClipboard } from '@/composables/useClipboard'
|
||||
import { getVideoFormatState } from '@/lib/video-format-support'
|
||||
import AppLayout from '@/components/AppLayout.vue'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
@@ -780,6 +781,21 @@ const availableFormats = computed(() => {
|
||||
return selectedDevice.value.formats
|
||||
})
|
||||
|
||||
const availableFormatOptions = computed(() => {
|
||||
return availableFormats.value.map(format => {
|
||||
const state = getVideoFormatState(format.format, 'config', config.value.encoder_backend)
|
||||
return {
|
||||
...format,
|
||||
state,
|
||||
disabled: state === 'unsupported',
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const selectableFormats = computed(() => {
|
||||
return availableFormatOptions.value.filter(format => !format.disabled)
|
||||
})
|
||||
|
||||
const selectedFormat = computed(() => {
|
||||
if (!selectedDevice.value || !config.value.video_format) return null
|
||||
return selectedDevice.value.formats.find(f => f.format === config.value.video_format)
|
||||
@@ -810,17 +826,22 @@ const availableFps = computed(() => {
|
||||
return currentRes ? currentRes.fps : []
|
||||
})
|
||||
|
||||
// Watch for device change to set default format
|
||||
watch(() => config.value.video_device, () => {
|
||||
if (availableFormats.value.length > 0) {
|
||||
const isValid = availableFormats.value.some(f => f.format === config.value.video_format)
|
||||
if (!isValid) {
|
||||
config.value.video_format = availableFormats.value[0]?.format || ''
|
||||
// Keep the selected format aligned with currently selectable formats.
|
||||
watch(
|
||||
selectableFormats,
|
||||
() => {
|
||||
if (selectableFormats.value.length === 0) {
|
||||
config.value.video_format = ''
|
||||
return
|
||||
}
|
||||
} else {
|
||||
config.value.video_format = ''
|
||||
}
|
||||
})
|
||||
|
||||
const isValid = selectableFormats.value.some(f => f.format === config.value.video_format)
|
||||
if (!isValid) {
|
||||
config.value.video_format = selectableFormats.value[0]?.format || ''
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
// Watch for format change to set default resolution
|
||||
watch(() => config.value.video_format, () => {
|
||||
@@ -2091,7 +2112,14 @@ watch(() => route.query.tab, (tab) => {
|
||||
<Label for="video-format">{{ t('settings.videoFormat') }}</Label>
|
||||
<select id="video-format" v-model="config.video_format" class="w-full h-9 px-3 rounded-md border border-input bg-background text-sm" :disabled="!config.video_device">
|
||||
<option value="">{{ t('settings.selectFormat') }}</option>
|
||||
<option v-for="fmt in availableFormats" :key="fmt.format" :value="fmt.format">{{ fmt.format }} - {{ fmt.description }}</option>
|
||||
<option
|
||||
v-for="fmt in availableFormatOptions"
|
||||
:key="fmt.format"
|
||||
:value="fmt.format"
|
||||
:disabled="fmt.disabled"
|
||||
>
|
||||
{{ fmt.format }} - {{ fmt.description }}{{ fmt.disabled ? t('common.notSupportedYet') : '' }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid gap-4 sm:grid-cols-2">
|
||||
|
||||
Reference in New Issue
Block a user