@glassly/engine 0.3.8-dev.1014 → 0.3.8-dev.1016

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Decides when each connected Meta Neural Band runs its handwriting model. The
3
+ * model streams to the phone for as long as it runs, written on or not, so it
4
+ * runs only while it can type somewhere: the wearer has handwriting enabled
5
+ * and a miniapp has a text field open on the glasses. It outlives the last
6
+ * field by OFF_DELAY_MS, so moving between fields doesn't restart it. A session
7
+ * the band ends on its own (timeout, refused setting, silence) isn't retried
8
+ * until no field is open, so a band that can't run the model isn't asked again
9
+ * and again.
10
+ */
11
+ import type { NeuralBandHandwritingStatus } from "./NeuralBandInput";
12
+ type Phase = NeuralBandHandwritingStatus["phase"];
13
+ export interface HandwritingGateDeps {
14
+ enabled: () => boolean;
15
+ textFieldOpen: () => boolean;
16
+ setHandwriting: (id: string, enabled: boolean) => Promise<void>;
17
+ setTimeout: (fn: () => void, ms: number) => unknown;
18
+ clearTimeout: (handle: unknown) => void;
19
+ }
20
+ export declare const OFF_DELAY_MS = 5000;
21
+ export declare class HandwritingGate {
22
+ private readonly deps;
23
+ private bands;
24
+ private offTimer;
25
+ constructor(deps: HandwritingGateDeps);
26
+ /** The connected bands. A band keeps nothing across connections, so a reconnect starts fresh. */
27
+ setBands(ids: string[]): void;
28
+ /** A band reported its handwriting phase. */
29
+ status(id: string, phase: Phase): void;
30
+ /** Re-evaluate after the setting or the open text fields changed. */
31
+ update(): void;
32
+ dispose(): void;
33
+ private stopAll;
34
+ private request;
35
+ private clearOffTimer;
36
+ }
37
+ export {};
38
+ //# sourceMappingURL=HandwritingGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HandwritingGate.d.ts","sourceRoot":"","sources":["../../../src/services/neuralBand/HandwritingGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,mBAAmB,CAAA;AAElE,KAAK,KAAK,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAA;AAEjD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,OAAO,CAAA;IACtB,aAAa,EAAE,MAAM,OAAO,CAAA;IAC5B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/D,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACnD,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACxC;AASD,eAAO,MAAM,YAAY,OAAQ,CAAA;AAGjC,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,QAAQ,CAAgB;gBAEH,IAAI,EAAE,mBAAmB;IAEtD,iGAAiG;IACjG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAM7B,6CAA6C;IAC7C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAWtC,qEAAqE;IACrE,MAAM,IAAI,IAAI;IA2Bd,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,aAAa;CAKtB"}
@@ -0,0 +1,89 @@
1
+ export const OFF_DELAY_MS = 5_000;
2
+ const ACTIVE = new Set(["preparing", "ready", "restoring"]);
3
+ export class HandwritingGate {
4
+ deps;
5
+ bands = new Map();
6
+ offTimer = null;
7
+ constructor(deps) {
8
+ this.deps = deps;
9
+ }
10
+ /** The connected bands. A band keeps nothing across connections, so a reconnect starts fresh. */
11
+ setBands(ids) {
12
+ for (const id of [...this.bands.keys()])
13
+ if (!ids.includes(id))
14
+ this.bands.delete(id);
15
+ for (const id of ids)
16
+ if (!this.bands.has(id))
17
+ this.bands.set(id, { requested: false, failed: false, phase: "idle" });
18
+ this.update();
19
+ }
20
+ /** A band reported its handwriting phase. */
21
+ status(id, phase) {
22
+ const band = this.bands.get(id);
23
+ if (!band)
24
+ return;
25
+ band.phase = phase;
26
+ if (phase === "finished" && band.requested) {
27
+ band.requested = false;
28
+ band.failed = true;
29
+ }
30
+ this.update();
31
+ }
32
+ /** Re-evaluate after the setting or the open text fields changed. */
33
+ update() {
34
+ const enabled = this.deps.enabled();
35
+ if (enabled && this.deps.textFieldOpen()) {
36
+ this.clearOffTimer();
37
+ for (const [id, band] of this.bands) {
38
+ // A session still winding down (or one we didn't start) has to finish first.
39
+ if (band.requested || band.failed || ACTIVE.has(band.phase))
40
+ continue;
41
+ this.request(id, band, true);
42
+ }
43
+ return;
44
+ }
45
+ for (const band of this.bands.values())
46
+ band.failed = false;
47
+ if (![...this.bands.values()].some((band) => band.requested)) {
48
+ this.clearOffTimer();
49
+ return;
50
+ }
51
+ if (!enabled) {
52
+ this.clearOffTimer();
53
+ this.stopAll();
54
+ }
55
+ else if (this.offTimer === null) {
56
+ this.offTimer = this.deps.setTimeout(() => {
57
+ this.offTimer = null;
58
+ if (!this.deps.textFieldOpen() || !this.deps.enabled())
59
+ this.stopAll();
60
+ }, OFF_DELAY_MS);
61
+ }
62
+ }
63
+ dispose() {
64
+ this.clearOffTimer();
65
+ this.bands.clear();
66
+ }
67
+ stopAll() {
68
+ for (const [id, band] of this.bands)
69
+ if (band.requested)
70
+ this.request(id, band, false);
71
+ }
72
+ request(id, band, enabled) {
73
+ band.requested = enabled;
74
+ this.deps.setHandwriting(id, enabled).catch((err) => {
75
+ console.warn(`HandwritingGate: turning handwriting ${enabled ? "on" : "off"} failed:`, err);
76
+ if (enabled && this.bands.get(id) === band && band.requested) {
77
+ band.requested = false;
78
+ band.failed = true;
79
+ }
80
+ });
81
+ }
82
+ clearOffTimer() {
83
+ if (this.offTimer === null)
84
+ return;
85
+ this.deps.clearTimeout(this.offTimer);
86
+ this.offTimer = null;
87
+ }
88
+ }
89
+ //# sourceMappingURL=HandwritingGate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HandwritingGate.js","sourceRoot":"","sources":["../../../src/services/neuralBand/HandwritingGate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Decides when each connected Meta Neural Band runs its handwriting model. The\n * model streams to the phone for as long as it runs, written on or not, so it\n * runs only while it can type somewhere: the wearer has handwriting enabled\n * and a miniapp has a text field open on the glasses. It outlives the last\n * field by OFF_DELAY_MS, so moving between fields doesn't restart it. A session\n * the band ends on its own (timeout, refused setting, silence) isn't retried\n * until no field is open, so a band that can't run the model isn't asked again\n * and again.\n */\nimport type {NeuralBandHandwritingStatus} from \"./NeuralBandInput\"\n\ntype Phase = NeuralBandHandwritingStatus[\"phase\"]\n\nexport interface HandwritingGateDeps {\n enabled: () => boolean\n textFieldOpen: () => boolean\n setHandwriting: (id: string, enabled: boolean) => Promise<void>\n setTimeout: (fn: () => void, ms: number) => unknown\n clearTimeout: (handle: unknown) => void\n}\n\ninterface Band {\n /** What we last asked this band for. */\n requested: boolean\n failed: boolean\n phase: Phase\n}\n\nexport const OFF_DELAY_MS = 5_000\nconst ACTIVE = new Set<Phase>([\"preparing\", \"ready\", \"restoring\"])\n\nexport class HandwritingGate {\n private bands = new Map<string, Band>()\n private offTimer: unknown = null\n\n constructor(private readonly deps: HandwritingGateDeps) {}\n\n /** The connected bands. A band keeps nothing across connections, so a reconnect starts fresh. */\n setBands(ids: string[]): void {\n for (const id of [...this.bands.keys()]) if (!ids.includes(id)) this.bands.delete(id)\n for (const id of ids) if (!this.bands.has(id)) this.bands.set(id, {requested: false, failed: false, phase: \"idle\"})\n this.update()\n }\n\n /** A band reported its handwriting phase. */\n status(id: string, phase: Phase): void {\n const band = this.bands.get(id)\n if (!band) return\n band.phase = phase\n if (phase === \"finished\" && band.requested) {\n band.requested = false\n band.failed = true\n }\n this.update()\n }\n\n /** Re-evaluate after the setting or the open text fields changed. */\n update(): void {\n const enabled = this.deps.enabled()\n if (enabled && this.deps.textFieldOpen()) {\n this.clearOffTimer()\n for (const [id, band] of this.bands) {\n // A session still winding down (or one we didn't start) has to finish first.\n if (band.requested || band.failed || ACTIVE.has(band.phase)) continue\n this.request(id, band, true)\n }\n return\n }\n for (const band of this.bands.values()) band.failed = false\n if (![...this.bands.values()].some((band) => band.requested)) {\n this.clearOffTimer()\n return\n }\n if (!enabled) {\n this.clearOffTimer()\n this.stopAll()\n } else if (this.offTimer === null) {\n this.offTimer = this.deps.setTimeout(() => {\n this.offTimer = null\n if (!this.deps.textFieldOpen() || !this.deps.enabled()) this.stopAll()\n }, OFF_DELAY_MS)\n }\n }\n\n dispose(): void {\n this.clearOffTimer()\n this.bands.clear()\n }\n\n private stopAll(): void {\n for (const [id, band] of this.bands) if (band.requested) this.request(id, band, false)\n }\n\n private request(id: string, band: Band, enabled: boolean): void {\n band.requested = enabled\n this.deps.setHandwriting(id, enabled).catch((err) => {\n console.warn(`HandwritingGate: turning handwriting ${enabled ? \"on\" : \"off\"} failed:`, err)\n if (enabled && this.bands.get(id) === band && band.requested) {\n band.requested = false\n band.failed = true\n }\n })\n }\n\n private clearOffTimer(): void {\n if (this.offTimer === null) return\n this.deps.clearTimeout(this.offTimer)\n this.offTimer = null\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"NeuralBandSettingsSync.d.ts","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandSettingsSync.ts"],"names":[],"mappings":"AAyCA,wBAAgB,2BAA2B,IAAI,IAAI,CA8BlD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD"}
1
+ {"version":3,"file":"NeuralBandSettingsSync.d.ts","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandSettingsSync.ts"],"names":[],"mappings":"AAqEA,wBAAgB,2BAA2B,IAAI,IAAI,CAgClD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD"}
@@ -1,14 +1,21 @@
1
1
  /**
2
- * Pushes the Neural Band user settings (air mouse, wearing hand) to every
3
- * connected band: to each band as it connects, and to all of them whenever
4
- * either setting changes. The native side keeps nothing across connections.
2
+ * Pushes the Neural Band user settings (air mouse, wearing hand, vibration) to
3
+ * every connected band: to each band as it connects, and to all of them
4
+ * whenever a setting changes. The native side keeps nothing across
5
+ * connections. Handwriting is gated, not pushed: HandwritingGate runs it while
6
+ * the setting is on and a miniapp has a text field open.
5
7
  */
