Files
sexy/packages/buttplug/src/utils/ButtplugMessageSorter.ts
Sebastian Krüger e744d1e40f
All checks were successful
Build and Push Docker Image to Gitea / build-and-push (push) Successful in 5m44s
fix: clean up stale sorter entries and fix battery reactivity
ButtplugMessageSorter never deleted entries from _waitingMsgs after
resolving, causing unsolicited DeviceList messages (with reused Ids)
to be swallowed. Also fix battery level not updating in UI by accessing
the device through the Svelte $state proxy array.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 13:07:13 +01:00

68 lines
2.0 KiB
TypeScript

/*!
* Buttplug JS Source Code File - Visit https://buttplug.io for more info about
* the project. Licensed under the BSD 3-Clause license. See LICENSE file in the
* project root for full license information.
*
* @copyright Copyright (c) Nonpolynomial Labs LLC. All rights reserved.
*/
import * as Messages from '../core/Messages';
import { ButtplugError } from '../core/Exceptions';
export class ButtplugMessageSorter {
protected _counter = 1;
protected _waitingMsgs: Map<
number,
[(val: Messages.ButtplugMessage) => void, (err: Error) => void]
> = new Map();
public constructor(private _useCounter: boolean) {}
// One of the places we should actually return a promise, as we need to store
// them while waiting for them to return across the line.
// tslint:disable:promise-function-async
public PrepareOutgoingMessage(
msg: Messages.ButtplugMessage
): Promise<Messages.ButtplugMessage> {
if (this._useCounter) {
Messages.setMsgId(msg, this._counter);
// Always increment last, otherwise we might lose sync
this._counter += 1;
}
let res;
let rej;
const msgPromise = new Promise<Messages.ButtplugMessage>(
(resolve, reject) => {
res = resolve;
rej = reject;
}
);
this._waitingMsgs.set(Messages.msgId(msg), [res, rej]);
return msgPromise;
}
public ParseIncomingMessages(
msgs: Messages.ButtplugMessage[]
): Messages.ButtplugMessage[] {
const noMatch: Messages.ButtplugMessage[] = [];
for (const x of msgs) {
let id = Messages.msgId(x);
if (id !== Messages.SYSTEM_MESSAGE_ID && this._waitingMsgs.has(id)) {
const [res, rej] = this._waitingMsgs.get(id)!;
this._waitingMsgs.delete(id);
// If we've gotten back an error, reject the related promise using a
// ButtplugException derived type.
if (x.Error !== undefined) {
rej(ButtplugError.FromError(x.Error!));
continue;
}
res(x);
continue;
} else {
noMatch.push(x);
}
}
return noMatch;
}
}