auto_route_library icon indicating copy to clipboard operation
auto_route_library copied to clipboard

[Hero] not working as expected on [web] when `includePrefixMatches` is set to `true`

Open a-h-mzd opened this issue 1 year ago • 23 comments

Steps to reproduce:

  1. Create a simple app with two screens each containing a Hero widget with its transitionOnUserGestures set to true.
  2. Assign these routes to them:
    • /
    • /second
  3. Set includePrefixMatches to true
  4. Open the app and navigate to the second screen.
  5. Reload the page.
  6. Try to go back using a swipe gesture to see the issue.

Screen record

https://github.com/Milad-Akarie/auto_route_library/assets/42738288/ecb30a95-b4aa-4a96-a6bc-764dd63b4d9c

Versions:

flutter: 3.10.6 auto_route: 7.7.1 auto_route_generator: 7.2.0

Stack trace:

══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Assertion failed:
packages/flutter/src/widgets/heroes.dart 477:12
box.hasSize && box.size.isFinite
is not true
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49  throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3    assertFailed
packages/flutter/src/widgets/heroes.dart 477:30                               _boundingBoxFor
packages/flutter/src/widgets/heroes.dart 493:36                               get toHeroLocation
packages/flutter/src/widgets/heroes.dart 502:53                               get isValid
packages/flutter/src/widgets/heroes.dart 957:39                               [_startHeroTransition]
packages/flutter/src/widgets/heroes.dart 872:9                                [_maybeStartHeroTransition]
packages/flutter/src/widgets/heroes.dart 813:5                                didStartUserGesture
packages/flutter/src/widgets/navigator.dart 5187:17                           didStartUserGesture
packages/flutter/src/cupertino/route.dart 711:15                              new
packages/flutter/src/cupertino/route.dart 241:12                              _startPopGesture
packages/flutter/src/cupertino/route.dart 288:36                              <fn>
packages/flutter/src/cupertino/route.dart 624:54                              [_handleDragStart]
packages/flutter/src/gestures/monodrag.dart 497:45                            <fn>
packages/flutter/src/gestures/recognizer.dart 275:24                          invokeCallback
packages/flutter/src/gestures/monodrag.dart 497:7                             [_checkStart]
packages/flutter/src/gestures/monodrag.dart 420:7                             acceptGesture
packages/flutter/src/gestures/arena.dart 268:10                               [_resolveByDefault]
packages/flutter/src/gestures/arena.dart 248:31                               callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 177:15           <fn>
Handler: "onStart"
Recognizer:
  HorizontalDragGestureRecognizer#e42fb
════════════════════════════════════════════════════════════════════════════════════════════════════

a-h-mzd avatar Aug 01 '23 09:08 a-h-mzd

Hey @a-h-mzd does this work with includePrefixmatches set to false?

Milad-Akarie avatar Aug 03 '23 13:08 Milad-Akarie

Hey @Milad-Akarie. in that case there are no screens behind the current one because we have just reloaded the screen. Am I right?

a-h-mzd avatar Aug 03 '23 13:08 a-h-mzd

@a-h-mzd You are right, so in your case there are actual a page behind active route but the transaction not working?

Milad-Akarie avatar Aug 03 '23 13:08 Milad-Akarie

@Milad-Akarie Correct. Also, interactivity is lost if you try to pop using a gesture. You can check the stack trace and the video to see this.

a-h-mzd avatar Aug 03 '23 13:08 a-h-mzd

@Milad-Akarie I can send you a minimum working project so you can see the error for yourself if this would help.

a-h-mzd avatar Aug 03 '23 13:08 a-h-mzd

@a-h-mzd that would be great, I've noticed that you're initiating your router inside of the build method which can cause a lot of issues, remove it from the build method first then see if you still get issues.

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

class MyApp extends StatelessWidget {
   MyApp();
   
  final _rootRouter = RootRouter();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _rootRouter.config(),
    );
  }

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

