Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

customRouteBuilder's completion result type has broken in the 8.0.3 version #1913

Open
SergeShkurko opened this issue Apr 2, 2024 · 13 comments

Comments

@SergeShkurko
Copy link

SergeShkurko commented Apr 2, 2024

Now, return types don't work with customRouteBuilder correctly

Because of the last commit c2953fe. Type annotation removed from the function

/// Signature for custom router builder used by
/// [CustomRouteType]
-typedef CustomRouteBuilder = Route<T> Function<T>(
+typedef CustomRouteBuilder<T> = Route<T> Function(
  BuildContext context,
  Widget child,
  AutoRoutePage<T> page,
);

Then any reusable customRouteBuilder implementation will return Route with a dynamic type. We won't return any route with passed by router type. We need to handle generics inside the function. Like earlier

Screenshot 2024-04-03 at 03 27 02

More earlier versions work pretty

@Milad-Akarie
Copy link
Owner

@SergeShkurko try specifiying the type when returning your custom Route e.g DialogRoute<String>(....)

@LocLt-Mobile
Copy link

I have same issue.

@Skogsfrae
Copy link

@Milad-Akarie I'm running into the same problem mainly because I have a custom class that extends the CustomRoute class to avoid boilerplate code, so I can't explicitly pass the return type.

I have different CustomRoute classes with different animations that combined in the navigation stack perform different forward/back animations such as iOS modal animations styles.

class MyRoute extends CustomRoute {
  MyRoute({
    required super.page,
    ...
    super.opaque,
  }) : super(customRouteBuilder: <T>(BuildContext context,
    Widget child,
    AutoRoutePage<T> page,
  ) => MyRoutePage<T>(
              builder: (context) => child,
              settings: page,
            ));
}

I solved with this workaround that forces me to specify the return type in the navigation tree declaration too:

class MyRoute<R> extends CustomRoute {
  MyRoute({
    required super.page,
    ...
    super.opaque,
  }) : super(customRouteBuilder: (BuildContext context,
    Widget child,
    AutoRoutePage<T> page,
  ) => MyRoutePage<R>(
              builder: (context) => child,
              settings: page,
            ));
}

@Mik77o
Copy link

Mik77o commented Apr 18, 2024

We encounter the same issue for 8.0.3.

class DialogAutoRoute extends CustomRoute {
  DialogAutoRoute({
    required super.page,
    super.barrierDismissible,
    super.path,
  }) : super(
          opaque: false,
          transitionsBuilder: TransitionsBuilders.fadeIn,
          durationInMilliseconds: dialogAutoRouteDefaultDuration,
          reverseDurationInMilliseconds: dialogAutoRouteDefaultDuration,
          customRouteBuilder: <T>(context, child, routePage) => DialogRoute(
            context: context,
            builder: (_) => child,
            barrierDismissible: barrierDismissible,
            settings: routePage,
          ),
        );
}

sososdk added a commit to sososdk/auto_route_library that referenced this issue Apr 24, 2024
@vpohrebniako
Copy link

Any plans on fixing this issue?

niwaguan pushed a commit to niwaguan/auto_route that referenced this issue May 11, 2024
@Mixron469
Copy link

Still same issues for me when I upgrade auto_route to Ver. 8, with my both custom bottomSheet route and dialog route.

@akadatsky
Copy link

Any updates on this issue?

@Milad-Akarie
Copy link
Owner

Make sure your return type is exclusively provided in both annotation and route implementation.

@RoutePage<String>() /// this page returns a string value
class MyPage extends StatelessWidget {}
CustomRoute(
      page: MyRoute.page,
      customRouteBuilder: (context, child, page) {
        return MyCustomRoute<String>( // provide the same return type
          builder: (context) => child,
          settings: page,
        );
      },
    ),

@Mixron469
Copy link

Mixron469 commented Jul 18, 2024

Make sure your return type is exclusively provided in both annotation and route implementation.

@RoutePage<String>() /// this page returns a string value
class MyPage extends StatelessWidget {}
CustomRoute(
     page: MyRoute.page,
     customRouteBuilder: (context, child, page) {
       return MyCustomRoute<String>( // provide the same return type
         builder: (context) => child,
         settings: page,
       );
     },
   ),

@Milad-Akarie

My custom route screen is

@RoutePage<bool>(name: 'ProductInfoBottomSheetRoute')
class ProductInfoBottomSheet extends ConsumerWidget {
  const ProductInfoBottomSheet({
    super.key,
    @pathParam required this.productId,
  });

  final String productId;

my route is

        AppCustomBottomSheetRoute<bool>(
          path: 'warehouse/myorder/detail/:productId',
          page: ProductInfoBottomSheetRoute.page,
        ),

and my AppCustomBottomSheetRoute is

class AppCustomBottomSheetRoute<T> extends CustomRoute {
  AppCustomBottomSheetRoute({
    required String super.path,
    required super.page,
    super.barrierDismissible = false,
    Color? barrierColor,
    bool isScrollControlled = true,
    super.children,
  }) : super(
          opaque: false,
          barrierColor: barrierColor ?? Colors.black.withOpacity(0.48),
          fullscreenDialog: false,
          transitionsBuilder: TransitionsBuilders.noTransition,
          customRouteBuilder: <T>(BuildContext context, Widget child, AutoRoutePage<T> page) {
            return ModalBottomSheetRoute<T>(
              settings: page,
              builder: (context) => child,
              isScrollControlled: isScrollControlled,
            );
          },
        );
}

when I try to push like

await context.router.pushNamed<bool>('warehouse/myorder/detail/${item.id}').then((bool? value) {
            if (value ?? false) {
              Future.delayed(const Duration(milliseconds: 150), () {
                context.router.pushNamed('warehouse/edit-product/${item.id}');
              });
            }
          });

it will throw
Screenshot 2567-07-18 at 15 11 28

Note: this implementation work fine before upgrade to auto_route 8, after that upgrade, it throw me an error and I cannot work with custom route anymore

@Milad-Akarie
Copy link
Owner

Did you run the generator after setting @RoutePage

@Mixron469
Copy link

Mixron469 commented Jul 19, 2024

Did you run the generator after setting @RoutePage

@Milad-Akarie Yes, my router.gr.dart file is

    ProductInfoBottomSheetRoute.name: (routeData) {
      final pathParams = routeData.inheritedPathParams;
      final args = routeData.argsAs<ProductInfoBottomSheetRouteArgs>(
          orElse: () => ProductInfoBottomSheetRouteArgs(
              productId: pathParams.getString('productId')));
      return AutoRoutePage<bool>(
        routeData: routeData,
        child: ProductInfoBottomSheet(
          key: args.key,
          productId: args.productId,
        ),
      );
    },
    
    
 
/// generated route for
/// [ProductInfoBottomSheet]
class ProductInfoBottomSheetRoute
    extends PageRouteInfo<ProductInfoBottomSheetRouteArgs> {
  ProductInfoBottomSheetRoute({
    Key? key,
    required String productId,
    List<PageRouteInfo>? children,
  }) : super(
          ProductInfoBottomSheetRoute.name,
          args: ProductInfoBottomSheetRouteArgs(
            key: key,
            productId: productId,
          ),
          rawPathParams: {'productId': productId},
          initialChildren: children,
        );

  static const String name = 'ProductInfoBottomSheetRoute';

  static const PageInfo<ProductInfoBottomSheetRouteArgs> page =
      PageInfo<ProductInfoBottomSheetRouteArgs>(name);
}

class ProductInfoBottomSheetRouteArgs {
  const ProductInfoBottomSheetRouteArgs({
    this.key,
    required this.productId,
  });

  final Key? key;

  final String productId;

  @override
  String toString() {
    return 'ProductInfoBottomSheetRouteArgs{key: $key, productId: $productId}';
  }
}

with
auto_route: ^8.3.0
auto_route_generator: ^8.0.0

you can see #1942 is a fix of this custom route error that now I using it instead of official in pub version, you should review it.

@outring
Copy link

outring commented Jul 23, 2024

Same thing here. I'm specifying a custom route type via type in routes:

@AutoRouterConfig()
class AppRouter extends $AppRouter {
  @override
  late final List<AutoRoute> routes = [
    AutoRoute(page: SomePage.page, type: CustomRouteType(customRouteBuilder: <T>(BuildContext context, Widget child, AutoRoutePage<T> page) {
      return MyPageRoute<T>(settings: page, builder: (context) => child);
    })),
  ];
}

The error is:

TypeError: Instance of 'MyPageRoute<dynamic>': type 'MyPageRoute<dynamic>' is not a subtype of type 'Route<BookkeepingTaskSessionResult>'

Which is quite logical, since CustomRouteType is not generic the type paramter for customRouteBuilder can't be inferred AOT and dynamic is being used. The PR #1942 looks legit

@Mixron469
Copy link

Did it was resolved in latest 9.3.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants