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,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
|
-
}
|
package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart
DELETED
|
@@ -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,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`.
|