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.
Files changed (141) hide show
  1. package/bin/kasy.js +25 -4
  2. package/lib/commands/check.js +40 -50
  3. package/lib/commands/deploy.js +25 -25
  4. package/lib/commands/splash.js +220 -0
  5. package/lib/scaffold/CHANGELOG.json +9 -0
  6. package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
  7. package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
  8. package/lib/scaffold/features/README.md +15 -139
  9. package/lib/scaffold/shared/generator-utils.js +16 -15
  10. package/lib/utils/i18n.js +292 -43
  11. package/package.json +2 -2
  12. package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
  13. package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
  14. package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
  15. package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
  16. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  17. package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
  18. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
  19. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
  20. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
  21. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
  22. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  23. package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
  24. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
  25. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
  26. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
  27. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
  28. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
  29. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
  30. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
  31. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
  32. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
  33. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
  34. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
  35. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
  36. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
  37. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
  38. package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
  39. package/templates/firebase/assets/images/splash_logo_light.png +0 -0
  40. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
  41. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  42. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
  43. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  44. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  45. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  46. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
  47. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
  48. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
  49. package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
  50. package/templates/firebase/lib/core/initializer/onstart_widget.dart +7 -1
  51. package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
  52. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
  53. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
  54. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
  55. package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
  56. package/templates/firebase/lib/i18n/en.i18n.json +6 -2
  57. package/templates/firebase/lib/i18n/es.i18n.json +6 -2
  58. package/templates/firebase/lib/i18n/pt.i18n.json +6 -2
  59. package/templates/firebase/lib/main.dart +29 -10
  60. package/templates/firebase/pubspec.yaml +4 -5
  61. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
  62. package/templates/firebase/web/index.html +47 -39
  63. package/templates/firebase/web/splash/img/dark-1x.png +0 -0
  64. package/templates/firebase/web/splash/img/dark-2x.png +0 -0
  65. package/templates/firebase/web/splash/img/dark-3x.png +0 -0
  66. package/templates/firebase/web/splash/img/dark-4x.png +0 -0
  67. package/templates/firebase/web/splash/img/light-1x.png +0 -0
  68. package/templates/firebase/web/splash/img/light-2x.png +0 -0
  69. package/templates/firebase/web/splash/img/light-3x.png +0 -0
  70. package/templates/firebase/web/splash/img/light-4x.png +0 -0
  71. package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
  72. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
  73. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
  74. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
  75. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
  76. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
  77. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
  78. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
  79. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  80. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
  81. package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
  82. package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
  83. package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
  84. package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
  85. package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
  86. package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
  87. package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
  88. package/lib/scaffold/features/ci/codemagic.yaml +0 -157
  89. package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
  90. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
  91. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
  92. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
  93. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
  94. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
  95. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
  96. package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
  97. package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
  98. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
  99. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
  100. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
  101. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
  102. package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
  103. package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
  104. package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
  105. package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
  106. package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
  107. package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
  108. package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
  109. package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
  110. package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
  111. package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
  112. package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
  113. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
  114. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
  115. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
  116. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
  117. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
  118. package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
  119. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
  120. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
  121. package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
  122. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
  123. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
  124. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
  125. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
  126. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
  127. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
  128. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
  129. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
  130. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
  131. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
  132. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
  133. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
  134. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
  135. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
  136. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
  137. package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
  138. package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
  139. package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
  140. package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
  141. package/templates/firebase/assets/images/splashscreen.png +0 -0
