mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Add April Fools easter egg
Summary: What happens when you type "rr" instead of "r" in an anchor link's row number? Test Plan: Browser tests. Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D3829
This commit is contained in:
115
app/client/ui/YouTubePlayer.ts
Normal file
115
app/client/ui/YouTubePlayer.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import {get as getBrowserGlobals} from 'app/client/lib/browserGlobals';
|
||||
import {waitObs} from 'app/common/gutil';
|
||||
import {Disposable, dom, DomElementArg} from 'grainjs';
|
||||
import ko from 'knockout';
|
||||
|
||||
export interface Player {
|
||||
playVideo(): void;
|
||||
pauseVideo(): void;
|
||||
stopVideo(): void;
|
||||
mute(): void;
|
||||
unMute(): void;
|
||||
setVolume(volume: number): void;
|
||||
}
|
||||
|
||||
export interface PlayerOptions {
|
||||
height?: string;
|
||||
width?: string;
|
||||
origin?: string;
|
||||
playerVars?: PlayerVars;
|
||||
onPlayerReady?(player: Player): void
|
||||
onPlayerStateChange?(player: Player, event: PlayerStateChangeEvent): void;
|
||||
}
|
||||
|
||||
export interface PlayerVars {
|
||||
controls?: 0 | 1;
|
||||
disablekb?: 0 | 1;
|
||||
fs?: 0 | 1;
|
||||
iv_load_policy?: 1 | 3;
|
||||
modestbranding?: 0 | 1;
|
||||
}
|
||||
|
||||
export interface PlayerStateChangeEvent {
|
||||
data: PlayerState;
|
||||
}
|
||||
|
||||
export enum PlayerState {
|
||||
Unstarted = -1,
|
||||
Ended = 0,
|
||||
Playing = 1,
|
||||
Paused = 2,
|
||||
Buffering = 3,
|
||||
VideoCued = 5,
|
||||
}
|
||||
|
||||
const G = getBrowserGlobals('document', 'window');
|
||||
|
||||
/**
|
||||
* Wrapper component for the YouTube IFrame Player API.
|
||||
*
|
||||
* Fetches the JavaScript code for the API if needed, and creates an iframe that
|
||||
* points to a YouTube video with the specified id.
|
||||
*
|
||||
* For more documentation, see https://developers.google.com/youtube/iframe_api_reference.
|
||||
*/
|
||||
export class YouTubePlayer extends Disposable {
|
||||
private _domArgs: DomElementArg[];
|
||||
private _isLoading: ko.Observable<boolean> = ko.observable(true);
|
||||
private _playerId = `youtube-player-${this._videoId}`;
|
||||
private _player: Player;
|
||||
|
||||
constructor(
|
||||
private _videoId: string,
|
||||
private _options: PlayerOptions,
|
||||
...domArgs: DomElementArg[]
|
||||
) {
|
||||
super();
|
||||
|
||||
this._domArgs = domArgs;
|
||||
|
||||
if (!G.window.YT) {
|
||||
const tag = document.createElement('script');
|
||||
|
||||
tag.src = 'https://www.youtube.com/iframe_api';
|
||||
const firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag?.parentNode?.insertBefore(tag, firstScriptTag);
|
||||
|
||||
G.window.onYouTubeIframeAPIReady = () => this._handleYouTubeIframeAPIReady();
|
||||
} else {
|
||||
setTimeout(() => this._handleYouTubeIframeAPIReady(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public isLoaded() {
|
||||
return waitObs(this._isLoading, (val) => !val);
|
||||
}
|
||||
|
||||
public play() {
|
||||
this._player.playVideo();
|
||||
}
|
||||
|
||||
public setVolume(volume: number) {
|
||||
this._player.setVolume(volume);
|
||||
}
|
||||
|
||||
public buildDom() {
|
||||
return dom('div', {id: this._playerId}, ...this._domArgs);
|
||||
}
|
||||
|
||||
private _handleYouTubeIframeAPIReady() {
|
||||
const {onPlayerReady, onPlayerStateChange, playerVars, ...otherOptions} = this._options;
|
||||
this._player = new G.window.YT.Player(this._playerId, {
|
||||
videoId: this._videoId,
|
||||
playerVars,
|
||||
events: {
|
||||
onReady: () => {
|
||||
this._isLoading(false);
|
||||
onPlayerReady?.(this._player);
|
||||
},
|
||||
onStateChange: (event: PlayerStateChangeEvent) =>
|
||||
onPlayerStateChange?.(this._player, event),
|
||||
},
|
||||
...otherOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user