diff --git a/Marks/Models/Bookmark.swift b/Marks/Models/Bookmark.swift index 725ba1a..e06e772 100644 --- a/Marks/Models/Bookmark.swift +++ b/Marks/Models/Bookmark.swift @@ -41,6 +41,17 @@ struct Bookmark: Codable, Identifiable, Sendable, Hashable { var domain: String { 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 { diff --git a/Marks/Views/BookmarkRow.swift b/Marks/Views/BookmarkRow.swift index 2c595e5..98b3c3b 100644 --- a/Marks/Views/BookmarkRow.swift +++ b/Marks/Views/BookmarkRow.swift @@ -55,10 +55,10 @@ struct BookmarkRow: View { } } - if let summary = bookmark.aiSummary { - Text(summary) + if let excerpt = rowExcerpt { + Text(excerpt.text) .font(.subheadline) - .italic() + .italic(excerpt.isAI) .foregroundStyle(.secondary) .lineLimit(2) .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] { let base = bookmark.tagNames let ai = bookmark.aiTags ?? []