Skip to content

Commit

Permalink
refactor(player): private fields and methods
Browse files Browse the repository at this point in the history
  • Loading branch information
WakelessSloth56 committed Mar 13, 2024
1 parent 491c510 commit 02c2425
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 84 deletions.
62 changes: 44 additions & 18 deletions src/player.main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ interface PlayerOptions extends StrAnyKV {
class Player {
readonly version = '{version}';
options: PlayerOptions;
private readonly metadata: PlayerMetadata;
readonly #metadata: PlayerMetadata;
readonly title: string;
readonly videoUrl: string;
readonly video: HTMLVideoElement;
private overHour: boolean;
#overHour: boolean;
readonly style: HTMLStyleElement;
readonly container: HTMLDivElement;
readonly danmakuUrl: string;
commentManager;
readonly subtitleUrl: string;
subtitleManager: SubtitleManager;
private constructed: boolean;
#constructed: boolean;
elements: StrGenKV<HTMLElement> = {};
_dyn: StrAnyKV = {};
temp: StrAnyKV = {};

constructor(
container: HTMLDivElement,
Expand All @@ -31,17 +32,18 @@ class Player {
options: PlayerOptions
) {
console.log('Version:', this.version);
this.metadata = metadata;
this.#metadata = metadata;
this.options = options;
container.classList.add('player');
container.tabIndex = 10;
{
this.title = title;
this.videoUrl = videoUrl;
const video = document.createElement('video');
container.appendChild(video);
video.src = videoUrl;
this.video = video;
this.overHour = false;
this.#overHour = false;
}
{
const style = document.createElement('style');
Expand All @@ -52,26 +54,28 @@ class Player {
this.danmakuUrl = danmakuUrl;
if (0) this.commentManager = new CommentManager(); // for type intellisense
this.subtitleUrl = subtitleUrl;
this.__bindElements();
this.__bindEvents();
this.#bindElements();
this.#bindEvents();
{
this.options.autoPlay ? this.play() : this.pause();
this.options.muted ? this.mute() : this.unmute();
this.options.fullscreen ? this.requestFullscreen() : this.setContainerData('fullscreen', false);
}
this.constructed = true;
this.#constructed = true;
if (this.options.autoPlay) this.toast('Autoplay');
this.focus();
}
private __bindElements() {
for (const data of this.metadata.elements) {

#bindElements() {
for (const data of this.#metadata.elements) {
appendChild(this.container, data.create(this));
}
}
private __bindEvents() {

#bindEvents() {
this.onVideoEvent('loadedmetadata', () => {
this.setContainerData('paused', this.video.paused);
this.overHour = this.video.duration >= 60 * 60;
this.#overHour = this.video.duration >= 60 * 60;
});
this.onVideoEvent('play', () => this.setContainerData('paused', this.video.paused));
this.onVideoEvent('pause', () => this.setContainerData('paused', this.video.paused));
Expand All @@ -93,100 +97,122 @@ class Player {
);
}).observe(this.video);
}
bindMetaEvent(this.container, this.metadata.playerEvent, this);
bindMetaEvent(this.video, this.metadata.videoEvent, this, this.video);
bindMetaEvent(this.container, this.#metadata.playerEvent, this);
bindMetaEvent(this.video, this.#metadata.videoEvent, this, this.video);
}

focus() {
this.container.focus();
}

setContainerData(key: string, value: any) {
this.container.dataset[key] = value;
}

getContainerData(key: string) {
return this.container.dataset[key];
}

onVideoEvent(type: string, listener: EventListenerOrEventListenerObject) {
this.video.addEventListener(type, listener);
}

onPlayerEvent(type: string, listener: EventListenerOrEventListenerObject) {
this.container.addEventListener(type, listener);
}

firePlayerEvent(type: string, detail?: any) {
this.container.dispatchEvent(new CustomEvent(type, detail ? { detail: detail } : null));
}

toast(html: string) {
if (this.constructed) {
if (this.#constructed) {
this.firePlayerEvent('toast', { content: html });
}
}

fCurrentTime(alwaysHour?: boolean) {
return fTime(this.video.currentTime, alwaysHour === undefined ? this.overHour : alwaysHour);
return fTime(this.video.currentTime, alwaysHour === undefined ? this.#overHour : alwaysHour);
}

seek(time: number) {
const fixedTime = clamp(time, 0, this.video.duration);
this.toast(`Seek: ${fTime(fixedTime, this.overHour)} / ${fTime(this.video.duration)}`);
this.toast(`Seek: ${fTime(fixedTime, this.#overHour)} / ${fTime(this.video.duration)}`);
this.video.currentTime = fixedTime;
}

seekPercent(percent: number) {
this.seek(this.video.duration * percent);
}

skip(time: number) {
this.seek(this.video.currentTime + time);
}

play() {
this.video.play().catch((e) => alert(e));
this.toast('Play');
}

pause() {
this.video.pause();
this.toast('Pause');
}

togglePlay() {
if (this.video.paused) {
this.play();
} else {
this.pause();
}
}

mute() {
this.video.muted = true;
this.setContainerData('muted', true);
this.firePlayerEvent('mute');
this.toast('Mute');
}

unmute() {
this.video.muted = false;
this.setContainerData('muted', false);
this.firePlayerEvent('unmute');
this.toast('Unmute');
}

toggleMute() {
if (this.video.muted) {
this.unmute();
} else {
this.mute();
}
}

requestFullscreen() {
this.container.requestFullscreen();
this.focus();
}

exitFullscreen() {
document.exitFullscreen().catch(() => {});
this.focus();
}

toggleFullscreen() {
if (this.getContainerData('fullscreen') === 'true') {
this.exitFullscreen();
} else {
this.requestFullscreen();
}
}

setVolume(volume: number) {
const fixedVolume = clamp(volume, 0, 1);
this.video.volume = fixedVolume;
this.toast(`Volume: ${Math.round(fixedVolume * 100)}%`);
}

adjustVolume(volume: number) {
if (!this.video.muted) {
this.setVolume(this.video.volume + volume);
Expand Down
83 changes: 42 additions & 41 deletions src/player.metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,35 @@ type ElementVideoMetaEvents<T extends HTMLTagNames> = MetaEvents<
>;

function bindMetaEvent<F extends AnyFunction>(target: HTMLElement, listeners: MetaEvents<F>, ...params: any[]) {
const _l = typeof listeners === 'function' ? listeners() : listeners;
if (_l) {
bindEvents(target, _l, params);
const l = typeof listeners === 'function' ? listeners() : listeners;
if (l) {
bindEvents(target, l, params);
}
}

class EDC<T extends HTMLTagNames> {
private tag: T;
private name: string;
private _condition: (player: Player) => boolean;
private _css: (data: EDC<T>) => string;
_attrs: StrKV = {};
private _html: string;
private _selfEvents: ElementMetaEvents<T>;
private _playerEvents: ElementMetaEvents<T>;
private _videoEvent: ElementVideoMetaEvents<T>;
private _childrenBuilders: EDC<any>[] = [];
private _children: HTMLElement[] = [];
#tag: T;
#name: string;
#condition: (player: Player) => boolean;
#css: (data: EDC<T>) => string;
#attrs: StrKV = {};
#html: string;
#selfEvents: ElementMetaEvents<T>;
#playerEvents: ElementMetaEvents<T>;
#videoEvent: ElementVideoMetaEvents<T>;
#childrenBuilders: EDC<any>[] = [];
#children: HTMLElement[] = [];

constructor(tag: T, name?: string) {
this.tag = tag;
this.name = name;
this.#tag = tag;
this.#name = name;
}
attrs(attrs: StrKV) {
this._attrs = { ...this._attrs, ...attrs };
this.#attrs = { ...this.#attrs, ...attrs };
return this;
}
attr(k: string, v: string) {
this._attrs[k] = v;
this.#attrs[k] = v;
return this;
}
title(title: string) {
Expand All @@ -51,62 +52,62 @@ class EDC<T extends HTMLTagNames> {
children(...c: (EDC<any> | HTMLElement)[]) {
for (const e of c) {
if (e instanceof HTMLElement) {
this._children.push(e);
this.#children.push(e);
} else {
this._childrenBuilders.push(e);
this.#childrenBuilders.push(e);
}
}
return this;
}
condition(f: (player: Player) => boolean) {
this._condition = f;
this.#condition = f;
return this;
}
css(sup: (data: EDC<T>) => string) {
this._css = sup;
css(sup: () => string) {
this.#css = sup;
return this;
}
html(html: string) {
this._html = html;
this.#html = html;
return this;
}
selfEvents(map: ElementMetaEvents<T>) {
this._selfEvents = map;
this.#selfEvents = map;
return this;
}
playerEvents(map: ElementMetaEvents<T>) {
this._playerEvents = map;
this.#playerEvents = map;
return this;
}
videoEvents(map: ElementVideoMetaEvents<T>) {
this._videoEvent = map;
this.#videoEvent = map;
return this;
}
create(player: Player): HTMLElementTagNameMap[T] | null {
if (this._condition && !this._condition(player)) {
if (this.#condition && !this.#condition(player)) {
return null;
}
const element = document.createElement(this.tag);
for (const [key, value] of Object.entries(this._attrs)) {
const element = document.createElement(this.#tag);
for (const [key, value] of Object.entries(this.#attrs)) {
element.setAttribute(key, value);
}
if (this._html) {
element.innerHTML = this._html;
if (this.#html) {
element.innerHTML = this.#html;
}
if (this._css) {
player.style.textContent += this._css(this);
if (this.#css) {
player.style.textContent += this.#css(this);
}
bindMetaEvent(element, this._selfEvents, player, element);
bindMetaEvent(player.container, this._playerEvents, player, element);
bindMetaEvent(player.video, this._videoEvent, player, element, player.video);
for (const childBulder of this._childrenBuilders) {
bindMetaEvent(element, this.#selfEvents, player, element);
bindMetaEvent(player.container, this.#playerEvents, player, element);
bindMetaEvent(player.video, this.#videoEvent, player, element, player.video);
for (const childBulder of this.#childrenBuilders) {
appendChild(element, childBulder.create(player));
}
for (const childElement of this._children) {
for (const childElement of this.#children) {
appendChild(element, childElement);
}
if (this.name) {
player.elements[this.name] = element;
if (this.#name) {
player.elements[this.#name] = element;
}
element.dispatchEvent(new CustomEvent('create'));
return element;
Expand Down
Loading

0 comments on commit 02c2425

Please sign in to comment.