mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 02:49:51 +00:00
Use media selector for media_player.play_media (#26559)
This commit is contained in:
@@ -18,7 +18,6 @@ import { HaDeviceAction } from "../../../../src/panels/config/automation/action/
|
|||||||
import { HaEventAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-event";
|
import { HaEventAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-event";
|
||||||
import { HaIfAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-if";
|
import { HaIfAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-if";
|
||||||
import { HaParallelAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-parallel";
|
import { HaParallelAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-parallel";
|
||||||
import { HaPlayMediaAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-play_media";
|
|
||||||
import { HaRepeatAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-repeat";
|
import { HaRepeatAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-repeat";
|
||||||
import { HaSequenceAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-sequence";
|
import { HaSequenceAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-sequence";
|
||||||
import { HaServiceAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-service";
|
import { HaServiceAction } from "../../../../src/panels/config/automation/action/types/ha-automation-action-service";
|
||||||
@@ -32,7 +31,6 @@ const SCHEMAS: { name: string; actions: Action[] }[] = [
|
|||||||
{ name: "Service", actions: [HaServiceAction.defaultConfig] },
|
{ name: "Service", actions: [HaServiceAction.defaultConfig] },
|
||||||
{ name: "Condition", actions: [HaConditionAction.defaultConfig] },
|
{ name: "Condition", actions: [HaConditionAction.defaultConfig] },
|
||||||
{ name: "Delay", actions: [HaDelayAction.defaultConfig] },
|
{ name: "Delay", actions: [HaDelayAction.defaultConfig] },
|
||||||
{ name: "Play media", actions: [HaPlayMediaAction.defaultConfig] },
|
|
||||||
{ name: "Wait", actions: [HaWaitAction.defaultConfig] },
|
{ name: "Wait", actions: [HaWaitAction.defaultConfig] },
|
||||||
{ name: "WaitForTrigger", actions: [HaWaitForTriggerAction.defaultConfig] },
|
{ name: "WaitForTrigger", actions: [HaWaitForTriggerAction.defaultConfig] },
|
||||||
{ name: "Repeat", actions: [HaRepeatAction.defaultConfig] },
|
{ name: "Repeat", actions: [HaRepeatAction.defaultConfig] },
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import "../ha-alert";
|
|||||||
import "../ha-form/ha-form";
|
import "../ha-form/ha-form";
|
||||||
import type { SchemaUnion } from "../ha-form/types";
|
import type { SchemaUnion } from "../ha-form/types";
|
||||||
import { showMediaBrowserDialog } from "../media-player/show-media-browser-dialog";
|
import { showMediaBrowserDialog } from "../media-player/show-media-browser-dialog";
|
||||||
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
|
|
||||||
const MANUAL_SCHEMA = [
|
const MANUAL_SCHEMA = [
|
||||||
{ name: "media_content_id", required: false, selector: { text: {} } },
|
{ name: "media_content_id", required: false, selector: { text: {} } },
|
||||||
@@ -44,9 +45,19 @@ export class HaMediaSelector extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, reflect: true }) public required = true;
|
@property({ type: Boolean, reflect: true }) public required = true;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public context?: {
|
||||||
|
filter_entity?: string | string[];
|
||||||
|
};
|
||||||
|
|
||||||
@state() private _thumbnailUrl?: string | null;
|
@state() private _thumbnailUrl?: string | null;
|
||||||
|
|
||||||
|
private _contextEntities: string[] | undefined;
|
||||||
|
|
||||||
willUpdate(changedProps: PropertyValues<this>) {
|
willUpdate(changedProps: PropertyValues<this>) {
|
||||||
|
if (changedProps.has("context")) {
|
||||||
|
this._contextEntities = ensureArray(this.context?.filter_entity);
|
||||||
|
}
|
||||||
|
|
||||||
if (changedProps.has("value")) {
|
if (changedProps.has("value")) {
|
||||||
const thumbnail = this.value?.metadata?.thumbnail;
|
const thumbnail = this.value?.metadata?.thumbnail;
|
||||||
const oldThumbnail = (changedProps.get("value") as this["value"])
|
const oldThumbnail = (changedProps.get("value") as this["value"])
|
||||||
@@ -79,24 +90,25 @@ export class HaMediaSelector extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const stateObj = this.value?.entity_id
|
const entityId = this._getActiveEntityId();
|
||||||
? this.hass.states[this.value.entity_id]
|
|
||||||
: undefined;
|
const stateObj = entityId ? this.hass.states[entityId] : undefined;
|
||||||
|
|
||||||
const supportsBrowse =
|
const supportsBrowse =
|
||||||
!this.value?.entity_id ||
|
!entityId ||
|
||||||
(stateObj &&
|
(stateObj &&
|
||||||
supportsFeature(stateObj, MediaPlayerEntityFeature.BROWSE_MEDIA));
|
supportsFeature(stateObj, MediaPlayerEntityFeature.BROWSE_MEDIA));
|
||||||
|
|
||||||
const hasAccept = this.selector?.media?.accept?.length;
|
const hasAccept = this.selector?.media?.accept?.length;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${hasAccept
|
${hasAccept ||
|
||||||
|
(this._contextEntities && this._contextEntities.length <= 1)
|
||||||
? nothing
|
? nothing
|
||||||
: html`
|
: html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.value?.entity_id}
|
.value=${entityId}
|
||||||
.label=${this.label ||
|
.label=${this.label ||
|
||||||
this.hass.localize(
|
this.hass.localize(
|
||||||
"ui.components.selectors.media.pick_media_player"
|
"ui.components.selectors.media.pick_media_player"
|
||||||
@@ -104,8 +116,10 @@ export class HaMediaSelector extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.helper=${this.helper}
|
.helper=${this.helper}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
|
.hideClearIcon=${!!this._contextEntities}
|
||||||
.includeDomains=${INCLUDE_DOMAINS}
|
.includeDomains=${INCLUDE_DOMAINS}
|
||||||
allow-custom-entity
|
.includeEntities=${this._contextEntities}
|
||||||
|
.allowCustomEntity=${!this._contextEntities}
|
||||||
@value-changed=${this._entityChanged}
|
@value-changed=${this._entityChanged}
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
`}
|
`}
|
||||||
@@ -121,6 +135,7 @@ export class HaMediaSelector extends LitElement {
|
|||||||
.data=${this.value || EMPTY_FORM}
|
.data=${this.value || EMPTY_FORM}
|
||||||
.schema=${MANUAL_SCHEMA}
|
.schema=${MANUAL_SCHEMA}
|
||||||
.computeLabel=${this._computeLabelCallback}
|
.computeLabel=${this._computeLabelCallback}
|
||||||
|
.computeHelper=${this._computeHelperCallback}
|
||||||
></ha-form>
|
></ha-form>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
@@ -133,7 +148,7 @@ export class HaMediaSelector extends LitElement {
|
|||||||
: this.value.metadata?.title || this.value.media_content_id}
|
: this.value.metadata?.title || this.value.media_content_id}
|
||||||
@click=${this._pickMedia}
|
@click=${this._pickMedia}
|
||||||
@keydown=${this._handleKeyDown}
|
@keydown=${this._handleKeyDown}
|
||||||
class=${this.disabled || (!this.value?.entity_id && !hasAccept)
|
class=${this.disabled || (!entityId && !hasAccept)
|
||||||
? "disabled"
|
? "disabled"
|
||||||
: ""}
|
: ""}
|
||||||
>
|
>
|
||||||
@@ -193,21 +208,38 @@ export class HaMediaSelector extends LitElement {
|
|||||||
): string =>
|
): string =>
|
||||||
this.hass.localize(`ui.components.selectors.media.${schema.name}`);
|
this.hass.localize(`ui.components.selectors.media.${schema.name}`);
|
||||||
|
|
||||||
|
private _computeHelperCallback = (
|
||||||
|
schema: SchemaUnion<typeof MANUAL_SCHEMA>
|
||||||
|
): string =>
|
||||||
|
this.hass.localize(`ui.components.selectors.media.${schema.name}_detail`);
|
||||||
|
|
||||||
private _entityChanged(ev: CustomEvent) {
|
private _entityChanged(ev: CustomEvent) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
fireEvent(this, "value-changed", {
|
if (this.context?.filter_entity) {
|
||||||
value: {
|
fireEvent(this, "value-changed", {
|
||||||
entity_id: ev.detail.value,
|
value: {
|
||||||
media_content_id: "",
|
media_content_id: "",
|
||||||
media_content_type: "",
|
media_content_type: "",
|
||||||
},
|
metadata: {
|
||||||
});
|
browse_entity_id: ev.detail.value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: {
|
||||||
|
entity_id: ev.detail.value,
|
||||||
|
media_content_id: "",
|
||||||
|
media_content_type: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _pickMedia() {
|
private _pickMedia() {
|
||||||
showMediaBrowserDialog(this, {
|
showMediaBrowserDialog(this, {
|
||||||
action: "pick",
|
action: "pick",
|
||||||
entityId: this.value?.entity_id,
|
entityId: this._getActiveEntityId(),
|
||||||
navigateIds: this.value?.metadata?.navigateIds,
|
navigateIds: this.value?.metadata?.navigateIds,
|
||||||
accept: this.selector.media?.accept,
|
accept: this.selector.media?.accept,
|
||||||
mediaPickedCallback: (pickedMedia: MediaPickedEvent) => {
|
mediaPickedCallback: (pickedMedia: MediaPickedEvent) => {
|
||||||
@@ -225,6 +257,9 @@ export class HaMediaSelector extends LitElement {
|
|||||||
media_content_type: id.media_content_type,
|
media_content_type: id.media_content_type,
|
||||||
media_content_id: id.media_content_id,
|
media_content_id: id.media_content_id,
|
||||||
})),
|
})),
|
||||||
|
...(this.context?.filter_entity
|
||||||
|
? { browse_entity_id: this._getActiveEntityId() }
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -232,6 +267,15 @@ export class HaMediaSelector extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _getActiveEntityId(): string | undefined {
|
||||||
|
const metaId = this.value?.metadata?.browse_entity_id;
|
||||||
|
return (
|
||||||
|
this.value?.entity_id ||
|
||||||
|
(metaId && this._contextEntities?.includes(metaId) && metaId) ||
|
||||||
|
this._contextEntities?.[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private _handleKeyDown(ev: KeyboardEvent) {
|
private _handleKeyDown(ev: KeyboardEvent) {
|
||||||
if (ev.key === "Enter" || ev.key === " ") {
|
if (ev.key === "Enter" || ev.key === " ") {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ import {
|
|||||||
union,
|
union,
|
||||||
array,
|
array,
|
||||||
assign,
|
assign,
|
||||||
literal,
|
|
||||||
is,
|
|
||||||
boolean,
|
boolean,
|
||||||
refine,
|
refine,
|
||||||
} from "superstruct";
|
} from "superstruct";
|
||||||
@@ -68,17 +66,6 @@ export const serviceActionStruct: Describe<ServiceActionWithTemplate> = assign(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const playMediaActionStruct: Describe<PlayMediaAction> = assign(
|
|
||||||
baseActionStruct,
|
|
||||||
object({
|
|
||||||
action: literal("media_player.play_media"),
|
|
||||||
target: optional(object({ entity_id: optional(string()) })),
|
|
||||||
entity_id: optional(string()),
|
|
||||||
data: object({ media_content_id: string(), media_content_type: string() }),
|
|
||||||
metadata: object(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface ScriptEntity extends HassEntityBase {
|
export interface ScriptEntity extends HassEntityBase {
|
||||||
attributes: HassEntityAttributeBase & {
|
attributes: HassEntityAttributeBase & {
|
||||||
last_triggered: string;
|
last_triggered: string;
|
||||||
@@ -182,14 +169,6 @@ export interface WaitForTriggerAction extends BaseAction {
|
|||||||
continue_on_timeout?: boolean;
|
continue_on_timeout?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlayMediaAction extends BaseAction {
|
|
||||||
action: "media_player.play_media";
|
|
||||||
target?: { entity_id?: string };
|
|
||||||
entity_id?: string;
|
|
||||||
data: { media_content_id: string; media_content_type: string };
|
|
||||||
metadata: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RepeatAction extends BaseAction {
|
export interface RepeatAction extends BaseAction {
|
||||||
repeat: CountRepeat | WhileRepeat | UntilRepeat | ForEachRepeat;
|
repeat: CountRepeat | WhileRepeat | UntilRepeat | ForEachRepeat;
|
||||||
}
|
}
|
||||||
@@ -266,7 +245,6 @@ export type NonConditionAction =
|
|||||||
| ChooseAction
|
| ChooseAction
|
||||||
| IfAction
|
| IfAction
|
||||||
| VariablesAction
|
| VariablesAction
|
||||||
| PlayMediaAction
|
|
||||||
| StopAction
|
| StopAction
|
||||||
| SequenceAction
|
| SequenceAction
|
||||||
| ParallelAction
|
| ParallelAction
|
||||||
@@ -291,7 +269,6 @@ export interface ActionTypes {
|
|||||||
wait_for_trigger: WaitForTriggerAction;
|
wait_for_trigger: WaitForTriggerAction;
|
||||||
variables: VariablesAction;
|
variables: VariablesAction;
|
||||||
service: ServiceAction;
|
service: ServiceAction;
|
||||||
play_media: PlayMediaAction;
|
|
||||||
stop: StopAction;
|
stop: StopAction;
|
||||||
sequence: SequenceAction;
|
sequence: SequenceAction;
|
||||||
parallel: ParallelAction;
|
parallel: ParallelAction;
|
||||||
@@ -398,11 +375,6 @@ export const getActionType = (action: Action): ActionType => {
|
|||||||
return "set_conversation_response";
|
return "set_conversation_response";
|
||||||
}
|
}
|
||||||
if ("action" in action || "service" in action) {
|
if ("action" in action || "service" in action) {
|
||||||
if ("metadata" in action) {
|
|
||||||
if (is(action, playMediaActionStruct)) {
|
|
||||||
return "play_media";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "service";
|
return "service";
|
||||||
}
|
}
|
||||||
return "unknown";
|
return "unknown";
|
||||||
@@ -443,6 +415,31 @@ export const migrateAutomationAction = (
|
|||||||
delete action.scene;
|
delete action.scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// legacy play media
|
||||||
|
if (
|
||||||
|
typeof action === "object" &&
|
||||||
|
action !== null &&
|
||||||
|
"action" in action &&
|
||||||
|
action.action === "media_player.play_media" &&
|
||||||
|
"data" in action &&
|
||||||
|
((action.data as any)?.media_content_id ||
|
||||||
|
(action.data as any)?.media_content_type)
|
||||||
|
) {
|
||||||
|
const oldData = { ...(action.data as any) };
|
||||||
|
const media = {
|
||||||
|
media_content_id: oldData.media_content_id,
|
||||||
|
media_content_type: oldData.media_content_type,
|
||||||
|
metadata: { ...(action.metadata || {}) },
|
||||||
|
};
|
||||||
|
delete action.metadata;
|
||||||
|
delete oldData.media_content_id;
|
||||||
|
delete oldData.media_content_type;
|
||||||
|
action.data = {
|
||||||
|
...oldData,
|
||||||
|
media,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof action === "object" && action !== null && "sequence" in action) {
|
if (typeof action === "object" && action !== null && "sequence" in action) {
|
||||||
for (const sequenceAction of (action as SequenceAction).sequence) {
|
for (const sequenceAction of (action as SequenceAction).sequence) {
|
||||||
migrateAutomationAction(sequenceAction);
|
migrateAutomationAction(sequenceAction);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import type {
|
|||||||
EventAction,
|
EventAction,
|
||||||
IfAction,
|
IfAction,
|
||||||
ParallelAction,
|
ParallelAction,
|
||||||
PlayMediaAction,
|
|
||||||
RepeatAction,
|
RepeatAction,
|
||||||
SequenceAction,
|
SequenceAction,
|
||||||
SetConversationResponseAction,
|
SetConversationResponseAction,
|
||||||
@@ -303,27 +302,6 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionType === "play_media") {
|
|
||||||
const config = action as PlayMediaAction;
|
|
||||||
const entityId = config.target?.entity_id || config.entity_id;
|
|
||||||
const mediaStateObj = entityId ? hass.states[entityId] : undefined;
|
|
||||||
return hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.play_media.description.full`,
|
|
||||||
{
|
|
||||||
hasMedia:
|
|
||||||
config.metadata.title || config.data.media_content_id
|
|
||||||
? "true"
|
|
||||||
: "false",
|
|
||||||
media:
|
|
||||||
(config.metadata.title as string | undefined) ||
|
|
||||||
config.data.media_content_id,
|
|
||||||
hasMediaPlayer:
|
|
||||||
mediaStateObj || entityId !== undefined ? "true" : "false",
|
|
||||||
mediaPlayer: mediaStateObj ? computeStateName(mediaStateObj) : entityId,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actionType === "wait_for_trigger") {
|
if (actionType === "wait_for_trigger") {
|
||||||
const config = action as WaitForTriggerAction;
|
const config = action as WaitForTriggerAction;
|
||||||
const triggers = ensureArray(config.wait_for_trigger);
|
const triggers = ensureArray(config.wait_for_trigger);
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ export interface MediaSelectorValue {
|
|||||||
media_class?: string;
|
media_class?: string;
|
||||||
children_media_class?: string | null;
|
children_media_class?: string | null;
|
||||||
navigateIds?: { media_content_type: string; media_content_id: string }[];
|
navigateIds?: { media_content_type: string; media_content_id: string }[];
|
||||||
|
browse_entity_id?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ import "./types/ha-automation-action-device_id";
|
|||||||
import "./types/ha-automation-action-event";
|
import "./types/ha-automation-action-event";
|
||||||
import "./types/ha-automation-action-if";
|
import "./types/ha-automation-action-if";
|
||||||
import "./types/ha-automation-action-parallel";
|
import "./types/ha-automation-action-parallel";
|
||||||
import "./types/ha-automation-action-play_media";
|
|
||||||
import { getRepeatType } from "./types/ha-automation-action-repeat";
|
import { getRepeatType } from "./types/ha-automation-action-repeat";
|
||||||
import "./types/ha-automation-action-sequence";
|
import "./types/ha-automation-action-sequence";
|
||||||
import "./types/ha-automation-action-service";
|
import "./types/ha-automation-action-service";
|
||||||
@@ -96,7 +95,7 @@ export const getAutomationActionType = memoizeOne(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if ("action" in action) {
|
if ("action" in action) {
|
||||||
return getActionType(action) as "action" | "play_media";
|
return getActionType(action) as "action";
|
||||||
}
|
}
|
||||||
if (CONDITION_BUILDING_BLOCKS.some((key) => key in action)) {
|
if (CONDITION_BUILDING_BLOCKS.some((key) => key in action)) {
|
||||||
return "condition" as const;
|
return "condition" as const;
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
import { html, LitElement } from "lit";
|
|
||||||
import { customElement, property } from "lit/decorators";
|
|
||||||
import memoizeOne from "memoize-one";
|
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
|
||||||
import "../../../../../components/ha-selector/ha-selector";
|
|
||||||
import type { PlayMediaAction } from "../../../../../data/script";
|
|
||||||
import type {
|
|
||||||
MediaSelectorValue,
|
|
||||||
Selector,
|
|
||||||
} from "../../../../../data/selector";
|
|
||||||
import type { HomeAssistant } from "../../../../../types";
|
|
||||||
import type { ActionElement } from "../ha-automation-action-row";
|
|
||||||
|
|
||||||
const MEDIA_SELECTOR_SCHEMA: Selector = {
|
|
||||||
media: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("ha-automation-action-play_media")
|
|
||||||
export class HaPlayMediaAction extends LitElement implements ActionElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public action!: PlayMediaAction;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public narrow = false;
|
|
||||||
|
|
||||||
public static get defaultConfig(): PlayMediaAction {
|
|
||||||
return {
|
|
||||||
action: "media_player.play_media",
|
|
||||||
target: { entity_id: "" },
|
|
||||||
data: { media_content_id: "", media_content_type: "" },
|
|
||||||
metadata: {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getSelectorValue = memoizeOne(
|
|
||||||
(action: PlayMediaAction): MediaSelectorValue => ({
|
|
||||||
entity_id: action.target?.entity_id || action.entity_id,
|
|
||||||
media_content_id: action.data?.media_content_id,
|
|
||||||
media_content_type: action.data?.media_content_type,
|
|
||||||
metadata: action.metadata,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
return html`
|
|
||||||
<ha-selector
|
|
||||||
.selector=${MEDIA_SELECTOR_SCHEMA}
|
|
||||||
.hass=${this.hass}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
.value=${this._getSelectorValue(this.action)}
|
|
||||||
@value-changed=${this._valueChanged}
|
|
||||||
></ha-selector>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent<{ value: MediaSelectorValue }>) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: {
|
|
||||||
...this.action,
|
|
||||||
action: "media_player.play_media",
|
|
||||||
target: { entity_id: ev.detail.value.entity_id },
|
|
||||||
data: {
|
|
||||||
media_content_id: ev.detail.value.media_content_id,
|
|
||||||
media_content_type: ev.detail.value.media_content_type,
|
|
||||||
},
|
|
||||||
metadata: ev.detail.value.metadata || {},
|
|
||||||
} as PlayMediaAction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"ha-automation-action-play_media": HaPlayMediaAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -244,14 +244,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
|
|||||||
manifests?: DomainManifestLookup
|
manifests?: DomainManifestLookup
|
||||||
): ListItem[] => {
|
): ListItem[] => {
|
||||||
if (type === "action" && isService(group)) {
|
if (type === "action" && isService(group)) {
|
||||||
let result = this._services(localize, services, manifests, group);
|
return this._services(localize, services, manifests, group);
|
||||||
if (group === `${SERVICE_PREFIX}media_player`) {
|
|
||||||
result = [
|
|
||||||
this._convertToItem("play_media", {}, type, localize),
|
|
||||||
...result,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = this._getGroups(type, group);
|
const groups = this._getGroups(type, group);
|
||||||
|
|||||||
@@ -452,7 +452,9 @@
|
|||||||
"browse_media": "Browse media",
|
"browse_media": "Browse media",
|
||||||
"manual": "Manually enter media ID",
|
"manual": "Manually enter media ID",
|
||||||
"media_content_id": "Media content ID",
|
"media_content_id": "Media content ID",
|
||||||
"media_content_type": "Media content type"
|
"media_content_type": "Media content type",
|
||||||
|
"media_content_id_detail": "The ID of the content to play. Platform dependent.",
|
||||||
|
"media_content_type_detail": "The type of the content to play, such as image, music, tv show, video, episode, channel, or playlist."
|
||||||
},
|
},
|
||||||
"file": {
|
"file": {
|
||||||
"upload_failed": "Upload failed",
|
"upload_failed": "Upload failed",
|
||||||
|
|||||||
Reference in New Issue
Block a user