mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-01 21:59:43 +02:00
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:
1 parent
13b917d1a0
commit
7ca032b3f5
6 files changed
+193
-207
No files matched your search
@@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in new issue
Block a user