From 4946c00d34d14f613356a5f5937c8284afeff589 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Mon, 17 Jul 2023 18:57:43 +0200 Subject: [PATCH] Add last_used option for pipeline and explicit default (#17329) * Add last-used option for pipeline and explicit default * Default to last used --- src/components/ha-assist-pipeline-picker.ts | 24 +++++++++++++++---- .../ha-selector-assist-pipeline.ts | 21 +++++++++------- src/data/selector.ts | 4 +++- .../ha-voice-command-dialog.ts | 19 +++++++++++---- .../show-ha-voice-command-dialog.ts | 15 ++++++++---- src/external_app/external_messaging.ts | 4 ++-- src/panels/lovelace/common/handle-action.ts | 4 ++-- .../lovelace/components/hui-action-editor.ts | 4 +++- src/panels/lovelace/hui-root.ts | 4 ++-- .../shopping-list/ha-panel-shopping-list.ts | 2 +- src/translations/en.json | 3 ++- 11 files changed, 73 insertions(+), 31 deletions(-) diff --git a/src/components/ha-assist-pipeline-picker.ts b/src/components/ha-assist-pipeline-picker.ts index 0d51bc1444..80a69b2d27 100644 --- a/src/components/ha-assist-pipeline-picker.ts +++ b/src/components/ha-assist-pipeline-picker.ts @@ -16,7 +16,8 @@ import "./ha-list-item"; import "./ha-select"; import type { HaSelect } from "./ha-select"; -const PREFERRED = "__PREFERRED_PIPELINE_OPTION__"; +const PREFERRED = "preferred"; +const LAST_USED = "last_used"; @customElement("ha-assist-pipeline-picker") export class HaAssistPipelinePicker extends LitElement { @@ -30,15 +31,21 @@ export class HaAssistPipelinePicker extends LitElement { @property({ type: Boolean }) public required = false; + @property() public includeLastUsed = false; + @state() _pipelines?: AssistPipeline[]; @state() _preferredPipeline: string | null = null; + private get _default() { + return this.includeLastUsed ? LAST_USED : PREFERRED; + } + protected render() { if (!this._pipelines) { return nothing; } - const value = this.value ?? PREFERRED; + const value = this.value ?? this._default; return html` + ${this.includeLastUsed + ? html` + + ${this.hass!.localize( + "ui.components.pipeline-picker.last_used" + )} + + ` + : null} ${this.hass!.localize("ui.components.pipeline-picker.preferred", { preferred: this._pipelines.find( @@ -93,11 +109,11 @@ export class HaAssistPipelinePicker extends LitElement { !this.hass || target.value === "" || target.value === this.value || - (this.value === undefined && target.value === PREFERRED) + (this.value === undefined && target.value === this._default) ) { return; } - this.value = target.value === PREFERRED ? undefined : target.value; + this.value = target.value === this._default ? undefined : target.value; fireEvent(this, "value-changed", { value: this.value }); } } diff --git a/src/components/ha-selector/ha-selector-assist-pipeline.ts b/src/components/ha-selector/ha-selector-assist-pipeline.ts index 74a143b819..9a00519f07 100644 --- a/src/components/ha-selector/ha-selector-assist-pipeline.ts +++ b/src/components/ha-selector/ha-selector-assist-pipeline.ts @@ -21,14 +21,19 @@ export class HaAssistPipelineSelector extends LitElement { @property({ type: Boolean }) public required = true; protected render() { - return html``; + return html` + + `; } static styles = css` diff --git a/src/data/selector.ts b/src/data/selector.ts index 71805ef7d4..0a24bc2def 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -278,7 +278,9 @@ export interface ObjectSelector { export interface AssistPipelineSelector { // eslint-disable-next-line @typescript-eslint/ban-types - assist_pipeline: {} | null; + assist_pipeline: { + include_last_used?: boolean; + } | null; } export interface SelectOption { diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts index b479b07a22..7bf95f7c33 100644 --- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts @@ -87,9 +87,16 @@ export class HaVoiceCommandDialog extends LitElement { private _pipelinePromise?: Promise; - public async showDialog(params?: VoiceCommandDialogParams): Promise { - if (params?.pipeline_id) { - this._pipelineId = params?.pipeline_id; + public async showDialog( + params: Required + ): Promise { + if (params.pipeline_id === "last_used") { + // Do not set pipeline id (retrieve from storage) + } else if (params.pipeline_id === "preferred") { + await this._loadPipelines(); + this._pipelineId = this._preferredPipeline; + } else { + this._pipelineId = params.pipeline_id; } this._conversation = [ @@ -103,7 +110,11 @@ export class HaVoiceCommandDialog extends LitElement { this._scrollMessagesBottom(); await this._pipelinePromise; - if (params?.start_listening && this._pipeline?.stt_engine) { + if ( + params?.start_listening && + this._pipeline?.stt_engine && + AudioRecorder.isSupported + ) { this._toggleListening(); } } diff --git a/src/dialogs/voice-command-dialog/show-ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/show-ha-voice-command-dialog.ts index c755877cd3..3c29fb8d16 100644 --- a/src/dialogs/voice-command-dialog/show-ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/show-ha-voice-command-dialog.ts @@ -4,21 +4,22 @@ import { HomeAssistant } from "../../types"; const loadVoiceCommandDialog = () => import("./ha-voice-command-dialog"); export interface VoiceCommandDialogParams { - pipeline_id?: string; + pipeline_id: "last_used" | "preferred" | string; start_listening?: boolean; } export const showVoiceCommandDialog = ( element: HTMLElement, hass: HomeAssistant, - dialogParams?: VoiceCommandDialogParams + dialogParams: VoiceCommandDialogParams ): void => { if (hass.auth.external?.config.hasAssist) { hass.auth.external!.fireMessage({ type: "assist/show", payload: { - pipeline_id: dialogParams?.pipeline_id, - start_listening: dialogParams?.start_listening, + pipeline_id: dialogParams.pipeline_id, + // Start listening by default for app + start_listening: dialogParams.start_listening ?? true, }, }); return; @@ -26,6 +27,10 @@ export const showVoiceCommandDialog = ( fireEvent(element, "show-dialog", { dialogTag: "ha-voice-command-dialog", dialogImport: loadVoiceCommandDialog, - dialogParams, + dialogParams: { + pipeline_id: dialogParams.pipeline_id, + // Don't start listening by default for web + start_listening: dialogParams.start_listening ?? false, + }, }); }; diff --git a/src/external_app/external_messaging.ts b/src/external_app/external_messaging.ts index 5c10155138..1b6e9d87f6 100644 --- a/src/external_app/external_messaging.ts +++ b/src/external_app/external_messaging.ts @@ -98,8 +98,8 @@ interface EMOutgoingMessageSidebarShow extends EMMessage { interface EMOutgoingMessageAssistShow extends EMMessage { type: "assist/show"; payload?: { - pipeline_id?: string; - start_listening?: boolean; + pipeline_id: "preferred" | "last_used" | string; + start_listening: boolean; }; } diff --git a/src/panels/lovelace/common/handle-action.ts b/src/panels/lovelace/common/handle-action.ts index febf1c848f..bd849bd428 100644 --- a/src/panels/lovelace/common/handle-action.ts +++ b/src/panels/lovelace/common/handle-action.ts @@ -164,8 +164,8 @@ export const handleAction = async ( } case "assist": { showVoiceCommandDialog(node, hass, { - start_listening: actionConfig.start_listening, - pipeline_id: actionConfig.pipeline_id, + start_listening: actionConfig.start_listening ?? false, + pipeline_id: actionConfig.pipeline_id ?? "last_used", }); break; } diff --git a/src/panels/lovelace/components/hui-action-editor.ts b/src/panels/lovelace/components/hui-action-editor.ts index 20d5e0f597..6ae48d59f1 100644 --- a/src/panels/lovelace/components/hui-action-editor.ts +++ b/src/panels/lovelace/components/hui-action-editor.ts @@ -38,7 +38,9 @@ const ASSIST_SCHEMA = [ { name: "pipeline_id", selector: { - assist_pipeline: {}, + assist_pipeline: { + include_last_used: true, + }, }, }, { diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index 0447b6f646..b023483ab9 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -567,7 +567,7 @@ class HUIRoot extends LitElement { if (searchParams.edit === "1") { this.lovelace!.setEditMode(true); } else if (searchParams.conversation === "1") { - showVoiceCommandDialog(this, this.hass); + this._showVoiceCommandDialog(); window.history.replaceState( null, "", @@ -793,7 +793,7 @@ class HUIRoot extends LitElement { } private _showVoiceCommandDialog(): void { - showVoiceCommandDialog(this, this.hass); + showVoiceCommandDialog(this, this.hass, { pipeline_id: "last_used" }); } private _handleEnableEditMode(ev: CustomEvent): void { diff --git a/src/panels/shopping-list/ha-panel-shopping-list.ts b/src/panels/shopping-list/ha-panel-shopping-list.ts index 94f675a601..a9cfb23eaf 100644 --- a/src/panels/shopping-list/ha-panel-shopping-list.ts +++ b/src/panels/shopping-list/ha-panel-shopping-list.ts @@ -76,7 +76,7 @@ class PanelShoppingList extends LitElement { } private _showVoiceCommandDialog(): void { - showVoiceCommandDialog(this, this.hass); + showVoiceCommandDialog(this, this.hass, { pipeline_id: "last_used" }); } static get styles(): CSSResultGroup { diff --git a/src/translations/en.json b/src/translations/en.json index 9079fcf245..d7673cff1e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -398,7 +398,8 @@ }, "pipeline-picker": { "pipeline": "Assistant", - "preferred": "Preferred assistant ({preferred})" + "preferred": "Preferred assistant ({preferred})", + "last_used": "Last used assistant" }, "theme-picker": { "theme": "Theme",