mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix(android): pressing back while the player is open doesn't take to previous page
#1388
This commit is contained in:
parent
9cb828bb55
commit
5ff36a8643
104
lib/components/framework/app_pop_scope.dart
Normal file
104
lib/components/framework/app_pop_scope.dart
Normal file
@ -0,0 +1,104 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A temporary workaround for [WillPopScope] and [PopScope] not working in GoRouter
|
||||
/// https://github.com/flutter/flutter/issues/140869#issuecomment-2247181468
|
||||
class AppPopScope extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
final PopInvokedCallback? onPopInvoked;
|
||||
|
||||
final bool canPop;
|
||||
|
||||
const AppPopScope({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.canPop = true,
|
||||
this.onPopInvoked,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AppPopScope> createState() => _AppPopScopeState();
|
||||
}
|
||||
|
||||
class _AppPopScopeState extends State<AppPopScope> {
|
||||
final bool _enable = Platform.isAndroid;
|
||||
ModalRoute? _route;
|
||||
BackButtonDispatcher? _parentBackBtnDispatcher;
|
||||
ChildBackButtonDispatcher? _backBtnDispatcher;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_route = ModalRoute.of(context);
|
||||
_updateBackButtonDispatcher();
|
||||
}
|
||||
|
||||
@override
|
||||
void activate() {
|
||||
super.activate();
|
||||
_updateBackButtonDispatcher();
|
||||
}
|
||||
|
||||
@override
|
||||
void deactivate() {
|
||||
super.deactivate();
|
||||
_disposeBackBtnDispatcher();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposeBackBtnDispatcher();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
canPop: widget.canPop,
|
||||
onPopInvoked: widget.onPopInvoked,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
void _updateBackButtonDispatcher() {
|
||||
if (!_enable) return;
|
||||
|
||||
var dispatcher = Router.maybeOf(context)?.backButtonDispatcher;
|
||||
if (dispatcher != _parentBackBtnDispatcher) {
|
||||
_disposeBackBtnDispatcher();
|
||||
_parentBackBtnDispatcher = dispatcher;
|
||||
if (dispatcher is BackButtonDispatcher &&
|
||||
dispatcher is! ChildBackButtonDispatcher) {
|
||||
dispatcher = dispatcher.createChildBackButtonDispatcher();
|
||||
}
|
||||
_backBtnDispatcher = dispatcher as ChildBackButtonDispatcher;
|
||||
}
|
||||
_backBtnDispatcher?.removeCallback(_handleBackButton);
|
||||
_backBtnDispatcher?.addCallback(_handleBackButton);
|
||||
_backBtnDispatcher?.takePriority();
|
||||
}
|
||||
|
||||
void _disposeBackBtnDispatcher() {
|
||||
_backBtnDispatcher?.removeCallback(_handleBackButton);
|
||||
if (_backBtnDispatcher is ChildBackButtonDispatcher) {
|
||||
final child = _backBtnDispatcher as ChildBackButtonDispatcher;
|
||||
_parentBackBtnDispatcher?.forget(child);
|
||||
}
|
||||
_backBtnDispatcher = null;
|
||||
_parentBackBtnDispatcher = null;
|
||||
}
|
||||
|
||||
bool get _onlyRoute => _route != null && _route!.isFirst && _route!.isCurrent;
|
||||
|
||||
Future<bool> _handleBackButton() async {
|
||||
if (_onlyRoute) {
|
||||
widget.onPopInvoked?.call(widget.canPop);
|
||||
if (!widget.canPop) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import 'package:spotube/collections/assets.gen.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/framework/app_pop_scope.dart';
|
||||
import 'package:spotube/modules/player/player_actions.dart';
|
||||
import 'package:spotube/modules/player/player_controls.dart';
|
||||
import 'package:spotube/modules/player/player_queue.dart';
|
||||
@ -100,11 +101,11 @@ class PlayerView extends HookConsumerWidget {
|
||||
|
||||
final topPadding = MediaQueryData.fromView(View.of(context)).padding.top;
|
||||
|
||||
// ignore: deprecated_member_use
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
return AppPopScope(
|
||||
canPop: context.canPop(),
|
||||
onPopInvoked: (didPop) async {
|
||||
if (didPop) return;
|
||||
await panelController.close();
|
||||
return false;
|
||||
},
|
||||
child: IconTheme(
|
||||
data: theme.iconTheme.copyWith(color: bodyTextColor),
|
||||
|
@ -6,6 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/framework/app_pop_scope.dart';
|
||||
import 'package:spotube/modules/player/player_queue.dart';
|
||||
import 'package:spotube/components/dialogs/replace_downloaded_dialog.dart';
|
||||
import 'package:spotube/modules/root/bottom_player.dart';
|
||||
@ -30,10 +31,12 @@ class RootApp extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final theme = Theme.of(context);
|
||||
final routerState = GoRouterState.of(context);
|
||||
|
||||
final showingDialogCompleter = useRef(Completer()..complete());
|
||||
final downloader = ref.watch(downloadManagerProvider);
|
||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final connectRoutes = ref.watch(serverConnectRoutesProvider);
|
||||
|
||||
useEffect(() {
|
||||
@ -164,15 +167,17 @@ class RootApp extends HookConsumerWidget {
|
||||
return null;
|
||||
}, [backgroundColor]);
|
||||
|
||||
// ignore: deprecated_member_use
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
return AppPopScope(
|
||||
// Only allow to pop when in root screen
|
||||
canPop: routerState.namedLocation(HomePage.name) ==
|
||||
routerState.matchedLocation,
|
||||
onPopInvoked: (didPop) async {
|
||||
if (didPop) return;
|
||||
|
||||
final routerState = GoRouterState.of(context);
|
||||
if (routerState.matchedLocation != "/") {
|
||||
context.goNamed(HomePage.name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
body: Sidebar(child: child),
|
||||
|
@ -1006,10 +1006,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: go_router
|
||||
sha256: c5fa45fa502ee880839e3b2152d987c44abae26d064a2376d4aad434cf0f7b15
|
||||
sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.3"
|
||||
version: "14.2.7"
|
||||
google_fonts:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -51,7 +51,6 @@ dependencies:
|
||||
flutter_svg: ^1.1.6
|
||||
form_validator: ^2.1.1
|
||||
fuzzywuzzy: ^1.1.6
|
||||
go_router: 12.1.3 # Stuck on this https://github.com/flutter/flutter/issues/140869
|
||||
google_fonts: ^6.2.1
|
||||
hive: ^2.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
@ -135,6 +134,7 @@ dependencies:
|
||||
sqlite3_flutter_libs: ^0.5.23
|
||||
sqlite3: ^2.4.3
|
||||
encrypt: ^5.0.3
|
||||
go_router: ^14.2.7
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.9
|
||||
|
Loading…
Reference in New Issue
Block a user