SOURCE / PINNED RELEASE
Made of little things.
Funclet
- Release
- 0b497cfc2f66…
- Author-recorded commit
- 1e531b24f490…
- License
- LICENSE
- Author’s source reference
- nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-6b7a37cac1d
Archive hash verified: 71d97a89ed8c40c2…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
interface VolumeStorage {
getItem(key: string): Promise<string | null>;
setItem(key: string, value: string): Promise<void>;
}
/** Serialize writes and never overwrite a new gesture with a late startup read. */
class StoredPreference<T> {
private revision = 0;
private pending: string | undefined;
private writing = false;
constructor(private storage: VolumeStorage | undefined, private key: string, private decode: (raw: string) => T | null, private encode: (value: T) => string) {}
async load(): Promise<T | null> {
const revision = this.revision;
try {
const raw = await this.storage?.getItem(this.key);
if (revision !== this.revision || raw == null || raw.trim() === '') return null;
return this.decode(raw);
} catch { return null; }
}
save(value: T): void {
++this.revision;
if (!this.storage) return;
this.pending = this.encode(value);
void this.flush();
}
private async flush(): Promise<void> {
if (this.writing || !this.storage) return;
this.writing = true;
try {
while (this.pending !== undefined) {
const value = this.pending;
this.pending = undefined;
try { await this.storage.setItem(this.key, value); } catch { /* Session controls remain usable. */ }
}
} finally { this.writing = false; }
}
}
export class VolumePreference extends StoredPreference<number> {
constructor(storage: VolumeStorage | undefined) {
super(storage, 'receiver-volume', raw => {
const value = Number(raw);
return Number.isFinite(value) && value >= 0 && value <= 1 ? value : null;
}, String);
}
}
export class StationPreference extends StoredPreference<string> {
constructor(storage: VolumeStorage | undefined) {
super(storage, 'receiver-station', raw => /^31237:[a-f0-9]{64}:.{1,1024}$/i.test(raw) ? raw : null, String);
}
}
