46 Commits

Author SHA1 Message Date
a3b3863fa3 Refactor tag management system with improved search and real-time sync
- Add CreateLabelUseCase for consistent label creation across app and extension
- Implement TagRepository for Share Extension to persist new labels to Core Data
- Enhance CoreDataTagManagementView with real-time search functionality
- Add automatic tag synchronization on app startup and resume
- Improve Core Data context configuration for better extension support
- Unify label terminology across UI components (tags -> labels)
- Fix label persistence issues in Share Extension
- Add immediate Core Data persistence for newly created labels
- Bump version to 36
2025-11-10 21:29:38 +01:00
4134b41be2 Fix tag scrolling and improve debug logging
- Fix duplicate ID warning in CoreDataTagManagementView by using objectID
- Enhance debug logging system with category filtering
2025-11-08 19:18:56 +01:00
f3719fa9d4 Refactor tag management to use Core Data with configurable sorting
This commit introduces a comprehensive refactoring of the tag management
system, replacing the previous API-based approach with a Core Data-first
strategy for improved performance and offline support.

Major Changes:

Tag Management Architecture:
- Add CoreDataTagManagementView using @FetchRequest for reactive updates
- Implement cache-first sync strategy in LabelsRepository
- Create SyncTagsUseCase following Clean Architecture principles
- Add TagSortOrder enum for configurable tag sorting (by count/alphabetically)
- Mark LegacyTagManagementView as deprecated

Share Extension Improvements:
- Replace API-based tag loading with Core Data queries
- Display top 150 tags sorted by usage count
- Remove unnecessary label fetching logic
- Add "Most used tags" localized title
- Improve offline bookmark tag management

Main App Enhancements:
- Add tag sync triggers in AddBookmarkView and BookmarkLabelsView
- Implement user-configurable tag sorting in settings
- Add sort order indicator labels with localization
- Automatic UI updates via SwiftUI @FetchRequest reactivity

Settings & Configuration:
- Add TagSortOrder setting with persistence
- Refactor Settings model structure
- Add FontFamily and FontSize domain models
- Improve settings repository with tag sort order support

Use Case Layer:
- Add SyncTagsUseCase for background tag synchronization
- Update UseCaseFactory with tag sync support
- Add mock implementations for testing

Localization:
- Add German and English translations for:
  - "Most used tags"
  - "Sorted by usage count"
  - "Sorted alphabetically"

Technical Improvements:
- Batch tag updates with conflict detection
- Background sync with silent failure handling
- Reduced server load through local caching
- Better separation of concerns following Clean Architecture
2025-11-08 13:46:40 +01:00
4b93c605f1 Redesign settings screen with native iOS style
- Refactor all settings views to use List with .insetGrouped style
- Create reusable SettingsRow components for consistent UI
- Separate onboarding flow into dedicated OnboardingServerView
- Consolidate font, theme, and card layout into unified Appearance section
- Add visual card layout previews in dedicated selection screen
- Move "Open links in" option to Appearance with descriptive footer
- Improve settings organization and native iOS feel
2025-10-31 23:39:59 +01:00
cdfa6dc4c5 Fix annotation navigation by scrolling outer ScrollView instead of WebView
The JavaScript was executing scrollIntoView() but the WebView itself cannot
scroll (isScrollEnabled = false). Fixed by calculating the annotation's Y
position in the WebView and scrolling the outer ScrollView to the correct
position instead.

Changes:
- WebView.swift: Added onScrollToPosition callback and scrollToPosition
  message handler. JavaScript now calculates and sends annotation position
  to Swift instead of using scrollIntoView().
- NativeWebView.swift: Same changes for iOS 26+ with polling mechanism for
  window.__pendingScrollPosition.
- BookmarkDetailLegacyView.swift: Implemented onScrollToPosition callback
  that calculates final scroll position (header height + annotation position)
  and scrolls the outer ScrollView.
- BookmarkDetailView2.swift: Same implementation as BookmarkDetailLegacyView.
2025-10-30 21:07:13 +01:00
907cc9220f perf: Optimize label loading for 1000+ labels
Major performance improvements to prevent crashes and lag when working with large label collections:

