Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ Groups are rendered as cards. Each group can be collapsed without deleting data.

## UI behavior reference
- **Collapse group:** hides rows but does not delete data.
- **Collapse/expand all:** a navbar button toggles every group open or closed. Default on initial load: all groups start collapsed except the most recent one.
- **Restore all:** restores all tabs in the group, then deletes the group.
- **Delete all:** deletes the entire group without opening tabs.
- **Restore single:** opens one tab, then removes it from the group.
Expand Down
8 changes: 8 additions & 0 deletions entrypoints/background/condense.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
/**
* Orchestrates the condense workflow: query tabs, save eligible ones,
* close them, and focus/create the list page tab.
*/
import { LIST_PAGE_PATH, appendSavedGroup, readSettings } from '../shared/storage';
import { createCondenseGroupKey, filterEligibleTabs, resolveWindowId, saveTabsToList } from '../shared/condense';
import { logExtensionError } from '../shared/utils';
import { focusExistingListTabOrCreate } from './list_tab';

/**
* Main condense action: queries all tabs in the target (or current) window,
* saves eligible ones to storage, closes them, and opens the list page.
*/
export async function condenseCurrentWindow(targetWindowId?: number): Promise<void> {
const settings = await readSettings();
let tabs: chrome.tabs.Tab[] = [];
Expand Down
7 changes: 7 additions & 0 deletions entrypoints/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
/**
* Background service worker entrypoint for the nufftabs extension.
* Registers the browser-action click handler that triggers the condense workflow.
*/
import { condenseCurrentWindow } from './condense';
import { logExtensionError } from '../shared/utils';

/** Re-export so other modules can import `condenseCurrentWindow` from the background barrel. */
export { condenseCurrentWindow };

/** Registers a `chrome.action.onClicked` listener that condenses all eligible tabs in the clicked window. */
export function registerActionClickHandler(): void {
chrome.action.onClicked.addListener((tab) => {
void condenseCurrentWindow(tab?.windowId).catch((error: unknown) => {
Expand All @@ -11,6 +17,7 @@ export function registerActionClickHandler(): void {
});
}

/** WXT background entrypoint — invoked once when the service worker starts. */
export default defineBackground(() => {
registerActionClickHandler();
});
9 changes: 9 additions & 0 deletions entrypoints/background/list_tab.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/**
* Helpers for managing the nufftabs list page tab:
* finding the most recently accessed one and focusing or creating it.
*/
import { logExtensionError } from '../shared/utils';

/** Returns the most recently accessed list-page tab, preferring active tabs on ties. */
export function pickMostRecentListTab(tabs: chrome.tabs.Tab[]): chrome.tabs.Tab | undefined {
return tabs.reduce<chrome.tabs.Tab | undefined>((best, tab) => {
if (!best) return tab;
Expand All @@ -11,6 +16,10 @@ export function pickMostRecentListTab(tabs: chrome.tabs.Tab[]): chrome.tabs.Tab
}, undefined);
}

/**
* Focuses an existing list-page tab (pinning it) or creates a new one.
* Falls back to a new tab if focusing the existing one fails.
*/
export async function focusExistingListTabOrCreate(
listTabs: chrome.tabs.Tab[],
listUrl: string,
Expand Down
14 changes: 14 additions & 0 deletions entrypoints/nufftabs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ <h1>nufftabs</h1>
/>
</div>
<div class="app-actions">
<!-- Toggle button to collapse or expand all group cards at once -->
<button
id="toggleCollapseAll"
type="button"
class="icon-button"
aria-label="Collapse all groups"
title="Collapse all groups"
>
<!-- Double-chevron icon: points up when groups are expanded (collapse action) -->
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12 14z" fill="currentColor"/>
<path d="M7.41 12.59L8.83 14 12 10.83 15.17 14l1.41-1.41L12 8z" fill="currentColor"/>
</svg>
</button>
<button
id="scrollTop"
type="button"
Expand Down
Loading