mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Reflect media browser panel state in URL (#11317)
This commit is contained in:
parent
32bbdc194a
commit
09a27a6791
@ -9,32 +9,30 @@ import { haStyleDialog } from "../../resources/styles";
|
|||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../ha-dialog";
|
import "../ha-dialog";
|
||||||
import "./ha-media-player-browse";
|
import "./ha-media-player-browse";
|
||||||
|
import type { MediaPlayerItemId } from "./ha-media-player-browse";
|
||||||
import { MediaPlayerBrowseDialogParams } from "./show-media-browser-dialog";
|
import { MediaPlayerBrowseDialogParams } from "./show-media-browser-dialog";
|
||||||
|
|
||||||
@customElement("dialog-media-player-browse")
|
@customElement("dialog-media-player-browse")
|
||||||
class DialogMediaPlayerBrowse extends LitElement {
|
class DialogMediaPlayerBrowse extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@state() private _entityId!: string;
|
@state() private _navigateIds?: MediaPlayerItemId[];
|
||||||
|
|
||||||
@state() private _mediaContentId?: string;
|
|
||||||
|
|
||||||
@state() private _mediaContentType?: string;
|
|
||||||
|
|
||||||
@state() private _action?: MediaPlayerBrowseAction;
|
|
||||||
|
|
||||||
@state() private _params?: MediaPlayerBrowseDialogParams;
|
@state() private _params?: MediaPlayerBrowseDialogParams;
|
||||||
|
|
||||||
public showDialog(params: MediaPlayerBrowseDialogParams): void {
|
public showDialog(params: MediaPlayerBrowseDialogParams): void {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._entityId = this._params.entityId;
|
this._navigateIds = [
|
||||||
this._mediaContentId = this._params.mediaContentId;
|
{
|
||||||
this._mediaContentType = this._params.mediaContentType;
|
media_content_id: this._params.mediaContentId,
|
||||||
this._action = this._params.action || "play";
|
media_content_type: this._params.mediaContentType,
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog() {
|
public closeDialog() {
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
|
this._navigateIds = undefined;
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,17 +53,21 @@ class DialogMediaPlayerBrowse extends LitElement {
|
|||||||
<ha-media-player-browse
|
<ha-media-player-browse
|
||||||
dialog
|
dialog
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.entityId=${this._entityId}
|
.entityId=${this._params.entityId}
|
||||||
.action=${this._action!}
|
.navigateIds=${this._navigateIds}
|
||||||
.mediaContentId=${this._mediaContentId}
|
.action=${this._action}
|
||||||
.mediaContentType=${this._mediaContentType}
|
|
||||||
@close-dialog=${this.closeDialog}
|
@close-dialog=${this.closeDialog}
|
||||||
@media-picked=${this._mediaPicked}
|
@media-picked=${this._mediaPicked}
|
||||||
|
@media-browsed=${this._mediaBrowsed}
|
||||||
></ha-media-player-browse>
|
></ha-media-player-browse>
|
||||||
</ha-dialog>
|
</ha-dialog>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _mediaBrowsed(ev) {
|
||||||
|
this._navigateIds = ev.detail.ids;
|
||||||
|
}
|
||||||
|
|
||||||
private _mediaPicked(ev: HASSDomEvent<MediaPickedEvent>): void {
|
private _mediaPicked(ev: HASSDomEvent<MediaPickedEvent>): void {
|
||||||
this._params!.mediaPickedCallback(ev.detail);
|
this._params!.mediaPickedCallback(ev.detail);
|
||||||
if (this._action !== "play") {
|
if (this._action !== "play") {
|
||||||
@ -73,6 +75,10 @@ class DialogMediaPlayerBrowse extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get _action(): MediaPlayerBrowseAction {
|
||||||
|
return this._params!.action || "play";
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
|
@ -53,19 +53,21 @@ import "../ha-svg-icon";
|
|||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"media-picked": MediaPickedEvent;
|
"media-picked": MediaPickedEvent;
|
||||||
|
"media-browsed": { ids: MediaPlayerItemId[]; back?: boolean };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MediaPlayerItemId {
|
||||||
|
media_content_id: string | undefined;
|
||||||
|
media_content_type: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
@customElement("ha-media-player-browse")
|
@customElement("ha-media-player-browse")
|
||||||
export class HaMediaPlayerBrowse extends LitElement {
|
export class HaMediaPlayerBrowse extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public entityId!: string;
|
@property() public entityId!: string;
|
||||||
|
|
||||||
@property() public mediaContentId?: string;
|
|
||||||
|
|
||||||
@property() public mediaContentType?: string;
|
|
||||||
|
|
||||||
@property() public action: MediaPlayerBrowseAction = "play";
|
@property() public action: MediaPlayerBrowseAction = "play";
|
||||||
|
|
||||||
@property({ type: Boolean }) public dialog = false;
|
@property({ type: Boolean }) public dialog = false;
|
||||||
@ -76,11 +78,13 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
@property({ type: Boolean, attribute: "scroll", reflect: true })
|
@property({ type: Boolean, attribute: "scroll", reflect: true })
|
||||||
private _scrolled = false;
|
private _scrolled = false;
|
||||||
|
|
||||||
@state() private _loading = false;
|
@property() public navigateIds!: MediaPlayerItemId[];
|
||||||
|
|
||||||
@state() private _error?: { message: string; code: string };
|
@state() private _error?: { message: string; code: string };
|
||||||
|
|
||||||
@state() private _mediaPlayerItems: MediaPlayerItem[] = [];
|
@state() private _parentItem?: MediaPlayerItem;
|
||||||
|
|
||||||
|
@state() private _currentItem?: MediaPlayerItem;
|
||||||
|
|
||||||
@query(".header") private _header?: HTMLDivElement;
|
@query(".header") private _header?: HTMLDivElement;
|
||||||
|
|
||||||
@ -109,47 +113,18 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public navigateBack() {
|
|
||||||
this._mediaPlayerItems!.pop();
|
|
||||||
const item = this._mediaPlayerItems!.pop();
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._navigate(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (this._loading) {
|
if (this._error) {
|
||||||
|
return html`
|
||||||
|
<div class="container">${this._renderError(this._error)}</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._currentItem) {
|
||||||
return html`<ha-circular-progress active></ha-circular-progress>`;
|
return html`<ha-circular-progress active></ha-circular-progress>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._error && !this._mediaPlayerItems.length) {
|
const currentItem = this._currentItem;
|
||||||
if (this.dialog) {
|
|
||||||
this._closeDialogAction();
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.hass.localize(
|
|
||||||
"ui.components.media-browser.media_browsing_error"
|
|
||||||
),
|
|
||||||
text: this._renderError(this._error),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return html`
|
|
||||||
<div class="container">${this._renderError(this._error)}</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._mediaPlayerItems.length) {
|
|
||||||
return html``;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentItem =
|
|
||||||
this._mediaPlayerItems[this._mediaPlayerItems.length - 1];
|
|
||||||
|
|
||||||
const previousItem: MediaPlayerItem | undefined =
|
|
||||||
this._mediaPlayerItems.length > 1
|
|
||||||
? this._mediaPlayerItems[this._mediaPlayerItems.length - 2]
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const subtitle = this.hass.localize(
|
const subtitle = this.hass.localize(
|
||||||
`ui.components.media-browser.class.${currentItem.media_class}`
|
`ui.components.media-browser.class.${currentItem.media_class}`
|
||||||
@ -202,11 +177,11 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
: html``}
|
: html``}
|
||||||
<div class="header-info">
|
<div class="header-info">
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
${previousItem
|
${this.navigateIds.length > 1
|
||||||
? html`
|
? html`
|
||||||
<div class="previous-title" @click=${this.navigateBack}>
|
<div class="previous-title" @click=${this.navigateBack}>
|
||||||
<ha-svg-icon .path=${mdiArrowLeft}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiArrowLeft}></ha-svg-icon>
|
||||||
${previousItem.title}
|
${this._parentItem ? this._parentItem.title : ""}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
@ -401,49 +376,115 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
this._attachResizeObserver();
|
this._attachResizeObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
|
if (changedProps.size > 1 || !changedProps.has("hass")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const oldHass = changedProps.get("hass") as this["hass"];
|
||||||
|
return oldHass === undefined || oldHass.localize !== this.hass.localize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public willUpdate(changedProps: PropertyValues<this>): void {
|
||||||
|
super.willUpdate(changedProps);
|
||||||
|
|
||||||
|
if (changedProps.has("entityId")) {
|
||||||
|
this._setError(undefined);
|
||||||
|
}
|
||||||
|
if (!changedProps.has("navigateIds")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const oldNavigateIds = changedProps.get("navigateIds") as
|
||||||
|
| this["navigateIds"]
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
// We're navigating. Reset the shizzle.
|
||||||
|
this._content?.scrollTo(0, 0);
|
||||||
|
this._scrolled = false;
|
||||||
|
const oldCurrentItem = this._currentItem;
|
||||||
|
const oldParentItem = this._parentItem;
|
||||||
|
this._currentItem = undefined;
|
||||||
|
this._parentItem = undefined;
|
||||||
|
const currentId = this.navigateIds[this.navigateIds.length - 1];
|
||||||
|
const parentId =
|
||||||
|
this.navigateIds.length > 1
|
||||||
|
? this.navigateIds[this.navigateIds.length - 2]
|
||||||
|
: undefined;
|
||||||
|
let currentProm: Promise<MediaPlayerItem> | undefined;
|
||||||
|
let parentProm: Promise<MediaPlayerItem> | undefined;
|
||||||
|
|
||||||
|
// See if we can take loading shortcuts if navigating to parent or child
|
||||||
|
if (
|
||||||
|
// Check if we navigated to a child
|
||||||
|
oldNavigateIds &&
|
||||||
|
this.navigateIds.length > oldNavigateIds.length &&
|
||||||
|
oldNavigateIds.every((oldVal, idx) => {
|
||||||
|
const curVal = this.navigateIds[idx];
|
||||||
|
return (
|
||||||
|
curVal.media_content_id === oldVal.media_content_id &&
|
||||||
|
curVal.media_content_type === oldVal.media_content_type
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
parentProm = Promise.resolve(oldCurrentItem!);
|
||||||
|
} else if (
|
||||||
|
// Check if we navigated to a parent
|
||||||
|
oldNavigateIds &&
|
||||||
|
this.navigateIds.length < oldNavigateIds.length &&
|
||||||
|
this.navigateIds.every((curVal, idx) => {
|
||||||
|
const oldVal = oldNavigateIds[idx];
|
||||||
|
return (
|
||||||
|
curVal.media_content_id === oldVal.media_content_id &&
|
||||||
|
curVal.media_content_type === oldVal.media_content_type
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
currentProm = Promise.resolve(oldParentItem!);
|
||||||
|
}
|
||||||
|
// Fetch current
|
||||||
|
if (!currentProm) {
|
||||||
|
currentProm = this._fetchData(
|
||||||
|
this.entityId,
|
||||||
|
currentId.media_content_id,
|
||||||
|
currentId.media_content_type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
currentProm.then(
|
||||||
|
(item) => {
|
||||||
|
this._currentItem = item;
|
||||||
|
},
|
||||||
|
(err) => this._setError(err)
|
||||||
|
);
|
||||||
|
// Fetch parent
|
||||||
|
if (!parentProm && parentId !== undefined) {
|
||||||
|
parentProm = this._fetchData(
|
||||||
|
this.entityId,
|
||||||
|
parentId.media_content_id,
|
||||||
|
parentId.media_content_type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (parentProm) {
|
||||||
|
parentProm.then((parent) => {
|
||||||
|
this._parentItem = parent;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
|
|
||||||
if (
|
if (changedProps.has("_scrolled")) {
|
||||||
changedProps.has("_mediaPlayerItems") &&
|
this._animateHeaderHeight();
|
||||||
this._mediaPlayerItems.length
|
} else if (changedProps.has("_currentItem")) {
|
||||||
) {
|
|
||||||
this._setHeaderHeight();
|
this._setHeaderHeight();
|
||||||
this._attachIntersectionObserver();
|
this._attachIntersectionObserver();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
private navigateBack() {
|
||||||
changedProps.get("_scrolled") !== undefined &&
|
fireEvent(this, "media-browsed", {
|
||||||
this._mediaPlayerItems.length
|
ids: this.navigateIds.slice(0, -1),
|
||||||
) {
|
back: true,
|
||||||
this._animateHeaderHeight();
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!changedProps.has("entityId") &&
|
|
||||||
!changedProps.has("mediaContentId") &&
|
|
||||||
!changedProps.has("mediaContentType") &&
|
|
||||||
!changedProps.has("action")
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProps.has("entityId")) {
|
|
||||||
this._error = undefined;
|
|
||||||
this._mediaPlayerItems = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._fetchData(this.mediaContentId, this.mediaContentType)
|
|
||||||
.then((itemData) => {
|
|
||||||
if (!itemData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._mediaPlayerItems = [itemData];
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this._error = err;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _setHeaderHeight() {
|
private async _setHeaderHeight() {
|
||||||
@ -497,54 +538,19 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._navigate(item);
|
fireEvent(this, "media-browsed", {
|
||||||
}
|
ids: [...this.navigateIds, item],
|
||||||
|
});
|
||||||
private async _navigate(item: MediaPlayerItem) {
|
|
||||||
this._error = undefined;
|
|
||||||
|
|
||||||
let itemData: MediaPlayerItem;
|
|
||||||
|
|
||||||
try {
|
|
||||||
itemData = await this._fetchData(
|
|
||||||
item.media_content_id,
|
|
||||||
item.media_content_type
|
|
||||||
);
|
|
||||||
} catch (err: any) {
|
|
||||||
showAlertDialog(this, {
|
|
||||||
title: this.hass.localize(
|
|
||||||
"ui.components.media-browser.media_browsing_error"
|
|
||||||
),
|
|
||||||
text: this._renderError(err),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._content?.scrollTo(0, 0);
|
|
||||||
this._scrolled = false;
|
|
||||||
this._mediaPlayerItems = [...this._mediaPlayerItems, itemData];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchData(
|
private async _fetchData(
|
||||||
|
entityId: string,
|
||||||
mediaContentId?: string,
|
mediaContentId?: string,
|
||||||
mediaContentType?: string
|
mediaContentType?: string
|
||||||
): Promise<MediaPlayerItem> {
|
): Promise<MediaPlayerItem> {
|
||||||
this._loading = true;
|
return entityId !== BROWSER_PLAYER
|
||||||
let itemData: any;
|
? browseMediaPlayer(this.hass, entityId, mediaContentId, mediaContentType)
|
||||||
try {
|
: browseLocalMediaPlayer(this.hass, mediaContentId);
|
||||||
itemData =
|
|
||||||
this.entityId !== BROWSER_PLAYER
|
|
||||||
? await browseMediaPlayer(
|
|
||||||
this.hass,
|
|
||||||
this.entityId,
|
|
||||||
mediaContentId,
|
|
||||||
mediaContentType
|
|
||||||
)
|
|
||||||
: await browseLocalMediaPlayer(this.hass, mediaContentId);
|
|
||||||
} finally {
|
|
||||||
this._loading = false;
|
|
||||||
}
|
|
||||||
return itemData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _measureCard(): void {
|
private _measureCard(): void {
|
||||||
@ -576,7 +582,7 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
* Load thumbnails for images on demand as they become visible.
|
* Load thumbnails for images on demand as they become visible.
|
||||||
*/
|
*/
|
||||||
private async _attachIntersectionObserver(): Promise<void> {
|
private async _attachIntersectionObserver(): Promise<void> {
|
||||||
if (!this._thumbnails) {
|
if (!("IntersectionObserver" in window) || !this._thumbnails) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this._intersectionObserver) {
|
if (!this._intersectionObserver) {
|
||||||
@ -605,15 +611,34 @@ export class HaMediaPlayerBrowse extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const observer = this._intersectionObserver!;
|
const observer = this._intersectionObserver!;
|
||||||
this._thumbnails.forEach((thumbnailCard) => {
|
for (const thumbnailCard of this._thumbnails) {
|
||||||
observer.observe(thumbnailCard);
|
observer.observe(thumbnailCard);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _closeDialogAction(): void {
|
private _closeDialogAction(): void {
|
||||||
fireEvent(this, "close-dialog");
|
fireEvent(this, "close-dialog");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _setError(error: any) {
|
||||||
|
if (!this.dialog) {
|
||||||
|
this._error = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._closeDialogAction();
|
||||||
|
showAlertDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.components.media-browser.media_browsing_error"
|
||||||
|
),
|
||||||
|
text: this._renderError(error),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _renderError(err: { message: string; code: string }) {
|
private _renderError(err: { message: string; code: string }) {
|
||||||
if (err.message === "Media directory does not exist.") {
|
if (err.message === "Media directory does not exist.") {
|
||||||
return html`
|
return html`
|
||||||
|
@ -21,13 +21,11 @@ import "./home-assistant-main";
|
|||||||
|
|
||||||
const useHash = __DEMO__;
|
const useHash = __DEMO__;
|
||||||
const curPath = () =>
|
const curPath = () =>
|
||||||
window.decodeURIComponent(
|
useHash ? location.hash.substring(1) : location.pathname;
|
||||||
useHash ? location.hash.substr(1) : location.pathname
|
|
||||||
);
|
|
||||||
|
|
||||||
const panelUrl = (path: string) => {
|
const panelUrl = (path: string) => {
|
||||||
const dividerPos = path.indexOf("/", 1);
|
const dividerPos = path.indexOf("/", 1);
|
||||||
return dividerPos === -1 ? path.substr(1) : path.substr(1, dividerPos - 1);
|
return dividerPos === -1 ? path.substring(1) : path.substring(1, dividerPos);
|
||||||
};
|
};
|
||||||
|
|
||||||
@customElement("home-assistant")
|
@customElement("home-assistant")
|
||||||
|
@ -16,6 +16,7 @@ import { supportsFeature } from "../../common/entity/supports-feature";
|
|||||||
import { navigate } from "../../common/navigate";
|
import { navigate } from "../../common/navigate";
|
||||||
import "../../components/ha-menu-button";
|
import "../../components/ha-menu-button";
|
||||||
import "../../components/media-player/ha-media-player-browse";
|
import "../../components/media-player/ha-media-player-browse";
|
||||||
|
import type { MediaPlayerItemId } from "../../components/media-player/ha-media-player-browse";
|
||||||
import {
|
import {
|
||||||
BROWSER_PLAYER,
|
BROWSER_PLAYER,
|
||||||
MediaPickedEvent,
|
MediaPickedEvent,
|
||||||
@ -36,8 +37,14 @@ class PanelMediaBrowser extends LitElement {
|
|||||||
|
|
||||||
@property() public route!: Route;
|
@property() public route!: Route;
|
||||||
|
|
||||||
// @ts-ignore
|
private _navigateIds: MediaPlayerItemId[] = [
|
||||||
@LocalStorage("mediaBrowseEntityId", true)
|
{
|
||||||
|
media_content_id: undefined,
|
||||||
|
media_content_type: undefined,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@LocalStorage("mediaBrowseEntityId")
|
||||||
private _entityId = BROWSER_PLAYER;
|
private _entityId = BROWSER_PLAYER;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@ -77,15 +84,17 @@ class PanelMediaBrowser extends LitElement {
|
|||||||
<ha-media-player-browse
|
<ha-media-player-browse
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.entityId=${this._entityId}
|
.entityId=${this._entityId}
|
||||||
|
.navigateIds=${this._navigateIds}
|
||||||
@media-picked=${this._mediaPicked}
|
@media-picked=${this._mediaPicked}
|
||||||
|
@media-browsed=${this._mediaBrowsed}
|
||||||
></ha-media-player-browse>
|
></ha-media-player-browse>
|
||||||
</div>
|
</div>
|
||||||
</ha-app-layout>
|
</ha-app-layout>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updated(changedProps: PropertyValues): void {
|
public willUpdate(changedProps: PropertyValues): void {
|
||||||
super.updated(changedProps);
|
super.willUpdate(changedProps);
|
||||||
|
|
||||||
if (!changedProps.has("route")) {
|
if (!changedProps.has("route")) {
|
||||||
return;
|
return;
|
||||||
@ -96,10 +105,28 @@ class PanelMediaBrowser extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const routePlayer = this.route.path.substring(1).split("/")[0];
|
const [routePlayer, ...navigateIdsEncoded] = this.route.path
|
||||||
|
.substring(1)
|
||||||
|
.split("/");
|
||||||
|
|
||||||
if (routePlayer !== this._entityId) {
|
if (routePlayer !== this._entityId) {
|
||||||
this._entityId = routePlayer;
|
this._entityId = routePlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._navigateIds = [
|
||||||
|
{
|
||||||
|
media_content_type: undefined,
|
||||||
|
media_content_id: undefined,
|
||||||
|
},
|
||||||
|
...navigateIdsEncoded.map((navigateId) => {
|
||||||
|
const [media_content_type, media_content_id] =
|
||||||
|
decodeURIComponent(navigateId).split(",");
|
||||||
|
return {
|
||||||
|
media_content_type,
|
||||||
|
media_content_id,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private _showSelectMediaPlayerDialog(): void {
|
private _showSelectMediaPlayerDialog(): void {
|
||||||
@ -111,6 +138,22 @@ class PanelMediaBrowser extends LitElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _mediaBrowsed(ev) {
|
||||||
|
if (ev.detail.back) {
|
||||||
|
history.back();
|
||||||
|
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}`);
|
||||||
|
}
|
||||||
|
|
||||||
private async _mediaPicked(
|
private async _mediaPicked(
|
||||||
ev: HASSDomEvent<MediaPickedEvent>
|
ev: HASSDomEvent<MediaPickedEvent>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user