From eadf7a94c1b12edb62a127532661655634aa03e0 Mon Sep 17 00:00:00 2001 From: "Felipe M." Date: Thu, 12 Feb 2026 22:38:02 +0100 Subject: [PATCH] fix: ensure epub content does not go behind in-screen cameras --- lib/screens/reader/epub_reader_screen.dart | 45 ++++++++++++++-------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/screens/reader/epub_reader_screen.dart b/lib/screens/reader/epub_reader_screen.dart index 92b00c9..c0cf88e 100644 --- a/lib/screens/reader/epub_reader_screen.dart +++ b/lib/screens/reader/epub_reader_screen.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:flutter_epub_viewer/flutter_epub_viewer.dart'; @@ -73,6 +74,9 @@ class _EpubReaderScreenState extends ConsumerState { // Keep screen awake while reading WakelockPlus.enable(); + + // Enter immersive mode to hide system bars (matching image reader behavior) + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); } Future _loadEpub() async { @@ -464,22 +468,24 @@ class _EpubReaderScreenState extends ConsumerState { const minWidthForDualPage = 768.0; final shouldUseDualPage = screenWidth >= minWidthForDualPage; - return EpubViewer( - key: ValueKey( - '$_viewerKey-${shouldUseDualPage ? "dual" : "single"}'), // Include spread in key to force recreation - epubController: _epubController!, - epubSource: EpubSource.fromFile(_epubFile!), - initialCfi: _initialCfi, - displaySettings: _buildDisplaySettings(orientation), - onEpubLoaded: () { - debugPrint('EPUB loaded successfully'); - }, - onChaptersLoaded: _handleChaptersLoaded, - onRelocated: _handleRelocated, - onTextSelected: (selection) { - // Future: Handle text selection for highlights/notes - debugPrint('Selected: ${selection.selectedText}'); - }, + return SafeArea( + child: EpubViewer( + key: ValueKey( + '$_viewerKey-${shouldUseDualPage ? "dual" : "single"}'), // Include spread in key to force recreation + epubController: _epubController!, + epubSource: EpubSource.fromFile(_epubFile!), + initialCfi: _initialCfi, + displaySettings: _buildDisplaySettings(orientation), + onEpubLoaded: () { + debugPrint('EPUB loaded successfully'); + }, + onChaptersLoaded: _handleChaptersLoaded, + onRelocated: _handleRelocated, + onTextSelected: (selection) { + // Future: Handle text selection for highlights/notes + debugPrint('Selected: ${selection.selectedText}'); + }, + ), ); }, ), @@ -630,8 +636,10 @@ class _EpubReaderScreenState extends ConsumerState { }); if (_showAppBar) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); _startAutoHideTimer(); } else { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); _cancelAutoHideTimer(); } } @@ -644,6 +652,7 @@ class _EpubReaderScreenState extends ConsumerState { setState(() { _showAppBar = false; }); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); } }); } @@ -660,6 +669,7 @@ class _EpubReaderScreenState extends ConsumerState { setState(() { _showAppBar = false; }); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); } /// Build custom app bar overlay @@ -779,6 +789,9 @@ class _EpubReaderScreenState extends ConsumerState { // Allow screen to sleep again WakelockPlus.disable(); + // Restore system UI bars when leaving the reader + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + // Clean up WebView resources to prevent OOM crashes // The EpubController holds a reference to the InAppWebViewController // which needs to be properly disposed -- 2.52.0