kasy-cli 1.34.0 → 1.35.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/README.md +1 -1
- package/bin/kasy.js +24 -2
- package/docs/cli-reference.md +7 -7
- package/lib/commands/new.js +11 -9
- package/lib/commands/release-version.js +234 -0
- package/lib/commands/update.js +27 -0
- package/lib/scaffold/CHANGELOG.json +9 -0
- package/lib/scaffold/backends/api/patch/lib/features/authentication/api/authentication_api.dart +24 -0
- package/lib/scaffold/backends/api/patch/lib/features/authentication/api/authentication_api_interface.dart +15 -0
- package/lib/scaffold/backends/api/patch/lib/features/authentication/repositories/authentication_repository.dart +27 -0
- package/lib/scaffold/backends/api/patch/lib/features/subscriptions/api/entities/subscription_entity.dart +1 -0
- package/lib/scaffold/backends/firebase/setup-from-scratch.js +35 -21
- package/lib/scaffold/backends/patch-base-hashes.json +66 -0
- package/lib/scaffold/backends/supabase/edge-functions/stripe-webhook/index.ts +2 -0
- package/lib/scaffold/backends/supabase/migrations/20240101000007_welcome_notification.sql +36 -23
- package/lib/scaffold/backends/supabase/migrations/20240101000014_subscription_trial_end.sql +6 -0
- package/lib/scaffold/backends/supabase/patch/lib/features/authentication/api/authentication_api.dart +82 -3
- package/lib/scaffold/backends/supabase/patch/lib/features/authentication/repositories/authentication_repository.dart +36 -0
- package/lib/scaffold/backends/supabase/patch/lib/features/subscriptions/api/entities/subscription_entity.dart +1 -0
- package/lib/scaffold/generate.js +53 -4
- package/lib/utils/i18n/messages-en.js +23 -0
- package/lib/utils/i18n/messages-es.js +23 -0
- package/lib/utils/i18n/messages-pt.js +23 -0
- package/package.json +5 -2
- package/templates/firebase/.firebase/hosting.YnVpbGQvd2Vi.cache +73 -0
- package/templates/firebase/AGENTS.md +83 -0
- package/templates/firebase/DESIGN_SYSTEM.md +37 -2
- package/templates/firebase/docs/auth-setup.en.md +2 -0
- package/templates/firebase/docs/auth-setup.es.md +2 -0
- package/templates/firebase/docs/auth-setup.pt.md +2 -0
- package/templates/firebase/firebase.json +56 -1
- package/templates/firebase/functions/src/authentication/triggers.ts +10 -6
- package/templates/firebase/functions/src/core/data/entities/subscription_entity.ts +5 -0
- package/templates/firebase/functions/src/core/data/entities/user_entity.ts +9 -1
- package/templates/firebase/functions/src/core/data/repositories/user_repository.ts +27 -0
- package/templates/firebase/functions/src/subscriptions/models/subscriptions.ts +3 -0
- package/templates/firebase/functions/src/subscriptions/stripe_functions.ts +4 -0
- package/templates/firebase/lib/components/kasy_alert.dart +0 -1
- package/templates/firebase/lib/components/kasy_app_bar.dart +31 -16
- package/templates/firebase/lib/components/kasy_bottom_sheet.dart +0 -1
- package/templates/firebase/lib/components/kasy_date_picker.dart +0 -5
- package/templates/firebase/lib/components/kasy_dialog.dart +0 -1
- package/templates/firebase/lib/components/kasy_otp_verification_bottom_sheet.dart +1 -1
- package/templates/firebase/lib/components/kasy_sidebar.dart +189 -120
- package/templates/firebase/lib/components/kasy_text_area.dart +0 -1
- package/templates/firebase/lib/components/kasy_text_field.dart +0 -1
- package/templates/firebase/lib/components/kasy_text_field_otp.dart +0 -1
- package/templates/firebase/lib/components/kasy_toast.dart +107 -41
- package/templates/firebase/lib/core/app_update/app_update_repository.dart +54 -0
- package/templates/firebase/lib/core/app_update/app_update_status.dart +14 -0
- package/templates/firebase/lib/core/app_update/update_available_sheet.dart +70 -0
- package/templates/firebase/lib/core/bottom_menu/active_tab_notifier.dart +40 -3
- package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +82 -34
- package/templates/firebase/lib/core/bottom_menu/web_content_wrapper.dart +6 -6
- package/templates/firebase/lib/core/bottom_menu/web_url.dart +20 -0
- package/templates/firebase/lib/core/data/api/remote_config_api.dart +38 -1
- package/templates/firebase/lib/core/guards/guard.dart +16 -2
- package/templates/firebase/lib/core/icons/kasy_icons.dart +3 -0
- package/templates/firebase/lib/core/rating/widgets/rate_banner.dart +2 -5
- package/templates/firebase/lib/core/rating/widgets/review_popup.dart +5 -3
- package/templates/firebase/lib/core/shared_preferences/shared_preferences.dart +14 -0
- package/templates/firebase/lib/core/states/components/maybe_show_update_available.dart +32 -0
- package/templates/firebase/lib/core/states/logout_action.dart +5 -1
- package/templates/firebase/lib/core/states/user_state_notifier.dart +85 -14
- package/templates/firebase/lib/core/theme/responsive_text_theme.dart +69 -0
- package/templates/firebase/lib/core/theme/texts.dart +90 -57
- package/templates/firebase/lib/core/theme/type_scale.dart +77 -0
- package/templates/firebase/lib/core/theme/web_background_sync_web.dart +20 -6
- package/templates/firebase/lib/core/utils/image_bytes_loader.dart +12 -0
- package/templates/firebase/lib/core/utils/image_bytes_loader_io.dart +28 -0
- package/templates/firebase/lib/core/utils/image_bytes_loader_web.dart +56 -0
- package/templates/firebase/lib/core/web_screen_width.dart +15 -0
- package/templates/firebase/lib/core/web_screen_width_io.dart +3 -0
- package/templates/firebase/lib/core/web_screen_width_web.dart +10 -0
- package/templates/firebase/lib/core/web_viewport_scale.dart +61 -25
- package/templates/firebase/lib/core/widgets/focus_visibility.dart +89 -0
- package/templates/firebase/lib/features/ai_chat/ai_chat_page.dart +1 -2
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_chat_conversation_view.dart +1 -2
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_list.dart +2 -3
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_tile.dart +1 -2
- package/templates/firebase/lib/features/authentication/api/auth_web_support.dart +12 -0
- package/templates/firebase/lib/features/authentication/api/auth_web_support_web.dart +25 -0
- package/templates/firebase/lib/features/authentication/api/authentication_api.dart +205 -0
- package/templates/firebase/lib/features/authentication/api/authentication_api_interface.dart +22 -0
- package/templates/firebase/lib/features/authentication/navigation/post_login_navigation.dart +32 -0
- package/templates/firebase/lib/features/authentication/providers/phone_auth_notifier.dart +7 -7
- package/templates/firebase/lib/features/authentication/providers/signin_state_provider.dart +34 -10
- package/templates/firebase/lib/features/authentication/providers/signup_state_provider.dart +2 -2
- package/templates/firebase/lib/features/authentication/repositories/authentication_repository.dart +37 -0
- package/templates/firebase/lib/features/authentication/repositories/exceptions/authentication_exceptions.dart +8 -0
- package/templates/firebase/lib/features/authentication/ui/components/otp_verification.dart +2 -2
- package/templates/firebase/lib/features/authentication/ui/components/phone_input.dart +2 -2
- package/templates/firebase/lib/features/authentication/ui/signin_page.dart +59 -0
- package/templates/firebase/lib/features/authentication/ui/widgets/auth_card_scaffold.dart +2 -2
- package/templates/firebase/lib/features/authentication/ui/widgets/recover_password_result.dart +2 -2
- package/templates/firebase/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -1
- package/templates/firebase/lib/features/home/design_system_page.dart +134 -67
- package/templates/firebase/lib/features/home/home_components_page.dart +4 -3
- package/templates/firebase/lib/features/home/home_components_preview_page.dart +1 -3
- package/templates/firebase/lib/features/home/home_components_preview_registry.dart +154 -56
- package/templates/firebase/lib/features/home/home_page.dart +4 -0
- package/templates/firebase/lib/features/local_reminders/ui/reminder_page.dart +8 -3
- package/templates/firebase/lib/features/notifications/providers/notifications_provider.dart +10 -0
- package/templates/firebase/lib/features/notifications/ui/notifications_page.dart +3 -1
- package/templates/firebase/lib/features/notifications/ui/widgets/notification_tile.dart +8 -3
- package/templates/firebase/lib/features/onboarding/providers/onboarding_model.dart +11 -0
- package/templates/firebase/lib/features/onboarding/providers/onboarding_provider.dart +30 -3
- package/templates/firebase/lib/features/onboarding/ui/components/onboarding_loader.dart +13 -4
- package/templates/firebase/lib/features/settings/settings_page.dart +152 -11
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_page.dart +43 -15
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_tab.dart +12 -12
- package/templates/firebase/lib/features/settings/ui/components/admin/send_push_notification_page.dart +1 -4
- package/templates/firebase/lib/features/settings/ui/components/create_password_sheet.dart +141 -0
- package/templates/firebase/lib/features/settings/ui/components/language_switcher.dart +0 -1
- package/templates/firebase/lib/features/settings/ui/widgets/admin_card.dart +42 -38
- package/templates/firebase/lib/features/settings/ui/widgets/settings_tile.dart +17 -2
- package/templates/firebase/lib/features/subscriptions/api/entities/subscription_entity.dart +3 -0
- package/templates/firebase/lib/features/subscriptions/api/stripe_product.dart +12 -11
- package/templates/firebase/lib/features/subscriptions/repositories/subscription_repository.dart +25 -2
- package/templates/firebase/lib/features/subscriptions/ui/component/active_premium_content.dart +319 -143
- package/templates/firebase/lib/features/subscriptions/ui/component/paywall_minimal.dart +1 -5
- package/templates/firebase/lib/features/subscriptions/ui/component/paywall_row.dart +1 -5
- package/templates/firebase/lib/features/subscriptions/ui/component/paywall_with_switch.dart +2 -5
- package/templates/firebase/lib/features/subscriptions/ui/component/premium_content.dart +1 -4
- package/templates/firebase/lib/features/subscriptions/ui/widgets/feature_line.dart +1 -2
- package/templates/firebase/lib/features/subscriptions/ui/widgets/premium_banner.dart +2 -7
- package/templates/firebase/lib/features/subscriptions/ui/widgets/premium_feature.dart +2 -4
- package/templates/firebase/lib/features/subscriptions/ui/widgets/selectable_col.dart +1 -4
- package/templates/firebase/lib/features/subscriptions/ui/widgets/selectable_row.dart +0 -3
- package/templates/firebase/lib/i18n/en.i18n.json +49 -3
- package/templates/firebase/lib/i18n/es.i18n.json +49 -3
- package/templates/firebase/lib/i18n/pt.i18n.json +49 -3
- package/templates/firebase/lib/main.dart +11 -2
- package/templates/firebase/lib/router.dart +92 -13
- package/templates/firebase/pubspec.yaml +1 -1
- package/templates/firebase/test/core/data/api/fake_remote_config_api.dart +14 -0
- package/templates/firebase/test/core/states/user_state_notifier_test.dart +47 -3
- package/templates/firebase/test/core/web_viewport_scale_test.dart +68 -0
- package/templates/firebase/test/features/authentication/data/api/auth_api_fake.dart +15 -0
- package/templates/firebase/web/index.html +162 -14
- package/templates/firebase/lib/core/guards/user_info_guard.dart +0 -61
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
|
+
import 'package:kasy_kit/components/kasy_card.dart';
|
|
2
3
|
import 'package:kasy_kit/core/haptics/kasy_haptics.dart';
|
|
3
4
|
import 'package:kasy_kit/core/theme/theme.dart';
|
|
4
|
-
import 'package:kasy_kit/core/widgets/kasy_focus_ring.dart';
|
|
5
5
|
|
|
6
|
-
///
|
|
6
|
+
/// A tappable admin panel card. Uses the design-system [KasyCard] (elevated
|
|
7
|
+
/// surface, hairline border, soft shadow) with a compact title / description
|
|
8
|
+
/// and a trailing chevron, so admin tools read like the rest of the app
|
|
9
|
+
/// instead of a flat tinted block.
|
|
7
10
|
class AdminPanelCard extends StatelessWidget {
|
|
8
11
|
final VoidCallback onTap;
|
|
9
12
|
final String title;
|
|
@@ -22,45 +25,46 @@ class AdminPanelCard extends StatelessWidget {
|
|
|
22
25
|
|
|
23
26
|
@override
|
|
24
27
|
Widget build(BuildContext context) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Text(
|
|
47
|
-
title,
|
|
48
|
-
style: context.textTheme.headlineSmall?.copyWith(
|
|
49
|
-
color: textColor ?? context.colors.onSurface,
|
|
28
|
+
return KasyCard(
|
|
29
|
+
onTap: () {
|
|
30
|
+
KasyHaptics.medium(context);
|
|
31
|
+
onTap();
|
|
32
|
+
},
|
|
33
|
+
color: backgroundColor,
|
|
34
|
+
borderRadius: KasyRadius.lgBorderRadius,
|
|
35
|
+
padding: const EdgeInsets.all(KasySpacing.md),
|
|
36
|
+
semanticLabel: title,
|
|
37
|
+
child: Row(
|
|
38
|
+
children: [
|
|
39
|
+
Expanded(
|
|
40
|
+
child: Column(
|
|
41
|
+
crossAxisAlignment: CrossAxisAlignment.start,
|
|
42
|
+
mainAxisSize: MainAxisSize.min,
|
|
43
|
+
children: [
|
|
44
|
+
Text(
|
|
45
|
+
title,
|
|
46
|
+
style: context.kasyTextTheme.cardTitle.copyWith(
|
|
47
|
+
color: textColor ?? context.colors.onSurface,
|
|
48
|
+
),
|
|
50
49
|
),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
const SizedBox(height: 2),
|
|
51
|
+
Text(
|
|
52
|
+
description,
|
|
53
|
+
style: context.textTheme.bodySmall?.copyWith(
|
|
54
|
+
color: textColor ?? context.colors.muted,
|
|
55
|
+
height: 1.35,
|
|
56
|
+
),
|
|
58
57
|
),
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
],
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
const SizedBox(width: KasySpacing.sm),
|
|
62
|
+
Icon(
|
|
63
|
+
KasyIcons.arrowForwardIos,
|
|
64
|
+
size: KasyIconSize.xs,
|
|
65
|
+
color: context.colors.muted,
|
|
61
66
|
),
|
|
62
|
-
|
|
63
|
-
),
|
|
67
|
+
],
|
|
64
68
|
),
|
|
65
69
|
);
|
|
66
70
|
}
|
|
@@ -140,12 +140,16 @@ class SettingsSwitchTile extends StatelessWidget {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
/// This widget is used to show a settings tile with an icon and a title
|
|
143
|
+
/// This widget is used to show a settings tile with an icon and a title.
|
|
144
|
+
/// Optionally shows a [trailingLabel] value before the chevron — mirrors the
|
|
145
|
+
/// pattern of [LanguageSwitcher] where the current value appears on the right.
|
|
144
146
|
class SettingsTile extends StatelessWidget {
|
|
145
147
|
final IconData icon;
|
|
146
148
|
final String title;
|
|
147
149
|
final SettingsTileOnTap onTap;
|
|
148
150
|
final Color? iconBackgroundColor;
|
|
151
|
+
final String? trailingLabel;
|
|
152
|
+
final Widget? trailingWidget;
|
|
149
153
|
|
|
150
154
|
const SettingsTile({
|
|
151
155
|
super.key,
|
|
@@ -153,6 +157,8 @@ class SettingsTile extends StatelessWidget {
|
|
|
153
157
|
required this.title,
|
|
154
158
|
required this.onTap,
|
|
155
159
|
this.iconBackgroundColor,
|
|
160
|
+
this.trailingLabel,
|
|
161
|
+
this.trailingWidget,
|
|
156
162
|
});
|
|
157
163
|
|
|
158
164
|
@override
|
|
@@ -184,7 +190,16 @@ class SettingsTile extends StatelessWidget {
|
|
|
184
190
|
),
|
|
185
191
|
),
|
|
186
192
|
),
|
|
187
|
-
|
|
193
|
+
if (trailingLabel != null) ...[
|
|
194
|
+
Text(
|
|
195
|
+
trailingLabel!,
|
|
196
|
+
style: context.textTheme.bodyMedium?.copyWith(
|
|
197
|
+
color: context.colors.muted,
|
|
198
|
+
),
|
|
199
|
+
),
|
|
200
|
+
const SizedBox(width: KasySpacing.xs),
|
|
201
|
+
],
|
|
202
|
+
trailingWidget ?? const SettingsListChevron(),
|
|
188
203
|
],
|
|
189
204
|
),
|
|
190
205
|
);
|
|
@@ -44,6 +44,9 @@ sealed class SubscriptionEntity with _$SubscriptionEntity {
|
|
|
44
44
|
@JsonKey(name: 'expiration_date')
|
|
45
45
|
@TimestampConverter()
|
|
46
46
|
DateTime? periodEndDate,
|
|
47
|
+
@JsonKey(name: 'trial_end')
|
|
48
|
+
@TimestampConverter()
|
|
49
|
+
DateTime? trialEnd,
|
|
47
50
|
@JsonKey(name: 'status') required SubscriptionStatus status,
|
|
48
51
|
// Origin of the subscription (apple/play/stripe/...). Nullable + tolerant
|
|
49
52
|
// parsing so old records (no `store`) and future values never break.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import 'package:flutter/material.dart';
|
|
2
|
+
import 'package:intl/intl.dart';
|
|
2
3
|
import 'package:kasy_kit/core/data/models/subscription.dart';
|
|
3
4
|
import 'package:kasy_kit/i18n/translations.g.dart';
|
|
4
5
|
|
|
@@ -121,15 +122,13 @@ class StripeProduct implements SubscriptionProduct {
|
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
String _formatMoney(double value)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (currency == 'EUR') return "$amount€";
|
|
128
|
-
return "$amount $currency";
|
|
129
|
-
}
|
|
125
|
+
String _formatMoney(double value, {String? locale}) =>
|
|
126
|
+
NumberFormat.simpleCurrency(locale: locale, name: _currency.toUpperCase())
|
|
127
|
+
.format(value);
|
|
130
128
|
|
|
131
129
|
@override
|
|
132
130
|
String formattedPrice(BuildContext context) {
|
|
131
|
+
final locale = Localizations.localeOf(context).toString();
|
|
133
132
|
final translatedDuration = switch (durationType) {
|
|
134
133
|
DurationType.week => Translations.of(context).premium.duration_weekly,
|
|
135
134
|
DurationType.year => Translations.of(context).premium.duration_annual,
|
|
@@ -139,16 +138,17 @@ class StripeProduct implements SubscriptionProduct {
|
|
|
139
138
|
).premium.duration_lifetime,
|
|
140
139
|
_ => "",
|
|
141
140
|
};
|
|
142
|
-
return "$
|
|
141
|
+
return "${_formatMoney(price, locale: locale)} $translatedDuration";
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
@override
|
|
146
145
|
String pricePerMonth(BuildContext context) {
|
|
146
|
+
final locale = Localizations.localeOf(context).toString();
|
|
147
147
|
final translatedDuration = Translations.of(
|
|
148
148
|
context,
|
|
149
149
|
).premium.duration_monthly;
|
|
150
150
|
if (durationType == DurationType.lifetime) {
|
|
151
|
-
return
|
|
151
|
+
return _formatMoney(price, locale: locale);
|
|
152
152
|
}
|
|
153
153
|
final monthly = switch (durationType) {
|
|
154
154
|
DurationType.year => price / 12,
|
|
@@ -157,14 +157,15 @@ class StripeProduct implements SubscriptionProduct {
|
|
|
157
157
|
DurationType.week => (price * 4) / 12,
|
|
158
158
|
_ => price,
|
|
159
159
|
};
|
|
160
|
-
return "${_formatMoney(monthly)}/$translatedDuration";
|
|
160
|
+
return "${_formatMoney(monthly, locale: locale)}/$translatedDuration";
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
@override
|
|
164
164
|
String? pricePerYear(BuildContext context) {
|
|
165
|
+
final locale = Localizations.localeOf(context).toString();
|
|
165
166
|
final translatedDuration = Translations.of(context).premium.duration_annual;
|
|
166
167
|
if (durationType == DurationType.lifetime) {
|
|
167
|
-
return
|
|
168
|
+
return _formatMoney(price, locale: locale);
|
|
168
169
|
}
|
|
169
170
|
final yearly = switch (durationType) {
|
|
170
171
|
DurationType.year => price,
|
|
@@ -173,6 +174,6 @@ class StripeProduct implements SubscriptionProduct {
|
|
|
173
174
|
DurationType.week => (price * 4) * 12,
|
|
174
175
|
_ => price * 12,
|
|
175
176
|
};
|
|
176
|
-
return "${_formatMoney(yearly)}/$translatedDuration";
|
|
177
|
+
return "${_formatMoney(yearly, locale: locale)}/$translatedDuration";
|
|
177
178
|
}
|
|
178
179
|
}
|
package/templates/firebase/lib/features/subscriptions/repositories/subscription_repository.dart
CHANGED
|
@@ -86,11 +86,19 @@ class SubscriptionRepository implements OnStartService {
|
|
|
86
86
|
final product = await _inAppSubscriptionApi.getFromProductId(
|
|
87
87
|
entity!.skuId,
|
|
88
88
|
);
|
|
89
|
-
|
|
89
|
+
|
|
90
|
+
// When the payment provider has no entitlement data (e.g. Stripe returns
|
|
91
|
+
// an empty list), synthesize one from the backend entity so the UI can
|
|
92
|
+
// show trial status, expiration date and renewal info.
|
|
93
|
+
final effectiveEntitlements =
|
|
94
|
+
(entitlements == null || entitlements.isEmpty)
|
|
95
|
+
? _entitlementsFromEntity(entity)
|
|
96
|
+
: entitlements;
|
|
97
|
+
|
|
90
98
|
return switch(subscription) {
|
|
91
99
|
final SubscriptionStateData active => active.copyWith(
|
|
92
100
|
activeOffer: product,
|
|
93
|
-
entitlements:
|
|
101
|
+
entitlements: effectiveEntitlements,
|
|
94
102
|
),
|
|
95
103
|
_ => subscription,
|
|
96
104
|
};
|
|
@@ -109,6 +117,21 @@ class SubscriptionRepository implements OnStartService {
|
|
|
109
117
|
return subscription;
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
List<Entitlement> _entitlementsFromEntity(SubscriptionEntity entity) {
|
|
121
|
+
final now = DateTime.now();
|
|
122
|
+
final trialEnd = entity.trialEnd;
|
|
123
|
+
final isInTrial = trialEnd != null && trialEnd.isAfter(now);
|
|
124
|
+
final willRenew = entity.status != SubscriptionStatus.CANCELLED;
|
|
125
|
+
return [
|
|
126
|
+
Entitlement(
|
|
127
|
+
identifier: entity.skuId,
|
|
128
|
+
isInTrial: isInTrial,
|
|
129
|
+
willRenew: willRenew,
|
|
130
|
+
expirationDate: isInTrial ? trialEnd : entity.periodEndDate,
|
|
131
|
+
),
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
|
|
112
135
|
// We can have multiple offers (BASIC MONTH, BASIC YEAR, GOLD MONTH, GOLD YEAR, ...)
|
|
113
136
|
Future<List<SubscriptionProduct>> getOffers({String? offerId}) {
|
|
114
137
|
return _inAppSubscriptionApi.getOffers(offerId);
|