Main App:
- Switch to Core Data as primary source for labels (instant loading)
- Implement background API sync to keep labels up-to-date
- Add LazyVStack for efficient rendering of large label lists
- Use batch operations instead of individual queries (1 query vs 1000)
- Generate unique IDs for local labels to prevent duplicate warnings

Share Extension:
- Convert getTags() to async with background context
- Add saveTags() method with batch insert support
- Load labels from Core Data first, then sync with API
- Remove duplicate server reachability checks
- Reduce memory usage and prevent UI freezes

Technical Details:
- Labels now load instantly from local cache
- API sync happens in background without blocking UI
- Batch fetch operations for optimal database performance
- Proper error handling for offline scenarios
- Fixed duplicate ID warnings in ForEach loops

Fixes crashes and lag reported by users with 1000+ labels.
2025-10-26 21:24:12 +01:00
b77e4e3e9f refactor: Centralize annotation colors and improve color consistency
- Move AnnotationColor enum to Constants.swift for centralized color management
- Add hexColor property to provide hex values for JavaScript overlays
- Add cssColorWithOpacity method for flexible opacity control
- Update NativeWebView and WebView to use centralized color values
- Replace modal color picker with inline overlay for better UX
- Implement annotation creation directly from text selection
- Add API endpoint for creating annotations with selectors
2025-10-25 09:19:49 +02:00
1b9f79bccc fix: Use callJavaScript instead of evaluateJavaScript for WebPage
WebPage in iOS 26 uses callJavaScript method, not evaluateJavaScript.
2025-10-22 15:58:07 +02:00
d1157defbe fix: Resolve WebPage binding error in NativeWebView text selection
Capture webPage locally in Task to avoid @State binding issues when
calling evaluateJavaScript in async context.
2025-10-22 15:54:55 +02:00
a041300b4f feat: Add text selection support for iOS 26+ NativeWebView
Implement text selection detection in NativeWebView:
- Add onTextSelected callback parameter to NativeWebView
- Use JavaScript polling to detect text selections
- Calculate text offsets for precise annotation positioning
- Integrate color picker in BookmarkDetailView2 for iOS 26+
- Match feature parity with legacy WebView implementation

Text selection now works on both WebView implementations.
2025-10-22 15:35:56 +02:00
ec12815a51 feat: Add text selection and annotation creation UI
Implement interactive text annotation feature:
- Add text selection detection via JavaScript in WebView
- Create AnnotationColorPicker with 4 color options (yellow, green, blue, red)
- Integrate color picker sheet in bookmark detail views
- Calculate text offsets for precise annotation positioning
- Add onTextSelected callback for WebView component
- Prepare UI for future API integration

Users can now select text in articles and choose a highlight color.
API integration for persisting annotations will follow.
2025-10-22 15:30:34 +02:00
cf06a3147d feat: Add annotations support with color-coded highlighting
Add comprehensive annotations feature to bookmark detail views:
- Implement annotations list view with date formatting and state machine
- Add CSS-based highlighting for rd-annotation tags in WebView components
- Support Readeck color scheme (yellow, green, blue, red) for annotations
- Enable tap-to-scroll functionality to navigate to selected annotations
- Integrate annotations button in bookmark detail toolbar
- Add API endpoint and repository layer for fetching annotations
2025-10-22 15:25:55 +02:00
4c744e6d10 fix: Add comprehensive width constraints to NativeWebView CSS
Added multiple CSS rules to prevent content overflow:

Universal rules:
- * { max-width: 100%; box-sizing: border-box; }

HTML/Body:
- overflow-x: hidden on both html and body
- width: 100% to enforce viewport width
- word-wrap and overflow-wrap: break-word on body

Pre blocks:
- max-width: 100%
- white-space: pre-wrap (allows wrapping)
- word-wrap: break-word

Viewport meta:
- Added maximum-scale=1.0, user-scalable=no to prevent zooming issues

