Merge pull request #32 from dermotduffy/browse-folders

Add browsing of folders in media mini-gallery
This commit is contained in:
Dermot Duffy
2021-08-29 12:06:53 -07:00
committed by GitHub
2 changed files with 84 additions and 46 deletions
+16 -2
View File
@@ -44,6 +44,20 @@
@include image-list.shape-radius(5px); @include image-list.shape-radius(5px);
} }
ha-card .frigate-card-image-list-folder {
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
text-align: center;
border-style: 2px solid;
color: var(--secondary-text-color, white);
border-color: var(--secondary-text-color, black);
background-color: var(--primary-background-color, black);
--mdc-icon-size: 40px;
padding: 10px;
}
video, img { video, img {
display: block; display: block;
} }
@@ -61,8 +75,8 @@ ha-card {
transform-style: preserve-3d; /* Safari brings video elements forward without this */ transform-style: preserve-3d; /* Safari brings video elements forward without this */
} }
/* Don't drop shadow or have radius for nested cards: webrtc */ /* Don't drop shadow or have radius for nested webrtc card */
ha-card ha-card { webrtc-camera ha-card {
box-shadow: none; box-shadow: none;
border-radius: 0px; border-radius: 0px;
background-color: var(--secondary-background-color, black); background-color: var(--secondary-background-color, black);
+68 -44
View File
@@ -120,9 +120,13 @@ export class FrigateCardMenu extends LitElement {
// Call the callback. // Call the callback.
protected _callAction(name: string): void { protected _callAction(name: string): void {
if (name == 'frigate' && this.menuMode == 'hidden') { if (this.menuMode == 'hidden') {
this.expand = !this.expand; if (name == 'frigate') {
return; this.expand = !this.expand;
return;
}
// Collapse menu after the user clicks on something.
this.expand = false;
} }
if (this.actionCallback) { if (this.actionCallback) {
@@ -133,7 +137,7 @@ export class FrigateCardMenu extends LitElement {
// Render a menu button. // Render a menu button.
protected _renderButton(name: string, button: MenuButton): TemplateResult { protected _renderButton(name: string, button: MenuButton): TemplateResult {
return html` <ha-icon-button return html` <ha-icon-button
class=${button.emphasize ? "emphasized-button" : "button"} class=${button.emphasize ? 'emphasized-button' : 'button'}
icon=${button.icon || 'mdi:gesture-tap-button'} icon=${button.icon || 'mdi:gesture-tap-button'}
data-toggle="tooltip" data-toggle="tooltip"
title=${button.description} title=${button.description}
@@ -215,7 +219,7 @@ export class FrigateCard extends LitElement {
protected _interactionTimerID: number | null = null; protected _interactionTimerID: number | null = null;
protected _webrtcElement: any | null = null; protected _webrtcElement: any | null = null;
// Event specifically requested to be shown by the user. // A specific media source requested by the user.
@property({ attribute: false }) @property({ attribute: false })
protected _requestedMediaSource: BrowseMediaSource | null = null; protected _requestedMediaSource: BrowseMediaSource | null = null;
@@ -315,22 +319,14 @@ export class FrigateCard extends LitElement {
this._changeView(); this._changeView();
} }
// Update the card view.
protected _changeView( protected _changeView(
view?: FrigateCardView | undefined, view?: FrigateCardView | undefined,
mediaSource?: BrowseMediaSource | undefined, mediaSource?: BrowseMediaSource | undefined,
): void { ): void {
if (view !== undefined) { this._viewMode = view || this.config.view_default;
this._viewMode = view; this._requestedMediaSource = mediaSource || null;
} else {
this._viewMode = this.config.view_default;
if (['clip', 'snapshot'].includes(this.config.view_default)) {
this._requestedMediaSource = null;
}
}
this._mediaBeingShown = null; this._mediaBeingShown = null;
if (mediaSource !== undefined) {
this._requestedMediaSource = mediaSource;
}
} }
// Determine whether the card should be updated. // Determine whether the card should be updated.
@@ -388,17 +384,27 @@ export class FrigateCard extends LitElement {
return parseResult.data; return parseResult.data;
} }
// Browse Frigate media. // Browse Frigate media with a media content id.
protected async _browseMedia( protected async _browseMedia(
media_content_id: string,
): Promise<BrowseMediaSource | null> {
const request = {
type: 'media_source/browse_media',
media_content_id: media_content_id,
};
return this._makeWSRequest(browseMediaSourceSchema, request);
}
// Browse Frigate media with query parameters.
protected async _browseMediaQuery(
want_clips?: boolean, want_clips?: boolean,
before?: number, before?: number,
after?: number, after?: number,
): Promise<BrowseMediaSource | null> { ): Promise<BrowseMediaSource | null> {
// Defined in: return this._browseMedia(
// https://github.com/blakeblackshear/frigate-hass-integration/blob/master/custom_components/frigate/media_source.py // Defined in:
const request = { // https://github.com/blakeblackshear/frigate-hass-integration/blob/master/custom_components/frigate/media_source.py
type: 'media_source/browse_media', [
media_content_id: [
'media-source://frigate', 'media-source://frigate',
this.config.frigate_client_id, this.config.frigate_client_id,
'event-search', 'event-search',
@@ -410,8 +416,7 @@ export class FrigateCard extends LitElement {
this.config.label, this.config.label,
this.config.zone, this.config.zone,
].join('/'), ].join('/'),
}; );
return this._makeWSRequest(browseMediaSourceSchema, request);
} }
// Resolve Frigate media identifier to a real URL. // Resolve Frigate media identifier to a real URL.
@@ -453,7 +458,11 @@ export class FrigateCard extends LitElement {
const want_clips = this._viewMode == 'clips'; const want_clips = this._viewMode == 'clips';
let media; let media;
try { try {
media = await this._browseMedia(want_clips); if (this._requestedMediaSource) {
media = await this._browseMedia(this._requestedMediaSource.media_content_id);
} else {
media = await this._browseMediaQuery(want_clips);
}
} catch (e: any) { } catch (e: any) {
return this._renderError(e.message); return this._renderError(e.message);
} }
@@ -466,22 +475,33 @@ export class FrigateCard extends LitElement {
} }
return html` <ul class="mdc-image-list frigate-card-image-list"> return html` <ul class="mdc-image-list frigate-card-image-list">
${media.children.map((mediaSource) => ${media.children.map(
mediaSource.can_expand (mediaSource) =>
? '' html` <li class="mdc-image-list__item">
: html` <li class="mdc-image-list__item"> <div class="mdc-image-list__image-aspect-container">
<div class="mdc-image-list__image-aspect-container"> ${mediaSource.can_expand
<img ? html`<div class="mdc-image-list__image">
data-toggle="tooltip" <ha-card
title="${mediaSource.title}" @click=${() => {
class="mdc-image-list__image" this._changeView(this._viewMode, mediaSource);
src="${mediaSource.thumbnail}" }}
@click=${() => { outlined=""
this._changeView(want_clips ? 'clip' : 'snapshot', mediaSource); class="frigate-card-image-list-folder"
}} >
/> <div>${mediaSource.title}</div>
</div> </ha-card>
</li>`, </div>`
: html`<img
data-toggle="tooltip"
title="${mediaSource.title}"
class="mdc-image-list__image"
src="${mediaSource.thumbnail}"
@click=${() => {
this._changeView(want_clips ? 'clip' : 'snapshot', mediaSource);
}}
/>`}
</div>
</li>`,
)} )}
</ul>`; </ul>`;
} }
@@ -645,7 +665,7 @@ export class FrigateCard extends LitElement {
} else { } else {
let media; let media;
try { try {
media = await this._browseMedia(true); media = await this._browseMediaQuery(true);
} catch (e: any) { } catch (e: any) {
return this._renderError(e.message); return this._renderError(e.message);
} }
@@ -726,7 +746,11 @@ export class FrigateCard extends LitElement {
if (startTime) { if (startTime) {
try { try {
// Fetch clips within the same second (same camera/zone/label, etc). // Fetch clips within the same second (same camera/zone/label, etc).
const clipsAtSameTime = await this._browseMedia(true, startTime + 1, startTime); const clipsAtSameTime = await this._browseMediaQuery(
true,
startTime + 1,
startTime,
);
if (clipsAtSameTime) { if (clipsAtSameTime) {
return this._getFirstTrueMediaItem(clipsAtSameTime); return this._getFirstTrueMediaItem(clipsAtSameTime);
} }
@@ -745,7 +769,7 @@ export class FrigateCard extends LitElement {
} else { } else {
let media; let media;
try { try {
media = await this._browseMedia(false); media = await this._browseMediaQuery(false);
} catch (e: any) { } catch (e: any) {
return this._renderError(e.message); return this._renderError(e.message);
} }