- Replace ScrollView + LazyVStack with native List for better performance - Add swipe actions for bookmark management (archive left, favorite/delete right) - Implement programmatic navigation with NavigationStack and navigationDestination - Create reusable SafariUtil for opening URLs in SFSafariViewController - Add clipboard URL detection and paste functionality in AddBookmarkView - Improve BookmarkCardView layout with better image handling and meta info - Add comprehensive date formatting with relative time display - Implement proper progress bar visualization for reading progress Navigation improvements: - Use Button + navigationDestination instead of NavigationLink - Add selectedBookmarkId state management for programmatic navigation - Support for share extension URL handling with notification system UI/UX enhancements: - Native iOS swipe gestures with haptic feedback - Consistent Safari integration across all views - Better accessibility with proper button targets - Improved visual hierarchy with refined spacing and typography - Added image fallback chain (image → thumbnail → icon → placeholder) Technical changes: - Remove ScrollView scroll tracking complexity - Simplify FAB button logic (always visible on unread tab) - Add String+Identifiable extension for navigation - Refactor duplicate Safari opening code into utility class
88 lines
2.5 KiB
Swift
88 lines
2.5 KiB
Swift
import Foundation
|
|
import UIKit
|
|
|
|
@Observable
|
|
class AddBookmarkViewModel {
|
|
private let createBookmarkUseCase = DefaultUseCaseFactory.shared.makeCreateBookmarkUseCase()
|
|
|
|
var url: String = ""
|
|
var title: String = ""
|
|
var labelsText: String = ""
|
|
|
|
var isLoading: Bool = false
|
|
var errorMessage: String?
|
|
var showErrorAlert: Bool = false
|
|
var hasCreated: Bool = false
|
|
var clipboardURL: String?
|
|
|
|
var isValid: Bool {
|
|
!url.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
|
URL(string: url.trimmingCharacters(in: .whitespacesAndNewlines)) != nil
|
|
}
|
|
|
|
var parsedLabels: [String] {
|
|
labelsText
|
|
.components(separatedBy: ",")
|
|
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
|
.filter { !$0.isEmpty }
|
|
}
|
|
|
|
@MainActor
|
|
func createBookmark() async {
|
|
guard isValid else { return }
|
|
|
|
isLoading = true
|
|
errorMessage = nil
|
|
hasCreated = false
|
|
|
|
do {
|
|
let cleanURL = url.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let cleanTitle = title.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let labels = parsedLabels
|
|
|
|
let request = CreateBookmarkRequest(
|
|
url: cleanURL,
|
|
title: cleanTitle.isEmpty ? nil : cleanTitle,
|
|
labels: labels.isEmpty ? nil : labels
|
|
)
|
|
|
|
let message = try await createBookmarkUseCase.execute(createRequest: request)
|
|
|
|
// Optional: Zeige die Server-Nachricht an
|
|
print("Server response: \(message)")
|
|
|
|
clearForm()
|
|
hasCreated = true
|
|
} catch let error as CreateBookmarkError {
|
|
errorMessage = error.localizedDescription
|
|
showErrorAlert = true
|
|
} catch {
|
|
errorMessage = "Fehler beim Erstellen des Bookmarks"
|
|
showErrorAlert = true
|
|
}
|
|
|
|
isLoading = false
|
|
}
|
|
|
|
func checkClipboard() {
|
|
guard let clipboardString = UIPasteboard.general.string,
|
|
URL(string: clipboardString) != nil else {
|
|
clipboardURL = nil
|
|
return
|
|
}
|
|
|
|
clipboardURL = clipboardString
|
|
}
|
|
|
|
func pasteFromClipboard() {
|
|
guard let clipboardURL = clipboardURL else { return }
|
|
url = clipboardURL
|
|
}
|
|
|
|
func clearForm() {
|
|
url = ""
|
|
title = ""
|
|
labelsText = ""
|
|
}
|
|
}
|