Skip to content

Commit 15f9331

Browse files
committed
add deeplink support
1 parent 394ee16 commit 15f9331

File tree

8 files changed

+181
-97
lines changed

8 files changed

+181
-97
lines changed

app/lib/main/app.dart

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,92 @@ import 'package:app/presentation/themes/app_themes.dart';
88
import 'package:app/presentation/utils/lang_extensions.dart';
99
import 'package:flutter_bloc/flutter_bloc.dart';
1010
import 'package:flutter_localizations/flutter_localizations.dart';
11-
11+
import 'package:flutter/foundation.dart' show kIsWeb;
12+
import 'package:app_links/app_links.dart';
13+
import 'package:go_router/go_router.dart';
1214
import 'init.dart';
1315

14-
class App extends StatelessWidget {
16+
class App extends StatefulWidget {
1517
const App({super.key});
1618

19+
@override
20+
State<App> createState() => _AppState();
21+
}
22+
23+
class _AppState extends State<App> {
24+
late final GoRouter _router;
25+
bool _isRouterReady = false;
26+
27+
@override
28+
void initState() {
29+
super.initState();
30+
_initRouter();
31+
}
32+
33+
Future<void> _initRouter() async {
34+
String? initialLocation;
35+
if (kIsWeb) {
36+
final path = Uri.base.path;
37+
if (path.isNotEmpty && path != '/') {
38+
initialLocation = path;
39+
}
40+
} else {
41+
final appLinks = AppLinks();
42+
final initialUri = await appLinks.getInitialLink();
43+
if (initialUri != null) {
44+
initialLocation = initialUri.path;
45+
}
46+
}
47+
48+
debugPrint('App entry point: $initialLocation');
49+
50+
if (mounted) {
51+
setState(() {
52+
_router = Routes.init(
53+
context,
54+
initialLocation: initialLocation,
55+
);
56+
_isRouterReady = true;
57+
});
58+
}
59+
}
60+
1761
@override
1862
Widget build(BuildContext context) {
1963
return MultiBlocProvider(
2064
providers: [
2165
BlocProvider(create: (_) => getIt<AppCubit>()),
2266
BlocProvider(create: (_) => getIt<AuthCubit>()),
2367
],
24-
child: BlocBuilder<AppCubit, AppState>(
25-
builder: (context, state) {
26-
return MaterialApp.router(
27-
theme: AppThemes.getAppTheme(state.themeType).data,
28-
locale: LangExtensions.langLocale[state.appLang],
29-
supportedLocales: LangExtensions.supportedLang,
30-
localizationsDelegates: const [
31-
S.delegate,
32-
GlobalMaterialLocalizations.delegate,
33-
GlobalWidgetsLocalizations.delegate,
34-
GlobalCupertinoLocalizations.delegate,
35-
],
36-
builder: (context, child) =>
37-
child ??
38-
const Material(
39-
child: Center(
40-
child: CircularProgressIndicator(),
41-
),
42-
),
43-
routerConfig: Routes.router,
44-
);
45-
},
46-
),
68+
child: !_isRouterReady
69+
? const Material(
70+
child: Center(
71+
child: CircularProgressIndicator(),
72+
),
73+
)
74+
: BlocBuilder<AppCubit, AppState>(
75+
builder: (context, state) {
76+
return MaterialApp.router(
77+
theme: AppThemes.getAppTheme(state.themeType).data,
78+
locale: LangExtensions.langLocale[state.appLang],
79+
supportedLocales: LangExtensions.supportedLang,
80+
localizationsDelegates: const [
81+
S.delegate,
82+
GlobalMaterialLocalizations.delegate,
83+
GlobalWidgetsLocalizations.delegate,
84+
GlobalCupertinoLocalizations.delegate,
85+
],
86+
builder: (context, child) =>
87+
child ??
88+
const Material(
89+
child: Center(
90+
child: CircularProgressIndicator(),
91+
),
92+
),
93+
routerConfig: _router,
94+
);
95+
},
96+
),
4797
);
4898
}
4999
}

app/lib/presentation/navigation/routers.dart

Lines changed: 97 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,88 +20,117 @@ enum Routes {
2020
String get path => '/$name';
2121
String get subPath => name;
2222

23-
void nav({Object? extra}) {
24-
Routers.authRouter.goNamed(
23+
void nav(BuildContext context, {Object? extra}) {
24+
context.router.goNamed(
2525
name,
2626
extra: extra,
2727
);
2828
}
2929

30-
static GoRouter get router => Routers.authRouter;
30+
static GoRouter init(BuildContext context, {String? initialLocation}) =>
31+
Routers.appRouter(context, initialLocation: initialLocation);
32+
}
33+
34+
extension ContextOnRouter on BuildContext {
35+
GoRouter get router => GoRouter.of(this);
3136
}
3237

3338
class Routers {
34-
static GoRouter authRouter = GoRouter(
35-
initialLocation: '/',
36-
routes: [
37-
GoRoute(
38-
path: '/',
39-
builder: (context, state) {
40-
return BlocListener<AuthCubit, Resource>(
41-
listenWhen: (previous, current) => current is RSuccess,
42-
listener: (_, state) {
43-
if (state is RSuccess) {
44-
switch (state.data) {
45-
case AuthStateAuthenticated _:
46-
debugPrint('User is authenticated');
47-
Routes.app.nav();
48-
break;
49-
case AuthStateUnauthenticated _:
50-
debugPrint('User is unauthenticated');
51-
Routes.auth.nav();
52-
break;
53-
case _:
54-
}
55-
}
56-
},
57-
child: const SplashPage(),
58-
);
59-
},
39+
static GoRouter appRouter(
40+
BuildContext context, {
41+
String? initialLocation,
42+
}) =>
43+
GoRouter(
44+
initialLocation: initialLocation ??
45+
(context.read<AuthCubit>().isLoggedIn()
46+
? Routes.app.path
47+
: Routes.auth.path),
6048
routes: [
61-
ShellRoute(
62-
builder: (context, state, child) => child,
63-
redirect: (context, state) {
64-
if (context.read<AuthCubit>().isLoggedIn()) {
65-
return Routes.app.path;
66-
}
67-
return null;
68-
},
69-
routes: [
70-
GoRoute(
71-
name: Routes.auth.name,
72-
path: Routes.auth.path,
73-
builder: (context, state) => const LoginPage(),
74-
),
75-
GoRoute(
76-
name: Routes.signup.name,
77-
path: '${Routes.auth.path}${Routes.signup.path}',
78-
builder: (context, state) => const SignUpPage(),
79-
),
80-
],
81-
),
82-
ShellRoute(
83-
builder: (context, state, child) => child,
84-
redirect: (context, state) {
85-
if (!context.read<AuthCubit>().isLoggedIn()) {
86-
return Routes.auth.path;
87-
}
88-
return null;
49+
GoRoute(
50+
path: '/',
51+
builder: (context, state) {
52+
return BlocListener<AuthCubit, Resource>(
53+
listenWhen: (previous, current) => current is RSuccess,
54+
listener: (_, appState) {
55+
if (appState is RSuccess) {
56+
switch (appState.data) {
57+
case AuthStateAuthenticated _:
58+
debugPrint('User is authenticated: ${state.fullPath}');
59+
if (state.fullPath?.contains(Routes.app.path) ??
60+
false) {
61+
// Already navigating to app, do nothing
62+
return;
63+
}
64+
debugPrint('Navigating to app route');
65+
Routes.app.nav(context);
66+
break;
67+
case AuthStateUnauthenticated _:
68+
debugPrint(
69+
'User is unauthenticated: ${state.fullPath}');
70+
if (state.fullPath?.contains(Routes.auth.path) ??
71+
false) {
72+
// Already navigating to auth, do nothing
73+
return;
74+
}
75+
debugPrint('Navigating to auth route');
76+
Routes.auth.nav(context);
77+
break;
78+
case _:
79+
}
80+
}
81+
},
82+
child: const SplashPage(),
83+
);
8984
},
9085
routes: [
91-
GoRoute(
92-
name: Routes.app.name,
93-
path: Routes.app.path,
94-
builder: (context, state) => const HomePage(),
86+
ShellRoute(
87+
builder: (context, state, child) => child,
88+
routes: [
89+
GoRoute(
90+
name: Routes.auth.name,
91+
path: Routes.auth.path,
92+
redirect: (context, state) {
93+
if (context.read<AuthCubit>().isLoggedIn()) {
94+
return Routes.app.path;
95+
}
96+
return null;
97+
},
98+
builder: (context, state) => const LoginPage(),
99+
routes: [
100+
GoRoute(
101+
name: Routes.signup.name,
102+
path: Routes.signup.subPath,
103+
builder: (context, state) => const SignUpPage(),
104+
),
105+
],
106+
),
107+
],
95108
),
96-
GoRoute(
97-
name: Routes.placeholder.name,
98-
path: "${Routes.app.path}${Routes.placeholder.path}",
99-
builder: (context, state) => const Placeholder(),
109+
ShellRoute(
110+
builder: (context, state, child) => child,
111+
routes: [
112+
GoRoute(
113+
name: Routes.app.name,
114+
path: Routes.app.path,
115+
redirect: (context, state) {
116+
if (!context.read<AuthCubit>().isLoggedIn()) {
117+
return Routes.auth.path;
118+
}
119+
return null;
120+
},
121+
builder: (context, state) => const HomePage(),
122+
routes: [
123+
GoRoute(
124+
name: Routes.placeholder.name,
125+
path: Routes.placeholder.subPath,
126+
builder: (context, state) => const Placeholder(),
127+
),
128+
],
129+
),
130+
],
100131
),
101132
],
102133
),
103134
],
104-
),
105-
],
106-
);
135+
);
107136
}

app/lib/presentation/ui/pages/login/login_page.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ class LoginPage extends StatelessWidget {
3333
child: ElevatedButton(
3434
child: const Text('Login'),
3535
onPressed: () {
36-
Routes.signup.nav();
37-
//_authCubit.login('Rootstrap', '12345678');
36+
_authCubit.login('Rootstrap', '12345678');
3837
},
3938
),
4039
),

app/linux/flutter/generated_plugin_registrant.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
#include "generated_plugin_registrant.h"
88

9+
#include <gtk/gtk_plugin.h>
910

1011
void fl_register_plugins(FlPluginRegistry* registry) {
12+
g_autoptr(FlPluginRegistrar) gtk_registrar =
13+
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
14+
gtk_plugin_register_with_registrar(gtk_registrar);
1115
}

app/linux/flutter/generated_plugins.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#
44

55
list(APPEND FLUTTER_PLUGIN_LIST
6+
gtk
67
)
78

89
list(APPEND FLUTTER_FFI_PLUGIN_LIST

app/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ dependencies:
5454
flutter_dotenv: ^5.2.1
5555
flutter_web_plugins:
5656
sdk: flutter
57+
app_links: ^6.4.1
5758

5859
dev_dependencies:
5960
bloc_test: ^9.0.2

modules/domain/lib/bloc/auth/auth_cubit.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ class AuthCubit extends BaseCubit<AuthState> {
3131
isLogOut();
3232
}
3333

34-
bool isLoggedIn() =>
35-
state is RSuccess && (state as RSuccess).data is AuthStateAuthenticated;
34+
bool isLoggedIn() => _authService.isLoggedIn();
3635

3736
void isLogin() => isSuccess(AuthStateAuthenticated());
3837

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ environment:
1111
dependencies:
1212
flutter:
1313
sdk: flutter
14+
app_links: ^6.4.1
1415

1516
dev_dependencies:
1617
flutter_test:

0 commit comments

Comments
 (0)