Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(all)!: isSupported becomes Ref<boolean> instead of boolean for SSR compatibility #1800

Merged
merged 10 commits into from Jul 10, 2022
1 change: 1 addition & 0 deletions packages/core/index.ts
Expand Up @@ -100,6 +100,7 @@ export * from './useStepper'
export * from './useStorage'
export * from './useStorageAsync'
export * from './useStyleTag'
export * from './useSupported'
export * from './useSwipe'
export * from './useTemplateRefsList'
export * from './useTextSelection'
Expand Down
5 changes: 3 additions & 2 deletions packages/core/useBattery/index.ts
Expand Up @@ -2,6 +2,7 @@

import { ref } from 'vue-demi'
import { useEventListener } from '../useEventListener'
import { useSupported } from '../useSupported'
import type { ConfigurableNavigator } from '../_configurable'
import { defaultNavigator } from '../_configurable'

Expand All @@ -25,7 +26,7 @@ type NavigatorWithBattery = Navigator & {
export function useBattery({ navigator = defaultNavigator }: ConfigurableNavigator = {}) {
const events = ['chargingchange', 'chargingtimechange', 'dischargingtimechange', 'levelchange']

const isSupported = navigator && 'getBattery' in navigator
const isSupported = useSupported(() => navigator && 'getBattery' in navigator)

const charging = ref(false)
const chargingTime = ref(0)
Expand All @@ -41,7 +42,7 @@ export function useBattery({ navigator = defaultNavigator }: ConfigurableNavigat
level.value = this.level
}

if (isSupported) {
if (isSupported.value) {
(navigator as NavigatorWithBattery)
.getBattery()
.then((_battery) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/core/useBluetooth/index.ts
Expand Up @@ -3,6 +3,7 @@ import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared'
import type { ConfigurableNavigator } from '../_configurable'

import { defaultNavigator } from '../_configurable'
import { useSupported } from '../useSupported'

export interface UseBluetoothRequestDeviceOptions {
/**
Expand Down Expand Up @@ -51,7 +52,7 @@ export function useBluetooth(options?: UseBluetoothOptions) {
navigator = defaultNavigator,
} = options || {}

const isSupported = navigator && 'bluetooth' in navigator
const isSupported = useSupported(() => navigator && 'bluetooth' in navigator)

const device = ref<undefined | BluetoothDevice>(undefined)

Expand All @@ -63,7 +64,7 @@ export function useBluetooth(options?: UseBluetoothOptions) {

async function requestDevice(): Promise<void> {
// This is the function can only be called if Bluetooth API is supported:
if (!isSupported)
if (!isSupported.value)
return

// Reset any errors we currently have:
Expand Down
5 changes: 3 additions & 2 deletions packages/core/useBroadcastChannel/index.ts
Expand Up @@ -2,6 +2,7 @@ import { ref } from 'vue-demi'
import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared'
import type { ConfigurableWindow } from '../_configurable'
import { defaultWindow } from '../_configurable'
import { useSupported } from '../useSupported'

export interface UseBroadcastChannelOptions extends ConfigurableWindow {
/**
Expand All @@ -24,7 +25,7 @@ export const useBroadcastChannel = (options: UseBroadcastChannelOptions) => {
window = defaultWindow,
} = options

const isSupported = window && 'BroadcastChannel' in window
const isSupported = useSupported(() => window && 'BroadcastChannel' in window)
const isClosed = ref(false)

const channel = ref<BroadcastChannel | undefined>()
Expand All @@ -42,7 +43,7 @@ export const useBroadcastChannel = (options: UseBroadcastChannelOptions) => {
isClosed.value = true
}

if (isSupported) {
if (isSupported.value) {
tryOnMounted(() => {
error.value = null
channel.value = new BroadcastChannel(name)
Expand Down
11 changes: 6 additions & 5 deletions packages/core/useClipboard/index.ts
Expand Up @@ -2,10 +2,11 @@

import type { MaybeComputedRef } from '@vueuse/shared'
import { resolveUnref, useTimeoutFn } from '@vueuse/shared'
import type { ComputedRef } from 'vue-demi'
import type { ComputedRef, Ref } from 'vue-demi'
import { ref } from 'vue-demi'
import type { WindowEventName } from '../useEventListener'
import { useEventListener } from '../useEventListener'
import { useSupported } from '../useSupported'
import type { ConfigurableNavigator } from '../_configurable'
import { defaultNavigator } from '../_configurable'

Expand All @@ -31,7 +32,7 @@ export interface ClipboardOptions<Source> extends ConfigurableNavigator {
}

export interface ClipboardReturn<Optional> {
isSupported: boolean
isSupported: Ref<boolean>
text: ComputedRef<string>
copied: ComputedRef<boolean>
copy: Optional extends true ? (text?: string) => Promise<void> : (text: string) => Promise<void>
Expand All @@ -54,7 +55,7 @@ export function useClipboard(options: ClipboardOptions<MaybeComputedRef<string>
} = options

const events = ['copy', 'cut']
const isSupported = Boolean(navigator && 'clipboard' in navigator)
const isSupported = useSupported(() => navigator && 'clipboard' in navigator)
const text = ref('')
const copied = ref(false)

Expand All @@ -66,13 +67,13 @@ export function useClipboard(options: ClipboardOptions<MaybeComputedRef<string>
})
}

if (isSupported && read) {
if (isSupported.value && read) {
for (const event of events)
useEventListener(event as WindowEventName, updateText)
}

async function copy(value = resolveUnref(source)) {
if (isSupported && value != null) {
if (isSupported.value && value != null) {
await navigator!.clipboard.writeText(value)
text.value = value
copied.value = true
Expand Down
5 changes: 3 additions & 2 deletions packages/core/useDeviceOrientation/index.ts
Expand Up @@ -3,6 +3,7 @@
import type { Ref } from 'vue-demi'
import { ref } from 'vue-demi'
import { useEventListener } from '../useEventListener'
import { useSupported } from '../useSupported'
import type { ConfigurableWindow } from '../_configurable'
import { defaultWindow } from '../_configurable'

Expand All @@ -14,14 +15,14 @@ import { defaultWindow } from '../_configurable'
*/
export function useDeviceOrientation(options: ConfigurableWindow = {}) {
const { window = defaultWindow } = options
const isSupported = Boolean(window && 'DeviceOrientationEvent' in window)
const isSupported = useSupported(() => window && 'DeviceOrientationEvent' in window)

const isAbsolute = ref(false)
const alpha: Ref<number | null> = ref(null)
const beta: Ref<number | null> = ref(null)
const gamma: Ref<number | null> = ref(null)

if (window && isSupported) {
if (window && isSupported.value) {
useEventListener(window, 'deviceorientation', (event) => {
isAbsolute.value = event.absolute
alpha.value = event.alpha
Expand Down
23 changes: 10 additions & 13 deletions packages/core/useDevicesList/index.ts
Expand Up @@ -4,6 +4,7 @@ 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'

Expand Down Expand Up @@ -34,7 +35,7 @@ export interface UseDevicesListReturn {
audioOutputs: ComputedRef<MediaDeviceInfo[]>
permissionGranted: Ref<boolean>
ensurePermissions: () => Promise<boolean>
isSupported: boolean
isSupported: Ref<boolean>
}

/**
Expand All @@ -55,19 +56,19 @@ export function useDevicesList(options: UseDevicesListOptions = {}): UseDevicesL
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'))
let isSupported = false
const isSupported = useSupported(() => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
const permissionGranted = ref(false)

async function update() {
if (!isSupported)
if (!isSupported.value)
return

devices.value = await navigator!.mediaDevices.enumerateDevices()
onUpdated?.(devices.value)
}

async function ensurePermissions() {
if (!isSupported)
if (!isSupported.value)
return false

if (permissionGranted.value)
Expand All @@ -88,16 +89,12 @@ export function useDevicesList(options: UseDevicesListOptions = {}): UseDevicesL
return permissionGranted.value
}

if (navigator) {
isSupported = Boolean(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
if (isSupported.value) {
if (requestPermissions)
ensurePermissions()

if (isSupported) {
if (requestPermissions)
ensurePermissions()

useEventListener(navigator.mediaDevices, 'devicechange', update)
update()
}
useEventListener(navigator!.mediaDevices, 'devicechange', update)
update()
}

return {
Expand Down
5 changes: 3 additions & 2 deletions packages/core/useDisplayMedia/index.ts
@@ -1,6 +1,7 @@
import type { MaybeRef } from '@vueuse/shared'
import type { Ref } from 'vue-demi'
import { ref, shallowRef, watch } from 'vue-demi'
import { useSupported } from '../useSupported'
import type { ConfigurableNavigator } from '../_configurable'
import { defaultNavigator } from '../_configurable'

Expand Down Expand Up @@ -32,14 +33,14 @@ export function useDisplayMedia(options: UseDisplayMediaOptions = {}) {
const video = options.video
const audio = options.audio
const { navigator = defaultNavigator } = options
const isSupported = Boolean(navigator?.mediaDevices?.getDisplayMedia)
const isSupported = useSupported(() => navigator?.mediaDevices?.getDisplayMedia)

const constraint: DisplayMediaStreamConstraints = { audio, video }

const stream: Ref<MediaStream | undefined> = shallowRef()

async function _start() {
if (!isSupported || stream.value)
if (!isSupported.value || stream.value)
return
stream.value = await navigator!.mediaDevices.getDisplayMedia(constraint)
return stream.value
Expand Down
7 changes: 4 additions & 3 deletions packages/core/useEyeDropper/demo.vue
Expand Up @@ -8,13 +8,14 @@ const { isSupported, open, sRGBHex } = useEyeDropper()
<template v-if="isSupported">
<div>isSupported: {{ isSupported }}</div>
<div>sRGBHex: <span :style="{ color: sRGBHex }">{{ sRGBHex }}</span></div>
</template>
<div>
<button
:disabled="!isSupported"
@click="() => open()"
>
{{ isSupported ? 'Open Eye Dropper' : 'Not Supported by Your Browser' }}
Open Eye Dropper
</button>
</template>
<div v-else>
<span>Not Supported by Your Browser</span>
</div>
</template>
5 changes: 3 additions & 2 deletions packages/core/useEyeDropper/index.ts
@@ -1,4 +1,5 @@
import { ref } from 'vue-demi'
import { useSupported } from '../useSupported'

export interface EyeDropperOpenOptions {
/**
Expand Down Expand Up @@ -31,11 +32,11 @@ export interface UseEyeDropperOptions {
*/
export function useEyeDropper(options: UseEyeDropperOptions = {}) {
const { initialValue = '' } = options
const isSupported = Boolean(typeof window !== 'undefined' && 'EyeDropper' in window)
const isSupported = useSupported(() => typeof window !== 'undefined' && 'EyeDropper' in window)
const sRGBHex = ref(initialValue)

async function open(openOptions?: EyeDropperOpenOptions) {
if (!isSupported)
if (!isSupported.value)
return
const eyeDropper: EyeDropper = new (window as any).EyeDropper()
const result = await eyeDropper.open(openOptions)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/useFileDialog/index.md
Expand Up @@ -11,7 +11,7 @@ Open file dialog with ease.
```ts
import { useFileDialog } from '@vueuse/core'

const { files, open, reset } = useDialog()
const { files, open, reset } = useFileDialog()
```

```html
Expand Down
13 changes: 7 additions & 6 deletions packages/core/useFileSystemAccess/index.ts
Expand Up @@ -3,6 +3,7 @@ import { computed, ref, unref, watch } from 'vue-demi'
import type { Awaitable, MaybeComputedRef } from '@vueuse/shared'
import type { ConfigurableWindow } from '../_configurable'
import { defaultWindow } from '../_configurable'
import { useSupported } from '../useSupported'

/**
* window.showOpenFilePicker parameters
Expand Down Expand Up @@ -102,7 +103,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
dataType = 'Text',
} = unref(options)
const window = _window as FileSystemAccessWindow
const isSupported = Boolean(window && 'showSaveFilePicker' in window && 'showOpenFilePicker' in window)
const isSupported = useSupported(() => window && 'showSaveFilePicker' in window && 'showOpenFilePicker' in window)

const fileHandle = ref<FileSystemFileHandle>()
const data = ref<string | ArrayBuffer | Blob>()
Expand All @@ -114,7 +115,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
const fileLastModified = computed(() => file.value?.lastModified ?? 0)

async function open(_options: UseFileSystemAccessCommonOptions = {}) {
if (!isSupported)
if (!isSupported.value)
return
const [handle] = await window.showOpenFilePicker({ ...unref(options), ..._options })
fileHandle.value = handle
Expand All @@ -123,7 +124,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
}

async function create(_options: UseFileSystemAccessShowSaveFileOptions = {}) {
if (!isSupported)
if (!isSupported.value)
return
fileHandle.value = await (window as FileSystemAccessWindow).showSaveFilePicker({ ...unref(options), ..._options })
data.value = undefined
Expand All @@ -132,7 +133,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
}

async function save(_options: UseFileSystemAccessShowSaveFileOptions = {}) {
if (!isSupported)
if (!isSupported.value)
return

if (!fileHandle.value)
Expand All @@ -148,7 +149,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
}

async function saveAs(_options: UseFileSystemAccessShowSaveFileOptions = {}) {
if (!isSupported)
if (!isSupported.value)
return

fileHandle.value = await (window as FileSystemAccessWindow).showSaveFilePicker({ ...unref(options), ..._options })
Expand Down Expand Up @@ -194,7 +195,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U
}

export interface UseFileSystemAccessReturn<T = string> {
isSupported: boolean
isSupported: Ref<boolean>
data: Ref<T | undefined>
file: Ref<File | undefined>
fileName: Ref<string>
Expand Down