Improve disconnection/reconnection UX

This commit is contained in:
Dermot Duffy
2022-06-23 05:08:53 +00:00
parent 839d4f3f8a
commit fff6d7ecad
8 changed files with 75 additions and 21 deletions
+10
View File
@@ -0,0 +1,10 @@
# Review comments generated by i18n-ally. Please commit this file.
reviews:
error.reconnecting:
locales:
pt-BR:
translation_candidate:
source: en
text: Reconectando
time: '2022-06-23T03:45:39.286Z'
+7 -8
View File
@@ -1,9 +1,8 @@
{ {
"i18n-ally.localesPaths": [ "i18n-ally.localesPaths": ["src/localize/languages"],
"src/localize/languages" "i18n-ally.keystyle": "nested",
], "i18n-ally.sortKeys": true,
"i18n-ally.keystyle": "nested", "i18n-ally.keepFulfilled": true,
"i18n-ally.sortKeys": true, "i18n-ally.editor.preferEditor": true,
"i18n-ally.keepFulfilled": true, "i18n-ally.translate.saveAsCandidates": true
"i18n-ally.editor.preferEditor": true }
}
+21 -3
View File
@@ -1106,8 +1106,26 @@ export class FrigateCard extends LitElement {
if (oldHass) { if (oldHass) {
const selectedCamera = this._getSelectedCameraConfig(); const selectedCamera = this._getSelectedCameraConfig();
if (this._getConfig().view.scan.enabled && this._updateTriggeredCameras(oldHass)) { if (oldHass.connected !== !!this._hass?.connected) {
shouldUpdate ||= true; if (!this._hass?.connected) {
this._setMessageAndUpdate(
{
message: localize('error.reconnecting'),
icon: 'mdi:lan-disconnect',
type: 'info',
dotdotdot: true,
},
true,
);
} else {
this._changeView();
}
shouldUpdate = true;
} else if (
this._getConfig().view.scan.enabled &&
this._updateTriggeredCameras(oldHass)
) {
shouldUpdate = true;
} else if ( } else if (
// Home Assistant pumps a lot of updates through. Re-rendering the card is // Home Assistant pumps a lot of updates through. Re-rendering the card is
// necessary at times (e.g. to update the 'clip' view as new clips // necessary at times (e.g. to update the 'clip' view as new clips
@@ -1125,7 +1143,7 @@ export class FrigateCard extends LitElement {
// default. Note that as per the Lit lifecycle, the setting of the view // default. Note that as per the Lit lifecycle, the setting of the view
// itself will not trigger an *additional* re-render here. // itself will not trigger an *additional* re-render here.
this._changeView(); this._changeView();
shouldUpdate ||= true; shouldUpdate = true;
} else { } else {
shouldUpdate ||= isHassDifferent( shouldUpdate ||= isHassDifferent(
this._hass, this._hass,
+10 -10
View File
@@ -1,10 +1,4 @@
import { import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
CSSResultGroup,
html,
LitElement,
TemplateResult,
unsafeCSS,
} from 'lit';
import { customElement, property } from 'lit/decorators.js'; import { customElement, property } from 'lit/decorators.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';
@@ -23,6 +17,9 @@ export class FrigateCardMessage extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public icon?: string; public icon?: string;
@property({ attribute: true, type: Boolean })
public dotdotdot?: boolean;
// 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';
@@ -33,6 +30,7 @@ export class FrigateCardMessage extends LitElement {
</div> </div>
<div class="contents"> <div class="contents">
<span> ${this.message ? html`${this.message}` : ''} </span> <span> ${this.message ? html`${this.message}` : ''} </span>
${this.dotdotdot ? html`<span class="dotdotdot"></span>` : ``}
${this.context ${this.context
? html`<pre>${JSON.stringify(this.context, null, 2)}</pre>` ? html`<pre>${JSON.stringify(this.context, null, 2)}</pre>`
: ''} : ''}
@@ -60,6 +58,7 @@ export class FrigateCardErrorMessage extends LitElement {
<a href="${TROUBLESHOOTING_URL}"> ${localize('error.troubleshooting')}</a>.`} <a href="${TROUBLESHOOTING_URL}"> ${localize('error.troubleshooting')}</a>.`}
.icon=${'mdi:alert-circle'} .icon=${'mdi:alert-circle'}
.context=${this.message.context} .context=${this.message.context}
.dotdotdot=${this.message.dotdotdot}
> >
</frigate-card-message>`; </frigate-card-message>`;
} }
@@ -89,15 +88,16 @@ export class FrigateCardProgressIndicator extends LitElement {
} }
export function renderMessage(message: Message): TemplateResult { export function renderMessage(message: Message): TemplateResult {
if (message.type == 'error') { if (message.type === 'error') {
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 if (message.type === 'info') {
return html` <frigate-card-message return html` <frigate-card-message
.message=${message.message} .message=${message.message}
.icon=${message.icon} .icon=${message.icon}
.context=${message.context} .context=${message.context}
.dotdotdot=${message.dotdotdot}
></frigate-card-message>`; ></frigate-card-message>`;
} }
return html``; return html``;
@@ -165,7 +165,7 @@ export function dispatchFrigateCardErrorEvent(
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"frigate-card-progress-indicator": FrigateCardProgressIndicator 'frigate-card-progress-indicator': FrigateCardProgressIndicator;
'frigate-card-error-message': FrigateCardErrorMessage; 'frigate-card-error-message': FrigateCardErrorMessage;
'frigate-card-message': FrigateCardMessage; 'frigate-card-message': FrigateCardMessage;
} }
+1
View File
@@ -328,6 +328,7 @@
"no_camera_name": "Could not determine a Frigate camera name for camera (or one of its dependents), please specify either 'camera_entity' or 'camera_name'", "no_camera_name": "Could not determine a Frigate camera name for camera (or one of its dependents), please specify either 'camera_entity' or 'camera_name'",
"no_cameras": "No valid cameras found, you must configure at least one camera entry", "no_cameras": "No valid cameras found, you must configure at least one camera entry",
"no_live_camera": "The camera_entity parameter must be set and valid for this live provider", "no_live_camera": "The camera_entity parameter must be set and valid for this live provider",
"reconnecting": "Reconnecting",
"timeline_no_cameras": "No Frigate cameras to show in timeline", "timeline_no_cameras": "No Frigate cameras to show in timeline",
"troubleshooting": "Check troubleshooting", "troubleshooting": "Check troubleshooting",
"undecodable_response": "Could not decode response from Home Assistant for request", "undecodable_response": "Could not decode response from Home Assistant for request",
+1
View File
@@ -330,6 +330,7 @@
"no_camera_name": "Não foi possível determinar o nome da câmera da Frigate, especifique 'camera_entity' ou 'camera_name' para a câmera a seguir", "no_camera_name": "Não foi possível determinar o nome da câmera da Frigate, especifique 'camera_entity' ou 'camera_name' para a câmera a seguir",
"no_cameras": "Nenhuma câmera válida encontrada, você deve configurar pelo menos uma câmera", "no_cameras": "Nenhuma câmera válida encontrada, você deve configurar pelo menos uma câmera",
"no_live_camera": "O parâmetro camera_entity deve ser definido e válido para este provedor ativo", "no_live_camera": "O parâmetro camera_entity deve ser definido e válido para este provedor ativo",
"reconnecting": "",
"timeline_no_cameras": "Nenhuma câmera do Frigate para mostrar na linha do tempo", "timeline_no_cameras": "Nenhuma câmera do Frigate para mostrar na linha do tempo",
"troubleshooting": "Verifique a solução de problemas", "troubleshooting": "Verifique a solução de problemas",
"undecodable_response": "Não foi possível decodificar a resposta do Home Assistant para solicitação", "undecodable_response": "Não foi possível decodificar a resposta do Home Assistant para solicitação",
+24
View File
@@ -48,3 +48,27 @@ div.message div.icon {
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-all; word-break: break-all;
} }
.dotdotdot:before {
@keyframes dots {
0%,
20% {
content: '.';
}
40% {
content: '..';
}
60% {
content: '...';
}
90%,
100% {
content: '';
}
}
animation: dots 2s linear infinite;
content: '';
display: inline-block;
width: 3em;
}
+1
View File
@@ -1193,6 +1193,7 @@ export interface Message {
type: 'error' | 'info'; type: 'error' | 'info';
icon?: string; icon?: string;
context?: unknown; context?: unknown;
dotdotdot?: boolean;
} }
export interface StateParameters { export interface StateParameters {