The native iOS 26+ WebView handles width differently than WKWebView,
requiring explicit overflow and width constraints in CSS.
2025-10-10 20:18:38 +02:00
842c404f04 fix: Add return statement to JavaScript height detection in NativeWebView
Added 'return' keyword before document.body.scrollHeight to ensure
the JavaScript expression returns a value that can be captured by
webPage.callJavaScript().
2025-10-10 19:56:35 +02:00
614042c3bd fix: Simplify NativeWebView CSS and JavaScript height detection
CSS Changes:
- Removed all overflow/max-width/word-break rules from body/html
- Simplified to match WebView.swift CSS structure exactly
- Only img keeps max-width: 100%
- Removed box-sizing and universal max-width rules

JavaScript Height Detection:
- Simplified from Math.max() with multiple properties to simple document.body.scrollHeight
- This matches how the standard WebView gets height
- Should resolve 'No valid JavaScript height found' errors

The width overflow was caused by aggressive CSS rules that interfered
with native layout. The height detection issue was likely due to complex
JavaScript expressions not working with webPage.callJavaScript().
2025-10-10 19:46:09 +02:00
008303d043 fix: Prevent content overflow in NativeWebView
- Added universal max-width: 100% to all elements
- Added overflow-wrap, word-wrap, and word-break to body
- Added overflow-x: hidden to html
- Fixed pre blocks with white-space: pre-wrap and max-width
- Fixed tables with display: block and overflow-x: auto
- Added word-wrap to table cells

This prevents wide content (long URLs, code blocks, tables) from
overflowing the viewport width in iOS 26+ NativeWebView.
2025-10-10 17:27:27 +02:00
a782a27eea revert: Remove JavaScript scroll tracking, back to SwiftUI-based solution
- Removed JavaScript scroll event listeners and console.log debugging
- Removed WebViewCoordinator.updateScrollProgress() method
- Removed onExternalScrollUpdate callback
- Removed webView reference and lastSentProgress from coordinator
- Restored scrollViewHeight state variable
- Restored JumpButton functionality with ScrollPosition
- Back to onScrollPhaseChange with 3% threshold for reading progress

The JavaScript approach didn't work because WebView scrolling is disabled
(embedded in SwiftUI ScrollView). The SwiftUI-based solution is cleaner
and performs well with onScrollPhaseChange.
2025-10-10 15:43:50 +02:00
5c9c00134a feat: Connect SwiftUI ScrollView tracking to WebView coordinator
- Added WebViewCoordinator reference storage in BookmarkDetailLegacyView
- Added updateScrollProgress() method to WebViewCoordinator with 3% threshold
- Connected onScrollPhaseChange to coordinator's updateScrollProgress
- Added onExternalScrollUpdate callback to pass coordinator reference
- Scroll progress now flows: SwiftUI ScrollView -> Coordinator -> onScroll callback

This bridges the gap between SwiftUI ScrollView (which wraps the WebView)
and the JavaScript-style scroll progress tracking with threshold.
2025-10-10 15:33:20 +02:00
0a53705df1 debug: Add comprehensive logging to JavaScript scroll tracking
- Added console.log statements in JavaScript for scroll events
- Added Swift print statements in message handler
- Added logging in BookmarkDetailLegacyView onScroll callback
- Logs cover: JS initialization, scroll events, message passing, Swift handling

This will help diagnose why scroll events aren't being captured.
2025-10-10 15:25:19 +02:00
32dbab400e feat: Implement JavaScript-based scroll tracking in BookmarkDetailLegacyView
- Added scroll progress tracking via JavaScript in WebView
- Implemented 3% threshold to reduce message frequency
- Removed SwiftUI onScrollGeometryChange and onScrollPhaseChange
- Cleaned up unused state variables (scrollViewHeight, currentScrollOffset)
- Removed Combine import (no longer needed)
- Disabled JumpButton scroll-to-position (requires JavaScript implementation)