6
8
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal";
7
9
  import { useGlassesStore } from "../../stores/glasses";
8
10
  import { SETTINGS, useSettingsStore } from "../../stores/settings";
9
11
  import { ControllerTypes } from "../../types/enums";
12
+ import { BgTimer } from "../../utils/timers";
10
13
  import { readyControllers } from "../controllers";
14
+ import localMiniappRuntime from "../LocalMiniappRuntime";
15
+ import { HandwritingGate } from "./HandwritingGate";
16
+ import neuralBandInput from "./NeuralBandInput";
11
17
  let unsubscribers = [];
18
+ let handwriting = null;
12
19
  function connectedBandIds() {
13
20
  return readyControllers(useGlassesStore.getState().controllers)
14
21
  .filter((status) => status.model === ControllerTypes.NEURAL_BAND)
@@ -26,11 +33,29 @@ function pushVibration(id) {
26
33
  const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_vibration.key) !== false;
27
34
  void BluetoothSdk.neuralBandSetGestureHaptics(id, enabled).catch((err) => console.warn("NeuralBandSettingsSync: vibration push failed:", err));
28
35
  }
36
+ function startHandwritingGate() {
37
+ const gate = new HandwritingGate({
38
+ enabled: () => useSettingsStore.getState().getSetting(SETTINGS.neural_band_handwriting.key) !== false,
39
+ textFieldOpen: () => localMiniappRuntime.hasOpenTextField(),
40
+ setHandwriting: (id, enabled) => BluetoothSdk.neuralBandSetHandwriting(id, enabled),
41
+ setTimeout: (fn, ms) => BgTimer.setTimeout(fn, ms),
42
+ clearTimeout: (handle) => BgTimer.clearTimeout(handle),
43
+ });
44
+ handwriting = gate;
45
+ gate.setBands(connectedBandIds());
46
+ return [
47
+ useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.neural_band_handwriting.key), () => gate.update()),
48
+ localMiniappRuntime.onTextFieldChange(() => gate.update()),
49
+ neuralBandInput.onHandwritingStatus(({ id, status }) => gate.status(id, status.phase)),
50
+ () => gate.dispose(),
51
+ ];
52
+ }
29
53
  export function startNeuralBandSettingsSync() {
30
54
  if (unsubscribers.length > 0)
31
55
  return;
32
56
  let connected = new Set(connectedBandIds());
33
57
  unsubscribers = [
58
+ ...startHandwritingGate(),
34
59
  useGlassesStore.subscribe(() => connectedBandIds().sort().join(","), () => {
35
60
  const next = new Set(connectedBandIds());
36
61
  for (const id of next) {
@@ -41,6 +66,7 @@ export function startNeuralBandSettingsSync() {
41
66
  pushVibration(id);
42
67
  }
43
68
  connected = next;
69
+ handwriting?.setBands([...next]);
44
70
  }),
45
71
  useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.neural_band_air_mouse.key), () => connectedBandIds().forEach(pushAirMouse)),
46
72
  useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.neural_band_hand.key), () => connectedBandIds().forEach(pushHand)),
