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 {
interface HASSDomEvents {
"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")) {
this._setError(undefined);
}
if (!changedProps.has("navigateIds")) {
} else if (!changedProps.has("navigateIds")) {
// Neither entity ID or navigateIDs changed, nothing to fetch
return;
}
@ -443,6 +450,7 @@ export class HaMediaPlayerBrowse extends LitElement {
const oldNavigateIds = changedProps.get("navigateIds") as
| this["navigateIds"]
| undefined;
const navigateIds = this.navigateIds;
// We're navigating. Reset the shizzle.
this._content?.scrollTo(0, 0);
@ -451,11 +459,9 @@ export class HaMediaPlayerBrowse extends LitElement {
const oldParentItem = this._parentItem;
this._currentItem = undefined;
this._parentItem = undefined;
const currentId = this.navigateIds[this.navigateIds.length - 1];
const currentId = navigateIds[navigateIds.length - 1];
const parentId =
this.navigateIds.length > 1
? this.navigateIds[this.navigateIds.length - 2]
: undefined;
navigateIds.length > 1 ? navigateIds[navigateIds.length - 2] : undefined;
let currentProm: Promise<MediaPlayerItem> | undefined;
let parentProm: Promise<MediaPlayerItem> | undefined;
@ -464,9 +470,9 @@ export class HaMediaPlayerBrowse extends LitElement {
if (
// Check if we navigated to a child
oldNavigateIds &&
this.navigateIds.length > oldNavigateIds.length &&
navigateIds.length === oldNavigateIds.length + 1 &&
oldNavigateIds.every((oldVal, idx) => {
const curVal = this.navigateIds[idx];
const curVal = navigateIds[idx];
return (
curVal.media_content_id === oldVal.media_content_id &&
curVal.media_content_type === oldVal.media_content_type
@ -477,8 +483,8 @@ export class HaMediaPlayerBrowse extends LitElement {
} else if (
// Check if we navigated to a parent
oldNavigateIds &&
this.navigateIds.length < oldNavigateIds.length &&
this.navigateIds.every((curVal, idx) => {
navigateIds.length === oldNavigateIds.length - 1 &&
navigateIds.every((curVal, idx) => {
const oldVal = oldNavigateIds[idx];
return (
curVal.media_content_id === oldVal.media_content_id &&
@ -501,11 +507,33 @@ export class HaMediaPlayerBrowse extends LitElement {
(item) => {
this._currentItem = item;
fireEvent(this, "media-browsed", {
ids: this.navigateIds,
ids: navigateIds,
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
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 { domainIcon } from "../../common/entity/domain_icon";
import { supportsFeature } from "../../common/entity/supports-feature";
import { navigate } from "../../common/navigate";
import "../../components/ha-button-menu";
import "../../components/ha-icon-button";
import { UNAVAILABLE_STATES } from "../../data/entity";
@ -47,6 +46,12 @@ import type { HomeAssistant } from "../../types";
import "../lovelace/components/hui-marquee";
import { BrowserMediaPlayer } from "./browser-media-player";
declare global {
interface HASSDomEvents {
"player-picked": { entityId: string };
}
}
@customElement("ha-bar-media-player")
class BarMediaPlayer extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -399,7 +404,7 @@ class BarMediaPlayer extends LitElement {
private _selectPlayer(ev: CustomEvent): void {
const entityId = (ev.currentTarget as any).player;
navigate(`/media-browser/${entityId}`, { replace: true });
fireEvent(this, "player-picked", { entityId });
}
static get styles(): CSSResultGroup {

View File

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