-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.js
More file actions
90 lines (79 loc) · 3.85 KB
/
app.js
File metadata and controls
90 lines (79 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Claude Code Chat Browser — Entry module (router + theme + window registrations).
// Route modules live in sessions.js, projects.js, search.js, export.js.
// Shared helpers live in shared/utils.js, shared/markdown.js, shared/theme.js.
import { state } from './shared/state.js';
import { toggleSidebar, closeSidebar, loadingBar } from './shared/utils.js';
import { HLJS_THEME_SHEETS, applyHljsTheme, applyTheme, toggleTheme, setWorkspaceMode } from './shared/theme.js';
import { showProjects } from './projects.js';
import { showWorkspace, loadSession, selectSession, copyAll } from './sessions.js';
import { showSearchPage, doSearch } from './search.js';
import { bulkExport, downloadSession } from './export.js';
// ==================== Router ====================
function safeDecode(str) {
try { return decodeURIComponent(str); } catch { return null; }
}
function handleRoute() {
if (state.navInProgress) return;
window.scrollTo(0, 0);
const hash = window.location.hash || '#';
if (hash.startsWith('#project/')) {
const parts = hash.slice(9);
const slashIdx = parts.indexOf('/');
if (slashIdx > 0) {
const project = safeDecode(parts.slice(0, slashIdx));
if (!project) { showProjects(); return; }
const sessionId = parts.slice(slashIdx + 1);
if (state.currentProject === project && state.cachedSessions.length > 0 && document.getElementById('sidebar')) {
document.querySelectorAll('.sidebar-item').forEach(el => el.classList.remove('active'));
const el = document.getElementById(`sidebar-${sessionId}`);
if (el) { el.classList.add('active'); el.scrollIntoView({ block: 'nearest' }); }
loadSession(project, sessionId);
} else {
showWorkspace(project, sessionId);
}
} else {
const project = safeDecode(parts);
if (!project) { showProjects(); return; }
showWorkspace(project);
}
} else if (hash === '#search') {
showSearchPage();
} else {
showProjects();
}
}
// ==================== Bootstrap ====================
document.addEventListener('DOMContentLoaded', () => {
applyTheme(localStorage.getItem('theme') || 'dark');
const yearEl = document.getElementById('footer-year');
if (yearEl) yearEl.textContent = new Date().getFullYear();
handleRoute();
window.addEventListener('hashchange', handleRoute);
const overlay = document.createElement('div');
overlay.className = 'sidebar-overlay';
overlay.id = 'sidebar-overlay';
overlay.addEventListener('click', closeSidebar);
document.body.appendChild(overlay);
const topBtn = document.createElement('button');
topBtn.className = 'scroll-top-btn';
topBtn.id = 'scroll-top-btn';
topBtn.textContent = '\u2191';
topBtn.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' }));
document.body.appendChild(topBtn);
window.addEventListener('scroll', () => topBtn.classList.toggle('show', window.scrollY > 400));
});
// ==================== Window registrations for inline HTML handlers ====================
// Functions listed here are called from onclick="..." attributes in index.html or
// in HTML strings generated by route modules. ES module scope does not expose
// identifiers to the global scope automatically, so they must be registered on window.
window.showProjects = showProjects;
window.showSearchPage = showSearchPage;
window.toggleTheme = toggleTheme;
window.toggleSidebar = toggleSidebar;
window.selectSession = selectSession;
window.copyAll = copyAll;
window.downloadSession = downloadSession;
window.bulkExport = bulkExport;
window.doSearch = doSearch;
// Keep HLJS_THEME_SHEETS accessible for test_hljs_theme_consistency.py (source-level check)
export { HLJS_THEME_SHEETS };