From 72a14ec6cc369b86f3e3c6c409b630a9d9301425 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 8 Feb 2022 22:52:06 -0800 Subject: [PATCH 1/5] Allow uploading media --- .../media-player/ha-media-player-browse.ts | 17 +++++ src/data/media_source.ts | 23 +++++++ .../media-browser/ha-panel-media-browser.ts | 63 +++++++++++++++---- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index 6eccdd42a932..f61a503bbcfc 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -101,6 +101,10 @@ export class HaMediaPlayerBrowse extends LitElement { // @ts-ignore private _intersectionObserver?: IntersectionObserver; + public get currentItem(): MediaPlayerItem | undefined { + return this._currentItem; + } + public connectedCallback(): void { super.connectedCallback(); this.updateComplete.then(() => this._attachResizeObserver()); @@ -115,6 +119,19 @@ export class HaMediaPlayerBrowse extends LitElement { } } + public async refresh() { + const currentId = this.navigateIds[this.navigateIds.length - 1]; + try { + this._currentItem = await this._fetchData( + this.entityId, + currentId.media_content_id, + currentId.media_content_type + ); + } catch (err) { + this._setError(err); + } + } + public play(): void { if (this._currentItem?.can_play) { this._runAction(this._currentItem); diff --git a/src/data/media_source.ts b/src/data/media_source.ts index 759be2a7d354..a56b943cbaa4 100644 --- a/src/data/media_source.ts +++ b/src/data/media_source.ts @@ -23,3 +23,26 @@ export const browseLocalMediaPlayer = ( type: "media_source/browse_media", media_content_id: mediaContentId, }); + +export const isLocalMediaSourceContentId = (mediaId: string) => + mediaId.startsWith("media-source://media_source"); + +export const uploadLocalMedia = async ( + hass: HomeAssistant, + media_content_id: string, + file: File +) => { + const fd = new FormData(); + fd.append("media_content_id", media_content_id); + fd.append("file", file); + const resp = await hass.fetchWithAuth("/api/media_source/upload", { + method: "POST", + body: fd, + }); + if (resp.status === 413) { + throw new Error("Uploaded image is too large"); + } else if (resp.status !== 200) { + throw new Error("Unknown error"); + } + return resp.json(); +}; diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts index 95931759cb43..ba1e3fb4696f 100644 --- a/src/panels/media-browser/ha-panel-media-browser.ts +++ b/src/panels/media-browser/ha-panel-media-browser.ts @@ -1,4 +1,4 @@ -import { mdiArrowLeft } from "@mdi/js"; +import { mdiArrowLeft, mdiUpload } from "@mdi/js"; import "@polymer/app-layout/app-header/app-header"; import "@polymer/app-layout/app-toolbar/app-toolbar"; import { @@ -9,20 +9,27 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property } from "lit/decorators"; +import { customElement, property, query } from "lit/decorators"; import { LocalStorage } from "../../common/decorators/local-storage"; import { HASSDomEvent } from "../../common/dom/fire_event"; import { navigate } from "../../common/navigate"; import "../../components/ha-menu-button"; import "../../components/ha-icon-button"; import "../../components/media-player/ha-media-player-browse"; -import type { MediaPlayerItemId } from "../../components/media-player/ha-media-player-browse"; +import type { + HaMediaPlayerBrowse, + MediaPlayerItemId, +} from "../../components/media-player/ha-media-player-browse"; import { BROWSER_PLAYER, MediaPickedEvent, MediaPlayerItem, } from "../../data/media-player"; -import { resolveMediaSource } from "../../data/media_source"; +import { + isLocalMediaSourceContentId, + resolveMediaSource, + uploadLocalMedia, +} from "../../data/media_source"; import "../../layouts/ha-app-layout"; import { haStyle } from "../../resources/styles"; import type { HomeAssistant, Route } from "../../types"; @@ -51,6 +58,8 @@ class PanelMediaBrowser extends LitElement { @LocalStorage("mediaBrowseEntityId", true, false) private _entityId = BROWSER_PLAYER; + @query("ha-media-player-browse") private _browser!: HaMediaPlayerBrowse; + protected render(): TemplateResult { return html` @@ -69,15 +78,25 @@ class PanelMediaBrowser extends LitElement { .narrow=${this.narrow} > `} -
-
- ${!this._currentItem - ? this.hass.localize( - "ui.components.media-browser.media-player-browser" - ) - : this._currentItem.title} -
+
+ ${!this._currentItem + ? this.hass.localize( + "ui.components.media-browser.media-player-browser" + ) + : this._currentItem.title}
+ ${isLocalMediaSourceContentId( + this._navigateIds[this._navigateIds.length - 1] + .media_content_id || "" + ) + ? html` + + ` + : ""} { + try { + await uploadLocalMedia( + this.hass, + this._browser.currentItem!.media_content_id!, + input.files![0] + ); + } catch (err) { + alert(err); + return; + } + + await this._browser.refresh(); + }); + input.click(); + } + static get styles(): CSSResultGroup { return [ haStyle, From c8265b153bade019cfc9c8255f554d99f014876b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Feb 2022 08:24:04 -0800 Subject: [PATCH 2/5] Update path --- src/data/media_source.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/data/media_source.ts b/src/data/media_source.ts index a56b943cbaa4..dfcdbb37ab08 100644 --- a/src/data/media_source.ts +++ b/src/data/media_source.ts @@ -35,10 +35,13 @@ export const uploadLocalMedia = async ( const fd = new FormData(); fd.append("media_content_id", media_content_id); fd.append("file", file); - const resp = await hass.fetchWithAuth("/api/media_source/upload", { - method: "POST", - body: fd, - }); + const resp = await hass.fetchWithAuth( + "/api/media_source/local_source/upload", + { + method: "POST", + body: fd, + } + ); if (resp.status === 413) { throw new Error("Uploaded image is too large"); } else if (resp.status !== 200) { From 0d85cccf4c93f703c8a0ba82485fae37f751bba2 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 9 Feb 2022 22:36:41 -0800 Subject: [PATCH 3/5] Use current item we already have --- .../media-player/ha-media-player-browse.ts | 4 ---- src/panels/media-browser/ha-panel-media-browser.ts | 12 ++++++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index f61a503bbcfc..9310285c1660 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -101,10 +101,6 @@ export class HaMediaPlayerBrowse extends LitElement { // @ts-ignore private _intersectionObserver?: IntersectionObserver; - public get currentItem(): MediaPlayerItem | undefined { - return this._currentItem; - } - public connectedCallback(): void { super.connectedCallback(); this.updateComplete.then(() => this._attachResizeObserver()); diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts index ba1e3fb4696f..8d5eaa54103b 100644 --- a/src/panels/media-browser/ha-panel-media-browser.ts +++ b/src/panels/media-browser/ha-panel-media-browser.ts @@ -9,7 +9,7 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { LocalStorage } from "../../common/decorators/local-storage"; import { HASSDomEvent } from "../../common/dom/fire_event"; import { navigate } from "../../common/navigate"; @@ -46,7 +46,7 @@ class PanelMediaBrowser extends LitElement { @property() public route!: Route; - @property() _currentItem?: MediaPlayerItem; + @state() _currentItem?: MediaPlayerItem; private _navigateIds: MediaPlayerItemId[] = [ { @@ -85,9 +85,9 @@ class PanelMediaBrowser extends LitElement { ) : this._currentItem.title}
- ${isLocalMediaSourceContentId( - this._navigateIds[this._navigateIds.length - 1] - .media_content_id || "" + ${this._currentItem && + isLocalMediaSourceContentId( + this._currentItem.media_content_id || "" ) ? html` Date: Thu, 10 Feb 2022 09:15:18 -0800 Subject: [PATCH 4/5] Update src/panels/media-browser/ha-panel-media-browser.ts Co-authored-by: Bram Kragten --- src/panels/media-browser/ha-panel-media-browser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts index 8d5eaa54103b..e371fb51f4ac 100644 --- a/src/panels/media-browser/ha-panel-media-browser.ts +++ b/src/panels/media-browser/ha-panel-media-browser.ts @@ -91,7 +91,7 @@ class PanelMediaBrowser extends LitElement { ) ? html` From e56644c732e9776385c1e6e97bf8f2fa9d84b3dd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 10 Feb 2022 09:33:57 -0800 Subject: [PATCH 5/5] Use alert dialog and use button for add media --- .../media-browser/ha-panel-media-browser.ts | 29 ++++++++++++++----- src/translations/en.json | 4 +++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/panels/media-browser/ha-panel-media-browser.ts b/src/panels/media-browser/ha-panel-media-browser.ts index e371fb51f4ac..299a401325f5 100644 --- a/src/panels/media-browser/ha-panel-media-browser.ts +++ b/src/panels/media-browser/ha-panel-media-browser.ts @@ -1,6 +1,7 @@ import { mdiArrowLeft, mdiUpload } from "@mdi/js"; import "@polymer/app-layout/app-header/app-header"; import "@polymer/app-layout/app-toolbar/app-toolbar"; +import "@material/mwc-button"; import { css, CSSResultGroup, @@ -15,6 +16,7 @@ import { HASSDomEvent } from "../../common/dom/fire_event"; import { navigate } from "../../common/navigate"; import "../../components/ha-menu-button"; import "../../components/ha-icon-button"; +import "../../components/ha-svg-icon"; import "../../components/media-player/ha-media-player-browse"; import type { HaMediaPlayerBrowse, @@ -90,11 +92,14 @@ class PanelMediaBrowser extends LitElement { this._currentItem.media_content_id || "" ) ? html` - + > + + ` : ""} @@ -229,11 +234,17 @@ class PanelMediaBrowser extends LitElement { this._currentItem!.media_content_id!, input.files![0] ); - } catch (err) { - alert(err); + } catch (err: any) { + showAlertDialog(this, { + text: this.hass.localize( + "ui.components.media-browser.file_management.upload_failed", + { + reason: err.message || err, + } + ), + }); return; } - await this._browser.refresh(); }); input.click(); @@ -261,6 +272,10 @@ class PanelMediaBrowser extends LitElement { left: 0; right: 0; } + + ha-svg-icon[slot="icon"] { + vertical-align: middle; + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index ed8ff943bf6b..d6f8ed25a1ca 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -524,6 +524,10 @@ "no_local_media_found": "No local media found", "no_media_folder": "It looks like you have not yet created a media directory.", "setup_local_help": "Check the {documentation} on how to setup local media.", + "file_management": { + "upload_failed": "Upload failed: {reason}", + "add_media": "Add Media" + }, "class": { "album": "Album", "app": "App",