Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export function App() {
author: extracted.author,
pages: extracted.pages,
outline: extracted.outline,
structure: extracted.structure,
wordCount: extracted.wordCount,
savedAt: Date.now(),
};
Expand Down
39 changes: 31 additions & 8 deletions src/components/Reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,27 @@ export function Reader({ doc, onExit }: Props) {
};
}, [settings.theme, settings.brightness]);

const filteredOutline = doc.outline.filter((o) =>
// Prefer the kind-aware structure when present (so the contents panel can show
// levels, section numbers, and labels like "References"); fall back to the
// flat outline for docs cached before structure shipped.
const tocItems = useMemo(() => {
if (doc.structure?.length) {
return doc.structure.map((n) => ({
title: n.title.trim(),
pageNumber: n.page,
level: n.level,
kind: n.kind,
}));
}
return doc.outline.map((o) => ({
title: o.title.trim(),
pageNumber: o.pageNumber,
level: Math.floor((o.title.match(/^\s*/)?.[0].length ?? 0) / 2) + 1,
kind: undefined as string | undefined,
}));
}, [doc.structure, doc.outline]);

const filteredToc = tocItems.filter((o) =>
query ? o.title.toLowerCase().includes(query.toLowerCase()) : true,
);

Expand Down Expand Up @@ -1181,7 +1201,7 @@ export function Reader({ doc, onExit }: Props) {
/>
</div>
<ul className="space-y-1">
{filteredOutline.map((item, i) => (
{filteredToc.map((item, i) => (
<li key={i}>
<button
onClick={() => {
Expand All @@ -1192,15 +1212,18 @@ export function Reader({ doc, onExit }: Props) {
pos.sourcePage === item.pageNumber
? "bg-ember/10 text-ember"
: "text-muted-foreground hover:bg-muted/40 hover:text-foreground"
}`}
} ${item.level > 1 ? "text-xs" : ""}`}
>
<span
className="truncate"
style={{
paddingLeft: `${(item.title.match(/^\s*/)?.[0].length || 0) * 4}px`,
}}
className="truncate flex items-center gap-2"
style={{ paddingLeft: `${(item.level - 1) * 12}px` }}
>
{item.title.trim()}
{item.kind && item.kind !== "section" && item.kind !== "subsection" && (
<span className="text-[10px] uppercase tracking-wide opacity-50 shrink-0">
{item.kind}
</span>
)}
<span className="truncate">{item.title}</span>
</span>
<span className="text-xs opacity-70 shrink-0">{item.pageNumber}</span>
</button>
Expand Down
Loading
Loading