Skip to content

Commit

Permalink
Merge pull request #83 from matt8707/input_number
Browse files Browse the repository at this point in the history
Add input_number and number support, closes #66
  • Loading branch information
matt8707 authored Jan 4, 2024
2 parents b2ebb1e + 31bc45e commit 2c3acbc
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 3 deletions.
7 changes: 4 additions & 3 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ List grouped by domains and categorized based on their similar behaviors
- [x] cover
- [x] <https://github.com/matt8707/ha-fusion/issues/29>
- [x] <https://github.com/matt8707/ha-fusion/issues/13>
- [ ] input_number
- [ ] idea: round state if .0
- [ ] support different modes other than mode: slider
- [x] number
- [x] input_number
- [x] idea: round state if .0
- [x] support different modes other than mode: slider
- [x] light
- [x] open rgb issue <https://github.com/matt8707/ha-fusion/issues/18>
- [ ] media_player
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Components/RangeSlider.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
export let value: number;
export let min: number;
export let max: number;
export let step: number | undefined = undefined;
const dispatch = createEventDispatcher();
Expand Down Expand Up @@ -34,6 +35,7 @@
<input
name="slider"
type="range"
{step}
{min}
{max}
bind:value
Expand Down
6 changes: 6 additions & 0 deletions src/lib/Components/StateLogic.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { states, lang, selectedLanguage, editMode } from '$lib/Stores';
import type { HassEntity } from 'home-assistant-js-websocket';
import { isTimestamp, relativeTime } from '$lib/Utils';
import { getDomain } from '$lib/Utils';
export let selected: any;
export let contentWidth: number | undefined = undefined;
Expand Down Expand Up @@ -45,6 +46,11 @@
{:else if entity_id && entity_id.split('.')[0] === 'timer'}
handle timer logic

<!-- Input Number / Number -->
{:else if entity_id && (getDomain(entity_id) === 'input_number' || getDomain(entity_id) === 'number')}
{Number(state) || $lang('unknown')}
{#if attributes?.unit_of_measurement}{attributes.unit_of_measurement}{/if}

<!-- Camera -->
{:else if entity_id && entity_id.split('.')[0] === 'camera'}
<!-- instead of idle? -->
Expand Down
5 changes: 5 additions & 0 deletions src/lib/Main/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@
openModal(() => import('$lib/Modal/SensorModal.svelte'), { sel });
break;
case 'number':
case 'input_number':
openModal(() => import('$lib/Modal/InputNumberModal.svelte'), { sel });
break;
case 'input_select':
case 'select':
openModal(() => import('$lib/Modal/InputSelectModal.svelte'), { sel });
Expand Down
142 changes: 142 additions & 0 deletions src/lib/Modal/InputNumberModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<script lang="ts">
import { states, lang, connection, motion } from '$lib/Stores';
import Modal from '$lib/Modal/Index.svelte';
import ConfigButtons from '$lib/Modal/ConfigButtons.svelte';
import { getDomain, getName } from '$lib/Utils';
import RangeSlider from '$lib/Components/RangeSlider.svelte';
import { callService } from 'home-assistant-js-websocket';
import { onDestroy } from 'svelte';
import { slide } from 'svelte/transition';
export let isOpen: boolean;
export let sel: any;
let draggingValue: number | undefined;
let timeout: ReturnType<typeof setTimeout>;
let errorMessage: string | undefined;
$: entity = $states[sel?.entity_id];
$: value =
entity && (draggingValue === 0 || draggingValue !== undefined)
? draggingValue
: Number(entity?.state);
/**
* Updates the specified entity's value using
* the 'input_number' or 'number' service
*/
async function handleChange(value: number) {
if (!entity?.entity_id) return;
const service = getDomain(entity.entity_id) as string;
errorMessage = undefined;
try {
await callService($connection, service, 'set_value', {
entity_id: entity?.entity_id,
value
});
} catch (error: any) {
errorMessage = error?.message;
}
}
/**
* Handle input_number 'box' mode
*/
function handleInputBox(event: any) {
const target = event?.target as HTMLInputElement;
handleChange(parseFloat(target?.value));
}
/**
* Ends drag event handling by resetting
* `draggingValue` after a delay
*/
function handleEvent() {
clearTimeout(timeout);
timeout = setTimeout(() => {
draggingValue = undefined;
}, $motion);
}
/**
* Clean-up operations when the
* component is unmounted
*/
onDestroy(() => {
clearTimeout(timeout);
});
</script>

<svelte:window on:pointerup={handleEvent} />

{#if isOpen}
<Modal>
<h1 slot="title">{getName(sel, entity)}</h1>

<h2>
{$lang('state')}

<span class="align-right">
{value}

{#if entity?.attributes?.unit_of_measurement}
{entity.attributes.unit_of_measurement}
{/if}
</span>
</h2>

{#if entity && entity?.attributes?.mode === 'slider'}
<RangeSlider
{value}
min={entity?.attributes?.min}
max={entity?.attributes?.max}
step={entity?.attributes?.step}
on:input={(event) => {
draggingValue = event?.detail;
}}
on:change={(event) => {
handleChange(event?.detail);
}}
/>
{:else if entity && entity?.attributes?.mode === 'box'}
<input
class="input"
type="number"
value={Number(entity?.state)}
min={entity?.attributes?.min}
max={entity?.attributes?.max}
step={entity?.attributes?.step}
on:change={handleInputBox}
/>
{/if}

{#if errorMessage}
<p transition:slide={{ duration: $motion / 1.5 }}>
{errorMessage}
</p>
{/if}

<ConfigButtons />
</Modal>
{/if}

<style>
.input[type='number'] {
color-scheme: dark;
}
p {
color: white;
margin-bottom: 12px;
background-color: rgb(178 0 0 / 74%);
padding: 0.6rem 0.7rem 0.45rem 0.7rem;
border-radius: 0.6rem;
font-family: monospace;
font-size: 0.85rem;
border: 1px solid rgb(255 255 255 / 15%);
}
</style>

0 comments on commit 2c3acbc

Please sign in to comment.