1. 09 Jan, 2024 1 commit
    • SharbelOkzan's avatar
      Introduce new Form validation method (#135578) · 0c40f21f
      SharbelOkzan authored
      Introduced `validateGranually` which, apart from announcing the errors to the UI, returns a `Map<Key, bool>` providing more granular validation details: The results of calling `validate` on each `FormField` and their corresponding widget keys.
      
      * related issue: #135363
      0c40f21f
  2. 25 Sep, 2023 1 commit
    • Edgar Jan's avatar
      Fix and Test Conditional Validator Behavior in FormField (#132714) · 79caa837
      Edgar Jan authored
      In the FormField widget, if a validator is initially set (and validation fails), then subsequently the validator is set to null, the form incorrectly retains its error state. This is not expected behavior as removing the validator should clear any validation errors.
      79caa837
  3. 20 Sep, 2023 1 commit
    • Greg Spencer's avatar
      Remove 'must be non-null' and 'must not be null' comments in widgets library (#134992) · 6e5134b0
      Greg Spencer authored
      ## Description
      
      This removes all of the comments that are of the form "so-and-so (must not be null|can ?not be null|must be non-null)" from the cases where those values are defines as non-nullable values.
      
      This PR removes them from the widgets library.
      
      This was done by hand, since it really didn't lend itself to scripting, so it needs to be more than just spot-checked, I think. I was careful to leave any comment that referred to parameters that were nullable, but I may have missed some.
      
      In addition to being no longer relevant after null safety has been made the default, these comments were largely fragile, in that it was easy for them to get out of date, and not be accurate anymore anyhow.
      
      This did create a number of constructor comments which basically say "Creates a [Foo].", but I don't really know how to avoid that in a large scale change, since there's not much you can really say in a lot of cases.  I think we might consider some leniency for constructors to the "Comment must be meaningful" style guidance (which we de facto have already, since there are a bunch of these).
      
      ## Related PRs
      - https://github.com/flutter/flutter/pull/134984
      - https://github.com/flutter/flutter/pull/134991
      - https://github.com/flutter/flutter/pull/134993
      - https://github.com/flutter/flutter/pull/134994
      
      ## Tests
       - Documentation only change.
      6e5134b0
  4. 22 Aug, 2023 1 commit
  5. 17 Aug, 2023 1 commit
  6. 10 Aug, 2023 1 commit
  7. 08 Aug, 2023 1 commit
  8. 04 Aug, 2023 1 commit
    • Justin McCandless's avatar
      Predictive back support for root routes (#120385) · dedd100e
      Justin McCandless authored
      This PR aims to support Android's predictive back gesture when popping the entire Flutter app.  Predictive route transitions between routes inside of a Flutter app will come later.
      
      <img width="200" src="https://user-images.githubusercontent.com/389558/217918109-945febaa-9086-41cc-a476-1a189c7831d8.gif" />
      
      ### Trying it out
      
      If you want to try this feature yourself, here are the necessary steps:
      
        1. Run Android 33 or above.
        1. Enable the feature flag for predictive back on the device under "Developer
           options".
        1. Create a Flutter project, or clone [my example project](https://github.com/justinmc/flutter_predictive_back_examples).
        1. Set `android:enableOnBackInvokedCallback="true"` in
           android/app/src/main/AndroidManifest.xml (already done in the example project).
        1. Check out this branch.
        1. Run the app. Perform a back gesture (swipe from the left side of the
           screen).
      
      You should see the predictive back animation like in the animation above and be able to commit or cancel it.
      
      ### go_router support
      
      go_router works with predictive back out of the box because it uses a Navigator internally that dispatches NavigationNotifications!
      
      ~~go_router can be supported by adding a listener to the router and updating SystemNavigator.setFrameworkHandlesBack.~~
      
      Similar to with nested Navigators, nested go_routers is supported by using a PopScope widget.
      
      <details>
      
      <summary>Full example of nested go_routers</summary>
      
      ```dart
      // Copyright 2014 The Flutter Authors. All rights reserved.
      // Use of this source code is governed by a BSD-style license that can be
      // found in the LICENSE file.
      
      import 'package:go_router/go_router.dart';
      
      import 'package:flutter/material.dart';
      import 'package:flutter/scheduler.dart';
      
      void main() => runApp(_MyApp());
      
      class _MyApp extends StatelessWidget {
        final GoRouter router = GoRouter(
          routes: <RouteBase>[
            GoRoute(
              path: '/',
              builder: (BuildContext context, GoRouterState state) => _HomePage(),
            ),
            GoRoute(
              path: '/nested_navigators',
              builder: (BuildContext context, GoRouterState state) => _NestedGoRoutersPage(),
            ),
          ],
        );
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp.router(
            routerConfig: router,
          );
        }
      }
      
      class _HomePage extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: const Text('Nested Navigators Example'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const Text('Home Page'),
                  const Text('A system back gesture here will exit the app.'),
                  const SizedBox(height: 20.0),
                  ListTile(
                    title: const Text('Nested go_router route'),
                    subtitle: const Text('This route has another go_router in addition to the one used with MaterialApp above.'),
                    onTap: () {
                      context.push('/nested_navigators');
                    },
                  ),
                ],
              ),
            ),
          );
        }
      }
      
      class _NestedGoRoutersPage extends StatefulWidget {
        @override
        State<_NestedGoRoutersPage> createState() => _NestedGoRoutersPageState();
      }
      
      class _NestedGoRoutersPageState extends State<_NestedGoRoutersPage> {
        late final GoRouter _router;
        final GlobalKey<NavigatorState> _nestedNavigatorKey = GlobalKey<NavigatorState>();
      
        // If the nested navigator has routes that can be popped, then we want to
        // block the root navigator from handling the pop so that the nested navigator
        // can handle it instead.
        bool get _popEnabled {
          // canPop will throw an error if called before build. Is this the best way
          // to avoid that?
          return _nestedNavigatorKey.currentState == null ? true : !_router.canPop();
        }
      
        void _onRouterChanged() {
          // Here the _router reports the location correctly, but canPop is still out
          // of date.  Hence the post frame callback.
          SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
            setState(() {});
          });
        }
      
        @override
        void initState() {
          super.initState();
      
          final BuildContext rootContext = context;
          _router = GoRouter(
            navigatorKey: _nestedNavigatorKey,
            routes: [
              GoRoute(
                path: '/',
                builder: (BuildContext context, GoRouterState state) => _LinksPage(
                  title: 'Nested once - home route',
                  backgroundColor: Colors.indigo,
                  onBack: () {
                    rootContext.pop();
                  },
                  buttons: <Widget>[
                    TextButton(
                      onPressed: () {
                        context.push('/two');
                      },
                      child: const Text('Go to another route in this nested Navigator'),
                    ),
                  ],
                ),
              ),
              GoRoute(
                path: '/two',
                builder: (BuildContext context, GoRouterState state) => _LinksPage(
                  backgroundColor: Colors.indigo.withBlue(255),
                  title: 'Nested once - page two',
                ),
              ),
            ],
          );
      
          _router.addListener(_onRouterChanged);
        }
      
        @override
        void dispose() {
          _router.removeListener(_onRouterChanged);
          super.dispose();
        }
      
        @override
        Widget build(BuildContext context) {
          return PopScope(
            popEnabled: _popEnabled,
            onPopped: (bool success) {
              if (success) {
                return;
              }
              _router.pop();
            },
            child: Router<Object>.withConfig(
              restorationScopeId: 'router-2',
              config: _router,
            ),
          );
        }
      }
      
      class _LinksPage extends StatelessWidget {
        const _LinksPage ({
          required this.backgroundColor,
          this.buttons = const <Widget>[],
          this.onBack,
          required this.title,
        });
      
        final Color backgroundColor;
        final List<Widget> buttons;
        final VoidCallback? onBack;
        final String title;
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            backgroundColor: backgroundColor,
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(title),
                  //const Text('A system back here will go back to Nested Navigators Page One'),
                  ...buttons,
                  TextButton(
                    onPressed: onBack ?? () {
                      context.pop();
                    },
                    child: const Text('Go back'),
                  ),
                ],
              ),
            ),
          );
        }
      }
      ```
      
      </details>
      
      ### Resources
      
      Fixes https://github.com/flutter/flutter/issues/109513
      Depends on engine PR https://github.com/flutter/engine/pull/39208 :heavy_check_mark: 
      Design doc: https://docs.google.com/document/d/1BGCWy1_LRrXEB6qeqTAKlk-U2CZlKJ5xI97g45U7azk/edit#
      Migration guide: https://github.com/flutter/website/pull/8952
      dedd100e
  9. 15 May, 2023 1 commit
  10. 29 Mar, 2023 1 commit
  11. 22 Mar, 2023 1 commit
  12. 24 Jan, 2023 1 commit
  13. 11 Dec, 2022 1 commit
  14. 31 Oct, 2022 1 commit
  15. 10 Aug, 2022 1 commit
  16. 26 May, 2022 1 commit
  17. 14 Apr, 2022 1 commit
  18. 15 Oct, 2021 1 commit
  19. 14 Oct, 2021 1 commit
  20. 07 Oct, 2021 1 commit
  21. 06 Oct, 2021 1 commit
  22. 04 Oct, 2021 1 commit
    • Greg Spencer's avatar
      Clean up examples, remove section markers and --template args (#91133) · fd9ce277
      Greg Spencer authored
      This does a cleanup of the examples, removing all of the "section" markers and extra comments that we don't need anymore now that the samples are no longer in the source code. It also removes the --template arguments from the {@tool dartpad} and {@tool sample} directives, since those are no longer used. It converts two examples that I discovered were still embedded into linked examples in the examples folder.
      
      I didn't delete the templates from the snippets config folder yet, because there are still embedded samples in the dart:ui package from the engine that use them. Once dart:ui no longer uses the templates, they can be removed.
      
      I bumped the version of the snippets package to pick up a change that allows removal of the --template argument.
      fd9ce277
  23. 25 Aug, 2021 1 commit
    • Greg Spencer's avatar
      Extract Sample code into examples/api (#87280) · 33403bd2
      Greg Spencer authored
      This extracts the sample code out from the API doc comments, and places them in separate files on disk, allowing running of the examples locally, testing them, and building of slightly larger examples.
      33403bd2
  24. 14 Apr, 2021 1 commit
  25. 31 Mar, 2021 2 commits
  26. 26 Mar, 2021 1 commit
  27. 12 Mar, 2021 1 commit
  28. 16 Jan, 2021 1 commit
  29. 24 Dec, 2020 1 commit
  30. 11 Dec, 2020 1 commit
  31. 02 Nov, 2020 1 commit
  32. 27 Oct, 2020 1 commit
  33. 28 Sep, 2020 1 commit
  34. 15 Sep, 2020 1 commit
    • Alexandre Ardhuin's avatar
      Reland "Nnbd widgets" (#65528) · b007a81a
      Alexandre Ardhuin authored
      * Reland "Nnbd widgets (#64672)"
      
      This reverts commit 127e6790.
      
      * remove non-nullable enforcement on AsyncSnapshot
      
      * make data param non-nullable for AsyncSnapshot.withData
      
      * make some Text params non-nullable
      b007a81a
  35. 09 Sep, 2020 2 commits
    • Michael Goderbauer's avatar
      Revert "Nnbd widgets (#64672)" (#65488) · 127e6790
      Michael Goderbauer authored
      This reverts commit e682ec71.
      127e6790
    • Alexandre Ardhuin's avatar
      Nnbd widgets (#64672) · e682ec71
      Alexandre Ardhuin authored
      * migrate widget to nullsafety
      
      * remove double blank line after license
      
      * address review comments in actions.dart
      
      * nullable ObjectKey.value
      
      * use local variable oldElement
      
      * make State.build non-nullable
      
      * make State.context non-nullable
      
      * newline at eof
      
      * make ProxyWidget.child non-nullable
      
      * make _InactiveElements.debugContains non-nullable
      
      * make Element.depth non-nullable
      
      * make ProxyElement.build non-nullable
      
      * make StatefulElement.state non-nullable
      
      * remove 'Notice that'
      
      * avoid cast of list in RenderObjectElement.updateChildren
      
      * make IndexedSlot.value non-nullable
      
      * avoid cast of list in MultiChildRenderObjectElement.mount
      
      * make some WidgetsApp parameters non-nullable
      
      * hitTest take non-nullable position
      
      * make ScrollableState.position non-nullable
      
      * use _pixels instead of pixels
      
      * make ViewportOffset.pixels non-nullable
      
      * make param and return type of IndexedWidgetBuilder non-nullable
      
      * unused_import
      
      * make context param non-nullable for Builder in animated_list.dart
      
      * make ScrollMetrics.viewportDimension non-nullable
      
      * make ScrollMetrics.{min,max}ScrollExtent non-nullable
      
      * make _Location.file non-nullable
      
      * _WidgetForTypeTests.createElement throw UnimplementedError
      
      * update _NullWidget.build error message
      
      * make _ShortcutsState.manager non-nullable
      
      * Fix childCount issues for NNBD
      
      * fix childCount computation on web
      
      * increase max value on js side to compute childCount
      
      * make aspect parameter of dependOnInheritedWidgetOfExactType nullable
      
      * merge has{min,max}ScrollExtent into hasScrollExtents
      
      * update focus_manager.dart
      
      * address review comments in icon.dart
      
      * address review comments in image.dart
      
      * address review comments in routes.dart
      
      * address review comments in scroll_activity.dart
      
      * update doc comments
      
      * make UserScrollNotification.direction non-nullable and required
      
      * rename hasScrollExtents to hasContentDimensions
      
      * unnecessary late
      Co-authored-by: 's avatarIan Hickson <ian@hixie.ch>
      e682ec71
  36. 02 Sep, 2020 1 commit
  37. 29 Jul, 2020 1 commit
  38. 28 Jul, 2020 1 commit