codedash-app 1.1.1 → 1.2.0
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/package.json +1 -1
- package/src/frontend/app.js +33 -1
- package/src/frontend/index.html +6 -0
- package/src/frontend/styles.css +46 -0
- package/src/server.js +38 -0
- package/src/terminals.js +1 -1
package/package.json
CHANGED
package/src/frontend/app.js
CHANGED
|
@@ -829,7 +829,7 @@ function launchSession(sessionId, tool, project) {
|
|
|
829
829
|
|
|
830
830
|
function copyResume(sessionId, tool) {
|
|
831
831
|
var cmd = tool === 'codex'
|
|
832
|
-
? 'codex
|
|
832
|
+
? 'codex resume ' + sessionId
|
|
833
833
|
: 'claude --resume ' + sessionId;
|
|
834
834
|
navigator.clipboard.writeText(cmd).then(function() {
|
|
835
835
|
showToast('Copied: ' + cmd);
|
|
@@ -1099,12 +1099,44 @@ document.addEventListener('keydown', function(e) {
|
|
|
1099
1099
|
}
|
|
1100
1100
|
});
|
|
1101
1101
|
|
|
1102
|
+
// ── Update check ──────────────────────────────────────────────
|
|
1103
|
+
|
|
1104
|
+
async function checkForUpdates() {
|
|
1105
|
+
try {
|
|
1106
|
+
var resp = await fetch('/api/version');
|
|
1107
|
+
var data = await resp.json();
|
|
1108
|
+
if (data.updateAvailable) {
|
|
1109
|
+
var banner = document.getElementById('updateBanner');
|
|
1110
|
+
var text = document.getElementById('updateText');
|
|
1111
|
+
if (banner && text) {
|
|
1112
|
+
text.textContent = 'Update available: v' + data.current + ' → v' + data.latest;
|
|
1113
|
+
banner.style.display = 'flex';
|
|
1114
|
+
banner.dataset.cmd = 'npm update -g codedash-app && codedash run';
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
} catch {}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function copyUpdate() {
|
|
1121
|
+
var banner = document.getElementById('updateBanner');
|
|
1122
|
+
var cmd = banner ? banner.dataset.cmd : 'npm update -g codedash-app';
|
|
1123
|
+
navigator.clipboard.writeText(cmd).then(function() {
|
|
1124
|
+
showToast('Copied: ' + cmd);
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
function dismissUpdate() {
|
|
1129
|
+
var banner = document.getElementById('updateBanner');
|
|
1130
|
+
if (banner) banner.style.display = 'none';
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1102
1133
|
// ── Initialization ─────────────────────────────────────────────
|
|
1103
1134
|
|
|
1104
1135
|
(function init() {
|
|
1105
1136
|
// Load data
|
|
1106
1137
|
loadSessions();
|
|
1107
1138
|
loadTerminals();
|
|
1139
|
+
checkForUpdates();
|
|
1108
1140
|
|
|
1109
1141
|
// Apply saved theme
|
|
1110
1142
|
var savedTheme = localStorage.getItem('codedash-theme') || 'dark';
|
package/src/frontend/index.html
CHANGED
|
@@ -111,6 +111,12 @@
|
|
|
111
111
|
|
|
112
112
|
<div class="toast" id="toast"></div>
|
|
113
113
|
|
|
114
|
+
<div class="update-banner" id="updateBanner" style="display:none">
|
|
115
|
+
<span id="updateText"></span>
|
|
116
|
+
<button class="update-btn" onclick="copyUpdate()">Copy update command</button>
|
|
117
|
+
<button class="update-dismiss" onclick="dismissUpdate()">×</button>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
114
120
|
<script>{{SCRIPT}}</script>
|
|
115
121
|
</body>
|
|
116
122
|
</html>
|
package/src/frontend/styles.css
CHANGED
|
@@ -1370,6 +1370,52 @@ body {
|
|
|
1370
1370
|
color: #fff;
|
|
1371
1371
|
}
|
|
1372
1372
|
|
|
1373
|
+
/* ── Update banner ──────────────────────────────────────────── */
|
|
1374
|
+
|
|
1375
|
+
.update-banner {
|
|
1376
|
+
position: fixed;
|
|
1377
|
+
top: 0;
|
|
1378
|
+
left: 200px;
|
|
1379
|
+
right: 0;
|
|
1380
|
+
background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
|
|
1381
|
+
color: #fff;
|
|
1382
|
+
padding: 10px 20px;
|
|
1383
|
+
display: flex;
|
|
1384
|
+
align-items: center;
|
|
1385
|
+
gap: 12px;
|
|
1386
|
+
font-size: 13px;
|
|
1387
|
+
z-index: 200;
|
|
1388
|
+
animation: slideDown 0.3s ease;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
@keyframes slideDown {
|
|
1392
|
+
from { transform: translateY(-100%); }
|
|
1393
|
+
to { transform: translateY(0); }
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
.update-btn {
|
|
1397
|
+
background: rgba(255,255,255,0.2);
|
|
1398
|
+
border: 1px solid rgba(255,255,255,0.3);
|
|
1399
|
+
color: #fff;
|
|
1400
|
+
padding: 4px 12px;
|
|
1401
|
+
border-radius: 6px;
|
|
1402
|
+
font-size: 12px;
|
|
1403
|
+
cursor: pointer;
|
|
1404
|
+
white-space: nowrap;
|
|
1405
|
+
}
|
|
1406
|
+
.update-btn:hover { background: rgba(255,255,255,0.3); }
|
|
1407
|
+
|
|
1408
|
+
.update-dismiss {
|
|
1409
|
+
background: none;
|
|
1410
|
+
border: none;
|
|
1411
|
+
color: rgba(255,255,255,0.7);
|
|
1412
|
+
font-size: 18px;
|
|
1413
|
+
cursor: pointer;
|
|
1414
|
+
margin-left: auto;
|
|
1415
|
+
padding: 0 4px;
|
|
1416
|
+
}
|
|
1417
|
+
.update-dismiss:hover { color: #fff; }
|
|
1418
|
+
|
|
1373
1419
|
/* ── List view ──────────────────────────────────────────────── */
|
|
1374
1420
|
|
|
1375
1421
|
.list-view {
|
package/src/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// HTTP server + API routes
|
|
2
2
|
const http = require('http');
|
|
3
|
+
const https = require('https');
|
|
3
4
|
const { URL } = require('url');
|
|
4
5
|
const { exec } = require('child_process');
|
|
5
6
|
const { loadSessions, loadSessionDetail, deleteSession, getGitCommits, exportSessionMarkdown } = require('./data');
|
|
@@ -103,6 +104,18 @@ function startServer(port, openBrowser = true) {
|
|
|
103
104
|
json(res, commits);
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
// ── Version check ────────────────────────
|
|
108
|
+
else if (req.method === 'GET' && pathname === '/api/version') {
|
|
109
|
+
const pkg = require('../package.json');
|
|
110
|
+
const current = pkg.version;
|
|
111
|
+
// Fetch latest from npm registry
|
|
112
|
+
fetchLatestVersion(pkg.name).then(latest => {
|
|
113
|
+
json(res, { current, latest, updateAvailable: latest && latest !== current && isNewer(latest, current) });
|
|
114
|
+
}).catch(() => {
|
|
115
|
+
json(res, { current, latest: null, updateAvailable: false });
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
106
119
|
// ── 404 ─────────────────────────────────
|
|
107
120
|
else {
|
|
108
121
|
res.writeHead(404);
|
|
@@ -139,4 +152,29 @@ function readBody(req, cb) {
|
|
|
139
152
|
req.on('end', () => cb(body));
|
|
140
153
|
}
|
|
141
154
|
|
|
155
|
+
// ── npm version check ───────────────────
|
|
156
|
+
function fetchLatestVersion(packageName) {
|
|
157
|
+
return new Promise((resolve, reject) => {
|
|
158
|
+
https.get(`https://registry.npmjs.org/${packageName}/latest`, { timeout: 5000 }, (res) => {
|
|
159
|
+
let data = '';
|
|
160
|
+
res.on('data', chunk => data += chunk);
|
|
161
|
+
res.on('end', () => {
|
|
162
|
+
try {
|
|
163
|
+
resolve(JSON.parse(data).version);
|
|
164
|
+
} catch { reject(); }
|
|
165
|
+
});
|
|
166
|
+
}).on('error', reject);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function isNewer(latest, current) {
|
|
171
|
+
const l = latest.split('.').map(Number);
|
|
172
|
+
const c = current.split('.').map(Number);
|
|
173
|
+
for (let i = 0; i < 3; i++) {
|
|
174
|
+
if ((l[i] || 0) > (c[i] || 0)) return true;
|
|
175
|
+
if ((l[i] || 0) < (c[i] || 0)) return false;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
142
180
|
module.exports = { startServer };
|
package/src/terminals.js
CHANGED
|
@@ -70,7 +70,7 @@ function openInTerminal(sessionId, tool, flags, projectDir, terminalId) {
|
|
|
70
70
|
let cmd;
|
|
71
71
|
|
|
72
72
|
if (tool === 'codex') {
|
|
73
|
-
cmd = `codex
|
|
73
|
+
cmd = `codex resume ${sessionId}`;
|
|
74
74
|
} else {
|
|
75
75
|
cmd = `claude --resume ${sessionId}`;
|
|
76
76
|
if (skipPerms) cmd += ' --dangerously-skip-permissions';
|