aboutsummaryrefslogtreecommitdiff
path: root/src/lib/stores/widgets.js
blob: 2796a7bfa8cb1beb671fe7a2faae9fdc0d761b05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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);
				}
			}
		})();
	});
};