From f3c0978136c64275807653b11b1f0aade2ca1f86 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Sun, 17 Sep 2023 00:24:00 +0330 Subject: [PATCH] feat: add intro screen --- lib/core/router/app_router.dart | 8 +++ lib/core/router/routes/routes.dart | 4 +- lib/core/router/routes/shared_routes.dart | 17 ++++++ lib/features/intro/view/intro_page.dart | 66 +++++++++++++++++++++++ lib/features/intro/view/view.dart | 1 + 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 lib/features/intro/view/intro_page.dart create mode 100644 lib/features/intro/view/view.dart diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart index 530ef3f5..81b76860 100644 --- a/lib/core/router/app_router.dart +++ b/lib/core/router/app_router.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/core/router/routes/routes.dart'; import 'package:hiddify/services/deep_link_service.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -9,6 +10,7 @@ part 'app_router.g.dart'; // TODO: test and improve handling of deep link @riverpod GoRouter router(RouterRef ref) { + final introCompleted = ref.watch(introCompletedProvider); final deepLink = ref.listen( deepLinkServiceProvider, (_, next) async { @@ -28,6 +30,12 @@ GoRouter router(RouterRef ref) { initialLocation: initialLocation, debugLogDiagnostics: true, routes: $routes, + redirect: (context, state) { + if (!introCompleted && state.uri.path != const IntroRoute().location) { + return const IntroRoute().location; + } + return null; + }, ); } diff --git a/lib/core/router/routes/routes.dart b/lib/core/router/routes/routes.dart index 9c3bf2d7..5805cd24 100644 --- a/lib/core/router/routes/routes.dart +++ b/lib/core/router/routes/routes.dart @@ -1,12 +1,14 @@ import 'package:go_router/go_router.dart'; import 'package:hiddify/core/router/routes/desktop_routes.dart' as desktop; import 'package:hiddify/core/router/routes/mobile_routes.dart' as mobile; +import 'package:hiddify/core/router/routes/shared_routes.dart' as shared; import 'package:hiddify/utils/utils.dart'; export 'mobile_routes.dart'; -export 'shared_routes.dart'; +export 'shared_routes.dart' hide $appRoutes; List get $routes => [ + ...shared.$appRoutes, if (PlatformUtils.isDesktop) ...desktop.$appRoutes else diff --git a/lib/core/router/routes/shared_routes.dart b/lib/core/router/routes/shared_routes.dart index a45ef978..d0908005 100644 --- a/lib/core/router/routes/shared_routes.dart +++ b/lib/core/router/routes/shared_routes.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hiddify/features/home/view/view.dart'; +import 'package:hiddify/features/intro/view/view.dart'; import 'package:hiddify/features/profile_detail/view/view.dart'; import 'package:hiddify/features/profiles/view/view.dart'; import 'package:hiddify/features/proxies/view/view.dart'; import 'package:hiddify/utils/utils.dart'; +part 'shared_routes.g.dart'; + final GlobalKey rootNavigatorKey = GlobalKey(); class HomeRoute extends GoRouteData { @@ -47,6 +50,20 @@ class AddProfileRoute extends GoRouteData { } } +@TypedGoRoute(path: IntroRoute.path) +class IntroRoute extends GoRouteData { + const IntroRoute(); + static const path = '/intro'; + + @override + Page buildPage(BuildContext context, GoRouterState state) { + return const MaterialPage( + fullscreenDialog: true, + child: IntroPage(), + ); + } +} + class ProfilesRoute extends GoRouteData { const ProfilesRoute(); static const path = 'profiles'; diff --git a/lib/features/intro/view/intro_page.dart b/lib/features/intro/view/intro_page.dart new file mode 100644 index 00000000..ca5f5e61 --- /dev/null +++ b/lib/features/intro/view/intro_page.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:hiddify/core/core_providers.dart'; +import 'package:hiddify/core/prefs/prefs.dart'; +import 'package:hiddify/features/common/common.dart'; +import 'package:hiddify/gen/assets.gen.dart'; +import 'package:hiddify/utils/utils.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sliver_tools/sliver_tools.dart'; + +class IntroPage extends HookConsumerWidget with PresLogger { + const IntroPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final t = ref.watch(translationsProvider); + + return Scaffold( + body: CustomScrollView( + shrinkWrap: true, + slivers: [ + const SliverGap(24), + SliverToBoxAdapter( + child: SizedBox( + width: 248, + height: 248, + child: Padding( + padding: const EdgeInsets.all(36), + child: Assets.images.logo.svg(), + ), + ), + ), + SliverCrossAxisConstrained( + maxCrossAxisExtent: 368, + child: MultiSliver( + children: [ + const LocalePrefTile(), + const SliverGap(8), + const EnableAnalyticsPrefTile(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 24, + ), + child: FilledButton( + onPressed: () async { + if (!ref.read(enableAnalyticsProvider)) { + loggy.debug("disabling analytics per user request"); + await Sentry.close(); + } + await ref + .read(introCompletedProvider.notifier) + .update(true); + }, + child: Text(t.intro.start), + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/intro/view/view.dart b/lib/features/intro/view/view.dart new file mode 100644 index 00000000..507e9508 --- /dev/null +++ b/lib/features/intro/view/view.dart @@ -0,0 +1 @@ +export 'intro_page.dart';