Allow uploading media (#11615)

* Allow uploading media

* Update path

* Use current item we already have

* Update src/panels/media-browser/ha-panel-media-browser.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

* Use alert dialog and use button for add media

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Paulus Schoutsen 2022-02-10 09:54:01 -08:00 committed by GitHub
parent cefa2ee183
commit d7a5921e7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 13 deletions

View File

@ -114,6 +114,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 { public play(): void {
if (this._currentItem?.can_play) { if (this._currentItem?.can_play) {
this._runAction(this._currentItem); this._runAction(this._currentItem);

View File

@ -23,3 +23,29 @@ export const browseLocalMediaPlayer = (
type: "media_source/browse_media", type: "media_source/browse_media",
media_content_id: mediaContentId, 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/local_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();
};

View File

@ -1,6 +1,7 @@
import { mdiArrowLeft } from "@mdi/js"; import { mdiArrowLeft, mdiUpload } from "@mdi/js";
import "@polymer/app-layout/app-header/app-header"; import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar"; import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@material/mwc-button";
import { import {
css, css,
CSSResultGroup, CSSResultGroup,
@ -9,20 +10,28 @@ import {
PropertyValues, PropertyValues,
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { LocalStorage } from "../../common/decorators/local-storage"; import { LocalStorage } from "../../common/decorators/local-storage";
import { fireEvent, HASSDomEvent } from "../../common/dom/fire_event"; import { fireEvent, HASSDomEvent } from "../../common/dom/fire_event";
import { navigate } from "../../common/navigate"; import { navigate } from "../../common/navigate";
import "../../components/ha-menu-button"; import "../../components/ha-menu-button";
import "../../components/ha-icon-button"; import "../../components/ha-icon-button";
import "../../components/ha-svg-icon";
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 type {
HaMediaPlayerBrowse,
MediaPlayerItemId,
} from "../../components/media-player/ha-media-player-browse";
import { import {
BROWSER_PLAYER, BROWSER_PLAYER,
MediaPickedEvent, MediaPickedEvent,
MediaPlayerItem, MediaPlayerItem,
} from "../../data/media-player"; } from "../../data/media-player";
import { resolveMediaSource } from "../../data/media_source"; import {
isLocalMediaSourceContentId,
resolveMediaSource,
uploadLocalMedia,
} from "../../data/media_source";
import "../../layouts/ha-app-layout"; import "../../layouts/ha-app-layout";
import { haStyle } from "../../resources/styles"; import { haStyle } from "../../resources/styles";
import type { HomeAssistant, Route } from "../../types"; import type { HomeAssistant, Route } from "../../types";
@ -43,7 +52,7 @@ class PanelMediaBrowser extends LitElement {
@property() public route!: Route; @property() public route!: Route;
@property() _currentItem?: MediaPlayerItem; @state() _currentItem?: MediaPlayerItem;
private _navigateIds: MediaPlayerItemId[] = [ private _navigateIds: MediaPlayerItemId[] = [
{ {
@ -55,6 +64,8 @@ class PanelMediaBrowser extends LitElement {
@LocalStorage("mediaBrowseEntityId", true, false) @LocalStorage("mediaBrowseEntityId", true, false)
private _entityId = BROWSER_PLAYER; private _entityId = BROWSER_PLAYER;
@query("ha-media-player-browse") private _browser!: HaMediaPlayerBrowse;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<ha-app-layout> <ha-app-layout>
@ -73,15 +84,28 @@ class PanelMediaBrowser extends LitElement {
.narrow=${this.narrow} .narrow=${this.narrow}
></ha-menu-button> ></ha-menu-button>
`} `}
<div main-title class="heading"> <div main-title>
<div> ${!this._currentItem
${!this._currentItem ? this.hass.localize(
? this.hass.localize( "ui.components.media-browser.media-player-browser"
"ui.components.media-browser.media-player-browser" )
) : this._currentItem.title}
: this._currentItem.title}
</div>
</div> </div>
${this._currentItem &&
isLocalMediaSourceContentId(
this._currentItem.media_content_id || ""
)
? html`
<mwc-button
.label=${this.hass.localize(
"ui.components.media-browser.file_management.add_media"
)}
@click=${this._startUpload}
>
<ha-svg-icon .path=${mdiUpload} slot="icon"></ha-svg-icon>
</mwc-button>
`
: ""}
</app-toolbar> </app-toolbar>
</app-header> </app-header>
<ha-media-player-browse <ha-media-player-browse
@ -215,6 +239,32 @@ class PanelMediaBrowser extends LitElement {
}); });
} }
private async _startUpload() {
const input = document.createElement("input");
input.type = "file";
input.addEventListener("change", async () => {
try {
await uploadLocalMedia(
this.hass,
this._currentItem!.media_content_id!,
input.files![0]
);
} 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();
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
haStyle, haStyle,
@ -237,6 +287,10 @@ class PanelMediaBrowser extends LitElement {
left: 0; left: 0;
right: 0; right: 0;
} }
ha-svg-icon[slot="icon"] {
vertical-align: middle;
}
`, `,
]; ];
} }

View File

@ -524,6 +524,10 @@
"no_local_media_found": "No local media found", "no_local_media_found": "No local media found",
"no_media_folder": "It looks like you have not yet created a media directory.", "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.", "setup_local_help": "Check the {documentation} on how to setup local media.",
"file_management": {
"upload_failed": "Upload failed: {reason}",
"add_media": "Add Media"
},
"class": { "class": {
"album": "Album", "album": "Album",
"app": "App", "app": "App",