mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-04 20:17:03 +00:00
fix(library): surface unreadable books
list_books silently skipped any .margin file it could not read, parse, or that lacked an id, so a truncated manuscript just vanished. Emit a corrupt placeholder entry instead and show it in the library as a non-openable card with a recovery hint pointing at the .bak backup. Claude-Session: https://claude.ai/code/session_01RzTWrLiy4zGuw2hZSQGamk
This commit is contained in:
1 parent
aa75b3ebda
commit
b63951f814
4 files changed
+51
-13
No files matched your search
+19
-11
@@ -78,17 +78,25 @@ export function Library({ onOpen }: { onOpen: (book: Book) => void }) {
|
||||
<span className="card-badge">Example</span>
|
||||
</button>
|
||||
)}
|
||||
{books.map((b) => (
|
||||
<div
|
||||
key={b.id}
|
||||
className="card card-book"
|
||||
onClick={() => loadBook(b.id).then(onOpen).catch((e) => setNotice(`Could not open book: ${e}`))}
|
||||
>
|
||||
<span className="card-title">{b.title || "Untitled"}</span>
|
||||
{b.author && <span className="card-author">{b.author}</span>}
|
||||
<RowMenu label="Book options" className="card-menu" onDelete={() => setPendingDelete(b)} />
|
||||
</div>
|
||||
))}
|
||||
{books.map((b) =>
|
||||
b.corrupt ? (
|
||||
<div key={b.id} className="card card-book card-corrupt">
|
||||
<span className="card-title">{b.title}</span>
|
||||
<span className="card-author">Couldn't be read; a .bak backup may sit beside it.</span>
|
||||
<RowMenu label="Book options" className="card-menu" onDelete={() => setPendingDelete(b)} />
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
key={b.id}
|
||||
className="card card-book"
|
||||
onClick={() => loadBook(b.id).then(onOpen).catch((e) => setNotice(`Could not open book: ${e}`))}
|
||||
>
|
||||
<span className="card-title">{b.title || "Untitled"}</span>
|
||||
{b.author && <span className="card-author">{b.author}</span>}
|
||||
<RowMenu label="Book options" className="card-menu" onDelete={() => setPendingDelete(b)} />
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
{notice && (
|
||||
<div className="toast" onClick={() => setNotice(null)}>
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface BookSummary {
|
||||
id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
corrupt?: boolean;
|
||||
}
|
||||
|
||||
export async function listBooks(): Promise<BookSummary[]> {
|
||||
|
||||
@@ -1209,6 +1209,16 @@ body.resizing {
|
||||
box-shadow: 0 4px 10px rgba(35, 32, 27, 0.1), 0 20px 38px rgba(35, 32, 27, 0.13);
|
||||
}
|
||||
|
||||
.card-corrupt {
|
||||
cursor: default;
|
||||
opacity: 0.65;
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.card-corrupt:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-family: var(--font-book);
|
||||
font-size: 20px;
|
||||
|
||||
Reference in new issue
Block a user