1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'framework.dart';
6import 'navigator.dart';
7import 'routes.dart';
8
9/// Registers a callback to veto attempts by the user to dismiss the enclosing
10/// [ModalRoute].
11///
12/// See also:
13///
14/// * [ModalRoute.addScopedWillPopCallback] and [ModalRoute.removeScopedWillPopCallback],
15/// which this widget uses to register and unregister [onWillPop].
16/// * [Form], which provides an `onWillPop` callback that enables the form
17/// to veto a `pop` initiated by the app's back button.
18@Deprecated(
19 'Use PopScope instead. '
20 'This feature was deprecated after v3.12.0-1.0.pre.',
21)
22class WillPopScope extends StatefulWidget {
23 /// Creates a widget that registers a callback to veto attempts by the user to
24 /// dismiss the enclosing [ModalRoute].
25 @Deprecated(
26 'Use PopScope instead. '
27 'This feature was deprecated after v3.12.0-1.0.pre.',
28 )
29 const WillPopScope({
30 super.key,
31 required this.child,
32 required this.onWillPop,
33 });
34
35 /// The widget below this widget in the tree.
36 ///
37 /// {@macro flutter.widgets.ProxyWidget.child}
38 final Widget child;
39
40 /// Called to veto attempts by the user to dismiss the enclosing [ModalRoute].
41 ///
42 /// If the callback returns a Future that resolves to false, the enclosing
43 /// route will not be popped.
44 final WillPopCallback? onWillPop;
45
46 @override
47 State<WillPopScope> createState() => _WillPopScopeState();
48}
49
50class _WillPopScopeState extends State<WillPopScope> {
51 ModalRoute<dynamic>? _route;
52
53 @override
54 void didChangeDependencies() {
55 super.didChangeDependencies();
56 if (widget.onWillPop != null) {
57 _route?.removeScopedWillPopCallback(widget.onWillPop!);
58 }
59 _route = ModalRoute.of(context);
60 if (widget.onWillPop != null) {
61 _route?.addScopedWillPopCallback(widget.onWillPop!);
62 }
63 }
64
65 @override
66 void didUpdateWidget(WillPopScope oldWidget) {
67 super.didUpdateWidget(oldWidget);
68 if (widget.onWillPop != oldWidget.onWillPop && _route != null) {
69 if (oldWidget.onWillPop != null) {
70 _route!.removeScopedWillPopCallback(oldWidget.onWillPop!);
71 }
72 if (widget.onWillPop != null) {
73 _route!.addScopedWillPopCallback(widget.onWillPop!);
74 }
75 }
76 }
77
78 @override
79 void dispose() {
80 if (widget.onWillPop != null) {
81 _route?.removeScopedWillPopCallback(widget.onWillPop!);
82 }
83 super.dispose();
84 }
85
86 @override
87 Widget build(BuildContext context) => widget.child;
88}
89