kasy-cli 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/bin/kasy.js +21 -0
  2. package/lib/commands/splash.js +220 -0
  3. package/lib/scaffold/CHANGELOG.json +9 -0
  4. package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
  5. package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
  6. package/lib/scaffold/features/README.md +15 -139
  7. package/lib/scaffold/shared/generator-utils.js +16 -15
  8. package/lib/utils/i18n.js +78 -0
  9. package/package.json +2 -2
  10. package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
  11. package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
  12. package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
  13. package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
  14. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  15. package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
  16. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
  17. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
  18. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
  19. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
  20. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  21. package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
  22. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
  23. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
  24. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
  25. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
  26. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
  27. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
  28. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
  29. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
  30. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
  31. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
  32. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
  33. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
  34. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
  35. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
  36. package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
  37. package/templates/firebase/assets/images/splash_logo_light.png +0 -0
  38. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
  39. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  40. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
  41. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  42. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  43. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  44. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
  45. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
  46. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
  47. package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
  48. package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
  49. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
  50. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
  51. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
  52. package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
  53. package/templates/firebase/lib/i18n/en.i18n.json +6 -2
  54. package/templates/firebase/lib/i18n/es.i18n.json +6 -2
  55. package/templates/firebase/lib/i18n/pt.i18n.json +6 -2
  56. package/templates/firebase/lib/main.dart +29 -10
  57. package/templates/firebase/pubspec.yaml +4 -5
  58. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
  59. package/templates/firebase/web/index.html +47 -39
  60. package/templates/firebase/web/splash/img/dark-1x.png +0 -0
  61. package/templates/firebase/web/splash/img/dark-2x.png +0 -0
  62. package/templates/firebase/web/splash/img/dark-3x.png +0 -0
  63. package/templates/firebase/web/splash/img/dark-4x.png +0 -0
  64. package/templates/firebase/web/splash/img/light-1x.png +0 -0
  65. package/templates/firebase/web/splash/img/light-2x.png +0 -0
  66. package/templates/firebase/web/splash/img/light-3x.png +0 -0
  67. package/templates/firebase/web/splash/img/light-4x.png +0 -0
  68. package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
  69. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
  70. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
  71. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
  72. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
  73. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
  74. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
  75. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
  76. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  77. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
  78. package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
  79. package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
  80. package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
  81. package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
  82. package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
  83. package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
  84. package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
  85. package/lib/scaffold/features/ci/codemagic.yaml +0 -157
  86. package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
  87. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
  88. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
  89. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
  90. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
  91. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
  92. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
  93. package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
  94. package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
  95. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
  96. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
  97. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
  98. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
  99. package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
  100. package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
  101. package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
  102. package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
  103. package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
  104. package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
  105. package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
  106. package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
  107. package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
  108. package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
  109. package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
  110. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
  111. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
  112. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
  113. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
  114. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
  115. package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
  116. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
  117. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
  118. package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
  119. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
  120. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
  121. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
  122. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
  123. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
  124. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
  125. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
  126. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
  127. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
  128. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
  129. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
  130. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
  131. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
  132. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
  133. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
  134. package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
  135. package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
  136. package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
  137. package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
  138. package/templates/firebase/assets/images/splashscreen.png +0 -0
