feat(BookmarkRow): show a content excerpt under each bookmark title
All checks were successful
CI / build-and-deploy (push) Successful in 30s

Surface a bit of the page content in the list without fetching/parsing pages
ourselves — linkding already returns the scraped metadata in the bookmark
payload. Add Bookmark.contentExcerpt (website_description, falling back to the
user's note) and render it under the title: AI summary takes priority and stays
italic, otherwise the scraped excerpt shows. Rows with neither degrade to the
existing favicon + title layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Krishna Kumar
2026-06-16 14:20:28 -05:00
parent f5c0f0929d
commit 8a27b692b8
2 changed files with 26 additions and 3 deletions

View File

@@ -41,6 +41,17 @@ struct Bookmark: Codable, Identifiable, Sendable, Hashable {
var domain: String { var domain: String {
URL(string: url)?.host ?? url URL(string: url)?.host ?? url
} }
/// A short content snippet for list previews: the page's scraped meta
/// description, falling back to the user's own note. nil when neither exists.
var contentExcerpt: String? {
for candidate in [websiteDescription, description] {
if let c = candidate?.trimmingCharacters(in: .whitespacesAndNewlines), !c.isEmpty {
return c
}
}
return nil
}
} }
struct BookmarkResponse: Codable, Sendable { struct BookmarkResponse: Codable, Sendable {

View File

@@ -55,10 +55,10 @@ struct BookmarkRow: View {
} }
} }
if let summary = bookmark.aiSummary { if let excerpt = rowExcerpt {
Text(summary) Text(excerpt.text)
.font(.subheadline) .font(.subheadline)
.italic() .italic(excerpt.isAI)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
.lineLimit(2) .lineLimit(2)
.padding(.leading, 44) .padding(.leading, 44)
@@ -106,6 +106,18 @@ struct BookmarkRow: View {
} }
} }
/// Excerpt shown under the title: prefer the AI summary (italic), else the
/// page's scraped description / user note. nil hides the line entirely.
private var rowExcerpt: (text: String, isAI: Bool)? {
if let s = bookmark.aiSummary?.trimmingCharacters(in: .whitespacesAndNewlines), !s.isEmpty {
return (s, true)
}
if let e = bookmark.contentExcerpt {
return (e, false)
}
return nil
}
private var effectiveTags: [String] { private var effectiveTags: [String] {
let base = bookmark.tagNames let base = bookmark.tagNames
let ai = bookmark.aiTags ?? [] let ai = bookmark.aiTags ?? []