fix: ensure epub content does not go behind in-screen cameras #3

Merged
fmartingr merged 2 commits from epub-safearea into master 2026-02-12 22:46:09 +01:00

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:flutter_epub_viewer/flutter_epub_viewer.dart'; import 'package:flutter_epub_viewer/flutter_epub_viewer.dart';
@ -74,6 +75,9 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
// Keep screen awake while reading // Keep screen awake while reading
WakelockPlus.enable(); WakelockPlus.enable();
// Enter immersive mode to hide system bars (matching image reader behavior)
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
} }
Future<void> _loadEpub() async { Future<void> _loadEpub() async {
@ -476,7 +480,8 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
const minWidthForDualPage = 768.0; const minWidthForDualPage = 768.0;
final shouldUseDualPage = screenWidth >= minWidthForDualPage; final shouldUseDualPage = screenWidth >= minWidthForDualPage;
return EpubViewer( return SafeArea(
child: EpubViewer(
key: ValueKey( key: ValueKey(
'$_viewerKey-${shouldUseDualPage ? "dual" : "single"}'), // Include spread in key to force recreation '$_viewerKey-${shouldUseDualPage ? "dual" : "single"}'), // Include spread in key to force recreation
epubController: _epubController!, epubController: _epubController!,
@ -492,6 +497,7 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
// Future: Handle text selection for highlights/notes // Future: Handle text selection for highlights/notes
debugPrint('Selected: ${selection.selectedText}'); debugPrint('Selected: ${selection.selectedText}');
}, },
),
); );
}, },
), ),
@ -646,8 +652,10 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
}); });
if (_showAppBar) { if (_showAppBar) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
_startAutoHideTimer(); _startAutoHideTimer();
} else { } else {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
_cancelAutoHideTimer(); _cancelAutoHideTimer();
} }
} }
@ -660,6 +668,7 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
setState(() { setState(() {
_showAppBar = false; _showAppBar = false;
}); });
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
} }
}); });
} }
@ -676,6 +685,7 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
setState(() { setState(() {
_showAppBar = false; _showAppBar = false;
}); });
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
} }
/// Build custom app bar overlay /// Build custom app bar overlay
@ -796,6 +806,9 @@ class _EpubReaderScreenState extends ConsumerState<EpubReaderScreen> {
// Allow screen to sleep again // Allow screen to sleep again
WakelockPlus.disable(); WakelockPlus.disable();
// Restore system UI bars when leaving the reader
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
// Clean up WebView resources to prevent OOM crashes // Clean up WebView resources to prevent OOM crashes
// The EpubController holds a reference to the InAppWebViewController // The EpubController holds a reference to the InAppWebViewController
// which needs to be properly disposed // which needs to be properly disposed