mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
refactor(core): airplay button (#1614)
This commit is contained in:
@@ -34,3 +34,13 @@ export {
|
||||
} from './text-track';
|
||||
export { serializeTimeRanges } from './time-ranges';
|
||||
export type { CustomElement, CustomElementCallbacks } from './types';
|
||||
export {
|
||||
isWebKitAirPlayCapable,
|
||||
supportsWebKitAirPlay,
|
||||
type WebKitAirPlayMedia,
|
||||
type WebKitDocument,
|
||||
type WebKitFullscreenElement,
|
||||
type WebKitPresentationMode,
|
||||
type WebKitVideoElement,
|
||||
type WebkitAvailabilityEvent,
|
||||
} from './webkit';
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { isWebKitAirPlayCapable, supportsWebKitAirPlay } from '../webkit';
|
||||
|
||||
// jsdom lacks WebKit's AirPlay APIs, so stub the global support flag per test.
|
||||
function stubWebKit(present: boolean) {
|
||||
const key = 'WebKitPlaybackTargetAvailabilityEvent';
|
||||
if (present) {
|
||||
(globalThis as unknown as Record<string, unknown>)[key] = class {};
|
||||
} else {
|
||||
delete (globalThis as unknown as Record<string, unknown>)[key];
|
||||
}
|
||||
}
|
||||
|
||||
describe('webkit', () => {
|
||||
afterEach(() => stubWebKit(false));
|
||||
|
||||
describe('supportsWebKitAirPlay', () => {
|
||||
it('returns true when the WebKit availability event is present', () => {
|
||||
stubWebKit(true);
|
||||
expect(supportsWebKitAirPlay()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when absent', () => {
|
||||
stubWebKit(false);
|
||||
expect(supportsWebKitAirPlay()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isWebKitAirPlayCapable', () => {
|
||||
it('returns true when supported and the media exposes the AirPlay flag', () => {
|
||||
stubWebKit(true);
|
||||
const media = { webkitCurrentPlaybackTargetIsWireless: false } as unknown as EventTarget;
|
||||
expect(isWebKitAirPlayCapable(media)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when WebKit is unsupported', () => {
|
||||
stubWebKit(false);
|
||||
const media = { webkitCurrentPlaybackTargetIsWireless: false } as unknown as EventTarget;
|
||||
expect(isWebKitAirPlayCapable(media)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false when the media lacks the AirPlay flag', () => {
|
||||
stubWebKit(true);
|
||||
expect(isWebKitAirPlayCapable(new EventTarget())).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
/** WebKit-only addition to HTMLMediaElement exposing the active AirPlay flag. */
|
||||
export interface WebKitAirPlayMedia extends HTMLMediaElement {
|
||||
readonly webkitCurrentPlaybackTargetIsWireless: boolean;
|
||||
}
|
||||
|
||||
/** WebKit presentation mode values for iOS Safari. */
|
||||
export type WebKitPresentationMode = 'inline' | 'fullscreen' | 'picture-in-picture';
|
||||
|
||||
/** Extended HTMLVideoElement with WebKit vendor APIs. */
|
||||
export interface WebKitVideoElement extends HTMLVideoElement {
|
||||
/** Current WebKit presentation mode (iOS Safari). */
|
||||
webkitPresentationMode?: WebKitPresentationMode;
|
||||
/** Set WebKit presentation mode (iOS Safari). */
|
||||
webkitSetPresentationMode?: (mode: WebKitPresentationMode) => void;
|
||||
}
|
||||
|
||||
/** Extended Element with WebKit fullscreen vendor API. */
|
||||
export interface WebKitFullscreenElement extends Element {
|
||||
/** Request fullscreen using WebKit API (Safari). */
|
||||
webkitRequestFullscreen?: () => Promise<void>;
|
||||
}
|
||||
|
||||
/** Extended Document with WebKit fullscreen vendor APIs. */
|
||||
export interface WebKitDocument extends Document {
|
||||
/** Current fullscreen element (WebKit). */
|
||||
webkitFullscreenElement?: Element | null;
|
||||
/** Whether fullscreen is enabled (WebKit). */
|
||||
webkitFullscreenEnabled?: boolean;
|
||||
/** Exit fullscreen (WebKit). */
|
||||
webkitExitFullscreen?: () => Promise<void>;
|
||||
}
|
||||
|
||||
/** WebKit-specific AirPlay availability event payload (not in lib.dom). */
|
||||
export type WebkitAvailabilityEvent = Event & { availability: 'available' | 'not-available' };
|
||||
|
||||
/** Whether WebKit's AirPlay APIs are present in this realm (Safari macOS/iOS). */
|
||||
export function supportsWebKitAirPlay(): boolean {
|
||||
return 'WebKitPlaybackTargetAvailabilityEvent' in globalThis;
|
||||
}
|
||||
|
||||
/** Whether `media` exposes WebKit's AirPlay APIs. */
|
||||
export function isWebKitAirPlayCapable(media: EventTarget): media is WebKitAirPlayMedia {
|
||||
return supportsWebKitAirPlay() && 'webkitCurrentPlaybackTargetIsWireless' in media;
|
||||
}
|
||||
Reference in New Issue
Block a user