@@ -51,5 +77,6 @@ export function stopNeuralBandSettingsSync() {
51
77
  for (const unsubscribe of unsubscribers)
52
78
  unsubscribe();
53
79
  unsubscribers = [];
80
+ handwriting = null;
54
81
  }
55
82
  //# sourceMappingURL=NeuralBandSettingsSync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NeuralBandSettingsSync.js","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandSettingsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pushes the Neural Band user settings (air mouse, wearing hand) to every\n * connected band: to each band as it connects, and to all of them whenever\n * either setting changes. The native side keeps nothing across connections.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\n\nimport {useGlassesStore} from \"../../stores/glasses\"\nimport {SETTINGS, useSettingsStore} from \"../../stores/settings\"\nimport {ControllerTypes} from \"../../types/enums\"\nimport {readyControllers} from \"../controllers\"\n\nlet unsubscribers: (() => void)[] = []\n\nfunction connectedBandIds(): string[] {\n return readyControllers(useGlassesStore.getState().controllers)\n .filter((status) => status.model === ControllerTypes.NEURAL_BAND)\n .map((status) => status.id)\n}\n\nfunction pushAirMouse(id: string): void {\n const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_air_mouse.key) === true\n void BluetoothSdk.neuralBandSetPointer(id, enabled).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: air mouse push failed:\", err),\n )\n}\n\nfunction pushHand(id: string): void {\n const hand = useSettingsStore.getState().getSetting(SETTINGS.neural_band_hand.key) === \"left\" ? \"left\" : \"right\"\n void BluetoothSdk.neuralBandSetHand(id, hand).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: hand push failed:\", err),\n )\n}\n\nfunction pushVibration(id: string): void {\n const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_vibration.key) !== false\n void BluetoothSdk.neuralBandSetGestureHaptics(id, enabled).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: vibration push failed:\", err),\n )\n}\n\nexport function startNeuralBandSettingsSync(): void {\n if (unsubscribers.length > 0) return\n let connected = new Set(connectedBandIds())\n unsubscribers = [\n useGlassesStore.subscribe(\n () => connectedBandIds().sort().join(\",\"),\n () => {\n const next = new Set(connectedBandIds())\n for (const id of next) {\n if (connected.has(id)) continue\n pushAirMouse(id)\n pushHand(id)\n pushVibration(id)\n }\n connected = next\n },\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_air_mouse.key),\n () => connectedBandIds().forEach(pushAirMouse),\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_hand.key),\n () => connectedBandIds().forEach(pushHand),\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_vibration.key),\n () => connectedBandIds().forEach(pushVibration),\n ),\n ]\n}\n\nexport function stopNeuralBandSettingsSync(): void {\n for (const unsubscribe of unsubscribers) unsubscribe()\n unsubscribers = []\n}\n"]}
