glad-web 1.0.43 → 1.0.45
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/README.md +2 -0
- package/README.zh-CN.md +2 -0
- package/lib/claude/structured-session.js +10 -5
- package/lib/codex/image-store.js +1 -2
- package/lib/codex/structured-session.js +24 -73
- package/lib/commands/web.js +43 -5
- package/lib/server/routes/providers.js +0 -12
- package/lib/session/file-attachment-store.js +168 -0
- package/lib/session/session-manager.js +75 -23
- package/lib/web/claude.js +28 -11
- package/lib/web/codex.js +49 -23
- package/lib/web/composer.js +263 -34
- package/lib/web/core.js +22 -6
- package/lib/web/git.js +53 -51
- package/lib/web/gitgraph.js +8 -8
- package/lib/web/index.html +94 -36
- package/lib/web/layout.js +72 -0
- package/lib/web/notifications.js +1 -0
- package/lib/web/session.js +6 -20
- package/lib/web/shell.js +3 -0
- package/lib/web/styles.css +375 -11
- package/lib/web/theme.js +60 -0
- package/lib/web/timed-inputs.js +9 -16
- package/package.json +1 -1
package/lib/web/git.js
CHANGED
|
@@ -51,23 +51,23 @@
|
|
|
51
51
|
let addCount = 0;
|
|
52
52
|
let subCount = 0;
|
|
53
53
|
for (const line of block.lines) {
|
|
54
|
-
let color = '
|
|
55
|
-
if (line.startsWith('+') && !line.startsWith('+++')) { color = '
|
|
56
|
-
else if (line.startsWith('-') && !line.startsWith('---')) { color = '
|
|
57
|
-
else if (line.startsWith('@@')) { color = '
|
|
58
|
-
else if (line.startsWith('diff') || line.startsWith('index') || line.startsWith('commit') || line.startsWith('Author') || line.startsWith('Date')) color = '
|
|
54
|
+
let color = 'var(--git-diff-text)', bg = 'transparent', borderLeft = '2px solid transparent';
|
|
55
|
+
if (line.startsWith('+') && !line.startsWith('+++')) { color = 'var(--git-add-text)'; bg = 'var(--git-add-bg)'; borderLeft = '2px solid var(--git-add-text)'; addCount++; }
|
|
56
|
+
else if (line.startsWith('-') && !line.startsWith('---')) { color = 'var(--git-del-text)'; bg = 'var(--git-del-bg)'; borderLeft = '2px solid var(--git-del-text)'; subCount++; }
|
|
57
|
+
else if (line.startsWith('@@')) { color = 'var(--git-hunk-text)'; bg = 'var(--git-hunk-bg)'; }
|
|
58
|
+
else if (line.startsWith('diff') || line.startsWith('index') || line.startsWith('commit') || line.startsWith('Author') || line.startsWith('Date')) color = 'var(--text)';
|
|
59
59
|
|
|
60
60
|
blockContent += `<div style="color:${color}; background:${bg}; border-left:${borderLeft}; padding:2px 8px; white-space:pre-wrap; word-break:break-all;">${line.replace(/</g, '<').replace(/>/g, '>') || ' '}</div>`;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const isOpen = block.name === 'Commit Details';
|
|
64
|
-
const statHTML = block.name !== 'Commit Details' ? `<span style="margin-left: 12px; font-family: monospace; font-size: 12px;"><span style="color
|
|
64
|
+
const statHTML = block.name !== 'Commit Details' ? `<span style="margin-left: 12px; font-family: monospace; font-size: 12px;"><span style="color:var(--git-add-text);">+${addCount}</span> <span style="color:var(--git-del-text); margin-left:6px;">-${subCount}</span></span>` : '';
|
|
65
65
|
diffHTML += `
|
|
66
|
-
<details ${isOpen ? 'open' : ''}
|
|
67
|
-
<summary
|
|
66
|
+
<details ${isOpen ? 'open' : ''} class="git-diff-panel">
|
|
67
|
+
<summary class="git-diff-summary">
|
|
68
68
|
${block.name === 'Commit Details' ? '📝 ' : '📄 '}${block.name.replace(/</g, '<').replace(/>/g, '>')}${statHTML}
|
|
69
69
|
</summary>
|
|
70
|
-
<div
|
|
70
|
+
<div class="git-diff-body">
|
|
71
71
|
${blockContent}
|
|
72
72
|
</div>
|
|
73
73
|
</details>
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
function renderCommitDiffFullView() {
|
|
87
87
|
const content = document.getElementById('git-content');
|
|
88
88
|
let html = `
|
|
89
|
-
<div style="display:flex; align-items:center; background: var(--card-bg); padding: 12px 14px; border-bottom: 1px solid
|
|
89
|
+
<div style="display:flex; align-items:center; background: var(--card-bg); padding: 12px 14px; border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 10;">
|
|
90
90
|
<button class="icon-btn" onclick="switchGitTab('graph')" style="color: var(--primary); margin-right: 12px; font-weight:600; font-size:14px; display:flex; align-items:center;">
|
|
91
91
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg> Back
|
|
92
92
|
</button>
|
|
@@ -150,11 +150,11 @@
|
|
|
150
150
|
let colorStyle = '';
|
|
151
151
|
let badgeHtml = '';
|
|
152
152
|
if (f.gitStatus) {
|
|
153
|
-
let color = '
|
|
153
|
+
let color = 'var(--text)';
|
|
154
154
|
let label = f.gitStatus.trim();
|
|
155
|
-
if (label.includes('U') || label.includes('?')) { colorStyle = 'color:
|
|
156
|
-
else if (label.includes('M')) { colorStyle = 'color:
|
|
157
|
-
else if (label.includes('D')) { colorStyle = 'color:
|
|
155
|
+
if (label.includes('U') || label.includes('?')) { colorStyle = 'color: var(--git-add-text);'; color = 'var(--git-add-text)'; if(label === '??') label = 'U'; }
|
|
156
|
+
else if (label.includes('M')) { colorStyle = 'color: var(--git-modified-text);'; color = 'var(--git-modified-text)'; }
|
|
157
|
+
else if (label.includes('D')) { colorStyle = 'color: var(--git-del-text);'; color = 'var(--git-del-text)'; }
|
|
158
158
|
badgeHtml = `<span style="color:${color}; font-weight:700; font-size:10px; border:1px solid ${color}; padding:1px 4px; border-radius:3px; opacity:0.7; margin-left: auto;">${label}</span>`;
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -232,11 +232,10 @@
|
|
|
232
232
|
files.forEach((f, idx) => {
|
|
233
233
|
const encodedPath = encodePathValue(f.path);
|
|
234
234
|
const escapedPath = escapeHtml(f.path);
|
|
235
|
-
let
|
|
235
|
+
let statusClass = 'modified';
|
|
236
236
|
let label = f.status;
|
|
237
|
-
if (label.includes('
|
|
238
|
-
else if (label.includes('
|
|
239
|
-
else if (label.includes('D')) { color = '#f87171'; }
|
|
237
|
+
if (label.includes('A') || label === '??') { statusClass = 'added'; if(label === '??') label = 'U'; }
|
|
238
|
+
else if (label.includes('D')) { statusClass = 'deleted'; }
|
|
240
239
|
const isUntracked = f.status === '??';
|
|
241
240
|
const hasStaged = !isUntracked && f.status[0] && f.status[0] !== ' ';
|
|
242
241
|
const hasUnstaged = !isUntracked && f.status[1] && f.status[1] !== ' ';
|
|
@@ -245,14 +244,14 @@
|
|
|
245
244
|
if (statsMap[f.path]) {
|
|
246
245
|
const { added, removed } = statsMap[f.path];
|
|
247
246
|
if (added > 0 || removed > 0) {
|
|
248
|
-
statHTML = `<span style="margin-left: 12px; font-family: monospace; font-size: 12px; white-space: nowrap;"><span style="color
|
|
247
|
+
statHTML = `<span style="margin-left: 12px; font-family: monospace; font-size: 12px; white-space: nowrap;"><span style="color:var(--git-add-text);">+${added}</span> <span style="color:var(--git-del-text); margin-left:6px;">-${removed}</span></span>`;
|
|
249
248
|
}
|
|
250
249
|
}
|
|
251
250
|
|
|
252
|
-
html += `<div
|
|
253
|
-
<div onclick="toggleInlineDiff('${encodedPath}', 'inline-diff-${idx}', ${!!hasStaged}, ${!!hasUnstaged}, ${isUntracked})"
|
|
254
|
-
<div
|
|
255
|
-
<span
|
|
251
|
+
html += `<div class="git-change-card">
|
|
252
|
+
<div class="git-change-header" onclick="toggleInlineDiff('${encodedPath}', 'inline-diff-${idx}', ${!!hasStaged}, ${!!hasUnstaged}, ${isUntracked})">
|
|
253
|
+
<div class="git-change-path">📄 ${escapedPath}${statHTML}</div>
|
|
254
|
+
<span class="git-status-badge ${statusClass}">${label}</span>
|
|
256
255
|
</div>
|
|
257
256
|
<div id="inline-diff-${idx}" style="display: none;" data-loaded="false"></div>
|
|
258
257
|
</div>`;
|
|
@@ -335,26 +334,26 @@
|
|
|
335
334
|
});
|
|
336
335
|
|
|
337
336
|
if (!currentFileDiff && !currentFileContent) {
|
|
338
|
-
container.innerHTML = `<div style="padding: 10px; color:
|
|
337
|
+
container.innerHTML = `<div style="padding: 10px; color: var(--git-del-text); font-size: 12px; text-align:center;">No diff available</div>`;
|
|
339
338
|
return;
|
|
340
339
|
}
|
|
341
340
|
|
|
342
341
|
let blockContent = '';
|
|
343
342
|
currentFileDiff.split('\n').forEach(line => {
|
|
344
|
-
let color = '
|
|
345
|
-
if (line.startsWith('+') && !line.startsWith('+++')) { color = '
|
|
346
|
-
else if (line.startsWith('-') && !line.startsWith('---')) { color = '
|
|
347
|
-
else if (line.startsWith('@@')) { color = '
|
|
343
|
+
let color = 'var(--git-diff-text)', bg = 'transparent', borderLeft = '2px solid transparent';
|
|
344
|
+
if (line.startsWith('+') && !line.startsWith('+++')) { color = 'var(--git-add-text)'; bg = 'var(--git-add-bg)'; borderLeft = '2px solid var(--git-add-text)'; }
|
|
345
|
+
else if (line.startsWith('-') && !line.startsWith('---')) { color = 'var(--git-del-text)'; bg = 'var(--git-del-bg)'; borderLeft = '2px solid var(--git-del-text)'; }
|
|
346
|
+
else if (line.startsWith('@@')) { color = 'var(--git-hunk-text)'; bg = 'var(--git-hunk-bg)'; }
|
|
348
347
|
|
|
349
348
|
blockContent += `<div style="color:${color}; background:${bg}; border-left:${borderLeft}; padding:2px 8px; white-space:pre-wrap; word-break:break-all;">${escapeHtml(line) || ' '}</div>`;
|
|
350
349
|
});
|
|
351
350
|
|
|
352
351
|
container.dataset.loaded = 'true';
|
|
353
352
|
container.innerHTML = `
|
|
354
|
-
<div
|
|
353
|
+
<div class="git-inline-diff git-inline-diff-body">
|
|
355
354
|
${blockContent}
|
|
356
355
|
</div>
|
|
357
|
-
<div
|
|
356
|
+
<div class="git-inline-diff-footer">
|
|
358
357
|
<button onclick="showFileDetails(decodePathValue('${encodedPath}'), true, ${!!hasStaged}, ${!!hasUnstaged}, ${!!isUntracked})" style="background: var(--primary); border: none; color: #fff; padding: 6px 12px; border-radius: 4px; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;">
|
|
359
358
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>
|
|
360
359
|
View Full File
|
|
@@ -362,7 +361,7 @@
|
|
|
362
361
|
</div>
|
|
363
362
|
`;
|
|
364
363
|
} catch (e) {
|
|
365
|
-
container.innerHTML = `<div style="padding: 10px; color:
|
|
364
|
+
container.innerHTML = `<div style="padding: 10px; color: var(--git-del-text); font-size: 12px; text-align:center;">Error: ${e.message}</div>`;
|
|
366
365
|
}
|
|
367
366
|
};
|
|
368
367
|
|
|
@@ -404,7 +403,7 @@
|
|
|
404
403
|
function renderFileDetails() {
|
|
405
404
|
const content = document.getElementById('git-content');
|
|
406
405
|
let html = `
|
|
407
|
-
<div style="display:flex; align-items:center; background: var(--card-bg); padding: 12px 14px; border-bottom: 1px solid
|
|
406
|
+
<div style="display:flex; align-items:center; background: var(--card-bg); padding: 12px 14px; border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 10;">
|
|
408
407
|
<button class="icon-btn" onclick="switchGitTab(currentGitTab)" style="color: var(--primary); margin-right: 12px; font-weight:600; font-size:14px; display:flex; align-items:center; flex-shrink: 0;">
|
|
409
408
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg> Back
|
|
410
409
|
</button>
|
|
@@ -415,27 +414,27 @@
|
|
|
415
414
|
if (currentFileDiff && currentFileContent) {
|
|
416
415
|
html += `
|
|
417
416
|
<div style="display: flex; gap: 6px; flex-shrink: 0; align-items: center;">
|
|
418
|
-
<div
|
|
419
|
-
<button onclick="changeFontSize(-1)"
|
|
420
|
-
<button onclick="changeFontSize(0)"
|
|
421
|
-
<button onclick="changeFontSize(1)"
|
|
417
|
+
<div class="git-file-toolbar-group">
|
|
418
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(-1)" title="Zoom Out">A-</button>
|
|
419
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(0)" title="Reset Size">${currentFontSize}</button>
|
|
420
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(1)" title="Zoom In">A+</button>
|
|
422
421
|
</div>
|
|
423
|
-
<button
|
|
422
|
+
<button class="git-file-mode-button${currentFileMode === 'diff' ? ' active' : ''}" onclick="toggleFileMode()">
|
|
424
423
|
Diff
|
|
425
424
|
</button>
|
|
426
|
-
<button
|
|
425
|
+
<button class="git-file-mode-button${currentFileWrap ? ' active' : ''}" onclick="toggleFileWrap()">
|
|
427
426
|
Wrap
|
|
428
427
|
</button>
|
|
429
428
|
</div>`;
|
|
430
429
|
} else {
|
|
431
430
|
html += `
|
|
432
431
|
<div style="display: flex; gap: 6px; flex-shrink: 0; align-items: center;">
|
|
433
|
-
<div
|
|
434
|
-
<button onclick="changeFontSize(-1)"
|
|
435
|
-
<button onclick="changeFontSize(0)"
|
|
436
|
-
<button onclick="changeFontSize(1)"
|
|
432
|
+
<div class="git-file-toolbar-group">
|
|
433
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(-1)" title="Zoom Out">A-</button>
|
|
434
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(0)" title="Reset Size">${currentFontSize}</button>
|
|
435
|
+
<button class="git-file-toolbar-button" onclick="changeFontSize(1)" title="Zoom In">A+</button>
|
|
437
436
|
</div>
|
|
438
|
-
<button
|
|
437
|
+
<button class="git-file-mode-button${currentFileWrap ? ' active' : ''}" onclick="toggleFileWrap()">
|
|
439
438
|
Wrap
|
|
440
439
|
</button>
|
|
441
440
|
</div>`;
|
|
@@ -446,7 +445,7 @@
|
|
|
446
445
|
const wrapStyle = currentFileWrap ? 'white-space: pre-wrap; word-break: break-all;' : 'white-space: pre;';
|
|
447
446
|
const innerWrapStyle = currentFileWrap ? '' : 'min-width: max-content;';
|
|
448
447
|
html += `<div style="padding: 10px;">`;
|
|
449
|
-
html += `<div
|
|
448
|
+
html += `<div class="git-file-code" style="font-size:${currentFontSize}px; line-height:1.5; -webkit-text-size-adjust:100%; text-size-adjust:100%;">`;
|
|
450
449
|
html += `<div style="${innerWrapStyle}">`;
|
|
451
450
|
|
|
452
451
|
let mergedLines = [];
|
|
@@ -505,20 +504,20 @@
|
|
|
505
504
|
}
|
|
506
505
|
|
|
507
506
|
mergedLines.forEach(item => {
|
|
508
|
-
let color = '
|
|
507
|
+
let color = 'var(--git-diff-text)', bg = 'transparent', borderLeft = '2px solid transparent';
|
|
509
508
|
let prefix = ' ';
|
|
510
|
-
if (item.type === 'added') { color = '
|
|
511
|
-
else if (item.type === 'deleted') { color = '
|
|
509
|
+
if (item.type === 'added') { color = 'var(--git-add-text)'; bg = 'var(--git-add-bg)'; borderLeft = '2px solid var(--git-add-text)'; prefix = '+'; }
|
|
510
|
+
else if (item.type === 'deleted') { color = 'var(--git-del-text)'; bg = 'var(--git-del-bg)'; borderLeft = '2px solid var(--git-del-text)'; prefix = '-'; }
|
|
512
511
|
else if (item.type === 'raw') {
|
|
513
|
-
if (item.text.startsWith('+') && !item.text.startsWith('+++')) { color = '
|
|
514
|
-
else if (item.text.startsWith('-') && !item.text.startsWith('---')) { color = '
|
|
515
|
-
else if (item.text.startsWith('@@')) { color = '
|
|
512
|
+
if (item.text.startsWith('+') && !item.text.startsWith('+++')) { color = 'var(--git-add-text)'; bg = 'var(--git-add-bg)'; borderLeft = '2px solid var(--git-add-text)'; }
|
|
513
|
+
else if (item.text.startsWith('-') && !item.text.startsWith('---')) { color = 'var(--git-del-text)'; bg = 'var(--git-del-bg)'; borderLeft = '2px solid var(--git-del-text)'; }
|
|
514
|
+
else if (item.text.startsWith('@@')) { color = 'var(--git-hunk-text)'; bg = 'var(--git-hunk-bg)'; }
|
|
516
515
|
prefix = '';
|
|
517
516
|
}
|
|
518
517
|
|
|
519
518
|
const renderedText = item.type === 'raw' ? item.text : `${prefix} ${item.text}`;
|
|
520
519
|
html += `<div style="color:${color}; background:${bg}; border-left:${borderLeft}; padding: 0 12px 0 8px; display:flex;">`;
|
|
521
|
-
html += `<div
|
|
520
|
+
html += `<div class="git-line-number">${item.lineNum || ''}</div>`;
|
|
522
521
|
html += `<div style="flex:1; min-width:0; ${wrapStyle}">${escapeHtml(renderedText) || ' '}</div>`;
|
|
523
522
|
html += `</div>`;
|
|
524
523
|
});
|
|
@@ -531,3 +530,6 @@
|
|
|
531
530
|
refreshSessionsNow();
|
|
532
531
|
document.addEventListener('visibilitychange', refreshSessionsNow);
|
|
533
532
|
});
|
|
533
|
+
window.addEventListener('glad-theme-change', () => {
|
|
534
|
+
if (document.getElementById('git-view').classList.contains('active')) switchGitTab(currentGitTab);
|
|
535
|
+
});
|
package/lib/web/gitgraph.js
CHANGED
|
@@ -74,10 +74,10 @@ class GitGraphRenderer {
|
|
|
74
74
|
rowDiv.style.display = 'flex';
|
|
75
75
|
rowDiv.style.alignItems = 'center';
|
|
76
76
|
rowDiv.style.height = this.rowHeight + 'px';
|
|
77
|
-
rowDiv.style.borderBottom = '1px solid
|
|
77
|
+
rowDiv.style.borderBottom = '1px solid var(--line)';
|
|
78
78
|
rowDiv.style.position = 'relative';
|
|
79
79
|
rowDiv.style.cursor = 'pointer';
|
|
80
|
-
rowDiv.onmouseover = () => rowDiv.style.backgroundColor = '
|
|
80
|
+
rowDiv.onmouseover = () => rowDiv.style.backgroundColor = 'var(--surface-soft)';
|
|
81
81
|
rowDiv.onmouseout = () => rowDiv.style.backgroundColor = 'transparent';
|
|
82
82
|
|
|
83
83
|
const canvas = document.createElement('canvas');
|
|
@@ -102,7 +102,7 @@ class GitGraphRenderer {
|
|
|
102
102
|
contentDiv.style.overflow = 'hidden';
|
|
103
103
|
|
|
104
104
|
const msgSpan = document.createElement('span');
|
|
105
|
-
msgSpan.style.color = '
|
|
105
|
+
msgSpan.style.color = 'var(--text)';
|
|
106
106
|
msgSpan.style.fontSize = '13px';
|
|
107
107
|
msgSpan.style.fontWeight = '500';
|
|
108
108
|
msgSpan.style.overflow = 'hidden';
|
|
@@ -160,18 +160,18 @@ class GitGraphRenderer {
|
|
|
160
160
|
el.remove();
|
|
161
161
|
});
|
|
162
162
|
|
|
163
|
-
rowDiv.style.backgroundColor = '
|
|
163
|
+
rowDiv.style.backgroundColor = 'var(--surface-soft)';
|
|
164
164
|
|
|
165
165
|
const detailsDiv = document.createElement('div');
|
|
166
166
|
detailsDiv.className = 'gitgraph-details-view';
|
|
167
|
-
detailsDiv.style.backgroundColor = '
|
|
167
|
+
detailsDiv.style.backgroundColor = 'var(--surface)';
|
|
168
168
|
detailsDiv.style.borderLeft = '2px solid ' + this.getColor(commit.col);
|
|
169
169
|
detailsDiv.style.padding = '16px';
|
|
170
170
|
detailsDiv.style.margin = '4px 0 4px ' + (canvasWidth) + 'px';
|
|
171
171
|
detailsDiv.style.borderRadius = '0 6px 6px 0';
|
|
172
172
|
detailsDiv.style.fontSize = '13px';
|
|
173
173
|
detailsDiv.style.color = 'var(--text)';
|
|
174
|
-
detailsDiv.style.boxShadow = 'inset 0 0 10px rgba(0,0,0,0.
|
|
174
|
+
detailsDiv.style.boxShadow = 'inset 0 0 10px rgba(0,0,0,0.12)';
|
|
175
175
|
|
|
176
176
|
let detailsHTML = `
|
|
177
177
|
<div style="display:flex; justify-content:space-between; margin-bottom:12px;">
|
|
@@ -189,7 +189,7 @@ class GitGraphRenderer {
|
|
|
189
189
|
|
|
190
190
|
// Add diff placeholder
|
|
191
191
|
detailsHTML += `
|
|
192
|
-
<div style="border-top:1px solid
|
|
192
|
+
<div style="border-top:1px solid var(--line); padding-top:12px; margin-top:12px;">
|
|
193
193
|
<button onclick="window.loadCommitDiff('${commit.hash}')" style="background:var(--primary); border:none; color:#fff; padding:6px 12px; border-radius:4px; font-size:12px; cursor:pointer;">View Full Diff</button>
|
|
194
194
|
</div>
|
|
195
195
|
`;
|
|
@@ -269,7 +269,7 @@ class GitGraphRenderer {
|
|
|
269
269
|
ctx.fillStyle = this.getColor(commit.col);
|
|
270
270
|
ctx.fill();
|
|
271
271
|
ctx.lineWidth = 2;
|
|
272
|
-
ctx.strokeStyle = '#121212';
|
|
272
|
+
ctx.strokeStyle = getComputedStyle(document.documentElement).getPropertyValue('--surface').trim() || '#121212';
|
|
273
273
|
ctx.stroke();
|
|
274
274
|
}
|
|
275
275
|
|
package/lib/web/index.html
CHANGED
|
@@ -5,6 +5,17 @@
|
|
|
5
5
|
<title>Glad - AI Sessions</title>
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
7
7
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
8
|
+
<meta name="theme-color" content="#000000">
|
|
9
|
+
<script>
|
|
10
|
+
(() => {
|
|
11
|
+
const storedTheme = localStorage.getItem('glad-theme');
|
|
12
|
+
const theme = storedTheme === 'light' || storedTheme === 'dark'
|
|
13
|
+
? storedTheme
|
|
14
|
+
: (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
15
|
+
document.documentElement.dataset.theme = theme;
|
|
16
|
+
document.documentElement.style.backgroundColor = theme === 'dark' ? '#000000' : '#f5f6f8';
|
|
17
|
+
})();
|
|
18
|
+
</script>
|
|
8
19
|
<link rel="manifest" href="manifest.json">
|
|
9
20
|
<link rel="icon" type="image/svg+xml" href="logo.svg">
|
|
10
21
|
<link rel="apple-touch-icon" href="logo.svg">
|
|
@@ -13,6 +24,27 @@
|
|
|
13
24
|
</head>
|
|
14
25
|
<body>
|
|
15
26
|
<div id="debug-log"></div>
|
|
27
|
+
<svg class="app-icon-sprite" aria-hidden="true">
|
|
28
|
+
<symbol id="icon-model" viewBox="0 0 24 24"><path d="M4 7h10M18 7h2M4 17h2M10 17h10M14 4v6M6 14v6"/></symbol>
|
|
29
|
+
<symbol id="icon-usage" viewBox="0 0 24 24"><path d="M5 20V10M12 20V4M19 20v-7"/></symbol>
|
|
30
|
+
<symbol id="icon-context" viewBox="0 0 24 24"><path d="M12 3a9 9 0 1 0 9 9h-9V3Z"/><path d="M15 3.5A9 9 0 0 1 20.5 9H15V3.5Z"/></symbol>
|
|
31
|
+
<symbol id="icon-stop" viewBox="0 0 24 24"><rect x="6" y="6" width="12" height="12" rx="2"/></symbol>
|
|
32
|
+
<symbol id="icon-resume" viewBox="0 0 24 24"><path d="M4 12a8 8 0 1 0 2.3-5.7L4 8.6"/><path d="M4 4v4.6h4.6"/><path d="M12 8v4l3 2"/></symbol>
|
|
33
|
+
<symbol id="icon-fork" viewBox="0 0 24 24"><circle cx="6" cy="5" r="2"/><circle cx="18" cy="5" r="2"/><circle cx="12" cy="19" r="2"/><path d="M6 7v2c0 4 6 3 6 8M18 7v2c0 4-6 3-6 8"/></symbol>
|
|
34
|
+
<symbol id="icon-shield" viewBox="0 0 24 24"><path d="M12 3 20 6v5c0 5-3.4 8.2-8 10-4.6-1.8-8-5-8-10V6l8-3Z"/><path d="m9 12 2 2 4-4"/></symbol>
|
|
35
|
+
<symbol id="icon-status" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v6M12 7h.01"/></symbol>
|
|
36
|
+
<symbol id="icon-prompts" viewBox="0 0 24 24"><path d="M4 5h16v11H8l-4 4V5Z"/><path d="M8 9h8M8 12h5"/></symbol>
|
|
37
|
+
<symbol id="icon-compact" viewBox="0 0 24 24"><path d="m4 9 5 0 0-5M9 9 4 4M20 9h-5V4M15 9l5-5M4 15h5v5M9 15l-5 5M20 15h-5v5M15 15l5 5"/></symbol>
|
|
38
|
+
<symbol id="icon-sandbox" viewBox="0 0 24 24"><path d="m12 3 8 4.5v9L12 21l-8-4.5v-9L12 3Z"/><path d="m4.5 7.8 7.5 4.3 7.5-4.3M12 12v9"/></symbol>
|
|
39
|
+
<symbol id="icon-lock" viewBox="0 0 24 24"><rect x="5" y="10" width="14" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/></symbol>
|
|
40
|
+
<symbol id="icon-skills" viewBox="0 0 24 24"><path d="M9 3H4a1 1 0 0 0-1 1v5h2.5a2.5 2.5 0 1 1 0 5H3v5a1 1 0 0 0 1 1h5v-2.5a2.5 2.5 0 1 1 5 0V20h5a1 1 0 0 0 1-1v-5h-2.5a2.5 2.5 0 1 1 0-5H20V4a1 1 0 0 0-1-1h-5v2.5a2.5 2.5 0 1 1-5 0V3Z"/></symbol>
|
|
41
|
+
<symbol id="icon-image" viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="2"/><path d="m4 17 4.5-4 3.5 3 2.5-2 5.5 4"/></symbol>
|
|
42
|
+
<symbol id="icon-file" viewBox="0 0 24 24"><path d="M9 8.5 14.5 3a4 4 0 0 1 5.7 5.7L10.4 18.5a5.5 5.5 0 0 1-7.8-7.8l9.2-9.2"/><path d="m7 11 7-7a2 2 0 1 1 2.8 2.8l-9.1 9.1a2.5 2.5 0 0 1-3.5-3.5L12 4.6"/></symbol>
|
|
43
|
+
<symbol id="icon-schedule" viewBox="0 0 24 24"><circle cx="10.5" cy="13" r="7.5"/><path d="M10.5 9v4l2.5 1.5M18 3v6M15 6h6"/></symbol>
|
|
44
|
+
<symbol id="icon-calendar" viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 10h18"/></symbol>
|
|
45
|
+
</svg>
|
|
46
|
+
|
|
47
|
+
<div id="app-shell">
|
|
16
48
|
|
|
17
49
|
<!-- Lobby View -->
|
|
18
50
|
<div id="lobby-view" class="view active">
|
|
@@ -29,9 +61,7 @@
|
|
|
29
61
|
</button>
|
|
30
62
|
<button id="schedule-create-button" class="header-action-btn icon-only" type="button"
|
|
31
63
|
onclick="showScheduleModal()" title="New scheduled task" aria-label="New scheduled task">
|
|
32
|
-
<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
33
|
-
<circle cx="12" cy="13" r="8"></circle><path d="M12 9v4l2.5 1.5"></path><path d="M9 2h6"></path><path d="M12 2v3"></path>
|
|
34
|
-
</svg>
|
|
64
|
+
<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-calendar"></use></svg>
|
|
35
65
|
</button>
|
|
36
66
|
<button id="app-settings-button" class="header-action-btn icon-only" type="button"
|
|
37
67
|
onclick="openSettings()" title="Settings" aria-label="Settings">
|
|
@@ -55,6 +85,14 @@
|
|
|
55
85
|
</div>
|
|
56
86
|
</div>
|
|
57
87
|
|
|
88
|
+
<div id="sidebar-resizer" role="separator" aria-label="Resize session sidebar" aria-orientation="vertical"></div>
|
|
89
|
+
<main id="detail-pane">
|
|
90
|
+
<div id="detail-empty">
|
|
91
|
+
<img src="logo.svg" alt="" aria-hidden="true">
|
|
92
|
+
<h2>Select a session</h2>
|
|
93
|
+
<p>Choose an active session from the sidebar or create a new one.</p>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
58
96
|
<!-- Usage Dashboard View -->
|
|
59
97
|
<div id="usage-view" class="view">
|
|
60
98
|
<div class="usage-nav">
|
|
@@ -126,7 +164,6 @@
|
|
|
126
164
|
</button>
|
|
127
165
|
<div id="session-title">Terminal</div>
|
|
128
166
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
129
|
-
<button id="codex-terminal-switch" class="icon-btn" onclick="toggleCodexPresentation()" title="Switch Codex interface" style="display:none; color: var(--primary); font-size: 12px; font-weight: 700; background: rgba(0, 122, 255, 0.1); padding: 5px 9px; border-radius: 15px; gap: 4px;">TERM</button>
|
|
130
167
|
<button class="icon-btn" onclick="showHistory()" title="History" style="color: var(--primary); font-size: 12px; font-weight: 700; background: rgba(0, 122, 255, 0.1); padding: 5px 9px; border-radius: 15px; gap: 4px;">
|
|
131
168
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7"></path><polyline points="3 3 3 9 9 9"></polyline><path d="M12 7v5l3 2"></path></svg>
|
|
132
169
|
HIS
|
|
@@ -137,21 +174,23 @@
|
|
|
137
174
|
</button>
|
|
138
175
|
</div>
|
|
139
176
|
</div>
|
|
177
|
+
<div id="session-status-strip" aria-live="polite">
|
|
178
|
+
<div id="session-attention-rail"></div>
|
|
179
|
+
</div>
|
|
140
180
|
<div id="terminal-controls">
|
|
141
181
|
<div id="timed-tag-rail"></div>
|
|
182
|
+
<div id="composer-skill-prefix"></div>
|
|
142
183
|
<div id="input-row">
|
|
143
184
|
<textarea id="cmd-input" rows="1" placeholder="Type a message..."></textarea>
|
|
144
|
-
<button id="
|
|
145
|
-
<button id="send-btn">
|
|
146
|
-
|
|
185
|
+
<button id="attachment-btn" class="composer-action-btn" type="button" title="Attachment" aria-label="Attachment"><svg class="action-icon" aria-hidden="true"><use href="#icon-file"></use></svg></button>
|
|
186
|
+
<button id="schedule-send-btn" class="composer-action-btn" type="button" title="Schedule" aria-label="Schedule"><svg class="action-icon" aria-hidden="true"><use href="#icon-schedule"></use></svg></button>
|
|
187
|
+
<button id="send-btn" type="button" title="Send" aria-label="Send">
|
|
188
|
+
<svg class="action-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
|
|
147
189
|
</button>
|
|
148
190
|
</div>
|
|
149
191
|
<div id="attachment-strip" aria-live="polite"></div>
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
<button id="schedule-send-btn" class="composer-menu-btn" type="button" role="menuitem">Schedule send</button>
|
|
153
|
-
</div>
|
|
154
|
-
<input id="image-file-input" type="file" accept="image/png,image/jpeg,image/gif,image/webp" multiple hidden>
|
|
192
|
+
<input id="attachment-file-input" type="file" multiple hidden>
|
|
193
|
+
<div id="composer-action-tooltip" role="tooltip"></div>
|
|
155
194
|
<div id="claude-control-panel">
|
|
156
195
|
<div class="claude-control-rail">
|
|
157
196
|
<div class="claude-control-page primary">
|
|
@@ -166,13 +205,13 @@
|
|
|
166
205
|
<option value="xhigh">Extra high</option>
|
|
167
206
|
<option value="max">Max</option>
|
|
168
207
|
</select>
|
|
169
|
-
<button id="claude-model-picker-btn" class="claude-select claude-picker-btn" onclick="toggleClaudePicker('model')" title="Model and effort">Model</button>
|
|
208
|
+
<button id="claude-model-picker-btn" class="claude-select claude-picker-btn" onclick="toggleClaudePicker('model')" title="Model and effort" aria-label="Model and effort"><svg class="action-icon" aria-hidden="true"><use href="#icon-model"></use></svg><span class="action-label">Model</span></button>
|
|
170
209
|
</div>
|
|
171
|
-
<button id="claude-usage-btn" class="claude-ctrl-btn" onclick="requestClaudeUsage()" title="Show Claude usage">Usage</button>
|
|
172
|
-
<button id="claude-context-btn" class="claude-ctrl-btn" onclick="requestClaudeContext()" title="Show Claude context">Context</button>
|
|
173
|
-
<button id="claude-abort-btn" class="claude-ctrl-btn danger" onclick="abortClaudeSession()" title="Abort current Claude turn">Abort</button>
|
|
174
|
-
<button id="claude-resume-btn" class="claude-ctrl-btn primary" onclick="toggleClaudeResumePanel()" title="Choose a Claude session to resume">Resume</button>
|
|
175
|
-
<button id="claude-fork-btn" class="claude-ctrl-btn primary" onclick="toggleClaudeForkPanel()" title="Fork a Claude session">Fork</button>
|
|
210
|
+
<button id="claude-usage-btn" class="claude-ctrl-btn" onclick="requestClaudeUsage()" title="Show Claude usage" aria-label="Show Claude usage"><svg class="action-icon" aria-hidden="true"><use href="#icon-usage"></use></svg><span class="action-label">Usage</span></button>
|
|
211
|
+
<button id="claude-context-btn" class="claude-ctrl-btn" onclick="requestClaudeContext()" title="Show Claude context" aria-label="Show Claude context"><svg class="action-icon" aria-hidden="true"><use href="#icon-context"></use></svg><span class="action-label">Context</span></button>
|
|
212
|
+
<button id="claude-abort-btn" class="claude-ctrl-btn danger" onclick="abortClaudeSession()" title="Abort current Claude turn" aria-label="Abort current Claude turn"><svg class="action-icon" aria-hidden="true"><use href="#icon-stop"></use></svg><span class="action-label">Abort</span></button>
|
|
213
|
+
<button id="claude-resume-btn" class="claude-ctrl-btn primary" onclick="toggleClaudeResumePanel()" title="Choose a Claude session to resume" aria-label="Choose a Claude session to resume"><svg class="action-icon" aria-hidden="true"><use href="#icon-resume"></use></svg><span class="action-label">Resume</span></button>
|
|
214
|
+
<button id="claude-fork-btn" class="claude-ctrl-btn primary" onclick="toggleClaudeForkPanel()" title="Fork a Claude session" aria-label="Fork a Claude session"><svg class="action-icon" aria-hidden="true"><use href="#icon-fork"></use></svg><span class="action-label">Fork</span></button>
|
|
176
215
|
</div>
|
|
177
216
|
<div class="claude-control-page secondary">
|
|
178
217
|
<div class="claude-picker-wrap">
|
|
@@ -182,7 +221,7 @@
|
|
|
182
221
|
<option value="plan">Plan mode</option>
|
|
183
222
|
<option value="bypassPermissions">Bypass</option>
|
|
184
223
|
</select>
|
|
185
|
-
<button id="claude-permission-picker-btn" class="claude-select claude-picker-btn" onclick="toggleClaudePicker('permission')" title="Permission mode">Permission</button>
|
|
224
|
+
<button id="claude-permission-picker-btn" class="claude-select claude-picker-btn" onclick="toggleClaudePicker('permission')" title="Permission mode" aria-label="Permission mode"><svg class="action-icon" aria-hidden="true"><use href="#icon-shield"></use></svg><span class="action-label">Permission</span></button>
|
|
186
225
|
</div>
|
|
187
226
|
</div>
|
|
188
227
|
</div>
|
|
@@ -194,28 +233,28 @@
|
|
|
194
233
|
<div id="codex-control-panel">
|
|
195
234
|
<div id="codex-control-rail" class="codex-control-rail">
|
|
196
235
|
<div class="codex-control-page">
|
|
197
|
-
<button id="codex-model-btn" class="claude-ctrl-btn" onclick="toggleCodexModelPanel()" title="Model and effort">Model</button>
|
|
198
|
-
<button id="codex-status-btn" class="claude-ctrl-btn" onclick="requestCodexStatus()" title="Show Codex account, limits, and context status">Status</button>
|
|
199
|
-
<button id="codex-abort-btn" class="claude-ctrl-btn danger" onclick="abortCodexSession()" title="Abort current Codex turn">Abort</button>
|
|
200
|
-
<button id="codex-resume-btn" class="claude-ctrl-btn primary" onclick="toggleCodexResumePanel()" title="Resume a Codex thread">Resume</button>
|
|
201
|
-
<button id="codex-fork-btn" class="claude-ctrl-btn primary" onclick="toggleCodexForkPanel()" title="Fork a Codex thread in this conversation">Fork</button>
|
|
236
|
+
<button id="codex-model-btn" class="claude-ctrl-btn" onclick="toggleCodexModelPanel()" title="Model and effort" aria-label="Model and effort"><svg class="action-icon" aria-hidden="true"><use href="#icon-model"></use></svg><span class="action-label">Model</span></button>
|
|
237
|
+
<button id="codex-status-btn" class="claude-ctrl-btn" onclick="requestCodexStatus()" title="Show Codex account, limits, and context status" aria-label="Show Codex status"><svg class="action-icon" aria-hidden="true"><use href="#icon-status"></use></svg><span class="action-label">Status</span></button>
|
|
238
|
+
<button id="codex-abort-btn" class="claude-ctrl-btn danger" onclick="abortCodexSession()" title="Abort current Codex turn" aria-label="Abort current Codex turn"><svg class="action-icon" aria-hidden="true"><use href="#icon-stop"></use></svg><span class="action-label">Abort</span></button>
|
|
239
|
+
<button id="codex-resume-btn" class="claude-ctrl-btn primary" onclick="toggleCodexResumePanel()" title="Resume a Codex thread" aria-label="Resume a Codex thread"><svg class="action-icon" aria-hidden="true"><use href="#icon-resume"></use></svg><span class="action-label">Resume</span></button>
|
|
240
|
+
<button id="codex-fork-btn" class="claude-ctrl-btn primary" onclick="toggleCodexForkPanel()" title="Fork a Codex thread in this conversation" aria-label="Fork this Codex thread"><svg class="action-icon" aria-hidden="true"><use href="#icon-fork"></use></svg><span class="action-label">Fork</span></button>
|
|
202
241
|
</div>
|
|
203
242
|
<div class="codex-control-page">
|
|
204
|
-
<button id="codex-prompts-btn" class="claude-ctrl-btn" onclick="toggleCodexPromptPanel()" title="Browse and copy recent prompts">Prompts</button>
|
|
205
|
-
<button id="codex-compact-btn" class="claude-ctrl-btn" onclick="compactCodexContext()" title="Compact the current Codex context">Compact</button>
|
|
243
|
+
<button id="codex-prompts-btn" class="claude-ctrl-btn" onclick="toggleCodexPromptPanel()" title="Browse and copy recent prompts" aria-label="Browse recent prompts"><svg class="action-icon" aria-hidden="true"><use href="#icon-prompts"></use></svg><span class="action-label">Prompts</span></button>
|
|
244
|
+
<button id="codex-compact-btn" class="claude-ctrl-btn" onclick="compactCodexContext()" title="Compact the current Codex context" aria-label="Compact Codex context"><svg class="action-icon" aria-hidden="true"><use href="#icon-compact"></use></svg><span class="action-label">Compact</span></button>
|
|
206
245
|
<label class="codex-select-control" title="Sandbox mode">
|
|
207
|
-
<span class="codex-select-label" aria-hidden="true">Sandbox</span>
|
|
246
|
+
<span class="codex-select-label" aria-hidden="true"><svg class="action-icon"><use href="#icon-sandbox"></use></svg><span class="action-label">Sandbox</span></span>
|
|
208
247
|
<select id="codex-sandbox-select" class="codex-select" aria-label="Sandbox mode" onchange="updateCodexSettingsFromControls()">
|
|
209
248
|
<option value="default">Default</option><option value="read-only">Read only</option><option value="workspace-write">Workspace write</option><option value="danger-full-access">Full access</option>
|
|
210
249
|
</select>
|
|
211
250
|
</label>
|
|
212
251
|
<label class="codex-select-control" title="Approval policy">
|
|
213
|
-
<span class="codex-select-label" aria-hidden="true">Ask</span>
|
|
252
|
+
<span class="codex-select-label" aria-hidden="true"><svg class="action-icon"><use href="#icon-lock"></use></svg><span class="action-label">Ask</span></span>
|
|
214
253
|
<select id="codex-permission-select" class="codex-select" aria-label="Approval policy" onchange="updateCodexSettingsFromControls()">
|
|
215
254
|
<option value="default">Default</option><option value="untrusted">Untrusted</option><option value="on-request">On request</option><option value="never">Never ask</option>
|
|
216
255
|
</select>
|
|
217
256
|
</label>
|
|
218
|
-
<button id="codex-skills-btn" class="claude-ctrl-btn" onclick="toggleCodexSkillPanel()" title="Choose a skill for the next message">Skills</button>
|
|
257
|
+
<button id="codex-skills-btn" class="claude-ctrl-btn" onclick="toggleCodexSkillPanel()" title="Choose a skill for the next message" aria-label="Skills"><svg class="action-icon" aria-hidden="true"><use href="#icon-skills"></use></svg><span class="action-label">Skills</span></button>
|
|
219
258
|
</div>
|
|
220
259
|
</div>
|
|
221
260
|
<div id="codex-state-bar"></div>
|
|
@@ -269,13 +308,13 @@
|
|
|
269
308
|
|
|
270
309
|
<!-- Plain Text History View -->
|
|
271
310
|
<div id="history-view" class="view">
|
|
272
|
-
<div
|
|
273
|
-
<div
|
|
311
|
+
<div class="subview-nav">
|
|
312
|
+
<div class="subview-nav-row">
|
|
274
313
|
<button class="icon-btn" onclick="showTerminal()" style="color: var(--primary); font-size: 16px; font-weight: 500;">
|
|
275
314
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
|
276
315
|
Terminal
|
|
277
316
|
</button>
|
|
278
|
-
<div
|
|
317
|
+
<div class="subview-nav-title">History</div>
|
|
279
318
|
<button class="icon-btn" onclick="loadHistory()" title="Refresh" style="color: var(--primary); margin-right: 8px;">
|
|
280
319
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3-6.7"></path><polyline points="21 3 21 9 15 9"></polyline></svg>
|
|
281
320
|
</button>
|
|
@@ -293,13 +332,13 @@
|
|
|
293
332
|
|
|
294
333
|
<!-- Git View -->
|
|
295
334
|
<div id="git-view" class="view">
|
|
296
|
-
<div
|
|
297
|
-
<div
|
|
335
|
+
<div class="subview-nav">
|
|
336
|
+
<div class="subview-nav-row">
|
|
298
337
|
<button class="icon-btn" onclick="showTerminal()" style="color: var(--primary); font-size: 16px; font-weight: 500;">
|
|
299
338
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
|
300
339
|
Terminal
|
|
301
340
|
</button>
|
|
302
|
-
<div
|
|
341
|
+
<div class="subview-nav-title">Git Status</div>
|
|
303
342
|
<button class="icon-btn" onclick="loadGitStatus()" style="color: var(--primary);">
|
|
304
343
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3-6.7"></path><polyline points="21 3 21 9 15 9"></polyline></svg>
|
|
305
344
|
</button>
|
|
@@ -314,10 +353,13 @@
|
|
|
314
353
|
</div>
|
|
315
354
|
</div>
|
|
316
355
|
|
|
356
|
+
</main>
|
|
357
|
+
</div>
|
|
358
|
+
|
|
317
359
|
<!-- Tool Modal -->
|
|
318
360
|
<div id="modal-overlay" onclick="closeToolModal(event)">
|
|
319
361
|
<div id="tool-modal" onclick="event.stopPropagation()">
|
|
320
|
-
<
|
|
362
|
+
<div class="tool-modal-header"><h2>Create Session</h2><button class="icon-btn" type="button" onclick="closeToolModal()" aria-label="Close">×</button></div>
|
|
321
363
|
<div style="margin-bottom: 15px;">
|
|
322
364
|
<label style="display:block; margin-bottom: 8px; font-size: 14px; color: var(--text-dim);">Working Directory (Optional):</label>
|
|
323
365
|
<div style="margin-bottom: 8px; color: var(--text-dim); font-size: 12px; line-height: 1.4;">
|
|
@@ -355,6 +397,20 @@
|
|
|
355
397
|
</div>
|
|
356
398
|
<button class="icon-btn settings-close" type="button" onclick="closeSettings()" aria-label="Close">×</button>
|
|
357
399
|
</div>
|
|
400
|
+
<section class="settings-section" aria-labelledby="appearance-settings-title">
|
|
401
|
+
<div class="settings-section-label" id="appearance-settings-title">Appearance</div>
|
|
402
|
+
<div class="theme-choice" role="group" aria-label="Color theme">
|
|
403
|
+
<button id="theme-light-btn" type="button" onclick="setGladTheme('light')" aria-pressed="false">
|
|
404
|
+
<span class="theme-swatch light" aria-hidden="true"></span>
|
|
405
|
+
Light
|
|
406
|
+
</button>
|
|
407
|
+
<button id="theme-dark-btn" type="button" onclick="setGladTheme('dark')" aria-pressed="false">
|
|
408
|
+
<span class="theme-swatch dark" aria-hidden="true"></span>
|
|
409
|
+
Dark
|
|
410
|
+
</button>
|
|
411
|
+
</div>
|
|
412
|
+
<p class="settings-theme-help">Glad follows your system until you choose a theme.</p>
|
|
413
|
+
</section>
|
|
358
414
|
<section class="settings-section" aria-labelledby="notifications-settings-title">
|
|
359
415
|
<div class="settings-section-label" id="notifications-settings-title">Notifications</div>
|
|
360
416
|
<div class="settings-provider-header">
|
|
@@ -441,8 +497,10 @@
|
|
|
441
497
|
|
|
442
498
|
<script defer src="vendor/xterm.js"></script>
|
|
443
499
|
<script defer src="vendor/xterm-addon-fit.js"></script>
|
|
500
|
+
<script src="theme.js"></script>
|
|
444
501
|
<script src="gitgraph.js"></script>
|
|
445
502
|
<script src="core.js"></script>
|
|
503
|
+
<script src="layout.js"></script>
|
|
446
504
|
<script src="notifications.js"></script>
|
|
447
505
|
<script src="claude.js"></script>
|
|
448
506
|
<script src="schedules.js"></script>
|