This approach offloads scroll tracking to the WebView's JavaScript,
reducing SwiftUI state updates and improving performance.
2025-10-10 14:47:56 +02:00
171bf881fb feat: Add native SwiftUI WebView support with iOS 26+ BookmarkDetailView2
- Created BookmarkDetailView2 with native SwiftUI WebView (iOS 26+)
- Refactored BookmarkDetailView as version router
- Renamed original implementation to BookmarkDetailLegacyView
- Moved Archive/Favorite buttons to bottom toolbar using ToolbarItemGroup
- Added toggle button to switch between native and legacy views
- Implemented onScrollPhaseChange for optimized reading progress tracking
- Added NativeWebView component with improved JavaScript height detection
- All changes preserve existing functionality while adding modern alternatives
2025-10-10 00:27:59 +02:00
7b12bb4cf5 fix: Improve WebView performance by sanitizing problematic HTML attributes
- Remove jsaction, jscontroller, jsname attributes that trigger navigation events
- Strip unnecessary id attributes to reduce DOM size
- Remove tabindex from non-interactive elements
- Fix invalid nested p tags inside pre/span blocks
- Prevents WebKit crashes on complex HTML content
2025-10-07 20:41:43 +02:00
f42d138f58 refactor: Clean up WebView code and remove debug prints
- Remove all debug print statements for cleaner output
- Group related properties in WebViewCoordinator for better organization
- Remove redundant comments throughout the code
- Simplify JavaScript code by removing unnecessary comments
- Maintain all functionality while improving code readability
2025-09-30 23:21:46 +02:00
f50ad505ae fix: Add memory leak prevention and proper WebView cleanup
- Add dismantleUIView method to properly cleanup WebView resources
- Remove script message handlers to prevent memory leaks
- Add cleanup() method to WebViewCoordinator with timer invalidation
- Clear all callbacks and references when view is destroyed
- Add isCleanedUp guard to prevent double cleanup
- Improve memory management for better stability
2025-09-30 23:20:00 +02:00
c8c93b76da update README with new iPhone and iPad screenshots 2025-09-27 22:44:12 +02:00
ac7f4e66eb fix: Improve Core Data thread safety and resolve scrolling flicker
- Add background context support to CoreDataManager
- Fix TagEntity threading crashes in LabelsRepository
- Prevent WebView height updates during scrolling to reduce flicker
- Add App Store download link to README
2025-09-26 21:56:49 +02:00
ba74430d10 feat: Improve label input functionality
- Split label input on space to create multiple labels at once
- Disable autocapitalization in tag search field
- Prevent duplicate labels when adding multiple at once
2025-09-17 13:36:36 +02:00
df8a7b64b2 feat: Add Kingfisher caching, card layouts, dynamic tag layout, and undo delete
- Integrate Kingfisher for image caching with CachedAsyncImage component
- Add CacheSettingsView for managing image cache size and clearing cache
- Implement three card layout styles: compact, magazine (default), natural
- Add AppearanceSettingsView with visual layout previews and theme settings
- Create Clean Architecture for card layout with domain models and use cases
- Implement FlowLayout for dynamic label width calculation
- Add skeleton loading animation for initial bookmark loads
- Replace delete confirmation dialogs with immediate delete + 3-second undo
- Support multiple simultaneous undo operations with individual progress bars
- Add grayed-out visual feedback for pending deletions
- Centralize notification names in dedicated NotificationNames file
- Remove pagination logic from label management (replaced with FlowLayout)
- Update AsyncImage usage across BookmarkCardView, BookmarkDetailView, ImageViewerView
- Improve UI consistency and spacing throughout the app
2025-09-04 10:43:27 +02:00
fd50f28628 feat: Enable text selection and improve bookmark error handling
- Enable text selection and copy functionality in article WebView
- Add CSS properties for proper text selection on iOS devices
- Preserve bookmark data during reload errors for better UX
- Update documentation with new offline sync features
- Restructure changelog with planned version roadmap

Users can now select and copy text from articles, and bookmark lists
remain visible even when refresh operations fail.
2025-08-20 21:00:50 +02:00
76bc28ae02 feat: Improve UI components and performance optimizations
- Refactor BookmarksView with better error handling and loading states
- Optimize BookmarkLabelsViewModel with cached properties and reduced recomputation
- Fix Core Data thread safety in LabelsRepository with performAndWait
- Enhance TagManagementView with sorted selected labels display
- Clean up ShareBookmarkViewModel comments
- Update localization strings for error states
- Bump build version to 19

