Files
RSSuper/iOS/RSSuper/Services/BookmarkStore.swift
Michael Freno ba1e2e96e7 feat: implement iOS UI integration with ViewModels
- Add SwiftUI views for feed list, detail, add feed, settings, and bookmarks
- Connect all views to ViewModels using @StateObject
- Implement pull-to-refresh for feed list
- Add error handling and loading states to all views
- Create FeedItemRow view for consistent feed item display
- Add toFeedItem() extension to Bookmark for UI integration
- Update FeedDetailView to use sync methods
- Update BookmarkView to use FeedService for unstar operations

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-31 06:50:11 -04:00

131 lines
4.1 KiB
Swift

import Foundation
enum BookmarkStoreError: LocalizedError {
case objectNotFound
case saveFailed(Error)
case fetchFailed(Error)
case deleteFailed(Error)
var errorDescription: String? {
switch self {
case .objectNotFound:
return "Bookmark not found"
case .saveFailed(let error):
return "Failed to save: \(error.localizedDescription)"
case .fetchFailed(let error):
return "Failed to fetch: \(error.localizedDescription)"
case .deleteFailed(let error):
return "Failed to delete: \(error.localizedDescription)"
}
}
}
protocol BookmarkStoreProtocol {
func getAllBookmarks() -> [Bookmark]
func getBookmark(byId id: String) -> Bookmark?
func getBookmark(byFeedItemId feedItemId: String) -> Bookmark?
func getBookmarks(byTag tag: String) -> [Bookmark]
func addBookmark(_ bookmark: Bookmark) -> Bool
func removeBookmark(_ bookmark: Bookmark) -> Bool
func removeBookmark(byId id: String) -> Bool
func removeBookmark(byFeedItemId feedItemId: String) -> Bool
func getBookmarkCount() -> Int
func getBookmarkCount(byTag tag: String) -> Int
}
class BookmarkStore: BookmarkStoreProtocol {
private let databaseManager: DatabaseManager
init(databaseManager: DatabaseManager = DatabaseManager.shared) {
self.databaseManager = databaseManager
}
func getAllBookmarks() -> [Bookmark] {
do {
let starredItems = try databaseManager.getStarredItems()
return starredItems.map { item in
Bookmark(
id: item.id,
feedItemId: item.id,
title: item.title,
link: item.link,
description: item.description,
content: item.content,
createdAt: item.published
)
}
} catch {
return []
}
}
func getBookmark(byId id: String) -> Bookmark? {
// For now, return nil since we don't have a direct bookmark lookup
// This would require a separate bookmarks table
return nil
}
func getBookmark(byFeedItemId feedItemId: String) -> Bookmark? {
// For now, return nil since we don't have a separate bookmarks table
return nil
}
func getBookmarks(byTag tag: String) -> [Bookmark] {
// Filter bookmarks by tag - this would require tag support
// For now, return all bookmarks
return getAllBookmarks()
}
func addBookmark(_ bookmark: Bookmark) -> Bool {
// Add bookmark by marking the feed item as starred
let success = databaseManager.markItemAsStarred(itemId: bookmark.feedItemId)
return success
}
func removeBookmark(_ bookmark: Bookmark) -> Bool {
// Remove bookmark by unmarking the feed item
let success = databaseManager.unstarItem(itemId: bookmark.feedItemId)
return success
}
func removeBookmark(byId id: String) -> Bool {
// Remove bookmark by ID
let success = databaseManager.unstarItem(itemId: id)
return success
}
func removeBookmark(byFeedItemId feedItemId: String) -> Bool {
// Remove bookmark by feed item ID
let success = databaseManager.unstarItem(itemId: feedItemId)
return success
}
func getBookmarkCount() -> Int {
let starredItems = databaseManager.getStarredItems()
return starredItems.count
}
func getBookmarkCount(byTag tag: String) -> Int {
// Count bookmarks by tag - this would require tag support
// For now, return total count
return getBookmarkCount()
}
}
extension Bookmark {
func toFeedItem() -> FeedItem {
FeedItem(
id: feedItemId,
title: title,
link: link,
description: description,
content: content,
published: createdAt,
updated: createdAt,
subscriptionId: "", // Will be set when linked to subscription
subscriptionTitle: nil,
read: false
)
}
}