import { derived, readable, writable } from 'svelte/store'; import { queryWithAbort } from '$lib/db'; import { maxSize } from '$lib/config'; const boxParser = /\(([0-9]+),([0-9]+)\),\(([0-9]+),([0-9]+)\)/; export const sensor = writable({ left: 0, top: 0, right: 0, bottom: 0 }); const getBoxQuery = function getBoxQuery({ left, top, right, bottom }) { const boxes = [ `box && box '((${left},${top}),(${right},${bottom}))'`, `box && box '((${left + maxSize},${top + maxSize}),(${right + maxSize},${bottom + maxSize}))'`, `box && box '((${left + maxSize},${top}),(${right + maxSize},${bottom}))'`, `box && box '((${left},${top + maxSize}),(${right},${bottom + maxSize}))'`, `box && box '((${left - maxSize},${top - maxSize}),(${right - maxSize},${bottom - maxSize}))'`, `box && box '((${left - maxSize},${top}),(${right - maxSize},${bottom}))'`, `box && box '((${left},${top - maxSize}),(${right},${bottom - maxSize}))'` ]; return `SELECT * FROM widgets WHERE ${boxes.join(' OR ')}`; }; const serialize = function serialize(widget) { const boxComponents = widget.box.match(boxParser).slice(1, 5).map(Number); const box = { left: Math.min(boxComponents[0], boxComponents[2]), right: Math.max(boxComponents[0], boxComponents[2]), top: Math.min(boxComponents[1], boxComponents[3]), bottom: Math.max(boxComponents[1], boxComponents[3]) }; return { ...widget, box }; }; let ac = null; export const widgets = derived(sensor, async ($sensor, set) => { const query = getBoxQuery($sensor); ac && ac.abort(); ac = new AbortController(); try { const { rows } = await queryWithAbort(query, [], ac.signal); if (rows) { return set(rows.map(serialize)); } } catch (error) { if (error.message !== 'Query aborted') { console.error('Error fetching widgets:', error); } } }); export const countElements = function countElements(left, top, right, bottom) { let countAc = null; return readable(0, (set) => { (async function () { countAc && countAc.abort(); countAc = new AbortController(); try { const countQuery = `SELECT COUNT(*) FROM widgets WHERE box && box '((${left},${top}),(${right},${bottom}))'`; const { rows } = await queryWithAbort(countQuery, [], countAc.signal); if (rows && rows[0]) { return set(parseInt(rows[0].count)); } } catch (error) { if (error.message !== 'Query aborted') { console.error('Error counting widgets:', error); } } })(); }); };