These changes improve overall app performance and user experience across
bookmark management workflows.
2025-08-20 20:38:42 +02:00
ffb41347af refactor: Implement state machine architecture for offline sync
- Replace multiple boolean properties with single OfflineBookmarkSyncState enum
- Add Use Case pattern for OfflineSyncManager with dependency injection
- Simplify LocalBookmarksSyncView using state-driven UI with external bindings
- Convert OfflineBookmarksViewModel to use @Observable instead of ObservableObject
- Move credentials from Core Data to Keychain for better persistence
- Implement comprehensive database migration for App Group containers
- Add structured logging throughout sync operations and API calls

Architecture improvements follow MVVM principles with clean separation of concerns.
2025-08-18 22:58:42 +02:00
ef13faeff7 feat: Add offline bookmark sync functionality
Add comprehensive offline bookmark support with sync capabilities:
- Implement offline bookmark storage using Core Data with App Group sharing
- Add Share Extension support for saving bookmarks when server unavailable
- Create LocalBookmarksSyncView for managing offline bookmark queue
- Add OfflineSyncManager for automatic and manual sync operations
- Implement ServerConnectivity monitoring and status handling
- Add badge notifications on More tab for pending offline bookmarks
- Fix tag pagination in Share Extension with unique IDs for proper rendering
- Update PhoneTabView with event-based badge count updates
- Add App Group entitlements for data sharing between main app and extension

