15 Commits

Author SHA1 Message Date
db3cbf41d4 Fix URL label translation and formatting
- Add localization keys for "open_url" and "open_original_page" in EN/DE
- Create URLUtil.openUrlLabel() helper function for consistent formatting
- Replace incorrect string concatenation with proper localized labels
- Fix: "example.comopen" now displays as "Open example.com" (EN) or "example.com öffnen" (DE)
- Update BookmarkDetailLegacyView, BookmarkDetailView2, and BookmarkCardView
2025-10-30 21:14:40 +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
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
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
e61dbc7d72 feat: Add iOS 26 native WebView with floating action buttons and improved header
BookmarkDetailView2 enhancements:
- Implement floating action buttons with iOS 26 GlassEffect
- Buttons appear at 90% reading progress with slide-up animation
- Use GlassEffectContainer with liquid glass interaction effect
- Position buttons in bottom-right corner with spring animation
- Auto-hide when scrolling back above 90%

Header image improvements:
- Use aspect fit with blurred background for better image display
- Prevents random cropping of header images
- Maintains full image visibility while filling header space

Debug-only features:
- Add #if DEBUG wrapper for view toggle buttons
- Toggle between legacy and native WebView only in debug builds

Technical details:
- GlassEffectContainer with 52pt buttons and 31pt icons
- Spring animation (response: 0.6, damping: 0.8)
- Combined move and opacity transitions
- Full screen ScrollView with bottom safe area extension
- Blurred background layer for non-filling images
2025-10-14 13:53:31 +02:00
a5d94d1aee feat: Implement performant scroll progress tracking with PreferenceKey
Replace onScrollGeometryChange/onScrollPhaseChange with ContentHeightPreferenceKey
approach for improved scroll performance and accurate read progress tracking.

Changes:
- Add ScrollOffsetPreferenceKey and ContentHeightPreferenceKey for scroll tracking
- Track content end position dynamically as WebView loads
- Calculate progress from scroll offset relative to total scrollable content
- Implement 3% threshold for progress updates to reduce API calls
- Add progress locking at 100% to prevent pixel-variation regressions
- Guarantee 100% update when reaching end of content
- Apply to both BookmarkDetailLegacyView and BookmarkDetailView2

Technical approach:
- Place invisible marker at end of content to measure position in scrollView
- Update initialContentEndPosition as content grows during WebView loading
- Progress = (initialPosition - currentPosition) / (initialPosition - containerHeight)
- Lock progress once 100% reached to avoid 100% -> 99% fluctuations
2025-10-12 20:56:59 +02:00
bef6a9dc2f fix: Use total content height for read progress calculation
Added ContentHeightPreferenceKey to track the total ScrollView content height.

The bug: Progress was calculated using only webViewHeight - containerHeight,
which ignores the header, title, and other content above the webview.

The fix: Use total content height (header + title + webview + archive section)
instead of just webViewHeight for accurate progress calculation.

Changes:
- Added ContentHeightPreferenceKey preference key
- Added contentHeight state variable
- Added background GeometryReader to VStack to measure total content height
- Changed progress calculation: contentHeight - containerHeight (not webViewHeight)

Applied to both BookmarkDetailLegacyView and BookmarkDetailView2.
2025-10-10 20:27:17 +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
e9195351aa perf: Optimize scroll tracking with PreferenceKey instead of onScrollGeometryChange
- Implemented ScrollOffsetPreferenceKey for performance-optimized scroll tracking
- Added invisible GeometryReader at top of ScrollView to track offset
- Replaced onScrollGeometryChange + onScrollPhaseChange with onPreferenceChange
- Removed currentScrollOffset and scrollViewHeight state variables
- Continuous tracking with 3% threshold check in onPreferenceChange
- Updated JumpButton to receive containerHeight as parameter

PreferenceKey approach is more performant than onScrollGeometryChange:
- Single preference update instead of multiple geometry changes
- Direct access to scroll coordinate space
- Simpler state management with lastSentProgress threshold
2025-10-10 15:49:48 +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