ReadKeep/readeck/UI/BookmarkDetail/BookmarkDetailViewModel.swift
Ilyas Hallak c8368f0a70 feat: Implement bookmark filtering, enhanced UI, and API integration
- Add BookmarkState enum with unread, favorite, and archived states
- Extend API layer with query parameter filtering for bookmark states
- Update Bookmark domain model to match complete API response schema
- Implement BookmarkListView with card-based UI and preview images
- Add BookmarkListViewModel with state management and error handling
- Enhance BookmarkDetailView with meta information and WebView rendering
- Create comprehensive DTO mapping for all bookmark fields
- Add TabView with state-based bookmark filtering
- Implement date formatting utilities for ISO8601 timestamps
- Add progress indicators and pull-to-refresh functionality
2025-06-11 22:02:44 +02:00

84 lines
2.3 KiB
Swift

import Foundation
@Observable
class BookmarkDetailViewModel {
private let getBookmarkUseCase: GetBookmarkUseCase
private let getBookmarkArticleUseCase: GetBookmarkArticleUseCase
var bookmarkDetail: BookmarkDetail = BookmarkDetail.empty
var articleContent: String = ""
var articleParagraphs: [String] = []
var bookmark: Bookmark? = nil
var isLoading = false
var isLoadingArticle = false
var errorMessage: String?
init() {
let factory = DefaultUseCaseFactory.shared
self.getBookmarkUseCase = factory.makeGetBookmarkUseCase()
self.getBookmarkArticleUseCase = factory.makeGetBookmarkArticleUseCase()
}
@MainActor
func loadBookmarkDetail(id: String) async {
isLoading = true
errorMessage = nil
do {
bookmarkDetail = try await getBookmarkUseCase.execute(id: id)
// Auch das vollständige Bookmark für readProgress laden
// (Falls GetBookmarkUseCase nur BookmarkDetail zurückgibt)
// Du könntest einen separaten UseCase für das vollständige Bookmark erstellen
} catch {
errorMessage = "Fehler beim Laden des Bookmarks"
}
isLoading = false
}
@MainActor
func loadArticleContent(id: String) async {
isLoadingArticle = true
do {
articleContent = try await getBookmarkArticleUseCase.execute(id: id)
processArticleContent()
} catch {
errorMessage = "Fehler beim Laden des Artikels"
}
isLoadingArticle = false
}
private func processArticleContent() {
// HTML in Paragraphen aufteilen
let paragraphs = articleContent
.components(separatedBy: .newlines)
.filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
articleParagraphs = paragraphs
}
}
extension BookmarkDetail {
static let empty = BookmarkDetail(
id: "",
title: "",
url: "",
description: "",
siteName: "",
authors: [],
created: "",
updated: "",
wordCount: 0,
readingTime: 0,
hasArticle: false,
isMarked: false,
isArchived: false,
thumbnailUrl: "",
imageUrl: ""
)
}