UNPKG

@corti/dictation-web

Version:
331 lines 20.2 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _DictationRecordingButton_instances, _DictationRecordingButton_mediaController, _DictationRecordingButton_dictationController, _DictationRecordingButton_keybindingController, _DictationRecordingButton_closeConnectionOnInit, _DictationRecordingButton_processing, _DictationRecordingButton_connection, _DictationRecordingButton_handleClick, _DictationRecordingButton_handleWebSocketMessage, _DictationRecordingButton_handleWebSocketError, _DictationRecordingButton_handleWebSocketClose, _DictationRecordingButton_dispatchRecordingStateChanged, _DictationRecordingButton_handleStart, _DictationRecordingButton_handleStop; import { consume } from "@lit/context"; import { html, LitElement, } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { AUDIO_CHUNK_INTERVAL_MS } from "../constants.js"; import { accessTokenContext, authConfigContext, debugDisplayAudioContext, dictationConfigContext, pushToTalkKeybindingContext, recordingStateContext, regionContext, selectedDeviceContext, socketProxyContext, socketUrlContext, tenantNameContext, toggleToTalkKeybindingContext, } from "../contexts/dictation-context.js"; import { DictationController, } from "../controllers/dictation-controller.js"; import { KeybindingController } from "../controllers/keybinding-controller.js"; import { MediaController } from "../controllers/media-controller.js"; import ButtonStyles from "../styles/buttons.js"; import RecordingButtonStyles from "../styles/recording-button.js"; import { audioLevelChangedEvent, commandEvent, deltaUsageEvent, errorEvent, networkActivityEvent, recordingStateChangedEvent, streamClosedEvent, transcriptEvent, usageEvent, } from "../utils/events.js"; import "./audio-visualiser.js"; import "../icons/icons.js"; let DictationRecordingButton = class DictationRecordingButton extends LitElement { constructor() { super(...arguments); _DictationRecordingButton_instances.add(this); this._recordingState = "stopped"; this.allowButtonFocus = false; _DictationRecordingButton_mediaController.set(this, new MediaController(this)); _DictationRecordingButton_dictationController.set(this, new DictationController(this)); _DictationRecordingButton_keybindingController.set(this, new KeybindingController(this)); _DictationRecordingButton_closeConnectionOnInit.set(this, false); _DictationRecordingButton_processing.set(this, false); _DictationRecordingButton_connection.set(this, "CLOSED"); _DictationRecordingButton_handleWebSocketMessage.set(this, (message) => { switch (message.type) { case "CONFIG_DENIED": this.dispatchEvent(errorEvent(`Config denied: ${message.reason ?? "Unknown reason"}`)); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); break; case "CONFIG_TIMEOUT": this.dispatchEvent(errorEvent("Config timeout")); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); break; case "transcript": this.dispatchEvent(transcriptEvent(message)); break; case "command": this.dispatchEvent(commandEvent(message)); break; case "usage": this.dispatchEvent(usageEvent(message)); break; case "delta_usage": this.dispatchEvent(deltaUsageEvent(message)); break; case "error": this.dispatchEvent(errorEvent(message.error)); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); break; case "flushed": if (this._recordingState === "stopped" || this._recordingState === "stopping") { __classPrivateFieldSet(this, _DictationRecordingButton_processing, false, "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, this._recordingState); } break; } }); _DictationRecordingButton_handleWebSocketError.set(this, (error) => { this.dispatchEvent(errorEvent("Socket error: " + error.message)); __classPrivateFieldSet(this, _DictationRecordingButton_processing, false, "f"); __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CLOSED", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); }); _DictationRecordingButton_handleWebSocketClose.set(this, (event) => { // When we already have new socket opened if (__classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").isConnectionOpen() || __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").isConnecting()) { return; } __classPrivateFieldSet(this, _DictationRecordingButton_processing, false, "f"); __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CLOSED", "f"); this.dispatchEvent(streamClosedEvent(event)); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, this._recordingState); }); } update(changedProperties) { if (changedProperties.has("_recordingState") && this._recordingState === "recording" && __classPrivateFieldGet(this, _DictationRecordingButton_closeConnectionOnInit, "f")) { __classPrivateFieldSet(this, _DictationRecordingButton_closeConnectionOnInit, false, "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); } super.update(changedProperties); } startRecording() { if (this._recordingState !== "stopped") { return; } __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStart).call(this); } stopRecording() { if (this._recordingState === "stopped" || this._recordingState === "stopping") { return; } if (this._recordingState === "initializing") { __classPrivateFieldSet(this, _DictationRecordingButton_closeConnectionOnInit, true, "f"); return; } __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); } toggleRecording() { if (this._recordingState === "stopped") { this.startRecording(); } else if (this._recordingState === "recording") { this.stopRecording(); } } async openConnection() { if (this._recordingState !== "stopped" || __classPrivateFieldGet(this, _DictationRecordingButton_processing, "f")) { return; } if (__classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").isConnectionOpen()) { return; } try { __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CONNECTING", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, this._recordingState); await __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").connect(this._dictationConfig, { onClose: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketClose, "f"), onError: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketError, "f"), onMessage: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketMessage, "f"), onNetworkActivity: (direction, data) => { this.dispatchEvent(networkActivityEvent(direction, data)); }, }); __classPrivateFieldSet(this, _DictationRecordingButton_connection, "OPEN", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, this._recordingState); } catch (error) { __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CLOSED", "f"); this.dispatchEvent(errorEvent(error)); } } async closeConnection() { if (this._recordingState !== "stopped" || __classPrivateFieldGet(this, _DictationRecordingButton_processing, "f")) { return; } if (__classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").isConnecting()) { await __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").waitForConnection(); } if (!__classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").isConnectionOpen()) { __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CLOSED", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "stopped"); return; } try { __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CLOSING", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "stopped"); await __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").closeConnection(__classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketClose, "f")); } catch (error) { this.dispatchEvent(errorEvent(error)); } } render() { const isLoading = this._recordingState === "initializing" || this._recordingState === "stopping"; const isRecording = this._recordingState === "recording"; return html ` <button @click=${__classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleClick)} ?disabled=${isLoading} class=${isRecording ? "red" : "accent"} aria-label=${isRecording ? "Stop recording" : "Start recording"} aria-pressed=${isRecording} > ${isLoading ? html `<icon-loading-spinner />` : isRecording ? html `<icon-recording />` : html `<icon-mic-on />`} <dictation-audio-visualiser .level=${__classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").audioLevel} ?active=${isRecording} /> </button> `; } }; _DictationRecordingButton_mediaController = new WeakMap(); _DictationRecordingButton_dictationController = new WeakMap(); _DictationRecordingButton_keybindingController = new WeakMap(); _DictationRecordingButton_closeConnectionOnInit = new WeakMap(); _DictationRecordingButton_processing = new WeakMap(); _DictationRecordingButton_connection = new WeakMap(); _DictationRecordingButton_handleWebSocketMessage = new WeakMap(); _DictationRecordingButton_handleWebSocketError = new WeakMap(); _DictationRecordingButton_handleWebSocketClose = new WeakMap(); _DictationRecordingButton_instances = new WeakSet(); _DictationRecordingButton_handleClick = function _DictationRecordingButton_handleClick(event) { if (!this.allowButtonFocus) { event.preventDefault(); } this.toggleRecording(); }; _DictationRecordingButton_dispatchRecordingStateChanged = function _DictationRecordingButton_dispatchRecordingStateChanged(state) { this.dispatchEvent(recordingStateChangedEvent(state, { connection: __classPrivateFieldGet(this, _DictationRecordingButton_connection, "f"), processing: __classPrivateFieldGet(this, _DictationRecordingButton_processing, "f"), })); }; _DictationRecordingButton_handleStart = async function _DictationRecordingButton_handleStart() { __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "initializing"); try { await __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").initialize(() => { if (this._recordingState === "recording") { this.dispatchEvent(errorEvent("Recording device access was lost.")); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); } }, __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").mediaRecorderHandler); __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").mediaRecorder?.start(AUDIO_CHUNK_INTERVAL_MS); __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").startAudioLevelMonitoring((level) => { this.dispatchEvent(audioLevelChangedEvent(level)); }); __classPrivateFieldSet(this, _DictationRecordingButton_processing, true, "f"); if (__classPrivateFieldGet(this, _DictationRecordingButton_connection, "f") !== "OPEN") { __classPrivateFieldSet(this, _DictationRecordingButton_connection, "CONNECTING", "f"); } __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "recording"); const isNewConnection = await __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").connect(this._dictationConfig, { onClose: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketClose, "f"), onError: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketError, "f"), onMessage: __classPrivateFieldGet(this, _DictationRecordingButton_handleWebSocketMessage, "f"), onNetworkActivity: (direction, data) => { this.dispatchEvent(networkActivityEvent(direction, data)); }, }); if (isNewConnection === "superseded") { return; } __classPrivateFieldSet(this, _DictationRecordingButton_connection, "OPEN", "f"); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, this._recordingState); } catch (error) { this.dispatchEvent(errorEvent(error)); await __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_handleStop).call(this); } }; _DictationRecordingButton_handleStop = async function _DictationRecordingButton_handleStop() { __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "stopping"); try { __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").stopAudioLevelMonitoring(); await __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").stopRecording(); __classPrivateFieldGet(this, _DictationRecordingButton_instances, "m", _DictationRecordingButton_dispatchRecordingStateChanged).call(this, "stopped"); await __classPrivateFieldGet(this, _DictationRecordingButton_dictationController, "f").pause(); await __classPrivateFieldGet(this, _DictationRecordingButton_mediaController, "f").cleanup(); } catch (error) { this.dispatchEvent(errorEvent(error)); } }; DictationRecordingButton.styles = [RecordingButtonStyles, ButtonStyles]; __decorate([ consume({ context: recordingStateContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_recordingState", void 0); __decorate([ consume({ context: selectedDeviceContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_selectedDevice", void 0); __decorate([ consume({ context: accessTokenContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_accessToken", void 0); __decorate([ consume({ context: authConfigContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_authConfig", void 0); __decorate([ consume({ context: regionContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_region", void 0); __decorate([ consume({ context: tenantNameContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_tenantName", void 0); __decorate([ consume({ context: dictationConfigContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_dictationConfig", void 0); __decorate([ consume({ context: socketUrlContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_socketUrl", void 0); __decorate([ consume({ context: socketProxyContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_socketProxy", void 0); __decorate([ consume({ context: debugDisplayAudioContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_debug_displayAudio", void 0); __decorate([ consume({ context: pushToTalkKeybindingContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_pushToTalkKeybinding", void 0); __decorate([ consume({ context: toggleToTalkKeybindingContext, subscribe: true }), state() ], DictationRecordingButton.prototype, "_toggleToTalkKeybinding", void 0); __decorate([ property({ type: Boolean }) ], DictationRecordingButton.prototype, "allowButtonFocus", void 0); DictationRecordingButton = __decorate([ customElement("dictation-recording-button") ], DictationRecordingButton); export { DictationRecordingButton }; //# sourceMappingURL=recording-button.js.map