Skip to content

Instantly share code, notes, and snippets.

@SuperPenguin
Created October 13, 2024 05:59
Show Gist options
  • Save SuperPenguin/891d3063b8ed8e2f65433e35979d9eed to your computer and use it in GitHub Desktop.
Save SuperPenguin/891d3063b8ed8e2f65433e35979d9eed to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const App());
}
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
late final UserCubit _userCubit;
late final GoRouter _goRouter;
late final StreamSubscription<User?> _userSubscription;
@override
void initState() {
super.initState();
_userCubit = UserCubit(null);
_goRouter = GoRouter(
initialLocation: '/home',
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNavBar(
navigationShell: navigationShell,
);
},
branches: [
StatefulShellBranch(
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Home'),
ProSwitch(),
],
),
),
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/screen-a',
builder: (context, state) => const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Screen A'),
ProSwitch(),
],
),
),
),
],
),
StatefulShellBranch(
routes: [
GoRoute(
path: '/pro',
redirect: (context, state) {
final isPremium = _userCubit.state?.isPremium ?? false;
if (!isPremium) {
return '/home';
}
return null;
},
builder: (context, state) => const Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Pro'),
ProSwitch(),
],
),
),
),
],
),
],
),
],
);
_userSubscription = _userCubit.stream.listen((user) {
_goRouter.refresh();
});
}
@override
void dispose() {
_userSubscription.cancel();
_userCubit.close();
_goRouter.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: _userCubit,
child: MaterialApp.router(
routerConfig: _goRouter,
),
);
}
}
class ScaffoldWithNavBar extends StatelessWidget {
const ScaffoldWithNavBar({
super.key,
required this.navigationShell,
});
final StatefulNavigationShell navigationShell;
@override
Widget build(BuildContext context) {
final userCubit = context.watch<UserCubit>();
final isPremium = userCubit.state?.isPremium ?? false;
return Scaffold(
body: navigationShell,
bottomNavigationBar: BottomNavigationBar(
currentIndex: navigationShell.currentIndex,
onTap: (value) {
navigationShell.goBranch(value);
},
items: [
const BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
const BottomNavigationBarItem(
icon: Icon(Icons.monitor),
label: 'Screen A',
),
if (isPremium)
const BottomNavigationBarItem(
icon: Icon(Icons.workspace_premium),
label: 'Pro',
),
],
),
);
}
}
class ProSwitch extends StatelessWidget {
const ProSwitch({super.key});
@override
Widget build(BuildContext context) {
final userCubit = context.watch<UserCubit>();
final isPremium = userCubit.state?.isPremium ?? false;
return Switch.adaptive(
value: isPremium,
onChanged: (value) {
userCubit.setUser(
User(
isPremium: value,
),
);
},
);
}
}
class UserCubit extends Cubit<User?> {
UserCubit(super.initialState);
void setUser(User? user) {
emit(user);
}
}
final class User {
const User({
required this.isPremium,
});
final bool isPremium;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is User && other.isPremium == isPremium;
}
@override
int get hashCode {
return Object.hashAll([
isPremium,
]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment