@corti/dictation-web
Version:
Web component for Corti Dictation
331 lines • 20.2 kB
JavaScript
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
=${__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