The offline system provides seamless bookmark saving when disconnected,
with automatic sync when connection is restored and manual sync options.
2025-08-16 22:32:20 +02:00
1ffafc3b35 fix: Improve tag chip alignment in TagManagementView
- Update grid container to align chips to top when fewer than 3 rows
- Adjust top padding to prevent label overlap with chips
2025-08-07 20:41:45 +02:00
f3f94f1cfe refactor: Clean up tag management UI and update project version
- Remove duplicate search functionality from BookmarkLabelsView
- Update TagManagementView font sizes for better readability
- Bump URLShare extension version to 13
2025-08-06 21:49:12 +02:00
a09cad5d7e feat: Add intelligent scroll behavior to AddBookmarkView
- Add enum-based FocusState (AddBookmarkFieldFocus) for cleaner code
- Implement auto-scroll to URL field when focused
- Implement auto-scroll to labels field with 40px offset when focused
- Implement auto-scroll to title field when focused
- Add ScrollViewReader with smooth animations
- Update TagManagementView to support enum-based focus binding
- Add FocusModifier for optional focus state handling
- Improve keyboard handling with proper padding adjustments
2025-08-03 22:40:51 +02:00
5b2d177f94 feat: Enhanced tag management with unified search and keyboard handling
- Added search functionality to BookmarkLabelsView with real-time filtering
- Implemented custom tag creation with smart suggestions
- Unified search and tag selection in ShareBookmarkView
- Added keyboard toolbar with 'Done' button for extensions
- Implemented notification-based keyboard dismissal for extensions
- Added pagination logic to ShareBookmarkViewModel
- Created selected tags section with remove functionality
- Improved UX with consistent tag management across views
- Added proper keyboard handling for iOS extensions
2025-07-30 23:53:30 +02:00
1cb87a4fb7 feat: enhance UI with improved label management and splash screen
- Add new logo and splash screen assets with multiple resolutions
- Implement paginated label selection with TabView
- Create UnifiedLabelChip component for consistent label display
- Add manual tag entry functionality with validation
- Refactor BookmarkLabelsViewModel with dependency injection
- Update launch screen configuration and color sets
- Add new localization strings for improved UX
- Improve ShareBookmarkView with better label selection UI
2025-07-29 21:26:32 +02:00
176885442e feat: add delete confirmation for bookmarks and UI improvements
- Add confirmation alert before deleting a bookmark to prevent accidental deletions (BookmarksView)
- Add localized strings for delete confirmation dialog
- Improve layout and logic in BookmarkDetailView (alignment, locale, progress jump)
- Show read progress only for non-archived/non-marked bookmarks (BookmarkCardView)
- Refine WebView: remove debug code, improve scroll/height update logic, disable scroll
2025-07-23 23:58:47 +02:00
8e8e67bfe1 UI/UX: Bookmark Detail and CardView improvements
- Progress indicator as a compact circle at the bottom right of the CardView, with percent display
- Jump-to-progress button in detail view, using ScrollPosition logic (removed iOS 17 mention)
- Archive/Unarchive button with flexible parameter and label
- Various bugfixes and refactoring (progress, mock, WebView, strings)
- Improved reading progress logic and display
- Code cleanup: removed debug prints, mutated properties directly
2025-07-23 22:15:21 +02:00
15ce5a223b Add reading progress bar for article view, optimize archive button UX, and improve WebView scroll tracking
- Add a reading progress bar at the top of the article detail view, based on WebView height and ScrollView height
- Remove unused contentHeight logic, use webViewHeight as the single source of truth
- Optimize archive button: show checkmark and 'Archived' after archiving, disable button, and show 'Go Back' button for dismiss
- Enable scrolling in WebView and add JavaScript for scroll progress reporting and debug logs
- Add new localization keys for 'Archived' and 'Go Back'
- Bump project version
2025-07-22 23:27:52 +02:00
8d4b08da11 Add TTS feature toggle, refactor settings, and improve UI
- Implemented a toggle for the 'Read Aloud' (TTS) feature in the general settings.
- Refactored AppSettings and PlayerUIState to support TTS enable/disable.
- Updated BookmarkDetailView, PadSidebarView, PhoneTabView, and GlobalPlayerContainerView to respect the TTS setting.
- Added new RButton component for consistent button styling.
- Improved LabelsView to support tag selection on iPad and iPhone.
- Updated SettingsGeneralView and SettingsGeneralViewModel for new TTS logic and removed unused app info code.
- Added app info section to SettingsContainerView.
- Updated SettingsServerView to use English labels and messages.
- Refactored SpeechPlayerViewModel to only initialize TTS when enabled.
- Updated Core Data model to include enableTTS in SettingEntity.
- Removed obsolete files (PersistenceController.swift, old PlayerUIState).
- Various bugfixes, code cleanups, and UI improvements.
2025-07-21 23:37:37 +02:00
07384215eb Add documentation and tools, refactor BookmarksView for DI, update mocks, and improve project structure
- Add CHANGELOG.md, CODE_OF_CONDUCT.md, and Contribute.md for documentation and community standards
- Add tools/add_spdx_header.sh for SPDX license header management
- Refactor BookmarksView and BookmarksViewModel to support dependency injection via UseCaseFactory
- Add retroactive extension for String: Identifiable in StringExtension.swift
- Update MockUseCaseFactory and MockGetBookmarksUseCase to provide mock data for previews and tests
- Update README.md: add TestFlight info, changelog link, HTTPS/local network note, and move planned features to changelog
2025-07-18 13:36:47 +02:00
930779169b feat: introduce protocol-based UseCase architecture and mock factory
- Add protocols for all UseCases and implement them in their respective classes
- Add DefaultUseCaseFactory and MockUseCaseFactory for dependency injection
- Implement all mock UseCases with dummy data
- Start migration of view models and views to protocol-based UseCase injection (not all migrated yet)
- Refactor previews and some initializers for easier testing
- Move SectionHeader to Components, update server settings UI text
- Add sample article.html for mock content
2025-07-18 00:46:07 +02:00
Ilyas Hallak
789d581705 Integrate Settings with WebView font customization
- Connect SettingsView font selection to WebView CSS rendering
- Add dynamic font size and family mapping in WebView
- Implement CSS custom properties for responsive font scaling
- Add font family fallback stacks for cross-platform compatibility
- Update WebView to use Settings object for typography configuration
2025-06-15 00:56:19 +02:00
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
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