78794499a2
* fix(dictionary): keep other dictionaries usable when System Dictionary syncs to an unsupported platform `dictionarySettings.providerEnabled` is whole-field synced across devices, so enabling System Dictionary on macOS/iOS sets the flag on web/Linux/Windows too. There the row is hidden and the feature is a no-op, but the settings UI read the raw flag and locked every other dictionary's toggle read-only. Gate the lock on `isSystemDictionaryEnabled(settings)` — the same platform-aware check the annotator uses — so it matches real lookup behavior and never triggers where the system dictionary can't run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(dictionary): dispatch system dictionary handoff by native OS (fixes iPad) iPadOS sends a desktop "Macintosh" user agent, so the UA-based `getOSPlatform()` reported iPad as 'macos' and the handoff invoked the macOS-only `show_lookup_popover` Rust command that iOS never registers ("Command show_lookup_popover not found"). Derive the OS from the app service's `is*App` capability flags (sourced from the Tauri OS plugin, correct on iPad) via a new synchronous `getInitializedAppService()` accessor, so iPad routes to the iOS plugin command path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ui): constrain reader View Options dropdown to h-8 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(agent): note System Dictionary platform-detection and synced-flag patterns Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.6 KiB
4.6 KiB
Platform Compatibility Fixes Reference
Android
WebView API Issues
navigator.getGamepads()returns null on older WebView (#3245): Always null-check before.some()CompressionStreamunavailable on some Android WebView versions (#3255): Add fallback zip compression path- Annotation tools unresponsive (#3225): Don't call
makeSelection()immediately on pointer-up; let popup flow complete naturally - Safe inset updates (#3469): Call
onUpdateInsets()aftersetSystemUIVisibility() - Navigation bar overlap (#3466): Use
calc(env(safe-area-inset-bottom) + 16px)for bottom padding
General Android Rules
- Test with older WebView versions (97+)
- Always check API availability before calling Web APIs
- Touch event handling differs from iOS - avoid premature re-selection
iOS
Common Issues
- Slider touch dead zones (#3382): Strip native appearance, use larger hit areas (min-h-12)
- Safe area insets stale (#3395): Native Swift plugin must push updated insets
- Section content caching (#3242, #3206): Don't cache section content in foliate-js when updating subitems; cached content retains stale styles after mode switch
- CompressionStream (#3255): Also broken on iOS 15.x; zip.js has its own native API disable
- zip.js native API (#3170): Disable native
CompressionStream/DecompressionStreamon iOS 15.x
iPad reports a desktop UA → never branch native dispatch on getOSPlatform()
getOSPlatform()(utils/misc) is user-agent based, and iPadOS sends a desktop "Macintosh" UA → it returns'macos'on iPad. Any native-OS dispatch keyed on it misroutes iPad to the macOS path.- Symptom seen: system dictionary on iPad threw
"Command show_lookup_popover not found"— the macOS-only Rust command (src-tauri/src/macos/system_dictionary.rs); iOS only registers the plugin commandplugin:native-bridge|show_lookup_popover. - Rule: for OS-specific native dispatch/capability, use
appService.isIOSApp / isMacOSApp / isAndroidApp(derived from the Tauri OS plugintype()→OS_TYPEinnativeAppService.ts), NOTgetOSPlatform(). The misc.ts comment says this explicitly. - Sync, non-React modules:
getInitializedAppService()(environment.ts) returns the cached singleton synchronously (null pre-init). Used bysystemDictionary.tsforisSystemDictionarySupported()(sync) +invokeSystemDictionary()(async).
iOS-Specific Code
src-tauri/plugins/tauri-plugin-native-bridge/ios/Sources/NativeBridgePlugin.swift- Slider CSS:
-webkit-appearance: none; appearance: nonein globals.css useSafeAreaInsets.tshook
macOS
Traffic Lights (Window Controls)
- Check
isFullscreen()before hiding (#3129) - Use timeouts (100ms) for visibility transitions (#3488)
- Don't hide when sidebar is open (#3488)
Input Issues
- Context menu steals event loop (#3324): 100ms setTimeout before calling menu.popup()
- Touchpad natural scrolling (#3127): Respect system setting in
usePagination.ts - Two-finger swipe (#3127): Support trackpad two-finger swipe for pagination
macOS-Specific Code
src-tauri/src/macos/- Platform-specific Rust codesrc/store/trafficLightStore.tssrc/hooks/useTrafficLight.ts
Linux
WebKitGTK Issues
- View Transitions API unsupported (#3417): Feature-detect
document.startViewTransitionbefore calling - Use
useAppRouter.tsto avoid transitions on Linux
E-ink Devices
Legibility Issues
- Low contrast colors (#3258): Use
not-eink:Tailwind variant prefix for colors/opacity - Links invisible (#3258): Don't apply
text-primary(blue) on e-ink; use default text color - Opacity too low (#3258): Don't apply
opacity-60/opacity-75on e-ink devices - Highlight visibility (#3299): Use foreground color for highlights in dark mode e-ink
E-ink CSS Pattern
// Instead of:
className="text-primary opacity-60"
// Use:
className="not-eink:text-primary not-eink:opacity-60"
Docker/Self-Hosting
- Missing submodules (#3233): Run
git submodule update --init --recursivebefore build - Simplecc WASM module must be initialized
OPDS
- Non-ASCII credentials (#3436): Use
TextEncoder+ manual Base64 instead ofbtoa() - Author parsing (#3120): Handle varied metadata structures in OPDS 2.0 feeds
- Responsive layout (#3418): Ensure catalog and download button layout works on small screens
Cross-Platform Testing Checklist
- Android (old WebView + current)
- iOS (15.x + current)
- macOS (traffic lights, trackpad)
- Linux (WebKitGTK)
- E-ink devices (contrast, colors)
- Web (CloudFlare Workers deployment)