@@ -9,8 +9,9 @@ export interface MediaNotificationOptions {
|
|||||||
// A short heading. A longer explanation goes in `detail`.
|
// A short heading. A longer explanation goes in `detail`.
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
// The heading icon. Defaults to a generic alert icon.
|
// The heading icon. Defaults to a generic alert icon; `null` for no icon at
|
||||||
icon?: string;
|
// all.
|
||||||
|
icon?: string | null;
|
||||||
|
|
||||||
// Appended to the heading to identify the media, when it has a title (e.g. the
|
// Appended to the heading to identify the media, when it has a title (e.g. the
|
||||||
// camera title `: Front Door`). Absent for untitled media (a url or
|
// camera title `: Front Door`). Absent for untitled media (a url or
|
||||||
@@ -36,7 +37,7 @@ export const createMediaNotification = (
|
|||||||
options: MediaNotificationOptions,
|
options: MediaNotificationOptions,
|
||||||
): Notification => ({
|
): Notification => ({
|
||||||
heading: {
|
heading: {
|
||||||
icon: options.icon ?? 'mdi:alert-circle',
|
...(options.icon !== null && { icon: options.icon ?? 'mdi:alert-circle' }),
|
||||||
text: options.targetTitle
|
text: options.targetTitle
|
||||||
? `${options.title}: ${options.targetTitle}`
|
? `${options.title}: ${options.targetTitle}`
|
||||||
: options.title,
|
: options.title,
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
|||||||
// endpoints). Instead, simply never render uninitialized cameras.
|
// endpoints). Instead, simply never render uninitialized cameras.
|
||||||
if (!this.camera?.isInitialized()) {
|
if (!this.camera?.isInitialized()) {
|
||||||
return renderMediaNotification({
|
return renderMediaNotification({
|
||||||
icon: 'mdi:progress-helper',
|
icon: null,
|
||||||
title: localize('error.awaiting_live'),
|
title: localize('error.awaiting_live'),
|
||||||
targetTitle: this.cameraTitle,
|
targetTitle: this.cameraTitle,
|
||||||
});
|
});
|
||||||
@@ -488,7 +488,7 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
|||||||
|
|
||||||
return html`<div class="fill">
|
return html`<div class="fill">
|
||||||
${renderMediaNotification({
|
${renderMediaNotification({
|
||||||
icon: 'mdi:progress-helper',
|
icon: null,
|
||||||
title: localize('error.awaiting_live'),
|
title: localize('error.awaiting_live'),
|
||||||
targetTitle: this.cameraTitle,
|
targetTitle: this.cameraTitle,
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
$ convert -strip -interlace Plane -quality 85% -scale 492x277 iris-screensaver-original.jpg iris-screensaver.jpg
|
$ convert -strip -interlace Plane -quality 85% -scale 492x277 iris-screensaver-original.jpg iris-screensaver.jpg
|
||||||
```
|
```
|
||||||
|
|
||||||
## icons/iris.svg / iris-background.svg
|
## icons/iris.svg
|
||||||
|
|
||||||
**Link**: https://pictogrammers.com/library/mdi/icon/camera-iris/
|
**Link**: https://pictogrammers.com/library/mdi/icon/camera-iris/
|
||||||
|
|
||||||
@@ -27,8 +27,7 @@ $ convert -strip -interlace Plane -quality 85% -scale 492x277 iris-screensaver-o
|
|||||||
|
|
||||||
**Image Formatting Process**:
|
**Image Formatting Process**:
|
||||||
|
|
||||||
- `icons/iris.svg`: single-path variant for the card's custom iconset
|
- Single-path variant for the card's custom iconset
|
||||||
- `iris-background.svg`: outline / opacity adjusted manually
|
|
||||||
|
|
||||||
## icons/{frigate,motioneye,reolink,tplink}.svg
|
## icons/{frigate,motioneye,reolink,tplink}.svg
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
|
||||||
sodipodi:docname="iris-outline.svg"
|
|
||||||
id="svg4"
|
|
||||||
version="1.1"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs8" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview6"
|
|
||||||
pagecolor="#b93e3e"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.60784314"
|
|
||||||
inkscape:pagecheckerboard="false"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="19.378578"
|
|
||||||
inkscape:cx="8.2823415"
|
|
||||||
inkscape:cy="12.359008"
|
|
||||||
inkscape:window-width="3840"
|
|
||||||
inkscape:window-height="1527"
|
|
||||||
inkscape:window-x="1080"
|
|
||||||
inkscape:window-y="227"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg4" />
|
|
||||||
<g
|
|
||||||
id="g1119"
|
|
||||||
style="fill-opacity:0.05;fill:#ffffff">
|
|
||||||
<circle
|
|
||||||
style="display:inline;fill:#000000;fill-opacity:0.49782825;stroke-width:1.39729;opacity:0.5"
|
|
||||||
id="path170"
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
inkscape:label="Background"
|
|
||||||
r="11.25" />
|
|
||||||
<path
|
|
||||||
d="M 13.730001,15 9.8300003,21.76 C 10.53,21.91 11.25,22 12,22 c 2.400001,0 4.6,-0.85 6.32,-2.25 L 14.660001,13.4 M 2.4600003,15 c 0.92,2.92 3.15,5.26 5.99,6.34 L 12.12,15 m -3.5799997,-3 -3.9,-6.7499996 c -1.64,1.749999 -2.64,4.1399993 -2.64,6.7499996 0,0.68 0.07,1.35 0.2,2 h 7.49 M 21.8,9.9999997 H 14.310001 L 14.600001,10.5 19.36,18.75 C 21,16.97 22,14.6 22,12 22,11.31 21.93,10.64 21.8,9.9999997 m -0.26,-1 C 20.62,6.0700005 18.39,3.7400002 15.550001,2.6600002 L 11.88,8.9999997 M 9.4000003,10.5 14.170001,2.2400002 c -0.7,-0.15 -1.420001,-0.24 -2.170001,-0.24 -2.3999997,0 -4.5999997,0.84 -6.3199997,2.2500003 l 3.66,6.3499995 z"
|
|
||||||
id="path2"
|
|
||||||
inkscape:label="Iris"
|
|
||||||
style="fill-opacity:0.50221002;fill:#ffffff;opacity:0.75" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -21,6 +21,18 @@
|
|||||||
.fill {
|
.fill {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|
||||||
|
// `both` holds the status invisible for the length of the delay.
|
||||||
|
animation: fade-in 0.4s ease-out 3s both;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
advanced-camera-card-icon {
|
advanced-camera-card-icon {
|
||||||
|
|||||||
@@ -24,10 +24,9 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The hidden element stays mounted: without this the icon would rotate
|
|
||||||
// invisibly forever.
|
|
||||||
:host([loaded]) advanced-camera-card-icon {
|
:host([loaded]) advanced-camera-card-icon {
|
||||||
animation: none;
|
display: none;
|
||||||
|
transition: display 0s 1.5s allow-discrete;
|
||||||
}
|
}
|
||||||
|
|
||||||
advanced-camera-card-icon {
|
advanced-camera-card-icon {
|
||||||
|
|||||||
@@ -1,11 +1,34 @@
|
|||||||
// Use the outlined Iris logo since the background color is unknown.
|
$bracket-length: 24px;
|
||||||
$bg-img: url('../images/iris-background.svg');
|
$bracket-thickness: 1px;
|
||||||
|
$bracket-inset: 10px;
|
||||||
|
|
||||||
|
// Mix from text color so the brackets show against both light/dark.
|
||||||
|
$bracket-color: color-mix(
|
||||||
|
in srgb,
|
||||||
|
var(--advanced-camera-card-text-color),
|
||||||
|
transparent 90%
|
||||||
|
);
|
||||||
|
|
||||||
|
$arm: linear-gradient($bracket-color 0 0);
|
||||||
|
$arm-horizontal: $bracket-length $bracket-thickness;
|
||||||
|
$arm-vertical: $bracket-thickness $bracket-length;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
background-color: var(--advanced-camera-card-background);
|
background-color: var(--advanced-camera-card-background);
|
||||||
background-position: center;
|
|
||||||
|
// Corner brackets mark a media surface that is rendering nothing at all,
|
||||||
|
// which is otherwise indistinguishable from a black video frame.
|
||||||
|
background-image: $arm, $arm, $arm, $arm, $arm, $arm, $arm, $arm;
|
||||||
|
background-size: $arm-horizontal, $arm-vertical, $arm-horizontal, $arm-vertical,
|
||||||
|
$arm-horizontal, $arm-vertical, $arm-horizontal, $arm-vertical;
|
||||||
|
background-position:
|
||||||
|
left $bracket-inset top $bracket-inset,
|
||||||
|
left $bracket-inset top $bracket-inset,
|
||||||
|
right $bracket-inset top $bracket-inset,
|
||||||
|
right $bracket-inset top $bracket-inset,
|
||||||
|
left $bracket-inset bottom $bracket-inset,
|
||||||
|
left $bracket-inset bottom $bracket-inset,
|
||||||
|
right $bracket-inset bottom $bracket-inset,
|
||||||
|
right $bracket-inset bottom $bracket-inset;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-image: $bg-img;
|
|
||||||
background-size: 10%;
|
|
||||||
background-position: center;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ describe('createMediaNotification', () => {
|
|||||||
expect(notification.heading?.icon).toBe('mdi:alert-circle');
|
expect(notification.heading?.icon).toBe('mdi:alert-circle');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should omit the heading icon when it is null', () => {
|
||||||
|
const notification = createMediaNotification({
|
||||||
|
icon: null,
|
||||||
|
title: 'Awaiting live view',
|
||||||
|
});
|
||||||
|
expect(notification.heading?.icon).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('should append the camera title to the heading', () => {
|
it('should append the camera title to the heading', () => {
|
||||||
const notification = createMediaNotification({
|
const notification = createMediaNotification({
|
||||||
icon: 'mdi:alert-circle',
|
icon: 'mdi:alert-circle',
|
||||||
|
|||||||
Reference in New Issue
Block a user