fix: remove unnecessary PopScope to prevent back gesture freeze

Removes PopScope wrapper from settings pages that don't need it.
PopScope with canPop: true was causing race condition with Android
gesture navigation, freezing the app.
This commit is contained in:
zarzet committed 2026-01-13 18:18:41 +07:00
1 parent 13b917d1a0
commit 7ca032b3f5
6 files changed
+193 -207

No files matched your search

+1
View File
@@ -22,6 +22,7 @@
### Fixed ### Fixed
- Extension packages now preserve directory structure (subdirectories supported) - Extension packages now preserve directory structure (subdirectories supported)
- Back gesture freeze in settings pages on Android gesture navigation
--- ---
+37 -40
View File
@@ -12,46 +12,44 @@ class AboutPage extends StatelessWidget {
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
return PopScope( return Scaffold(
canPop: true, body: CustomScrollView(
child: Scaffold( slivers: [
body: CustomScrollView( // Collapsing App Bar with back button
slivers: [ SliverAppBar(
// Collapsing App Bar with back button expandedHeight: 120 + topPadding,
SliverAppBar( collapsedHeight: kToolbarHeight,
expandedHeight: 120 + topPadding, floating: false,
collapsedHeight: kToolbarHeight, pinned: true,
floating: false, backgroundColor: colorScheme.surface,
pinned: true, surfaceTintColor: Colors.transparent,
backgroundColor: colorScheme.surface, leading: IconButton(
surfaceTintColor: Colors.transparent, icon: const Icon(Icons.arrow_back),
leading: IconButton( onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio = ((constraints.maxHeight - minHeight) / (maxHeight - minHeight)).clamp(0.0, 1.0);
// When collapsed (expandRatio=0): left=56 to avoid back button
// When expanded (expandRatio=1): left=24 for normal padding
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(left: leftPadding, bottom: 16),
title: Text(
'About',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
), ),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio = ((constraints.maxHeight - minHeight) / (maxHeight - minHeight)).clamp(0.0, 1.0);
// When collapsed (expandRatio=0): left=56 to avoid back button
// When expanded (expandRatio=1): left=24 for normal padding
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(left: leftPadding, bottom: 16),
title: Text(
'About',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
),
// App header card with logo and description // App header card with logo and description
SliverToBoxAdapter( SliverToBoxAdapter(
@@ -220,7 +218,6 @@ class AboutPage extends StatelessWidget {
const SliverToBoxAdapter(child: SizedBox(height: 16)), const SliverToBoxAdapter(child: SizedBox(height: 16)),
], ],
), ),
),
); );
} }
@@ -14,28 +14,26 @@ class AppearanceSettingsPage extends ConsumerWidget {
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
return PopScope( return Scaffold(
canPop: true, body: CustomScrollView(
child: Scaffold( slivers: [
body: CustomScrollView( // Collapsing App Bar with back button
slivers: [ SliverAppBar(
// Collapsing App Bar with back button expandedHeight: 120 + topPadding,
SliverAppBar( collapsedHeight: kToolbarHeight,
expandedHeight: 120 + topPadding, floating: false,
collapsedHeight: kToolbarHeight, pinned: true,
floating: false, backgroundColor: colorScheme.surface,
pinned: true, surfaceTintColor: Colors.transparent,
backgroundColor: colorScheme.surface, leading: IconButton(
surfaceTintColor: Colors.transparent, icon: const Icon(Icons.arrow_back),
leading: IconButton( onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
flexibleSpace: _AppBarTitle(
title: 'Appearance',
topPadding: topPadding,
),
), ),
flexibleSpace: _AppBarTitle(
title: 'Appearance',
topPadding: topPadding,
),
),
// Preview Section // Preview Section
SliverToBoxAdapter( SliverToBoxAdapter(
@@ -131,8 +129,7 @@ class AppearanceSettingsPage extends ConsumerWidget {
), ),
], ],
), ),
), );
);
} }
} }
@@ -22,50 +22,48 @@ class DownloadSettingsPage extends ConsumerWidget {
// Check if current service is built-in (supports quality options) // Check if current service is built-in (supports quality options)
final isBuiltInService = _builtInServices.contains(settings.defaultService); final isBuiltInService = _builtInServices.contains(settings.defaultService);
return PopScope( return Scaffold(
canPop: true, body: CustomScrollView(
child: Scaffold( slivers: [
body: CustomScrollView( // Collapsing App Bar with back button
slivers: [ SliverAppBar(
// Collapsing App Bar with back button expandedHeight: 120 + topPadding,
SliverAppBar( collapsedHeight: kToolbarHeight,
expandedHeight: 120 + topPadding, floating: false,
collapsedHeight: kToolbarHeight, pinned: true,
floating: false, backgroundColor: colorScheme.surface,
pinned: true, surfaceTintColor: Colors.transparent,
backgroundColor: colorScheme.surface, leading: IconButton(
surfaceTintColor: Colors.transparent, icon: const Icon(Icons.arrow_back),
leading: IconButton( onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio =
((constraints.maxHeight - minHeight) /
(maxHeight - minHeight))
.clamp(0.0, 1.0);
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(
left: leftPadding,
bottom: 16,
),
title: Text(
'Download',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
), ),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio =
((constraints.maxHeight - minHeight) /
(maxHeight - minHeight))
.clamp(0.0, 1.0);
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(
left: leftPadding,
bottom: 16,
),
title: Text(
'Download',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
),
// Service section // Service section
const SliverToBoxAdapter( const SliverToBoxAdapter(
@@ -217,8 +215,7 @@ class DownloadSettingsPage extends ConsumerWidget {
const SliverToBoxAdapter(child: SizedBox(height: 32)), const SliverToBoxAdapter(child: SizedBox(height: 32)),
], ],
), ),
), );
);
} }
void _showFormatEditor(BuildContext context, WidgetRef ref, String current) { void _showFormatEditor(BuildContext context, WidgetRef ref, String current) {
+51 -54
View File
@@ -124,60 +124,58 @@ class _LogScreenState extends State<LogScreen> {
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
final logs = _filteredLogs; final logs = _filteredLogs;
return PopScope( return Scaffold(
canPop: true, body: CustomScrollView(
child: Scaffold( controller: _scrollController,
body: CustomScrollView( slivers: [
controller: _scrollController, // Collapsing App Bar with back button - same as other settings pages
slivers: [ SliverAppBar(
// Collapsing App Bar with back button - same as other settings pages expandedHeight: 120 + topPadding,
SliverAppBar( collapsedHeight: kToolbarHeight,
expandedHeight: 120 + topPadding, floating: false,
collapsedHeight: kToolbarHeight, pinned: true,
floating: false, backgroundColor: colorScheme.surface,
pinned: true, surfaceTintColor: Colors.transparent,
backgroundColor: colorScheme.surface, leading: IconButton(
surfaceTintColor: Colors.transparent, icon: const Icon(Icons.arrow_back),
leading: IconButton( onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.arrow_back), ),
onPressed: () => Navigator.pop(context), actions: [
IconButton(
icon: Icon(_autoScroll ? Icons.vertical_align_bottom : Icons.vertical_align_center),
tooltip: _autoScroll ? 'Auto-scroll ON' : 'Auto-scroll OFF',
onPressed: () => setState(() => _autoScroll = !_autoScroll),
), ),
actions: [ IconButton(
IconButton( icon: const Icon(Icons.copy),
icon: Icon(_autoScroll ? Icons.vertical_align_bottom : Icons.vertical_align_center), tooltip: 'Copy logs',
tooltip: _autoScroll ? 'Auto-scroll ON' : 'Auto-scroll OFF', onPressed: _copyLogs,
onPressed: () => setState(() => _autoScroll = !_autoScroll), ),
), PopupMenuButton<String>(
IconButton( icon: const Icon(Icons.more_vert),
icon: const Icon(Icons.copy), onSelected: (value) {
tooltip: 'Copy logs', switch (value) {
onPressed: _copyLogs, case 'share':
), _shareLogs();
PopupMenuButton<String>( break;
icon: const Icon(Icons.more_vert), case 'clear':
onSelected: (value) { _clearLogs();
switch (value) { break;
case 'share': }
_shareLogs(); },
break; itemBuilder: (context) => [
case 'clear': const PopupMenuItem(
_clearLogs(); value: 'share',
break; child: ListTile(
} leading: Icon(Icons.share),
}, title: Text('Share logs'),
itemBuilder: (context) => [ contentPadding: EdgeInsets.zero,
const PopupMenuItem(
value: 'share',
child: ListTile(
leading: Icon(Icons.share),
title: Text('Share logs'),
contentPadding: EdgeInsets.zero,
),
), ),
const PopupMenuItem( ),
value: 'clear', const PopupMenuItem(
child: ListTile( value: 'clear',
leading: Icon(Icons.delete_outline), child: ListTile(
leading: Icon(Icons.delete_outline),
title: Text('Clear logs'), title: Text('Clear logs'),
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
), ),
@@ -380,8 +378,7 @@ class _LogScreenState extends State<LogScreen> {
const SliverToBoxAdapter(child: SizedBox(height: 32)), const SliverToBoxAdapter(child: SizedBox(height: 32)),
], ],
), ),
), );
);
} }
} }
+42 -45
View File
@@ -17,50 +17,48 @@ class OptionsSettingsPage extends ConsumerWidget {
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
return PopScope( return Scaffold(
canPop: true, body: CustomScrollView(
child: Scaffold( slivers: [
body: CustomScrollView( // Collapsing App Bar with back button
slivers: [ SliverAppBar(
// Collapsing App Bar with back button expandedHeight: 120 + topPadding,
SliverAppBar( collapsedHeight: kToolbarHeight,
expandedHeight: 120 + topPadding, floating: false,
collapsedHeight: kToolbarHeight, pinned: true,
floating: false, backgroundColor: colorScheme.surface,
pinned: true, surfaceTintColor: Colors.transparent,
backgroundColor: colorScheme.surface, leading: IconButton(
surfaceTintColor: Colors.transparent, icon: const Icon(Icons.arrow_back),
leading: IconButton( onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio =
((constraints.maxHeight - minHeight) /
(maxHeight - minHeight))
.clamp(0.0, 1.0);
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(
left: leftPadding,
bottom: 16,
),
title: Text(
'Options',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
), ),
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
final maxHeight = 120 + topPadding;
final minHeight = kToolbarHeight + topPadding;
final expandRatio =
((constraints.maxHeight - minHeight) /
(maxHeight - minHeight))
.clamp(0.0, 1.0);
final leftPadding = 56 - (32 * expandRatio); // 56 -> 24
return FlexibleSpaceBar(
expandedTitleScale: 1.0,
titlePadding: EdgeInsets.only(
left: leftPadding,
bottom: 16,
),
title: Text(
'Options',
style: TextStyle(
fontSize: 20 + (8 * expandRatio), // 20 -> 28
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
);
},
),
),
// Search Source section // Search Source section
const SliverToBoxAdapter( const SliverToBoxAdapter(
@@ -273,8 +271,7 @@ class OptionsSettingsPage extends ConsumerWidget {
const SliverToBoxAdapter(child: SizedBox(height: 32)), const SliverToBoxAdapter(child: SizedBox(height: 32)),
], ],
), ),
), );
);
} }
void _showClearHistoryDialog( void _showClearHistoryDialog(