Files
pole-book/server/node_modules/media-chrome/dist/media-store/media-store.js

281 lines
12 KiB
JavaScript

import {
stateMediator as defaultStateMediator,
prepareStateOwners
} from "./state-mediator.js";
import { areValuesEq } from "./util.js";
import { requestMap as defaultRequestMap } from "./request-map.js";
const createMediaStore = ({
media,
fullscreenElement,
documentElement,
stateMediator = defaultStateMediator,
requestMap = defaultRequestMap,
options = {},
monitorStateOwnersOnlyWithSubscriptions = true
}) => {
const callbacks = [];
const stateOwners = {
// Spreading options here since folks should not rely on holding onto references
// for any app-level logic wrt options.
options: { ...options }
};
let state = Object.freeze({
mediaPreviewTime: void 0,
mediaPreviewImage: void 0,
mediaPreviewCoords: void 0,
mediaPreviewChapter: void 0
});
const updateState = (nextStateDelta) => {
if (nextStateDelta == void 0)
return;
if (areValuesEq(nextStateDelta, state)) {
return;
}
state = Object.freeze({
...state,
...nextStateDelta
});
callbacks.forEach((cb) => cb(state));
};
const updateStateFromFacade = () => {
const nextState = Object.entries(stateMediator).reduce(
(nextState2, [stateName, { get }]) => {
nextState2[stateName] = get(stateOwners);
return nextState2;
},
{}
);
updateState(nextState);
};
const stateUpdateHandlers = {};
let nextStateOwners = void 0;
const updateStateOwners = async (nextStateOwnersDelta, nextSubscriberCount) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
const pendingUpdate = !!nextStateOwners;
nextStateOwners = {
...stateOwners,
...nextStateOwners != null ? nextStateOwners : {},
...nextStateOwnersDelta
};
if (pendingUpdate)
return;
await prepareStateOwners(...Object.values(nextStateOwnersDelta));
const shouldTeardownFromSubscriberCount = callbacks.length > 0 && nextSubscriberCount === 0 && monitorStateOwnersOnlyWithSubscriptions;
const mediaChanged = stateOwners.media !== nextStateOwners.media;
const textTracksChanged = ((_a = stateOwners.media) == null ? void 0 : _a.textTracks) !== ((_b = nextStateOwners.media) == null ? void 0 : _b.textTracks);
const videoRenditionsChanged = ((_c = stateOwners.media) == null ? void 0 : _c.videoRenditions) !== ((_d = nextStateOwners.media) == null ? void 0 : _d.videoRenditions);
const audioTracksChanged = ((_e = stateOwners.media) == null ? void 0 : _e.audioTracks) !== ((_f = nextStateOwners.media) == null ? void 0 : _f.audioTracks);
const remoteChanged = ((_g = stateOwners.media) == null ? void 0 : _g.remote) !== ((_h = nextStateOwners.media) == null ? void 0 : _h.remote);
const rootNodeChanged = stateOwners.documentElement !== nextStateOwners.documentElement;
const teardownMedia = !!stateOwners.media && (mediaChanged || shouldTeardownFromSubscriberCount);
const teardownTextTracks = !!((_i = stateOwners.media) == null ? void 0 : _i.textTracks) && (textTracksChanged || shouldTeardownFromSubscriberCount);
const teardownVideoRenditions = !!((_j = stateOwners.media) == null ? void 0 : _j.videoRenditions) && (videoRenditionsChanged || shouldTeardownFromSubscriberCount);
const teardownAudioTracks = !!((_k = stateOwners.media) == null ? void 0 : _k.audioTracks) && (audioTracksChanged || shouldTeardownFromSubscriberCount);
const teardownRemote = !!((_l = stateOwners.media) == null ? void 0 : _l.remote) && (remoteChanged || shouldTeardownFromSubscriberCount);
const teardownRootNode = !!stateOwners.documentElement && (rootNodeChanged || shouldTeardownFromSubscriberCount);
const teardownSomething = teardownMedia || teardownTextTracks || teardownVideoRenditions || teardownAudioTracks || teardownRemote || teardownRootNode;
const shouldSetupFromSubscriberCount = callbacks.length === 0 && nextSubscriberCount === 1 && monitorStateOwnersOnlyWithSubscriptions;
const setupMedia = !!nextStateOwners.media && (mediaChanged || shouldSetupFromSubscriberCount);
const setupTextTracks = !!((_m = nextStateOwners.media) == null ? void 0 : _m.textTracks) && (textTracksChanged || shouldSetupFromSubscriberCount);
const setupVideoRenditions = !!((_n = nextStateOwners.media) == null ? void 0 : _n.videoRenditions) && (videoRenditionsChanged || shouldSetupFromSubscriberCount);
const setupAudioTracks = !!((_o = nextStateOwners.media) == null ? void 0 : _o.audioTracks) && (audioTracksChanged || shouldSetupFromSubscriberCount);
const setupRemote = !!((_p = nextStateOwners.media) == null ? void 0 : _p.remote) && (remoteChanged || shouldSetupFromSubscriberCount);
const setupRootNode = !!nextStateOwners.documentElement && (rootNodeChanged || shouldSetupFromSubscriberCount);
const setupSomething = setupMedia || setupTextTracks || setupVideoRenditions || setupAudioTracks || setupRemote || setupRootNode;
const somethingToDo = teardownSomething || setupSomething;
if (!somethingToDo) {
Object.entries(nextStateOwners).forEach(
([stateOwnerName, stateOwner]) => {
stateOwners[stateOwnerName] = stateOwner;
}
);
updateStateFromFacade();
nextStateOwners = void 0;
return;
}
Object.entries(stateMediator).forEach(
([
stateName,
{
get,
mediaEvents = [],
textTracksEvents = [],
videoRenditionsEvents = [],
audioTracksEvents = [],
remoteEvents = [],
rootEvents = [],
stateOwnersUpdateHandlers = []
}
]) => {
if (!stateUpdateHandlers[stateName]) {
stateUpdateHandlers[stateName] = {};
}
const handler = (event) => {
const nextValue = get(stateOwners, event);
updateState({ [stateName]: nextValue });
};
let prevHandler;
prevHandler = stateUpdateHandlers[stateName].mediaEvents;
mediaEvents.forEach((eventType) => {
if (prevHandler && teardownMedia) {
stateOwners.media.removeEventListener(eventType, prevHandler);
stateUpdateHandlers[stateName].mediaEvents = void 0;
}
if (setupMedia) {
nextStateOwners.media.addEventListener(eventType, handler);
stateUpdateHandlers[stateName].mediaEvents = handler;
}
});
prevHandler = stateUpdateHandlers[stateName].textTracksEvents;
textTracksEvents.forEach((eventType) => {
var _a2, _b2;
if (prevHandler && teardownTextTracks) {
(_a2 = stateOwners.media.textTracks) == null ? void 0 : _a2.removeEventListener(
eventType,
prevHandler
);
stateUpdateHandlers[stateName].textTracksEvents = void 0;
}
if (setupTextTracks) {
(_b2 = nextStateOwners.media.textTracks) == null ? void 0 : _b2.addEventListener(
eventType,
handler
);
stateUpdateHandlers[stateName].textTracksEvents = handler;
}
});
prevHandler = stateUpdateHandlers[stateName].videoRenditionsEvents;
videoRenditionsEvents.forEach((eventType) => {
var _a2, _b2;
if (prevHandler && teardownVideoRenditions) {
(_a2 = stateOwners.media.videoRenditions) == null ? void 0 : _a2.removeEventListener(
eventType,
prevHandler
);
stateUpdateHandlers[stateName].videoRenditionsEvents = void 0;
}
if (setupVideoRenditions) {
(_b2 = nextStateOwners.media.videoRenditions) == null ? void 0 : _b2.addEventListener(
eventType,
handler
);
stateUpdateHandlers[stateName].videoRenditionsEvents = handler;
}
});
prevHandler = stateUpdateHandlers[stateName].audioTracksEvents;
audioTracksEvents.forEach((eventType) => {
var _a2, _b2;
if (prevHandler && teardownAudioTracks) {
(_a2 = stateOwners.media.audioTracks) == null ? void 0 : _a2.removeEventListener(
eventType,
prevHandler
);
stateUpdateHandlers[stateName].audioTracksEvents = void 0;
}
if (setupAudioTracks) {
(_b2 = nextStateOwners.media.audioTracks) == null ? void 0 : _b2.addEventListener(
eventType,
handler
);
stateUpdateHandlers[stateName].audioTracksEvents = handler;
}
});
prevHandler = stateUpdateHandlers[stateName].remoteEvents;
remoteEvents.forEach((eventType) => {
var _a2, _b2;
if (prevHandler && teardownRemote) {
(_a2 = stateOwners.media.remote) == null ? void 0 : _a2.removeEventListener(
eventType,
prevHandler
);
stateUpdateHandlers[stateName].remoteEvents = void 0;
}
if (setupRemote) {
(_b2 = nextStateOwners.media.remote) == null ? void 0 : _b2.addEventListener(eventType, handler);
stateUpdateHandlers[stateName].remoteEvents = handler;
}
});
prevHandler = stateUpdateHandlers[stateName].rootEvents;
rootEvents.forEach((eventType) => {
if (prevHandler && teardownRootNode) {
stateOwners.documentElement.removeEventListener(
eventType,
prevHandler
);
stateUpdateHandlers[stateName].rootEvents = void 0;
}
if (setupRootNode) {
nextStateOwners.documentElement.addEventListener(
eventType,
handler
);
stateUpdateHandlers[stateName].rootEvents = handler;
}
});
const prevHandlerTeardown = stateUpdateHandlers[stateName].stateOwnersUpdateHandlers;
stateOwnersUpdateHandlers.forEach((fn) => {
if (prevHandlerTeardown && teardownSomething) {
prevHandlerTeardown();
}
if (setupSomething) {
stateUpdateHandlers[stateName].stateOwnersUpdateHandlers = fn(
handler,
nextStateOwners
);
}
});
}
);
Object.entries(nextStateOwners).forEach(([stateOwnerName, stateOwner]) => {
stateOwners[stateOwnerName] = stateOwner;
});
updateStateFromFacade();
nextStateOwners = void 0;
};
updateStateOwners({ media, fullscreenElement, documentElement, options });
return {
// note that none of these cases directly interact with the media element, root node, full screen element, etc.
// note these "actions" could just be the events if we wanted, especially if we normalize on "detail" for
// any payload-relevant values
// This is roughly equivalent to our used to be in our state requests dictionary object, though much of the
// "heavy lifting" is now moved into the facade `set()`
dispatch(action) {
const { type, detail } = action;
if (requestMap[type]) {
updateState(requestMap[type](stateMediator, stateOwners, action));
return;
}
if (type === "mediaelementchangerequest") {
updateStateOwners({ media: detail });
} else if (type === "fullscreenelementchangerequest") {
updateStateOwners({ fullscreenElement: detail });
} else if (type === "documentelementchangerequest") {
updateStateOwners({ documentElement: detail });
} else if (type === "optionschangerequest") {
Object.entries(detail != null ? detail : {}).forEach(([optionName, optionValue]) => {
stateOwners.options[optionName] = optionValue;
});
}
},
getState() {
return state;
},
subscribe(callback) {
updateStateOwners({}, callbacks.length + 1);
callbacks.push(callback);
callback(state);
return () => {
const idx = callbacks.indexOf(callback);
if (idx >= 0) {
updateStateOwners({}, callbacks.length - 1);
callbacks.splice(idx, 1);
}
};
}
};
};
var media_store_default = createMediaStore;
export {
media_store_default as default
};