4sp-dv-latest 1.0.5 → 1.0.7
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.
- package/4simpleproblems_v5_latest.html +141 -258
- package/package.json +1 -1
|
@@ -6,71 +6,16 @@
|
|
|
6
6
|
<title>4SP - VERSION 5 CLIENT</title>
|
|
7
7
|
<link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo.png">
|
|
8
8
|
|
|
9
|
-
<base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.0.
|
|
9
|
+
<base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.0.44/logged-in/">
|
|
10
10
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" rel="stylesheet">
|
|
12
12
|
|
|
13
13
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
|
14
|
-
<style>
|
|
15
|
-
/* --- PRELOADER --- */
|
|
16
|
-
#app-preloader {
|
|
17
|
-
position: fixed;
|
|
18
|
-
inset: 0;
|
|
19
|
-
background-color: #000000;
|
|
20
|
-
z-index: 99999;
|
|
21
|
-
display: flex;
|
|
22
|
-
flex-direction: column;
|
|
23
|
-
align-items: flex-end;
|
|
24
|
-
justify-content: flex-end;
|
|
25
|
-
padding: 3rem;
|
|
26
|
-
transition: opacity 0.5s ease-out, visibility 0.5s;
|
|
27
|
-
}
|
|
28
|
-
#app-preloader.fade-out {
|
|
29
|
-
opacity: 0;
|
|
30
|
-
visibility: hidden;
|
|
31
|
-
}
|
|
32
14
|
|
|
33
|
-
.
|
|
34
|
-
position: absolute;
|
|
35
|
-
top: 1.5rem;
|
|
36
|
-
right: 1.5rem;
|
|
37
|
-
height: 3rem;
|
|
38
|
-
width: auto;
|
|
39
|
-
opacity: 0.5; /* Initial opacity per universal style, not darkened */
|
|
40
|
-
}
|
|
15
|
+
<script src="https://cdn.jsdelivr.net/npm/fireworks-js@2.x/dist/index.umd.js"></script>
|
|
41
16
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
flex-direction: column;
|
|
45
|
-
align-items: flex-end;
|
|
46
|
-
gap: 0.5rem;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.preloader-title {
|
|
50
|
-
color: #fff;
|
|
51
|
-
font-size: 1.875rem; /* 3xl */
|
|
52
|
-
font-weight: 300;
|
|
53
|
-
font-style: italic;
|
|
54
|
-
font-family: 'Geist', sans-serif;
|
|
55
|
-
white-space: nowrap;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.preloader-bar-container {
|
|
59
|
-
width: 16rem; /* 64 */
|
|
60
|
-
height: 0.25rem; /* 1 */
|
|
61
|
-
background-color: #333;
|
|
62
|
-
border-radius: 9999px;
|
|
63
|
-
overflow: hidden;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.preloader-bar {
|
|
67
|
-
height: 100%;
|
|
68
|
-
background-color: #fff;
|
|
69
|
-
width: 0%;
|
|
70
|
-
transition: width 0.5s ease-out;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
body {
|
|
17
|
+
<style>
|
|
18
|
+
body {
|
|
74
19
|
background-color: #040404;
|
|
75
20
|
color: #c0c0c0;
|
|
76
21
|
font-family: 'Geist', sans-serif;
|
|
@@ -103,6 +48,27 @@
|
|
|
103
48
|
z-index: 60;
|
|
104
49
|
transition: background-color 0.3s ease, border-color 0.3s ease;
|
|
105
50
|
position: relative;
|
|
51
|
+
overflow: visible;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* --- FIREWORKS CONTAINER --- */
|
|
55
|
+
#fireworks-container {
|
|
56
|
+
position: absolute;
|
|
57
|
+
top: 0;
|
|
58
|
+
left: 0;
|
|
59
|
+
width: 100%;
|
|
60
|
+
height: 100%;
|
|
61
|
+
pointer-events: none; /* Let clicks pass through */
|
|
62
|
+
z-index: 1; /* Sit above background */
|
|
63
|
+
opacity: 0;
|
|
64
|
+
transition: opacity 0.5s ease;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Ensure navbar content sits ABOVE the fireworks */
|
|
69
|
+
#navbar-container > *:not(#fireworks-container) {
|
|
70
|
+
position: relative;
|
|
71
|
+
z-index: 10;
|
|
106
72
|
}
|
|
107
73
|
|
|
108
74
|
/* --- FIXED OVERLAY LOGIC --- */
|
|
@@ -229,15 +195,15 @@
|
|
|
229
195
|
z-index: 50;
|
|
230
196
|
}
|
|
231
197
|
|
|
232
|
-
/* --- DISABLE ANIMATIONS FOR AUTH BTN --- */
|
|
233
198
|
#auth-btn, #auth-btn:hover, #auth-btn:active {
|
|
234
199
|
transform: none !important;
|
|
235
200
|
transition: none !important;
|
|
236
201
|
background-color: transparent !important;
|
|
237
|
-
z-index:
|
|
202
|
+
z-index: 65 !important;
|
|
203
|
+
cursor: pointer !important;
|
|
238
204
|
}
|
|
239
205
|
|
|
240
|
-
/* Auth Menu & Settings */
|
|
206
|
+
/* --- Auth Menu & Settings (Updated for dynamic theming) --- */
|
|
241
207
|
.auth-menu {
|
|
242
208
|
position: absolute;
|
|
243
209
|
right: 0;
|
|
@@ -250,7 +216,7 @@
|
|
|
250
216
|
display: none;
|
|
251
217
|
flex-direction: column;
|
|
252
218
|
gap: 0.5rem;
|
|
253
|
-
z-index:
|
|
219
|
+
z-index: 70;
|
|
254
220
|
box-shadow: 0 10px 30px rgba(0,0,0,0.6);
|
|
255
221
|
transform-origin: top right;
|
|
256
222
|
}
|
|
@@ -271,9 +237,10 @@
|
|
|
271
237
|
align-items: center;
|
|
272
238
|
gap: 0.75rem;
|
|
273
239
|
padding: 0.75rem 1rem;
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
240
|
+
/* UPDATED: Uses variables for dynamic theme support */
|
|
241
|
+
color: var(--menu-item-text, #d1d5db);
|
|
242
|
+
background: var(--menu-item-bg, #0a0a0a);
|
|
243
|
+
border: 1px solid var(--menu-item-border, #333);
|
|
277
244
|
border-radius: 1rem;
|
|
278
245
|
text-decoration: none;
|
|
279
246
|
font-size: 0.9rem;
|
|
@@ -283,9 +250,10 @@
|
|
|
283
250
|
}
|
|
284
251
|
|
|
285
252
|
.auth-menu-item:hover {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
color: #fff;
|
|
253
|
+
/* UPDATED: Uses variables for dynamic theme support */
|
|
254
|
+
background-color: var(--menu-item-hover-bg, #000);
|
|
255
|
+
border-color: var(--menu-item-hover-border, #fff);
|
|
256
|
+
color: var(--menu-item-hover-text, #fff);
|
|
289
257
|
transform: translateY(-2px) scale(1.02);
|
|
290
258
|
box-shadow: 0 5px 15px rgba(255,255,255,0.05);
|
|
291
259
|
}
|
|
@@ -294,21 +262,6 @@
|
|
|
294
262
|
transform: translateY(0) scale(0.98);
|
|
295
263
|
}
|
|
296
264
|
|
|
297
|
-
.auth-menu-item i, .nav-tab i, .settings-tab i {
|
|
298
|
-
display: inline-flex;
|
|
299
|
-
align-items: center;
|
|
300
|
-
justify-content: center;
|
|
301
|
-
width: 1.1em;
|
|
302
|
-
height: 1.1em;
|
|
303
|
-
line-height: 1;
|
|
304
|
-
position: relative;
|
|
305
|
-
top: 1px;
|
|
306
|
-
flex-shrink: 0;
|
|
307
|
-
margin: 0;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
265
|
.auth-header {
|
|
313
266
|
padding: 0.5rem 1rem;
|
|
314
267
|
border-bottom: 1px solid var(--menu-divider, #333);
|
|
@@ -378,13 +331,13 @@
|
|
|
378
331
|
}
|
|
379
332
|
|
|
380
333
|
.settings-box {
|
|
381
|
-
border: 1px solid #333; border-radius:
|
|
334
|
+
border: 1px solid #333; border-radius: 1rem;
|
|
382
335
|
background-color: #000000; padding: 1.5rem; margin-bottom: 1.5rem;
|
|
383
336
|
}
|
|
384
337
|
|
|
385
338
|
.input-text-style, .input-select-style {
|
|
386
339
|
width: 100%; padding: 0.75rem; border: 1px solid #252525;
|
|
387
|
-
background-color: #111111; border-radius:
|
|
340
|
+
background-color: #111111; border-radius: 0.5rem; color: #c0c0c0; transition: all 0.2s;
|
|
388
341
|
}
|
|
389
342
|
.input-text-style:focus, .input-select-style:focus {
|
|
390
343
|
border-color: #505050; outline: none; box-shadow: 0 0 0 2px rgba(80, 80, 80, 0.5);
|
|
@@ -392,24 +345,13 @@
|
|
|
392
345
|
|
|
393
346
|
.input-key-style {
|
|
394
347
|
width: 4rem; padding: 0.75rem; border: 1px solid #252525;
|
|
395
|
-
background-color: #111111; border-radius:
|
|
348
|
+
background-color: #111111; border-radius: 0.5rem; color: #c0c0c0;
|
|
396
349
|
transition: all 0.2s; font-size: 1.1rem; text-align: center;
|
|
397
350
|
font-weight: 500; text-transform: uppercase; caret-color: transparent;
|
|
398
351
|
}
|
|
399
352
|
.input-key-style:focus {
|
|
400
353
|
border-color: #505050; outline: none; box-shadow: 0 0 0 2px rgba(80, 80, 80, 0.5);
|
|
401
354
|
}
|
|
402
|
-
|
|
403
|
-
/* Preference Toggles */
|
|
404
|
-
.icon-btn.off {
|
|
405
|
-
border-color: #ef4444;
|
|
406
|
-
color: #ef4444;
|
|
407
|
-
background-color: rgba(239, 68, 68, 0.05);
|
|
408
|
-
}
|
|
409
|
-
.icon-btn.off:hover {
|
|
410
|
-
background-color: rgba(239, 68, 68, 0.1);
|
|
411
|
-
border-color: #f87171;
|
|
412
|
-
}
|
|
413
355
|
.input-key-style::placeholder { font-size: 1rem; text-transform: none; }
|
|
414
356
|
|
|
415
357
|
.general-message-area { min-height: 20px; margin-top: 1rem; font-weight: 400; }
|
|
@@ -464,21 +406,8 @@
|
|
|
464
406
|
}
|
|
465
407
|
.shake-anim { animation: shake 0.4s cubic-bezier(.36,.07,.19,.97) both; }
|
|
466
408
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
body.no-animations *:hover,
|
|
470
|
-
body.no-animations *:active,
|
|
471
|
-
body.no-animations *:focus {
|
|
472
|
-
transition: none !important;
|
|
473
|
-
animation: none !important;
|
|
474
|
-
transform: none !important;
|
|
475
|
-
box-shadow: none !important;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
body.no-animations .auth-menu-item .fa-gear,
|
|
479
|
-
body.no-animations .nav-tab .fa-gear {
|
|
480
|
-
transition: none !important;
|
|
481
|
-
transform: none !important;
|
|
409
|
+
body.no-animations * {
|
|
410
|
+
transition: none !important; animation: none !important; transform: none !important;
|
|
482
411
|
}
|
|
483
412
|
|
|
484
413
|
/* Bubbly Spring Transition */
|
|
@@ -615,17 +544,6 @@
|
|
|
615
544
|
</style>
|
|
616
545
|
</head>
|
|
617
546
|
<body>
|
|
618
|
-
<!-- PRELOADER -->
|
|
619
|
-
<div id="app-preloader">
|
|
620
|
-
<img src="https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png" class="preloader-logo" alt="Logo" onerror="this.style.display='none'">
|
|
621
|
-
<div class="preloader-content">
|
|
622
|
-
<h2 class="preloader-title">4simpleproblems Version 5 Client</h2>
|
|
623
|
-
<div class="preloader-bar-container">
|
|
624
|
-
<div id="preloader-bar" class="preloader-bar"></div>
|
|
625
|
-
</div>
|
|
626
|
-
</div>
|
|
627
|
-
</div>
|
|
628
|
-
|
|
629
547
|
<div id="lock-screen" class="w-full h-full flex flex-col items-center justify-center p-4">
|
|
630
548
|
<div class="max-w-5xl w-full bg-[#040404] flex flex-col md:flex-row border border-[#252525] rounded-3xl overflow-hidden shadow-2xl">
|
|
631
549
|
<div class="flex-1 p-8 flex flex-col justify-center items-center border-b md:border-b-0 md:border-r border-[#252525]">
|
|
@@ -656,6 +574,8 @@
|
|
|
656
574
|
</div>
|
|
657
575
|
|
|
658
576
|
<div id="navbar-container">
|
|
577
|
+
<div id="fireworks-container"></div>
|
|
578
|
+
|
|
659
579
|
<img src="https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png" id="navbar-logo" class="navbar-logo" alt="Logo">
|
|
660
580
|
|
|
661
581
|
<div class="tab-wrapper">
|
|
@@ -712,29 +632,13 @@
|
|
|
712
632
|
<h3 class="text-3xl font-bold text-white mb-6">General Settings</h3>
|
|
713
633
|
|
|
714
634
|
<div class="settings-box">
|
|
715
|
-
<h3 class="text-xl font-bold text-white mb-2">Account
|
|
716
|
-
|
|
635
|
+
<h3 class="text-xl font-bold text-white mb-2">Account Username</h3>
|
|
717
636
|
<label class="block text-gray-400 text-sm mb-2 font-light">New Username</label>
|
|
718
|
-
<div class="flex gap-2
|
|
637
|
+
<div class="flex gap-2">
|
|
719
638
|
<input type="text" id="settings-username-input" class="input-text-style" placeholder="Enter username">
|
|
720
639
|
<button id="save-username-btn" class="btn-toolbar-style btn-primary-override">Save</button>
|
|
721
640
|
</div>
|
|
722
641
|
<p id="username-msg" class="general-message-area text-sm mt-2"></p>
|
|
723
|
-
|
|
724
|
-
<div class="flex gap-8 items-center pt-4 border-t border-[#1a1a1a]">
|
|
725
|
-
<div class="flex flex-col items-center gap-2">
|
|
726
|
-
<button id="toggle-animations-btn" class="icon-btn" title="Toggle Navbar Animations">
|
|
727
|
-
<i class="fa-solid fa-wand-magic-sparkles"></i>
|
|
728
|
-
</button>
|
|
729
|
-
<span class="text-xs text-gray-500">Animations</span>
|
|
730
|
-
</div>
|
|
731
|
-
<div class="flex flex-col items-center gap-2">
|
|
732
|
-
<button id="toggle-sounds-btn" class="icon-btn" title="Toggle UI Sounds">
|
|
733
|
-
<i class="fa-solid fa-volume-high"></i>
|
|
734
|
-
</button>
|
|
735
|
-
<span class="text-xs text-gray-500">Sounds</span>
|
|
736
|
-
</div>
|
|
737
|
-
</div>
|
|
738
642
|
</div>
|
|
739
643
|
|
|
740
644
|
<h3 class="text-xl font-bold text-white mb-2 mt-6">Organization</h3>
|
|
@@ -787,8 +691,7 @@
|
|
|
787
691
|
|
|
788
692
|
<label class="block text-gray-400 text-xs mb-2 font-light">Background Color</label>
|
|
789
693
|
<div class="flex flex-wrap gap-2 mb-6" id="pfp-color-grid">
|
|
790
|
-
|
|
791
|
-
</div>
|
|
694
|
+
</div>
|
|
792
695
|
|
|
793
696
|
<button id="save-letter-pfp-btn" class="btn-toolbar-style btn-primary-override w-full justify-center">Set Letter Avatar</button>
|
|
794
697
|
</div>
|
|
@@ -809,8 +712,7 @@
|
|
|
809
712
|
|
|
810
713
|
<h3 class="text-xl font-bold text-white mb-2">Navigation Bar Theme</h3>
|
|
811
714
|
<div class="settings-box p-4">
|
|
812
|
-
<div id="theme-picker-container">
|
|
813
|
-
</div>
|
|
715
|
+
<div id="theme-picker-container"></div>
|
|
814
716
|
</div>
|
|
815
717
|
</div>
|
|
816
718
|
|
|
@@ -949,7 +851,7 @@
|
|
|
949
851
|
const displayUsername = document.getElementById('display-username');
|
|
950
852
|
const displayEmail = document.getElementById('display-email');
|
|
951
853
|
|
|
952
|
-
const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.0.
|
|
854
|
+
const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.0.44/logged-in/';
|
|
953
855
|
|
|
954
856
|
// Preload Logos
|
|
955
857
|
const preloadImgs = [
|
|
@@ -963,8 +865,10 @@
|
|
|
963
865
|
const USER_DATA_KEY = 'local_user_data';
|
|
964
866
|
const LAST_PAGE_KEY = 'local_last_page';
|
|
965
867
|
const OWNER_EMAIL = "4simpleproblems@gmail.com"; // For admin checks
|
|
868
|
+
const FIREWORKS_SETTINGS_KEY = 'fireworks_settings';
|
|
966
869
|
|
|
967
|
-
|
|
870
|
+
// RENAMED TO AVOID CONFLICTS
|
|
871
|
+
const CLIENT_PAGE_DATA = {
|
|
968
872
|
"dashboard": { "name": "Dashboard", "icon": "fa-solid fa-house-user", "url": "dashboard.html" },
|
|
969
873
|
"soundboard": { "name": "Soundboard", "icon": "fa-solid fa-volume-up", "url": "soundboard.html" },
|
|
970
874
|
"notes": { "name": "Notes", "icon": "fa-solid fa-sticky-note", "url": "notes.html" },
|
|
@@ -980,6 +884,27 @@
|
|
|
980
884
|
let currentUser = null;
|
|
981
885
|
let userDataUnsubscribe = null;
|
|
982
886
|
|
|
887
|
+
// --- FIREWORKS ENGINE INITIALIZATION ---
|
|
888
|
+
const fwContainer = document.getElementById('fireworks-container');
|
|
889
|
+
|
|
890
|
+
// HARDCODED SETTINGS AS REQUESTED
|
|
891
|
+
const fireworks = new Fireworks.default(fwContainer, {
|
|
892
|
+
autoresize: true,
|
|
893
|
+
opacity: 1.0, // Hardcoded
|
|
894
|
+
acceleration: 1.05,
|
|
895
|
+
friction: 0.97,
|
|
896
|
+
gravity: 1.5,
|
|
897
|
+
particles: 50, // Hardcoded
|
|
898
|
+
traceLength: 3,
|
|
899
|
+
traceSpeed: 10,
|
|
900
|
+
explosion: 5,
|
|
901
|
+
intensity: 5, // Hardcoded
|
|
902
|
+
flickering: 50,
|
|
903
|
+
lineStyle: 'round',
|
|
904
|
+
rocketsPoint: { min: 50, max: 50 }
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
|
|
983
908
|
// --- ADMIN KEYBINDS LOGIC (Updated to Match admin_keybinds.js exactly) ---
|
|
984
909
|
function initAdminKeybinds(db, auth, user) {
|
|
985
910
|
console.log("[Admin Keybinds] Initializing for", user.uid);
|
|
@@ -1240,7 +1165,7 @@
|
|
|
1240
1165
|
|
|
1241
1166
|
let currentPath = activePageUrl.replace(BASE_URL, '');
|
|
1242
1167
|
|
|
1243
|
-
Object.entries(
|
|
1168
|
+
Object.entries(CLIENT_PAGE_DATA).forEach(([key, page]) => {
|
|
1244
1169
|
const isAuth = page.url === currentPath;
|
|
1245
1170
|
const tab = document.createElement('a');
|
|
1246
1171
|
tab.className = `nav-tab ${isAuth ? 'active' : ''}`;
|
|
@@ -1316,7 +1241,7 @@
|
|
|
1316
1241
|
}, 50);
|
|
1317
1242
|
}
|
|
1318
1243
|
|
|
1319
|
-
// Auth Menu
|
|
1244
|
+
// Auth Menu (Wait for DOMContentLoaded equivalent in module)
|
|
1320
1245
|
if (authBtn) {
|
|
1321
1246
|
authBtn.addEventListener('click', (e) => {
|
|
1322
1247
|
e.stopPropagation();
|
|
@@ -1439,9 +1364,6 @@
|
|
|
1439
1364
|
}
|
|
1440
1365
|
|
|
1441
1366
|
authBtn.innerHTML = pfpHtml;
|
|
1442
|
-
authBtn.style.padding = '0'; // Remove padding to let avatar fill
|
|
1443
|
-
authBtn.style.overflow = 'hidden'; // Ensure roundness
|
|
1444
|
-
authBtn.style.border = '1px solid #4b5563'; // Maintain border
|
|
1445
1367
|
}
|
|
1446
1368
|
|
|
1447
1369
|
// --- Auto-Login Logic ---
|
|
@@ -1452,19 +1374,9 @@
|
|
|
1452
1374
|
unlockBtn.classList.add('hidden');
|
|
1453
1375
|
codeInput.classList.add('hidden');
|
|
1454
1376
|
|
|
1455
|
-
// Timeout Race to prevent infinite "Verifying..."
|
|
1456
|
-
const timeoutPromise = new Promise((_, reject) =>
|
|
1457
|
-
setTimeout(() => reject(new Error("Verification timed out.")), 10000)
|
|
1458
|
-
);
|
|
1459
|
-
|
|
1460
1377
|
try {
|
|
1461
1378
|
const docRef = doc(db, "access_codes", savedCode);
|
|
1462
|
-
|
|
1463
|
-
// Race the Firestore connection
|
|
1464
|
-
const docSnap = await Promise.race([
|
|
1465
|
-
getDoc(docRef),
|
|
1466
|
-
timeoutPromise
|
|
1467
|
-
]);
|
|
1379
|
+
const docSnap = await getDoc(docRef);
|
|
1468
1380
|
|
|
1469
1381
|
if (docSnap.exists() && docSnap.data().active) {
|
|
1470
1382
|
const codeData = docSnap.data();
|
|
@@ -1480,12 +1392,9 @@
|
|
|
1480
1392
|
currentUser = userData;
|
|
1481
1393
|
}
|
|
1482
1394
|
|
|
1483
|
-
// Always fetch fresh to re-verify admin status
|
|
1395
|
+
// Always fetch fresh to re-verify admin status
|
|
1484
1396
|
if (codeData.ownerUid) {
|
|
1485
|
-
await
|
|
1486
|
-
fetchUserData(codeData.ownerUid),
|
|
1487
|
-
timeoutPromise
|
|
1488
|
-
]);
|
|
1397
|
+
await fetchUserData(codeData.ownerUid);
|
|
1489
1398
|
}
|
|
1490
1399
|
|
|
1491
1400
|
launchApp();
|
|
@@ -1496,7 +1405,7 @@
|
|
|
1496
1405
|
}
|
|
1497
1406
|
} catch(e) {
|
|
1498
1407
|
console.error("Auto-login error:", e);
|
|
1499
|
-
resetLockScreen("Connection
|
|
1408
|
+
resetLockScreen("Connection failed. Retrying...");
|
|
1500
1409
|
}
|
|
1501
1410
|
}
|
|
1502
1411
|
}
|
|
@@ -1577,7 +1486,7 @@
|
|
|
1577
1486
|
|
|
1578
1487
|
// Priority: Last Page > > Default
|
|
1579
1488
|
if (lastPage) {
|
|
1580
|
-
const isValid = Object.values(
|
|
1489
|
+
const isValid = Object.values(CLIENT_PAGE_DATA).some(p => p.url === lastPage);
|
|
1581
1490
|
if (isValid) startPage = lastPage;
|
|
1582
1491
|
}
|
|
1583
1492
|
|
|
@@ -1633,7 +1542,7 @@
|
|
|
1633
1542
|
if (loader && loaderTitle && loaderBar) {
|
|
1634
1543
|
// Determine Title
|
|
1635
1544
|
let pageTitle = "Loading...";
|
|
1636
|
-
const pageEntry = Object.values(
|
|
1545
|
+
const pageEntry = Object.values(CLIENT_PAGE_DATA).find(p => p.url === cleanPageName || p.url.includes(lookupName));
|
|
1637
1546
|
if (pageEntry) pageTitle = pageEntry.name;
|
|
1638
1547
|
|
|
1639
1548
|
loaderTitle.textContent = pageTitle;
|
|
@@ -2238,8 +2147,42 @@
|
|
|
2238
2147
|
if (!res.ok) return;
|
|
2239
2148
|
let themes = await res.json();
|
|
2240
2149
|
|
|
2150
|
+
// --- INJECT CUSTOM "THE NEW YEAR" THEME & REMOVE ROYAL ---
|
|
2151
|
+
// 1. Filter out Royal
|
|
2152
|
+
themes = themes.filter(t => t.name !== 'Royal');
|
|
2153
|
+
|
|
2154
|
+
// 2. Inject The New Year (Deep Blue)
|
|
2155
|
+
const newYearTheme = {
|
|
2156
|
+
"name": "The New Year",
|
|
2157
|
+
"navbar-bg": "#020617", // Very deep blue (Slate-950)
|
|
2158
|
+
"navbar-border": "#1e293b",
|
|
2159
|
+
"navbar-text": "#e2e8f0",
|
|
2160
|
+
"tab-text": "#94a3b8",
|
|
2161
|
+
"tab-hover-text": "#ffffff",
|
|
2162
|
+
"tab-hover-bg": "rgba(255, 255, 255, 0.1)",
|
|
2163
|
+
"tab-active-text": "#fcd34d", // Gold accent for festive feel
|
|
2164
|
+
"tab-active-bg": "rgba(252, 211, 77, 0.15)",
|
|
2165
|
+
"tab-active-border": "#fcd34d",
|
|
2166
|
+
"accent-color": "#fcd34d",
|
|
2167
|
+
"logo-src": "https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png",
|
|
2168
|
+
|
|
2169
|
+
// --- UPDATED: AUTH MENU SPECIFIC THEME COLORS ---
|
|
2170
|
+
"menu-bg": "#020617",
|
|
2171
|
+
"menu-border": "#fcd34d", // Gold border for menu
|
|
2172
|
+
"menu-divider": "#1e293b",
|
|
2173
|
+
"menu-username-text": "#fcd34d", // Gold Username
|
|
2174
|
+
"menu-email-text": "#94a3b8",
|
|
2175
|
+
"menu-item-bg": "#0f172a", // Dark Slate for items
|
|
2176
|
+
"menu-item-text": "#cbd5e1",
|
|
2177
|
+
"menu-item-hover-bg": "rgba(252, 211, 77, 0.1)", // Gold tint on hover
|
|
2178
|
+
"menu-item-hover-text": "#fcd34d"
|
|
2179
|
+
};
|
|
2180
|
+
|
|
2181
|
+
themes.push(newYearTheme);
|
|
2182
|
+
// --------------------------------------------------------
|
|
2183
|
+
|
|
2241
2184
|
// --- Sorting Logic from settings.js ---
|
|
2242
|
-
const orderedThemeNames = ['Dark', 'Light', 'Christmas'];
|
|
2185
|
+
const orderedThemeNames = ['Dark', 'Light', 'Christmas', 'The New Year']; // Prioritize New Year
|
|
2243
2186
|
const sortedThemes = [];
|
|
2244
2187
|
|
|
2245
2188
|
orderedThemeNames.forEach(name => {
|
|
@@ -2304,22 +2247,33 @@
|
|
|
2304
2247
|
function applyTheme(theme) {
|
|
2305
2248
|
const root = document.documentElement;
|
|
2306
2249
|
|
|
2250
|
+
// --- FIREWORKS LOGIC ---
|
|
2251
|
+
if (theme.name === 'The New Year') {
|
|
2252
|
+
document.getElementById('fireworks-container').style.opacity = '1';
|
|
2253
|
+
fireworks.start();
|
|
2254
|
+
} else {
|
|
2255
|
+
document.getElementById('fireworks-container').style.opacity = '0';
|
|
2256
|
+
fireworks.stop();
|
|
2257
|
+
}
|
|
2258
|
+
// -----------------------
|
|
2259
|
+
|
|
2307
2260
|
// --- Logo Path Modification ---
|
|
2308
2261
|
let logoSrc;
|
|
2309
2262
|
const isLightTheme = lightThemeNames.includes(theme.name);
|
|
2310
2263
|
|
|
2311
2264
|
if (isLightTheme) {
|
|
2312
2265
|
logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo-dark.png';
|
|
2313
|
-
|
|
2314
|
-
root.style.setProperty('--menu-
|
|
2266
|
+
// Default light theme variables if not specified in theme
|
|
2267
|
+
if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', '#000000');
|
|
2268
|
+
if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#444444');
|
|
2315
2269
|
} else if (theme.name === 'Christmas') {
|
|
2316
2270
|
logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo-christmas.png';
|
|
2317
|
-
root.style.setProperty('--menu-username-text', 'white');
|
|
2318
|
-
root.style.setProperty('--menu-email-text', '#9ca3af');
|
|
2271
|
+
if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', 'white');
|
|
2272
|
+
if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#9ca3af');
|
|
2319
2273
|
} else {
|
|
2320
2274
|
logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png';
|
|
2321
|
-
root.style.setProperty('--menu-username-text', 'white');
|
|
2322
|
-
root.style.setProperty('--menu-email-text', '#9ca3af');
|
|
2275
|
+
if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', 'white');
|
|
2276
|
+
if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#9ca3af');
|
|
2323
2277
|
}
|
|
2324
2278
|
|
|
2325
2279
|
// Apply CSS Variables from theme object (overrides defaults if present)
|
|
@@ -2368,7 +2322,8 @@
|
|
|
2368
2322
|
localStorage.setItem('user-navbar-theme', JSON.stringify(theme));
|
|
2369
2323
|
|
|
2370
2324
|
// Apply Glide Button Color Sync
|
|
2371
|
-
|
|
2325
|
+
const glideColor = theme['tab-active-text'] || theme['accent-color'] || '#ffffff';
|
|
2326
|
+
root.style.setProperty('--glide-btn-color', glideColor);
|
|
2372
2327
|
|
|
2373
2328
|
// Also update user doc if logged in
|
|
2374
2329
|
if (currentUser) {
|
|
@@ -2632,41 +2587,6 @@
|
|
|
2632
2587
|
|
|
2633
2588
|
loadThemes();
|
|
2634
2589
|
loadPanicKeys();
|
|
2635
|
-
|
|
2636
|
-
// --- App Preference Toggles Init ---
|
|
2637
|
-
const animBtn = document.getElementById('toggle-animations-btn');
|
|
2638
|
-
const soundBtn = document.getElementById('toggle-sounds-btn');
|
|
2639
|
-
|
|
2640
|
-
const updateToggleUI = () => {
|
|
2641
|
-
const isEnabled = window.areAnimationsEnabled;
|
|
2642
|
-
animBtn.classList.toggle('off', !isEnabled);
|
|
2643
|
-
animBtn.innerHTML = isEnabled ? '<i class="fa-solid fa-wand-magic-sparkles"></i>' : '<i class="fa-solid fa-wand-magic"></i>';
|
|
2644
|
-
|
|
2645
|
-
// Apply to body
|
|
2646
|
-
if (isEnabled) document.body.classList.remove('no-animations');
|
|
2647
|
-
else document.body.classList.add('no-animations');
|
|
2648
|
-
|
|
2649
|
-
soundBtn.classList.toggle('off', window.isMuted);
|
|
2650
|
-
soundBtn.innerHTML = window.isMuted ? '<i class="fa-solid fa-volume-xmark"></i>' : '<i class="fa-solid fa-volume-high"></i>';
|
|
2651
|
-
};
|
|
2652
|
-
|
|
2653
|
-
if (animBtn) {
|
|
2654
|
-
animBtn.onclick = () => {
|
|
2655
|
-
window.areAnimationsEnabled = !window.areAnimationsEnabled;
|
|
2656
|
-
localStorage.setItem('app_animations_enabled', window.areAnimationsEnabled);
|
|
2657
|
-
updateToggleUI();
|
|
2658
|
-
};
|
|
2659
|
-
}
|
|
2660
|
-
|
|
2661
|
-
if (soundBtn) {
|
|
2662
|
-
soundBtn.onclick = () => {
|
|
2663
|
-
window.isMuted = !window.isMuted;
|
|
2664
|
-
localStorage.setItem('app_is_muted', window.isMuted);
|
|
2665
|
-
updateToggleUI();
|
|
2666
|
-
};
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
updateToggleUI();
|
|
2670
2590
|
}
|
|
2671
2591
|
|
|
2672
2592
|
checkAutoLogin();
|
|
@@ -2678,26 +2598,14 @@
|
|
|
2678
2598
|
<script>
|
|
2679
2599
|
// --- Sound & Notification Logic ---
|
|
2680
2600
|
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
Object.defineProperty(window, 'isMuted', {
|
|
2684
|
-
get: () => localStorage.getItem('app_is_muted') === 'true',
|
|
2685
|
-
set: (v) => localStorage.setItem('app_is_muted', v)
|
|
2686
|
-
});
|
|
2687
|
-
|
|
2688
|
-
Object.defineProperty(window, 'areAnimationsEnabled', {
|
|
2689
|
-
get: () => localStorage.getItem('app_animations_enabled') !== 'false',
|
|
2690
|
-
set: (v) => localStorage.setItem('app_animations_enabled', v)
|
|
2691
|
-
});
|
|
2692
|
-
|
|
2693
|
-
// Initial Class Set
|
|
2694
|
-
if (!window.areAnimationsEnabled) document.body.classList.add('no-animations');
|
|
2601
|
+
let isMuted = false;
|
|
2602
|
+
let areAnimationsEnabled = true;
|
|
2695
2603
|
|
|
2696
2604
|
// EXPOSE PlayTypeSound GLOBALLY
|
|
2697
2605
|
// Debounce to prevent rapid-fire stuttering if called too fast
|
|
2698
2606
|
let typeSoundTimeout = null;
|
|
2699
2607
|
window.playTypeSound = function() {
|
|
2700
|
-
if (
|
|
2608
|
+
if (isMuted) return;
|
|
2701
2609
|
if (audioCtx.state === 'suspended') audioCtx.resume();
|
|
2702
2610
|
|
|
2703
2611
|
// Small debounce
|
|
@@ -2738,7 +2646,7 @@
|
|
|
2738
2646
|
};
|
|
2739
2647
|
|
|
2740
2648
|
function playClickSound() {
|
|
2741
|
-
if (
|
|
2649
|
+
if (isMuted) return;
|
|
2742
2650
|
if (audioCtx.state === 'suspended') audioCtx.resume();
|
|
2743
2651
|
|
|
2744
2652
|
const osc = audioCtx.createOscillator();
|
|
@@ -2753,12 +2661,8 @@
|
|
|
2753
2661
|
osc.stop(audioCtx.currentTime + 0.015);
|
|
2754
2662
|
}
|
|
2755
2663
|
|
|
2756
|
-
// --- App Preferences State ---
|
|
2757
|
-
window.isMuted = localStorage.getItem('app_is_muted') === 'true';
|
|
2758
|
-
window.areAnimationsEnabled = localStorage.getItem('app_animations_enabled') !== 'false'; // Default true
|
|
2759
|
-
|
|
2760
2664
|
window.playMechClick = function(isReverse = false) {
|
|
2761
|
-
if (
|
|
2665
|
+
if (isMuted) return;
|
|
2762
2666
|
if (audioCtx.state === 'suspended') audioCtx.resume();
|
|
2763
2667
|
const now = audioCtx.currentTime;
|
|
2764
2668
|
|
|
@@ -2799,7 +2703,7 @@
|
|
|
2799
2703
|
osc.stop(now + 0.02);
|
|
2800
2704
|
};
|
|
2801
2705
|
|
|
2802
|
-
|
|
2706
|
+
// Removed Gear Animation Logic
|
|
2803
2707
|
|
|
2804
2708
|
const notificationContainer = document.getElementById('notification-container');
|
|
2805
2709
|
function showNotification(message, iconClass = 'fa-solid fa-info-circle', type = 'info') {
|
|
@@ -2839,27 +2743,6 @@
|
|
|
2839
2743
|
document.addEventListener('paste', (e) => {
|
|
2840
2744
|
if (e.target.closest('input, textarea')) showNotification('Pasted from clipboard', 'fa-solid fa-paste', 'info');
|
|
2841
2745
|
});
|
|
2842
|
-
|
|
2843
|
-
// --- PRELOADER REMOVAL ---
|
|
2844
|
-
window.addEventListener('load', () => {
|
|
2845
|
-
const preloader = document.getElementById('app-preloader');
|
|
2846
|
-
const bar = document.getElementById('preloader-bar');
|
|
2847
|
-
|
|
2848
|
-
if (preloader && bar) {
|
|
2849
|
-
// Animate bar to 100%
|
|
2850
|
-
setTimeout(() => {
|
|
2851
|
-
bar.style.width = '100%';
|
|
2852
|
-
|
|
2853
|
-
// Then fade out
|
|
2854
|
-
setTimeout(() => {
|
|
2855
|
-
preloader.classList.add('fade-out');
|
|
2856
|
-
setTimeout(() => {
|
|
2857
|
-
preloader.remove();
|
|
2858
|
-
}, 500);
|
|
2859
|
-
}, 600); // Wait for bar animation
|
|
2860
|
-
}, 100);
|
|
2861
|
-
}
|
|
2862
|
-
});
|
|
2863
2746
|
</script>
|
|
2864
2747
|
</body>
|
|
2865
2748
|
</html>
|