@@ -1,175 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_riverpod/flutter_riverpod.dart';
3
- import 'package:go_router/go_router.dart';
4
- import 'package:kasy_kit/components/kasy_toast.dart';
5
- import 'package:kasy_kit/core/theme/theme.dart';
6
- import 'package:kasy_kit/core/widgets/responsive_layout.dart';
7
- import 'package:kasy_kit/i18n/translations.g.dart';
8
- import 'package:kasy_kit/features/feedbacks/providers/feedback_page_notifier.dart';
9
- import 'package:kasy_kit/features/feedbacks/ui/widgets/add_feature_button.dart';
10
- import 'package:kasy_kit/features/feedbacks/ui/widgets/feature_card.dart';
11
-
12
- class FeedbackPage extends ConsumerWidget {
13
- const FeedbackPage({super.key});
14
-
15
- @override
16
- Widget build(BuildContext context, WidgetRef ref) {
17
- final state = ref.watch(feedbackPageProvider);
18
- final translations = Translations.of(context).feature_requests;
19
-
20
- return Scaffold(
21
- backgroundColor: context.colors.background,
22
- body: SafeArea(
23
- child: LargeLayoutContainer(
24
- child: CustomScrollView(
25
- slivers: [
26
- SliverAppBar(
27
- backgroundColor: Colors.transparent,
28
- leading: IconButton(
29
- icon: const Icon(Icons.arrow_back),
30
- onPressed: () =>
31
- context.canPop() ? context.pop() : context.go('/'),
32
- ),
33
- ),
34
- SliverToBoxAdapter(
35
- child: Padding(
36
- padding: const EdgeInsets.fromLTRB(
37
- KasySpacing.lg,
38
- KasySpacing.xl,
39
- KasySpacing.lg,
40
- 0,
41
- ),
42
- child: Text(
43
- translations.title,
44
- style: context.textTheme.headlineMedium?.copyWith(
45
- fontWeight: FontWeight.bold,
46
- ),
47
- ),
48
- ),
49
- ),
50
- SliverToBoxAdapter(
51
- child: Padding(
52
- padding: const EdgeInsets.fromLTRB(
53
- KasySpacing.lg,
54
- KasySpacing.sm,
55
- KasySpacing.lg,
56
- KasySpacing.md,
57
- ),
58
- child: Text(
59
- translations.description,
60
- style: context.textTheme.bodyLarge?.copyWith(
61
- fontWeight: FontWeight.w400,
62
- color: context.colors.muted,
63
- ),
64
- ),
65
- ),
66
- ),
67
- SliverToBoxAdapter(
68
- child: Padding(
69
- padding: const EdgeInsets.symmetric(
70
- horizontal: KasySpacing.lg,
71
- vertical: KasySpacing.md,
72
- ),
73
- child: AddFeatureButton(
74
- title: translations.add_feature.title,
75
- description: translations.add_feature.description,
76
- onPressed: () async {
77
- final success = await context.push<bool>('/feedback/new');
78
- if (success == true && context.mounted) {
79
- showSuccessToast(
80
- context: context,
81
- title: translations.add_feature.toast_success.title,
82
- text: translations.add_feature.toast_success.description,
83
- );
84
- }
85
- },
86
- ),
87
- ),
88
- ),
89
- state.map(
90
- data: (data) {
91
- if (data.value.featureRequests.isEmpty) {
92
- return SliverToBoxAdapter(
93
- child: Padding(
94
- padding: const EdgeInsets.symmetric(
95
- horizontal: KasySpacing.lg,
96
- vertical: KasySpacing.md,
97
- ),
98
- child: Text(
99
- translations.no_requests,
100
- textAlign: TextAlign.center,
101
- style: context.textTheme.bodyMedium?.copyWith(
102
- fontWeight: FontWeight.w300,
103
- color: context.colors.muted,
104
- ),
105
- ),
106
- ),
107
- );
108
- }
109
- return SliverList.separated(
110
- itemBuilder: (context, index) => Padding(
111
- padding: const EdgeInsets.symmetric(
112
- horizontal: KasySpacing.lg,
113
- ),
114
- child: FeatureCard(
115
- title: data.value.featureRequests[index].title,
116
- description:
117
- data.value.featureRequests[index].description,
118
- votes: data.value.featureRequests[index].votes,
119
- onVote: () {
120
- ref
121
- .read(feedbackPageProvider.notifier)
122
- .vote(data.value.featureRequests[index]);
123
- },
124
- voted: data.value.hasVoted(
125
- data.value.featureRequests[index],
126
- ),
127
- ),
128
- ),
129
- separatorBuilder: (context, index) =>
130
- const SizedBox(height: KasySpacing.smd),
131
- itemCount: data.value.featureRequests.length,
132
- );
133
- },
134
- error: (error) => SliverFillRemaining(
135
- child: Center(child: Text(error.error.toString())),
136
- ),
137
- loading: (data) {
138
- if (!data.hasValue) {
139
- return const SliverFillRemaining(
140
- child: Center(child: CircularProgressIndicator()),
141
- );
142
- }
143
- return SliverList.separated(
144
- itemBuilder: (context, index) => Padding(
145
- padding: const EdgeInsets.symmetric(
146
- horizontal: KasySpacing.lg,
147
- ),
148
- child: FeatureCard(
149
- title: data.value!.featureRequests[index].title,
150
- description:
151
- data.value!.featureRequests[index].description,
152
- votes: data.value!.featureRequests[index].votes,
153
- onVote: () {},
154
- disabled: true,
155
- voted: data.value!.hasVoted(
156
- data.value!.featureRequests[index],
157
- ),
158
- ),
159
- ),
160
- separatorBuilder: (context, index) =>
161
- const SizedBox(height: KasySpacing.smd),
162
- itemCount: data.value!.featureRequests.length,
163
- );
164
- },
165
- ),
166
- const SliverToBoxAdapter(
167
- child: SizedBox(height: KasySpacing.xxxl),
168
- ),
169
- ],
170
- ),
171
- ),
172
- ),
173
- );
174
- }
175
- }
@@ -1,76 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/core/theme/theme.dart';
3
-
4
- class AddFeatureButton extends StatefulWidget {
5
- final String title;
6
- final String description;
7
- final VoidCallback onPressed;
8
-
9
- const AddFeatureButton({
10
- super.key,
11
- required this.title,
12
- required this.description,
13
- required this.onPressed,
14
- });
15
-
16
- @override
17
- State<AddFeatureButton> createState() => _AddFeatureButtonState();
18
- }
19
-
20
- class _AddFeatureButtonState extends State<AddFeatureButton> {
21
- @override
22
- Widget build(BuildContext context) {
23
- return InkWell(
24
- onTap: widget.onPressed,
25
- borderRadius: KasyRadius.mdBorderRadius,
26
- child: Ink(
27
- padding: const EdgeInsets.symmetric(
28
- horizontal: KasySpacing.lg,
29
- vertical: KasySpacing.md,
30
- ),
31
- decoration: BoxDecoration(
32
- color: context.colors.primary,
33
- borderRadius: KasyRadius.mdBorderRadius,
34
- border: Border.all(
35
- color: context.colors.onBackground.withValues(alpha: .05),
36
- ),
37
- boxShadow: [
38
- BoxShadow(
39
- color: context.colors.primary.withValues(alpha: 0.05),
40
- blurRadius: 8,
41
- offset: const Offset(0, 4),
42
- ),
43
- ],
44
- ),
45
- child: Row(
46
- children: [
47
- Icon(Icons.add, size: 32, color: context.colors.onPrimary),
48
- const SizedBox(width: KasySpacing.md),
49
- Expanded(
50
- child: Column(
51
- crossAxisAlignment: CrossAxisAlignment.start,
52
- spacing: KasySpacing.xs,
53
- children: [
54
- Text(
55
- widget.title,
56
- style: context.textTheme.titleLarge?.copyWith(
57
- fontWeight: FontWeight.bold,
58
- color: context.colors.onPrimary,
59
- ),
60
- ),
61
- Text(
62
- widget.description,
63
- style: context.textTheme.bodyMedium?.copyWith(
64
- fontWeight: FontWeight.w400,
65
- color: context.colors.onPrimary.withValues(alpha: 0.7),
66
- ),
67
- ),
68
- ],
69
- ),
70
- ),
71
- ],
72
- ),
73
- ),
74
- );
75
- }
76
- }
@@ -1,279 +0,0 @@
1
- import 'dart:math';
2
-
3
- import 'package:flutter/material.dart';
4
- import 'package:flutter/services.dart';
5
- import 'package:kasy_kit/core/theme/theme.dart';
6
- import 'package:kasy_kit/core/widgets/debouncer.dart';
7
-
8
- class FeatureCard extends StatefulWidget {
9
- final String title;
10
- final String description;
11
- final int votes;
12
- final VoidCallback onVote;
13
- final bool disabled;
14
- final bool voted;
15
-
16
- const FeatureCard({
17
- super.key,
18
- required this.title,
19
- required this.description,
20
- required this.votes,
21
- required this.onVote,
22
- this.disabled = false,
23
- required this.voted,
24
- });
25
-
26
- @override
27
- State<FeatureCard> createState() => _FeatureCardState();
28
- }
29
-
30
- class _FeatureCardState extends State<FeatureCard> {
31
- @override
32
- Widget build(BuildContext context) {
33
- return Container(
34
- padding: const EdgeInsets.all(KasySpacing.lg),
35
- decoration: BoxDecoration(
36
- color: context.colors.surface,
37
- borderRadius: KasyRadius.smBorderRadius,
38
- border: Border.all(
39
- color: context.colors.outline,
40
- ),
41
- boxShadow: [
42
- BoxShadow(
43
- color: context.colors.primary.withValues(alpha: 0.05),
44
- blurRadius: 8,
45
- offset: const Offset(0, 4),
46
- ),
47
- BoxShadow(
48
- color: context.colors.onBackground.withValues(alpha: 0.03),
49
- blurRadius: 8,
50
- offset: const Offset(0, 4),
51
- spreadRadius: 2,
52
- ),
53
- ],
54
- ),
55
- child: Row(
56
- children: [
57
- Expanded(
58
- child: Column(
59
- crossAxisAlignment: CrossAxisAlignment.start,
60
- children: [
61
- Text(
62
- widget.title,
63
- style: context.textTheme.bodyLarge?.copyWith(
64
- fontWeight: FontWeight.bold,
65
- ),
66
- ),
67
- const SizedBox(height: KasySpacing.xs),
68
- Text(
69
- widget.description,
70
- style: context.textTheme.bodyMedium?.copyWith(
71
- fontWeight: FontWeight.w400,
72
- color: context.colors.muted,
73
- ),
74
- ),
75
- ],
76
- ),
77
- ),
78
- const SizedBox(width: KasySpacing.md),
79
- switch (widget.voted) {
80
- false => VoteCard.blank(
81
- context: context,
82
- id: widget.title,
83
- votes: widget.votes,
84
- onVote: widget.onVote,
85
- disabled: widget.disabled,
86
- ),
87
- true => VoteCard.voted(
88
- context: context,
89
- id: widget.title,
90
- votes: widget.votes,
91
- onVote: widget.onVote,
92
- disabled: widget.disabled,
93
- ),
94
- }
95
- ],
96
- ),
97
- );
98
- }
99
- }
100
-
101
- class VoteCard extends StatefulWidget {
102
- final int votes;
103
- final VoidCallback onVote;
104
- final Color borderColor;
105
- final Color bgColor;
106
- final Color textColor;
107
- final bool isBold;
108
- final bool disabled;
109
- final String id;
110
-
111
- const VoteCard({
112
- super.key,
113
- required this.votes,
114
- required this.onVote,
115
- required this.bgColor,
116
- required this.textColor,
117
- required this.isBold,
118
- required this.borderColor,
119
- required this.disabled,
120
- required this.id,
121
- });
122
-
123
- factory VoteCard.blank({
124
- required BuildContext context,
125
- required VoidCallback onVote,
126
- required int votes,
127
- required bool disabled,
128
- required String id,
129
- }) =>
130
- VoteCard(
131
- id: id,
132
- onVote: onVote,
133
- votes: votes,
134
- bgColor: context.colors.primary,
135
- textColor: context.colors.onPrimary,
136
- borderColor: context.colors.primary,
137
- isBold: false,
138
- disabled: disabled,
139
- );
140
-
141
- factory VoteCard.voted({
142
- required BuildContext context,
143
- required VoidCallback onVote,
144
- required int votes,
145
- required bool disabled,
146
- required String id,
147
- }) =>
148
- VoteCard(
149
- id: id,
150
- onVote: onVote,
151
- votes: votes,
152
- bgColor: context.colors.primary.withValues(alpha: .1),
153
- textColor: context.colors.onBackground,
154
- borderColor: context.colors.outline,
155
- isBold: true,
156
- disabled: disabled,
157
- );
158
-
159
- @override
160
- State<VoteCard> createState() => _VoteCardState();
161
- }
162
-
163
- class _VoteCardState extends State<VoteCard>
164
- with SingleTickerProviderStateMixin {
165
- // ignore: use_late_for_private_fields_and_variables
166
- AnimationController? _controller;
167
- // ignore: use_late_for_private_fields_and_variables
168
- Animation<double>? _animation;
169
-
170
- final debouncer = Debouncer(delay: const Duration(milliseconds: 250));
171
- bool _goingUp = true;
172
-
173
- @override
174
- void initState() {
175
- super.initState();
176
- _controller = AnimationController(
177
- duration: const Duration(milliseconds: 250),
178
- vsync: this,
179
- );
180
- _animation = Tween<double>(begin: 1, end: 1.2).animate(
181
- CurvedAnimation(parent: _controller!, curve: Curves.easeInOut),
182
- );
183
- }
184
-
185
- @override
186
- void didUpdateWidget(VoteCard oldWidget) {
187
- super.didUpdateWidget(oldWidget);
188
- if (widget.votes != oldWidget.votes) {
189
- _goingUp = widget.votes > oldWidget.votes;
190
- }
191
- }
192
-
193
- @override
194
- void dispose() {
195
- _controller?.dispose();
196
- super.dispose();
197
- }
198
-
199
- @override
200
- Widget build(BuildContext context) {
201
- return AnimatedBuilder(
202
- animation: _animation!,
203
- builder: (context, child) {
204
- return Transform.scale(scale: _animation!.value, child: child);
205
- },
206
- child: Material(
207
- color: Colors.transparent,
208
- child: InkWell(
209
- onTap: () {
210
- if (widget.disabled) return;
211
- HapticFeedback.selectionClick();
212
- SystemSound.play(SystemSoundType.click);
213
- widget.onVote();
214
- _controller!.forward().then((_) => _controller!.reverse());
215
- },
216
- child: Ink(
217
- width: 48,
218
- height: 64,
219
- decoration: BoxDecoration(
220
- color: widget.bgColor,
221
- borderRadius: KasyRadius.smBorderRadius,
222
- border: Border.all(color: widget.borderColor),
223
- ),
224
- padding: const EdgeInsets.all(KasySpacing.sm),
225
- child: Column(
226
- mainAxisAlignment: MainAxisAlignment.center,
227
- children: [
228
- Transform.rotate(
229
- angle: pi / 2,
230
- child: Icon(
231
- Icons.arrow_back_ios,
232
- size: 16,
233
- color: widget.textColor,
234
- ),
235
- ),
236
- ClipRect(
237
- child: AnimatedSwitcher(
238
- duration: const Duration(milliseconds: 250),
239
- transitionBuilder: (child, animation) {
240
- final isIncoming = (child.key as ValueKey?)?.value ==
241
- 'votes-${widget.id}-${widget.votes}';
242
- final beginOffset = isIncoming
243
- ? (_goingUp
244
- ? const Offset(0, 1)
245
- : const Offset(0, -1))
246
- : (_goingUp
247
- ? const Offset(0, -1)
248
- : const Offset(0, 1));
249
- return SlideTransition(
250
- position: Tween<Offset>(
251
- begin: beginOffset,
252
- end: Offset.zero,
253
- ).animate(CurvedAnimation(
254
- parent: animation,
255
- curve: Curves.easeOut,
256
- )),
257
- child:
258
- FadeTransition(opacity: animation, child: child),
259
- );
260
- },
261
- child: Text(
262
- key: ValueKey('votes-${widget.id}-${widget.votes}'),
263
- widget.votes.toString(),
264
- style: context.textTheme.bodyLarge?.copyWith(
265
- fontWeight:
266
- widget.isBold ? FontWeight.bold : FontWeight.w400,
267
- color: widget.textColor,
268
- ),
269
- ),
270
- ),
271
- ),
272
- ],
273
- ),
274
- ),
275
- ),
276
- ),
277
- );
278
- }
279
- }
@@ -1,8 +0,0 @@
1
- # App Store Connect API — copy to apple.env and fill in (never commit apple.env)
2
- # Run: kasy ios configure
3
-
4
- APP_STORE_API_KEY=
5
- APP_STORE_ISSUER_ID=
6
-
7
- # Optional: numeric App Store Connect app ID (for reference / future sync)
8
- # APP_STORE_APP_ID=
@@ -1,7 +0,0 @@
1
- # Codemagic API — copy to codemagic.env and fill in (never commit codemagic.env)
2
- # Run: kasy codemagic configure
3
-
4
- CODEMAGIC_API_TOKEN=
5
- CODEMAGIC_APP_ID=
6
- CODEMAGIC_WORKFLOW_ID=ios-workflow
7
- CODEMAGIC_BRANCH=main
@@ -1,50 +0,0 @@
1
- # Publish iOS with Codemagic (no Mac)
2
-
3
- ## Prerequisites
4
-
5
- - [Codemagic](https://codemagic.io) account
6
- - Git repository connected to Codemagic
7
- - Apple Developer account + app in App Store Connect
8
-
9
- ## 1. Add CI to the project (if missing)
10
-
11
- ```bash
12
- kasy add ci
13
- ```
14
-
15
- Creates `codemagic.yaml` at the project root.
16
-
17
- ## 2. Configure in the Codemagic dashboard
18
-
19
- 1. Open [codemagic.io/apps](https://codemagic.io/apps) and add your repository.
20
- 2. **Code signing (iOS):** set up App Store distribution certificate and profile.
21
- 3. **Integrations → App Store Connect:** link your Apple account.
22
- 4. **Environment variables:** add to your variable group (e.g. `appstore_credentials`):
23
- - `BACKEND_URL`, `SENTRY_DSN`, `RC_IOS_API_KEY`, `RC_ANDROID_API_KEY`, `MIXPANEL_TOKEN`
24
- 5. In `codemagic.yaml`, set `APP_ID` (numeric App Store Connect app ID from the app URL).
25
-
26
- ## 3. Configure from the terminal
27
-
28
- ```bash
29
- kasy codemagic configure
30
- ```
31
-
32
- Enter **API token** (Settings → Codemagic API), **App ID**, and **Workflow ID** (default `ios-workflow`).
33
-
34
- ## 4. Trigger a build
35
-
36
- ```bash
37
- kasy codemagic release
38
- ```
39
-
40
- The cloud build runs and may upload to TestFlight per `codemagic.yaml`.
41
-
42
- ## Build status
43
-
44
- ```bash
45
- kasy codemagic status <buildId>
46
- ```
47
-
48
- ## Local Mac
49
-
50
- If you have a Mac: [ios-release.md](./ios-release.md) and `kasy ios release`.
@@ -1,50 +0,0 @@
1
- # Publicar iOS con Codemagic (sin Mac)
2
-
3
- ## Requisitos
4
-
5
- - Cuenta [Codemagic](https://codemagic.io)
6
- - Repositorio Git conectado a Codemagic
7
- - Cuenta Apple Developer + app en App Store Connect
8
-
9
- ## 1. Agregar CI al proyecto (si falta)
10
-
11
- ```bash
12
- kasy add ci
13
- ```
14
-
15
- Crea `codemagic.yaml` en la raíz del proyecto.
16
-
17
- ## 2. Configurar en el panel Codemagic
18
-
19
- 1. Abre [codemagic.io/apps](https://codemagic.io/apps) y agrega el repositorio.
20
- 2. **Code signing (iOS):** certificado y perfil de distribución App Store.
21
- 3. **Integrations → App Store Connect:** vincula la cuenta Apple.
22
- 4. **Environment variables:** en el grupo del app (ej. `appstore_credentials`):
23
- - `BACKEND_URL`, `SENTRY_DSN`, `RC_IOS_API_KEY`, `RC_ANDROID_API_KEY`, `MIXPANEL_TOKEN`
24
- 5. En `codemagic.yaml`, completa `APP_ID` (ID numérico del app en App Store Connect).
25
-
26
- ## 3. Configurar en la terminal
27
-
28
- ```bash
29
- kasy codemagic configure
30
- ```
31
-
32
- Indica **API token** (Settings → Codemagic API), **App ID** y **Workflow ID** (`ios-workflow` por defecto).
33
-
34
- ## 4. Disparar build
35
-
36
- ```bash
37
- kasy codemagic release
38
- ```
39
-
40
- El build en la nube puede subir a TestFlight según `codemagic.yaml`.
41
-
42
- ## Estado del build
43
-
44
- ```bash
45
- kasy codemagic status <buildId>
46
- ```
47
-
48
- ## Mac local
49
-
50
- Si tienes Mac: [ios-release.md](./ios-release.md) y `kasy ios release`.
@@ -1,50 +0,0 @@
1
- # Publicar iOS com Codemagic (sem Mac)
2
-
3
- ## Pré-requisitos
4
-
5
- - Conta [Codemagic](https://codemagic.io)
6
- - Repositório Git conectado ao Codemagic
7
- - Conta Apple Developer + app no App Store Connect
8
-
9
- ## 1. Adicionar CI ao projeto (se ainda não tiver)
10
-
11
- ```bash
12
- kasy add ci
13
- ```
14
-
15
- Isso cria `codemagic.yaml` na raiz do projeto.
16
-
17
- ## 2. Configurar no painel Codemagic
18
-
19
- 1. Abra [codemagic.io/apps](https://codemagic.io/apps) e adicione o repositório.
20
- 2. **Code signing (iOS):** configure certificado e perfil de distribuição App Store.
21
- 3. **Integrations → App Store Connect:** conecte a conta Apple (recomendado).
22
- 4. **Environment variables:** adicione no grupo do app (ex.: `appstore_credentials`):
23
- - `BACKEND_URL`, `SENTRY_DSN`, `RC_IOS_API_KEY`, `RC_ANDROID_API_KEY`, `MIXPANEL_TOKEN`
24
- 5. No `codemagic.yaml`, preencha `APP_ID` (ID numérico do app no App Store Connect — aparece na URL do app).
25
-
26
- ## 3. Configurar no terminal
27
-
28
- ```bash
29
- kasy codemagic configure
30
- ```
31
-
32
- Informe o **API token** (Settings → Codemagic API), **App ID** e **Workflow ID** (`ios-workflow` por padrão).
33
-
34
- ## 4. Disparar build
35
-
36
- ```bash
37
- kasy codemagic release
38
- ```
39
-
40
- O build roda na nuvem e, conforme o `codemagic.yaml`, pode enviar para TestFlight automaticamente.
41
-
42
- ## Status do build
43
-
44
- ```bash
45
- kasy codemagic status <buildId>
46
- ```
47
-
48
- ## Mac local
49
-
50
- Se tiver Mac: [ios-release.md](./ios-release.md) e `kasy ios release`.