claude-simple 0.2.2 → 0.2.3
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/dist/{app.0.2.2.min.js → app.0.2.3.min.js} +87 -84
- package/dist/index.html +2 -2
- package/dist/{style.0.2.2.min.css → style.0.2.3.min.css} +33 -7
- package/package.json +1 -1
- package/public/index.html +2 -2
- package/public/shell/dashboard.js +64 -1
- package/public/shell/templates.js +15 -12
- package/public/shell.js +28 -11
- package/public/style.css +32 -6
- package/public/sw.js +2 -2
|
@@ -266,7 +266,70 @@ export function updateRecentSessionsList(sessions) {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
export function closeRecentMenu() {
|
|
269
|
-
$('recent-menu')
|
|
269
|
+
const menu = $('recent-menu');
|
|
270
|
+
if (menu) {
|
|
271
|
+
menu.classList.add('hidden');
|
|
272
|
+
menu.classList.remove('recent-menu-open');
|
|
273
|
+
// clear inline placement for next open
|
|
274
|
+
menu.style.top = '';
|
|
275
|
+
menu.style.left = '';
|
|
276
|
+
menu.style.right = '';
|
|
277
|
+
menu.style.width = '';
|
|
278
|
+
menu.style.maxHeight = '';
|
|
279
|
+
}
|
|
280
|
+
$('recent-menu-backdrop')?.classList.add('hidden');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Place the panel under the topbar with position:fixed so it is never clipped
|
|
285
|
+
* by #app / #topbar overflow (the previous top-full + fixed combo put it
|
|
286
|
+
* below the viewport on phones — looked like “no response”).
|
|
287
|
+
*/
|
|
288
|
+
export function positionRecentMenu() {
|
|
289
|
+
const menu = $('recent-menu');
|
|
290
|
+
const topbar = $('topbar');
|
|
291
|
+
if (!menu || !topbar) return;
|
|
292
|
+
const rect = topbar.getBoundingClientRect();
|
|
293
|
+
const gap = 6;
|
|
294
|
+
const top = Math.round(rect.bottom + gap);
|
|
295
|
+
const side = window.matchMedia('(max-width: 640px)').matches ? 8 : null;
|
|
296
|
+
menu.style.top = `${top}px`;
|
|
297
|
+
if (side != null) {
|
|
298
|
+
menu.style.left = `${side}px`;
|
|
299
|
+
menu.style.right = `${side}px`;
|
|
300
|
+
} else {
|
|
301
|
+
// desktop: align under the “最近” button when possible
|
|
302
|
+
const btn = $('btn-recent-sessions');
|
|
303
|
+
const br = btn?.getBoundingClientRect();
|
|
304
|
+
if (br) {
|
|
305
|
+
const width = Math.min(320, window.innerWidth - 16);
|
|
306
|
+
let left = br.left;
|
|
307
|
+
if (left + width > window.innerWidth - 8) left = window.innerWidth - width - 8;
|
|
308
|
+
if (left < 8) left = 8;
|
|
309
|
+
menu.style.left = `${Math.round(left)}px`;
|
|
310
|
+
menu.style.right = 'auto';
|
|
311
|
+
menu.style.width = `${width}px`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const maxH = Math.max(160, window.innerHeight - top - 12);
|
|
315
|
+
menu.style.maxHeight = `${Math.min(maxH, Math.round(window.innerHeight * 0.7))}px`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function openRecentMenu(sessions) {
|
|
319
|
+
const menu = $('recent-menu');
|
|
320
|
+
if (!menu) return;
|
|
321
|
+
renderRecentSessionsMenu(sessions ?? getDashboardSessions());
|
|
322
|
+
menu.classList.remove('hidden');
|
|
323
|
+
menu.classList.add('recent-menu-open');
|
|
324
|
+
positionRecentMenu();
|
|
325
|
+
$('recent-menu-backdrop')?.classList.remove('hidden');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function toggleRecentMenu(sessions) {
|
|
329
|
+
const menu = $('recent-menu');
|
|
330
|
+
if (!menu) return;
|
|
331
|
+
if (menu.classList.contains('hidden')) openRecentMenu(sessions);
|
|
332
|
+
else closeRecentMenu();
|
|
270
333
|
}
|
|
271
334
|
|
|
272
335
|
/** Topbar quick-jump: last N sessions by updatedAt. */
|
|
@@ -61,24 +61,15 @@ export const AppShell = (opts = {}) => {
|
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
63
|
<div id="recent-menu-wrap" class="relative flex-shrink-0">
|
|
64
|
-
<button type="button" id="btn-recent-sessions" class="btn btn-ghost btn-xs border border-base-300 gap-1"
|
|
65
|
-
title="最近会话 / 快速跳转">
|
|
64
|
+
<button type="button" id="btn-recent-sessions" class="btn btn-ghost btn-xs border border-base-300 gap-1 min-h-8 px-2"
|
|
65
|
+
title="最近会话 / 快速跳转" aria-haspopup="listbox" aria-expanded="false">
|
|
66
66
|
<span>最近</span>
|
|
67
67
|
<span class="text-[10px] opacity-50">▾</span>
|
|
68
68
|
</button>
|
|
69
|
-
<div id="recent-menu" class="hidden absolute left-0 top-full mt-1 z-50 w-80 max-h-[min(24rem,70vh)] overflow-y-auto
|
|
70
|
-
rounded-lg border border-base-300 bg-base-100 shadow-xl p-2">
|
|
71
|
-
<div class="flex items-center justify-between px-1 pb-1.5 mb-1 border-b border-base-300 sticky top-0 bg-base-100 z-[1]">
|
|
72
|
-
<span class="text-[10px] uppercase tracking-wide text-base-content/45 font-semibold">Recent sessions</span>
|
|
73
|
-
<span id="recent-menu-count" class="text-[10px] text-base-content/35 font-mono"></span>
|
|
74
|
-
</div>
|
|
75
|
-
<div id="recent-menu-list" class="flex flex-col gap-0.5"></div>
|
|
76
|
-
<p id="recent-menu-empty" class="text-xs text-base-content/40 px-1 py-2 hidden">暂无最近会话</p>
|
|
77
|
-
</div>
|
|
78
69
|
</div>
|
|
79
70
|
<span id="topbar-project" class="text-sm text-base-content/50 flex-1 truncate min-w-0">Select a session</span>
|
|
80
71
|
<span id="conn-dot" class="w-2 h-2 rounded-full bg-base-content/30 flex-shrink-0" title="连接状态"></span>
|
|
81
|
-
<div class="flex gap-2">
|
|
72
|
+
<div class="flex gap-2 topbar-actions">
|
|
82
73
|
<button id="btn-refresh-conn" class="btn btn-ghost btn-xs border border-base-300" title="重新连接并同步">↻</button>
|
|
83
74
|
<button id="btn-pwa-install" class="btn btn-ghost btn-xs border border-base-300 hidden" title="安装到主屏幕">安装</button>
|
|
84
75
|
<button id="btn-meta-agent" class="btn btn-ghost btn-xs border border-primary/40 text-primary" title="Meta Agent — 报告 / 问答 / VLM">✦ Agent</button>
|
|
@@ -88,6 +79,18 @@ export const AppShell = (opts = {}) => {
|
|
|
88
79
|
<button id="btn-logout" class="btn btn-ghost btn-xs border border-base-300">Sign out</button>
|
|
89
80
|
</div>
|
|
90
81
|
</div>
|
|
82
|
+
<!-- Fixed panel + backdrop: siblings of topbar so flex layout never clips them -->
|
|
83
|
+
<div id="recent-menu-backdrop" class="hidden fixed inset-0 z-[55] bg-black/40" aria-hidden="true"></div>
|
|
84
|
+
<div id="recent-menu" class="hidden fixed z-[60] w-80 max-h-[min(24rem,70vh)] overflow-y-auto
|
|
85
|
+
rounded-lg border border-base-300 bg-base-100 shadow-xl p-2"
|
|
86
|
+
role="listbox" aria-label="最近会话">
|
|
87
|
+
<div class="flex items-center justify-between px-1 pb-1.5 mb-1 border-b border-base-300 sticky top-0 bg-base-100 z-[1]">
|
|
88
|
+
<span class="text-[10px] uppercase tracking-wide text-base-content/45 font-semibold">最近会话</span>
|
|
89
|
+
<span id="recent-menu-count" class="text-[10px] text-base-content/35 font-mono"></span>
|
|
90
|
+
</div>
|
|
91
|
+
<div id="recent-menu-list" class="flex flex-col gap-0.5"></div>
|
|
92
|
+
<p id="recent-menu-empty" class="text-xs text-base-content/40 px-1 py-2 hidden">暂无最近会话</p>
|
|
93
|
+
</div>
|
|
91
94
|
<!-- Hub: only when no remembered machine (or last one offline) -->
|
|
92
95
|
<div id="machine-picker" class="hidden fixed inset-0 z-[60] bg-base-100 flex items-center justify-center p-4">
|
|
93
96
|
<div class="w-full max-w-md">
|
package/public/shell.js
CHANGED
|
@@ -26,7 +26,7 @@ import { openMetaAgent, toggleMetaAgent } from './agent-panel.js';
|
|
|
26
26
|
import { AuthScreen, AppShell } from './shell/templates.js';
|
|
27
27
|
import {
|
|
28
28
|
updateDashboard, shiftCalMonth, setSelectedCalDate, getDashboardSessions,
|
|
29
|
-
|
|
29
|
+
openRecentMenu, toggleRecentMenu, closeRecentMenu, positionRecentMenu,
|
|
30
30
|
} from './shell/dashboard.js';
|
|
31
31
|
import {
|
|
32
32
|
loadAllSessions, loadWorkspaces, renderSessionList, syncSidebarChrome,
|
|
@@ -570,26 +570,43 @@ export function initShell(opts = {}) {
|
|
|
570
570
|
}
|
|
571
571
|
});
|
|
572
572
|
delegate.on('click', '#btn-recent-sessions', e => {
|
|
573
|
+
e.preventDefault();
|
|
573
574
|
e.stopPropagation();
|
|
574
575
|
closeMachineMenu();
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
576
|
+
toggleRecentMenu(getDashboardSessions());
|
|
577
|
+
const open = !$('recent-menu')?.classList.contains('hidden');
|
|
578
|
+
const btn = $('btn-recent-sessions');
|
|
579
|
+
if (btn) btn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
580
|
+
});
|
|
581
|
+
delegate.on('click', '#recent-menu-backdrop', e => {
|
|
582
|
+
e.preventDefault();
|
|
583
|
+
e.stopPropagation();
|
|
584
|
+
closeRecentMenu();
|
|
585
|
+
$('btn-recent-sessions')?.setAttribute('aria-expanded', 'false');
|
|
583
586
|
});
|
|
584
587
|
document.addEventListener('click', e => {
|
|
585
588
|
const machineWrap = $('machine-menu-wrap');
|
|
586
589
|
if (machineWrap && !machineWrap.contains(e.target)) closeMachineMenu();
|
|
587
|
-
const
|
|
588
|
-
|
|
590
|
+
const menu = $('recent-menu');
|
|
591
|
+
const btn = $('btn-recent-sessions');
|
|
592
|
+
const t = e.target;
|
|
593
|
+
// Menu is portaled (fixed) outside the button wrap — check both
|
|
594
|
+
if (menu && !menu.classList.contains('hidden')) {
|
|
595
|
+
if (menu.contains(t) || btn?.contains(t)) return;
|
|
596
|
+
closeRecentMenu();
|
|
597
|
+
btn?.setAttribute('aria-expanded', 'false');
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
// Keep panel glued under topbar on rotate / URL bar show-hide
|
|
601
|
+
window.addEventListener('resize', () => {
|
|
602
|
+
if ($('recent-menu') && !$('recent-menu').classList.contains('hidden')) {
|
|
603
|
+
positionRecentMenu();
|
|
604
|
+
}
|
|
589
605
|
});
|
|
590
606
|
// After picking a session from the topbar menu, close it (row click also resumes).
|
|
591
607
|
delegate.on('click', '#recent-menu [data-session-id]', () => {
|
|
592
608
|
closeRecentMenu();
|
|
609
|
+
$('btn-recent-sessions')?.setAttribute('aria-expanded', 'false');
|
|
593
610
|
});
|
|
594
611
|
|
|
595
612
|
delegate.on('click', '#btn-edit-project-notes, #project-goal-text, #project-notes-text', () => {
|
package/public/style.css
CHANGED
|
@@ -931,17 +931,43 @@ html.pwa-standalone .ma-panel {
|
|
|
931
931
|
transition: background-color 99999s ease-in-out 0s;
|
|
932
932
|
}
|
|
933
933
|
|
|
934
|
-
/* Recent sessions topbar
|
|
934
|
+
/* Recent sessions panel (position set in JS under topbar; never use top:100% with fixed) */
|
|
935
935
|
#recent-menu {
|
|
936
936
|
min-width: 16rem;
|
|
937
|
+
overscroll-behavior: contain;
|
|
938
|
+
-webkit-overflow-scrolling: touch;
|
|
939
|
+
}
|
|
940
|
+
#recent-menu.recent-menu-open {
|
|
941
|
+
display: block; /* beat .hidden if both race */
|
|
937
942
|
}
|
|
938
943
|
@media (max-width: 640px) {
|
|
939
|
-
#recent-menu
|
|
940
|
-
|
|
941
|
-
left: 0.5rem;
|
|
942
|
-
right: 0.5rem;
|
|
944
|
+
#recent-menu {
|
|
945
|
+
min-width: 0;
|
|
943
946
|
width: auto;
|
|
944
|
-
|
|
947
|
+
}
|
|
948
|
+
/* Keep 最近 + hamburger reachable; tuck secondary actions */
|
|
949
|
+
#topbar {
|
|
950
|
+
overflow: visible;
|
|
951
|
+
gap: 0.35rem;
|
|
952
|
+
}
|
|
953
|
+
#topbar .topbar-actions {
|
|
954
|
+
gap: 0.25rem;
|
|
955
|
+
flex-shrink: 0;
|
|
956
|
+
}
|
|
957
|
+
#btn-theme,
|
|
958
|
+
#btn-settings,
|
|
959
|
+
#btn-logout,
|
|
960
|
+
#btn-pwa-install {
|
|
961
|
+
display: none !important;
|
|
962
|
+
}
|
|
963
|
+
#topbar-project {
|
|
964
|
+
font-size: 11px;
|
|
965
|
+
max-width: 30vw;
|
|
966
|
+
}
|
|
967
|
+
#recent-menu-list .recent-menu-item {
|
|
968
|
+
min-height: 44px; /* comfortable touch targets */
|
|
969
|
+
padding-top: 0.5rem;
|
|
970
|
+
padding-bottom: 0.5rem;
|
|
945
971
|
}
|
|
946
972
|
}
|
|
947
973
|
#chat-input:focus,
|
package/public/sw.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* Agent UI service worker — cache shell assets only.
|
|
2
2
|
* Never intercepts WebSocket or mutates API semantics beyond offline fallback.
|
|
3
3
|
* Bump CACHE when shipping UI that must invalidate old shells. */
|
|
4
|
-
const CACHE = 'agent-ui-shell-
|
|
4
|
+
const CACHE = 'agent-ui-shell-v7';
|
|
5
5
|
const PRECACHE = [
|
|
6
6
|
'/',
|
|
7
7
|
'/index.html',
|
|
8
8
|
'/manifest.webmanifest',
|
|
9
|
-
'/style.css?v=ui-
|
|
9
|
+
'/style.css?v=ui-9',
|
|
10
10
|
'/style.css',
|
|
11
11
|
'/app.js',
|
|
12
12
|
'/icons/icon-192.png',
|