ReadKeep/readeck/UI/Bookmarks/BookmarksView.swift
Ilyas Hallak da7bb1613c feat: Add bookmark creation functionality and WebView dark mode support
- Add CREATE API endpoint for new bookmarks with POST request
- Implement CreateBookmarkRequestDto and CreateBookmarkResponseDto
- Create AddBookmarkView with form validation and clipboard integration
- Add AddBookmarkViewModel with URL validation and label parsing
- Implement CreateBookmarkUseCase with convenience methods
- Extend BookmarksRepository with createBookmark method returning server message
- Add comprehensive error handling for bookmark creation scenarios
- Integrate WebView dark mode support with CSS variables and system color scheme
- Add dynamic theme switching based on iOS appearance settings
- Enhance WebView styling with iOS-native colors and typography
- Fix BookmarksView refresh after bookmark creation
- Add floating action button and sheet presentation for adding bookmarks
- Implement form validation with real-time feedback
- Add clipboard URL detection and paste functionality
2025-06-11 23:02:58 +02:00

92 lines
3.8 KiB
Swift

import SwiftUI
struct BookmarksView: View {
@State private var viewModel = BookmarksViewModel()
@State private var showingAddBookmark = false
let state: BookmarkState
var body: some View {
NavigationView {
ZStack {
if viewModel.isLoading && viewModel.bookmarks.isEmpty {
ProgressView("Lade \(state.displayName)...")
} else {
ScrollView {
LazyVStack(spacing: 12) {
ForEach(viewModel.bookmarks, id: \.id) { bookmark in
NavigationLink(destination: BookmarkDetailView(bookmarkId: bookmark.id)) {
BookmarkCardView(
bookmark: bookmark,
currentState: state,
onArchive: { bookmark in
Task {
await viewModel.toggleArchive(bookmark: bookmark)
}
},
onDelete: { bookmark in
Task {
await viewModel.deleteBookmark(bookmark: bookmark)
}
},
onToggleFavorite: { bookmark in
Task {
await viewModel.toggleFavorite(bookmark: bookmark)
}
}
)
.padding(.bottom, 20)
}
.buttonStyle(PlainButtonStyle())
}
}
.padding()
}
.refreshable {
await viewModel.refreshBookmarks()
}
.overlay {
if viewModel.bookmarks.isEmpty && !viewModel.isLoading {
ContentUnavailableView(
"Keine Bookmarks",
systemImage: "bookmark",
description: Text("Es wurden noch keine Bookmarks in \(state.displayName.lowercased()) gefunden.")
)
}
}
}
}
.navigationTitle(state.displayName)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
showingAddBookmark = true
}) {
Image(systemName: "plus")
}
}
}
.sheet(isPresented: $showingAddBookmark) {
AddBookmarkView()
}
.alert("Fehler", isPresented: .constant(viewModel.errorMessage != nil)) {
Button("OK", role: .cancel) {
viewModel.errorMessage = nil
}
} message: {
Text(viewModel.errorMessage ?? "")
}
.task {
await viewModel.loadBookmarks(state: state)
}
.onChange(of: showingAddBookmark) { oldValue, newValue in
// Refresh bookmarks when sheet is dismissed
if oldValue && !newValue {
Task {
await viewModel.refreshBookmarks()
}
}
}
}
}
}