@hawsen-the-first/interactiv 0.0.1

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.
Files changed (48) hide show
  1. package/README.md +326 -0
  2. package/dist/animations.css +160 -0
  3. package/dist/index.d.ts +20 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +26 -0
  6. package/dist/src/animationBus.d.ts +30 -0
  7. package/dist/src/animationBus.d.ts.map +1 -0
  8. package/dist/src/animationBus.js +125 -0
  9. package/dist/src/appBuilder.d.ts +173 -0
  10. package/dist/src/appBuilder.d.ts.map +1 -0
  11. package/dist/src/appBuilder.js +957 -0
  12. package/dist/src/eventBus.d.ts +100 -0
  13. package/dist/src/eventBus.d.ts.map +1 -0
  14. package/dist/src/eventBus.js +326 -0
  15. package/dist/src/eventManager.d.ts +87 -0
  16. package/dist/src/eventManager.d.ts.map +1 -0
  17. package/dist/src/eventManager.js +455 -0
  18. package/dist/src/garbageCollector.d.ts +68 -0
  19. package/dist/src/garbageCollector.d.ts.map +1 -0
  20. package/dist/src/garbageCollector.js +169 -0
  21. package/dist/src/logger.d.ts +11 -0
  22. package/dist/src/logger.d.ts.map +1 -0
  23. package/dist/src/logger.js +15 -0
  24. package/dist/src/navigationManager.d.ts +105 -0
  25. package/dist/src/navigationManager.d.ts.map +1 -0
  26. package/dist/src/navigationManager.js +533 -0
  27. package/dist/src/screensaverManager.d.ts +66 -0
  28. package/dist/src/screensaverManager.d.ts.map +1 -0
  29. package/dist/src/screensaverManager.js +417 -0
  30. package/dist/src/settingsManager.d.ts +48 -0
  31. package/dist/src/settingsManager.d.ts.map +1 -0
  32. package/dist/src/settingsManager.js +317 -0
  33. package/dist/src/stateManager.d.ts +58 -0
  34. package/dist/src/stateManager.d.ts.map +1 -0
  35. package/dist/src/stateManager.js +278 -0
  36. package/dist/src/types.d.ts +32 -0
  37. package/dist/src/types.d.ts.map +1 -0
  38. package/dist/src/types.js +1 -0
  39. package/dist/utils/generateGuid.d.ts +2 -0
  40. package/dist/utils/generateGuid.d.ts.map +1 -0
  41. package/dist/utils/generateGuid.js +19 -0
  42. package/dist/utils/logger.d.ts +9 -0
  43. package/dist/utils/logger.d.ts.map +1 -0
  44. package/dist/utils/logger.js +42 -0
  45. package/dist/utils/template-helpers.d.ts +32 -0
  46. package/dist/utils/template-helpers.d.ts.map +1 -0
  47. package/dist/utils/template-helpers.js +24 -0
  48. package/package.json +59 -0
