gt_navigation 1.0.0 copy "gt_navigation: ^1.0.0" to clipboard
gt_navigation: ^1.0.0 copied to clipboard

A production-ready Flutter navigation package with middleware, deep linking, nested navigation, custom transitions, and type-safe routing.

example/lib/main.dart

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

void main() {
  // Initialize the router with routes
  AppRouter().initialize(
    routes: AppPages.all,
    deepLinkConfig: const DeepLinkConfig(
      scheme: 'myapp',
      host: 'example.com',
    ),
    enableLogging: true,
  );
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GT Navigation Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      navigatorKey: AppRouter().navigatorKey,
      onGenerateRoute: AppRouter().onGenerateRoute,
      navigatorObservers: [AppRouter().routeObserver],
      initialRoute: AppRoutes.home,
    );
  }
}

// --- Route Constants ---

class AppRoutes {
  static const String home = '/home';
  static const String detail = '/detail/:id';
  static const String settings = '/settings';
  static const String login = '/login';
}

// --- Route Configurations ---

class AppPages {
  static final List<AppRoute> all = [
    AppRoute(
      path: AppRoutes.home,
      builder: (context, args) => const HomeScreen(),
      transition: const AppTransition(type: AppTransitionType.fade),
    ),
    AppRoute(
      path: AppRoutes.detail,
      builder: (context, args) => DetailScreen(args: args),
      transition: const AppTransition(
        type: AppTransitionType.slide,
        direction: AppTransitionDirection.bottomToTop,
      ),
    ),
    AppRoute(
      path: AppRoutes.settings,
      builder: (context, args) => const SettingsScreen(),
      middlewares: [AuthGuardMiddleware()],
    ),
    AppRoute(
      path: AppRoutes.login,
      builder: (context, args) => const LoginScreen(),
      transition: const AppTransition(type: AppTransitionType.material),
    ),
  ];
}

// --- Middleware ---

class AuthGuardMiddleware extends AppMiddleware {
  @override
  Future<bool> canNavigate(
    BuildContext context,
    String route,
    AppRouteArguments? args,
  ) async {
    return AuthService.isLoggedIn;
  }

  @override
  String? getRedirectRoute() => AppRoutes.login;
}

// --- Simple Auth Service ---

class AuthService {
  static bool isLoggedIn = false;
}

// --- Screens ---

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GT Navigation Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildNavigationCard(
            title: 'Basic Push Navigation',
            subtitle: 'Push to detail screen with path parameter',
            onTap: () => AppRouter().navigateTo('/detail/123'),
          ),
          _buildNavigationCard(
            title: 'Navigation with Query Args',
            subtitle: 'Pass additional query parameters',
            onTap: () => AppRouter().navigateTo(
              '/detail/456',
              arguments: const AppRouteArguments(
                queryParameters: {'source': 'home'},
              ),
            ),
          ),
          _buildNavigationCard(
            title: 'Protected Route (Auth Guard)',
            subtitle: 'Redirects to login if not authenticated',
            onTap: () => AppRouter().navigateTo(AppRoutes.settings),
          ),
          _buildNavigationCard(
            title: 'Show Dialog (Context-Free)',
            subtitle: 'Open dialog using AppRouter',
            onTap: () => _showGlobalDialog(),
          ),
          _buildNavigationCard(
            title: 'Simulate Deep Link',
            subtitle: 'Handle deep link: myapp://example.com/detail/999',
            onTap: () => AppRouter().handleDeepLink(
              Uri.parse('myapp://example.com/detail/999?ref=deeplink'),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildNavigationCard({
    required String title,
    required String subtitle,
    required VoidCallback onTap,
  }) {
    return Card(
      margin: const EdgeInsets.only(bottom: 12),
      child: ListTile(
        title: Text(title, style: const TextStyle(fontWeight: FontWeight.w600)),
        subtitle: Text(subtitle, style: const TextStyle(fontSize: 12)),
        trailing: const Icon(Icons.chevron_right),
        onTap: onTap,
      ),
    );
  }

  void _showGlobalDialog() {
    AppRouter().openDialog(
      builder: (_) => AlertDialog(
        title: const Text('Context-Free Dialog'),
        content: const Text(
          'This dialog was opened without needing direct BuildContext access!',
        ),
        actions: [
          TextButton(
            onPressed: () => AppRouter().goBack(),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  final AppRouteArguments? args;

  const DetailScreen({super.key, this.args});

  @override
  Widget build(BuildContext context) {
    final id = args?.getString('id') ?? 'Unknown';
    final source = args?.getString('source') ?? 'Direct';
    final ref = args?.getString('ref') ?? 'None';

    return Scaffold(
      appBar: AppBar(
        title: const Text('Detail Screen'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.info_outline, size: 64, color: Colors.indigo),
            const SizedBox(height: 20),
            Text('ID: $id', style: Theme.of(context).textTheme.headlineMedium),
            const SizedBox(height: 8),
            Text('Source: $source'),
            Text('Ref: $ref'),
            const SizedBox(height: 32),
            ElevatedButton(
              onPressed: () => AppRouter().goBack(),
              child: const Text('Go Back'),
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Settings (Protected)'),
        backgroundColor: Colors.green.shade100,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.security, size: 64, color: Colors.green),
            const SizedBox(height: 20),
            const Text('🎉 You are authenticated!'),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                AuthService.isLoggedIn = false;
                AppRouter().navigateTo(
                  AppRoutes.login,
                  mode: NavigationModes.pushAndRemoveAll,
                );
              },
              child: const Text('Logout'),
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.lock_outline, size: 64, color: Colors.orange),
            const SizedBox(height: 20),
            const Text('Please login to access protected routes'),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                AuthService.isLoggedIn = true;
                AppRouter().navigateTo(
                  AppRoutes.home,
                  mode: NavigationModes.pushReplacement,
                );
              },
              child: const Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}
0
likes
160
points
144
downloads

Publisher

unverified uploader

Weekly Downloads

A production-ready Flutter navigation package with middleware, deep linking, nested navigation, custom transitions, and type-safe routing.

Repository (GitHub)
View/report issues

Topics

#navigation #router #routing #deep-linking #middleware

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on gt_navigation