diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts
index df10572558..8f54e1204c 100644
--- a/src/components/media-player/ha-media-player-browse.ts
+++ b/src/components/media-player/ha-media-player-browse.ts
@@ -68,6 +68,8 @@ export class HaMediaPlayerBrowse extends LitElement {
@internalProperty() private _loading = false;
+ @internalProperty() private _error?: { message: string; code: string };
+
@internalProperty() private _mediaPlayerItems: MediaPlayerItem[] = [];
private _resizeObserver?: ResizeObserver;
@@ -92,11 +94,55 @@ export class HaMediaPlayerBrowse extends LitElement {
this._navigate(item);
}
+ private _renderError(err: { message: string; code: string }) {
+ if (err.message === "Media directory does not exist.") {
+ return html`
+
No local media found.
+
+ It looks like you have not yet created a media directory.
+
Create a directory with the name "media" in the
+ configuration directory of Home Assistant
+ (${this.hass.config.config_dir}).
Place your video, audio and
+ image files in this directory to be able to browse and play them in
+ the browser or on supported media players.
+
+
+
+ Check the
+ documentation
+ for more info
+
+ `;
+ }
+ return err.message;
+ }
+
protected render(): TemplateResult {
if (this._loading) {
return html``;
}
+ if (this._error && !this._mediaPlayerItems.length) {
+ 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`
+ ${this._renderError(this._error)}
+
`;
+ }
+ }
+
if (!this._mediaPlayerItems.length) {
return html``;
}
@@ -216,7 +262,11 @@ export class HaMediaPlayerBrowse extends LitElement {
`
: ""}
- ${currentItem.children?.length
+ ${this._error
+ ? html`
+ ${this._renderError(this._error)}
+
`
+ : currentItem.children?.length
? hasExpandableChildren
? html`
@@ -316,7 +366,9 @@ export class HaMediaPlayerBrowse extends LitElement {
)}
`
- : this.hass.localize("ui.components.media-browser.no_items")}
+ : html`
+ ${this.hass.localize("ui.components.media-browser.no_items")}
+
`}
`;
}
@@ -342,15 +394,22 @@ export class HaMediaPlayerBrowse extends LitElement {
return;
}
- this._fetchData(this.mediaContentId, this.mediaContentType).then(
- (itemData) => {
+ 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 _actionClicked(ev: MouseEvent): void {
@@ -381,12 +440,22 @@ export class HaMediaPlayerBrowse extends LitElement {
}
private async _navigate(item: MediaPlayerItem) {
- const itemData = await this._fetchData(
- item.media_content_id,
- item.media_content_type
- );
+ this._error = undefined;
- if (!itemData) {
+ let itemData: MediaPlayerItem;
+
+ try {
+ itemData = await this._fetchData(
+ item.media_content_id,
+ item.media_content_type
+ );
+ } catch (err) {
+ showAlertDialog(this, {
+ title: this.hass.localize(
+ "ui.components.media-browser.media_browsing_error"
+ ),
+ text: this._renderError(err),
+ });
return;
}
@@ -397,33 +466,23 @@ export class HaMediaPlayerBrowse extends LitElement {
private async _fetchData(
mediaContentId?: string,
mediaContentType?: string
- ): Promise
{
- let itemData: MediaPlayerItem | undefined;
- try {
- itemData =
- this.entityId !== BROWSER_SOURCE
- ? await browseMediaPlayer(
- this.hass,
- this.entityId,
- mediaContentId,
- mediaContentType
- )
- : await browseLocalMediaPlayer(this.hass, mediaContentId);
- itemData.children = itemData.children?.sort((first, second) =>
- !first.can_expand && second.can_expand
- ? 1
- : first.can_expand && !second.can_expand
- ? -1
- : compare(first.title, second.title)
- );
- } catch (error) {
- showAlertDialog(this, {
- title: this.hass.localize(
- "ui.components.media-browser.media_browsing_error"
- ),
- text: error.message,
- });
- }
+ ): Promise {
+ const itemData =
+ this.entityId !== BROWSER_SOURCE
+ ? await browseMediaPlayer(
+ this.hass,
+ this.entityId,
+ mediaContentId,
+ mediaContentType
+ )
+ : await browseLocalMediaPlayer(this.hass, mediaContentId);
+ itemData.children = itemData.children?.sort((first, second) =>
+ !first.can_expand && second.can_expand
+ ? 1
+ : first.can_expand && !second.can_expand
+ ? -1
+ : compare(first.title, second.title)
+ );
return itemData;
}
@@ -451,8 +510,8 @@ export class HaMediaPlayerBrowse extends LitElement {
this._resizeObserver.observe(this);
}
- private _hasExpandableChildren = memoizeOne((children) =>
- children.find((item: MediaPlayerItem) => item.can_expand)
+ private _hasExpandableChildren = memoizeOne((children?: MediaPlayerItem[]) =>
+ children?.find((item: MediaPlayerItem) => item.can_expand)
);
private _closeDialogAction(): void {
@@ -471,6 +530,10 @@ export class HaMediaPlayerBrowse extends LitElement {
flex-direction: column;
}
+ .container {
+ padding: 16px;
+ }
+
.header {
display: flex;
justify-content: space-between;