claude-code-memory-explorer 0.7.0 → 0.9.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/public/app.js +71 -24
- package/public/style.css +4 -1
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -137,7 +137,7 @@ function buildThemeMenu() {
|
|
|
137
137
|
const menu = document.getElementById('themeMenu');
|
|
138
138
|
menu.innerHTML = COLOR_THEMES.map(
|
|
139
139
|
([id, label]) =>
|
|
140
|
-
`<button type="button" class="theme-menu-item" data-theme-id="${id}"
|
|
140
|
+
`<button type="button" class="theme-menu-item theme-swatch-${id}" data-theme-id="${id}"
|
|
141
141
|
onclick="event.stopPropagation(); setColorTheme('${id}'); toggleThemeMenu()">
|
|
142
142
|
<span class="theme-swatch theme-swatch-${id}"><i class="sw-bg"></i><i class="sw-accent"></i><i class="sw-ink"></i></span>${label}
|
|
143
143
|
</button>`,
|
|
@@ -194,6 +194,20 @@ async function loadProject() {
|
|
|
194
194
|
document.getElementById('projectBtn').title = projectData.path;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// Shared by the project picker, the boot restore, and the hub project shim. Throws with the
|
|
198
|
+
// server's error message so callers can surface it directly.
|
|
199
|
+
async function putProject(dirPath) {
|
|
200
|
+
const res = await fetch('/api/project', {
|
|
201
|
+
method: 'PUT',
|
|
202
|
+
headers: { 'Content-Type': 'application/json' },
|
|
203
|
+
body: JSON.stringify({ path: dirPath }),
|
|
204
|
+
});
|
|
205
|
+
if (!res.ok) {
|
|
206
|
+
const err = await res.json().catch(() => ({}));
|
|
207
|
+
throw new Error(err.error || `${res.status}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
197
211
|
function changeProject() {
|
|
198
212
|
const current = document.getElementById('projectBtn').title;
|
|
199
213
|
document.getElementById('projectPathInput').value = current;
|
|
@@ -209,20 +223,10 @@ async function submitProjectPicker() {
|
|
|
209
223
|
btn.disabled = true;
|
|
210
224
|
btn.textContent = 'Switching...';
|
|
211
225
|
try {
|
|
212
|
-
|
|
213
|
-
method: 'PUT',
|
|
214
|
-
headers: { 'Content-Type': 'application/json' },
|
|
215
|
-
body: JSON.stringify({ path: dirPath }),
|
|
216
|
-
});
|
|
217
|
-
if (!res.ok) {
|
|
218
|
-
const err = await res.json();
|
|
219
|
-
showToast(err.error, 'error');
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
226
|
+
await putProject(dirPath);
|
|
222
227
|
closeModal('projectPickerModal');
|
|
223
228
|
addRecentProject(dirPath);
|
|
224
|
-
await loadProject();
|
|
225
|
-
await loadData();
|
|
229
|
+
await Promise.all([loadProject(), loadData()]);
|
|
226
230
|
showToast('Project switched', 'success');
|
|
227
231
|
} catch (err) {
|
|
228
232
|
showToast(err.message, 'error');
|
|
@@ -977,14 +981,24 @@ document.addEventListener('keydown', (e) => {
|
|
|
977
981
|
.catch(() => ({}));
|
|
978
982
|
if (!cfg.enabled) return;
|
|
979
983
|
window.__HUB__ = cfg;
|
|
984
|
+
const fwd = (e) =>
|
|
985
|
+
window.parent?.postMessage(
|
|
986
|
+
{ type: 'hub:keydown', key: e.key, ctrl: e.ctrlKey, alt: e.altKey, shift: e.shiftKey },
|
|
987
|
+
'*',
|
|
988
|
+
);
|
|
980
989
|
document.addEventListener('keydown', (e) => {
|
|
981
990
|
if (e.ctrlKey && e.altKey && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {
|
|
982
991
|
e.preventDefault();
|
|
983
|
-
|
|
992
|
+
fwd(e);
|
|
993
|
+
}
|
|
994
|
+
// Its own branch: the Alt+digit case below requires !ctrlKey.
|
|
995
|
+
if (e.ctrlKey && e.altKey && !e.shiftKey && !e.metaKey && e.key.toLowerCase() === 'p') {
|
|
996
|
+
e.preventDefault();
|
|
997
|
+
fwd(e);
|
|
984
998
|
}
|
|
985
999
|
if (e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey && /^[1-9]$/.test(e.key)) {
|
|
986
1000
|
e.preventDefault();
|
|
987
|
-
|
|
1001
|
+
fwd(e);
|
|
988
1002
|
}
|
|
989
1003
|
});
|
|
990
1004
|
})();
|
|
@@ -994,10 +1008,12 @@ function _hubNavigate(app, url) {
|
|
|
994
1008
|
window.parent?.postMessage({ type: 'hub:navigate', app, url }, '*');
|
|
995
1009
|
}
|
|
996
1010
|
|
|
1011
|
+
// Hoisted out of initHubTheme so initHubProject can share it.
|
|
1012
|
+
const hubOrigin = () => (window.__HUB__?.url ? new URL(window.__HUB__.url).origin : null);
|
|
1013
|
+
|
|
997
1014
|
(function initHubTheme() {
|
|
998
1015
|
const getTheme = () => (document.body.classList.contains('light') ? 'light' : 'dark');
|
|
999
1016
|
const getColorTheme = () => document.body.dataset.colorTheme || 'ember';
|
|
1000
|
-
const hubOrigin = () => (window.__HUB__?.url ? new URL(window.__HUB__.url).origin : null);
|
|
1001
1017
|
// lastTheme/lastColorTheme are updated synchronously when applying a hub
|
|
1002
1018
|
// message, so the (async) observer sees no diff and doesn't echo it back.
|
|
1003
1019
|
let lastTheme = getTheme();
|
|
@@ -1028,6 +1044,32 @@ function _hubNavigate(app, url) {
|
|
|
1028
1044
|
});
|
|
1029
1045
|
})();
|
|
1030
1046
|
|
|
1047
|
+
// Set synchronously when the hub pushes a project, so the DOMContentLoaded restore below can't
|
|
1048
|
+
// let a stale localStorage recent win the race against the hub's choice.
|
|
1049
|
+
let hubProjectPath = null;
|
|
1050
|
+
|
|
1051
|
+
(function initHubProject() {
|
|
1052
|
+
let lastApplied = null;
|
|
1053
|
+
window.addEventListener('message', async (e) => {
|
|
1054
|
+
if (e.source !== window.parent || e.origin !== hubOrigin()) return;
|
|
1055
|
+
if (e.data?.type !== 'hub:project') return;
|
|
1056
|
+
const dirPath = e.data.project;
|
|
1057
|
+
if (typeof dirPath !== 'string' || !dirPath) return;
|
|
1058
|
+
hubProjectPath = dirPath;
|
|
1059
|
+
// Dedupes against the last applied value, not just an in-flight one: the hub re-posts on
|
|
1060
|
+
// every iframe load, so without this each load would PUT and reload twice.
|
|
1061
|
+
if (lastApplied === dirPath) return;
|
|
1062
|
+
lastApplied = dirPath;
|
|
1063
|
+
try {
|
|
1064
|
+
await putProject(dirPath);
|
|
1065
|
+
await Promise.all([loadProject(), loadData()]);
|
|
1066
|
+
} catch (err) {
|
|
1067
|
+
lastApplied = null;
|
|
1068
|
+
console.warn('hub:project failed:', err.message);
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
})();
|
|
1072
|
+
|
|
1031
1073
|
// #endregion HUB_INTEGRATION
|
|
1032
1074
|
|
|
1033
1075
|
// #region RESIZE
|
|
@@ -1086,16 +1128,21 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
1086
1128
|
// Handle ?project= query param, else restore last-used project from localStorage
|
|
1087
1129
|
const params = new URLSearchParams(location.search);
|
|
1088
1130
|
let desiredProject = params.get('project');
|
|
1089
|
-
|
|
1131
|
+
// A hub-pushed project outranks the localStorage recent: initHub() is fire-and-forget at script
|
|
1132
|
+
// eval, so hub:project can land before or during this block.
|
|
1133
|
+
if (!desiredProject) desiredProject = hubProjectPath || getRecentProjects()[0] || null;
|
|
1090
1134
|
if (desiredProject) {
|
|
1091
1135
|
try {
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1136
|
+
await putProject(desiredProject);
|
|
1137
|
+
} catch {
|
|
1138
|
+
if (params.has('project')) showToast('Failed to switch project', 'error');
|
|
1139
|
+
}
|
|
1140
|
+
// A push that arrived while the PUT above was in flight must still win.
|
|
1141
|
+
if (hubProjectPath && hubProjectPath !== desiredProject) {
|
|
1142
|
+
try {
|
|
1143
|
+
await putProject(hubProjectPath);
|
|
1144
|
+
} catch {}
|
|
1145
|
+
}
|
|
1099
1146
|
}
|
|
1100
1147
|
if (params.has('project')) {
|
|
1101
1148
|
params.delete('project');
|
package/public/style.css
CHANGED
|
@@ -202,8 +202,11 @@ body {
|
|
|
202
202
|
background: var(--bg-hover);
|
|
203
203
|
color: var(--text-primary);
|
|
204
204
|
}
|
|
205
|
+
/* Highlighted with the row's *own* theme accent rather than the active theme's, so the selected
|
|
206
|
+
row previews the theme it names. --sw-accent comes from the theme-swatch-<id> class on the row. */
|
|
205
207
|
.theme-menu-item.on {
|
|
206
|
-
color: var(--accent-text);
|
|
208
|
+
color: var(--sw-accent, var(--accent-text));
|
|
209
|
+
background: color-mix(in srgb, var(--sw-accent, var(--accent-text)) 16%, transparent);
|
|
207
210
|
}
|
|
208
211
|
/* 3-dot palette preview: surface, accent, ink (colors from themes.css vars) */
|
|
209
212
|
.theme-swatch {
|