first commit
Some checks failed
Build / run (push) Has been cancelled

This commit is contained in:
maher
2025-10-29 11:42:25 +01:00
commit 703f50a09d
4595 changed files with 385164 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
import {StateCreator} from 'zustand';
import {
PlayerState,
ProviderListeners,
} from '@common/player/state/player-state';
import {PipAdapter} from '@common/player/state/pip/pip-adapter';
import {createChromePipAdapter} from '@common/player/state/pip/chrome-pip-adapter';
import {createSafariPipAdapter} from '@common/player/state/pip/safari-pip-adapter';
export interface PipSlice {
isPip: boolean;
canPip: boolean;
enterPip: () => void;
exitPip: () => void;
togglePip: () => void;
initPip: () => void;
destroyPip: () => void;
}
type BaseSliceCreator = StateCreator<
PipSlice & PlayerState,
[['zustand/immer', unknown]],
[],
PipSlice
>;
type StoreLice = BaseSliceCreator extends (...a: infer U) => infer R
? (...a: [...U, Set<Partial<ProviderListeners>>]) => R
: never;
const adapterFactories = [createChromePipAdapter, createSafariPipAdapter];
export const createPipSlice: StoreLice = (set, get) => {
let subscription: () => void | undefined;
let adapters: PipAdapter[] = [];
const onPipChange = () => {
set({isPip: adapters.some(a => a.isPip())});
};
const isSupported = (): boolean => {
if (get().providerName !== 'htmlVideo') {
return false;
}
return adapters.some(adapter => adapter.isSupported());
};
return {
isPip: false,
canPip: false,
enterPip: async () => {
if (get().isPip || !isSupported()) return;
await adapters.find(a => a.isSupported())?.enter();
},
exitPip: async () => {
if (!get().isPip) return;
await adapters.find(a => a.isSupported())?.exit();
},
togglePip: () => {
if (get().isPip) {
get().exitPip();
} else {
get().enterPip();
}
},
initPip: () => {
subscription = get().subscribe({
providerReady: ({el}) => {
// when changing adapters, remove previous adapter events and exit pip
adapters.every(a => a.unbindEvents());
if (get().isPip) {
adapters.every(a => a.exit());
}
// create new adapters, and if pip is supported on at least one, bind events
adapters = adapterFactories.map(factory =>
factory(el as HTMLVideoElement, onPipChange)
);
const canPip = isSupported();
if (canPip) {
adapters.every(a => a.bindEvents());
}
set({canPip});
},
});
},
destroyPip: () => {
get().exitPip();
subscription?.();
},
};
};