kasy-cli 1.10.0 → 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.
- package/bin/kasy.js +25 -4
- package/lib/commands/check.js +40 -50
- package/lib/commands/deploy.js +25 -25
- package/lib/commands/splash.js +220 -0
- package/lib/scaffold/CHANGELOG.json +9 -0
- package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
- package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
- package/lib/scaffold/features/README.md +15 -139
- package/lib/scaffold/shared/generator-utils.js +16 -15
- package/lib/utils/i18n.js +292 -43
- package/package.json +2 -2
- package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
- package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
- package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
- package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
- package/templates/firebase/assets/images/splash_logo_light.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
- package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
- package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
- package/templates/firebase/lib/core/initializer/onstart_widget.dart +7 -1
- package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
- package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
- package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
- package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
- package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
- package/templates/firebase/lib/i18n/en.i18n.json +6 -2
- package/templates/firebase/lib/i18n/es.i18n.json +6 -2
- package/templates/firebase/lib/i18n/pt.i18n.json +6 -2
- package/templates/firebase/lib/main.dart +29 -10
- package/templates/firebase/pubspec.yaml +4 -5
- package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
- package/templates/firebase/web/index.html +47 -39
- package/templates/firebase/web/splash/img/dark-1x.png +0 -0
- package/templates/firebase/web/splash/img/dark-2x.png +0 -0
- package/templates/firebase/web/splash/img/dark-3x.png +0 -0
- package/templates/firebase/web/splash/img/dark-4x.png +0 -0
- package/templates/firebase/web/splash/img/light-1x.png +0 -0
- package/templates/firebase/web/splash/img/light-2x.png +0 -0
- package/templates/firebase/web/splash/img/light-3x.png +0 -0
- package/templates/firebase/web/splash/img/light-4x.png +0 -0
- package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
- package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
- package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
- package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
- package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
- package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
- package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
- package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
- package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
- package/lib/scaffold/features/ci/codemagic.yaml +0 -157
- package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
- package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
- package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
- package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
- package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
- package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
- package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
- package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
- package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
- package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
- package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
- package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
- package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
- package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
- package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
- package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
- package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
- package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
- package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
- package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
- package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
- package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
- package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
- package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
- package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
- package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
- package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
- package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
- package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
- package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
- package/templates/firebase/assets/images/splashscreen.png +0 -0
|
@@ -1,66 +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/data/api/tracking_api.dart';
|
|
6
|
-
import 'package:kasy_kit/core/states/user_state_notifier.dart';
|
|
7
|
-
import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
|
|
8
|
-
import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart';
|
|
9
|
-
import 'package:kasy_kit/features/subscription/repositories/subscription_repository.dart';
|
|
10
|
-
import 'package:kasy_kit/i18n/translations.g.dart';
|
|
11
|
-
import 'package:permission_handler/permission_handler.dart';
|
|
12
|
-
|
|
13
|
-
/// ATT Permission Step
|
|
14
|
-
/// ATT is only available on iOS
|
|
15
|
-
/// This is the consent screen for iOS 14+ that asks the user to allow the app to access the ATT framework
|
|
16
|
-
/// In a few words you need this to get the IDFA (Identifier for Advertisers) which is used for tracking purposes
|
|
17
|
-
/// So you can create better facebook ads, google ads, etc...
|
|
18
|
-
class AttPermissionStep extends ConsumerWidget {
|
|
19
|
-
final String nextRoute;
|
|
20
|
-
|
|
21
|
-
const AttPermissionStep({
|
|
22
|
-
super.key,
|
|
23
|
-
required this.nextRoute,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
@override
|
|
27
|
-
Widget build(BuildContext context, WidgetRef ref) {
|
|
28
|
-
final translations = Translations.of(context).onboarding.att;
|
|
29
|
-
|
|
30
|
-
return OnboardingBackground(
|
|
31
|
-
child: OnboardingIllustrationScaffold(
|
|
32
|
-
progress: 0.9,
|
|
33
|
-
title: translations.title,
|
|
34
|
-
description: translations.description,
|
|
35
|
-
imageAsset: 'assets/images/onboarding/img3.jpg',
|
|
36
|
-
footerActions: [
|
|
37
|
-
KasyButton(
|
|
38
|
-
label: translations.continue_button,
|
|
39
|
-
expand: true,
|
|
40
|
-
onPressed: () async {
|
|
41
|
-
final Map<Permission, PermissionStatus> permission = await [
|
|
42
|
-
Permission.appTrackingTransparency,
|
|
43
|
-
].request();
|
|
44
|
-
final isGranted =
|
|
45
|
-
permission.values.first == PermissionStatus.granted;
|
|
46
|
-
ref.read(analyticsApiProvider).logEvent('att_request', {
|
|
47
|
-
'granted': isGranted,
|
|
48
|
-
});
|
|
49
|
-
final userId =
|
|
50
|
-
ref.read(userStateNotifierProvider).user.idOrNull;
|
|
51
|
-
if (userId != null) {
|
|
52
|
-
ref
|
|
53
|
-
.read(subscriptionRepositoryProvider)
|
|
54
|
-
.initUser(userId)
|
|
55
|
-
.ignore();
|
|
56
|
-
ref.read(facebookEventApiProvider).initUser(userId).ignore();
|
|
57
|
-
}
|
|
58
|
-
if (!context.mounted) return;
|
|
59
|
-
Navigator.of(context).pushNamed(nextRoute);
|
|
60
|
-
},
|
|
61
|
-
),
|
|
62
|
-
],
|
|
63
|
-
),
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -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
|
-
}
|