-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.ts
113 lines (99 loc) · 3.17 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */
import type { ComputedRef, Ref } from 'vue-demi'
import { computed, ref } from 'vue-demi'
import { useEventListener } from '../useEventListener'
import { usePermission } from '../usePermission'
import { useSupported } from '../useSupported'
import type { ConfigurableNavigator } from '../_configurable'
import { defaultNavigator } from '../_configurable'
export interface UseDevicesListOptions extends ConfigurableNavigator {
onUpdated?: (devices: MediaDeviceInfo[]) => void
/**
* Request for permissions immediately if it's not granted,
* otherwise label and deviceIds could be empty
*
* @default false
*/
requestPermissions?: boolean
/**
* Request for types of media permissions
*
* @default { audio: true, video: true }
*/
constraints?: MediaStreamConstraints
}
export interface UseDevicesListReturn {
/**
* All devices
*/
devices: Ref<MediaDeviceInfo[]>
videoInputs: ComputedRef<MediaDeviceInfo[]>
audioInputs: ComputedRef<MediaDeviceInfo[]>
audioOutputs: ComputedRef<MediaDeviceInfo[]>
permissionGranted: Ref<boolean>
ensurePermissions: () => Promise<boolean>
isSupported: Ref<boolean>
}
/**
* Reactive `enumerateDevices` listing available input/output devices
*
* @see https://vueuse.org/useDevicesList
* @param options
*/
export function useDevicesList(options: UseDevicesListOptions = {}): UseDevicesListReturn {
const {
navigator = defaultNavigator,
requestPermissions = false,
constraints = { audio: true, video: true },
onUpdated,
} = options
const devices = ref([]) as Ref<MediaDeviceInfo[]>
const videoInputs = computed(() => devices.value.filter(i => i.kind === 'videoinput'))
const audioInputs = computed(() => devices.value.filter(i => i.kind === 'audioinput'))
const audioOutputs = computed(() => devices.value.filter(i => i.kind === 'audiooutput'))
const isSupported = useSupported(() => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
const permissionGranted = ref(false)
let stream: MediaStream | null
async function update() {
if (!isSupported.value)
return
devices.value = await navigator!.mediaDevices.enumerateDevices()
onUpdated?.(devices.value)
if (stream) {
stream.getTracks().forEach(t => t.stop())
stream = null
}
}
async function ensurePermissions() {
if (!isSupported.value)
return false
if (permissionGranted.value)
return true
const { state, query } = usePermission('camera', { controls: true })
await query()
if (state.value !== 'granted') {
stream = await navigator!.mediaDevices.getUserMedia(constraints)
update()
permissionGranted.value = true
}
else {
permissionGranted.value = true
}
return permissionGranted.value
}
if (isSupported.value) {
if (requestPermissions)
ensurePermissions()
useEventListener(navigator!.mediaDevices, 'devicechange', update)
update()
}
return {
devices,
ensurePermissions,
permissionGranted,
videoInputs,
audioInputs,
audioOutputs,
isSupported,
}
}