From f8962f93688347bab70bddc93b7158163d832785 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 8 Jul 2022 15:19:11 +0200 Subject: [PATCH 1/9] docs: typo (#1797) --- packages/core/useFileDialog/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/useFileDialog/index.md b/packages/core/useFileDialog/index.md index 904885ac3d4..67b1ae210c9 100644 --- a/packages/core/useFileDialog/index.md +++ b/packages/core/useFileDialog/index.md @@ -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 From 6d64af07681fb83455ce12d7bacbab7b5b35108f Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 01:22:08 +0800 Subject: [PATCH 2/9] feat(shared): isSup --- packages/core/useEyeDropper/index.ts | 3 ++- packages/shared/utils/is.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/core/useEyeDropper/index.ts b/packages/core/useEyeDropper/index.ts index 32509e44626..0b633dd1d5c 100644 --- a/packages/core/useEyeDropper/index.ts +++ b/packages/core/useEyeDropper/index.ts @@ -1,3 +1,4 @@ +import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' export interface EyeDropperOpenOptions { @@ -31,7 +32,7 @@ export interface UseEyeDropperOptions { */ export function useEyeDropper(options: UseEyeDropperOptions = {}) { const { initialValue = '' } = options - const isSupported = Boolean(typeof window !== 'undefined' && 'EyeDropper' in window) + const isSupported = isSup(() => Boolean(typeof window !== 'undefined' && 'EyeDropper' in window)) const sRGBHex = ref(initialValue) async function open(openOptions?: EyeDropperOpenOptions) { diff --git a/packages/shared/utils/is.ts b/packages/shared/utils/is.ts index 455aa546698..df16bef9aed 100644 --- a/packages/shared/utils/is.ts +++ b/packages/shared/utils/is.ts @@ -1,3 +1,5 @@ +import { nextTick, ref } from 'vue-demi' + export const isClient = typeof window !== 'undefined' export const isDef = (val?: T): val is T => typeof val !== 'undefined' export const assert = (condition: boolean, ...infos: any[]) => { @@ -23,3 +25,11 @@ export const rand = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1)) + min } export const isIOS = /* #__PURE__ */ isClient && window?.navigator?.userAgent && /iP(ad|hone|od)/.test(window.navigator.userAgent) + +export function isSup(callback: () => boolean) { + const isSupported = ref(callback()) + nextTick(() => { + isSupported.value = callback() + }) + return isSupported +} From 5d347cd6d653b6d44d674e30e053f898272b4b75 Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 01:23:08 +0800 Subject: [PATCH 3/9] fix: ref value --- packages/core/useEyeDropper/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/useEyeDropper/index.ts b/packages/core/useEyeDropper/index.ts index 0b633dd1d5c..fce145761ff 100644 --- a/packages/core/useEyeDropper/index.ts +++ b/packages/core/useEyeDropper/index.ts @@ -36,7 +36,7 @@ export function useEyeDropper(options: UseEyeDropperOptions = {}) { 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) From b530417a133863115bf241e3e6d058383f715293 Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 01:56:44 +0800 Subject: [PATCH 4/9] refactor: `isSupported` --- packages/core/useBattery/index.ts | 5 ++-- packages/core/useBluetooth/index.ts | 6 ++-- packages/core/useBroadcastChannel/index.ts | 6 ++-- packages/core/useClipboard/index.ts | 12 ++++---- packages/core/useDeviceOrientation/index.ts | 5 ++-- packages/core/useDevicesList/index.ts | 23 +++++++------- packages/core/useDisplayMedia/index.ts | 5 ++-- packages/core/useFileSystemAccess/index.ts | 13 ++++---- packages/core/useFullscreen/index.ts | 30 +++++++++---------- packages/core/useGamepad/index.ts | 4 +-- packages/core/useGeolocation/index.ts | 6 ++-- .../core/useIntersectionObserver/index.ts | 6 ++-- packages/core/useMediaQuery/index.ts | 6 ++-- packages/core/useMemory/index.ts | 6 ++-- packages/core/useMutationObserver/index.ts | 6 ++-- packages/core/useNavigatorLanguage/index.ts | 5 ++-- packages/core/useNetwork/index.ts | 7 +++-- packages/core/usePermission/index.ts | 8 ++--- packages/core/useResizeObserver/index.ts | 6 ++-- packages/core/useScreenOrientation/index.ts | 11 +++---- packages/core/useShare/index.ts | 5 ++-- packages/core/useSpeechRecognition/index.ts | 7 +++-- packages/core/useSpeechSynthesis/index.ts | 6 ++-- packages/core/useUserMedia/index.ts | 5 ++-- packages/core/useVibrate/index.ts | 13 ++++---- packages/core/useWakeLock/index.ts | 9 +++--- packages/core/useWebNotification/index.md | 2 +- packages/core/useWebNotification/index.ts | 12 ++++---- packages/guidelines.md | 4 +-- 29 files changed, 124 insertions(+), 115 deletions(-) diff --git a/packages/core/useBattery/index.ts b/packages/core/useBattery/index.ts index 0000039bd4b..288af670743 100644 --- a/packages/core/useBattery/index.ts +++ b/packages/core/useBattery/index.ts @@ -1,5 +1,6 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ +import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' import type { ConfigurableNavigator } from '../_configurable' @@ -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 = isSup(() => Boolean(navigator && 'getBattery' in navigator)) const charging = ref(false) const chargingTime = ref(0) @@ -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) => { diff --git a/packages/core/useBluetooth/index.ts b/packages/core/useBluetooth/index.ts index 0ff27fd5cdc..981cf8e30b8 100644 --- a/packages/core/useBluetooth/index.ts +++ b/packages/core/useBluetooth/index.ts @@ -1,5 +1,5 @@ import { computed, ref, watch } from 'vue-demi' -import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -51,7 +51,7 @@ export function useBluetooth(options?: UseBluetoothOptions) { navigator = defaultNavigator, } = options || {} - const isSupported = navigator && 'bluetooth' in navigator + const isSupported = isSup(() => Boolean(navigator && 'bluetooth' in navigator)) const device = ref(undefined) @@ -63,7 +63,7 @@ export function useBluetooth(options?: UseBluetoothOptions) { async function requestDevice(): Promise { // 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: diff --git a/packages/core/useBroadcastChannel/index.ts b/packages/core/useBroadcastChannel/index.ts index 506079ec0c8..bdc0ed173a0 100644 --- a/packages/core/useBroadcastChannel/index.ts +++ b/packages/core/useBroadcastChannel/index.ts @@ -1,5 +1,5 @@ import { ref } from 'vue-demi' -import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -24,7 +24,7 @@ export const useBroadcastChannel = (options: UseBroadcastChannelOptions) => { window = defaultWindow, } = options - const isSupported = window && 'BroadcastChannel' in window + const isSupported = isSup(() => Boolean(window && 'BroadcastChannel' in window)) const isClosed = ref(false) const channel = ref() @@ -42,7 +42,7 @@ export const useBroadcastChannel = (options: UseBroadcastChannelOptions) => { isClosed.value = true } - if (isSupported) { + if (isSupported.value) { tryOnMounted(() => { error.value = null channel.value = new BroadcastChannel(name) diff --git a/packages/core/useClipboard/index.ts b/packages/core/useClipboard/index.ts index bcd83f7462f..6c0685bd1b1 100644 --- a/packages/core/useClipboard/index.ts +++ b/packages/core/useClipboard/index.ts @@ -1,8 +1,8 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import type { MaybeRef } from '@vueuse/shared' -import { useTimeoutFn } from '@vueuse/shared' -import type { ComputedRef } from 'vue-demi' +import { isSup, useTimeoutFn } from '@vueuse/shared' +import type { ComputedRef, Ref } from 'vue-demi' import { ref, unref } from 'vue-demi' import type { WindowEventName } from '../useEventListener' import { useEventListener } from '../useEventListener' @@ -31,7 +31,7 @@ export interface ClipboardOptions extends ConfigurableNavigator { } export interface ClipboardReturn { - isSupported: boolean + isSupported: Ref text: ComputedRef copied: ComputedRef copy: Optional extends true ? (text?: string) => Promise : (text: string) => Promise @@ -54,7 +54,7 @@ export function useClipboard(options: ClipboardOptions | undefi } = options const events = ['copy', 'cut'] - const isSupported = Boolean(navigator && 'clipboard' in navigator) + const isSupported = isSup(() => Boolean(navigator && 'clipboard' in navigator)) const text = ref('') const copied = ref(false) @@ -66,13 +66,13 @@ export function useClipboard(options: ClipboardOptions | undefi }) } - if (isSupported && read) { + if (isSupported.value && read) { for (const event of events) useEventListener(event as WindowEventName, updateText) } async function copy(value = unref(source)) { - if (isSupported && value != null) { + if (isSupported.value && value != null) { await navigator!.clipboard.writeText(value) text.value = value copied.value = true diff --git a/packages/core/useDeviceOrientation/index.ts b/packages/core/useDeviceOrientation/index.ts index 80e7377faa2..6f342c767a6 100644 --- a/packages/core/useDeviceOrientation/index.ts +++ b/packages/core/useDeviceOrientation/index.ts @@ -1,5 +1,6 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ +import { isSup } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' @@ -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 = isSup(() => Boolean(window && 'DeviceOrientationEvent' in window)) const isAbsolute = ref(false) const alpha: Ref = ref(null) const beta: Ref = ref(null) const gamma: Ref = ref(null) - if (window && isSupported) { + if (window && isSupported.value) { useEventListener(window, 'deviceorientation', (event) => { isAbsolute.value = event.absolute alpha.value = event.alpha diff --git a/packages/core/useDevicesList/index.ts b/packages/core/useDevicesList/index.ts index 91471473422..c749dab3843 100644 --- a/packages/core/useDevicesList/index.ts +++ b/packages/core/useDevicesList/index.ts @@ -1,5 +1,6 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ +import { isSup } from '@vueuse/shared' import type { ComputedRef, Ref } from 'vue-demi' import { computed, ref } from 'vue-demi' import { useEventListener } from '../useEventListener' @@ -34,7 +35,7 @@ export interface UseDevicesListReturn { audioOutputs: ComputedRef permissionGranted: Ref ensurePermissions: () => Promise - isSupported: boolean + isSupported: Ref } /** @@ -55,11 +56,11 @@ 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 = isSup(() => Boolean(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() @@ -67,7 +68,7 @@ export function useDevicesList(options: UseDevicesListOptions = {}): UseDevicesL } async function ensurePermissions() { - if (!isSupported) + if (!isSupported.value) return false if (permissionGranted.value) @@ -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 { diff --git a/packages/core/useDisplayMedia/index.ts b/packages/core/useDisplayMedia/index.ts index 034111d42c1..60db1e7fcd6 100644 --- a/packages/core/useDisplayMedia/index.ts +++ b/packages/core/useDisplayMedia/index.ts @@ -1,4 +1,5 @@ import type { MaybeRef } from '@vueuse/shared' +import { isSup } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref, shallowRef, watch } from 'vue-demi' import type { ConfigurableNavigator } from '../_configurable' @@ -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 = isSup(() => Boolean(navigator?.mediaDevices?.getDisplayMedia)) const constraint: DisplayMediaStreamConstraints = { audio, video } const stream: Ref = shallowRef() async function _start() { - if (!isSupported || stream.value) + if (!isSupported.value || stream.value) return stream.value = await navigator!.mediaDevices.getDisplayMedia(constraint) return stream.value diff --git a/packages/core/useFileSystemAccess/index.ts b/packages/core/useFileSystemAccess/index.ts index 0ccb3b72d8e..167a75fe278 100644 --- a/packages/core/useFileSystemAccess/index.ts +++ b/packages/core/useFileSystemAccess/index.ts @@ -1,6 +1,7 @@ import type { Ref } from 'vue-demi' import { computed, ref, unref, watch } from 'vue-demi' import type { Awaitable, MaybeRef } from '@vueuse/shared' +import { isSup } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -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 = isSup(() => Boolean(window && 'showSaveFilePicker' in window && 'showOpenFilePicker' in window)) const fileHandle = ref() const data = ref() @@ -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 @@ -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 @@ -132,7 +133,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U } async function save(_options: UseFileSystemAccessShowSaveFileOptions = {}) { - if (!isSupported) + if (!isSupported.value) return if (!fileHandle.value) @@ -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 }) @@ -194,7 +195,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U } export interface UseFileSystemAccessReturn { - isSupported: boolean + isSupported: Ref data: Ref file: Ref fileName: Ref diff --git a/packages/core/useFullscreen/index.ts b/packages/core/useFullscreen/index.ts index 1aa4f8c04c9..085300e26a2 100644 --- a/packages/core/useFullscreen/index.ts +++ b/packages/core/useFullscreen/index.ts @@ -1,7 +1,7 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import { ref } from 'vue-demi' -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' import { useEventListener } from '../useEventListener' @@ -86,27 +86,27 @@ export function useFullscreen( const { document = defaultDocument, autoExit = false } = options const targetRef = target || document?.querySelector('html') const isFullscreen = ref(false) - let isSupported = false - let map: FunctionMap = functionsMap[0] - if (!document) { - isSupported = false - } - else { - for (const m of functionsMap) { - if (m[1] in document) { - map = m - isSupported = true - break + const isSupported = isSup(() => { + if (!document) { + return false + } + else { + for (const m of functionsMap) { + if (m[1] in document) { + map = m + return true + } } } - } + return false + }) const [REQUEST, EXIT, ELEMENT,, EVENT] = map async function exit() { - if (!isSupported) + if (!isSupported.value) return if (document?.[ELEMENT]) await document[EXIT]() @@ -115,7 +115,7 @@ export function useFullscreen( } async function enter() { - if (!isSupported) + if (!isSupported.value) return await exit() diff --git a/packages/core/useGamepad/index.ts b/packages/core/useGamepad/index.ts index d99298ff4c9..8e0c8b27dfb 100644 --- a/packages/core/useGamepad/index.ts +++ b/packages/core/useGamepad/index.ts @@ -1,4 +1,4 @@ -import { createEventHook, tryOnMounted } from '@vueuse/shared' +import { createEventHook, isSup, tryOnMounted } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { computed, ref } from 'vue-demi' import { useRafFn } from '../useRafFn' @@ -62,7 +62,7 @@ export function useGamepad(options: UseGamepadOptions = {}) { const { navigator = defaultNavigator, } = options - const isSupported = navigator && 'getGamepads' in navigator + const isSupported = isSup(() => Boolean(navigator && 'getGamepads' in navigator)) const gamepads = ref([]) const onConnectedHook = createEventHook() diff --git a/packages/core/useGeolocation/index.ts b/packages/core/useGeolocation/index.ts index 6e06b06c445..8195220a3d0 100644 --- a/packages/core/useGeolocation/index.ts +++ b/packages/core/useGeolocation/index.ts @@ -2,7 +2,7 @@ import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -22,7 +22,7 @@ export function useGeolocation(options: GeolocationOptions = {}) { navigator = defaultNavigator, } = options - const isSupported = navigator && 'geolocation' in navigator + const isSupported = isSup(() => Boolean(navigator && 'geolocation' in navigator)) const locatedAt: Ref = ref(null) const error = ref(null) @@ -44,7 +44,7 @@ export function useGeolocation(options: GeolocationOptions = {}) { let watcher: number - if (isSupported) { + if (isSupported.value) { watcher = navigator!.geolocation.watchPosition( updatePosition, err => error.value = err, diff --git a/packages/core/useIntersectionObserver/index.ts b/packages/core/useIntersectionObserver/index.ts index cfbbf3097f0..10744354085 100644 --- a/packages/core/useIntersectionObserver/index.ts +++ b/packages/core/useIntersectionObserver/index.ts @@ -1,5 +1,5 @@ import { watch } from 'vue-demi' -import { noop, tryOnScopeDispose } from '@vueuse/shared' +import { isSup, noop, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' import type { MaybeElementRef } from '../unrefElement' @@ -42,11 +42,11 @@ export function useIntersectionObserver( window = defaultWindow, } = options - const isSupported = window && 'IntersectionObserver' in window + const isSupported = isSup(() => Boolean(window && 'IntersectionObserver' in window)) let cleanup = noop - const stopWatch = isSupported + const stopWatch = isSupported.value ? watch( () => ({ el: unrefElement(target), diff --git a/packages/core/useMediaQuery/index.ts b/packages/core/useMediaQuery/index.ts index ab2cda54996..eb6d0ecb5cb 100644 --- a/packages/core/useMediaQuery/index.ts +++ b/packages/core/useMediaQuery/index.ts @@ -1,7 +1,7 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import { ref } from 'vue-demi' -import { tryOnBeforeMount, tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnBeforeMount, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -14,13 +14,13 @@ import { defaultWindow } from '../_configurable' */ export function useMediaQuery(query: string, options: ConfigurableWindow = {}) { const { window = defaultWindow } = options - const isSupported = Boolean(window && 'matchMedia' in window && typeof window!.matchMedia === 'function') + const isSupported = isSup(() => Boolean(window && 'matchMedia' in window && typeof window!.matchMedia === 'function')) let mediaQuery: MediaQueryList | undefined const matches = ref(false) const update = () => { - if (!isSupported) + if (!isSupported.value) return if (!mediaQuery) mediaQuery = window!.matchMedia(query) diff --git a/packages/core/useMemory/index.ts b/packages/core/useMemory/index.ts index 7a44c2adde1..5d1c0460655 100644 --- a/packages/core/useMemory/index.ts +++ b/packages/core/useMemory/index.ts @@ -1,6 +1,6 @@ import { ref } from 'vue-demi' import type { IntervalFnOptions } from '@vueuse/shared' -import { useIntervalFn } from '@vueuse/shared' +import { isSup, useIntervalFn } from '@vueuse/shared' /** * Performance.memory @@ -40,9 +40,9 @@ type PerformanceMemory = Performance & { */ export function useMemory(options: MemoryOptions = {}) { const memory = ref() - const isSupported = typeof performance !== 'undefined' && 'memory' in performance + const isSupported = isSup(() => typeof performance !== 'undefined' && 'memory' in performance) - if (isSupported) { + if (isSupported.value) { const { interval = 1000 } = options useIntervalFn(() => { memory.value = (performance as PerformanceMemory).memory diff --git a/packages/core/useMutationObserver/index.ts b/packages/core/useMutationObserver/index.ts index 202faf1a1eb..125f6eec2c6 100644 --- a/packages/core/useMutationObserver/index.ts +++ b/packages/core/useMutationObserver/index.ts @@ -1,4 +1,4 @@ -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' import { watch } from 'vue-demi' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' @@ -23,7 +23,7 @@ export function useMutationObserver( ) { const { window = defaultWindow, ...mutationOptions } = options let observer: MutationObserver | undefined - const isSupported = window && 'MutationObserver' in window + const isSupported = isSup(() => Boolean(window && 'MutationObserver' in window)) const cleanup = () => { if (observer) { @@ -37,7 +37,7 @@ export function useMutationObserver( (el) => { cleanup() - if (isSupported && window && el) { + if (isSupported.value && window && el) { observer = new MutationObserver(callback) observer!.observe(el, mutationOptions) } diff --git a/packages/core/useNavigatorLanguage/index.ts b/packages/core/useNavigatorLanguage/index.ts index 368c1d37dff..3ddcbccc9e4 100644 --- a/packages/core/useNavigatorLanguage/index.ts +++ b/packages/core/useNavigatorLanguage/index.ts @@ -1,3 +1,4 @@ +import { isSup } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' @@ -7,7 +8,7 @@ import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' export interface NavigatorLanguageState { - isSupported: boolean + isSupported: Ref /** * * ISO 639-1 standard Language Code @@ -40,7 +41,7 @@ export const useNavigatorLanguage = (options: ConfigurableWindow = {}): Readonly const navigator = window?.navigator - const isSupported = Boolean(navigator && 'language' in navigator) + const isSupported = isSup(() => Boolean(navigator && 'language' in navigator)) const language = ref(navigator?.language) diff --git a/packages/core/useNetwork/index.ts b/packages/core/useNetwork/index.ts index 6a9c32e7930..5af3c967bac 100644 --- a/packages/core/useNetwork/index.ts +++ b/packages/core/useNetwork/index.ts @@ -1,5 +1,6 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ +import { isSup } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' @@ -11,7 +12,7 @@ export type NetworkType = 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi export type NetworkEffectiveType = 'slow-2g' | '2g' | '3g' | '4g' | undefined export interface NetworkState { - isSupported: boolean + isSupported: Ref /** * If the user is currently connected. */ @@ -59,7 +60,7 @@ export interface NetworkState { export function useNetwork(options: ConfigurableWindow = {}): Readonly { const { window = defaultWindow } = options const navigator = window?.navigator - const isSupported = Boolean(navigator && 'connection' in navigator) + const isSupported = isSup(() => Boolean(navigator && 'connection' in navigator)) const isOnline = ref(true) const saveData = ref(false) @@ -71,7 +72,7 @@ export function useNetwork(options: ConfigurableWindow = {}): Readonly = ref(undefined) const type: Ref = ref('unknown') - const connection = isSupported && (navigator as any).connection + const connection = isSupported.value && (navigator as any).connection function updateNetworkInformation() { if (!navigator) diff --git a/packages/core/usePermission/index.ts b/packages/core/usePermission/index.ts index 95867a61db3..0767ebe04b5 100644 --- a/packages/core/usePermission/index.ts +++ b/packages/core/usePermission/index.ts @@ -1,6 +1,6 @@ import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' -import { createSingletonPromise } from '@vueuse/shared' +import { createSingletonPromise, isSup } from '@vueuse/shared' import { useEventListener } from '../useEventListener' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -38,7 +38,7 @@ export interface UsePermissionOptions extends Configur export type UsePermissionReturn = Readonly> export interface UsePermissionReturnWithControls { state: UsePermissionReturn - isSupported: boolean + isSupported: Ref query: () => Promise } @@ -64,7 +64,7 @@ export function usePermission( navigator = defaultNavigator, } = options - const isSupported = Boolean(navigator && 'permissions' in navigator) + const isSupported = isSup(() => Boolean(navigator && 'permissions' in navigator)) let permissionStatus: PermissionStatus | undefined const desc = typeof permissionDesc === 'string' @@ -78,7 +78,7 @@ export function usePermission( } const query = createSingletonPromise(async () => { - if (!isSupported) + if (!isSupported.value) return if (!permissionStatus) { try { diff --git a/packages/core/useResizeObserver/index.ts b/packages/core/useResizeObserver/index.ts index 6b15d3ff3c2..5fef62f0f48 100644 --- a/packages/core/useResizeObserver/index.ts +++ b/packages/core/useResizeObserver/index.ts @@ -1,4 +1,4 @@ -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' import { watch } from 'vue-demi' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' @@ -52,7 +52,7 @@ export function useResizeObserver( ) { const { window = defaultWindow, ...observerOptions } = options let observer: ResizeObserver | undefined - const isSupported = window && 'ResizeObserver' in window + const isSupported = isSup(() => Boolean(window && 'ResizeObserver' in window)) const cleanup = () => { if (observer) { @@ -66,7 +66,7 @@ export function useResizeObserver( (el) => { cleanup() - if (isSupported && window && el) { + if (isSupported.value && window && el) { observer = new ResizeObserver(callback) observer!.observe(el, observerOptions) } diff --git a/packages/core/useScreenOrientation/index.ts b/packages/core/useScreenOrientation/index.ts index ecb4d583745..13dd8573f10 100644 --- a/packages/core/useScreenOrientation/index.ts +++ b/packages/core/useScreenOrientation/index.ts @@ -1,3 +1,4 @@ +import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' import type { ConfigurableWindow } from '../_configurable' @@ -14,14 +15,14 @@ export const useScreenOrientation = (options: ConfigurableWindow = {}) => { window = defaultWindow, } = options - const isSupported = !!(window && 'screen' in window && 'orientation' in window.screen) + const isSupported = isSup(() => Boolean(window && 'screen' in window && 'orientation' in window.screen)) - const screenOrientation = isSupported ? window.screen.orientation : {} as ScreenOrientation + const screenOrientation = isSupported.value ? window!.screen.orientation : {} as ScreenOrientation const orientation = ref(screenOrientation.type) const angle = ref(screenOrientation.angle || 0) - if (isSupported) { + if (isSupported.value) { useEventListener(window, 'orientationchange', () => { orientation.value = screenOrientation.type angle.value = screenOrientation.angle @@ -29,14 +30,14 @@ export const useScreenOrientation = (options: ConfigurableWindow = {}) => { } const lockOrientation = (type: OrientationLockType) => { - if (!isSupported) + if (!isSupported.value) return Promise.reject(new Error('Not supported')) return screenOrientation.lock(type) } const unlockOrientation = () => { - if (isSupported) + if (isSupported.value) screenOrientation.unlock() } diff --git a/packages/core/useShare/index.ts b/packages/core/useShare/index.ts index 265400bd4c7..62a37958843 100644 --- a/packages/core/useShare/index.ts +++ b/packages/core/useShare/index.ts @@ -1,4 +1,5 @@ import type { MaybeRef } from '@vueuse/shared' +import { isSup } from '@vueuse/shared' import { unref } from 'vue-demi' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -26,10 +27,10 @@ export function useShare(shareOptions: MaybeRef = {}, options: Con const { navigator = defaultNavigator } = options const _navigator = (navigator as NavigatorWithShare) - const isSupported = _navigator && 'canShare' in _navigator + const isSupported = isSup(() => Boolean(_navigator && 'canShare' in _navigator)) const share = async (overrideOptions: MaybeRef = {}) => { - if (isSupported) { + if (isSupported.value) { const data = { ...unref(shareOptions), ...unref(overrideOptions), diff --git a/packages/core/useSpeechRecognition/index.ts b/packages/core/useSpeechRecognition/index.ts index 4f54078746b..8213e472c92 100644 --- a/packages/core/useSpeechRecognition/index.ts +++ b/packages/core/useSpeechRecognition/index.ts @@ -2,7 +2,8 @@ // by https://github.com/wobsoriano import type { MaybeRef } from '@vueuse/shared' -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' + import type { Ref } from 'vue-demi' import { ref, shallowRef, unref, watch } from 'vue-demi' import type { ConfigurableWindow } from '../_configurable' @@ -63,11 +64,11 @@ export function useSpeechRecognition(options: SpeechRecognitionOptions = {}) { } const SpeechRecognition = window && ((window as any).SpeechRecognition || (window as any).webkitSpeechRecognition) - const isSupported = Boolean(SpeechRecognition) + const isSupported = isSup(() => Boolean(SpeechRecognition)) let recognition: SpeechRecognition | undefined - if (isSupported) { + if (isSupported.value) { recognition = new SpeechRecognition() as SpeechRecognition recognition.continuous = continuous diff --git a/packages/core/useSpeechSynthesis/index.ts b/packages/core/useSpeechSynthesis/index.ts index 884f5283382..a348e4bcdc5 100644 --- a/packages/core/useSpeechSynthesis/index.ts +++ b/packages/core/useSpeechSynthesis/index.ts @@ -1,5 +1,5 @@ import type { MaybeRef } from '@vueuse/shared' -import { tryOnScopeDispose } from '@vueuse/shared' +import { isSup, tryOnScopeDispose } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { computed, ref, shallowRef, unref, watch } from 'vue-demi' import type { ConfigurableWindow } from '../_configurable' @@ -56,7 +56,7 @@ export function useSpeechSynthesis(text: MaybeRef, options: SpeechSynthe } = options const synth = window && (window as any).speechSynthesis as SpeechSynthesis - const isSupported = Boolean(synth) + const isSupported = isSup(() => Boolean(synth)) const isPlaying = ref(false) const status = ref('init') @@ -125,7 +125,7 @@ export function useSpeechSynthesis(text: MaybeRef, options: SpeechSynthe utterance && synth!.speak(utterance.value) } - if (isSupported) { + if (isSupported.value) { bindEventsForUtterance(utterance.value) watch(lang, (lang) => { diff --git a/packages/core/useUserMedia/index.ts b/packages/core/useUserMedia/index.ts index 17a444db445..06d1776f098 100644 --- a/packages/core/useUserMedia/index.ts +++ b/packages/core/useUserMedia/index.ts @@ -1,6 +1,7 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import type { MaybeRef } from '@vueuse/shared' +import { isSup } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref, shallowRef, watch } from 'vue-demi' import type { ConfigurableNavigator } from '../_configurable' @@ -50,7 +51,7 @@ export function useUserMedia(options: UseUserMediaOptions = {}) { const videoDeviceId = ref(options.videoDeviceId) const audioDeviceId = ref(options.audioDeviceId) const { navigator = defaultNavigator } = options - const isSupported = Boolean(navigator?.mediaDevices?.getUserMedia) + const isSupported = isSup(() => Boolean(navigator?.mediaDevices?.getUserMedia)) const stream: Ref = shallowRef() @@ -65,7 +66,7 @@ export function useUserMedia(options: UseUserMediaOptions = {}) { } async function _start() { - if (!isSupported || stream.value) + if (!isSupported.value || stream.value) return stream.value = await navigator!.mediaDevices.getUserMedia({ video: getDeviceOptions(videoDeviceId), diff --git a/packages/core/useVibrate/index.ts b/packages/core/useVibrate/index.ts index 6b410f0e6b4..1897a0d867c 100644 --- a/packages/core/useVibrate/index.ts +++ b/packages/core/useVibrate/index.ts @@ -1,6 +1,7 @@ import { ref } from 'vue-demi' import type { MaybeRef, Pausable } from '@vueuse/shared' -import { useIntervalFn } from '@vueuse/shared' +import { isSup, useIntervalFn } from '@vueuse/shared' + import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -44,21 +45,21 @@ export function useVibrate(options?: UseVibrateOptions) { navigator = defaultNavigator, } = options || {} - const isSupported = typeof navigator !== 'undefined' && 'vibrate' in navigator + const isSupported = isSup(() => typeof navigator !== 'undefined' && 'vibrate' in navigator) const patternRef = ref(pattern) let intervalControls: Pausable | undefined const vibrate = (pattern = patternRef.value) => { - if (isSupported) - navigator.vibrate(pattern) + if (isSupported.value) + navigator!.vibrate(pattern) } // Attempt to stop the vibration: const stop = () => { // Stope the vibration if we need to: - if (isSupported) - navigator.vibrate(0) + if (isSupported.value) + navigator!.vibrate(0) intervalControls?.pause() } diff --git a/packages/core/useWakeLock/index.ts b/packages/core/useWakeLock/index.ts index ae02bf77718..a8b53576218 100644 --- a/packages/core/useWakeLock/index.ts +++ b/packages/core/useWakeLock/index.ts @@ -1,3 +1,4 @@ +import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' import type { ConfigurableDocument, ConfigurableNavigator } from '../_configurable' @@ -27,11 +28,11 @@ export const useWakeLock = (options: ConfigurableNavigator & ConfigurableDocumen document = defaultDocument, } = options let wakeLock: WakeLockSentinel | null - const isSupported = navigator && 'wakeLock' in navigator + const isSupported = isSup(() => Boolean(navigator && 'wakeLock' in navigator)) const isActive = ref(false) async function onVisibilityChange() { - if (!isSupported || !wakeLock) + if (!isSupported.value || !wakeLock) return if (document && document.visibilityState === 'visible') @@ -44,14 +45,14 @@ export const useWakeLock = (options: ConfigurableNavigator & ConfigurableDocumen useEventListener(document, 'visibilitychange', onVisibilityChange, { passive: true }) async function request(type: WakeLockType) { - if (!isSupported) + if (!isSupported.value) return wakeLock = await (navigator as NavigatorWithWakeLock).wakeLock.request(type) isActive.value = !wakeLock.released } async function release() { - if (!isSupported || !wakeLock) + if (!isSupported.value || !wakeLock) return await wakeLock.release() isActive.value = !wakeLock.released diff --git a/packages/core/useWebNotification/index.md b/packages/core/useWebNotification/index.md index d23f2f2de52..0df08862525 100644 --- a/packages/core/useWebNotification/index.md +++ b/packages/core/useWebNotification/index.md @@ -28,7 +28,7 @@ const { tag: 'test', }) -if (isSupported) +if (isSupported.value) show() ``` diff --git a/packages/core/useWebNotification/index.ts b/packages/core/useWebNotification/index.ts index 041a4db8889..bffb164ecd9 100644 --- a/packages/core/useWebNotification/index.ts +++ b/packages/core/useWebNotification/index.ts @@ -1,6 +1,6 @@ import { ref } from 'vue-demi' import type { Ref } from 'vue-demi' -import { createEventHook, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { createEventHook, isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { EventHook } from '@vueuse/shared' import { useEventListener } from '../useEventListener' import type { ConfigurableWindow } from '../_configurable' @@ -100,13 +100,13 @@ export const useWebNotification = ( window = defaultWindow, } = defaultOptions - const isSupported: boolean = !!window && 'Notification' in window + const isSupported = isSup(() => !!window && 'Notification' in window) const notification: Ref = ref(null) // Request permission to use web notifications: const requestPermission = async () => { - if (!isSupported) + if (!isSupported.value) return if ('permission' in Notification && Notification.permission !== 'denied') @@ -120,7 +120,7 @@ export const useWebNotification = ( // Show notification method: const show = async (overrides?: WebNotificationOptions) => { - if (!isSupported) + if (!isSupported.value) return await requestPermission() @@ -143,7 +143,7 @@ export const useWebNotification = ( // On mount, attempt to request permission: tryOnMounted(async () => { - if (isSupported) + if (isSupported.value) await requestPermission() }) @@ -154,7 +154,7 @@ export const useWebNotification = ( // the user (e.g.the user already read the notification on the webpage). // Most modern browsers dismiss notifications automatically after a few // moments(around four seconds). - if (isSupported && window) { + if (isSupported.value && window) { const document = window.document useEventListener(document, 'visibilitychange', (e: Event) => { e.preventDefault() diff --git a/packages/guidelines.md b/packages/guidelines.md index b7b2b39b0dc..52976ad8958 100644 --- a/packages/guidelines.md +++ b/packages/guidelines.md @@ -144,10 +144,10 @@ export function useShare( options: ConfigurableNavigator = {}, ) { const { navigator = defaultNavigator } = options - const isSupported = navigator && 'canShare' in navigator + const isSupported = isSup(() => navigator && 'canShare' in navigator) const share = async (overrideOptions) => { - if (isSupported) { + if (isSupported.value) { /* ...implementation */ } } From 6bd248e48291219683acceee82f41baa044e4621 Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 02:01:29 +0800 Subject: [PATCH 5/9] docs: fix example --- packages/guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/guidelines.md b/packages/guidelines.md index 52976ad8958..bfcc6cfa05b 100644 --- a/packages/guidelines.md +++ b/packages/guidelines.md @@ -144,7 +144,7 @@ export function useShare( options: ConfigurableNavigator = {}, ) { const { navigator = defaultNavigator } = options - const isSupported = isSup(() => navigator && 'canShare' in navigator) + const isSupported = isSup(() => Boolean(navigator && 'canShare' in navigator)) const share = async (overrideOptions) => { if (isSupported.value) { From b83bd0362f40de84cd71daf2b5eb14fea7534fc5 Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 21:17:54 +0800 Subject: [PATCH 6/9] feat(all): `isSup` -> `useSupported` --- packages/core/useBattery/index.ts | 4 ++-- packages/core/useBluetooth/index.ts | 5 +++-- packages/core/useBroadcastChannel/index.ts | 5 +++-- packages/core/useClipboard/index.ts | 5 +++-- packages/core/useDeviceOrientation/index.ts | 4 ++-- packages/core/useDevicesList/index.ts | 4 ++-- packages/core/useDisplayMedia/index.ts | 4 ++-- packages/core/useEyeDropper/index.ts | 4 ++-- packages/core/useFileSystemAccess/index.ts | 4 ++-- packages/core/useFullscreen/index.ts | 5 +++-- packages/core/useGamepad/index.ts | 5 +++-- packages/core/useGeolocation/index.ts | 5 +++-- packages/core/useIntersectionObserver/index.ts | 5 +++-- packages/core/useMediaQuery/index.ts | 5 +++-- packages/core/useMemory/index.ts | 5 +++-- packages/core/useMutationObserver/index.ts | 5 +++-- packages/core/useNavigatorLanguage/index.ts | 4 ++-- packages/core/useNetwork/index.ts | 4 ++-- packages/core/usePermission/index.ts | 5 +++-- packages/core/useResizeObserver/index.ts | 5 +++-- packages/core/useScreenOrientation/index.ts | 4 ++-- packages/core/useShare/index.ts | 5 +++-- packages/core/useSpeechRecognition/index.ts | 5 +++-- packages/core/useSpeechSynthesis/index.ts | 5 +++-- packages/core/useSupported/index.md | 16 ++++++++++++++++ packages/core/useSupported/index.ts | 14 ++++++++++++++ packages/core/useUserMedia/index.ts | 4 ++-- packages/core/useVibrate/index.ts | 5 +++-- packages/core/useWakeLock/index.ts | 4 ++-- packages/core/useWebNotification/index.ts | 5 +++-- packages/guidelines.md | 2 +- packages/shared/utils/is.ts | 10 ---------- 32 files changed, 104 insertions(+), 67 deletions(-) create mode 100644 packages/core/useSupported/index.md create mode 100644 packages/core/useSupported/index.ts diff --git a/packages/core/useBattery/index.ts b/packages/core/useBattery/index.ts index 288af670743..0349d3cb9ec 100644 --- a/packages/core/useBattery/index.ts +++ b/packages/core/useBattery/index.ts @@ -1,8 +1,8 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ -import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' +import { useSupported } from '../useSupported' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -26,7 +26,7 @@ type NavigatorWithBattery = Navigator & { export function useBattery({ navigator = defaultNavigator }: ConfigurableNavigator = {}) { const events = ['chargingchange', 'chargingtimechange', 'dischargingtimechange', 'levelchange'] - const isSupported = isSup(() => Boolean(navigator && 'getBattery' in navigator)) + const isSupported = useSupported(() => navigator && 'getBattery' in navigator) const charging = ref(false) const chargingTime = ref(0) diff --git a/packages/core/useBluetooth/index.ts b/packages/core/useBluetooth/index.ts index 981cf8e30b8..395584ec51f 100644 --- a/packages/core/useBluetooth/index.ts +++ b/packages/core/useBluetooth/index.ts @@ -1,8 +1,9 @@ import { computed, ref, watch } from 'vue-demi' -import { isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' +import { useSupported } from '../useSupported' export interface UseBluetoothRequestDeviceOptions { /** @@ -51,7 +52,7 @@ export function useBluetooth(options?: UseBluetoothOptions) { navigator = defaultNavigator, } = options || {} - const isSupported = isSup(() => Boolean(navigator && 'bluetooth' in navigator)) + const isSupported = useSupported(() => navigator && 'bluetooth' in navigator) const device = ref(undefined) diff --git a/packages/core/useBroadcastChannel/index.ts b/packages/core/useBroadcastChannel/index.ts index bdc0ed173a0..64a5a3c1076 100644 --- a/packages/core/useBroadcastChannel/index.ts +++ b/packages/core/useBroadcastChannel/index.ts @@ -1,7 +1,8 @@ import { ref } from 'vue-demi' -import { isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' +import { useSupported } from '../useSupported' export interface UseBroadcastChannelOptions extends ConfigurableWindow { /** @@ -24,7 +25,7 @@ export const useBroadcastChannel = (options: UseBroadcastChannelOptions) => { window = defaultWindow, } = options - const isSupported = isSup(() => Boolean(window && 'BroadcastChannel' in window)) + const isSupported = useSupported(() => window && 'BroadcastChannel' in window) const isClosed = ref(false) const channel = ref() diff --git a/packages/core/useClipboard/index.ts b/packages/core/useClipboard/index.ts index c0c5cd5f48e..be369f863c6 100644 --- a/packages/core/useClipboard/index.ts +++ b/packages/core/useClipboard/index.ts @@ -1,11 +1,12 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import type { MaybeComputedRef } from '@vueuse/shared' -import { isSup, resolveUnref, useTimeoutFn } from '@vueuse/shared' +import { resolveUnref, useTimeoutFn } from '@vueuse/shared' 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' @@ -54,7 +55,7 @@ export function useClipboard(options: ClipboardOptions } = options const events = ['copy', 'cut'] - const isSupported = isSup(() => Boolean(navigator && 'clipboard' in navigator)) + const isSupported = useSupported(() => navigator && 'clipboard' in navigator) const text = ref('') const copied = ref(false) diff --git a/packages/core/useDeviceOrientation/index.ts b/packages/core/useDeviceOrientation/index.ts index 6f342c767a6..340aa29ceb9 100644 --- a/packages/core/useDeviceOrientation/index.ts +++ b/packages/core/useDeviceOrientation/index.ts @@ -1,9 +1,9 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ -import { isSup } from '@vueuse/shared' 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' @@ -15,7 +15,7 @@ import { defaultWindow } from '../_configurable' */ export function useDeviceOrientation(options: ConfigurableWindow = {}) { const { window = defaultWindow } = options - const isSupported = isSup(() => Boolean(window && 'DeviceOrientationEvent' in window)) + const isSupported = useSupported(() => window && 'DeviceOrientationEvent' in window) const isAbsolute = ref(false) const alpha: Ref = ref(null) diff --git a/packages/core/useDevicesList/index.ts b/packages/core/useDevicesList/index.ts index c749dab3843..ae3f4ccacec 100644 --- a/packages/core/useDevicesList/index.ts +++ b/packages/core/useDevicesList/index.ts @@ -1,10 +1,10 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ -import { isSup } from '@vueuse/shared' 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' @@ -56,7 +56,7 @@ 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')) - const isSupported = isSup(() => Boolean(navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)) + const isSupported = useSupported(() => navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) const permissionGranted = ref(false) async function update() { diff --git a/packages/core/useDisplayMedia/index.ts b/packages/core/useDisplayMedia/index.ts index 60db1e7fcd6..d1e2fb43b8e 100644 --- a/packages/core/useDisplayMedia/index.ts +++ b/packages/core/useDisplayMedia/index.ts @@ -1,7 +1,7 @@ import type { MaybeRef } from '@vueuse/shared' -import { isSup } 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' @@ -33,7 +33,7 @@ export function useDisplayMedia(options: UseDisplayMediaOptions = {}) { const video = options.video const audio = options.audio const { navigator = defaultNavigator } = options - const isSupported = isSup(() => Boolean(navigator?.mediaDevices?.getDisplayMedia)) + const isSupported = useSupported(() => navigator?.mediaDevices?.getDisplayMedia) const constraint: DisplayMediaStreamConstraints = { audio, video } diff --git a/packages/core/useEyeDropper/index.ts b/packages/core/useEyeDropper/index.ts index fce145761ff..554b56fd565 100644 --- a/packages/core/useEyeDropper/index.ts +++ b/packages/core/useEyeDropper/index.ts @@ -1,5 +1,5 @@ -import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' +import { useSupported } from '../useSupported' export interface EyeDropperOpenOptions { /** @@ -32,7 +32,7 @@ export interface UseEyeDropperOptions { */ export function useEyeDropper(options: UseEyeDropperOptions = {}) { const { initialValue = '' } = options - const isSupported = isSup(() => 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) { diff --git a/packages/core/useFileSystemAccess/index.ts b/packages/core/useFileSystemAccess/index.ts index ce6fcf847d6..e8169b8850e 100644 --- a/packages/core/useFileSystemAccess/index.ts +++ b/packages/core/useFileSystemAccess/index.ts @@ -1,9 +1,9 @@ import type { Ref } from 'vue-demi' import { computed, ref, unref, watch } from 'vue-demi' import type { Awaitable, MaybeComputedRef } from '@vueuse/shared' -import { isSup } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' +import { useSupported } from '../useSupported' /** * window.showOpenFilePicker parameters @@ -103,7 +103,7 @@ export function useFileSystemAccess(options: UseFileSystemAccessOptions = {}): U dataType = 'Text', } = unref(options) const window = _window as FileSystemAccessWindow - const isSupported = isSup(() => Boolean(window && 'showSaveFilePicker' in window && 'showOpenFilePicker' in window)) + const isSupported = useSupported(() => window && 'showSaveFilePicker' in window && 'showOpenFilePicker' in window) const fileHandle = ref() const data = ref() diff --git a/packages/core/useFullscreen/index.ts b/packages/core/useFullscreen/index.ts index 085300e26a2..5b77e9f3106 100644 --- a/packages/core/useFullscreen/index.ts +++ b/packages/core/useFullscreen/index.ts @@ -1,12 +1,13 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import { ref } from 'vue-demi' -import { isSup, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnScopeDispose } from '@vueuse/shared' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' import { useEventListener } from '../useEventListener' import type { ConfigurableDocument } from '../_configurable' import { defaultDocument } from '../_configurable' +import { useSupported } from '../useSupported' type FunctionMap = [ 'requestFullscreen', @@ -88,7 +89,7 @@ export function useFullscreen( const isFullscreen = ref(false) let map: FunctionMap = functionsMap[0] - const isSupported = isSup(() => { + const isSupported = useSupported(() => { if (!document) { return false } diff --git a/packages/core/useGamepad/index.ts b/packages/core/useGamepad/index.ts index 8e0c8b27dfb..3ba1ca3538b 100644 --- a/packages/core/useGamepad/index.ts +++ b/packages/core/useGamepad/index.ts @@ -1,10 +1,11 @@ -import { createEventHook, isSup, tryOnMounted } from '@vueuse/shared' +import { createEventHook, tryOnMounted } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { computed, ref } from 'vue-demi' import { useRafFn } from '../useRafFn' import { useEventListener } from '../useEventListener' import type { ConfigurableNavigator, ConfigurableWindow } from '../_configurable' import { defaultNavigator } from '../_configurable' +import { useSupported } from '../useSupported' export interface UseGamepadOptions extends ConfigurableWindow, ConfigurableNavigator { @@ -62,7 +63,7 @@ export function useGamepad(options: UseGamepadOptions = {}) { const { navigator = defaultNavigator, } = options - const isSupported = isSup(() => Boolean(navigator && 'getGamepads' in navigator)) + const isSupported = useSupported(() => navigator && 'getGamepads' in navigator) const gamepads = ref([]) const onConnectedHook = createEventHook() diff --git a/packages/core/useGeolocation/index.ts b/packages/core/useGeolocation/index.ts index 8195220a3d0..461d53d7ee6 100644 --- a/packages/core/useGeolocation/index.ts +++ b/packages/core/useGeolocation/index.ts @@ -2,9 +2,10 @@ import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' -import { isSup, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' +import { useSupported } from '../useSupported' export interface GeolocationOptions extends Partial, ConfigurableNavigator {} @@ -22,7 +23,7 @@ export function useGeolocation(options: GeolocationOptions = {}) { navigator = defaultNavigator, } = options - const isSupported = isSup(() => Boolean(navigator && 'geolocation' in navigator)) + const isSupported = useSupported(() => navigator && 'geolocation' in navigator) const locatedAt: Ref = ref(null) const error = ref(null) diff --git a/packages/core/useIntersectionObserver/index.ts b/packages/core/useIntersectionObserver/index.ts index 10744354085..a1dda20c1b9 100644 --- a/packages/core/useIntersectionObserver/index.ts +++ b/packages/core/useIntersectionObserver/index.ts @@ -1,9 +1,10 @@ import { watch } from 'vue-demi' -import { isSup, noop, tryOnScopeDispose } from '@vueuse/shared' +import { noop, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' +import { useSupported } from '../useSupported' export interface IntersectionObserverOptions extends ConfigurableWindow { /** @@ -42,7 +43,7 @@ export function useIntersectionObserver( window = defaultWindow, } = options - const isSupported = isSup(() => Boolean(window && 'IntersectionObserver' in window)) + const isSupported = useSupported(() => window && 'IntersectionObserver' in window) let cleanup = noop diff --git a/packages/core/useMediaQuery/index.ts b/packages/core/useMediaQuery/index.ts index eb6d0ecb5cb..e1c92de5711 100644 --- a/packages/core/useMediaQuery/index.ts +++ b/packages/core/useMediaQuery/index.ts @@ -1,9 +1,10 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import { ref } from 'vue-demi' -import { isSup, tryOnBeforeMount, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnBeforeMount, tryOnScopeDispose } from '@vueuse/shared' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' +import { useSupported } from '../useSupported' /** * Reactive Media Query. @@ -14,7 +15,7 @@ import { defaultWindow } from '../_configurable' */ export function useMediaQuery(query: string, options: ConfigurableWindow = {}) { const { window = defaultWindow } = options - const isSupported = isSup(() => Boolean(window && 'matchMedia' in window && typeof window!.matchMedia === 'function')) + const isSupported = useSupported(() => window && 'matchMedia' in window && typeof window!.matchMedia === 'function') let mediaQuery: MediaQueryList | undefined const matches = ref(false) diff --git a/packages/core/useMemory/index.ts b/packages/core/useMemory/index.ts index 8e8512c24b8..508febecef5 100644 --- a/packages/core/useMemory/index.ts +++ b/packages/core/useMemory/index.ts @@ -1,6 +1,7 @@ import { ref } from 'vue-demi' import type { IntervalFnOptions } from '@vueuse/shared' -import { isSup, useIntervalFn } from '@vueuse/shared' +import { useIntervalFn } from '@vueuse/shared' +import { useSupported } from '../useSupported' /** * Performance.memory @@ -40,7 +41,7 @@ type PerformanceMemory = Performance & { */ export function useMemory(options: UseMemoryOptions = {}) { const memory = ref() - const isSupported = isSup(() => typeof performance !== 'undefined' && 'memory' in performance) + const isSupported = useSupported(() => typeof performance !== 'undefined' && 'memory' in performance) if (isSupported.value) { const { interval = 1000 } = options diff --git a/packages/core/useMutationObserver/index.ts b/packages/core/useMutationObserver/index.ts index 125f6eec2c6..199c2322023 100644 --- a/packages/core/useMutationObserver/index.ts +++ b/packages/core/useMutationObserver/index.ts @@ -1,7 +1,8 @@ -import { isSup, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnScopeDispose } from '@vueuse/shared' import { watch } from 'vue-demi' import type { MaybeElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' +import { useSupported } from '../useSupported' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -23,7 +24,7 @@ export function useMutationObserver( ) { const { window = defaultWindow, ...mutationOptions } = options let observer: MutationObserver | undefined - const isSupported = isSup(() => Boolean(window && 'MutationObserver' in window)) + const isSupported = useSupported(() => window && 'MutationObserver' in window) const cleanup = () => { if (observer) { diff --git a/packages/core/useNavigatorLanguage/index.ts b/packages/core/useNavigatorLanguage/index.ts index 3ddcbccc9e4..3d659368926 100644 --- a/packages/core/useNavigatorLanguage/index.ts +++ b/packages/core/useNavigatorLanguage/index.ts @@ -1,8 +1,8 @@ -import { isSup } from '@vueuse/shared' 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' @@ -41,7 +41,7 @@ export const useNavigatorLanguage = (options: ConfigurableWindow = {}): Readonly const navigator = window?.navigator - const isSupported = isSup(() => Boolean(navigator && 'language' in navigator)) + const isSupported = useSupported(() => navigator && 'language' in navigator) const language = ref(navigator?.language) diff --git a/packages/core/useNetwork/index.ts b/packages/core/useNetwork/index.ts index 5af3c967bac..c4b0acde050 100644 --- a/packages/core/useNetwork/index.ts +++ b/packages/core/useNetwork/index.ts @@ -1,9 +1,9 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ -import { isSup } from '@vueuse/shared' 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' @@ -60,7 +60,7 @@ export interface NetworkState { export function useNetwork(options: ConfigurableWindow = {}): Readonly { const { window = defaultWindow } = options const navigator = window?.navigator - const isSupported = isSup(() => Boolean(navigator && 'connection' in navigator)) + const isSupported = useSupported(() => navigator && 'connection' in navigator) const isOnline = ref(true) const saveData = ref(false) diff --git a/packages/core/usePermission/index.ts b/packages/core/usePermission/index.ts index 0767ebe04b5..277040d2681 100644 --- a/packages/core/usePermission/index.ts +++ b/packages/core/usePermission/index.ts @@ -1,9 +1,10 @@ import type { Ref } from 'vue-demi' import { ref } from 'vue-demi' -import { createSingletonPromise, isSup } from '@vueuse/shared' +import { createSingletonPromise } from '@vueuse/shared' import { useEventListener } from '../useEventListener' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' +import { useSupported } from '../useSupported' type DescriptorNamePolyfill = 'accelerometer' | @@ -64,7 +65,7 @@ export function usePermission( navigator = defaultNavigator, } = options - const isSupported = isSup(() => Boolean(navigator && 'permissions' in navigator)) + const isSupported = useSupported(() => navigator && 'permissions' in navigator) let permissionStatus: PermissionStatus | undefined const desc = typeof permissionDesc === 'string' diff --git a/packages/core/useResizeObserver/index.ts b/packages/core/useResizeObserver/index.ts index bc8cba0a05b..1e12b3f025d 100644 --- a/packages/core/useResizeObserver/index.ts +++ b/packages/core/useResizeObserver/index.ts @@ -1,7 +1,8 @@ -import { isSup, tryOnScopeDispose } from '@vueuse/shared' +import { tryOnScopeDispose } from '@vueuse/shared' import { watch } from 'vue-demi' import type { MaybeComputedElementRef } from '../unrefElement' import { unrefElement } from '../unrefElement' +import { useSupported } from '../useSupported' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -52,7 +53,7 @@ export function useResizeObserver( ) { const { window = defaultWindow, ...observerOptions } = options let observer: ResizeObserver | undefined - const isSupported = isSup(() => Boolean(window && 'ResizeObserver' in window)) + const isSupported = useSupported(() => window && 'ResizeObserver' in window) const cleanup = () => { if (observer) { diff --git a/packages/core/useScreenOrientation/index.ts b/packages/core/useScreenOrientation/index.ts index 592672bd5f7..ee0db36e2d6 100644 --- a/packages/core/useScreenOrientation/index.ts +++ b/packages/core/useScreenOrientation/index.ts @@ -1,6 +1,6 @@ -import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' +import { useSupported } from '../useSupported' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -14,7 +14,7 @@ export const useScreenOrientation = (options: ConfigurableWindow = {}) => { window = defaultWindow, } = options - const isSupported = isSup(() => Boolean(window && 'screen' in window && 'orientation' in window.screen)) + const isSupported = useSupported(() => window && 'screen' in window && 'orientation' in window.screen) const screenOrientation = isSupported.value ? window!.screen.orientation : {} as ScreenOrientation diff --git a/packages/core/useShare/index.ts b/packages/core/useShare/index.ts index 5f581ff5293..275fad43079 100644 --- a/packages/core/useShare/index.ts +++ b/packages/core/useShare/index.ts @@ -1,5 +1,6 @@ import type { MaybeComputedRef } from '@vueuse/shared' -import { isSup, resolveUnref } from '@vueuse/shared' +import { resolveUnref } from '@vueuse/shared' +import { useSupported } from '../useSupported' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -26,7 +27,7 @@ export function useShare(shareOptions: MaybeComputedRef = {}, opti const { navigator = defaultNavigator } = options const _navigator = (navigator as NavigatorWithShare) - const isSupported = isSup(() => Boolean(_navigator && 'canShare' in _navigator)) + const isSupported = useSupported(() => _navigator && 'canShare' in _navigator) const share = async (overrideOptions: MaybeComputedRef = {}) => { if (isSupported.value) { diff --git a/packages/core/useSpeechRecognition/index.ts b/packages/core/useSpeechRecognition/index.ts index 6fa7dd996e0..c81dd4e3f9a 100644 --- a/packages/core/useSpeechRecognition/index.ts +++ b/packages/core/useSpeechRecognition/index.ts @@ -2,9 +2,10 @@ // by https://github.com/wobsoriano import type { MaybeComputedRef } from '@vueuse/shared' -import { isSup, resolveRef, tryOnScopeDispose } from '@vueuse/shared' +import { resolveRef, tryOnScopeDispose } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { ref, shallowRef, unref, watch } from 'vue-demi' +import { useSupported } from '../useSupported' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' import type { SpeechRecognition, SpeechRecognitionErrorEvent } from './types' @@ -63,7 +64,7 @@ export function useSpeechRecognition(options: SpeechRecognitionOptions = {}) { } const SpeechRecognition = window && ((window as any).SpeechRecognition || (window as any).webkitSpeechRecognition) - const isSupported = isSup(() => Boolean(SpeechRecognition)) + const isSupported = useSupported(() => SpeechRecognition) let recognition: SpeechRecognition | undefined diff --git a/packages/core/useSpeechSynthesis/index.ts b/packages/core/useSpeechSynthesis/index.ts index d1cd7be7d83..a2fb115b8b5 100644 --- a/packages/core/useSpeechSynthesis/index.ts +++ b/packages/core/useSpeechSynthesis/index.ts @@ -1,7 +1,8 @@ import type { MaybeComputedRef } from '@vueuse/shared' -import { isSup, resolveRef, tryOnScopeDispose } from '@vueuse/shared' +import { resolveRef, tryOnScopeDispose } from '@vueuse/shared' import type { Ref } from 'vue-demi' import { computed, ref, shallowRef, unref, watch } from 'vue-demi' +import { useSupported } from '../useSupported' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' @@ -56,7 +57,7 @@ export function useSpeechSynthesis(text: MaybeComputedRef, options: Spee } = options const synth = window && (window as any).speechSynthesis as SpeechSynthesis - const isSupported = isSup(() => Boolean(synth)) + const isSupported = useSupported(() => synth) const isPlaying = ref(false) const status = ref('init') diff --git a/packages/core/useSupported/index.md b/packages/core/useSupported/index.md new file mode 100644 index 00000000000..00bc1757474 --- /dev/null +++ b/packages/core/useSupported/index.md @@ -0,0 +1,16 @@ +# useSupported + +SSR compatibility `isSupported` + +## Usage + +```ts +import { useSupported } from '@vueuse/core' + +const isSupported = useSupported(() => navigator && 'getBattery' in navigator) + +if (isSupported.value) { + // do something + navigator.getBattery +} +``` diff --git a/packages/core/useSupported/index.ts b/packages/core/useSupported/index.ts new file mode 100644 index 00000000000..0948bf49fe5 --- /dev/null +++ b/packages/core/useSupported/index.ts @@ -0,0 +1,14 @@ +import { tryOnMounted } from '@vueuse/shared' +import type { Ref } from 'vue-demi' +import { ref } from 'vue-demi' + +export function useSupported(callback: () => unknown, sync?: boolean) { + const isSupported = ref() as Ref + + const update = () => isSupported.value = Boolean(callback()) + + update() + + tryOnMounted(update, sync) + return isSupported +} diff --git a/packages/core/useUserMedia/index.ts b/packages/core/useUserMedia/index.ts index 06d1776f098..8f2000cf8f0 100644 --- a/packages/core/useUserMedia/index.ts +++ b/packages/core/useUserMedia/index.ts @@ -1,9 +1,9 @@ /* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */ import type { MaybeRef } from '@vueuse/shared' -import { isSup } 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' @@ -51,7 +51,7 @@ export function useUserMedia(options: UseUserMediaOptions = {}) { const videoDeviceId = ref(options.videoDeviceId) const audioDeviceId = ref(options.audioDeviceId) const { navigator = defaultNavigator } = options - const isSupported = isSup(() => Boolean(navigator?.mediaDevices?.getUserMedia)) + const isSupported = useSupported(() => navigator?.mediaDevices?.getUserMedia) const stream: Ref = shallowRef() diff --git a/packages/core/useVibrate/index.ts b/packages/core/useVibrate/index.ts index e7f5f5bc676..f953eb8203f 100644 --- a/packages/core/useVibrate/index.ts +++ b/packages/core/useVibrate/index.ts @@ -1,5 +1,6 @@ import type { MaybeComputedRef, Pausable } from '@vueuse/shared' -import { isSup, resolveRef, useIntervalFn } from '@vueuse/shared' +import { resolveRef, useIntervalFn } from '@vueuse/shared' +import { useSupported } from '../useSupported' import type { ConfigurableNavigator } from '../_configurable' import { defaultNavigator } from '../_configurable' @@ -43,7 +44,7 @@ export function useVibrate(options?: UseVibrateOptions) { navigator = defaultNavigator, } = options || {} - const isSupported = isSup(() => typeof navigator !== 'undefined' && 'vibrate' in navigator) + const isSupported = useSupported(() => typeof navigator !== 'undefined' && 'vibrate' in navigator) const patternRef = resolveRef(pattern) let intervalControls: Pausable | undefined diff --git a/packages/core/useWakeLock/index.ts b/packages/core/useWakeLock/index.ts index a8b53576218..8fa85d9d749 100644 --- a/packages/core/useWakeLock/index.ts +++ b/packages/core/useWakeLock/index.ts @@ -1,6 +1,6 @@ -import { isSup } from '@vueuse/shared' import { ref } from 'vue-demi' import { useEventListener } from '../useEventListener' +import { useSupported } from '../useSupported' import type { ConfigurableDocument, ConfigurableNavigator } from '../_configurable' import { defaultDocument, defaultNavigator } from '../_configurable' @@ -28,7 +28,7 @@ export const useWakeLock = (options: ConfigurableNavigator & ConfigurableDocumen document = defaultDocument, } = options let wakeLock: WakeLockSentinel | null - const isSupported = isSup(() => Boolean(navigator && 'wakeLock' in navigator)) + const isSupported = useSupported(() => navigator && 'wakeLock' in navigator) const isActive = ref(false) async function onVisibilityChange() { diff --git a/packages/core/useWebNotification/index.ts b/packages/core/useWebNotification/index.ts index bffb164ecd9..89e0133292e 100644 --- a/packages/core/useWebNotification/index.ts +++ b/packages/core/useWebNotification/index.ts @@ -1,10 +1,11 @@ import { ref } from 'vue-demi' import type { Ref } from 'vue-demi' -import { createEventHook, isSup, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' +import { createEventHook, tryOnMounted, tryOnScopeDispose } from '@vueuse/shared' import type { EventHook } from '@vueuse/shared' import { useEventListener } from '../useEventListener' import type { ConfigurableWindow } from '../_configurable' import { defaultWindow } from '../_configurable' +import { useSupported } from '../useSupported' export interface WebNotificationOptions { /** @@ -100,7 +101,7 @@ export const useWebNotification = ( window = defaultWindow, } = defaultOptions - const isSupported = isSup(() => !!window && 'Notification' in window) + const isSupported = useSupported(() => !!window && 'Notification' in window) const notification: Ref = ref(null) diff --git a/packages/guidelines.md b/packages/guidelines.md index bfcc6cfa05b..8f56eb151d6 100644 --- a/packages/guidelines.md +++ b/packages/guidelines.md @@ -144,7 +144,7 @@ export function useShare( options: ConfigurableNavigator = {}, ) { const { navigator = defaultNavigator } = options - const isSupported = isSup(() => Boolean(navigator && 'canShare' in navigator)) + const isSupported = useSupported(() => navigator && 'canShare' in navigator) const share = async (overrideOptions) => { if (isSupported.value) { diff --git a/packages/shared/utils/is.ts b/packages/shared/utils/is.ts index df16bef9aed..455aa546698 100644 --- a/packages/shared/utils/is.ts +++ b/packages/shared/utils/is.ts @@ -1,5 +1,3 @@ -import { nextTick, ref } from 'vue-demi' - export const isClient = typeof window !== 'undefined' export const isDef = (val?: T): val is T => typeof val !== 'undefined' export const assert = (condition: boolean, ...infos: any[]) => { @@ -25,11 +23,3 @@ export const rand = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1)) + min } export const isIOS = /* #__PURE__ */ isClient && window?.navigator?.userAgent && /iP(ad|hone|od)/.test(window.navigator.userAgent) - -export function isSup(callback: () => boolean) { - const isSupported = ref(callback()) - nextTick(() => { - isSupported.value = callback() - }) - return isSupported -} From aeb3ba4e4501a47fb6a2f71baa90e5f4528cae93 Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 21:50:28 +0800 Subject: [PATCH 7/9] chore(useSupported): use `onMounted` --- packages/core/index.ts | 1 + packages/core/useSupported/index.md | 4 ++++ packages/core/useSupported/index.ts | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/core/index.ts b/packages/core/index.ts index 8d8cc39019d..1ea1453c108 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -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' diff --git a/packages/core/useSupported/index.md b/packages/core/useSupported/index.md index 00bc1757474..6f7eb21d634 100644 --- a/packages/core/useSupported/index.md +++ b/packages/core/useSupported/index.md @@ -1,3 +1,7 @@ +--- +category: Utilities +--- + # useSupported SSR compatibility `isSupported` diff --git a/packages/core/useSupported/index.ts b/packages/core/useSupported/index.ts index 0948bf49fe5..b289e916215 100644 --- a/packages/core/useSupported/index.ts +++ b/packages/core/useSupported/index.ts @@ -1,14 +1,14 @@ -import { tryOnMounted } from '@vueuse/shared' import type { Ref } from 'vue-demi' -import { ref } from 'vue-demi' +// eslint-disable-next-line no-restricted-imports +import { onMounted, ref } from 'vue-demi' -export function useSupported(callback: () => unknown, sync?: boolean) { +export function useSupported(callback: () => unknown) { const isSupported = ref() as Ref const update = () => isSupported.value = Boolean(callback()) update() - tryOnMounted(update, sync) + onMounted(update) return isSupported } From 5902ae536788620893ced8ee1499bef3c83084be Mon Sep 17 00:00:00 2001 From: okxiaoliang4 <353742991@qq.com> Date: Sat, 9 Jul 2022 22:24:33 +0800 Subject: [PATCH 8/9] fix: miss --- packages/core/useClipboard/index.ts | 2 +- packages/core/useEyeDropper/demo.vue | 7 ++++--- packages/core/useSpeechRecognition/demo.vue | 2 +- packages/core/useSpeechSynthesis/demo.vue | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/core/useClipboard/index.ts b/packages/core/useClipboard/index.ts index be369f863c6..f95c17342df 100644 --- a/packages/core/useClipboard/index.ts +++ b/packages/core/useClipboard/index.ts @@ -73,7 +73,7 @@ export function useClipboard(options: ClipboardOptions } 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 diff --git a/packages/core/useEyeDropper/demo.vue b/packages/core/useEyeDropper/demo.vue index 2dba02db7e6..54043379a47 100644 --- a/packages/core/useEyeDropper/demo.vue +++ b/packages/core/useEyeDropper/demo.vue @@ -8,13 +8,14 @@ const { isSupported, open, sRGBHex } = useEyeDropper() -
+ +
+ Not Supported by Your Browser
diff --git a/packages/core/useSpeechRecognition/demo.vue b/packages/core/useSpeechRecognition/demo.vue index 16dc2ac2984..c8c4f224550 100644 --- a/packages/core/useSpeechRecognition/demo.vue +++ b/packages/core/useSpeechRecognition/demo.vue @@ -28,7 +28,7 @@ const speech = useSpeechRecognition({ const color = ref('transparent') -if (speech.isSupported) { +if (speech.isSupported.value) { // @ts-expect-error missing types const SpeechGrammarList = window.SpeechGrammarList || window.webkitSpeechGrammarList const speechRecognitionList = new SpeechGrammarList() diff --git a/packages/core/useSpeechSynthesis/demo.vue b/packages/core/useSpeechSynthesis/demo.vue index 9fdaa0090ba..a4a82466bad 100644 --- a/packages/core/useSpeechSynthesis/demo.vue +++ b/packages/core/useSpeechSynthesis/demo.vue @@ -13,7 +13,7 @@ let synth: SpeechSynthesis const voices = ref([]) -if (speech.isSupported) { +if (speech.isSupported.value) { // load at last setTimeout(() => { synth = window.speechSynthesis @@ -42,7 +42,7 @@ const stop = () => {