smodusermc commited on
Commit
240b2d4
·
verified ·
1 Parent(s): 93909ea

Update static/script.js

Browse files
Files changed (1) hide show
  1. static/script.js +43 -24
static/script.js CHANGED
@@ -8,11 +8,30 @@
8
 
9
  const APP_VERSION = '2.0.0';
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  // ============================================================
12
  // State
13
  // ============================================================
14
  const State = {
15
- token: localStorage.getItem('token'),
16
  user: null, // {id, username, display_name, avatar_path}
17
  ws: null,
18
  wsState: 'disconnected',
@@ -38,18 +57,18 @@
38
  latestUnseen: null,
39
  unreadTotal: 0,
40
 
41
- theme: localStorage.getItem('theme') || 'light',
42
  customColors: {
43
- self: localStorage.getItem('custom-self') || '#2563EB',
44
- other: localStorage.getItem('custom-other') || '#F3F4F6',
45
- text: localStorage.getItem('custom-text') || '#111827'
46
  },
47
  prefs: {
48
- autoScroll: localStorage.getItem('pref-autoscroll') !== 'false',
49
- showScrollBtn: localStorage.getItem('pref-scrollbtn') !== 'false',
50
- showLatestBar: localStorage.getItem('pref-latestbar') !== 'false',
51
- sound: localStorage.getItem('pref-sound') !== 'false',
52
- enterSend: localStorage.getItem('pref-entersend') !== 'false'
53
  }
54
  };
55
 
@@ -311,7 +330,7 @@
311
  function applyTheme(theme) {
312
  document.documentElement.setAttribute('data-theme', theme);
313
  State.theme = theme;
314
- localStorage.setItem('theme', theme);
315
  if (theme === 'custom') {
316
  const s = State.customColors.self, o = State.customColors.other, t = State.customColors.text;
317
  document.documentElement.style.setProperty('--bubble-self', s);
@@ -342,11 +361,11 @@
342
  }
343
 
344
  function savePrefs() {
345
- localStorage.setItem('pref-autoscroll', State.prefs.autoScroll);
346
- localStorage.setItem('pref-scrollbtn', State.prefs.showScrollBtn);
347
- localStorage.setItem('pref-latestbar', State.prefs.showLatestBar);
348
- localStorage.setItem('pref-sound', State.prefs.sound);
349
- localStorage.setItem('pref-entersend', State.prefs.enterSend);
350
  }
351
 
352
  [['toggle-autoscroll', 'autoScroll'], ['toggle-scroll-btn', 'showScrollBtn'],
@@ -455,7 +474,7 @@
455
  function handleAuthSuccess(data) {
456
  State.token = data.token;
457
  State.user = data.user;
458
- localStorage.setItem('token', State.token);
459
  showChat();
460
  connectWebSocket();
461
  }
@@ -2364,9 +2383,9 @@
2364
  State.customColors.self = DOM.customSelfColor.value;
2365
  State.customColors.other = DOM.customOtherColor.value;
2366
  State.customColors.text = DOM.customTextColor.value;
2367
- localStorage.setItem('custom-self', State.customColors.self);
2368
- localStorage.setItem('custom-other', State.customColors.other);
2369
- localStorage.setItem('custom-text', State.customColors.text);
2370
  }
2371
  applyTheme(selectedTheme);
2372
  closeModal(DOM.settingsModal);
@@ -2455,7 +2474,7 @@
2455
  return;
2456
  }
2457
  } catch (e) { /* fall through to auth screen */ }
2458
- localStorage.removeItem('token');
2459
  State.token = null;
2460
  }
2461
  showAuth();
@@ -2488,7 +2507,7 @@
2488
 
2489
  function forceLogout() {
2490
  showToast('Session expired - please sign in again', 'warning');
2491
- localStorage.removeItem('token');
2492
  State.token = null;
2493
  State.wsState = 'disconnected';
2494
  if (State.ws) { try { State.ws.close(); } catch (e) { /* noop */ } }
@@ -2544,7 +2563,7 @@
2544
  }
2545
  if (State.ws) { try { State.ws.close(); } catch (e) { /* noop */ } }
2546
  State.ws = null;
2547
- localStorage.removeItem('token');
2548
  State.token = null;
2549
  resetAllState();
2550
  showAuth();
@@ -2582,4 +2601,4 @@
2582
  // Go
2583
  // ============================================================
2584
  init();
