Try to keep the browsing stack when changing players in media panel (#11681)

This commit is contained in:
Paulus Schoutsen 2022-02-14 15:21:17 -08:00 committed by GitHub
parent 92db272759
commit 520896a3c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 25 deletions

View File

@ -54,7 +54,14 @@ import "./ha-browse-media-tts";
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
"media-picked": MediaPickedEvent; "media-picked": MediaPickedEvent;
"media-browsed": { ids: MediaPlayerItemId[]; current?: MediaPlayerItem }; "media-browsed": {
// Items of the new browse stack
ids: MediaPlayerItemId[];
// Current fetched item for this browse stack
current?: MediaPlayerItem;
// If the new stack should replace the old stack
replace?: boolean;
};
} }
} }
@ -433,8 +440,8 @@ export class HaMediaPlayerBrowse extends LitElement {
if (changedProps.has("entityId")) { if (changedProps.has("entityId")) {
this._setError(undefined); this._setError(undefined);
} } else if (!changedProps.has("navigateIds")) {
if (!changedProps.has("navigateIds")) { // Neither entity ID or navigateIDs changed, nothing to fetch
return; return;
} }
@ -443,6 +450,7 @@ export class HaMediaPlayerBrowse extends LitElement {
const oldNavigateIds = changedProps.get("navigateIds") as const oldNavigateIds = changedProps.get("navigateIds") as
| this["navigateIds"] | this["navigateIds"]
| undefined; | undefined;
const navigateIds = this.navigateIds;
// We're navigating. Reset the shizzle. // We're navigating. Reset the shizzle.
this._content?.scrollTo(0, 0); this._content?.scrollTo(0, 0);
@ -451,11 +459,9 @@ export class HaMediaPlayerBrowse extends LitElement {
const oldParentItem = this._parentItem; const oldParentItem = this._parentItem;
this._currentItem = undefined; this._currentItem = undefined;
this._parentItem = undefined; this._parentItem = undefined;
const currentId = this.navigateIds[this.navigateIds.length - 1]; const currentId = navigateIds[navigateIds.length - 1];
const parentId = const parentId =
this.navigateIds.length > 1 navigateIds.length > 1 ? navigateIds[navigateIds.length - 2] : undefined;
? this.navigateIds[this.navigateIds.length - 2]
: undefined;
let currentProm: Promise<MediaPlayerItem> | undefined; let currentProm: Promise<MediaPlayerItem> | undefined;
let parentProm: Promise<MediaPlayerItem> | undefined; let parentProm: Promise<MediaPlayerItem> | undefined;
@ -464,9 +470,9 @@ export class HaMediaPlayerBrowse extends LitElement {
if ( if (
// Check if we navigated to a child // Check if we navigated to a child
oldNavigateIds && oldNavigateIds &&
this.navigateIds.length > oldNavigateIds.length && navigateIds.length === oldNavigateIds.length + 1 &&
oldNavigateIds.every((oldVal, idx) => { oldNavigateIds.every((oldVal, idx) => {
const curVal = this.navigateIds[idx]; const curVal = navigateIds[idx];
return ( return (
curVal.media_content_id === oldVal.media_content_id && curVal.media_content_id === oldVal.media_content_id &&
curVal.media_content_type === oldVal.media_content_type curVal.media_content_type === oldVal.media_content_type
@ -477,8 +483,8 @@ export class HaMediaPlayerBrowse extends LitElement {
} else if ( } else if (
// Check if we navigated to a parent // Check if we navigated to a parent
oldNavigateIds && oldNavigateIds &&
this.navigateIds.length < oldNavigateIds.length && navigateIds.length === oldNavigateIds.length - 1 &&
this.navigateIds.every((curVal, idx) => { navigateIds.every((curVal, idx) => {
const oldVal = oldNavigateIds[idx]; const oldVal = oldNavigateIds[idx];
return ( return (
curVal.media_content_id === oldVal.media_content_id && curVal.media_content_id === oldVal.media_content_id &&
@ -501,11 +507,33 @@ export class HaMediaPlayerBrowse extends LitElement {
(item) => { (item) => {
this._currentItem = item; this._currentItem = item;
fireEvent(this, "media-browsed", { fireEvent(this, "media-browsed", {
ids: this.navigateIds, ids: navigateIds,
current: item, current: item,
}); });
}, },
(err) => this._setError(err) (err) => {
// When we change entity ID, we will first try to see if the new entity is
// able to resolve the new path. If that results in an error, browse the root.
const isNewEntityWithSamePath =
oldNavigateIds &&
changedProps.has("entityId") &&
navigateIds.length === oldNavigateIds.length &&
oldNavigateIds.every(
(oldItem, idx) =>
navigateIds[idx].media_content_id === oldItem.media_content_id &&
navigateIds[idx].media_content_type === oldItem.media_content_type
);
if (isNewEntityWithSamePath) {
fireEvent(this, "media-browsed", {
ids: [
{ media_content_id: undefined, media_content_type: undefined },
],
replace: true,
});
} else {
this._setError(err);
}
}
); );
// Fetch parent // Fetch parent
if (!parentProm && parentId !== undefined) { if (!parentProm && parentId !== undefined) {

View File

@ -25,7 +25,6 @@ import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { computeStateName } from "../../common/entity/compute_state_name"; import { computeStateName } from "../../common/entity/compute_state_name";
import { domainIcon } from "../../common/entity/domain_icon"; import { domainIcon } from "../../common/entity/domain_icon";
import { supportsFeature } from "../../common/entity/supports-feature"; import { supportsFeature } from "../../common/entity/supports-feature";
import { navigate } from "../../common/navigate";
import "../../components/ha-button-menu"; import "../../components/ha-button-menu";
import "../../components/ha-icon-button"; import "../../components/ha-icon-button";
import { UNAVAILABLE_STATES } from "../../data/entity"; import { UNAVAILABLE_STATES } from "../../data/entity";
@ -47,6 +46,12 @@ import type { HomeAssistant } from "../../types";
import "../lovelace/components/hui-marquee"; import "../lovelace/components/hui-marquee";
import { BrowserMediaPlayer } from "./browser-media-player"; import { BrowserMediaPlayer } from "./browser-media-player";
declare global {
interface HASSDomEvents {
"player-picked": { entityId: string };
}
}
@customElement("ha-bar-media-player") @customElement("ha-bar-media-player")
class BarMediaPlayer extends LitElement { class BarMediaPlayer extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -399,7 +404,7 @@ class BarMediaPlayer extends LitElement {
private _selectPlayer(ev: CustomEvent): void { private _selectPlayer(ev: CustomEvent): void {
const entityId = (ev.currentTarget as any).player; const entityId = (ev.currentTarget as any).player;
navigate(`/media-browser/${entityId}`, { replace: true }); fireEvent(this, "player-picked", { entityId });
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@ -43,6 +43,16 @@ import {
isCameraMediaSource, isCameraMediaSource,
} from "../../data/camera"; } from "../../data/camera";
const createMediaPanelUrl = (entityId: string, items: MediaPlayerItemId[]) => {
let path = `/media-browser/${entityId}`;
for (const item of items.slice(1)) {
path +=
"/" +
encodeURIComponent(`${item.media_content_type},${item.media_content_id}`);
}
return path;
};
@customElement("ha-panel-media-browser") @customElement("ha-panel-media-browser")
class PanelMediaBrowser extends LitElement { class PanelMediaBrowser extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -120,6 +130,7 @@ class PanelMediaBrowser extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.entityId=${this._entityId} .entityId=${this._entityId}
.narrow=${this.narrow} .narrow=${this.narrow}
@player-picked=${this._playerPicked}
></ha-bar-media-player> ></ha-bar-media-player>
`; `;
} }
@ -179,7 +190,9 @@ class PanelMediaBrowser extends LitElement {
} }
private _goBack() { private _goBack() {
history.back(); navigate(
createMediaPanelUrl(this._entityId, this._navigateIds.slice(0, -1))
);
} }
private _mediaBrowsed(ev: { detail: HASSDomEvents["media-browsed"] }) { private _mediaBrowsed(ev: { detail: HASSDomEvents["media-browsed"] }) {
@ -188,15 +201,9 @@ class PanelMediaBrowser extends LitElement {
return; return;
} }
let path = ""; navigate(createMediaPanelUrl(this._entityId, ev.detail.ids), {
for (const item of ev.detail.ids.slice(1)) { replace: ev.detail.replace,
path += });
"/" +
encodeURIComponent(
`${item.media_content_type},${item.media_content_id}`
);
}
navigate(`/media-browser/${this._entityId}${path}`);
} }
private async _mediaPicked( private async _mediaPicked(
@ -239,6 +246,14 @@ class PanelMediaBrowser extends LitElement {
}); });
} }
private _playerPicked(ev) {
const entityId: string = ev.detail.entityId;
if (entityId === this._entityId) {
return;
}
navigate(createMediaPanelUrl(entityId, this._navigateIds));
}
private async _startUpload() { private async _startUpload() {
const input = document.createElement("input"); const input = document.createElement("input");
input.type = "file"; input.type = "file";