I'm initiating it this way only in this example project and not in the actual project that I'm working on. And I can tell you that the issue persists.

a-h-mzd avatar Aug 03 '23 14:08 a-h-mzd

I see, I'm waiting for minimum project that reproduces this issue.

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

main.dart

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Test',
      theme: ThemeData.light(),
      routerConfig: AppRouter().config(
        includePrefixMatches: true,
      ),
    );
  }
}

page1.dart

@RoutePage()
class Page1 extends StatelessWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Hero(
          tag: #tag,
          transitionOnUserGestures: true,
          child: FloatingActionButton(
            heroTag: null,
            onPressed: () => context.navigateTo(const Route2()),
            child: const Icon(Icons.arrow_forward_ios_rounded),
          ),
        ),
      ),
    );
  }
}

page2.dart

@RoutePage()
class Page2 extends StatelessWidget {
  const Page2({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Hero(
          tag: #tag,
          transitionOnUserGestures: true,
          child: FloatingActionButton(
            heroTag: null,
            onPressed: () => context.back(),
            child: const Icon(Icons.arrow_back_ios_new_rounded),
          ),
        ),
      ),
    );
  }
}

router.dart

@AutoRouterConfig()
final class AppRouter extends $AppRouter {
  @override
  List<AutoRoute> get routes {
    return <AutoRoute>[
      AutoRoute(
        path: '/',
        page: Route1.page,
      ),
      AutoRoute(
        path: '/second',
        page: Route2.page,
      ),
    ];
  }
}

a-h-mzd avatar Aug 03 '23 14:08 a-h-mzd

@a-h-mzd what does this hashtag mean? tag: #tag. this's new to me

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

@a-h-mzd When working for the web you should use context.router.back() instead of router.pop() or the shortcut context.back() because that's the same as clicking the browser's back button, on the other hand popping routes will add duplicate entries and complicate things on the web.

also, consider using context.router.navigate instead of context.router.push on the web so you avoid duplicate entries

shortcut: context.navigateTo(route)

try again with these suggestions and let me know what you get

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

@Milad-Akarie the hashtag is how you'd define a Symbol. Since the hero tag can be anything I prefer using a hashtag to create a symbol for it.

a-h-mzd avatar Aug 03 '23 14:08 a-h-mzd

@Milad-Akarie Thank you for the great advice. I updated the minimum project that reproduces this issue. Should I use those methods only on the web or are they safe to use also on other platforms? FYI the issue persists!

a-h-mzd avatar Aug 03 '23 14:08 a-h-mzd

ya they're preferred to be used in Web Apps, especially the back() method, what I also did is remove the initializing of the route from the build method.

class MyApp extends StatelessWidget {
    MyApp({super.key});
  final router = TestAppRouter();
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Test',
      theme: ThemeData.light(),
      routerConfig: router.config(
        includePrefixMatches: true,
      ),
    );
  }
}

I'm not getting any errors any more, everything works nicely

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

https://github.com/Milad-Akarie/auto_route_library/assets/55059449/a59d04e4-8408-48a4-8213-59a2330ca528

Milad-Akarie avatar Aug 03 '23 14:08 Milad-Akarie

Are you sure? Because I still get the error.

https://github.com/Milad-Akarie/auto_route_library/assets/42738288/9c55b033-f24e-43f8-8637-69a1d5c3ecf6

Make sure to use gestures to go back not click on the button.

a-h-mzd avatar Aug 03 '23 14:08 a-h-mzd

@Milad-Akarie, Is there anything else I can provide you with?

a-h-mzd avatar Aug 07 '23 14:08 a-h-mzd

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Oct 07 '23 08:10 github-actions[bot]

Commenting to prevent issue from getting closed.

a-h-mzd avatar Oct 07 '23 08:10 a-h-mzd

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Nov 07 '23 08:11 github-actions[bot]

Commenting to remove the no-issue-activity tag.

a-h-mzd avatar Nov 07 '23 08:11 a-h-mzd

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Dec 08 '23 08:12 github-actions[bot]