181 lines
6.5 KiB
Svelte
181 lines
6.5 KiB
Svelte
<script lang="ts">
|
||
import { runCommand } from "$lib/client/lucifer";
|
||
import HSplit from "$lib/components/HSplit.svelte";
|
||
import HSplitPart from "$lib/components/HSplitPart.svelte";
|
||
import Modal from "$lib/components/Modal.svelte";
|
||
import ModalBody from "$lib/components/ModalBody.svelte";
|
||
import ModalSection from "$lib/components/ModalSection.svelte";
|
||
import ScriptLineBlock from "$lib/components/scripting/ScriptLineBlock.svelte";
|
||
import { getModalContext } from "$lib/contexts/ModalContext.svelte";
|
||
import { getStateContext } from "$lib/contexts/StateContext.svelte";
|
||
import { fromEditableTrigger, newEditableScriptLine, newEditableTrigger, toEditableScriptLine, toEditableTrigger, type TriggerEditable } from "$lib/models/script";
|
||
|
||
const { state, deviceList, maskList } = getStateContext();
|
||
const { modal } = getModalContext();
|
||
|
||
let show = false;
|
||
let disabled = false;
|
||
let selectedTrigger = "";
|
||
let deleteCount = 3;
|
||
|
||
let current: TriggerEditable = newEditableTrigger("*", "");
|
||
|
||
async function submitForm() {
|
||
disabled = true;
|
||
|
||
try {
|
||
const before = Object.keys($state.triggers);
|
||
await runCommand({updateTrigger: fromEditableTrigger(current)});
|
||
|
||
if (current.id === null) {
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
const after = Object.keys($state.triggers);
|
||
selectedTrigger = after.find(id => !before.includes(id)) || triggerList[0].id;
|
||
}
|
||
} catch(_) {}
|
||
|
||
deleteCount = 3;
|
||
disabled = false;
|
||
}
|
||
|
||
async function deleteTrigger() {
|
||
deleteCount -= 1;
|
||
if (deleteCount <= 0) {
|
||
try {
|
||
await runCommand({deleteTrigger: {id: selectedTrigger}});
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
selectedTrigger = triggerList[0]?.id || "";
|
||
} catch(_) {}
|
||
}
|
||
}
|
||
|
||
function loadTrigger(id: string) {
|
||
deleteCount = 3;
|
||
|
||
if (id !== "") {
|
||
current = toEditableTrigger($state.triggers[id]);
|
||
} else {
|
||
current = {...current, id: null};
|
||
}
|
||
}
|
||
|
||
function addPreLine() {
|
||
current.scriptPre = [...current.scriptPre, newEditableScriptLine()]
|
||
}
|
||
|
||
function addPostLine() {
|
||
current.scriptPost = [...current.scriptPost, newEditableScriptLine()]
|
||
}
|
||
|
||
function ensureButton(buttonList: string[]) {
|
||
if (!buttonList.includes(current.button)) {
|
||
current.button = buttonList[0];
|
||
}
|
||
}
|
||
|
||
$: loadTrigger(selectedTrigger);
|
||
$: triggerList = Object.keys($state.triggers).map(k => $state.triggers[k]).sort((a, b) => (
|
||
a.event.localeCompare(b.event)
|
||
|| a.deviceMatch.localeCompare(b.deviceMatch)
|
||
|| a.parameter.localeCompare(b.parameter)
|
||
));
|
||
$: buttonList = $deviceList.filter(d => d.aliases.includes(current.deviceMatch))
|
||
.flatMap(d => d.hwState?.buttons||[])
|
||
.sort()
|
||
.filter((e,i,a) => a[i-1] !== e);
|
||
$: scriptList = Object.keys($state.scripts).sort();
|
||
$: maskGroups = $maskList.map(s => s.split(":")[1]).filter((e, i, a) => a[i-1] !== e).sort().reverse();
|
||
$: show = ($modal.kind === "trigger.edit");
|
||
$: if (scriptList.length > 0 && current.scriptName === "") { current.scriptName = scriptList[0]; };
|
||
$: ensureButton(buttonList);
|
||
</script>
|
||
|
||
<form novalidate on:submit|preventDefault={submitForm}>
|
||
<Modal
|
||
ultrawide closable show={show}
|
||
titleText="Trigger Editor"
|
||
disabled={disabled}
|
||
submitText="Save Trigger"
|
||
>
|
||
<ModalBody>
|
||
<HSplit>
|
||
<HSplitPart weight={1}>
|
||
<label for="mask">Trigger</label>
|
||
<select bind:value={selectedTrigger}>
|
||
{#each triggerList as trigger (trigger.id)}
|
||
<option value={trigger.id}>{trigger.name || `${trigger.deviceMatch} – ${trigger.event} ${trigger.parameter}`}</option>
|
||
{/each}
|
||
<option value="">New Trigger</option>
|
||
</select>
|
||
</HSplitPart>
|
||
<HSplitPart weight={2}>
|
||
</HSplitPart>
|
||
</HSplit>
|
||
<HSplit>
|
||
<HSplitPart weight={1}>
|
||
<label for="mask">Event</label>
|
||
<select bind:value={current.event}>
|
||
<option value="Button">Button Pressed</option>
|
||
<option value="Time">Time Changed</option>
|
||
</select>
|
||
</HSplitPart>
|
||
<HSplitPart weight={1}>
|
||
{#if current.event === "Button"}
|
||
<label for="mask">Button</label>
|
||
<select bind:value={current.button}>
|
||
{#each buttonList as buttonOption}
|
||
<option value={buttonOption}>{buttonOption}</option>
|
||
{/each}
|
||
</select>
|
||
{:else}
|
||
<label for="mask">Time</label>
|
||
<input type="time" bind:value={current.time} />
|
||
{/if}
|
||
</HSplitPart>
|
||
<HSplitPart weight={1}>
|
||
{#if current.event === "Button"}
|
||
<label for="mask">Device</label>
|
||
<select bind:value={current.deviceMatch}>
|
||
{#each maskGroups as g}
|
||
<optgroup label="{g.slice(0, 1).toUpperCase() + g.slice(1)}">
|
||
{#each $maskList.filter(m => m.split(":")[1] === g) as mask}
|
||
<option value={mask}>{mask}</option>
|
||
{/each}
|
||
</optgroup>
|
||
{/each}
|
||
</select>
|
||
{/if}
|
||
</HSplitPart>
|
||
</HSplit>
|
||
<HSplit>
|
||
<HSplitPart weight={1}>
|
||
<label for="mask">Run Script</label>
|
||
<select bind:value={current.scriptName}>
|
||
{#each scriptList as script}
|
||
<option value={script}>{script}</option>
|
||
{/each}
|
||
</select>
|
||
</HSplitPart>
|
||
<HSplitPart weight={1}>
|
||
<label for="mask">Script Target</label>
|
||
<select bind:value={current.scriptTarget}>
|
||
{#each maskGroups as g}
|
||
<optgroup label="{g.slice(0, 1).toUpperCase() + g.slice(1)}">
|
||
{#each $maskList.filter(m => m.split(":")[1] === g) as mask}
|
||
<option value={mask}>{mask}</option>
|
||
{/each}
|
||
</optgroup>
|
||
{/each}
|
||
</select>
|
||
</HSplitPart>
|
||
<HSplitPart weight={1}>
|
||
</HSplitPart>
|
||
</HSplit>
|
||
<ModalSection expanded disableExpandToggle title="Trigger-Specific Scripting">
|
||
<ScriptLineBlock add on:add={addPreLine} label="Before Script" bind:value={current.scriptPre} />
|
||
<ScriptLineBlock add on:add={addPostLine} label="After Script" bind:value={current.scriptPost} />
|
||
</ModalSection>
|
||
</ModalBody>
|
||
<button slot="secondary-button-1" disabled={disabled || selectedTrigger === ""} on:click|preventDefault={deleteTrigger}>Delete ({deleteCount})</button>
|
||
</Modal>
|
||
</form> |