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/assets.gen.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.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_actions.dart';
|
||||||
import 'package:spotube/modules/player/player_controls.dart';
|
import 'package:spotube/modules/player/player_controls.dart';
|
||||||
import 'package:spotube/modules/player/player_queue.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;
|
final topPadding = MediaQueryData.fromView(View.of(context)).padding.top;
|
||||||
|
|
||||||
// ignore: deprecated_member_use
|
return AppPopScope(
|
||||||
return WillPopScope(
|
canPop: context.canPop(),
|
||||||
onWillPop: () async {
|
onPopInvoked: (didPop) async {
|
||||||
|
if (didPop) return;
|
||||||
await panelController.close();
|
await panelController.close();
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: IconTheme(
|
child: IconTheme(
|
||||||
data: theme.iconTheme.copyWith(color: bodyTextColor),
|
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:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.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/modules/player/player_queue.dart';
|
||||||
import 'package:spotube/components/dialogs/replace_downloaded_dialog.dart';
|
import 'package:spotube/components/dialogs/replace_downloaded_dialog.dart';
|
||||||
import 'package:spotube/modules/root/bottom_player.dart';
|
import 'package:spotube/modules/root/bottom_player.dart';
|
||||||
@ -30,10 +31,12 @@ class RootApp extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final routerState = GoRouterState.of(context);
|
||||||
|
|
||||||
final showingDialogCompleter = useRef(Completer()..complete());
|
final showingDialogCompleter = useRef(Completer()..complete());
|
||||||
final downloader = ref.watch(downloadManagerProvider);
|
final downloader = ref.watch(downloadManagerProvider);
|
||||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||||
final theme = Theme.of(context);
|
|
||||||
final connectRoutes = ref.watch(serverConnectRoutesProvider);
|
final connectRoutes = ref.watch(serverConnectRoutesProvider);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
@ -164,15 +167,17 @@ class RootApp extends HookConsumerWidget {
|
|||||||
return null;
|
return null;
|
||||||
}, [backgroundColor]);
|
}, [backgroundColor]);
|
||||||
|
|
||||||
// ignore: deprecated_member_use
|
return AppPopScope(
|
||||||
return WillPopScope(
|
// Only allow to pop when in root screen
|
||||||
onWillPop: () async {
|
canPop: routerState.namedLocation(HomePage.name) ==
|
||||||
|
routerState.matchedLocation,
|
||||||
|
onPopInvoked: (didPop) async {
|
||||||
|
if (didPop) return;
|
||||||
|
|
||||||
final routerState = GoRouterState.of(context);
|
final routerState = GoRouterState.of(context);
|
||||||
if (routerState.matchedLocation != "/") {
|
if (routerState.matchedLocation != "/") {
|
||||||
context.goNamed(HomePage.name);
|
context.goNamed(HomePage.name);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: Sidebar(child: child),
|
body: Sidebar(child: child),
|
||||||
|
@ -1006,10 +1006,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: c5fa45fa502ee880839e3b2152d987c44abae26d064a2376d4aad434cf0f7b15
|
sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "12.1.3"
|
version: "14.2.7"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -51,7 +51,6 @@ dependencies:
|
|||||||
flutter_svg: ^1.1.6
|
flutter_svg: ^1.1.6
|
||||||
form_validator: ^2.1.1
|
form_validator: ^2.1.1
|
||||||
fuzzywuzzy: ^1.1.6
|
fuzzywuzzy: ^1.1.6
|
||||||
go_router: 12.1.3 # Stuck on this https://github.com/flutter/flutter/issues/140869
|
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
@ -135,6 +134,7 @@ dependencies:
|
|||||||
sqlite3_flutter_libs: ^0.5.23
|
sqlite3_flutter_libs: ^0.5.23
|
||||||
sqlite3: ^2.4.3
|
sqlite3: ^2.4.3
|
||||||
encrypt: ^5.0.3
|
encrypt: ^5.0.3
|
||||||
|
go_router: ^14.2.7
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.9
|
build_runner: ^2.4.9
|
||||||
|
Loading…
Reference in New Issue
Block a user