mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 06:12:18 +00:00
72 lines
2.0 KiB
JavaScript
72 lines
2.0 KiB
JavaScript
export { LOCAL_WEB_VOICE, localWebVoiceRequested } from './localWebFlag.js';
|
|
|
|
const cancelled = () =>
|
|
new DOMException('On-device voice was stopped', 'AbortError');
|
|
|
|
/**
|
|
* Session adapter factory for the on-device tier that loads the provider on
|
|
* first use, so pages without the flag never download it. A stop issued
|
|
* while the module loads cancels the pending start; after removal the
|
|
* provider is never constructed and every later start is refused.
|
|
*/
|
|
export function createLocalWebSessionLoader(
|
|
hooks,
|
|
{
|
|
load = () =>
|
|
Promise.all([
|
|
import('./localWebSession.js'),
|
|
import('../../ui/styles/local-voice.css'),
|
|
]).then(([module]) => module),
|
|
} = {},
|
|
) {
|
|
let adapter = null;
|
|
let bound = false;
|
|
let disposed = false;
|
|
let stopEpoch = 0;
|
|
const isDisposed = () => disposed || Boolean(hooks.signal?.aborted);
|
|
const ready = Promise.resolve()
|
|
.then(load)
|
|
.then((module) => {
|
|
if (isDisposed()) return null;
|
|
adapter = module.createLocalWebSession(hooks);
|
|
if (bound) adapter.bindControls();
|
|
return adapter;
|
|
});
|
|
ready.catch(() => {});
|
|
return {
|
|
capabilities: { costControls: false, pushToTalk: true, local: true },
|
|
get local() {
|
|
return adapter?.local || null;
|
|
},
|
|
ready,
|
|
async start(options) {
|
|
if (isDisposed()) throw cancelled();
|
|
const epoch = stopEpoch;
|
|
const loaded = await ready;
|
|
if (!loaded || isDisposed()) throw cancelled();
|
|
if (epoch !== stopEpoch) return undefined;
|
|
return loaded.start(options);
|
|
},
|
|
stop(options = {}) {
|
|
stopEpoch++;
|
|
if (options.removeUi) disposed = true;
|
|
adapter?.stop(options);
|
|
},
|
|
sendText(text) {
|
|
if (isDisposed()) return false;
|
|
void ready.then((loaded) => {
|
|
if (loaded && !isDisposed()) loaded.sendText(text);
|
|
});
|
|
return true;
|
|
},
|
|
sendMapEvent() {
|
|
return false;
|
|
},
|
|
ignoreButtonClick: () => Boolean(adapter?.ignoreButtonClick()),
|
|
bindControls() {
|
|
bound = true;
|
|
if (!isDisposed()) adapter?.bindControls();
|
|
},
|
|
};
|
|
}
|