Add message priorities.
This commit is contained in:
+10
-7
@@ -63,6 +63,7 @@ import {
|
|||||||
MediaShowInfo,
|
MediaShowInfo,
|
||||||
MEDIA_TYPE_IMAGE,
|
MEDIA_TYPE_IMAGE,
|
||||||
MEDIA_TYPE_VIDEO,
|
MEDIA_TYPE_VIDEO,
|
||||||
|
MESSAGE_TYPE_PRIORITIES,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
Message,
|
Message,
|
||||||
RawFrigateCardConfig,
|
RawFrigateCardConfig,
|
||||||
@@ -1115,7 +1116,7 @@ export class FrigateCard extends LitElement {
|
|||||||
{
|
{
|
||||||
message: localize('error.reconnecting'),
|
message: localize('error.reconnecting'),
|
||||||
icon: 'mdi:lan-disconnect',
|
icon: 'mdi:lan-disconnect',
|
||||||
type: 'info',
|
type: 'connection',
|
||||||
dotdotdot: true,
|
dotdotdot: true,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
@@ -1403,7 +1404,7 @@ export class FrigateCard extends LitElement {
|
|||||||
|
|
||||||
this._setMessageAndUpdate({
|
this._setMessageAndUpdate({
|
||||||
message: localize('error.diagnostics'),
|
message: localize('error.diagnostics'),
|
||||||
type: 'info',
|
type: 'diagnostics',
|
||||||
icon: 'mdi:information',
|
icon: 'mdi:information',
|
||||||
context: {
|
context: {
|
||||||
ha_version: this._hass.config.version,
|
ha_version: this._hass.config.version,
|
||||||
@@ -1562,8 +1563,12 @@ export class FrigateCard extends LitElement {
|
|||||||
* @param skipUpdate If true an update request is skipped.
|
* @param skipUpdate If true an update request is skipped.
|
||||||
*/
|
*/
|
||||||
protected _setMessageAndUpdate(message: Message, skipUpdate?: boolean): void {
|
protected _setMessageAndUpdate(message: Message, skipUpdate?: boolean): void {
|
||||||
// Register the first message, or prioritize errors if there's pre-render competition.
|
const currentPriority = this._message
|
||||||
if (!this._message || (message.type == 'error' && this._message.type != 'error')) {
|
? MESSAGE_TYPE_PRIORITIES[this._message.type] ?? 0
|
||||||
|
: 0;
|
||||||
|
const newPriority = MESSAGE_TYPE_PRIORITIES[message.type] ?? 0;
|
||||||
|
|
||||||
|
if (!this._message || newPriority >= currentPriority) {
|
||||||
this._message = message;
|
this._message = message;
|
||||||
if (!skipUpdate) {
|
if (!skipUpdate) {
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
@@ -1650,14 +1655,12 @@ export class FrigateCard extends LitElement {
|
|||||||
// - Aspect ratio enforcement is disabled.
|
// - Aspect ratio enforcement is disabled.
|
||||||
// - Aspect ratio enforcement is dynamic and it's a media view (i.e. not the
|
// - Aspect ratio enforcement is dynamic and it's a media view (i.e. not the
|
||||||
// gallery) or timeline.
|
// gallery) or timeline.
|
||||||
// - There is a message to display to the user.
|
|
||||||
|
|
||||||
return !(
|
return !(
|
||||||
(screenfull.isEnabled && screenfull.isFullscreen) ||
|
(screenfull.isEnabled && screenfull.isFullscreen) ||
|
||||||
aspectRatioMode == 'unconstrained' ||
|
aspectRatioMode == 'unconstrained' ||
|
||||||
(aspectRatioMode == 'dynamic' &&
|
(aspectRatioMode == 'dynamic' &&
|
||||||
(this._view?.isAnyMediaView() || this._view?.is('timeline'))) ||
|
(this._view?.isAnyMediaView() || this._view?.is('timeline')))
|
||||||
this._message != null
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ export class FrigateCardImage extends LitElement {
|
|||||||
dispatchErrorMessageEvent(
|
dispatchErrorMessageEvent(
|
||||||
this,
|
this,
|
||||||
localize('error.image_load_error'),
|
localize('error.image_load_error'),
|
||||||
this.imageConfig,
|
{ context: this.imageConfig },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { customElement, property, state } from 'lit/decorators.js';
|
|||||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||||
import { until } from 'lit/directives/until.js';
|
import { until } from 'lit/directives/until.js';
|
||||||
import { ConditionState, getOverriddenConfig } from '../card-condition.js';
|
import { ConditionState, getOverriddenConfig } from '../card-condition.js';
|
||||||
import { renderProgressIndicator } from '../components/message.js';
|
import { dispatchFrigateCardErrorEvent, renderProgressIndicator } from '../components/message.js';
|
||||||
import { localize } from '../localize/localize.js';
|
import { localize } from '../localize/localize.js';
|
||||||
import liveFrigateStyle from '../scss/live-frigate.scss';
|
import liveFrigateStyle from '../scss/live-frigate.scss';
|
||||||
import liveJSMPEGStyle from '../scss/live-jsmpeg.scss';
|
import liveJSMPEGStyle from '../scss/live-jsmpeg.scss';
|
||||||
@@ -751,7 +751,7 @@ export class FrigateCardLiveFrigate extends LitElement {
|
|||||||
return dispatchErrorMessageEvent(
|
return dispatchErrorMessageEvent(
|
||||||
this,
|
this,
|
||||||
localize('error.no_live_camera'),
|
localize('error.no_live_camera'),
|
||||||
this.cameraConfig,
|
{ context: this.cameraConfig },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,7 +760,7 @@ export class FrigateCardLiveFrigate extends LitElement {
|
|||||||
return dispatchErrorMessageEvent(
|
return dispatchErrorMessageEvent(
|
||||||
this,
|
this,
|
||||||
localize('error.live_camera_unavailable'),
|
localize('error.live_camera_unavailable'),
|
||||||
this.cameraConfig,
|
{ context: this.cameraConfig },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,7 +906,7 @@ export class FrigateCardLiveWebRTCCard extends LitElement {
|
|||||||
e instanceof FrigateCardError
|
e instanceof FrigateCardError
|
||||||
? e.message
|
? e.message
|
||||||
: localize('error.webrtc_card_reported_error') + ': ' + (e as Error).message,
|
: localize('error.webrtc_card_reported_error') + ': ' + (e as Error).message,
|
||||||
(e as FrigateCardError).context,
|
{ context: (e as FrigateCardError).context },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (webrtcElement) {
|
if (webrtcElement) {
|
||||||
@@ -924,7 +924,7 @@ export class FrigateCardLiveWebRTCCard extends LitElement {
|
|||||||
return html`${this._webrtcTask.render({
|
return html`${this._webrtcTask.render({
|
||||||
initial: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
initial: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
||||||
pending: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
pending: () => renderProgressIndicator(localize('error.webrtc_card_waiting')),
|
||||||
error: (e: unknown) => dispatchErrorMessageEvent(this, (e as Error).message),
|
error: (e: unknown) => dispatchFrigateCardErrorEvent(this, e as Error),
|
||||||
complete: () => render(),
|
complete: () => render(),
|
||||||
})}`;
|
})}`;
|
||||||
}
|
}
|
||||||
@@ -1147,7 +1147,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
|||||||
return dispatchErrorMessageEvent(
|
return dispatchErrorMessageEvent(
|
||||||
this,
|
this,
|
||||||
localize('error.no_camera_name'),
|
localize('error.no_camera_name'),
|
||||||
this.cameraConfig,
|
{ context: this.cameraConfig },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-20
@@ -1,9 +1,10 @@
|
|||||||
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
||||||
import { customElement, property } from 'lit/decorators.js';
|
import { customElement, property } from 'lit/decorators.js';
|
||||||
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { TROUBLESHOOTING_URL } from '../const.js';
|
import { TROUBLESHOOTING_URL } from '../const.js';
|
||||||
import { localize } from '../localize/localize.js';
|
import { localize } from '../localize/localize.js';
|
||||||
import messageStyle from '../scss/message.scss';
|
import messageStyle from '../scss/message.scss';
|
||||||
import { FrigateCardError, Message } from '../types.js';
|
import { FrigateCardError, Message, MessageType } from '../types.js';
|
||||||
import { dispatchFrigateCardEvent } from '../utils/basic.js';
|
import { dispatchFrigateCardEvent } from '../utils/basic.js';
|
||||||
|
|
||||||
@customElement('frigate-card-message')
|
@customElement('frigate-card-message')
|
||||||
@@ -23,14 +24,18 @@ export class FrigateCardMessage extends LitElement {
|
|||||||
// Render the menu.
|
// Render the menu.
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const icon = this.icon ? this.icon : 'mdi:information-outline';
|
const icon = this.icon ? this.icon : 'mdi:information-outline';
|
||||||
|
const classes = {
|
||||||
|
dotdotdot: !!this.dotdotdot,
|
||||||
|
};
|
||||||
return html` <div class="wrapper">
|
return html` <div class="wrapper">
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<ha-icon icon="${icon}"> </ha-icon>
|
<ha-icon icon="${icon}"> </ha-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<span> ${this.message ? html`${this.message}` : ''} </span>
|
<span class="${classMap(classes)}">
|
||||||
${this.dotdotdot ? html`<span class="dotdotdot"></span>` : ``}
|
${this.message ? html`${this.message}` : ''}
|
||||||
|
</span>
|
||||||
${this.context
|
${this.context
|
||||||
? html`<pre>${JSON.stringify(this.context, null, 2)}</pre>`
|
? html`<pre>${JSON.stringify(this.context, null, 2)}</pre>`
|
||||||
: ''}
|
: ''}
|
||||||
@@ -92,7 +97,7 @@ export function renderMessage(message: Message): TemplateResult {
|
|||||||
return html` <frigate-card-error-message
|
return html` <frigate-card-error-message
|
||||||
.message=${message}
|
.message=${message}
|
||||||
></frigate-card-error-message>`;
|
></frigate-card-error-message>`;
|
||||||
} else if (message.type === 'info') {
|
} else {
|
||||||
return html` <frigate-card-message
|
return html` <frigate-card-message
|
||||||
.message=${message.message}
|
.message=${message.message}
|
||||||
.icon=${message.icon}
|
.icon=${message.icon}
|
||||||
@@ -114,19 +119,22 @@ export function renderProgressIndicator(message?: string): TemplateResult {
|
|||||||
* Dispatch an event with a message to show to the user.
|
* Dispatch an event with a message to show to the user.
|
||||||
* @param element The element to send the event.
|
* @param element The element to send the event.
|
||||||
* @param message The message to show.
|
* @param message The message to show.
|
||||||
* @param icon An optional icon to attach to the message.
|
* @param options Optional icon and context to include.
|
||||||
*/
|
*/
|
||||||
export function dispatchMessageEvent(
|
export function dispatchMessageEvent(
|
||||||
element: EventTarget,
|
element: EventTarget,
|
||||||
message: string,
|
message: string,
|
||||||
icon?: string,
|
type: MessageType,
|
||||||
context?: unknown,
|
options?: {
|
||||||
|
icon?: string;
|
||||||
|
context?: unknown;
|
||||||
|
},
|
||||||
): void {
|
): void {
|
||||||
dispatchFrigateCardEvent<Message>(element, 'message', {
|
dispatchFrigateCardEvent<Message>(element, 'message', {
|
||||||
message: message,
|
message: message,
|
||||||
type: 'info',
|
type: type,
|
||||||
icon: icon,
|
icon: options?.icon,
|
||||||
context: context,
|
context: options?.context,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,16 +142,17 @@ export function dispatchMessageEvent(
|
|||||||
* Dispatch an event with an error message to show to the user.
|
* Dispatch an event with an error message to show to the user.
|
||||||
* @param element The element to send the event.
|
* @param element The element to send the event.
|
||||||
* @param message The message to show.
|
* @param message The message to show.
|
||||||
|
* @param options Optional context to include.
|
||||||
*/
|
*/
|
||||||
export function dispatchErrorMessageEvent(
|
export function dispatchErrorMessageEvent(
|
||||||
element: EventTarget,
|
element: EventTarget,
|
||||||
message: string,
|
message: string,
|
||||||
context?: unknown,
|
options?: {
|
||||||
|
context?: unknown;
|
||||||
|
},
|
||||||
): void {
|
): void {
|
||||||
dispatchFrigateCardEvent<Message>(element, 'message', {
|
dispatchMessageEvent(element, message, 'error', {
|
||||||
message: message,
|
context: options?.context,
|
||||||
type: 'error',
|
|
||||||
context: context,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,11 +165,7 @@ export function dispatchFrigateCardErrorEvent(
|
|||||||
element: EventTarget,
|
element: EventTarget,
|
||||||
error: FrigateCardError,
|
error: FrigateCardError,
|
||||||
): void {
|
): void {
|
||||||
dispatchFrigateCardEvent<Message>(element, 'message', {
|
dispatchErrorMessageEvent(element, error.message, { context: error.context });
|
||||||
message: error.message,
|
|
||||||
type: 'error',
|
|
||||||
context: error.context || '',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -1227,7 +1227,10 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
dispatchMessageEvent(
|
dispatchMessageEvent(
|
||||||
this,
|
this,
|
||||||
localize('error.timeline_no_cameras'),
|
localize('error.timeline_no_cameras'),
|
||||||
'mdi:chart-gantt',
|
'info',
|
||||||
|
{
|
||||||
|
icon: 'mdi:chart-gantt',
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { customElement, property } from 'lit/decorators.js';
|
|||||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||||
import { ref } from 'lit/directives/ref.js';
|
import { ref } from 'lit/directives/ref.js';
|
||||||
import {
|
import {
|
||||||
dispatchErrorMessageEvent,
|
dispatchFrigateCardErrorEvent,
|
||||||
renderProgressIndicator
|
renderProgressIndicator
|
||||||
} from '../components/message.js';
|
} from '../components/message.js';
|
||||||
import viewerStyle from '../scss/viewer.scss';
|
import viewerStyle from '../scss/viewer.scss';
|
||||||
@@ -632,7 +632,7 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
|
|||||||
return html`${this._mediaResolutionTask.render({
|
return html`${this._mediaResolutionTask.render({
|
||||||
initial: () => renderProgressIndicator(),
|
initial: () => renderProgressIndicator(),
|
||||||
pending: () => renderProgressIndicator(),
|
pending: () => renderProgressIndicator(),
|
||||||
error: (e: unknown) => dispatchErrorMessageEvent(this, (e as Error).message),
|
error: (e: unknown) => dispatchFrigateCardErrorEvent(this, e as Error),
|
||||||
complete: () => this._render(),
|
complete: () => this._render(),
|
||||||
})}`;
|
})}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,11 @@ div.message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.message div.contents {
|
div.message div.contents {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
height: 100%;
|
margin-top: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +52,7 @@ div.message div.icon {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dotdotdot:before {
|
.dotdotdot:after {
|
||||||
@keyframes dots {
|
@keyframes dots {
|
||||||
0%,
|
0%,
|
||||||
20% {
|
20% {
|
||||||
|
|||||||
+10
-1
@@ -1188,9 +1188,18 @@ export interface MediaShowInfo {
|
|||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const MESSAGE_TYPE_PRIORITIES = {
|
||||||
|
info: 10,
|
||||||
|
error: 20,
|
||||||
|
connection: 30,
|
||||||
|
diagnostics: 40,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MessageType = 'info' | 'error' | 'connection' | 'diagnostics';
|
||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
message: string;
|
message: string;
|
||||||
type: 'error' | 'info';
|
type: MessageType,
|
||||||
icon?: string;
|
icon?: string;
|
||||||
context?: unknown;
|
context?: unknown;
|
||||||
dotdotdot?: boolean;
|
dotdotdot?: boolean;
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import {
|
|||||||
differenceInHours,
|
differenceInHours,
|
||||||
differenceInMinutes,
|
differenceInMinutes,
|
||||||
differenceInSeconds,
|
differenceInSeconds,
|
||||||
fromUnixTime
|
fromUnixTime,
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
import { homeAssistantWSRequest } from '.';
|
import { homeAssistantWSRequest } from '.';
|
||||||
import {
|
import {
|
||||||
dispatchErrorMessageEvent,
|
dispatchErrorMessageEvent,
|
||||||
dispatchFrigateCardErrorEvent,
|
dispatchFrigateCardErrorEvent,
|
||||||
dispatchMessageEvent
|
dispatchMessageEvent,
|
||||||
} from '../../components/message.js';
|
} from '../../components/message.js';
|
||||||
import { localize } from '../../localize/localize.js';
|
import { localize } from '../../localize/localize.js';
|
||||||
import {
|
import {
|
||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
MEDIA_CLASS_PLAYLIST,
|
MEDIA_CLASS_PLAYLIST,
|
||||||
MEDIA_CLASS_VIDEO,
|
MEDIA_CLASS_VIDEO,
|
||||||
MEDIA_TYPE_PLAYLIST,
|
MEDIA_TYPE_PLAYLIST,
|
||||||
MEDIA_TYPE_VIDEO
|
MEDIA_TYPE_VIDEO,
|
||||||
} from '../../types.js';
|
} from '../../types.js';
|
||||||
import { View } from '../../view.js';
|
import { View } from '../../view.js';
|
||||||
import { getCameraTitle } from '../camera.js';
|
import { getCameraTitle } from '../camera.js';
|
||||||
@@ -318,11 +318,9 @@ export const getFullDependentBrowseMediaQueryParametersOrDispatchError = (
|
|||||||
mediaType,
|
mediaType,
|
||||||
);
|
);
|
||||||
if (!params) {
|
if (!params) {
|
||||||
dispatchErrorMessageEvent(
|
dispatchErrorMessageEvent(element, localize('error.no_camera_name'), {
|
||||||
element,
|
context: cameras.get(camera),
|
||||||
localize('error.no_camera_name'),
|
});
|
||||||
cameras.get(camera),
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
@@ -357,7 +355,10 @@ export const fetchLatestMediaAndDispatchViewChange = async (
|
|||||||
view.isClipRelatedView()
|
view.isClipRelatedView()
|
||||||
? localize('common.no_clip')
|
? localize('common.no_clip')
|
||||||
: localize('common.no_snapshot'),
|
: localize('common.no_snapshot'),
|
||||||
view.isClipRelatedView() ? 'mdi:filmstrip-off' : 'mdi:camera-off',
|
'info',
|
||||||
|
{
|
||||||
|
icon: view.isClipRelatedView() ? 'mdi:filmstrip-off' : 'mdi:camera-off',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user