Skip to content

Commit 036b040

Browse files
New1Directionclaude
andcommitted
feat(flow): circular library <-> output navigation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fa05c51 commit 036b040

2 files changed

Lines changed: 34 additions & 5 deletions

File tree

library.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,10 +532,29 @@ function openNote(repoId, btn) {
532532
panel.querySelector('.lc-note-save')?.addEventListener('click', saveNote);
533533
}
534534

535-
function openRow(repoId) {
535+
// Forward path (library → output). Before opening a fresh output tab, focus an
536+
// already-open output tab for the same repo so re-clicking a card round-trips
537+
// instead of orphaning duplicate analysis tabs. Output tabs set their title to
538+
// `… {repoId} — RepoLens` (output-tab.js), which is what we match on — the random
539+
// session key never reaches the URL, so the title is the only stable repo signal.
540+
async function focusExistingOutputTab(repoId) {
541+
try {
542+
const tabs = await chrome.tabs.query({ url: chrome.runtime.getURL('output-tab.html') + '*' });
543+
const existing = tabs.find((t) => typeof t.title === 'string' && t.title.includes(`${repoId} — RepoLens`));
544+
if (!existing) return false;
545+
await chrome.tabs.update(existing.id, { active: true });
546+
await chrome.windows.update(existing.windowId, { focused: true });
547+
return true;
548+
} catch {
549+
return false;
550+
}
551+
}
552+
553+
async function openRow(repoId) {
536554
const cached = cacheByRepo.get(repoId);
537-
if (cached) openCachedAnalysis(cached);
538-
else openSource(repoId);
555+
if (!cached) { openSource(repoId); return; }
556+
if (await focusExistingOutputTab(repoId)) return;
557+
openCachedAnalysis(cached);
539558
}
540559

541560
function openSource(repoId) {

output-tab.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,8 +2438,18 @@ document.getElementById('copy-url')?.addEventListener('click', async () => {
24382438
await copyWithFlash(document.getElementById('copy-url'), url);
24392439
});
24402440

2441-
document.getElementById('open-library')?.addEventListener('click', () => {
2442-
chrome.tabs.create({ url: chrome.runtime.getURL('library.html') });
2441+
// Return path (output → library): focus an existing Library tab if one is open,
2442+
// otherwise open a fresh one. Mirrors background.js's focus-or-create idiom so the
2443+
// library ↔ output round-trip never orphans duplicate Library tabs.
2444+
document.getElementById('open-library')?.addEventListener('click', async () => {
2445+
const libUrl = chrome.runtime.getURL('library.html');
2446+
const [existing] = await chrome.tabs.query({ url: libUrl });
2447+
if (existing) {
2448+
await chrome.tabs.update(existing.id, { active: true });
2449+
await chrome.windows.update(existing.windowId, { focused: true });
2450+
} else {
2451+
chrome.tabs.create({ url: libUrl });
2452+
}
24432453
});
24442454

24452455
const CURRENT_VERSION = '3.0.0';

0 commit comments

Comments
 (0)