|
|
<script lang="ts" context="module"> export const DARK_COLOR = rgb(0.5176470588235295/2, 0.5333333333333333/2, 0.5607843137254902/1.75); export const DARK_COLOR_SELECTED = rgb(0.5176470588235295/1.5, 0.5333333333333333/1.5, 0.5607843137254902/1.25); </script>
<script lang="ts"> import { getSelectedContext } from "$lib/contexts/SelectContext.svelte"; import type Device from "$lib/models/device"; import { SupportFlags } from "$lib/models/device"; import { rgb, type ColorRGB } from "../models/color"; import DeviceIcon from "./DeviceIcon.svelte"; import Icon from "./Icon.svelte";
export let device: Device; export let compact: boolean = false;
const {selectedMap, toggleSelection} = getSelectedContext();
function onSelect() { toggleSelection(device.id); }
// Process device let deviceTitle: string; let iconColor: ColorRGB | null; let barColor: ColorRGB | null; let barFraction: number | null; let roundboiText: string | null; let roles: string[]; let tags: string[]; let hasRoleOrTag: boolean;
$: { // TODO: Fix device.name on the backend const nameAlias = device.aliases?.find(a => a.startsWith("lucifer:name:")); if (nameAlias != null) { deviceTitle = nameAlias.slice("lucifer:name:".length); } else { deviceTitle = ""; }
roles = device.aliases?.filter(a => a.startsWith("lucifer:role:")).map(a => a.slice("lucifer:role:".length)); tags = device.aliases?.filter(a => a.startsWith("lucifer:tag:")).map(a => a.slice("lucifer:tag:".length)); hasRoleOrTag = !!(roles.length || tags.length)
barFraction = null; barColor = null; iconColor = null;
if (device.hwState) { const hws = device.hwState; const sflags = hws.supportFlags;
const hasColor = !!(sflags & SupportFlags.Color); const hasPower = !!(sflags & SupportFlags.Power)
if (deviceTitle == "") { deviceTitle = device.hwState.internalName; }
if (hasColor && (!hasPower || device.desiredState?.power)) { iconColor = device.desiredColorRgb; } else { iconColor = null; }
if (sflags & SupportFlags.SensorPresence) { barColor = rgb(0.5,0.5,0.5); barFraction = Math.max(0, (300 - (device.sensors.lastMotion!=null?device.sensors.lastMotion:300))/300); }
if (sflags & SupportFlags.Temperature) { barColor = rgb(1.000,0.2,0.2); barFraction = Math.min(1, Math.max(0, (device.desiredState?.temperature||0) - 5) / 35) * 1; }
if (sflags & SupportFlags.Intensity) { if (sflags & SupportFlags.Color) { barColor = device.desiredColorRgb; } else { barColor = rgb(1.000,0.671,0.355); }
barFraction = device.desiredState?.intensity || 0; }
if (sflags & SupportFlags.SensorTemperature && !!device.sensors.temperature) { roundboiText = `${device.sensors.temperature.toFixed(0)}°` } } }
// Make title visible let displayTitle: string; $: { if (deviceTitle.length > 12) { let last = deviceTitle.split(" ").pop() || deviceTitle; if (last.length > 4) { last = last.slice(-3); }
displayTitle = `${(deviceTitle.split(" ").shift()||"").slice(0, 10 - last.length)}... ${last}` } else { displayTitle = deviceTitle; } }
let darkColor: ColorRGB; $: darkColor = $selectedMap[device.id] ? DARK_COLOR_SELECTED : DARK_COLOR </script>
<!-- svelte-ignore a11y-click-events-have-key-events --> <div title={deviceTitle} class="lamp" class:compact class:selected={$selectedMap[device.id]} on:click={onSelect}> <div class="row"> <div class="row-icon"> {#if iconColor != null} <DeviceIcon name={device.icon||"generic_ball"} brightColor={iconColor} darkColor={darkColor} /> {:else} <DeviceIcon name={device.icon||"generic_ball"} brightColor={darkColor} darkColor={darkColor}> {#if !!roundboiText} <div class="roundboi-text">{roundboiText}</div> {/if} </DeviceIcon> {/if} </div> <div class="title"> <div class="name" class:hasRoleOrTag>{deviceTitle}</div> {#if hasRoleOrTag} <div class="tag-list"> {#each roles as role} <div class="tag"> <Icon block name="masks_theater" /> <div class="tag-name">{role}</div> </div> {/each} {#each tags as tag} <div class="tag"> <Icon block name="tag" /> <div class="tag-name">{tag}</div> </div> {/each} </div> {/if} </div> </div> <div class="flatboi"> {#if barColor != null && barFraction != null} <div style="width: {barFraction*100}%; background-color: rgb({barColor.red*255},{barColor.green*255},{barColor.blue*255})" class="flatboi2"></div> {/if} </div> </div>
<style lang="sass"> div.lamp cursor: pointer width: 19ch height: 2em margin: 0.5ch background: #18181c color: #84888f border-radius: 0.5ch border-top-right-radius: 1em overflow: hidden box-shadow: 1px 1px 1px #000
@media screen and (max-width: 1921px) width: calc(20% - 1ch)
@media screen and (max-width: 1600px) width: calc(25% - 1ch)
@media screen and (max-width: 1200px) width: calc(33.3333333% - 1ch)
@media screen and (max-width: 700px) width: calc(50% - 1ch) margin-top: 0.75ch margin-bottom: 0.75ch @media screen and (max-width: 380px) width: 100%
&.selected background: #282833 color: #cde
> div.row display: flex
> div.row-icon font-size: 1.8em position: absolute width: 0 height: 0
div.roundboi-text width: 0 height: 0 left: 1.4ch top: 0.9em text-align: center position: absolute font-size: 0.333em
> div.title font-size: 0.9em text-align: left margin-top: 0.4em margin-left: 2em margin-right: 1ch height: 1.6em
> div.name.hasRoleOrTag margin-top: -0.275em
> div.tag-list display: flex flex-direction: row font-size: 0.5em
> div.tag display: flex flex-direction: row padding: 0 0.5ch padding-right: 1ch div.tag-name padding-left: 0.5ch
> div.flatboi height: 0.2em
> div.flatboi2 height: 0.2em
&.compact width: 3.1ch border-top-right-radius: 0.25em margin: 0.25ch 0.25ch background: #282833
&.selected background: #3c3c50 div.row margin-left: -0.1ch div.title opacity: 0 </style>
|