@@ -0,0 +1,66 @@
1
+ import { EventOrchestrator } from "./eventBus";
2
+ import { Page } from "./appBuilder";
3
+ import { NavigationManager, type TransitionConfig } from "./navigationManager";
4
+ export interface ScreensaverConfig {
5
+ timeoutSeconds: number;
6
+ page: Page;
7
+ defaultViewId?: string;
8
+ screensaverViewBehavior?: "default" | "specific" | "return";
9
+ specificViewId?: string;
10
+ transitionConfig?: TransitionConfig;
11
+ exitBehavior?: "reset" | "return";
12
+ startingPageId?: string;
13
+ startingViewId?: string;
14
+ activityEvents?: string[];
15
+ excludeSelectors?: string[];
16
+ activateCallback?: () => void;
17
+ deactivateCallback?: () => void;
18
+ blockerCallback?: () => boolean;
19
+ rebootTimeout?: number | null;
20
+ rebootCallback?: () => void;
21
+ }
22
+ export declare class ScreensaverManager {
23
+ private eventBus;
24
+ private orchestrator;
25
+ private navigationManager;
26
+ private config;
27
+ private activityTimer;
28
+ private rebootCheckInterval;
29
+ private isScreensaverActive;
30
+ private lastActivePageId;
31
+ private lastActiveViewId;
32
+ private lastScreensaverViewId;
33
+ private lastActivityResetTime;
34
+ private globalListeners;
35
+ private readonly DEBOUNCE_INTERVAL;
36
+ private readonly DEFAULT_ACTIVITY_EVENTS;
37
+ constructor(orchestrator: EventOrchestrator, navigationManager: NavigationManager);
38
+ private initializeGlobalState;
39
+ private setupEventListeners;
40
+ registerScreensaver(config: ScreensaverConfig): void;
41
+ private validateConfig;
42
+ private setupGlobalActivityListeners;
43
+ private shouldIgnoreActivity;
44
+ private resetActivityTimer;
45
+ private pauseActivityTimer;
46
+ private clearActivityTimer;
47
+ private activateScreensaver;
48
+ private determineScreensaverView;
49
+ private handleScreensaverExit;
50
+ private deactivateScreensaver;
51
+ isActive(): boolean;
52
+ getCurrentConfig(): ScreensaverConfig | null;
53
+ getLastActivePageId(): string | null;
54
+ getLastActiveViewId(): string | null;
55
+ getLastScreensaverViewId(): string | null;
56
+ forceActivate(): void;
57
+ forceDeactivate(): void;
58
+ resetTimer(): void;
59
+ private cleanup;
60
+ destroy(): void;
61
+ private hasRebootTimeoutElapsed;
62
+ private checkAndPerformReboot;
63
+ private startRebootCheckInterval;
64
+ private stopRebootCheckInterval;
65
+ }
66
+ //# sourceMappingURL=screensaverManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screensaverManager.d.ts","sourceRoot":"","sources":["../../src/screensaverManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM/E,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,eAAe,CAIf;IAGR,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAG1C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAStC;gBAEU,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB;IASjF,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,mBAAmB;IAwCpB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAiC3D,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,4BAA4B;IAmDpC,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,kBAAkB;YAOZ,mBAAmB;IAkDjC,OAAO,CAAC,wBAAwB;YAclB,qBAAqB;YAmDrB,qBAAqB;IAI5B,QAAQ,IAAI,OAAO;IAInB,gBAAgB,IAAI,iBAAiB,GAAG,IAAI;IAI5C,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAKzC,aAAa,IAAI,IAAI;IAKrB,eAAe,IAAI,IAAI;IAIvB,UAAU,IAAI,IAAI;IAMzB,OAAO,CAAC,OAAO;IAcR,OAAO,IAAI,IAAI;IAUtB,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,uBAAuB;CAOhC"}
@@ -0,0 +1,417 @@
1
+ import { stateManager } from "./stateManager";
2
+ import { logger } from "./logger";
3
+ const log = logger;
4
+ export class ScreensaverManager {
5
+ eventBus;
6
+ orchestrator;
7
+ navigationManager;
8
+ config = null;
9
+ activityTimer = null;
10
+ rebootCheckInterval = null;
11
+ isScreensaverActive = false;
12
+ lastActivePageId = null;
13
+ lastActiveViewId = null;
14
+ lastScreensaverViewId = null;
15
+ lastActivityResetTime = null;
16
+ globalListeners = [];
17
+ // Debounce interval for activity timer resets (in milliseconds)
18
+ DEBOUNCE_INTERVAL = 1000;
19
+ // Default activity events to monitor
20
+ DEFAULT_ACTIVITY_EVENTS = [
21
+ "mousemove",
22
+ "click",
23
+ "keydown",
24
+ "keypress",
25
+ "touchstart",
26
+ "touchmove",
27
+ "wheel",
28
+ "scroll",
29
+ ];
30
+ constructor(orchestrator, navigationManager) {
31
+ this.orchestrator = orchestrator;
32
+ this.navigationManager = navigationManager;
33
+ this.eventBus = orchestrator.registerEventBus("screensaver-manager");
34
+ this.setupEventListeners();
35
+ this.initializeGlobalState();
36
+ }
37
+ initializeGlobalState() {
38
+ if (!stateManager.has("screensaver.isActive")) {
39
+ stateManager.set("screensaver.isActive", false);
40
+ }
41
+ if (!stateManager.has("screensaver.lastActivePageId")) {
42
+ stateManager.set("screensaver.lastActivePageId", null);
43
+ }
44
+ if (!stateManager.has("screensaver.lastActiveViewId")) {
45
+ stateManager.set("screensaver.lastActiveViewId", null);
46
+ }
47
+ if (!stateManager.has("screensaver.lastScreensaverViewId")) {
48
+ stateManager.set("screensaver.lastScreensaverViewId", null);
49
+ }
50
+ if (!stateManager.has("lastReboot")) {
51
+ stateManager.set("lastReboot", Date.now());
52
+ }
53
+ }
54
+ setupEventListeners() {
55
+ this.eventBus.on("register-screensaver", (e) => {
56
+ const { config } = e.detail;
57
+ this.registerScreensaver(config);
58
+ });
59
+ this.eventBus.on("activate-screensaver", () => {
60
+ this.activateScreensaver();
61
+ });
62
+ this.eventBus.on("deactivate-screensaver", () => {
63
+ this.deactivateScreensaver();
64
+ });
65
+ // Listen for navigation changes to track active pages and views
66
+ const navBus = this.orchestrator.getEventBus("navigation-manager");
67
+ if (navBus) {
68
+ navBus.on("page-changed", (e) => {
69
+ const { newPageId } = e.detail;
70
+ if (!this.isScreensaverActive && newPageId !== this.config?.page.componentId) {
71
+ this.lastActivePageId = newPageId;
72
+ stateManager.set("screensaver.lastActivePageId", newPageId);
73
+ }
74
+ });
75
+ navBus.on("view-changed", (e) => {
76
+ const { newViewId } = e.detail;
77
+ if (this.isScreensaverActive) {
78
+ // Track view changes within screensaver for "return" behavior
79
+ this.lastScreensaverViewId = newViewId;
80
+ stateManager.set("screensaver.lastScreensaverViewId", newViewId);
81
+ }
82
+ else {
83
+ this.lastActiveViewId = newViewId;
84
+ stateManager.set("screensaver.lastActiveViewId", newViewId);
85
+ // Timer reset is handled by activity event listeners, not navigation events
86
+ }
87
+ });
88
+ }
89
+ }
90
+ registerScreensaver(config) {
91
+ this.validateConfig(config);
92
+ // Clean up existing screensaver if any
93
+ if (this.config) {
94
+ this.cleanup();
95
+ }
96
+ this.config = {
97
+ ...config,
98
+ exitBehavior: config.exitBehavior || "reset",
99
+ screensaverViewBehavior: config.screensaverViewBehavior || "default",
100
+ activityEvents: config.activityEvents || this.DEFAULT_ACTIVITY_EVENTS,
101
+ excludeSelectors: config.excludeSelectors || [],
102
+ transitionConfig: config.transitionConfig || {
103
+ type: "snap",
104
+ },
105
+ };
106
+ // Register the screensaver page with navigation manager
107
+ const navBus = this.orchestrator.getEventBus("navigation-manager");
108
+ if (navBus) {
109
+ navBus.emit("register-page", { page: this.config.page });
110
+ }
111
+ this.setupGlobalActivityListeners();
112
+ this.resetActivityTimer();
113
+ log.trace(`Screensaver registered with ${config.timeoutSeconds}s timeout and '${this.config.exitBehavior}' exit behavior`);
114
+ }
115
+ validateConfig(config) {
116
+ if (!config.page) {
117
+ throw new Error("Screensaver page is required");
118
+ }
119
+ if (config.timeoutSeconds <= 0) {
120
+ throw new Error("timeoutSeconds must be greater than 0");
121
+ }
122
+ if (config.exitBehavior === "reset" && !config.startingPageId) {
123
+ throw new Error('startingPageId is required when exitBehavior is "reset"');
124
+ }
125
+ if (config.exitBehavior && !["reset", "return"].includes(config.exitBehavior)) {
126
+ throw new Error('exitBehavior must be either "reset" or "return"');
127
+ }
128
+ if (config.screensaverViewBehavior === "specific" && !config.specificViewId) {
129
+ throw new Error('specificViewId is required when screensaverViewBehavior is "specific"');
130
+ }
131
+ if (config.screensaverViewBehavior && !["default", "specific", "return"].includes(config.screensaverViewBehavior)) {
132
+ throw new Error('screensaverViewBehavior must be "default", "specific", or "return"');
133
+ }
134
+ }
135
+ setupGlobalActivityListeners() {
136
+ if (!this.config)
137
+ return;
138
+ const activityHandler = (event) => {
139
+ // Check if event should be ignored based on excludeSelectors
140
+ if (this.shouldIgnoreActivity(event)) {
141
+ return;
142
+ }
143
+ if (this.isScreensaverActive) {
144
+ // If screensaver is active, any activity should exit it
145
+ this.handleScreensaverExit();
146
+ }
147
+ else {
148
+ // If screensaver is not active, check debounce before resetting the timer
149
+ const now = Date.now();
150
+ if (this.lastActivityResetTime === null ||
151
+ now - this.lastActivityResetTime >= this.DEBOUNCE_INTERVAL) {
152
+ this.resetActivityTimer();
153
+ }
154
+ }
155
+ };
156
+ // Add listeners to document for global coverage
157
+ this.config.activityEvents.forEach((eventType) => {
158
+ const listener = activityHandler.bind(this);
159
+ document.addEventListener(eventType, listener, { passive: true });
160
+ this.globalListeners.push({
161
+ element: document,
162
+ type: eventType,
163
+ listener,
164
+ });
165
+ });
166
+ // Also listen for visibility changes (tab switching, etc.)
167
+ const visibilityHandler = () => {
168
+ if (document.hidden) {
169
+ this.pauseActivityTimer();
170
+ }
171
+ else {
172
+ this.resetActivityTimer();
173
+ }
174
+ };
175
+ document.addEventListener("visibilitychange", visibilityHandler);
176
+ this.globalListeners.push({
177
+ element: document,
178
+ type: "visibilitychange",
179
+ listener: visibilityHandler,
180
+ });
181
+ }
182
+ shouldIgnoreActivity(event) {
183
+ if (!this.config?.excludeSelectors?.length)
184
+ return false;
185
+ const target = event.target;
186
+ if (!target)
187
+ return false;
188
+ return this.config.excludeSelectors.some((selector) => {
189
+ try {
190
+ return target.matches(selector) || target.closest(selector);
191
+ }
192
+ catch (e) {
193
+ log.warn(`Invalid exclude selector: ${selector} ${e.message}`);
194
+ return false;
195
+ }
196
+ });
197
+ }
198
+ resetActivityTimer() {
199
+ if (!this.config)
200
+ return;
201
+ this.clearActivityTimer();
202
+ this.activityTimer = window.setTimeout(() => {
203
+ this.activateScreensaver();
204
+ }, this.config.timeoutSeconds * 1000);
205
+ // Record the timestamp for debouncing
206
+ this.lastActivityResetTime = Date.now();
207
+ log.trace(`Activity timer reset for ${this.config.timeoutSeconds} seconds`);
208
+ }
209
+ pauseActivityTimer() {
210
+ this.clearActivityTimer();
211
+ // Reset the debounce timestamp when pausing
212
+ this.lastActivityResetTime = null;
213
+ log.trace("Activity timer paused");
214
+ }
215
+ clearActivityTimer() {
216
+ if (this.activityTimer !== null) {
217
+ clearTimeout(this.activityTimer);
218
+ this.activityTimer = null;
219
+ }
220
+ }
221
+ async activateScreensaver() {
222
+ if (!this.config || this.isScreensaverActive)
223
+ return;
224
+ if (this.config.blockerCallback && this.config.blockerCallback()) {
225
+ this.resetActivityTimer();
226
+ return;
227
+ }
228
+ log.trace("Activating screensaver");
229
+ // Store the current page and view before switching to screensaver
230
+ const currentPageId = this.navigationManager.getCurrentPageId();
231
+ const currentViewId = this.navigationManager.getCurrentViewId();
232
+ if (currentPageId && currentPageId !== this.config.page.componentId) {
233
+ this.lastActivePageId = currentPageId;
234
+ this.lastActiveViewId = currentViewId;
235
+ stateManager.set("screensaver.lastActivePageId", currentPageId);
236
+ stateManager.set("screensaver.lastActiveViewId", currentViewId);
237
+ }
238
+ this.isScreensaverActive = true;
239
+ stateManager.set("screensaver.isActive", true);
240
+ try {
241
+ // Navigate to screensaver page
242
+ await this.navigationManager.navigateToPage(this.config.page.componentId, this.config.transitionConfig);
243
+ // Determine which view to show based on screensaverViewBehavior
244
+ const targetViewId = this.determineScreensaverView();
245
+ if (targetViewId) {
246
+ await this.navigationManager.navigateToView(targetViewId, { type: "snap" });
247
+ }
248
+ this.eventBus.emit("screensaver-activated", {
249
+ pageId: this.config.page.componentId,
250
+ viewId: targetViewId,
251
+ previousPageId: this.lastActivePageId,
252
+ previousViewId: this.lastActiveViewId,
253
+ });
254
+ }
255
+ catch (error) {
256
+ log.error("Failed to activate screensaver:", error);
257
+ this.isScreensaverActive = false;
258
+ stateManager.set("screensaver.isActive", false);
259
+ }
260
+ if (this.config.activateCallback)
261
+ this.config.activateCallback();
262
+ // Start periodic reboot check and check immediately
263
+ this.startRebootCheckInterval();
264
+ this.checkAndPerformReboot();
265
+ }
266
+ determineScreensaverView() {
267
+ if (!this.config)
268
+ return null;
269
+ switch (this.config.screensaverViewBehavior) {
270
+ case "return":
271
+ return this.lastScreensaverViewId || this.config.defaultViewId || null;
272
+ case "specific":
273
+ return this.config.specificViewId || null;
274
+ case "default":
275
+ default:
276
+ return this.config.defaultViewId || null;
277
+ }
278
+ }
279
+ async handleScreensaverExit() {
280
+ if (!this.config || !this.isScreensaverActive)
281
+ return;
282
+ log.trace(`Exiting screensaver with '${this.config.exitBehavior}' behavior`);
283
+ // Stop the reboot check interval
284
+ this.stopRebootCheckInterval();
285
+ if (this.config.deactivateCallback)
286
+ this.config.deactivateCallback();
287
+ this.isScreensaverActive = false;
288
+ stateManager.set("screensaver.isActive", false);
289
+ let targetPageId = null;
290
+ let targetViewId = null;
291
+ if (this.config.exitBehavior === "return") {
292
+ targetPageId = this.lastActivePageId;
293
+ targetViewId = this.lastActiveViewId;
294
+ }
295
+ else if (this.config.exitBehavior === "reset") {
296
+ targetPageId = this.config.startingPageId || null;
297
+ targetViewId = this.config.startingViewId || null;
298
+ }
299
+ if (targetPageId) {
300
+ try {
301
+ await this.navigationManager.navigateToPage(targetPageId, this.config.transitionConfig);
302
+ if (targetViewId) {
303
+ await this.navigationManager.navigateToView(targetViewId, { type: "snap" });
304
+ }
305
+ this.eventBus.emit("screensaver-deactivated", {
306
+ targetPageId,
307
+ targetViewId,
308
+ exitBehavior: this.config.exitBehavior,
309
+ });
310
+ // Reset timer for next cycle
311
+ this.resetActivityTimer();
312
+ }
313
+ catch (error) {
314
+ log.error("Failed to exit screensaver:", error);
315
+ // Reset state on error
316
+ this.isScreensaverActive = true;
317
+ stateManager.set("screensaver.isActive", true);
318
+ }
319
+ }
320
+ else {
321
+ log.warn("No target page available for screensaver exit");
322
+ this.resetActivityTimer();
323
+ }
324
+ }
325
+ async deactivateScreensaver() {
326
+ await this.handleScreensaverExit();
327
+ }
328
+ isActive() {
329
+ return this.isScreensaverActive;
330
+ }
331
+ getCurrentConfig() {
332
+ return this.config;
333
+ }
334
+ getLastActivePageId() {
335
+ return this.lastActivePageId;
336
+ }
337
+ getLastActiveViewId() {
338
+ return this.lastActiveViewId;
339
+ }
340
+ getLastScreensaverViewId() {
341
+ return this.lastScreensaverViewId;
342
+ }
343
+ // Manual control methods
344
+ forceActivate() {
345
+ this.clearActivityTimer();
346
+ this.activateScreensaver();
347
+ }
348
+ forceDeactivate() {
349
+ this.deactivateScreensaver();
350
+ }
351
+ resetTimer() {
352
+ if (!this.isScreensaverActive) {
353
+ this.resetActivityTimer();
354
+ }
355
+ }
356
+ cleanup() {
357
+ this.clearActivityTimer();
358
+ this.stopRebootCheckInterval();
359
+ // Remove all global event listeners
360
+ this.globalListeners.forEach(({ element, type, listener }) => {
361
+ element.removeEventListener(type, listener);
362
+ });
363
+ this.globalListeners.length = 0;
364
+ this.isScreensaverActive = false;
365
+ stateManager.set("screensaver.isActive", false);
366
+ }
367
+ destroy() {
368
+ this.cleanup();
369
+ this.config = null;
370
+ this.lastActivePageId = null;
371
+ this.lastActiveViewId = null;
372
+ this.lastScreensaverViewId = null;
373
+ log.trace("ScreensaverManager destroyed");
374
+ }
375
+ // Reboot timeout checking methods
376
+ hasRebootTimeoutElapsed() {
377
+ if (!this.config?.rebootTimeout)
378
+ return false;
379
+ const lastReboot = stateManager.get("lastReboot");
380
+ if (!lastReboot) {
381
+ // Initialize timestamp on first check
382
+ stateManager.set("lastReboot", Date.now());
383
+ return false;
384
+ }
385
+ const elapsedMinutes = (Date.now() - lastReboot) / (1000 * 60);
386
+ return elapsedMinutes >= this.config.rebootTimeout;
387
+ }
388
+ checkAndPerformReboot() {
389
+ if (!this.hasRebootTimeoutElapsed())
390
+ return;
391
+ log.trace("Reboot timeout elapsed, performing reboot");
392
+ // Call the reboot callback function
393
+ if (this.config?.rebootCallback) {
394
+ this.config.rebootCallback();
395
+ }
396
+ // Reset the timestamp after reboot is triggered
397
+ stateManager.set("lastReboot", Date.now());
398
+ }
399
+ startRebootCheckInterval() {
400
+ if (!this.config?.rebootTimeout)
401
+ return;
402
+ // Clear any existing interval
403
+ this.stopRebootCheckInterval();
404
+ // Check every 10 minutes (600000 ms)
405
+ this.rebootCheckInterval = window.setInterval(() => {
406
+ this.checkAndPerformReboot();
407
+ }, 600000);
408
+ log.trace("Reboot check interval started (10 minute intervals)");
409
+ }
410
+ stopRebootCheckInterval() {
411
+ if (this.rebootCheckInterval !== null) {
412
+ clearInterval(this.rebootCheckInterval);
413
+ this.rebootCheckInterval = null;
414
+ log.trace("Reboot check interval stopped");
415
+ }
416
+ }
417
+ }
@@ -0,0 +1,48 @@
1
+ import { EventOrchestrator } from "./eventBus";
2
+ import { View } from "./appBuilder";
3
+ import { NavigationManager, type TransitionConfig } from "./navigationManager";
4
+ export interface SettingsConfig {
5
+ view: View;
6
+ transitionConfig?: TransitionConfig;
7
+ exitBehavior?: "reset" | "return";
8
+ startingViewId?: string;
9
+ cornerTouchRadius?: number;
10
+ touchTimeout?: number;
11
+ debugMode?: boolean;
12
+ }
13
+ export declare class SettingsManager {
14
+ private eventBus;
15
+ private orchestrator;
16
+ private navigationManager;
17
+ private config;
18
+ private isSettingsActive;
19
+ private lastActiveViewId;
20
+ private touchSequenceState;
21
+ private lastEventTime;
22
+ private touchListeners;
23
+ private readonly DEFAULT_CORNER_RADIUS;
24
+ private readonly DEFAULT_TOUCH_TIMEOUT;
25
+ private readonly EVENT_DEBOUNCE_MS;
26
+ constructor(orchestrator: EventOrchestrator, navigationManager: NavigationManager);
27
+ private initializeGlobalState;
28
+ private setupEventListeners;
29
+ registerSettings(config: SettingsConfig): void;
30
+ private validateConfig;
31
+ private setupCornerTouchListeners;
32
+ private handleTouchAttempt;
33
+ private detectCornerTouch;
34
+ private getExpectedCorner;
35
+ private resetTouchSequence;
36
+ private activateSettings;
37
+ private handleSettingsExit;
38
+ private deactivateSettings;
39
+ isActive(): boolean;
40
+ getCurrentConfig(): SettingsConfig | null;
41
+ getLastActiveViewId(): string | null;
42
+ forceActivate(): void;
43
+ forceDeactivate(): void;
44
+ resetSequence(): void;
45
+ private cleanup;
46
+ destroy(): void;
47
+ }
48
+ //# sourceMappingURL=settingsManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settingsManager.d.ts","sourceRoot":"","sources":["../../src/settingsManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM/E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAOD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,kBAAkB,CAGxB;IACF,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,cAAc,CAId;IAGR,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAO;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAQ;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAM;gBAE5B,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB;IASjF,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,mBAAmB;IA2BpB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAkCrD,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,yBAAyB;IAwBjC,OAAO,CAAC,kBAAkB;IA+D1B,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,kBAAkB;YAQZ,gBAAgB;YA6BhB,kBAAkB;YAmClB,kBAAkB;IAIzB,QAAQ,IAAI,OAAO;IAInB,gBAAgB,IAAI,cAAc,GAAG,IAAI;IAIzC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAKpC,aAAa,IAAI,IAAI;IAKrB,eAAe,IAAI,IAAI;IAIvB,aAAa,IAAI,IAAI;IAI5B,OAAO,CAAC,OAAO;IAYR,OAAO,IAAI,IAAI;CAMvB"}