SchabanBo / qlevar_router

Manage you project Routes. Create nested routes. Simply navigation without context to your pages. Change only one sub widget in your page when navigating to new route.
MIT License
87 stars 22 forks source link

AuthMiddleware in children of QRoute.withChild not work #134

Closed min23asdw closed 3 months ago

min23asdw commented 1 year ago

on app_routes.dart

  final routes = <QRoute>[
    WebRoutes().route, // Add the dashboard routes
  ];

on web_router.dart

class WebRoutes {
  final route = QRoute.withChild(
      name: "web",
      path: '/',
      initRoute: '/homePage',
      builderChild: (router) => WebPage(router: router),
      middleware: [],
      children: [
        QRoute(
          path: '/homePage',
          builder: () => MyHomePage(),
        ),
        QRoute(
            path: '/CampaignDetail',
            builder: () => NotFoundView(),
            children: [
              QRoute(
              )
            ]),
        QRoute(
            path: '/profile',
            middleware: [
              AuthMiddleware(),
            ],
            builder: () => Profile()
        ),
        QRoute(
          path: '/login',
          builder: () => const LoginView(),
        ),
      ]);
}         
class AuthMiddleware extends QMiddleware {
  final authService = Get.find<AuthService>();

  @override
  Future<String?> redirectGuard(String path) async {

    if (authService.isAuth) {
      return null;
    }
    return '/login';
  }
}

if I click button in website that QR.to profile [ www.xxx.com/profile] if user not login it will redirect to /login [ www.xxx.com/login ] can work normally

but if I enter [www.xxx.com/profile ] in browser url bar that not Init Page
my web redirect to /login [ www.xxx.com/login ] but LoginView() not load and show

image

min23asdw commented 1 year ago

I found how to solve

when i remove QR.setUrlStrategy(); in main.dart image

it work!!!! LoginView() is loaded

it mean setUrlStrategy have something wrong?

min23asdw commented 1 year ago

I found way to solve with still use setUrlStrategy becase in root stack tree if user enter web by www.xxx.com/profile , that are not root of route the middle will display key[0] web (root route ) on top of the stack

that mean web don't have anything to display it will display Init page -> loading problem image

by add QR.navigator.switchTo('/login'); in middleware

class AuthMiddleware extends QMiddleware {
  final authService = Get.find<AuthService>();
  @override
  Future<String?> redirectGuard(String path) async {
    print('authService  run');
    if (authService.isAuth) {
      return null;
    }
    QR.navigator.switchTo('/login');
    return '/login';
  }
}

image

I not sure it a good way but it work

SchabanBo commented 3 months ago

Using this example, I could not reproduce the problem

import 'package:flutter/material.dart';
import 'package:qlevar_router/qlevar_router.dart';

void main() {
  QR.setUrlStrategy();
  runApp(const MyApp());
}

var isAuth = false;

class AuthMiddleware extends QMiddleware {
  @override
  Future<String?> redirectGuard(String path) async {
    if (isAuth) {
      return null;
    }
    return '/login';
  }
}

class Dashboard extends StatelessWidget {
  final QRouter router;
  const Dashboard(this.router, {super.key});
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('Dashboard'),
          centerTitle: true,
        ),
        body: Row(
          children: [
            SizedBox(
              width: MediaQuery.of(context).size.width * 0.2,
              child: const Sidebar(),
            ),
            Expanded(flex: 4, child: router)
          ],
        ),
      );
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey.shade800,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ListTile(
            title: const Text('homePage'),
            onTap: () => QR.to('/homePage'),
          ),
          ListTile(
            title: const Text('profile'),
            onTap: () => QR.to('/profile'),
          ),
          ListTile(
            title: const Text('login'),
            onTap: () => QR.to('/login'),
          )
        ],
      ),
    );
  }
}

class DashboardChild extends StatelessWidget {
  final String name;
  final Color color;
  const DashboardChild(this.name, this.color, {super.key});
  @override
  Widget build(BuildContext context) {
    return Container(
      color: color,
      child: Center(
        child: Text(name, style: const TextStyle(fontSize: 20)),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final routes = [
      QRoute.withChild(
          name: "web",
          path: '/',
          initRoute: '/homePage',
          builderChild: (c) => Dashboard(c),
          children: [
            QRoute(
                path: '/homePage',
                builder: () =>
                    DashboardChild('homePage', Colors.grey.shade900)),
            QRoute(
                path: '/profile',
                middleware: [
                  AuthMiddleware(),
                ],
                builder: () => DashboardChild('profile', Colors.grey.shade700)),
            QRoute(
                path: '/login',
                builder: () => DashboardChild('login', Colors.grey.shade500)),
          ]),
    ];
    return MaterialApp.router(
      routeInformationParser: const QRouteInformationParser(),
      routerDelegate: QRouterDelegate(routes),
      theme: ThemeData.dark(),
    );
  }
}

feel free to reopen if the problem still exists