2585
- })();
 
8
 
9
  const APP_VERSION = '2.0.0';
10
 
11
+ // ============================================================
12
+ // Safe storage
13
+ // Storage access can throw in sandboxed iframes / private mode /
14
+ // when cookies are blocked - that must never kill the whole app.
15
+ // Falls back to an in-memory store for the lifetime of the tab.
16
+ // ============================================================
17
+ const memStore = new Map();
18
+ const store = {
19
+ get(k) {
20
+ try { return localStorage.getItem(k); } catch (e) { return memStore.has(k) ? memStore.get(k) : null; }
21
+ },
22
+ set(k, v) {
23
+ try { localStorage.setItem(k, v); } catch (e) { memStore.set(k, v); }
24
+ },
25
+ remove(k) {
26
+ try { localStorage.removeItem(k); } catch (e) { memStore.delete(k); }
27
+ }
28
+ };
29
+
30
  // ============================================================
31
  // State
32
  // ============================================================
33
  const State = {
34
+ token: store.get('token'),
35
  user: null, // {id, username, display_name, avatar_path}
36
  ws: null,
37
  wsState: 'disconnected',
 
57
  latestUnseen: null,
58
  unreadTotal: 0,
59
 
60
+ theme: store.get('theme') || 'light',
61
  customColors: {
62
+ self: store.get('custom-self') || '#2563EB',
63
+ other: store.get('custom-other') || '#F3F4F6',
64
+ text: store.get('custom-text') || '#111827'
65
  },
66
  prefs: {
67
+ autoScroll: store.get('pref-autoscroll') !== 'false',
68
+ showScrollBtn: store.get('pref-scrollbtn') !== 'false',
69
+ showLatestBar: store.get('pref-latestbar') !== 'false',
70
+ sound: store.get('pref-sound') !== 'false',
71
+ enterSend: store.get('pref-entersend') !== 'false'
72
  }
73
  };
74
 
 
330
  function applyTheme(theme) {
331
  document.documentElement.setAttribute('data-theme', theme);
332
  State.theme = theme;
333
+ store.set('theme', theme);
334
  if (theme === 'custom') {
335
  const s = State.customColors.self, o = State.customColors.other, t = State.customColors.text;
336
  document.documentElement.style.setProperty('--bubble-self', s);
 
361
  }
362
 
363
  function savePrefs() {
364
+ store.set('pref-autoscroll', State.prefs.autoScroll);
365
+ store.set('pref-scrollbtn', State.prefs.showScrollBtn);
366
+ store.set('pref-latestbar', State.prefs.showLatestBar);
367
+ store.set('pref-sound', State.prefs.sound);
368
+ store.set('pref-entersend', State.prefs.enterSend);
369
  }
370
 
371
  [['toggle-autoscroll', 'autoScroll'], ['toggle-scroll-btn', 'showScrollBtn'],
 
474
  function handleAuthSuccess(data) {
475
  State.token = data.token;
476
  State.user = data.user;
477
+ store.set('token', State.token);
478
  showChat();
479
  connectWebSocket();
480
  }
 
2383
  State.customColors.self = DOM.customSelfColor.value;
2384
  State.customColors.other = DOM.customOtherColor.value;
2385
  State.customColors.text = DOM.customTextColor.value;
2386
+ store.set('custom-self', State.customColors.self);
2387
+ store.set('custom-other', State.customColors.other);
2388
+ store.set('custom-text', State.customColors.text);
2389
  }
2390
  applyTheme(selectedTheme);
2391
  closeModal(DOM.settingsModal);
 
2474
  return;
2475
  }
2476
  } catch (e) { /* fall through to auth screen */ }
2477
+ store.remove('token');
2478
  State.token = null;
2479
  }
2480
  showAuth();
 
2507
 
2508
  function forceLogout() {
2509
  showToast('Session expired - please sign in again', 'warning');
2510
+ store.remove('token');
2511
  State.token = null;
2512
  State.wsState = 'disconnected';
2513
  if (State.ws) { try { State.ws.close(); } catch (e) { /* noop */ } }
 
2563
  }
2564
  if (State.ws) { try { State.ws.close(); } catch (e) { /* noop */ } }
2565
  State.ws = null;
2566
+ store.remove('token');
2567
  State.token = null;
2568
  resetAllState();
2569
  showAuth();
 
2601
  // Go
2602
  // ============================================================
2603
  init();
2604
+ })();