Skip to content

Commit

Permalink
Merge pull request #184 from Eldar2021/el/use-go-router
Browse files Browse the repository at this point in the history
User go_router for navigation
  • Loading branch information
Eldar2021 authored Feb 2, 2024
2 parents 108bfa0 + 2c162ef commit c6f0dda
Show file tree
Hide file tree
Showing 20 changed files with 285 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci_android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ jobs:
if: always()
with:
name: my-artifact
path: ./app/screenshots/*
path: ./screenshots/*
1 change: 1 addition & 0 deletions app/lib/app/app.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export 'logic/app_cubit.dart';
export 'logic/auth_cubit.dart';
export 'router/app_router.dart';
export 'router/parse_parameters.dart';
export 'services/app_service.dart';
export 'services/auth_service.dart';
export 'services/theme_service.dart';
Expand Down
2 changes: 2 additions & 0 deletions app/lib/app/logic/auth_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ class AuthCubit extends Cubit<AuthState> {
await service.changeGender(gender);
emit(state.copyWith(user: state.user?.copyWith(gender: gender)));
}

bool get isAuthedticated => state.user != null;
}
222 changes: 174 additions & 48 deletions app/lib/app/router/app_router.dart
Original file line number Diff line number Diff line change
@@ -1,54 +1,180 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

import 'package:my_quran/models/models.dart';
import 'package:my_quran/app/app.dart';
import 'package:my_quran/modules/modules.dart';

class AppRouter {
const AppRouter();

static const String main = '/';
static const String home = '/home';
static const String hatim = '/hatim';
static const String quran = '/quran';
static const String read = '/read';
static const String login = '/login';
static const String signIn = '/sign-in';

static const String settingsPage = '/settings';
static const String langSettings = '/lang-settings';
static const String genderSettings = '/gender-settings';
static const String themeSettings = '/theme-settings';
static const String aboutUs = '/about-us';
static const String contactUs = '/contect-us';
static const String developers = '/developers';
static const String devModeView = '/dev-mode-view';

static Route<void> onGenerateRoute(RouteSettings settings, User? user) {
return switch (settings.name) {
main => CupertinoPageRoute(builder: (_) => user != null ? const MainView() : const LoginView()),
home => CupertinoPageRoute(builder: (_) => const HomeView()),
hatim => CupertinoPageRoute(builder: (_) => const HatimView()),
quran => CupertinoPageRoute(builder: (_) => const QuranView()),
login => CupertinoPageRoute(builder: (_) => const LoginView()),
signIn => CupertinoPageRoute(builder: (_) => const SignInView()),
settingsPage => CupertinoPageRoute(builder: (_) => const SettingsView()),
aboutUs => CupertinoPageRoute(builder: (_) => const AboutUsVuew()),
contactUs => CupertinoPageRoute(builder: (_) => const ContactUsView()),
developers => CupertinoPageRoute(builder: (_) => const DevelopersView()),
genderSettings => CupertinoPageRoute(builder: (_) => const GenderSettingView()),
langSettings => CupertinoPageRoute(builder: (_) => const LangSettingsView()),
themeSettings => CupertinoPageRoute(builder: (_) => const ThemeSettingsView()),
devModeView => CupertinoPageRoute(builder: (_) => const DevModeView()),
read => CupertinoPageRoute<bool>(
builder: (_) {
final args = settings.arguments!;
return ReadView(
(args as Map<String, dynamic>)['pages'] as List<int>,
isHatim: args['isHatim'] as bool,
);
},
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _sectionNavigatorKey1 = GlobalKey<NavigatorState>(debugLabel: 'home');
final _sectionNavigatorKey2 = GlobalKey<NavigatorState>(debugLabel: 'quran');
final _sectionNavigatorKey3 = GlobalKey<NavigatorState>(debugLabel: 'quran-audio');
final _sectionNavigatorKey4 = GlobalKey<NavigatorState>(debugLabel: 'settings');

@immutable
final class AppRouter {
const AppRouter._();

static const home = 'home';
static const hatim = 'hatim';
static const quran = 'quran';
static const quranAudio = 'quran-audio';

static const read = 'read';
static const hatimRead = 'hatim-read';
static const login = 'login';

static const settingsPage = 'settings';
static const langSettings = 'lang-settings';
static const genderSettings = 'gender-settings';
static const themeSettings = 'theme-settings';
static const aboutUs = 'about-us';
static const contactUs = 'contect-us';
static const developers = 'developers';
static const devModeView = 'dev-mode-view';

static final router = GoRouter(
initialLocation: '/home',
navigatorKey: _rootNavigatorKey,
debugLogDiagnostics: true,
routes: [
GoRoute(
path: '/',
builder: (context, state) => const Scaffold(
body: Center(child: Text('Init')),
),
_ => throw Exception('no builder specified for route named: [${settings.name}]'),
};
),
GoRoute(
path: '/$login',
name: login,
builder: (context, state) => const LoginView(),
),
GoRoute(
path: '/$devModeView',
name: devModeView,
builder: (context, state) => const DevModeView(),
),
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) => MainView(navigationShell),
branches: [
StatefulShellBranch(
navigatorKey: _sectionNavigatorKey1,
routes: [
GoRoute(
path: '/$home',
name: home,
builder: (context, state) => const HomeView(),
routes: homeSubRoutes,
),
],
),
StatefulShellBranch(
navigatorKey: _sectionNavigatorKey2,
routes: [
GoRoute(
path: '/$quran',
name: quran,
builder: (context, state) => const QuranView(),
routes: quranSubRoutes,
),
],
),
StatefulShellBranch(
navigatorKey: _sectionNavigatorKey3,
routes: [
GoRoute(
path: '/$quranAudio',
name: quranAudio,
builder: (context, state) => const QuranAudioView(),
),
],
),
StatefulShellBranch(
navigatorKey: _sectionNavigatorKey4,
routes: [
GoRoute(
path: '/$settingsPage',
name: settingsPage,
builder: (context, state) => const SettingsView(),
routes: settingsSubRoutes,
),
],
),
],
),
],
redirect: (context, state) {
return !context.read<AuthCubit>().isAuthedticated ? '/$login' : null;
},
);

static List<RouteBase> get homeSubRoutes {
return [
GoRoute(
path: hatim,
name: hatim,
builder: (context, state) => const HatimView(),
routes: [
GoRoute(
path: '$hatimRead/:isHatim/:pages',
name: hatimRead,
parentNavigatorKey: _rootNavigatorKey,
builder: (context, state) {
final args = ParseParams.parseRead(state.pathParameters);
return ReadView(args.$1, isHatim: args.$2);
},
),
],
),
];
}

static List<RouteBase> get quranSubRoutes {
return [
GoRoute(
path: '$read/:isHatim/:pages',
name: read,
parentNavigatorKey: _rootNavigatorKey,
builder: (context, state) {
final args = ParseParams.parseRead(state.pathParameters);
return ReadView(args.$1, isHatim: args.$2);
},
),
];
}

static List<RouteBase> get settingsSubRoutes {
return [
GoRoute(
path: genderSettings,
name: genderSettings,
builder: (context, state) => const GenderSettingView(),
),
GoRoute(
path: langSettings,
name: langSettings,
builder: (context, state) => const LangSettingsView(),
),
GoRoute(
path: themeSettings,
name: themeSettings,
builder: (context, state) => const ThemeSettingsView(),
),
GoRoute(
path: aboutUs,
name: aboutUs,
builder: (context, state) => const AboutUsVuew(),
),
GoRoute(
path: contactUs,
name: contactUs,
builder: (context, state) => const ContactUsView(),
),
GoRoute(
path: developers,
name: developers,
builder: (context, state) => const DevelopersView(),
),
];
}
}
20 changes: 20 additions & 0 deletions app/lib/app/router/parse_parameters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'dart:developer';

import 'package:meta/meta.dart';

@immutable
final class ParseParams {
const ParseParams._();

static (List<int>, bool) parseRead(Map<String, String> args) {
try {
final isHatim = args['isHatim'] == 'true';
final p1 = args['pages'] ?? '[1]';
final pages = p1.substring(1, p1.length - 1).split(',').map(int.parse).toList();
return (pages, isHatim);
} catch (e) {
log(e.toString());
return ([1], false);
}
}
}
7 changes: 2 additions & 5 deletions app/lib/app/view/app_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,14 @@ class QuranApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
return MaterialApp(
return MaterialApp.router(
title: 'MyQuranKhatm',
debugShowCheckedModeBanner: false,
locale: context.watch<AppCubit>().state.currentLocale,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: context.watch<AppCubit>().state.theme.themeData,
onGenerateRoute: (settings) => AppRouter.onGenerateRoute(
settings,
context.read<AuthCubit>().state.user,
),
routerConfig: AppRouter.router,
);
}
}
5 changes: 3 additions & 2 deletions app/lib/modules/hatim/view/hatim_select_page_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';

import 'package:my_quran/app/app.dart';
Expand Down Expand Up @@ -61,13 +62,13 @@ class HatimJusBottomSheet extends StatelessWidget {
children: [
OutlinedButton(
key: const Key(MqKeys.hatimSelectPageCancel),
onPressed: () => Navigator.pop(context),
onPressed: () => context.pop(),
child: Text(context.l10n.cancel),
),
const SizedBox(width: 12),
OutlinedButton(
key: const Key(MqKeys.hatimSelectPageOk),
onPressed: () => Navigator.pop(context),
onPressed: () => context.pop(),
child: Text(context.l10n.select),
),
],
Expand Down
11 changes: 7 additions & 4 deletions app/lib/modules/hatim/view/hatim_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';

import 'package:my_quran/app/app.dart';
Expand Down Expand Up @@ -92,10 +93,12 @@ class _HatimUIState extends State<HatimUI> {
context.read<HatimPagesCubit>().sendPage(username, token);
final pages = List<int>.generate(cubit.state.pages!.length, (index) => cubit.state.pages![index]!.number)
..sort();
final value = await Navigator.pushNamed<bool>(
context,
AppRouter.read,
arguments: {'pages': pages, 'isHatim': true},
final value = await context.pushNamed<bool>(
AppRouter.hatimRead,
pathParameters: {
'pages': pages.toString(),
'isHatim': true.toString(),
},
);
if (value != null && value && context.mounted) {
context.read<HatimPagesCubit>().donePage(username, token);
Expand Down
29 changes: 21 additions & 8 deletions app/lib/modules/home/view/home_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,36 @@ import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';
import 'package:upgrader/upgrader.dart';

import 'package:my_quran/core/core.dart';
import 'package:my_quran/app/app.dart';
import 'package:my_quran/components/components.dart';
import 'package:my_quran/config/app_config.dart';
import 'package:my_quran/constants/contants.dart';
import 'package:my_quran/l10n/l10.dart';
import 'package:my_quran/modules/modules.dart';
import 'package:upgrader/upgrader.dart';

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

@override
State<HomeView> createState() => _HomeViewState();
}

class _HomeViewState extends State<HomeView> {
@override
void initState() {
final homeCubit = context.read<HomeCubit>();
final authCubit = context.read<AuthCubit>();
if (homeCubit.state.status != FetchStatus.success && authCubit.state.user != null) {
homeCubit.getData(authCubit.state.user!.accessToken);
}
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down Expand Up @@ -77,12 +95,7 @@ class HomeBody extends StatelessWidget {
child: CustomButton(
key: const Key(MqKeys.participantToHatim),
text: l10n.homeGoHatim,
onPressed: () async {
await Navigator.pushNamed(context, AppRouter.hatim);
if (context.mounted) {
await context.read<HomeCubit>().getData(context.read<AuthCubit>().state.user!.accessToken);
}
},
onPressed: () => context.goNamed(AppRouter.hatim),
),
),
const SizedBox(height: 20),
Expand Down
Loading

0 comments on commit c6f0dda

Please sign in to comment.