Initial implementation of Bluetooth toy control app
Next.js app with a browser-side buttplug/buttplug-wasm control layer (server never touches real-time device commands), SQLite storage via Drizzle, single-secret auth, recordings/replay with device remapping, a usage stats dashboard, Docker deployment, and Gitea CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W8WkFF5ppURBAB918593Eb
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Per-actuator leading+trailing debounce so a dragged slider doesn't fire a
|
||||
* device command on every pointermove - devices don't need mouse-move-rate
|
||||
* updates, and most BLE stacks choke on a command flood.
|
||||
*/
|
||||
const THROTTLE_MS = 75;
|
||||
|
||||
interface ThrottleEntry {
|
||||
timer: ReturnType<typeof setTimeout> | null;
|
||||
pendingValue: number | null;
|
||||
pendingDuration: number | undefined;
|
||||
lastSentAt: number;
|
||||
}
|
||||
|
||||
const entries = new Map<string, ThrottleEntry>();
|
||||
|
||||
export function throttledSend(
|
||||
key: string,
|
||||
send: (value: number, durationMs?: number) => void | Promise<void>,
|
||||
value: number,
|
||||
durationMs?: number,
|
||||
): void {
|
||||
let entry = entries.get(key);
|
||||
if (!entry) {
|
||||
entry = { timer: null, pendingValue: null, pendingDuration: undefined, lastSentAt: 0 };
|
||||
entries.set(key, entry);
|
||||
}
|
||||
|
||||
entry.pendingValue = value;
|
||||
entry.pendingDuration = durationMs;
|
||||
|
||||
const flush = (): void => {
|
||||
const v = entry!.pendingValue;
|
||||
entry!.pendingValue = null;
|
||||
entry!.timer = null;
|
||||
entry!.lastSentAt = Date.now();
|
||||
if (v !== null) void send(v, entry!.pendingDuration);
|
||||
};
|
||||
|
||||
const elapsed = Date.now() - entry.lastSentAt;
|
||||
if (elapsed >= THROTTLE_MS) {
|
||||
if (entry.timer) clearTimeout(entry.timer);
|
||||
flush();
|
||||
} else if (!entry.timer) {
|
||||
entry.timer = setTimeout(flush, THROTTLE_MS - elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
export function clearThrottle(key: string): void {
|
||||
const entry = entries.get(key);
|
||||
if (entry?.timer) clearTimeout(entry.timer);
|
||||
entries.delete(key);
|
||||
}
|
||||
Reference in New Issue
Block a user