clay-server 2.9.0 → 2.9.2
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/bin/cli.js +47 -30
- package/lib/pages.js +18 -17
- package/lib/project.js +77 -63
- package/lib/public/app.js +250 -72
- package/lib/public/css/base.css +3 -0
- package/lib/public/css/filebrowser.css +8 -1
- package/lib/public/css/home-hub.css +1 -1
- package/lib/public/css/input.css +4 -0
- package/lib/public/css/menus.css +1 -44
- package/lib/public/css/messages.css +1 -0
- package/lib/public/css/mobile-nav.css +2 -2
- package/lib/public/css/overlays.css +175 -16
- package/lib/public/css/scheduler.css +1 -0
- package/lib/public/css/server-settings.css +37 -34
- package/lib/public/css/title-bar.css +0 -7
- package/lib/public/index.html +63 -22
- package/lib/public/manifest.json +2 -2
- package/lib/public/modules/notifications.js +15 -103
- package/lib/public/modules/scheduler.js +55 -48
- package/lib/public/modules/server-settings.js +13 -4
- package/lib/sdk-bridge.js +4 -6
- package/package.json +1 -1
|
@@ -41,6 +41,154 @@ button.top-bar-pill {
|
|
|
41
41
|
transition: background 0.15s;
|
|
42
42
|
}
|
|
43
43
|
button.top-bar-pill.pill-success:hover { background: color-mix(in srgb, var(--success) 20%, transparent); }
|
|
44
|
+
button.top-bar-pill.pill-accent:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
|
|
45
|
+
|
|
46
|
+
/* PWA install button — left side of top bar, icon only */
|
|
47
|
+
.top-bar-install-btn {
|
|
48
|
+
position: absolute;
|
|
49
|
+
left: 10px;
|
|
50
|
+
top: 50%;
|
|
51
|
+
transform: translateY(-50%);
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
background: none;
|
|
56
|
+
border: none;
|
|
57
|
+
border-radius: 6px;
|
|
58
|
+
color: var(--accent);
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
padding: 3px;
|
|
61
|
+
transition: color 0.15s, background 0.15s;
|
|
62
|
+
}
|
|
63
|
+
.top-bar-install-btn .lucide { width: 14px; height: 14px; }
|
|
64
|
+
.top-bar-install-btn:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
|
|
65
|
+
.top-bar-install-btn.hidden { display: none; }
|
|
66
|
+
.pwa-standalone .top-bar-install-btn { display: none !important; }
|
|
67
|
+
|
|
68
|
+
@media (max-width: 768px) {
|
|
69
|
+
.top-bar-install-btn {
|
|
70
|
+
top: auto;
|
|
71
|
+
bottom: 0;
|
|
72
|
+
height: 32px;
|
|
73
|
+
transform: none;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* PWA install modal */
|
|
78
|
+
.pwa-modal {
|
|
79
|
+
position: fixed;
|
|
80
|
+
inset: 0;
|
|
81
|
+
z-index: 700;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
padding: 20px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.pwa-modal.hidden { display: none; }
|
|
89
|
+
|
|
90
|
+
.pwa-modal-backdrop {
|
|
91
|
+
position: absolute;
|
|
92
|
+
inset: 0;
|
|
93
|
+
background: rgba(0,0,0,0.55);
|
|
94
|
+
backdrop-filter: blur(8px);
|
|
95
|
+
-webkit-backdrop-filter: blur(8px);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.pwa-modal-card {
|
|
99
|
+
position: relative;
|
|
100
|
+
background: var(--bg);
|
|
101
|
+
border: 1px solid var(--border);
|
|
102
|
+
border-radius: 16px;
|
|
103
|
+
padding: 28px 24px 20px;
|
|
104
|
+
max-width: 340px;
|
|
105
|
+
width: 100%;
|
|
106
|
+
box-shadow: 0 16px 48px rgba(0,0,0,0.35);
|
|
107
|
+
animation: modal-in 0.2s ease-out;
|
|
108
|
+
text-align: center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@keyframes modal-in {
|
|
112
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
113
|
+
to { opacity: 1; transform: scale(1); }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.pwa-modal-icon {
|
|
117
|
+
font-size: 36px;
|
|
118
|
+
margin-bottom: 8px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.pwa-modal-title {
|
|
122
|
+
font-family: "Pretendard", system-ui, sans-serif;
|
|
123
|
+
font-size: 18px;
|
|
124
|
+
font-weight: 700;
|
|
125
|
+
color: var(--text);
|
|
126
|
+
margin: 0 0 6px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.pwa-modal-desc {
|
|
130
|
+
font-size: 13px;
|
|
131
|
+
color: var(--text-muted);
|
|
132
|
+
margin: 0 0 16px;
|
|
133
|
+
line-height: 1.5;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.pwa-modal-benefits {
|
|
137
|
+
list-style: none;
|
|
138
|
+
padding: 0;
|
|
139
|
+
margin: 0 0 20px;
|
|
140
|
+
text-align: left;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.pwa-modal-benefits li {
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
gap: 10px;
|
|
147
|
+
font-size: 13px;
|
|
148
|
+
color: var(--text-secondary);
|
|
149
|
+
padding: 7px 0;
|
|
150
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.pwa-modal-benefits li:last-child { border-bottom: none; }
|
|
154
|
+
|
|
155
|
+
.pwa-benefit-icon {
|
|
156
|
+
width: 16px;
|
|
157
|
+
height: 16px;
|
|
158
|
+
color: var(--accent);
|
|
159
|
+
flex-shrink: 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.pwa-modal-buttons {
|
|
163
|
+
display: flex;
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
gap: 8px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.pwa-modal-btn {
|
|
169
|
+
width: 100%;
|
|
170
|
+
padding: 11px;
|
|
171
|
+
border-radius: 10px;
|
|
172
|
+
font-family: "Pretendard", system-ui, sans-serif;
|
|
173
|
+
font-size: 14px;
|
|
174
|
+
font-weight: 600;
|
|
175
|
+
cursor: pointer;
|
|
176
|
+
border: none;
|
|
177
|
+
transition: opacity 0.15s;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.pwa-modal-btn:hover { opacity: 0.85; }
|
|
181
|
+
|
|
182
|
+
.pwa-modal-btn.primary {
|
|
183
|
+
background: var(--accent);
|
|
184
|
+
color: #fff;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.pwa-modal-btn.secondary {
|
|
188
|
+
background: none;
|
|
189
|
+
color: var(--text-muted);
|
|
190
|
+
font-weight: 500;
|
|
191
|
+
}
|
|
44
192
|
|
|
45
193
|
/* Pill close button (onboarding) */
|
|
46
194
|
.pill-close {
|
|
@@ -58,22 +206,6 @@ button.top-bar-pill.pill-success:hover { background: color-mix(in srgb, var(--su
|
|
|
58
206
|
.pill-close:hover { opacity: 1; }
|
|
59
207
|
.pill-close .lucide { width: 10px; height: 10px; }
|
|
60
208
|
|
|
61
|
-
/* Onboarding pill text */
|
|
62
|
-
.onboarding-pill-text { display: inline-flex; align-items: center; gap: 4px; }
|
|
63
|
-
.onboarding-pill-text .lucide { width: 12px; height: 12px; }
|
|
64
|
-
.onboarding-pill-text a,
|
|
65
|
-
.onboarding-pill-text button.onboarding-cta {
|
|
66
|
-
color: inherit;
|
|
67
|
-
font-weight: 600;
|
|
68
|
-
text-decoration: underline;
|
|
69
|
-
background: none;
|
|
70
|
-
border: none;
|
|
71
|
-
font-family: inherit;
|
|
72
|
-
font-size: inherit;
|
|
73
|
-
cursor: pointer;
|
|
74
|
-
padding: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
209
|
/* Update pill wrapper */
|
|
78
210
|
#update-pill-wrap {
|
|
79
211
|
position: relative;
|
|
@@ -183,6 +315,33 @@ button.top-bar-pill.pill-success:hover { background: color-mix(in srgb, var(--su
|
|
|
183
315
|
|
|
184
316
|
#confirm-modal.hidden { display: none; }
|
|
185
317
|
|
|
318
|
+
#skill-install-modal {
|
|
319
|
+
position: fixed;
|
|
320
|
+
inset: 0;
|
|
321
|
+
z-index: 300;
|
|
322
|
+
display: flex;
|
|
323
|
+
align-items: center;
|
|
324
|
+
justify-content: center;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
#skill-install-modal.hidden { display: none; }
|
|
328
|
+
|
|
329
|
+
.skill-install-dialog { max-width: 460px; padding: 28px 32px; }
|
|
330
|
+
.skill-install-title { font-weight: 600; font-size: 17px; margin-bottom: 8px; color: var(--text); }
|
|
331
|
+
.skill-install-reason { color: var(--text-secondary); font-size: 14px; line-height: 1.5; margin-bottom: 18px; }
|
|
332
|
+
.skill-install-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
|
|
333
|
+
.skill-install-item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 10px; background: rgba(var(--overlay-rgb), 0.05); border: 1px solid var(--border); }
|
|
334
|
+
.skill-install-item .skill-icon { font-size: 20px; flex-shrink: 0; }
|
|
335
|
+
.skill-install-item .skill-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
336
|
+
.skill-install-item .skill-name { font-weight: 500; font-size: 14px; color: var(--text); }
|
|
337
|
+
.skill-install-item .skill-scope { font-size: 12px; color: var(--text-muted); }
|
|
338
|
+
.skill-install-item .skill-status { margin-left: auto; flex-shrink: 0; }
|
|
339
|
+
.skill-status-ok { color: var(--success, #2ecc71); font-size: 16px; font-weight: 600; }
|
|
340
|
+
#skill-install-status { font-size: 13px; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; color: var(--text-secondary); }
|
|
341
|
+
#skill-install-status.hidden { display: none; }
|
|
342
|
+
.confirm-proceed { background: var(--success, #2ecc71); color: #fff; border: none; }
|
|
343
|
+
.confirm-proceed:hover { opacity: 0.9; }
|
|
344
|
+
|
|
186
345
|
.confirm-backdrop {
|
|
187
346
|
position: absolute;
|
|
188
347
|
inset: 0;
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
.server-settings-nav-inner {
|
|
72
72
|
width: 200px;
|
|
73
73
|
flex-shrink: 0;
|
|
74
|
-
padding: 60px 6px 40px 0;
|
|
74
|
+
padding: calc(var(--safe-top) + 60px) 6px 40px 0;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/* --- Nav header --- */
|
|
@@ -89,6 +89,11 @@
|
|
|
89
89
|
white-space: nowrap;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/* --- Nav dropdown (mobile only) --- */
|
|
93
|
+
.settings-nav-dropdown {
|
|
94
|
+
display: none;
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
/* --- Nav items --- */
|
|
93
98
|
.server-settings-nav-items {
|
|
94
99
|
display: flex;
|
|
@@ -149,13 +154,13 @@
|
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
.server-settings-content-inner {
|
|
152
|
-
padding: 60px 40px 60px 40px;
|
|
157
|
+
padding: calc(var(--safe-top) + 60px) 40px calc(var(--safe-bottom) + 60px) 40px;
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
/* ========== CLOSE COLUMN ========== */
|
|
156
161
|
.server-settings-close-col {
|
|
157
162
|
position: fixed;
|
|
158
|
-
top: 60px;
|
|
163
|
+
top: calc(var(--safe-top) + 60px);
|
|
159
164
|
right: 20px;
|
|
160
165
|
z-index: 5;
|
|
161
166
|
}
|
|
@@ -734,7 +739,7 @@
|
|
|
734
739
|
|
|
735
740
|
.server-settings-nav-inner {
|
|
736
741
|
width: 100%;
|
|
737
|
-
padding: 0;
|
|
742
|
+
padding: var(--safe-top) 0 0;
|
|
738
743
|
display: flex;
|
|
739
744
|
flex-direction: column;
|
|
740
745
|
gap: 0;
|
|
@@ -744,41 +749,39 @@
|
|
|
744
749
|
padding: 12px 16px 8px;
|
|
745
750
|
}
|
|
746
751
|
|
|
747
|
-
/*
|
|
752
|
+
/* Hide desktop nav items on mobile, show dropdown instead */
|
|
748
753
|
.server-settings-nav-items {
|
|
749
|
-
|
|
750
|
-
overflow-x: auto;
|
|
751
|
-
gap: 2px;
|
|
752
|
-
scrollbar-width: none;
|
|
753
|
-
padding: 0 16px 10px;
|
|
754
|
-
-webkit-mask-image: linear-gradient(to right, transparent 0, black 16px, black calc(100% - 24px), transparent 100%);
|
|
755
|
-
mask-image: linear-gradient(to right, transparent 0, black 16px, black calc(100% - 24px), transparent 100%);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
.server-settings-nav-items::-webkit-scrollbar { display: none; }
|
|
759
|
-
|
|
760
|
-
.settings-nav-item {
|
|
761
|
-
flex-shrink: 0;
|
|
762
|
-
font-size: 13px;
|
|
763
|
-
padding: 6px 12px;
|
|
764
|
-
border-radius: 20px;
|
|
765
|
-
background: rgba(var(--overlay-rgb), 0.04);
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
.settings-nav-item.active {
|
|
769
|
-
background: rgba(var(--overlay-rgb), 0.12);
|
|
754
|
+
display: none;
|
|
770
755
|
}
|
|
771
756
|
|
|
772
|
-
.settings-nav-
|
|
773
|
-
|
|
757
|
+
.settings-nav-dropdown {
|
|
758
|
+
display: block;
|
|
759
|
+
width: calc(100% - 32px);
|
|
760
|
+
margin: 0 16px 12px;
|
|
761
|
+
padding: 10px 12px;
|
|
762
|
+
font-family: "Pretendard", system-ui, sans-serif;
|
|
763
|
+
font-size: 14px;
|
|
764
|
+
font-weight: 600;
|
|
765
|
+
color: var(--text);
|
|
766
|
+
background: var(--bg-alt);
|
|
767
|
+
border: 1px solid var(--border);
|
|
768
|
+
border-radius: 10px;
|
|
769
|
+
-webkit-appearance: none;
|
|
770
|
+
appearance: none;
|
|
771
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
|
|
772
|
+
background-repeat: no-repeat;
|
|
773
|
+
background-position: right 12px center;
|
|
774
|
+
cursor: pointer;
|
|
774
775
|
}
|
|
775
776
|
|
|
776
|
-
.settings-nav-
|
|
777
|
-
|
|
777
|
+
.settings-nav-dropdown optgroup {
|
|
778
|
+
font-weight: 700;
|
|
779
|
+
color: var(--text-muted);
|
|
778
780
|
}
|
|
779
781
|
|
|
780
|
-
.settings-nav-
|
|
781
|
-
|
|
782
|
+
.settings-nav-dropdown option {
|
|
783
|
+
font-weight: 500;
|
|
784
|
+
color: var(--text);
|
|
782
785
|
}
|
|
783
786
|
|
|
784
787
|
.server-settings-content {
|
|
@@ -787,11 +790,11 @@
|
|
|
787
790
|
}
|
|
788
791
|
|
|
789
792
|
.server-settings-content-inner {
|
|
790
|
-
padding: 24px 16px;
|
|
793
|
+
padding: 24px 16px calc(var(--safe-bottom) + 24px);
|
|
791
794
|
}
|
|
792
795
|
|
|
793
796
|
.server-settings-close-col {
|
|
794
|
-
top: 12px;
|
|
797
|
+
top: calc(var(--safe-top) + 12px);
|
|
795
798
|
right: 12px;
|
|
796
799
|
}
|
|
797
800
|
|
|
@@ -162,13 +162,6 @@
|
|
|
162
162
|
color: var(--text-dimmer); /* darker icon on light thumb */
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
/* Debug button in top bar */
|
|
166
|
-
.top-bar-actions #debug-menu-wrap { position: relative; }
|
|
167
|
-
.top-bar-actions #debug-menu-wrap.hidden { display: none; }
|
|
168
|
-
.top-bar-actions #debug-btn { color: var(--error); opacity: 0.6; }
|
|
169
|
-
.top-bar-actions #debug-btn:hover { opacity: 1; background: var(--error-8); }
|
|
170
|
-
.top-bar-actions #debug-btn.active { opacity: 1; background: var(--error-12); }
|
|
171
|
-
|
|
172
165
|
/* ==========================================================================
|
|
173
166
|
Title Bar — split into sidebar-column and main-column sections
|
|
174
167
|
========================================================================== */
|
package/lib/public/index.html
CHANGED
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
6
6
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
7
7
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
8
|
-
<
|
|
9
|
-
|
|
8
|
+
<script>
|
|
9
|
+
(function(){
|
|
10
|
+
var isIOS=/iPad|iPhone|iPod/.test(navigator.userAgent)||(navigator.platform==="MacIntel"&&navigator.maxTouchPoints>1);
|
|
11
|
+
if(!isIOS){var l=document.createElement("link");l.rel="manifest";l.href="manifest.json";document.head.appendChild(l)}
|
|
12
|
+
})();
|
|
13
|
+
</script>
|
|
14
|
+
<meta name="theme-color" content="#282a36">
|
|
10
15
|
<link rel="icon" type="image/png" href="favicon-banded.png">
|
|
11
16
|
<link rel="apple-touch-icon" href="apple-touch-icon.png">
|
|
12
17
|
<title>Clay</title>
|
|
@@ -17,12 +22,14 @@
|
|
|
17
22
|
<script>
|
|
18
23
|
(function(){try{var k="clay-theme-vars",v=localStorage.getItem(k),r=document.documentElement;if(v){var o=JSON.parse(v),p;for(p in o)r.style.setProperty(p,o[p]);var vt=localStorage.getItem(k.replace("-vars","-variant"));if(vt==="light"){r.classList.add("light-theme");r.classList.remove("dark-theme")}else{r.classList.add("dark-theme");r.classList.remove("light-theme")}var m=document.querySelector('meta[name="theme-color"]');if(m&&o["--bg"])m.setAttribute("content",o["--bg"])}else{var sl=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;if(sl){r.classList.add("light-theme");r.classList.remove("dark-theme")}}}catch(e){}})();
|
|
19
24
|
</script>
|
|
25
|
+
<script>if(window.navigator.standalone||window.matchMedia("(display-mode:standalone)").matches){document.documentElement.classList.add("pwa-standalone")}</script>
|
|
20
26
|
<link rel="stylesheet" href="style.css">
|
|
21
27
|
</head>
|
|
22
28
|
<body>
|
|
23
29
|
<div id="layout">
|
|
24
30
|
<!-- === Top Bar (full width, forms reverse-ㄱ with icon strip) === -->
|
|
25
31
|
<div id="top-bar">
|
|
32
|
+
<button id="pwa-install-pill" class="top-bar-install-btn hidden" title="Install app"><i data-lucide="download"></i></button>
|
|
26
33
|
<div class="top-bar-center">
|
|
27
34
|
<a href="https://github.com/chadbyte/clay" target="_blank" rel="noopener" class="top-bar-title"><img class="top-bar-icon" src="favicon-banded.png" width="16" height="16" alt="">Clay <span id="footer-version" class="footer-version"></span></a>
|
|
28
35
|
<div id="update-pill-wrap" class="hidden">
|
|
@@ -32,30 +39,11 @@
|
|
|
32
39
|
<div class="popover-row"><div class="popover-label">Or run manually:</div><div class="popover-cmd"><code>npx clay-server@latest</code><button class="popover-copy" title="Copy"><i data-lucide="copy"></i></button></div></div>
|
|
33
40
|
</div>
|
|
34
41
|
</div>
|
|
35
|
-
<div id="onboarding-pill" class="top-bar-pill pill-accent hidden">
|
|
36
|
-
<span class="onboarding-pill-text" id="onboarding-pill-text"></span>
|
|
37
|
-
<button id="onboarding-pill-close" class="pill-close" aria-label="Dismiss"><i data-lucide="x"></i></button>
|
|
38
|
-
</div>
|
|
39
42
|
</div>
|
|
40
43
|
<div class="top-bar-actions">
|
|
41
44
|
<!-- Pill badges -->
|
|
42
45
|
<div id="skip-perms-pill" class="top-bar-pill pill-error hidden"><i data-lucide="shield-off"></i> <span>Skip perms</span></div>
|
|
43
|
-
<
|
|
44
|
-
<div id="debug-menu-wrap" class="hidden">
|
|
45
|
-
<button id="debug-btn" title="Debug"><i data-lucide="bug"></i></button>
|
|
46
|
-
<div id="debug-menu" class="hidden">
|
|
47
|
-
<label class="notif-option">
|
|
48
|
-
<span>Update banner</span>
|
|
49
|
-
<input type="checkbox" id="debug-toggle-update">
|
|
50
|
-
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
51
|
-
</label>
|
|
52
|
-
<label class="notif-option">
|
|
53
|
-
<span>Onboarding banner</span>
|
|
54
|
-
<input type="checkbox" id="debug-toggle-onboarding">
|
|
55
|
-
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
56
|
-
</label>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
46
|
+
<div id="client-count" class="top-bar-pill pill-accent hidden"><i data-lucide="users"></i> <span id="client-count-text"></span></div>
|
|
59
47
|
<label id="theme-toggle-btn" class="theme-toggle" title="Toggle dark/light mode">
|
|
60
48
|
<input type="checkbox" id="theme-toggle-check">
|
|
61
49
|
<span class="theme-toggle-track">
|
|
@@ -614,6 +602,28 @@
|
|
|
614
602
|
<div class="server-settings-nav">
|
|
615
603
|
<div class="server-settings-nav-inner">
|
|
616
604
|
<div class="server-settings-nav-header" id="settings-server-name"></div>
|
|
605
|
+
<select id="settings-nav-dropdown" class="settings-nav-dropdown">
|
|
606
|
+
<optgroup label="General">
|
|
607
|
+
<option value="overview" selected>Status</option>
|
|
608
|
+
<option value="notifications">Notifications</option>
|
|
609
|
+
</optgroup>
|
|
610
|
+
<optgroup label="Session">
|
|
611
|
+
<option value="models">Model & Behavior</option>
|
|
612
|
+
<option value="claudemd">CLAUDE.md</option>
|
|
613
|
+
<option value="environment">Environment Variables</option>
|
|
614
|
+
</optgroup>
|
|
615
|
+
<optgroup label="Admin" class="settings-admin-only">
|
|
616
|
+
<option value="admin-users">Users</option>
|
|
617
|
+
<option value="admin-invites">Invites</option>
|
|
618
|
+
<option value="admin-projects">Projects</option>
|
|
619
|
+
<option value="admin-smtp">Email (SMTP)</option>
|
|
620
|
+
</optgroup>
|
|
621
|
+
<optgroup label="Server">
|
|
622
|
+
<option value="security">Security</option>
|
|
623
|
+
<option value="restart">Restart Server</option>
|
|
624
|
+
<option value="shutdown">Shutdown Server</option>
|
|
625
|
+
</optgroup>
|
|
626
|
+
</select>
|
|
617
627
|
<div class="server-settings-nav-items">
|
|
618
628
|
<div class="settings-nav-category">General</div>
|
|
619
629
|
<button class="settings-nav-item active" data-section="overview"><span>Status</span></button>
|
|
@@ -1025,6 +1035,20 @@
|
|
|
1025
1035
|
</div>
|
|
1026
1036
|
</div>
|
|
1027
1037
|
|
|
1038
|
+
<div id="skill-install-modal" class="hidden">
|
|
1039
|
+
<div class="confirm-backdrop"></div>
|
|
1040
|
+
<div class="confirm-dialog skill-install-dialog">
|
|
1041
|
+
<div class="skill-install-title" id="skill-install-title"></div>
|
|
1042
|
+
<div class="skill-install-reason" id="skill-install-reason"></div>
|
|
1043
|
+
<div class="skill-install-list" id="skill-install-list"></div>
|
|
1044
|
+
<div id="skill-install-status" class="hidden"></div>
|
|
1045
|
+
<div class="confirm-actions">
|
|
1046
|
+
<button class="confirm-btn confirm-cancel" id="skill-install-cancel">Cancel</button>
|
|
1047
|
+
<button class="confirm-btn confirm-delete" id="skill-install-ok">Install</button>
|
|
1048
|
+
</div>
|
|
1049
|
+
</div>
|
|
1050
|
+
</div>
|
|
1051
|
+
|
|
1028
1052
|
<div id="add-project-modal" class="hidden">
|
|
1029
1053
|
<div class="confirm-backdrop"></div>
|
|
1030
1054
|
<div class="confirm-dialog add-project-dialog">
|
|
@@ -1392,5 +1416,22 @@
|
|
|
1392
1416
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5/lib/xterm.min.js"></script>
|
|
1393
1417
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0/lib/addon-fit.min.js"></script>
|
|
1394
1418
|
<script type="module" src="app.js"></script>
|
|
1419
|
+
<div id="pwa-install-modal" class="pwa-modal hidden">
|
|
1420
|
+
<div class="pwa-modal-backdrop"></div>
|
|
1421
|
+
<div class="pwa-modal-card">
|
|
1422
|
+
<div class="pwa-modal-icon">📲</div>
|
|
1423
|
+
<h3 class="pwa-modal-title">Add to Home Screen</h3>
|
|
1424
|
+
<p class="pwa-modal-desc">Add Clay to your home screen for a better experience.</p>
|
|
1425
|
+
<ul class="pwa-modal-benefits">
|
|
1426
|
+
<li><i data-lucide="maximize" class="pwa-benefit-icon"></i>Full-screen — no browser toolbar</li>
|
|
1427
|
+
<li><i data-lucide="bell" class="pwa-benefit-icon"></i>Push notifications when tasks finish</li>
|
|
1428
|
+
<li><i data-lucide="zap" class="pwa-benefit-icon"></i>Instant launch from home screen</li>
|
|
1429
|
+
</ul>
|
|
1430
|
+
<div class="pwa-modal-buttons">
|
|
1431
|
+
<button id="pwa-modal-confirm" class="pwa-modal-btn primary">Continue</button>
|
|
1432
|
+
<button id="pwa-modal-cancel" class="pwa-modal-btn secondary">Not now</button>
|
|
1433
|
+
</div>
|
|
1434
|
+
</div>
|
|
1435
|
+
</div>
|
|
1395
1436
|
</body>
|
|
1396
1437
|
</html>
|
package/lib/public/manifest.json
CHANGED
|
@@ -187,29 +187,7 @@ export function initNotifications(_ctx) {
|
|
|
187
187
|
}
|
|
188
188
|
})();
|
|
189
189
|
|
|
190
|
-
//
|
|
191
|
-
onboardingPill = $("onboarding-pill");
|
|
192
|
-
onboardingText = $("onboarding-pill-text");
|
|
193
|
-
onboardingClose = $("onboarding-pill-close");
|
|
194
|
-
onboardingDismissed = localStorage.getItem("onboarding-dismissed");
|
|
195
|
-
|
|
196
|
-
if (onboardingClose) {
|
|
197
|
-
onboardingClose.addEventListener("click", function () {
|
|
198
|
-
hideOnboarding();
|
|
199
|
-
localStorage.setItem("onboarding-dismissed", "1");
|
|
200
|
-
onboardingDismissed = "1";
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Suggest HTTPS setup for push notification support
|
|
205
|
-
if (location.protocol !== "https:" && location.hostname !== "localhost") {
|
|
206
|
-
if (!onboardingDismissed) {
|
|
207
|
-
showOnboarding(
|
|
208
|
-
iconHtml("bell-ring") +
|
|
209
|
-
' <a href="/setup">Set up HTTPS</a>'
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
190
|
+
// Onboarding pill removed — install flow handled by PWA install button
|
|
213
191
|
|
|
214
192
|
// --- Tooltip ---
|
|
215
193
|
var tooltipEl = document.createElement("div");
|
|
@@ -495,6 +473,20 @@ export function initNotifications(_ctx) {
|
|
|
495
473
|
if (!("serviceWorker" in navigator)) return;
|
|
496
474
|
if (location.protocol !== "https:" && location.hostname !== "localhost") return;
|
|
497
475
|
|
|
476
|
+
// iOS Safari (non-standalone): unregister existing SW and skip registration
|
|
477
|
+
// to prevent iOS from treating the app as a modern PWA (which shows a floating toolbar).
|
|
478
|
+
// SW will be registered once the app is launched in standalone mode from the home screen.
|
|
479
|
+
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
|
|
480
|
+
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
481
|
+
var isStandalone = window.navigator.standalone ||
|
|
482
|
+
window.matchMedia("(display-mode:standalone)").matches;
|
|
483
|
+
if (isIOS && !isStandalone) {
|
|
484
|
+
navigator.serviceWorker.getRegistrations().then(function (regs) {
|
|
485
|
+
regs.forEach(function (r) { r.unregister(); });
|
|
486
|
+
});
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
|
|
498
490
|
navigator.serviceWorker.register("/sw.js")
|
|
499
491
|
.then(function () { return navigator.serviceWorker.ready; })
|
|
500
492
|
.then(function (reg) {
|
|
@@ -547,90 +539,10 @@ export function initNotifications(_ctx) {
|
|
|
547
539
|
location.href = "/setup" + (isTailscale ? "" : "?mode=lan");
|
|
548
540
|
return;
|
|
549
541
|
}
|
|
550
|
-
// Browser: show onboarding banner
|
|
551
|
-
if (!onboardingDismissed) {
|
|
552
|
-
showOnboarding(
|
|
553
|
-
iconHtml("bell-ring") +
|
|
554
|
-
' <button class="onboarding-cta" id="onboarding-enable-push">Enable push</button>'
|
|
555
|
-
);
|
|
556
|
-
var enableBtn = $("onboarding-enable-push");
|
|
557
|
-
if (enableBtn) {
|
|
558
|
-
enableBtn.addEventListener("click", function () {
|
|
559
|
-
subscribePush();
|
|
560
|
-
notifTogglePush.checked = true;
|
|
561
|
-
hideOnboarding();
|
|
562
|
-
localStorage.setItem("onboarding-dismissed", "1");
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
542
|
}
|
|
567
543
|
});
|
|
568
544
|
})
|
|
569
545
|
.catch(function () {});
|
|
570
546
|
})();
|
|
571
547
|
|
|
572
|
-
// --- Debug panel ---
|
|
573
|
-
(function () {
|
|
574
|
-
var debugBtn = $("debug-btn");
|
|
575
|
-
var debugMenu = $("debug-menu");
|
|
576
|
-
if (!debugBtn || !debugMenu) return;
|
|
577
|
-
|
|
578
|
-
var debugToggleUpdate = $("debug-toggle-update");
|
|
579
|
-
var debugToggleOnboarding = $("debug-toggle-onboarding");
|
|
580
|
-
|
|
581
|
-
debugBtn.addEventListener("click", function (e) {
|
|
582
|
-
e.stopPropagation();
|
|
583
|
-
var open = debugMenu.classList.toggle("hidden");
|
|
584
|
-
debugBtn.classList.toggle("active", !open);
|
|
585
|
-
|
|
586
|
-
// Sync toggle states with current pill visibility
|
|
587
|
-
var updatePillWrap = $("update-pill-wrap");
|
|
588
|
-
if (debugToggleUpdate && updatePillWrap) {
|
|
589
|
-
debugToggleUpdate.checked = !updatePillWrap.classList.contains("hidden");
|
|
590
|
-
}
|
|
591
|
-
if (debugToggleOnboarding && onboardingPill) {
|
|
592
|
-
debugToggleOnboarding.checked = !onboardingPill.classList.contains("hidden");
|
|
593
|
-
}
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
document.addEventListener("click", function (e) {
|
|
597
|
-
if (!debugMenu.contains(e.target) && e.target !== debugBtn) {
|
|
598
|
-
debugMenu.classList.add("hidden");
|
|
599
|
-
debugBtn.classList.remove("active");
|
|
600
|
-
}
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
if (debugToggleUpdate) {
|
|
604
|
-
debugToggleUpdate.addEventListener("change", function () {
|
|
605
|
-
var pillWrap = $("update-pill-wrap");
|
|
606
|
-
if (!pillWrap) return;
|
|
607
|
-
if (debugToggleUpdate.checked) {
|
|
608
|
-
// Trigger real update check from server (debug mode uses v0.0.9)
|
|
609
|
-
if (ctx.ws && ctx.connected) {
|
|
610
|
-
ctx.ws.send(JSON.stringify({ type: "check_update" }));
|
|
611
|
-
}
|
|
612
|
-
} else {
|
|
613
|
-
pillWrap.classList.add("hidden");
|
|
614
|
-
}
|
|
615
|
-
refreshIcons();
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
if (debugToggleOnboarding) {
|
|
620
|
-
debugToggleOnboarding.addEventListener("change", function () {
|
|
621
|
-
if (debugToggleOnboarding.checked) {
|
|
622
|
-
if (!onboardingText.innerHTML.trim()) {
|
|
623
|
-
showOnboarding(
|
|
624
|
-
iconHtml("bell-ring") +
|
|
625
|
-
' <a href="/setup">Set up HTTPS</a>'
|
|
626
|
-
);
|
|
627
|
-
} else {
|
|
628
|
-
onboardingPill.classList.remove("hidden");
|
|
629
|
-
}
|
|
630
|
-
} else {
|
|
631
|
-
hideOnboarding();
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
})();
|
|
636
548
|
}
|