clay-server 2.47.0-beta.4 → 2.47.0-beta.6
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/lib/project-connection.js +5 -25
- package/lib/project-http.js +5 -2
- package/lib/public/app.js +4 -1
- package/lib/public/css/icon-strip.css +0 -190
- package/lib/public/css/mobile-nav.css +20 -0
- package/lib/public/css/sidebar.css +19 -0
- package/lib/public/css/title-bar.css +169 -0
- package/lib/public/index.html +6 -0
- package/lib/public/modules/app-favicon.js +1 -10
- package/lib/public/modules/app-home-hub.js +2 -0
- package/lib/public/modules/app-messages.js +4 -7
- package/lib/public/modules/app-projects.js +43 -30
- package/lib/public/modules/branch-switcher.js +178 -0
- package/lib/public/modules/dom-refs.js +0 -1
- package/lib/public/modules/project-switcher.js +2 -1
- package/lib/public/modules/sidebar-mobile.js +27 -6
- package/lib/public/modules/sidebar-projects.js +63 -236
- package/lib/public/modules/sidebar-sessions.js +5 -0
- package/lib/public/modules/worktree-family.js +60 -0
- package/lib/sessions.js +1 -0
- package/package.json +1 -1
|
@@ -105,7 +105,6 @@ function attachConnection(ctx) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
var loopState = _loop.loopState;
|
|
108
|
-
var loopRegistry = _loop.loopRegistry;
|
|
109
108
|
|
|
110
109
|
// Resume loop if server restarted mid-execution (deferred so client gets initial state first)
|
|
111
110
|
if (loopState._needsResume) {
|
|
@@ -179,32 +178,13 @@ function attachConnection(ctx) {
|
|
|
179
178
|
if (_mcp) _mcp.sendConnectionState(ws);
|
|
180
179
|
if (_notifications) _notifications.sendConnectionState(ws, sendTo);
|
|
181
180
|
|
|
182
|
-
// Session list (filtered for access control)
|
|
181
|
+
// Session list (filtered for access control). Uses the same mapper as
|
|
182
|
+
// broadcastSessionList: a hand-rolled copy here silently drifts and
|
|
183
|
+
// drops fields (the connect-time list was missing vendor/spawn/mode,
|
|
184
|
+
// so vendor badges showed Claude until the next broadcast).
|
|
183
185
|
sendTo(ws, {
|
|
184
186
|
type: "session_list",
|
|
185
|
-
sessions: allSessions.map(function (s) {
|
|
186
|
-
var loop = s.loop ? Object.assign({}, s.loop) : null;
|
|
187
|
-
if (loop && loop.loopId && loopRegistry) {
|
|
188
|
-
var rec = loopRegistry.getById(loop.loopId);
|
|
189
|
-
if (rec) {
|
|
190
|
-
if (rec.name) loop.name = rec.name;
|
|
191
|
-
if (rec.source) loop.source = rec.source;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
id: s.localId,
|
|
196
|
-
cliSessionId: s.cliSessionId || null,
|
|
197
|
-
title: s.title || "New Session",
|
|
198
|
-
active: s.localId === sm.activeSessionId,
|
|
199
|
-
isProcessing: s.isProcessing,
|
|
200
|
-
lastActivity: s.lastActivity || s.createdAt || 0,
|
|
201
|
-
loop: loop,
|
|
202
|
-
ownerId: s.ownerId || null,
|
|
203
|
-
sessionVisibility: s.sessionVisibility || "shared",
|
|
204
|
-
bookmarked: !!s.bookmarked,
|
|
205
|
-
favoriteOrder: typeof s.favoriteOrder === "number" ? s.favoriteOrder : null,
|
|
206
|
-
};
|
|
207
|
-
}),
|
|
187
|
+
sessions: allSessions.map(function (s) { return sm.mapSessionForClient(s); }),
|
|
208
188
|
});
|
|
209
189
|
|
|
210
190
|
// Restore active session for this client from server-side presence
|
package/lib/project-http.js
CHANGED
|
@@ -676,10 +676,13 @@ function attachHTTP(ctx) {
|
|
|
676
676
|
defBr = hrRef.replace(/^origin\//, "");
|
|
677
677
|
} catch (e) {}
|
|
678
678
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
679
|
-
res.end(JSON.stringify({ branches: brList, defaultBranch: defBr }));
|
|
679
|
+
res.end(JSON.stringify({ branches: brList, defaultBranch: defBr, isGitRepo: true }));
|
|
680
680
|
} catch (e) {
|
|
681
|
+
// git failed: not a repository (or git missing). The branch chip
|
|
682
|
+
// hides itself on isGitRepo:false; the fallback branch list keeps
|
|
683
|
+
// the worktree modal from crashing if it is somehow reached.
|
|
681
684
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
682
|
-
res.end(JSON.stringify({ branches: ["main"], defaultBranch: "main" }));
|
|
685
|
+
res.end(JSON.stringify({ branches: ["main"], defaultBranch: "main", isGitRepo: false }));
|
|
683
686
|
}
|
|
684
687
|
return true;
|
|
685
688
|
}
|
package/lib/public/app.js
CHANGED
|
@@ -42,6 +42,7 @@ import { initProfile, getProfileLang } from './modules/profile.js';
|
|
|
42
42
|
import { initUserSettings } from './modules/user-settings.js';
|
|
43
43
|
import { initToolPalettes } from './modules/tool-palette.js';
|
|
44
44
|
import { initProjectSwitcher } from './modules/project-switcher.js';
|
|
45
|
+
import { initBranchSwitcher } from './modules/branch-switcher.js';
|
|
45
46
|
import { initAdmin, checkAdminAccess } from './modules/admin.js';
|
|
46
47
|
import { initSessionSearch, toggleSearch, closeSearch, isSearchOpen, handleFindInSessionResults, onHistoryPrepended as onSessionSearchHistoryPrepended } from './modules/session-search.js';
|
|
47
48
|
import { initTooltips, registerTooltip } from './modules/tooltip.js';
|
|
@@ -85,7 +86,6 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
85
86
|
var sendBtn = $("send-btn");
|
|
86
87
|
function getStatusDot() {
|
|
87
88
|
return document.querySelector("#icon-strip-projects .icon-strip-item.active .icon-strip-status") ||
|
|
88
|
-
document.querySelector("#icon-strip-projects .icon-strip-wt-item.active .icon-strip-status") ||
|
|
89
89
|
document.querySelector("#icon-strip-users .icon-strip-mate.active .icon-strip-status");
|
|
90
90
|
}
|
|
91
91
|
var headerTitleEl = $("header-title");
|
|
@@ -270,6 +270,8 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
270
270
|
projectName: projectName,
|
|
271
271
|
cwd: "",
|
|
272
272
|
currentSlug: currentSlug,
|
|
273
|
+
projects: [],
|
|
274
|
+
homeHubVisible: false,
|
|
273
275
|
currentProjectOwnerId: null,
|
|
274
276
|
isOsUsers: false,
|
|
275
277
|
skipPermsEnabled: false,
|
|
@@ -461,6 +463,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
461
463
|
// keydown listener registers later — capture-phase ordering doesn't
|
|
462
464
|
// matter here but it keeps related bootstrap steps adjacent.
|
|
463
465
|
initProjectSwitcher();
|
|
466
|
+
initBranchSwitcher();
|
|
464
467
|
|
|
465
468
|
// --- Connect overlay (animated ASCII logo) ---
|
|
466
469
|
var asciiLogoCanvas = $("ascii-logo-canvas");
|
|
@@ -223,7 +223,6 @@
|
|
|
223
223
|
|
|
224
224
|
/* Show dot only on active item or when processing */
|
|
225
225
|
.icon-strip-item.active .icon-strip-status,
|
|
226
|
-
.icon-strip-wt-item.active .icon-strip-status,
|
|
227
226
|
.icon-strip-status.processing {
|
|
228
227
|
opacity: 1;
|
|
229
228
|
}
|
|
@@ -248,7 +247,6 @@
|
|
|
248
247
|
|
|
249
248
|
/* Pending permission shake */
|
|
250
249
|
.icon-strip-item.has-pending-perm,
|
|
251
|
-
.icon-strip-wt-item.has-pending-perm,
|
|
252
250
|
.icon-strip-mate.has-pending-perm {
|
|
253
251
|
animation: permShake 2s ease-in-out infinite;
|
|
254
252
|
}
|
|
@@ -1146,155 +1144,6 @@
|
|
|
1146
1144
|
opacity: 1;
|
|
1147
1145
|
}
|
|
1148
1146
|
|
|
1149
|
-
/* --- Worktree folder groups --- */
|
|
1150
|
-
.icon-strip-group {
|
|
1151
|
-
display: flex;
|
|
1152
|
-
flex-direction: column;
|
|
1153
|
-
align-items: center;
|
|
1154
|
-
position: relative;
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
.icon-strip-group .folder-header {
|
|
1158
|
-
position: relative;
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
.icon-strip-group-chevron {
|
|
1162
|
-
position: absolute;
|
|
1163
|
-
bottom: 2px;
|
|
1164
|
-
right: 2px;
|
|
1165
|
-
width: 16px;
|
|
1166
|
-
height: 16px;
|
|
1167
|
-
border-radius: 50%;
|
|
1168
|
-
background: var(--bg-alt);
|
|
1169
|
-
border: 1px solid var(--border);
|
|
1170
|
-
display: flex;
|
|
1171
|
-
align-items: center;
|
|
1172
|
-
justify-content: center;
|
|
1173
|
-
color: var(--text-dimmer);
|
|
1174
|
-
pointer-events: auto;
|
|
1175
|
-
cursor: pointer;
|
|
1176
|
-
transition: transform 0.15s ease, background 0.15s, border-color 0.15s;
|
|
1177
|
-
z-index: 2;
|
|
1178
|
-
line-height: 1;
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
.icon-strip-group-chevron i,
|
|
1182
|
-
.icon-strip-group-chevron svg {
|
|
1183
|
-
width: 10px;
|
|
1184
|
-
height: 10px;
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
.icon-strip-group-chevron:hover {
|
|
1188
|
-
background: var(--bg-hover, var(--bg-alt));
|
|
1189
|
-
border-color: var(--text-dimmer);
|
|
1190
|
-
color: var(--text-secondary);
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
.icon-strip-group.collapsed .icon-strip-group-chevron {
|
|
1194
|
-
background: var(--border);
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
.icon-strip-group-items {
|
|
1198
|
-
display: flex;
|
|
1199
|
-
flex-direction: column;
|
|
1200
|
-
align-items: center;
|
|
1201
|
-
overflow: hidden;
|
|
1202
|
-
transition: max-height 0.2s ease;
|
|
1203
|
-
max-height: 500px;
|
|
1204
|
-
border-left: 2px solid var(--border);
|
|
1205
|
-
margin-left: 0;
|
|
1206
|
-
padding-left: 0;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
.icon-strip-group.collapsed .icon-strip-group-items {
|
|
1210
|
-
max-height: 0;
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
/* Worktree items (smaller than regular project icons) */
|
|
1214
|
-
.icon-strip-wt-item {
|
|
1215
|
-
width: 48px;
|
|
1216
|
-
height: 40px;
|
|
1217
|
-
display: flex;
|
|
1218
|
-
align-items: center;
|
|
1219
|
-
justify-content: center;
|
|
1220
|
-
cursor: pointer;
|
|
1221
|
-
position: relative;
|
|
1222
|
-
text-decoration: none;
|
|
1223
|
-
color: var(--text-secondary);
|
|
1224
|
-
transition: background 0.15s;
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
.icon-strip-wt-item::before {
|
|
1228
|
-
content: "";
|
|
1229
|
-
position: absolute;
|
|
1230
|
-
width: 30px;
|
|
1231
|
-
height: 30px;
|
|
1232
|
-
border-radius: 8px;
|
|
1233
|
-
background: var(--bg-alt);
|
|
1234
|
-
opacity: 0.7;
|
|
1235
|
-
transition: opacity 0.15s, background 0.15s;
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
.icon-strip-wt-item:hover::before {
|
|
1239
|
-
opacity: 1;
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
.icon-strip-wt-item.active::before {
|
|
1243
|
-
background: var(--accent);
|
|
1244
|
-
opacity: 1;
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
.icon-strip-wt-item.active {
|
|
1248
|
-
color: #fff;
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
.icon-strip-wt-item .wt-branch-abbrev {
|
|
1252
|
-
font-size: 11px;
|
|
1253
|
-
font-weight: 600;
|
|
1254
|
-
letter-spacing: -0.5px;
|
|
1255
|
-
pointer-events: none;
|
|
1256
|
-
position: relative;
|
|
1257
|
-
z-index: 1;
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
/* Disabled/inaccessible worktree */
|
|
1261
|
-
.icon-strip-wt-item.wt-disabled {
|
|
1262
|
-
opacity: 0.35;
|
|
1263
|
-
cursor: not-allowed;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
.icon-strip-wt-item.wt-disabled::after {
|
|
1267
|
-
content: "\1F6AB";
|
|
1268
|
-
position: absolute;
|
|
1269
|
-
font-size: 14px;
|
|
1270
|
-
z-index: 3;
|
|
1271
|
-
filter: grayscale(0.3);
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
/* Group add button */
|
|
1275
|
-
.icon-strip-group-add {
|
|
1276
|
-
width: 30px;
|
|
1277
|
-
height: 30px;
|
|
1278
|
-
border-radius: 8px;
|
|
1279
|
-
border: 1.5px dashed var(--border);
|
|
1280
|
-
background: transparent;
|
|
1281
|
-
color: var(--text-dimmer);
|
|
1282
|
-
font-size: 16px;
|
|
1283
|
-
font-weight: 400;
|
|
1284
|
-
cursor: pointer;
|
|
1285
|
-
display: flex;
|
|
1286
|
-
align-items: center;
|
|
1287
|
-
justify-content: center;
|
|
1288
|
-
margin: 2px 0 4px 0;
|
|
1289
|
-
transition: border-color 0.15s, color 0.15s, background 0.15s;
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
.icon-strip-group-add:hover {
|
|
1293
|
-
border-color: var(--accent);
|
|
1294
|
-
color: var(--accent);
|
|
1295
|
-
background: rgba(var(--accent-rgb, 124, 58, 237), 0.08);
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
1147
|
/* --- Worktree creation modal --- */
|
|
1299
1148
|
.wt-modal-overlay {
|
|
1300
1149
|
position: fixed;
|
|
@@ -1409,45 +1258,6 @@ select.wt-modal-input {
|
|
|
1409
1258
|
cursor: not-allowed;
|
|
1410
1259
|
}
|
|
1411
1260
|
|
|
1412
|
-
/* --- Mobile worktree folder --- */
|
|
1413
|
-
.mobile-project-folder {
|
|
1414
|
-
display: flex;
|
|
1415
|
-
flex-direction: column;
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
.mobile-project-item.wt-item {
|
|
1419
|
-
padding-left: 28px;
|
|
1420
|
-
opacity: 0.85;
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
.mobile-project-item.wt-disabled {
|
|
1424
|
-
opacity: 0.35;
|
|
1425
|
-
cursor: not-allowed;
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
.mobile-folder-chevron {
|
|
1429
|
-
font-size: 8px;
|
|
1430
|
-
color: var(--text-dimmer);
|
|
1431
|
-
margin-left: auto;
|
|
1432
|
-
cursor: pointer;
|
|
1433
|
-
transition: transform 0.15s ease;
|
|
1434
|
-
padding: 4px;
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
.mobile-project-folder.collapsed .mobile-folder-chevron {
|
|
1438
|
-
transform: rotate(-90deg);
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
.mobile-folder-items {
|
|
1442
|
-
overflow: hidden;
|
|
1443
|
-
transition: max-height 0.2s ease;
|
|
1444
|
-
max-height: 500px;
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
.mobile-project-folder.collapsed .mobile-folder-items {
|
|
1448
|
-
max-height: 0;
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
1261
|
/* --- Per-project presence avatars --- */
|
|
1452
1262
|
/* --- Mobile: hide icon strip --- */
|
|
1453
1263
|
/* --- Skeleton loading placeholders --- */
|
|
@@ -160,6 +160,10 @@
|
|
|
160
160
|
background: rgba(var(--overlay-rgb), 0.06);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
.mobile-project-item.has-pending-perm {
|
|
164
|
+
animation: permShake 2s ease-in-out infinite;
|
|
165
|
+
}
|
|
166
|
+
|
|
163
167
|
.mobile-project-abbrev {
|
|
164
168
|
width: 32px;
|
|
165
169
|
height: 32px;
|
|
@@ -438,6 +442,22 @@
|
|
|
438
442
|
object-fit: cover;
|
|
439
443
|
}
|
|
440
444
|
|
|
445
|
+
/* No hover on touch: rest state stays dimmed, the active session shows color. */
|
|
446
|
+
.mobile-session-vendor-icon {
|
|
447
|
+
width: 14px;
|
|
448
|
+
height: 14px;
|
|
449
|
+
flex-shrink: 0;
|
|
450
|
+
border-radius: 3px;
|
|
451
|
+
object-fit: cover;
|
|
452
|
+
margin-right: 8px;
|
|
453
|
+
opacity: 0.5;
|
|
454
|
+
filter: grayscale(0.9) brightness(0.9);
|
|
455
|
+
}
|
|
456
|
+
.mobile-session-item.active .mobile-session-vendor-icon {
|
|
457
|
+
opacity: 1;
|
|
458
|
+
filter: none;
|
|
459
|
+
}
|
|
460
|
+
|
|
441
461
|
/* --- Chat filter bar (horizontal scroll chips) --- */
|
|
442
462
|
.mobile-chat-filter-bar {
|
|
443
463
|
display: flex;
|
|
@@ -835,6 +835,25 @@
|
|
|
835
835
|
contain: size layout;
|
|
836
836
|
}
|
|
837
837
|
|
|
838
|
+
/* Vendor badge stays nearly monochrome at rest so a long session list does
|
|
839
|
+
not read as a row of logos; hover or the active session restores color. */
|
|
840
|
+
.session-vendor-icon {
|
|
841
|
+
width: 13px;
|
|
842
|
+
height: 13px;
|
|
843
|
+
border-radius: 3px;
|
|
844
|
+
object-fit: cover;
|
|
845
|
+
vertical-align: -2px;
|
|
846
|
+
margin-right: 5px;
|
|
847
|
+
opacity: 0.45;
|
|
848
|
+
filter: grayscale(0.9) brightness(0.9);
|
|
849
|
+
transition: opacity 0.15s, filter 0.15s;
|
|
850
|
+
}
|
|
851
|
+
.session-item:hover .session-vendor-icon,
|
|
852
|
+
.session-item.active .session-vendor-icon {
|
|
853
|
+
opacity: 1;
|
|
854
|
+
filter: none;
|
|
855
|
+
}
|
|
856
|
+
|
|
838
857
|
.session-item-text {
|
|
839
858
|
flex: 1;
|
|
840
859
|
overflow: hidden;
|
|
@@ -272,6 +272,175 @@
|
|
|
272
272
|
transform: rotate(180deg);
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
.branch-chip {
|
|
276
|
+
display: inline-flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 4px;
|
|
279
|
+
min-width: 0;
|
|
280
|
+
max-width: 132px;
|
|
281
|
+
/* Optical alignment: the pill reads slightly high next to the 17px/800
|
|
282
|
+
project name, so nudge it down within the centered flex row. */
|
|
283
|
+
margin-top: 2px;
|
|
284
|
+
padding: 4px 7px;
|
|
285
|
+
border: 1px solid var(--border);
|
|
286
|
+
border-radius: 999px;
|
|
287
|
+
background: var(--bg-alt);
|
|
288
|
+
color: var(--text-secondary);
|
|
289
|
+
font: 600 11px/1.2 "Pretendard", system-ui, sans-serif;
|
|
290
|
+
cursor: pointer;
|
|
291
|
+
flex-shrink: 1;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.branch-chip.hidden,
|
|
295
|
+
.branch-chip-menu.hidden {
|
|
296
|
+
display: none;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.branch-chip:hover,
|
|
300
|
+
.branch-chip.open {
|
|
301
|
+
border-color: var(--text-dimmer);
|
|
302
|
+
color: var(--text);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.branch-chip > svg {
|
|
306
|
+
width: 12px;
|
|
307
|
+
height: 12px;
|
|
308
|
+
flex-shrink: 0;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
#branch-chip-label {
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
text-overflow: ellipsis;
|
|
314
|
+
white-space: nowrap;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.branch-chip-chevron {
|
|
318
|
+
transition: transform 0.15s;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.branch-chip.open .branch-chip-chevron {
|
|
322
|
+
transform: rotate(180deg);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.branch-chip-menu {
|
|
326
|
+
position: fixed;
|
|
327
|
+
z-index: 10020;
|
|
328
|
+
width: 250px;
|
|
329
|
+
padding: 6px;
|
|
330
|
+
border: 1px solid var(--border);
|
|
331
|
+
border-radius: 10px;
|
|
332
|
+
background: var(--bg);
|
|
333
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.branch-chip-row {
|
|
337
|
+
display: flex;
|
|
338
|
+
align-items: center;
|
|
339
|
+
border-radius: 7px;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.branch-chip-row:hover {
|
|
343
|
+
background: var(--bg-alt);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.branch-chip-row-main,
|
|
347
|
+
.branch-chip-row-action,
|
|
348
|
+
.branch-chip-new {
|
|
349
|
+
border: 0;
|
|
350
|
+
background: transparent;
|
|
351
|
+
color: var(--text-secondary);
|
|
352
|
+
font-family: inherit;
|
|
353
|
+
cursor: pointer;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.branch-chip-row-main {
|
|
357
|
+
min-width: 0;
|
|
358
|
+
flex: 1;
|
|
359
|
+
display: flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
gap: 7px;
|
|
362
|
+
padding: 8px;
|
|
363
|
+
text-align: left;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.branch-chip-row-main:disabled {
|
|
367
|
+
opacity: 0.38;
|
|
368
|
+
cursor: not-allowed;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.branch-chip-row-main svg,
|
|
372
|
+
.branch-chip-row-action svg,
|
|
373
|
+
.branch-chip-new svg {
|
|
374
|
+
width: 14px;
|
|
375
|
+
height: 14px;
|
|
376
|
+
flex-shrink: 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.branch-chip-row-label {
|
|
380
|
+
overflow: hidden;
|
|
381
|
+
text-overflow: ellipsis;
|
|
382
|
+
white-space: nowrap;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.branch-chip-row.current .branch-chip-row-label {
|
|
386
|
+
color: var(--text);
|
|
387
|
+
font-weight: 700;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.branch-chip-row-main > .lucide-check {
|
|
391
|
+
margin-left: auto;
|
|
392
|
+
color: var(--accent);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.branch-chip-processing {
|
|
396
|
+
width: 7px;
|
|
397
|
+
height: 7px;
|
|
398
|
+
border-radius: 50%;
|
|
399
|
+
background: var(--success, #23a55a);
|
|
400
|
+
flex-shrink: 0;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.branch-chip-pending {
|
|
404
|
+
min-width: 17px;
|
|
405
|
+
padding: 1px 4px;
|
|
406
|
+
border-radius: 8px;
|
|
407
|
+
background: var(--danger, #e74c3c);
|
|
408
|
+
color: #fff;
|
|
409
|
+
font-size: 9px;
|
|
410
|
+
text-align: center;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.branch-chip-row-action {
|
|
414
|
+
display: flex;
|
|
415
|
+
padding: 7px;
|
|
416
|
+
opacity: 0;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.branch-chip-row:hover .branch-chip-row-action,
|
|
420
|
+
.branch-chip-row-action:focus-visible {
|
|
421
|
+
opacity: 0.7;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.branch-chip-row-action:hover {
|
|
425
|
+
color: var(--danger, #e74c3c);
|
|
426
|
+
opacity: 1;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.branch-chip-new {
|
|
430
|
+
width: 100%;
|
|
431
|
+
display: flex;
|
|
432
|
+
align-items: center;
|
|
433
|
+
gap: 7px;
|
|
434
|
+
margin-top: 5px;
|
|
435
|
+
padding: 9px 8px 7px;
|
|
436
|
+
border-top: 1px solid var(--border-subtle);
|
|
437
|
+
text-align: left;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.branch-chip-new:hover {
|
|
441
|
+
color: var(--text);
|
|
442
|
+
}
|
|
443
|
+
|
|
275
444
|
.project-rename-input {
|
|
276
445
|
width: 100%;
|
|
277
446
|
font-family: "Pretendard", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
package/lib/public/index.html
CHANGED
|
@@ -210,6 +210,12 @@
|
|
|
210
210
|
<span class="title-bar-project-name" id="title-bar-project-name"></span>
|
|
211
211
|
<i data-lucide="chevron-down" class="title-bar-chevron"></i>
|
|
212
212
|
</button>
|
|
213
|
+
<button id="branch-chip" class="branch-chip hidden" type="button" aria-label="Switch branch" aria-expanded="false" aria-haspopup="menu">
|
|
214
|
+
<i data-lucide="git-branch"></i>
|
|
215
|
+
<span id="branch-chip-label"></span>
|
|
216
|
+
<i data-lucide="chevron-down" class="branch-chip-chevron"></i>
|
|
217
|
+
</button>
|
|
218
|
+
<div id="branch-chip-menu" class="branch-chip-menu hidden"></div>
|
|
213
219
|
<span id="sidebar-presence" class="sidebar-presence"></span>
|
|
214
220
|
<button id="sidebar-toggle-btn" class="sidebar-collapse-btn" title="Collapse sidebar"><i data-lucide="panel-left-close"></i></button>
|
|
215
221
|
</div>
|
|
@@ -106,14 +106,6 @@ export function blinkIO() {
|
|
|
106
106
|
var sessionDot = document.querySelector(".session-item.active .session-processing") ||
|
|
107
107
|
document.querySelector(".mate-session-item.active .session-processing");
|
|
108
108
|
if (sessionDot) sessionDot.classList.add("io");
|
|
109
|
-
// If active project is a worktree, also blink the parent project dot
|
|
110
|
-
var activeWt = document.querySelector("#icon-strip-projects .icon-strip-wt-item.active");
|
|
111
|
-
var parentDot = null;
|
|
112
|
-
if (activeWt) {
|
|
113
|
-
var group = activeWt.closest(".icon-strip-group");
|
|
114
|
-
if (group) parentDot = group.querySelector(".folder-header .icon-strip-status");
|
|
115
|
-
if (parentDot) parentDot.classList.add("io");
|
|
116
|
-
}
|
|
117
109
|
// Mobile chat chip dot + mobile session dot
|
|
118
110
|
var mobileChipDot = null;
|
|
119
111
|
var _s = store.snap();
|
|
@@ -132,7 +124,6 @@ export function blinkIO() {
|
|
|
132
124
|
var sd = document.querySelector(".session-item.active .session-processing.io") ||
|
|
133
125
|
document.querySelector(".mate-session-item.active .session-processing.io");
|
|
134
126
|
if (sd) sd.classList.remove("io");
|
|
135
|
-
if (parentDot) parentDot.classList.remove("io");
|
|
136
127
|
if (mobileChipDot) mobileChipDot.classList.remove("io");
|
|
137
128
|
if (mobileSessionDot) mobileSessionDot.classList.remove("io");
|
|
138
129
|
}, 80);
|
|
@@ -152,7 +143,7 @@ export function blinkSessionDot(sessionId) {
|
|
|
152
143
|
export function updateCrossProjectBlink() {
|
|
153
144
|
if (crossProjectBlinkTimer) { clearTimeout(crossProjectBlinkTimer); crossProjectBlinkTimer = null; }
|
|
154
145
|
function doBlink() {
|
|
155
|
-
var dots = document.querySelectorAll("#icon-strip-projects .icon-strip-item:not(.active) .icon-strip-status.processing, #icon-strip-
|
|
146
|
+
var dots = document.querySelectorAll("#icon-strip-projects .icon-strip-item:not(.active) .icon-strip-status.processing, #icon-strip-users .icon-strip-mate:not(.active) .icon-strip-status.processing");
|
|
156
147
|
// Also blink mobile chat chip dots (same icon-strip-status class inside chips)
|
|
157
148
|
var mobileDots = document.querySelectorAll(".mobile-chat-chip .icon-strip-status.processing");
|
|
158
149
|
var allDots = [];
|
|
@@ -619,6 +619,7 @@ export function showHomeHub() {
|
|
|
619
619
|
// anywhere via the persistent FAB (#clay-fab), not embedded here.
|
|
620
620
|
if (store.get('dmMode')) exitDmMode();
|
|
621
621
|
homeHubVisible = true;
|
|
622
|
+
store.set({ homeHubVisible: true });
|
|
622
623
|
homeHub.classList.remove("hidden");
|
|
623
624
|
// Show close button only if there's a project to return to
|
|
624
625
|
if (hubCloseBtn) {
|
|
@@ -652,6 +653,7 @@ export function showHomeHub() {
|
|
|
652
653
|
export function hideHomeHub() {
|
|
653
654
|
if (!homeHubVisible) return;
|
|
654
655
|
homeHubVisible = false;
|
|
656
|
+
store.set({ homeHubVisible: false });
|
|
655
657
|
homeHub.classList.add("hidden");
|
|
656
658
|
stopTipRotation();
|
|
657
659
|
var mobileHome = document.getElementById("mobile-home-btn");
|
|
@@ -47,7 +47,7 @@ import { setStatus } from './app-connection.js';
|
|
|
47
47
|
import { handleWhatsNewState, handleWhatsNewSeenResult, setKnownEntries as setWhatsNewKnownEntries } from './whats-new.js';
|
|
48
48
|
import { closeArticle as closeWhatsNewArticle } from './whats-new-article.js';
|
|
49
49
|
import { getModelEffortLevels, accumulateUsage, updateUsagePanel, accumulateContext, updateContextPanel, renderCtxPopover, updateStatusPanel } from './app-panels.js';
|
|
50
|
-
import { updateProjectList, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
|
|
50
|
+
import { updateProjectList, updateTitleBarProjectIdentity, resetClientState, showUpdateAvailable, handleRemoveProjectCheckResult, handleRemoveProjectResult, handleBrowseDirResult, handleAddProjectResult, handleCloneProgress } from './app-projects.js';
|
|
51
51
|
import { updateHistorySentinel, prependOlderHistory } from './app-header.js';
|
|
52
52
|
import { hideHomeHub, handleHubSchedules } from './app-home-hub.js';
|
|
53
53
|
import { openDm, enterDmMode, exitDmMode, handleMateCreatedInApp, updateMateIconStatus, appendDmMessage, showDmTypingIndicator, buildMateInterviewPrompt } from './app-dm.js';
|
|
@@ -82,8 +82,7 @@ export function processMessage(msg) {
|
|
|
82
82
|
// Override title bar with mate name and re-apply color
|
|
83
83
|
var _mdn = (store.get('dmTargetUser').displayName || "New Mate");
|
|
84
84
|
if (headerTitleEl) headerTitleEl.textContent = _mdn;
|
|
85
|
-
|
|
86
|
-
if (_tbpn) _tbpn.textContent = _mdn;
|
|
85
|
+
updateTitleBarProjectIdentity(_mdn, null);
|
|
87
86
|
var _mc2 = (store.get('dmTargetUser').profile && store.get('dmTargetUser').profile.avatarColor) || store.get('dmTargetUser').avatarColor || "#7c3aed";
|
|
88
87
|
var _tbc2 = document.querySelector(".title-bar-content");
|
|
89
88
|
if (_tbc2) { _tbc2.style.background = _mc2; _tbc2.classList.add("mate-dm-active"); }
|
|
@@ -296,8 +295,7 @@ export function processMessage(msg) {
|
|
|
296
295
|
if (store.get('dmMode') && store.get('dmTargetUser') && store.get('dmTargetUser').isMate) {
|
|
297
296
|
var _mateDN = store.get('dmTargetUser').displayName || "New Mate";
|
|
298
297
|
headerTitleEl.textContent = _mateDN;
|
|
299
|
-
|
|
300
|
-
if (tbProjectName) tbProjectName.textContent = _mateDN;
|
|
298
|
+
updateTitleBarProjectIdentity(_mateDN, null);
|
|
301
299
|
// Re-apply mate title bar styling (may be lost during project switch)
|
|
302
300
|
var _mc = (store.get('dmTargetUser').profile && store.get('dmTargetUser').profile.avatarColor) || store.get('dmTargetUser').avatarColor || "#7c3aed";
|
|
303
301
|
var _tbc = document.querySelector(".title-bar-content");
|
|
@@ -305,8 +303,7 @@ export function processMessage(msg) {
|
|
|
305
303
|
document.body.classList.add("mate-dm-active");
|
|
306
304
|
} else {
|
|
307
305
|
headerTitleEl.textContent = store.get('projectName');
|
|
308
|
-
|
|
309
|
-
if (tbProjectName) tbProjectName.textContent = msg.title || store.get('projectName');
|
|
306
|
+
updateTitleBarProjectIdentity(msg.title || store.get('projectName'), null);
|
|
310
307
|
}
|
|
311
308
|
updatePageTitle();
|
|
312
309
|
if (msg.version) {
|