Fix thumbnails for non-gallery views.

This commit is contained in:
Dermot Duffy
2022-04-16 21:59:36 -07:00
parent ba196ff003
commit 0e751478d2
12 changed files with 91 additions and 42 deletions
+6 -6
View File
@@ -170,7 +170,7 @@ menu:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `mode` | `hidden-top` | :white_check_mark: | The menu mode to show by default. See [menu modes](#menu-modes) below.| | `mode` | `hidden-top` | :white_check_mark: | The menu mode to show by default. See [menu modes](#menu-modes) below.|
| `button_size` | `40px` | :white_check_mark: | The size of the menu buttons [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `button_size` | 40 | :white_check_mark: | The size of the menu buttons in pixels.|
| `buttons` | | :white_check_mark: | Whether to show or hide built-in buttons. See below. | | `buttons` | | :white_check_mark: | Whether to show or hide built-in buttons. See below. |
#### Menu Options: Buttons #### Menu Options: Buttons
@@ -258,7 +258,7 @@ live:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `mode` | `none` | :white_check_mark: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).| | `mode` | `none` | :white_check_mark: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).|
| `size` | `100px` | :white_check_mark: | The size of the thumbnails in the thumbnail carousel [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `size` | 100 | :white_check_mark: | The size of the thumbnails in the thumbnail carousel in pixels.|
| `show_details` | `false` | :white_check_mark: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.| | `show_details` | `false` | :white_check_mark: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.|
| `show_controls` | `true` | :white_check_mark: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.| | `show_controls` | `true` | :white_check_mark: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.|
| `media` | `clips` | :white_check_mark: | Whether to show `clips` or `snapshots` in the thumbnail carousel in the `live` view.| | `media` | `clips` | :white_check_mark: | Whether to show `clips` or `snapshots` in the thumbnail carousel in the `live` view.|
@@ -276,7 +276,7 @@ live:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `style` | `chevrons` | :white_check_mark: | When viewing live cameras, what kind of controls to show to move to the previous/next camera. Acceptable values: `chevrons`, `icons`, `none` . | | `style` | `chevrons` | :white_check_mark: | When viewing live cameras, what kind of controls to show to move to the previous/next camera. Acceptable values: `chevrons`, `icons`, `none` . |
| `size` | `48px` | :white_check_mark: | The size of the next/previous controls [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `size` | 48 | :white_check_mark: | The size of the next/previous controls in pixels.|
<a name="live-controls-title"></a> <a name="live-controls-title"></a>
@@ -328,7 +328,7 @@ event_viewer:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `style` | `thumbnails` | :heavy_multiplication_x: | When viewing media, what kind of controls to show to move to the previous/next media item. Acceptable values: `thumbnails`, `chevrons`, `none` . | | `style` | `thumbnails` | :heavy_multiplication_x: | When viewing media, what kind of controls to show to move to the previous/next media item. Acceptable values: `thumbnails`, `chevrons`, `none` . |
| `size` | `48px` | :heavy_multiplication_x: | The size of the next/previous controls [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `size` | 48 | :heavy_multiplication_x: | The size of the next/previous controls in pixels.|
#### Event Viewer Controls: Thumbnails #### Event Viewer Controls: Thumbnails
@@ -343,7 +343,7 @@ event_viewer:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `mode` | `none` | :heavy_multiplication_x: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).| | `mode` | `none` | :heavy_multiplication_x: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).|
| `size` | `100px` | :heavy_multiplication_x: | The size of the thumbnails in the thumbnail carousel [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `size` | 100 | :heavy_multiplication_x: | The size of the thumbnails in the thumbnail carousel pixels.|
| `show_details` | `false` | :heavy_multiplication_x: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.| | `show_details` | `false` | :heavy_multiplication_x: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.|
| `show_controls` | `true` | :heavy_multiplication_x: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.| | `show_controls` | `true` | :heavy_multiplication_x: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.|
@@ -423,7 +423,7 @@ timeline:
| Option | Default | Overridable | Description | | Option | Default | Overridable | Description |
| - | - | - | - | | - | - | - | - |
| `mode` | `none` | :heavy_multiplication_x: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).| | `mode` | `none` | :heavy_multiplication_x: | Whether to show the thumbnail carousel `below` the media, `above` the media, in a drawer to the `left` or `right` of the media or to hide it entirely (`none`).|
| `size` | `100px` | :heavy_multiplication_x: | The size of the thumbnails in the thumbnail carousel [in CSS Units](https://www.w3schools.com/cssref/css_units.asp).| | `size` | 100 | :heavy_multiplication_x: | The size of the thumbnails in the thumbnail carousel in pixels.|
| `show_details` | `false` | :heavy_multiplication_x: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.| | `show_details` | `false` | :heavy_multiplication_x: | Whether to show event details (e.g. duration, start time, object detected, etc) alongside the thumbnail.|
| `show_controls` | `true` | :heavy_multiplication_x: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.| | `show_controls` | `true` | :heavy_multiplication_x: | Whether to show event controls (e.g. timeline icon, favorite icon) alongside the thumbnail.|
+1 -2
View File
@@ -1,6 +1,5 @@
// TODO: Add details & controls & size support // TODO: Add details & controls & size support
// TODO: Remove mini support if it's not actually needed? // TODO: automatic upgrade for thumbnail sizes in px and menu buttons in px
// TODO: automatic upgrade for thumbnail sizes in px
// TODO: automatic remove of min_columns // TODO: automatic remove of min_columns
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
+4 -1
View File
@@ -60,7 +60,10 @@ export class FrigateCardMenu extends LitElement {
set menuConfig(menuConfig: MenuConfig) { set menuConfig(menuConfig: MenuConfig) {
this._menuConfig = menuConfig; this._menuConfig = menuConfig;
if (menuConfig) { if (menuConfig) {
this.style.setProperty('--frigate-card-menu-button-size', menuConfig.button_size); this.style.setProperty(
'--frigate-card-menu-button-size',
`${menuConfig.button_size}px`,
);
} }
// Store the menu mode as an attribute (used for CSS attribute selectors). // Store the menu mode as an attribute (used for CSS attribute selectors).
this.setAttribute('data-mode', menuConfig.mode); this.setAttribute('data-mode', menuConfig.mode);
+3 -7
View File
@@ -30,20 +30,16 @@ export class FrigateCardThumbnailDetails extends LitElement {
return html`<div class="left"> return html`<div class="left">
<div class="larger">${prettifyFrigateName(this.event.label)}</div> <div class="larger">${prettifyFrigateName(this.event.label)}</div>
<div> <div>
<span>
<span class="heading">${localize('event.start')}:</span> <span class="heading">${localize('event.start')}:</span>
${format(fromUnixTime(this.event.start_time), 'HH:mm:ss')} <span>${format(fromUnixTime(this.event.start_time), 'HH:mm:ss')}</span>
</span>
</div> </div>
<div> <div>
<span>
<span class="heading">${localize('event.duration')}:</span> <span class="heading">${localize('event.duration')}:</span>
${getEventDurationString(this.event)} <span>${getEventDurationString(this.event)}</span>
</span>
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="larger">${score}</div> <span class="larger">${score}</span>
</div>`; </div>`;
} }
+25 -8
View File
@@ -5,9 +5,11 @@ import { customElement, property, state } from 'lit/decorators.js';
import { HomeAssistant, LovelaceCardEditor, fireEvent } from 'custom-card-helpers'; import { HomeAssistant, LovelaceCardEditor, fireEvent } from 'custom-card-helpers';
import { localize } from './localize/localize.js'; import { localize } from './localize/localize.js';
import { import {
frigateCardConfigDefaults,
RawFrigateCardConfig, RawFrigateCardConfig,
RawFrigateCardConfigArray, RawFrigateCardConfigArray,
THUMBNAIL_WIDTH_MAX,
THUMBNAIL_WIDTH_MIN,
frigateCardConfigDefaults,
} from './types.js'; } from './types.js';
import { import {
@@ -843,7 +845,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
? html` ? html`
<div class="values"> <div class="values">
${this._renderOptionSelector(CONF_MENU_MODE, this._menuModes)} ${this._renderOptionSelector(CONF_MENU_MODE, this._menuModes)}
${this._renderStringInput(CONF_MENU_BUTTON_SIZE)} ${this._renderNumberInput(CONF_MENU_BUTTON_SIZE)}
${this._renderSwitch( ${this._renderSwitch(
CONF_MENU_BUTTONS_FRIGATE, CONF_MENU_BUTTONS_FRIGATE,
defaults.menu.buttons.frigate, defaults.menu.buttons.frigate,
@@ -900,7 +902,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE, CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE,
this._liveNextPreviousControlStyles, this._liveNextPreviousControlStyles,
)} )}
${this._renderStringInput(CONF_LIVE_CONTROLS_NEXT_PREVIOUS_SIZE)} ${this._renderNumberInput(CONF_LIVE_CONTROLS_NEXT_PREVIOUS_SIZE)}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_LIVE_CONTROLS_THUMBNAILS_MODE, CONF_LIVE_CONTROLS_THUMBNAILS_MODE,
this._thumbnailModes, this._thumbnailModes,
@@ -909,7 +911,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA, CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA,
this._thumbnailMedias, this._thumbnailMedias,
)} )}
${this._renderStringInput(CONF_LIVE_CONTROLS_THUMBNAILS_SIZE)} ${this._renderNumberInput(
CONF_LIVE_CONTROLS_THUMBNAILS_SIZE,
THUMBNAIL_WIDTH_MIN,
THUMBNAIL_WIDTH_MAX,
)}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_LIVE_CONTROLS_TITLE_MODE, CONF_LIVE_CONTROLS_TITLE_MODE,
this._titleModes, this._titleModes,
@@ -963,12 +969,16 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE, CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE,
this._eventViewerNextPreviousControlStyles, this._eventViewerNextPreviousControlStyles,
)} )}
${this._renderStringInput(CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE)} ${this._renderNumberInput(CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE)}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_MODE, CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_MODE,
this._thumbnailModes, this._thumbnailModes,
)} )}
${this._renderStringInput(CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_SIZE)} ${this._renderNumberInput(
CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_SIZE,
THUMBNAIL_WIDTH_MIN,
THUMBNAIL_WIDTH_MAX,
)}
${this._renderSwitch( ${this._renderSwitch(
CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_EVENT_VIEWER_CONTROLS_THUMBNAILS_SHOW_DETAILS,
defaults.event_viewer.controls.thumbnails.show_details, defaults.event_viewer.controls.thumbnails.show_details,
@@ -1005,12 +1015,19 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
? html` <div class="values"> ? html` <div class="values">
${this._renderNumberInput(CONF_TIMELINE_WINDOW_SECONDS)} ${this._renderNumberInput(CONF_TIMELINE_WINDOW_SECONDS)}
${this._renderNumberInput(CONF_TIMELINE_CLUSTERING_THRESHOLD)} ${this._renderNumberInput(CONF_TIMELINE_CLUSTERING_THRESHOLD)}
${this._renderOptionSelector(CONF_TIMELINE_MEDIA, this._timelineMediaTypes)} ${this._renderOptionSelector(
CONF_TIMELINE_MEDIA,
this._timelineMediaTypes,
)}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE, CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE,
this._thumbnailModes, this._thumbnailModes,
)} )}
${this._renderStringInput(CONF_TIMELINE_CONTROLS_THUMBNAILS_SIZE)} ${this._renderNumberInput(
CONF_TIMELINE_CONTROLS_THUMBNAILS_SIZE,
THUMBNAIL_WIDTH_MIN,
THUMBNAIL_WIDTH_MAX,
)}
${this._renderSwitch( ${this._renderSwitch(
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS,
defaults.timeline.controls.thumbnails.show_details, defaults.timeline.controls.thumbnails.show_details,
+6 -6
View File
@@ -66,7 +66,7 @@
"controls": { "controls": {
"next_previous": { "next_previous": {
"style": "Event Viewer next & previous control style", "style": "Event Viewer next & previous control style",
"size": "Event Viewer next & previous control size (e.g. '48px')", "size": "Event Viewer next & previous control size in pixels",
"styles": { "styles": {
"thumbnails": "Thumbnails", "thumbnails": "Thumbnails",
"chevrons": "Chevrons", "chevrons": "Chevrons",
@@ -75,7 +75,7 @@
}, },
"thumbnails": { "thumbnails": {
"mode": "Event Viewer thumbnails mode", "mode": "Event Viewer thumbnails mode",
"size": "Event Viewer thumbnails size (e.g. '100px')", "size": "Event Viewer thumbnails size in pixels",
"show_details": "Show event details with thumbnails", "show_details": "Show event details with thumbnails",
"show_controls": "Show event controls with thumbnails", "show_controls": "Show event controls with thumbnails",
"modes": { "modes": {
@@ -109,7 +109,7 @@
"controls": { "controls": {
"next_previous": { "next_previous": {
"style": "Live view next & previous control style", "style": "Live view next & previous control style",
"size": "Live view next & previous control size (e.g. '48px')", "size": "Live view next & previous control size in pixels",
"styles": { "styles": {
"chevrons": "Chevrons", "chevrons": "Chevrons",
"icons": "Icons", "icons": "Icons",
@@ -118,7 +118,7 @@
}, },
"thumbnails": { "thumbnails": {
"mode": "Live thumbnails mode", "mode": "Live thumbnails mode",
"size": "Live thumbnails size (e.g. '100px')", "size": "Live thumbnails size in pixels",
"show_details": "Show event details with thumbnails", "show_details": "Show event details with thumbnails",
"show_controls": "Show event controls with thumbnails", "show_controls": "Show event controls with thumbnails",
"media": "Whether to show thumbnails of clips or snapshots", "media": "Whether to show thumbnails of clips or snapshots",
@@ -169,7 +169,7 @@
"above": "Above", "above": "Above",
"below": "Below" "below": "Below"
}, },
"button_size": "Menu button size (e.g. '40px')" "button_size": "Menu button size in pixels"
}, },
"timeline": { "timeline": {
"window_seconds": "The default length of the timeline view in seconds", "window_seconds": "The default length of the timeline view in seconds",
@@ -183,7 +183,7 @@
"controls": { "controls": {
"thumbnails": { "thumbnails": {
"mode": "Timeline thumbnails mode", "mode": "Timeline thumbnails mode",
"size": "Timeline thumbnails size (e.g. '100px')", "size": "Timeline thumbnails size in pixels",
"show_details": "Show event details with thumbnails", "show_details": "Show event details with thumbnails",
"show_controls": "Show event controls with thumbnails" "show_controls": "Show event controls with thumbnails"
} }
+5
View File
@@ -0,0 +1,5 @@
:host {
--frigate-card-thumbnail-size: 100px;
--frigate-card-thumbnail-size-max: 175px;
--frigate-card-thumbnail-details-width: calc(var(--frigate-card-thumbnail-size) + 200px);
}
+2 -1
View File
@@ -1,3 +1,5 @@
@use "const.scss";
:host { :host {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -11,7 +13,6 @@
--frigate-card-gallery-gap: 3px; --frigate-card-gallery-gap: 3px;
--frigate-card-gallery-columns: 4; --frigate-card-gallery-columns: 4;
--frigate-card-thumbnail-size: 100px;
display: grid; display: grid;
grid-template-columns: repeat(var(--frigate-card-gallery-columns), minmax(0, 1fr)); grid-template-columns: repeat(var(--frigate-card-gallery-columns), minmax(0, 1fr));
+11
View File
@@ -1,3 +1,5 @@
@use "const.scss";
:host { :host {
--frigate-card-carousel-thumbnail-opacity: 1.0; --frigate-card-carousel-thumbnail-opacity: 1.0;
} }
@@ -19,3 +21,12 @@
.embla__slide.slide-selected { .embla__slide.slide-selected {
opacity: 1.0; opacity: 1.0;
} }
frigate-card-thumbnail[details] {
width: var(--frigate-card-thumbnail-details-width);
height: var(--frigate-card-thumbnail-size);
}
frigate-card-thumbnail:not([details]) {
width: var(--frigate-card-thumbnail-size);
height: var(--frigate-card-thumbnail-size);
}
+19 -4
View File
@@ -2,12 +2,13 @@
display: flex; display: flex;
width: 100%; width: 100%;
margin-left: 5px; margin-left: 5px;
padding: 15px; padding: 8px;
color: var(--primary-text-color); color: var(--primary-text-color);
overflow: hidden; overflow: hidden;
column-gap: 5%;
} }
div { div.right, div.left {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@@ -15,12 +16,26 @@ div {
div.left { div.left {
flex: 1; flex: 1;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
justify-content: center;
overflow: hidden;
column-gap: 5%;
} }
div.larger { div.left div {
font-size: 1.5rem; width: 100%;
} }
span.heading { span.heading {
font-weight: bold; font-weight: bold;
} }
.larger {
font-size: 1.5rem;
}
+5 -4
View File
@@ -1,3 +1,5 @@
@use "const.scss";
:host { :host {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -5,8 +7,6 @@
// Ensure control icons are relative to the thumbnail. // Ensure control icons are relative to the thumbnail.
position: relative; position: relative;
--frigate-card-max-thumbnail-size: 175px;
} }
:host([details]) { :host([details]) {
@@ -29,9 +29,10 @@ img {
// Restrict images to a maximum of thumbnail size. // Restrict images to a maximum of thumbnail size.
aspect-ratio: 1 / 1; aspect-ratio: 1 / 1;
height: 100%;
max-width: var(--frigate-card-max-thumbnail-size); max-width: var(--frigate-card-thumbnail-size-max);
max-height: var(--frigate-card-max-thumbnail-size); max-height: var(--frigate-card-thumbnail-size-max);
transition: transform 0.2s linear; transition: transform 0.2s linear;
} }
+4 -3
View File
@@ -16,6 +16,7 @@ import { deepRemoveDefaults } from './zod-util';
// The maximum width thumbnail Frigate returns // The maximum width thumbnail Frigate returns
export const THUMBNAIL_WIDTH_MAX = 175; export const THUMBNAIL_WIDTH_MAX = 175;
export const THUMBNAIL_WIDTH_MIN = 75;
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
@@ -442,7 +443,7 @@ export type ImageViewConfig = z.infer<typeof imageConfigSchema>;
const thumbnailsControlSchema = z.object({ const thumbnailsControlSchema = z.object({
mode: z.enum(['none', 'above', 'below', 'left', 'right']), mode: z.enum(['none', 'above', 'below', 'left', 'right']),
size: z.number().min(1).max(THUMBNAIL_WIDTH_MAX).optional(), size: z.number().min(THUMBNAIL_WIDTH_MIN).max(THUMBNAIL_WIDTH_MAX).optional(),
show_details: z.boolean().optional(), show_details: z.boolean().optional(),
show_controls: z.boolean().optional(), show_controls: z.boolean().optional(),
}); });
@@ -617,7 +618,7 @@ const menuConfigDefault = {
frigate_ui: true, frigate_ui: true,
fullscreen: true, fullscreen: true,
}, },
button_size: '40px', button_size: 40,
}; };
const menuConfigSchema = z const menuConfigSchema = z
@@ -637,7 +638,7 @@ const menuConfigSchema = z
fullscreen: z.boolean().default(menuConfigDefault.buttons.fullscreen), fullscreen: z.boolean().default(menuConfigDefault.buttons.fullscreen),
}) })
.default(menuConfigDefault.buttons), .default(menuConfigDefault.buttons),
button_size: z.string().default(menuConfigDefault.button_size), button_size: z.number().min(1).default(menuConfigDefault.button_size),
}) })
.default(menuConfigDefault); .default(menuConfigDefault);
export type MenuConfig = z.infer<typeof menuConfigSchema>; export type MenuConfig = z.infer<typeof menuConfigSchema>;