@@ -1,72 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/i18n/translations.g.dart';
3
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_feature.dart';
4
-
5
- class OnboardingFeatureOne extends StatelessWidget {
6
- final String nextRoute;
7
-
8
- const OnboardingFeatureOne({
9
- super.key,
10
- required this.nextRoute,
11
- });
12
-
13
- @override
14
- Widget build(BuildContext context) {
15
- final translations = Translations.of(context).onboarding.feature_1;
16
- return OnboardingStep(
17
- title: translations.title,
18
- description: translations.description,
19
- btnText: translations.action,
20
- nextRoute: nextRoute,
21
- imgPath: 'assets/images/onboarding/purchase.png',
22
- withBg: true,
23
- progress: 0.1,
24
- );
25
- }
26
- }
27
-
28
- class OnboardingFeatureTwo extends StatelessWidget {
29
- final String nextRoute;
30
-
31
- const OnboardingFeatureTwo({
32
- super.key,
33
- required this.nextRoute,
34
- });
35
-
36
- @override
37
- Widget build(BuildContext context) {
38
- final translations = Translations.of(context).onboarding.feature_2;
39
- return OnboardingStep(
40
- title: translations.title,
41
- description: translations.description,
42
- btnText: translations.action,
43
- nextRoute: nextRoute,
44
- imgPath: 'assets/images/onboarding/authentication-login-template.jpg',
45
- withBg: true,
46
- progress: 0.2,
47
- );
48
- }
49
- }
50
-
51
- class OnboardingFeatureThree extends StatelessWidget {
52
- final String nextRoute;
53
-
54
- const OnboardingFeatureThree({
55
- super.key,
56
- required this.nextRoute,
57
- });
58
-
59
- @override
60
- Widget build(BuildContext context) {
61
- final translations = Translations.of(context).onboarding.feature_3;
62
- return OnboardingStep(
63
- title: translations.title,
64
- description: translations.description,
65
- btnText: translations.action,
66
- nextRoute: nextRoute,
67
- imgPath: 'assets/images/onboarding/notifications.png',
68
- withBg: true,
69
- progress: 0.3,
70
- );
71
- }
72
- }
@@ -1,92 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_riverpod/flutter_riverpod.dart';
3
- import 'package:kasy_kit/core/theme/theme.dart';
4
- import 'package:kasy_kit/i18n/translations.g.dart';
5
- import 'package:kasy_kit/features/onboarding/providers/onboarding_provider.dart';
6
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
7
-
8
- class OnboardingLoader extends ConsumerStatefulWidget {
9
- final VoidCallback onCompleted;
10
-
11
- const OnboardingLoader({super.key, required this.onCompleted});
12
-
13
- @override
14
- ConsumerState<ConsumerStatefulWidget> createState() =>
15
- _OnboardingJournalLoaderState();
16
- }
17
-
18
- class _OnboardingJournalLoaderState extends ConsumerState<OnboardingLoader> {
19
- @override
20
- void initState() {
21
- super.initState();
22
- Future.delayed(const Duration(milliseconds: 3500), () async {
23
- await ref.onboardingNotifier.onOnboardingCompleted();
24
- widget.onCompleted();
25
- });
26
- }
27
-
28
- @override
29
- Widget build(BuildContext context) {
30
- final translations = Translations.of(context).onboarding.loading;
31
- return OnboardingBackground(
32
- child: SafeArea(
33
- child: Column(
34
- mainAxisAlignment: MainAxisAlignment.center,
35
- children: [
36
- Flexible(
37
- flex: 0,
38
- child: Padding(
39
- padding: const EdgeInsets.fromLTRB(
40
- KasySpacing.md,
41
- KasySpacing.xl,
42
- KasySpacing.md,
43
- 0,
44
- ),
45
- child: Text(
46
- translations.title,
47
- textAlign: TextAlign.center,
48
- style: context.textTheme.headlineMedium?.copyWith(
49
- color: context.colors.onBackground,
50
- ),
51
- ),
52
- ),
53
- ),
54
- Flexible(
55
- flex: 0,
56
- child: Padding(
57
- padding: const EdgeInsets.fromLTRB(
58
- KasySpacing.xl,
59
- KasySpacing.md,
60
- KasySpacing.xl,
61
- 0,
62
- ),
63
- child: Text(
64
- translations.subtitle,
65
- textAlign: TextAlign.center,
66
- style: context.textTheme.bodyMedium?.copyWith(
67
- color: context.colors.muted,
68
- fontWeight: FontWeight.w400,
69
- ),
70
- ),
71
- ),
72
- ),
73
- Padding(
74
- // Intentionally narrow (100px lateral) — visual design choice for loader
75
- padding: const EdgeInsets.fromLTRB(100, KasySpacing.xl, 100, 0),
76
- child: ClipRRect(
77
- borderRadius: KasyRadius.fullBorderRadius,
78
- child: LinearProgressIndicator(
79
- minHeight: 12,
80
- valueColor: AlwaysStoppedAnimation<Color>(
81
- context.colors.primary,
82
- ),
83
- backgroundColor: context.colors.primary.withValues(alpha: 0.1),
84
- ),
85
- ),
86
- ),
87
- ],
88
- ),
89
- ),
90
- );
91
- }
92
- }
@@ -1,73 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_riverpod/flutter_riverpod.dart';
3
- import 'package:kasy_kit/components/components.dart';
4
- import 'package:kasy_kit/core/data/api/analytics_api.dart';
5
- import 'package:kasy_kit/core/theme/theme.dart';
6
- import 'package:kasy_kit/features/notifications/providers/models/notification.dart';
7
- import 'package:kasy_kit/features/notifications/repositories/notifications_repository.dart';
8
- import 'package:kasy_kit/features/onboarding/providers/onboarding_provider.dart';
9
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
10
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart';
11
- import 'package:kasy_kit/i18n/translations.g.dart';
12
-
13
- final _formStep3Key = GlobalKey<FormState>();
14
-
15
- class NotificationsPermissionStep extends ConsumerWidget {
16
- final String nextRoute;
17
-
18
- const NotificationsPermissionStep({
19
- super.key,
20
- required this.nextRoute,
21
- });
22
-
23
- @override
24
- Widget build(BuildContext context, WidgetRef ref) {
25
- final notifRepository = ref.watch(notificationRepositoryProvider);
26
- final permissionFuture = notifRepository.getPermissionStatus();
27
- final translations = Translations.of(context).onboarding.notifications;
28
-
29
- return OnboardingBackground(
30
- child: FutureBuilder<NotificationPermission>(
31
- future: permissionFuture,
32
- builder: (context, snapshot) {
33
- if (!snapshot.hasData) {
34
- return const SizedBox();
35
- }
36
- return Form(
37
- key: _formStep3Key,
38
- child: OnboardingIllustrationScaffold(
39
- progress: 0.9,
40
- title: translations.title,
41
- description: translations.description,
42
- imageAsset: 'assets/images/onboarding/img2.jpg',
43
- footerActions: [
44
- KasyButton(
45
- label: translations.continue_button,
46
- expand: true,
47
- onPressed: () => ref.onboardingNotifier
48
- .setupNotifications()
49
- .then((_) {
50
- if (!context.mounted) return;
51
- Navigator.of(context).pushNamed(nextRoute);
52
- }),
53
- ),
54
- const SizedBox(height: KasySpacing.smd),
55
- KasyButton(
56
- label: translations.skip_button,
57
- variant: KasyButtonVariant.soft,
58
- expand: true,
59
- onPressed: () {
60
- ref
61
- .read(analyticsApiProvider)
62
- .logEvent('setup_notifications_refused', {});
63
- Navigator.of(context).pushNamed(nextRoute);
64
- },
65
- ),
66
- ],
67
- ),
68
- );
69
- },
70
- ),
71
- );
72
- }
73
- }
@@ -1,89 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_riverpod/flutter_riverpod.dart';
3
- import 'package:kasy_kit/i18n/translations.g.dart';
4
- import 'package:kasy_kit/features/onboarding/models/user_info.dart';
5
- import 'package:kasy_kit/features/onboarding/providers/onboarding_provider.dart';
6
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_radio_question.dart';
7
- import 'package:kasy_kit/features/onboarding/ui/widgets/selectable_row_tile.dart';
8
-
9
- //--------------------------------------------
10
- /// Question about the user's gender
11
- //--------------------------------------------
12
- class UserSexeOnboardingQuestion extends ConsumerWidget {
13
- final String nextRoute;
14
-
15
- const UserSexeOnboardingQuestion({
16
- super.key,
17
- required this.nextRoute,
18
- });
19
-
20
- @override
21
- Widget build(BuildContext context, WidgetRef ref) {
22
- final translations = Translations.of(context).onboarding.genderQuestion;
23
- return OnboardingRadioQuestion(
24
- title: translations.title,
25
- description: translations.description,
26
- btnText: translations.action,
27
- progress: 0.3,
28
- optionIds: translations.options.keys.toList(),
29
- optionBuilder: (key, selected) => SelectableRowTile(
30
- title: translations.options[key],
31
- selected: selected,
32
- ),
33
- // here we can add a reassurance message when the user selects an option
34
- // reassuranceBuilder: (key) => CheckedReassurance(
35
- // text: translations.reassurance[key]!,
36
- // ),
37
- onValidate: (key) {
38
- // print("Selected option: $key");
39
- if (key != null) {
40
- ref
41
- .read(onboardingProvider.notifier)
42
- .onAnsweredQuestion(UserSexeInfo.fromString(key));
43
- }
44
- Navigator.of(context).pushReplacementNamed(nextRoute);
45
- },
46
- );
47
- }
48
- }
49
-
50
- //--------------------------------------------
51
- /// Question about the user's gender
52
- //--------------------------------------------
53
- class UserAgeOnboardingQuestion extends ConsumerWidget {
54
- final String nextRoute;
55
-
56
- const UserAgeOnboardingQuestion({
57
- super.key,
58
- required this.nextRoute,
59
- });
60
-
61
- @override
62
- Widget build(BuildContext context, WidgetRef ref) {
63
- final translations = Translations.of(context).onboarding.ageQuestion;
64
- return OnboardingRadioQuestion(
65
- title: translations.title,
66
- description: translations.description,
67
- btnText: translations.action,
68
- progress: 0.3,
69
- optionIds: translations.options.keys.toList(),
70
- optionBuilder: (key, selected) => SelectableRowTile(
71
- title: translations.options[key],
72
- selected: selected,
73
- ),
74
- // here we can add a reassurance message when the user selects an option
75
- // reassuranceBuilder: (key) => CheckedReassurance(
76
- // text: translations.reassurance[key]!,
77
- // ),
78
- onValidate: (key) {
79
- // print("Selected option: $key");
80
- if (key != null) {
81
- ref
82
- .read(onboardingProvider.notifier)
83
- .onAnsweredQuestion(UserAgeInfo.fromString(key));
84
- }
85
- Navigator.of(context).pushReplacementNamed(nextRoute);
86
- },
87
- );
88
- }
89
- }
@@ -1,94 +0,0 @@
1
- import 'package:flutter/foundation.dart';
2
- import 'package:flutter/material.dart';
3
- import 'package:flutter_riverpod/flutter_riverpod.dart';
4
- import 'package:kasy_kit/core/data/api/analytics_api.dart';
5
- import 'package:kasy_kit/features/onboarding/ui/animations/page_transitions.dart';
6
- import 'package:kasy_kit/features/onboarding/ui/components/onboarding_att_setup.dart';
7
- import 'package:kasy_kit/features/onboarding/ui/components/onboarding_features.dart';
8
- import 'package:kasy_kit/features/onboarding/ui/components/onboarding_loader.dart';
9
- import 'package:kasy_kit/features/onboarding/ui/components/onboarding_notifications_setup.dart';
10
- import 'package:kasy_kit/features/onboarding/ui/components/onboarding_questions.dart';
11
- import 'package:kasy_kit/features/subscription/ui/premium_page.dart';
12
-
13
-
14
- class OnboardingPage extends ConsumerWidget {
15
- const OnboardingPage({super.key});
16
-
17
- @override
18
- Widget build(BuildContext context, WidgetRef ref) {
19
- return Navigator(
20
- initialRoute: 'feature_1',
21
- observers: [
22
- AnalyticsObserver(
23
- prefix: 'userOnboarding/',
24
- analyticsApi: MixpanelAnalyticsApi.instance(),
25
- ),
26
- ],
27
- onGenerateRoute: (settings) => switch (settings.name) {
28
- 'feature_1' => OnboardingRouteTransition(
29
- builder: (context) => const OnboardingFeatureOne(
30
- nextRoute: 'feature_2',
31
- ),
32
- settings: settings,
33
- ),
34
- 'feature_2' => OnboardingRouteTransition(
35
- builder: (context) => const OnboardingFeatureTwo(
36
- nextRoute: 'feature_3',
37
- ),
38
- settings: settings,
39
- ),
40
- 'feature_3' => OnboardingRouteTransition(
41
- builder: (context) => const OnboardingFeatureThree(
42
- nextRoute: 'sexe_question',
43
- ),
44
- settings: settings,
45
- ),
46
- 'sexe_question' => OnboardingRouteTransition(
47
- builder: (context) => const UserSexeOnboardingQuestion(
48
- nextRoute: 'age_question',
49
- ),
50
- settings: settings,
51
- ),
52
- 'age_question' => OnboardingRouteTransition(
53
- builder: (context) => const UserAgeOnboardingQuestion(
54
- nextRoute: 'notifications',
55
- ),
56
- settings: settings,
57
- ),
58
-
59
- 'notifications' => OnboardingRouteTransition(
60
- builder: (context) => NotificationsPermissionStep(
61
- nextRoute: switch (defaultTargetPlatform) {
62
- TargetPlatform.iOS => 'att_consent',
63
- _ => 'loader',
64
- },
65
- ),
66
- settings: settings,
67
- ),
68
- 'att_consent' => OnboardingRouteTransition(
69
- builder: (context) => const AttPermissionStep(
70
- nextRoute: 'loader',
71
- ),
72
- settings: settings,
73
- ),
74
- 'loader' => OnboardingRouteTransition(
75
- builder: (context) => OnboardingLoader(
76
- onCompleted: () => Navigator.of(context).pushReplacementNamed(
77
- 'paywall',
78
- ),
79
- ),
80
- settings: settings,
81
- ),
82
- 'paywall' => OnboardingRouteTransition(
83
- builder: (context) => const PremiumPage(
84
- args: PremiumPageArgs(
85
- redirect: '/',
86
- ),
87
- ),
88
- settings: settings,
89
- ),
90
- String() || null => throw 'Unimplemented route: $settings.name',
91
- },
92
- );
93
- }
94
- }
@@ -1,80 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/core/theme/theme.dart';
3
-
4
- class OnboardingBackground extends StatelessWidget {
5
- final Widget child;
6
- final String? bgImagePath;
7
- final double bgImageOpacity;
8
- final Color? bgColor;
9
-
10
- const OnboardingBackground({
11
- super.key,
12
- required this.child,
13
- this.bgImagePath,
14
- this.bgColor,
15
- this.bgImageOpacity = .15,
16
- });
17
-
18
- @override
19
- Widget build(BuildContext context) {
20
- return Stack(
21
- fit: StackFit.expand,
22
- children: <Widget>[
23
- if (bgImagePath != null)
24
- Positioned.fill(
25
- child: Opacity(
26
- opacity: bgImageOpacity,
27
- child: Container(
28
- decoration: BoxDecoration(
29
- image: DecorationImage(
30
- image: AssetImage(bgImagePath!),
31
- fit: BoxFit.cover,
32
- ),
33
- ),
34
- ),
35
- ),
36
- ),
37
- Positioned.fill(
38
- child: ColoredBox(
39
- color: context.colors.background,
40
- ),
41
- ),
42
- Positioned.fill(
43
- child: Container(
44
- decoration: BoxDecoration(
45
- gradient: LinearGradient(
46
- begin: Alignment.topCenter,
47
- end: Alignment.bottomCenter,
48
- colors: [
49
- bgColor ?? context.colors.primary.withValues(alpha: .15),
50
- bgColor ?? context.colors.primary.withValues(alpha: 0),
51
- ],
52
- stops: const [0.0, .5],
53
- ),
54
- )),
55
- ),
56
- // Positioned(
57
- // top: 120,
58
- // left: 0,
59
- // right: 0,
60
- // child: Image.asset(
61
- // 'assets/images/introduction/lines.png',
62
- // fit: BoxFit.cover,
63
- // ),
64
- // ),
65
- Positioned.fill(
66
- child: LayoutBuilder(
67
- builder: (context, constraints) {
68
- return SizedBox(
69
- key: const ValueKey("background"),
70
- width: constraints.maxWidth,
71
- height: constraints.maxHeight,
72
- child: child,
73
- );
74
- },
75
- ),
76
- ),
77
- ],
78
- );
79
- }
80
- }
@@ -1,139 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_animate/flutter_animate.dart';
3
- import 'package:kasy_kit/components/components.dart';
4
- import 'package:kasy_kit/core/theme/theme.dart';
5
- import 'package:kasy_kit/core/widgets/responsive_layout.dart';
6
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
7
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart';
8
-
9
- /// A generic onboarding step widget with text and image.
10
- class OnboardingStep extends StatelessWidget {
11
- final String? title;
12
- final Widget? titleWidget;
13
- final String imgPath;
14
- final String description;
15
- final String btnText;
16
- final String nextRoute;
17
- final VoidCallback? onNext;
18
- final double progress;
19
- final Widget? image;
20
- final bool withBg;
21
-
22
- const OnboardingStep({
23
- super.key,
24
- this.title,
25
- this.titleWidget,
26
- required this.imgPath,
27
- required this.description,
28
- required this.btnText,
29
- required this.nextRoute,
30
- required this.progress,
31
- this.onNext,
32
- this.withBg = false,
33
- this.image,
34
- });
35
-
36
- @override
37
- Widget build(BuildContext context) {
38
- final Widget? illustration = image ??
39
- (imgPath.isNotEmpty
40
- ? Animate(
41
- effects: const [
42
- FadeEffect(
43
- delay: Duration(milliseconds: 100),
44
- duration: Duration(milliseconds: 200),
45
- curve: Curves.easeIn,
46
- ),
47
- MoveEffect(
48
- delay: Duration(milliseconds: 100),
49
- duration: Duration(milliseconds: 450),
50
- curve: Curves.easeOut,
51
- begin: Offset(0, 50),
52
- end: Offset.zero,
53
- ),
54
- ],
55
- child: Image.asset(imgPath, fit: BoxFit.contain),
56
- )
57
- : null);
58
-
59
- final scaffold = OnboardingIllustrationScaffold(
60
- progress: progress,
61
- title: title ?? '',
62
- titleWidget: title != null
63
- ? Animate(
64
- effects: const [
65
- FadeEffect(
66
- delay: Duration(milliseconds: 200),
67
- duration: Duration(milliseconds: 200),
68
- curve: Curves.easeIn,
69
- ),
70
- MoveEffect(
71
- delay: Duration(milliseconds: 200),
72
- duration: Duration(milliseconds: 450),
73
- curve: Curves.easeOut,
74
- begin: Offset(0, 50),
75
- end: Offset.zero,
76
- ),
77
- ],
78
- child: Text(
79
- title!,
80
- textAlign: TextAlign.center,
81
- style: context.textTheme.headlineMedium?.copyWith(
82
- color: context.colors.onBackground,
83
- fontWeight: FontWeight.w600,
84
- ),
85
- ),
86
- )
87
- : titleWidget,
88
- description: description,
89
- descriptionWidget: Animate(
90
- effects: const [
91
- FadeEffect(
92
- delay: Duration(milliseconds: 300),
93
- duration: Duration(milliseconds: 200),
94
- curve: Curves.easeIn,
95
- ),
96
- MoveEffect(
97
- delay: Duration(milliseconds: 300),
98
- duration: Duration(milliseconds: 450),
99
- curve: Curves.easeOut,
100
- begin: Offset(0, 50),
101
- end: Offset.zero,
102
- ),
103
- ],
104
- child: Text(
105
- description,
106
- textAlign: TextAlign.center,
107
- style: context.textTheme.bodyLarge?.copyWith(
108
- color: context.colors.onBackground.withValues(alpha: 0.6),
109
- ),
110
- ),
111
- ),
112
- image: illustration,
113
- footerActions: [
114
- KasyButton(
115
- label: btnText,
116
- expand: true,
117
- onPressed: () {
118
- if (onNext != null) {
119
- onNext!.call();
120
- } else {
121
- Navigator.of(context).pushReplacementNamed(nextRoute);
122
- }
123
- },
124
- ),
125
- ],
126
- );
127
-
128
- final content = ResponsiveLayout(
129
- small: withBg
130
- ? OnboardingBackground(child: scaffold)
131
- : ColoredBox(
132
- color: context.colors.background,
133
- child: scaffold,
134
- ),
135
- );
136
-
137
- return content;
138
- }
139
- }