1
+ {"version":3,"file":"NeuralBandSettingsSync.js","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandSettingsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pushes the Neural Band user settings (air mouse, wearing hand, vibration) to\n * every connected band: to each band as it connects, and to all of them\n * whenever a setting changes. The native side keeps nothing across\n * connections. Handwriting is gated, not pushed: HandwritingGate runs it while\n * the setting is on and a miniapp has a text field open.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\n\nimport {useGlassesStore} from \"../../stores/glasses\"\nimport {SETTINGS, useSettingsStore} from \"../../stores/settings\"\nimport {ControllerTypes} from \"../../types/enums\"\nimport {BgTimer} from \"../../utils/timers\"\nimport {readyControllers} from \"../controllers\"\nimport localMiniappRuntime from \"../LocalMiniappRuntime\"\nimport {HandwritingGate} from \"./HandwritingGate\"\nimport neuralBandInput from \"./NeuralBandInput\"\n\nlet unsubscribers: (() => void)[] = []\nlet handwriting: HandwritingGate | null = null\n\nfunction connectedBandIds(): string[] {\n return readyControllers(useGlassesStore.getState().controllers)\n .filter((status) => status.model === ControllerTypes.NEURAL_BAND)\n .map((status) => status.id)\n}\n\nfunction pushAirMouse(id: string): void {\n const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_air_mouse.key) === true\n void BluetoothSdk.neuralBandSetPointer(id, enabled).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: air mouse push failed:\", err),\n )\n}\n\nfunction pushHand(id: string): void {\n const hand = useSettingsStore.getState().getSetting(SETTINGS.neural_band_hand.key) === \"left\" ? \"left\" : \"right\"\n void BluetoothSdk.neuralBandSetHand(id, hand).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: hand push failed:\", err),\n )\n}\n\nfunction pushVibration(id: string): void {\n const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_vibration.key) !== false\n void BluetoothSdk.neuralBandSetGestureHaptics(id, enabled).catch((err) =>\n console.warn(\"NeuralBandSettingsSync: vibration push failed:\", err),\n )\n}\n\nfunction startHandwritingGate(): (() => void)[] {\n const gate = new HandwritingGate({\n enabled: () => useSettingsStore.getState().getSetting(SETTINGS.neural_band_handwriting.key) !== false,\n textFieldOpen: () => localMiniappRuntime.hasOpenTextField(),\n setHandwriting: (id, enabled) => BluetoothSdk.neuralBandSetHandwriting(id, enabled),\n setTimeout: (fn, ms) => BgTimer.setTimeout(fn, ms),\n clearTimeout: (handle) => BgTimer.clearTimeout(handle as number),\n })\n handwriting = gate\n gate.setBands(connectedBandIds())\n return [\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_handwriting.key),\n () => gate.update(),\n ),\n localMiniappRuntime.onTextFieldChange(() => gate.update()),\n neuralBandInput.onHandwritingStatus(({id, status}) => gate.status(id, status.phase)),\n () => gate.dispose(),\n ]\n}\n\nexport function startNeuralBandSettingsSync(): void {\n if (unsubscribers.length > 0) return\n let connected = new Set(connectedBandIds())\n unsubscribers = [\n ...startHandwritingGate(),\n useGlassesStore.subscribe(\n () => connectedBandIds().sort().join(\",\"),\n () => {\n const next = new Set(connectedBandIds())\n for (const id of next) {\n if (connected.has(id)) continue\n pushAirMouse(id)\n pushHand(id)\n pushVibration(id)\n }\n connected = next\n handwriting?.setBands([...next])\n },\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_air_mouse.key),\n () => connectedBandIds().forEach(pushAirMouse),\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_hand.key),\n () => connectedBandIds().forEach(pushHand),\n ),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.neural_band_vibration.key),\n () => connectedBandIds().forEach(pushVibration),\n ),\n ]\n}\n\nexport function stopNeuralBandSettingsSync(): void {\n for (const unsubscribe of unsubscribers) unsubscribe()\n unsubscribers = []\n handwriting = null\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAS9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CA+oCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EA4D1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAuBD,eAAO,MAAM,gBAAgB;;;;;;;;EAsX5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAS9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAypCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EA4D1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAuBD,eAAO,MAAM,gBAAgB;;;;;;;;EAsX5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}
@@ -804,6 +804,16 @@ export const SETTINGS = {
804
804
  saveOnServer: false,
805
805
  persist: true,
806
806
  },
807
+ // Meta Neural Band handwriting typing into miniapps. Enabled means the band runs
808
+ // its handwriting model while a miniapp has a text field open on the glasses
809
+ // (HandwritingGate); the model streams the whole time it runs, so never otherwise.
810
+ neural_band_handwriting: {
811
+ key: "neural_band_handwriting",
812
+ defaultValue: () => true,
813
+ writable: true,
814
+ saveOnServer: false,
815
+ persist: true,
816
+ },
807
817
  // The band's own buzz on each gesture (its haptics pattern 1; pattern 2 is silent).
808
818
  neural_band_vibration: {
809
819
  key: "neural_band_vibration",