feat: trial using choreo (#2435)
* RC trial * generated * fixed mobile * reverted to resetSubscription * generated * fix for unloaded state * generated * chore: clean up some unused variables --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com> Co-authored-by: ggurdin <ggurdin@gmail.com>
This commit is contained in:
parent
63ade4c995
commit
c0680b5294
14 changed files with 158 additions and 132 deletions
|
|
@ -190,7 +190,6 @@ abstract class AppConfig {
|
|||
static String assetsBaseURL =
|
||||
"https://pangea-chat-client-assets.s3.us-east-1.amazonaws.com";
|
||||
|
||||
static String trialSubscriptionId = "pangea_new_user_trial";
|
||||
static String errorSubscriptionId = "pangea_subscription_error";
|
||||
// Pangea#
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ class Choreographer {
|
|||
ChoreoMode choreoMode = ChoreoMode.igc;
|
||||
|
||||
final StreamController stateStream = StreamController.broadcast();
|
||||
StreamSubscription? _trialStream;
|
||||
StreamSubscription? _languageStream;
|
||||
late AssistanceState _currentAssistanceState;
|
||||
|
||||
|
|
@ -72,9 +71,6 @@ class Choreographer {
|
|||
igc = IgcController(this);
|
||||
errorService = ErrorService(this);
|
||||
_textController.addListener(_onChangeListener);
|
||||
_trialStream = pangeaController
|
||||
.subscriptionController.trialActivationStream.stream
|
||||
.listen((_) => _onChangeListener);
|
||||
_languageStream =
|
||||
pangeaController.userController.stateStream.listen((update) {
|
||||
if (update is Map<String, dynamic> &&
|
||||
|
|
@ -568,7 +564,6 @@ class Choreographer {
|
|||
|
||||
dispose() {
|
||||
_textController.dispose();
|
||||
_trialStream?.cancel();
|
||||
_languageStream?.cancel();
|
||||
stateStream.close();
|
||||
tts.dispose();
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@ class ModelKey {
|
|||
static const String instructionsSettings = 'instructions_settings';
|
||||
static const String cefrLevel = 'user_cefr';
|
||||
|
||||
// matrix profile keys
|
||||
// making this a random string so that it's harder to guess
|
||||
static const String activatedTrialKey = '7C4EuKIsph';
|
||||
static const String autoPlayMessages = 'autoPlayMessages';
|
||||
static const String itAutoPlay = 'autoPlayIT';
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ class PApiUrls {
|
|||
static String rcAppsChoreo = "${PApiUrls.subscriptionEndpoint}/app_ids";
|
||||
static String rcProductsChoreo =
|
||||
"${PApiUrls.subscriptionEndpoint}/all_products";
|
||||
static String rcProductsTrial = "${PApiUrls.subscriptionEndpoint}/free_trial";
|
||||
|
||||
static String rcSubscription = PApiUrls.subscriptionEndpoint;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
|
|||
import 'package:fluffychat/pangea/subscription/models/base_subscription_info.dart';
|
||||
import 'package:fluffychat/pangea/subscription/models/mobile_subscriptions.dart';
|
||||
import 'package:fluffychat/pangea/subscription/models/web_subscriptions.dart';
|
||||
import 'package:fluffychat/pangea/subscription/repo/subscription_repo.dart';
|
||||
import 'package:fluffychat/pangea/subscription/utils/subscription_app_id.dart';
|
||||
import 'package:fluffychat/pangea/subscription/widgets/subscription_paywall.dart';
|
||||
import 'package:fluffychat/pangea/user/controllers/user_controller.dart';
|
||||
|
|
@ -42,7 +43,6 @@ class SubscriptionController extends BaseController {
|
|||
AvailableSubscriptionsInfo? availableSubscriptionInfo;
|
||||
|
||||
final StreamController subscriptionStream = StreamController.broadcast();
|
||||
final StreamController trialActivationStream = StreamController.broadcast();
|
||||
|
||||
SubscriptionController(PangeaController pangeaController) : super() {
|
||||
_pangeaController = pangeaController;
|
||||
|
|
@ -57,11 +57,6 @@ class SubscriptionController extends BaseController {
|
|||
final bool hasSubscription =
|
||||
currentSubscriptionInfo?.currentSubscriptionId != null;
|
||||
|
||||
if (_activatedNewUserTrial && !hasSubscription) {
|
||||
_setNewUserTrial();
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasSubscription;
|
||||
}
|
||||
|
||||
|
|
@ -101,20 +96,27 @@ class SubscriptionController extends BaseController {
|
|||
availableSubscriptionInfo = AvailableSubscriptionsInfo();
|
||||
await availableSubscriptionInfo!.setAvailableSubscriptions();
|
||||
|
||||
final subs =
|
||||
await SubscriptionRepo.getCurrentSubscriptionInfo(null, null);
|
||||
|
||||
currentSubscriptionInfo = kIsWeb
|
||||
? WebSubscriptionInfo(
|
||||
userID: _userID!,
|
||||
availableSubscriptionInfo: availableSubscriptionInfo!,
|
||||
history: subs.allSubscriptions,
|
||||
)
|
||||
: MobileSubscriptionInfo(
|
||||
userID: _userID!,
|
||||
availableSubscriptionInfo: availableSubscriptionInfo!,
|
||||
history: subs.allSubscriptions,
|
||||
);
|
||||
|
||||
await currentSubscriptionInfo!.configure();
|
||||
await currentSubscriptionInfo!.setCurrentSubscription();
|
||||
if (_activatedNewUserTrial) {
|
||||
_setNewUserTrial();
|
||||
|
||||
if (currentSubscriptionInfo!.currentSubscriptionId == null &&
|
||||
_pangeaController.userController.inTrialWindow()) {
|
||||
await activateNewUserTrial();
|
||||
}
|
||||
|
||||
if (!kIsWeb) {
|
||||
|
|
@ -153,6 +155,25 @@ class SubscriptionController extends BaseController {
|
|||
),
|
||||
},
|
||||
);
|
||||
|
||||
if (currentSubscriptionInfo?.currentSubscriptionId == null) {
|
||||
currentSubscriptionInfo ??= kIsWeb
|
||||
? WebSubscriptionInfo(
|
||||
userID: _userID!,
|
||||
availableSubscriptionInfo:
|
||||
availableSubscriptionInfo ?? AvailableSubscriptionsInfo(),
|
||||
history: {},
|
||||
)
|
||||
: MobileSubscriptionInfo(
|
||||
userID: _userID!,
|
||||
availableSubscriptionInfo:
|
||||
availableSubscriptionInfo ?? AvailableSubscriptionsInfo(),
|
||||
history: {},
|
||||
);
|
||||
|
||||
currentSubscriptionInfo!.currentSubscriptionId =
|
||||
AppConfig.errorSubscriptionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +184,12 @@ class SubscriptionController extends BaseController {
|
|||
}) async {
|
||||
if (selectedSubscription != null) {
|
||||
if (selectedSubscription.isTrial) {
|
||||
activateNewUserTrial();
|
||||
try {
|
||||
await activateNewUserTrial();
|
||||
await updateCustomerInfo();
|
||||
} catch (e) {
|
||||
debugPrint("Failed to initialize trial subscription");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -215,47 +241,17 @@ class SubscriptionController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
int get _currentTrialDays =>
|
||||
_userController.inTrialWindow(trialDays: 7) ? 7 : 0;
|
||||
|
||||
bool get _activatedNewUserTrial =>
|
||||
_userController.inTrialWindow(trialDays: 1) ||
|
||||
(_userController.inTrialWindow() &&
|
||||
_userController.profile.userSettings.activatedFreeTrial);
|
||||
|
||||
void activateNewUserTrial() {
|
||||
_userController.updateProfile(
|
||||
(profile) {
|
||||
profile.userSettings.activatedFreeTrial = true;
|
||||
return profile;
|
||||
},
|
||||
);
|
||||
_setNewUserTrial();
|
||||
trialActivationStream.add(true);
|
||||
}
|
||||
|
||||
void _setNewUserTrial() {
|
||||
final DateTime? createdAt = _userController.profile.userSettings.createdAt;
|
||||
if (createdAt == null) {
|
||||
ErrorHandler.logError(
|
||||
m: "Null user profile createdAt in subscription settings",
|
||||
s: StackTrace.current,
|
||||
data: {},
|
||||
);
|
||||
return;
|
||||
Future<void> activateNewUserTrial() async {
|
||||
if (await SubscriptionRepo.activateFreeTrial()) {
|
||||
await updateCustomerInfo();
|
||||
}
|
||||
|
||||
final DateTime expirationDate = createdAt.add(
|
||||
Duration(days: _currentTrialDays),
|
||||
);
|
||||
currentSubscriptionInfo?.setTrial(expirationDate);
|
||||
}
|
||||
|
||||
Future<void> updateCustomerInfo() async {
|
||||
if (!initCompleter.isCompleted) {
|
||||
await initialize();
|
||||
}
|
||||
await currentSubscriptionInfo!.setCurrentSubscription();
|
||||
await currentSubscriptionInfo?.setCurrentSubscription();
|
||||
setState(null);
|
||||
}
|
||||
|
||||
|
|
@ -384,11 +380,6 @@ class SubscriptionController extends BaseController {
|
|||
?.defaultManagementURL(availableSubscriptionInfo?.appIds);
|
||||
}
|
||||
|
||||
enum SubscriptionPeriodType {
|
||||
normal,
|
||||
trial,
|
||||
}
|
||||
|
||||
enum SubscriptionDuration {
|
||||
month,
|
||||
year,
|
||||
|
|
@ -403,7 +394,6 @@ class SubscriptionDetails {
|
|||
final SubscriptionDuration? duration;
|
||||
final String? appId;
|
||||
final String id;
|
||||
SubscriptionPeriodType periodType;
|
||||
Package? package;
|
||||
String? localizedPrice;
|
||||
|
||||
|
|
@ -413,11 +403,9 @@ class SubscriptionDetails {
|
|||
this.duration,
|
||||
this.package,
|
||||
this.appId,
|
||||
this.periodType = SubscriptionPeriodType.normal,
|
||||
});
|
||||
|
||||
void makeTrial() => periodType = SubscriptionPeriodType.trial;
|
||||
bool get isTrial => periodType == SubscriptionPeriodType.trial;
|
||||
bool get isTrial => appId == "trial";
|
||||
|
||||
String displayPrice(BuildContext context) => isTrial || price <= 0
|
||||
? L10n.of(context).freeTrial
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/local.key.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/subscription/controllers/subscription_controller.dart';
|
||||
|
|
@ -12,6 +11,7 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||
class CurrentSubscriptionInfo {
|
||||
final String userID;
|
||||
final AvailableSubscriptionsInfo availableSubscriptionInfo;
|
||||
final Map<String, RCSubscription>? history;
|
||||
|
||||
DateTime? expirationDate;
|
||||
String? currentSubscriptionId;
|
||||
|
|
@ -19,6 +19,7 @@ class CurrentSubscriptionInfo {
|
|||
CurrentSubscriptionInfo({
|
||||
required this.userID,
|
||||
required this.availableSubscriptionInfo,
|
||||
required this.history,
|
||||
});
|
||||
|
||||
SubscriptionDetails? get currentSubscription {
|
||||
|
|
@ -32,15 +33,11 @@ class CurrentSubscriptionInfo {
|
|||
|
||||
Future<void> configure() async {}
|
||||
|
||||
bool get isNewUserTrial =>
|
||||
currentSubscriptionId == AppConfig.trialSubscriptionId;
|
||||
|
||||
bool get currentSubscriptionIsPromotional =>
|
||||
currentSubscriptionId?.startsWith("rc_promo") ?? false;
|
||||
|
||||
bool get isPaidSubscription =>
|
||||
(currentSubscription != null || currentSubscriptionId != null) &&
|
||||
!isNewUserTrial &&
|
||||
!currentSubscriptionIsPromotional;
|
||||
|
||||
bool get isLifetimeSubscription =>
|
||||
|
|
@ -67,23 +64,6 @@ class CurrentSubscriptionInfo {
|
|||
availableSubscriptionInfo.appIds?.currentAppId);
|
||||
|
||||
void resetSubscription() => currentSubscriptionId = null;
|
||||
|
||||
void setTrial(DateTime expiration) {
|
||||
expirationDate = expiration;
|
||||
currentSubscriptionId = AppConfig.trialSubscriptionId;
|
||||
if (currentSubscription == null &&
|
||||
!availableSubscriptionInfo.availableSubscriptions
|
||||
.any((sub) => sub.isTrial)) {
|
||||
availableSubscriptionInfo.availableSubscriptions.add(
|
||||
SubscriptionDetails(
|
||||
price: 0,
|
||||
id: AppConfig.trialSubscriptionId,
|
||||
periodType: SubscriptionPeriodType.trial,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setCurrentSubscription() async {}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +89,10 @@ class AvailableSubscriptionsInfo {
|
|||
if (cachedInfo == null) await _cacheSubscriptionInfo();
|
||||
|
||||
availableSubscriptions = (allProducts ?? [])
|
||||
.where((product) => product.appId == appIds!.currentAppId)
|
||||
.where(
|
||||
(product) =>
|
||||
product.appId == appIds!.currentAppId || product.appId == "trial",
|
||||
)
|
||||
.sorted((a, b) => a.price.compareTo(b.price))
|
||||
.toList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class MobileSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
MobileSubscriptionInfo({
|
||||
required super.userID,
|
||||
required super.availableSubscriptionInfo,
|
||||
required super.history,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -65,7 +66,7 @@ class MobileSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
|
||||
CustomerInfo info;
|
||||
try {
|
||||
// await Purchases.syncPurchases();
|
||||
await Purchases.invalidateCustomerInfoCache();
|
||||
info = await Purchases.getCustomerInfo();
|
||||
} catch (err) {
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -81,9 +82,10 @@ class MobileSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
info.entitlements.all.entries
|
||||
.where(
|
||||
(MapEntry<String, EntitlementInfo> entry) =>
|
||||
entry.value.expirationDate == null ||
|
||||
DateTime.parse(entry.value.expirationDate!)
|
||||
.isAfter(DateTime.now()),
|
||||
entry.value.isActive &&
|
||||
(entry.value.expirationDate == null ||
|
||||
DateTime.parse(entry.value.expirationDate!)
|
||||
.isAfter(DateTime.now())),
|
||||
)
|
||||
.map((MapEntry<String, EntitlementInfo> entry) => entry.value)
|
||||
.toList();
|
||||
|
|
@ -94,9 +96,7 @@ class MobileSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
);
|
||||
} else if (activeEntitlements.isEmpty) {
|
||||
debugPrint("User has no active entitlements");
|
||||
if (!isNewUserTrial) {
|
||||
resetSubscription();
|
||||
}
|
||||
resetSubscription();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ class MobileSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
: null;
|
||||
|
||||
if (activeEntitlement.periodType == PeriodType.trial) {
|
||||
currentSubscription?.makeTrial();
|
||||
// We dont use actual trials as it would require adding a CC on devices
|
||||
}
|
||||
if (currentSubscriptionId != null && currentSubscription == null) {
|
||||
Sentry.addBreadcrumb(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ class WebSubscriptionInfo extends CurrentSubscriptionInfo {
|
|||
WebSubscriptionInfo({
|
||||
required super.userID,
|
||||
required super.availableSubscriptionInfo,
|
||||
required super.history,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ class SubscriptionManagementController extends State<SubscriptionManagement> {
|
|||
subscriptionController.currentSubscriptionInfo?.currentSubscription !=
|
||||
null;
|
||||
|
||||
bool get currentSubscriptionIsTrial =>
|
||||
currentSubscriptionAvailable &&
|
||||
(subscriptionController
|
||||
.currentSubscriptionInfo?.currentSubscription?.isTrial ??
|
||||
false);
|
||||
|
||||
String? get purchasePlatformDisplayName => subscriptionController
|
||||
.currentSubscriptionInfo?.purchasePlatformDisplayName;
|
||||
|
||||
|
|
@ -79,9 +85,6 @@ class SubscriptionManagementController extends State<SubscriptionManagement> {
|
|||
.currentSubscriptionInfo?.currentSubscriptionIsPromotional ??
|
||||
false;
|
||||
|
||||
bool get isNewUserTrial =>
|
||||
subscriptionController.currentSubscriptionInfo?.isNewUserTrial ?? false;
|
||||
|
||||
String get currentSubscriptionTitle =>
|
||||
subscriptionController.currentSubscriptionInfo?.currentSubscription
|
||||
?.displayName(context) ??
|
||||
|
|
@ -93,7 +96,7 @@ class SubscriptionManagementController extends State<SubscriptionManagement> {
|
|||
"";
|
||||
|
||||
bool get showManagementOptions {
|
||||
if (!currentSubscriptionAvailable || isNewUserTrial) {
|
||||
if (!currentSubscriptionAvailable) {
|
||||
return false;
|
||||
}
|
||||
if (subscriptionController.currentSubscriptionInfo!.purchasedOnWeb) {
|
||||
|
|
@ -183,8 +186,7 @@ class SubscriptionManagementController extends State<SubscriptionManagement> {
|
|||
|
||||
bool isCurrentSubscription(SubscriptionDetails subscription) =>
|
||||
subscriptionController.currentSubscriptionInfo?.currentSubscription ==
|
||||
subscription ||
|
||||
isNewUserTrial && subscription.isTrial;
|
||||
subscription;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsSubscriptionView(this);
|
||||
|
|
|
|||
|
|
@ -75,8 +75,7 @@ class SettingsSubscriptionView extends StatelessWidget {
|
|||
ManagementNotAvailableWarning(
|
||||
controller: controller,
|
||||
),
|
||||
if (isSubscribed != null && !isSubscribed ||
|
||||
controller.isNewUserTrial)
|
||||
if (isSubscribed != null && !isSubscribed)
|
||||
ChangeSubscription(controller: controller),
|
||||
if (controller.showManagementOptions) ...managementButtons,
|
||||
],
|
||||
|
|
@ -102,11 +101,12 @@ class ManagementNotAvailableWarning extends StatelessWidget {
|
|||
|
||||
String getWarningText() {
|
||||
final DateFormat formatter = DateFormat('yyyy-MM-dd');
|
||||
if (controller.isNewUserTrial) {
|
||||
if (controller.currentSubscriptionIsTrial) {
|
||||
return L10n.of(context).trialExpiration(
|
||||
formatter.format(currentSubscriptionInfo!.expirationDate!),
|
||||
);
|
||||
}
|
||||
|
||||
if (controller.currentSubscriptionAvailable) {
|
||||
String warningText = L10n.of(context).subsciptionPlatformTooltip;
|
||||
if (controller.purchasePlatformDisplayName != null) {
|
||||
|
|
@ -115,6 +115,7 @@ class ManagementNotAvailableWarning extends StatelessWidget {
|
|||
}
|
||||
return warningText;
|
||||
}
|
||||
|
||||
if (controller.currentSubscriptionIsPromotional) {
|
||||
if (currentSubscriptionInfo?.isLifetimeSubscription ?? false) {
|
||||
return L10n.of(context).promotionalSubscriptionDesc;
|
||||
|
|
@ -123,6 +124,7 @@ class ManagementNotAvailableWarning extends StatelessWidget {
|
|||
formatter.format(currentSubscriptionInfo!.expirationDate!),
|
||||
);
|
||||
}
|
||||
|
||||
return L10n.of(context).subscriptionManagementUnavailable;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,35 @@ class SubscriptionRepo {
|
|||
}
|
||||
}
|
||||
|
||||
static Future<bool> activateFreeTrial() async {
|
||||
try {
|
||||
final Requests req = Requests(
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
accessToken: MatrixState.pangeaController.userController.accessToken,
|
||||
);
|
||||
final http.Response res = await req.get(
|
||||
url: PApiUrls.rcProductsTrial,
|
||||
);
|
||||
|
||||
if (res.statusCode != 201) {
|
||||
ErrorHandler.logError(
|
||||
e: res.body,
|
||||
data: {},
|
||||
);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (err, s) {
|
||||
ErrorHandler.logError(
|
||||
e: err,
|
||||
s: s,
|
||||
data: {},
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<RCSubscriptionResponseModel> getCurrentSubscriptionInfo(
|
||||
String? userId,
|
||||
List<SubscriptionDetails>? allProducts,
|
||||
|
|
@ -125,12 +154,14 @@ class RCSubscriptionResponseModel {
|
|||
SubscriptionDetails? currentSubscription;
|
||||
DateTime? expirationDate;
|
||||
List<String>? allEntitlements;
|
||||
Map<String, RCSubscription>? allSubscriptions;
|
||||
|
||||
RCSubscriptionResponseModel({
|
||||
this.currentSubscriptionId,
|
||||
this.currentSubscription,
|
||||
this.allEntitlements,
|
||||
this.expirationDate,
|
||||
this.allSubscriptions,
|
||||
});
|
||||
|
||||
factory RCSubscriptionResponseModel.fromJson(
|
||||
|
|
@ -145,9 +176,16 @@ class RCSubscriptionResponseModel {
|
|||
"User has more than one active entitlement. This shouldn't happen",
|
||||
);
|
||||
}
|
||||
|
||||
final history = (json['subscriptions'] as Map<String, dynamic>).map(
|
||||
(key, value) => MapEntry(key, RCSubscription.fromJson(value)),
|
||||
);
|
||||
|
||||
if (activeEntitlements.isEmpty) {
|
||||
debugPrint("User has no active entitlements");
|
||||
return RCSubscriptionResponseModel();
|
||||
return RCSubscriptionResponseModel(
|
||||
allSubscriptions: history,
|
||||
);
|
||||
}
|
||||
|
||||
final String currentSubscriptionId = activeEntitlements[0];
|
||||
|
|
@ -159,9 +197,6 @@ class RCSubscriptionResponseModel {
|
|||
currentSubscriptionMetadata['expires_date'],
|
||||
);
|
||||
|
||||
final String currentSubscriptionPeriodType =
|
||||
currentSubscriptionMetadata['period_type'] ?? "";
|
||||
|
||||
final SubscriptionDetails? currentSubscription =
|
||||
allProducts?.firstWhereOrNull(
|
||||
(SubscriptionDetails sub) =>
|
||||
|
|
@ -169,15 +204,12 @@ class RCSubscriptionResponseModel {
|
|||
currentSubscriptionId.contains(sub.id),
|
||||
);
|
||||
|
||||
if (currentSubscriptionPeriodType == "trial") {
|
||||
currentSubscription?.makeTrial();
|
||||
}
|
||||
|
||||
return RCSubscriptionResponseModel(
|
||||
currentSubscription: currentSubscription,
|
||||
currentSubscriptionId: currentSubscriptionId,
|
||||
expirationDate: expirationDate,
|
||||
allEntitlements: activeEntitlements,
|
||||
allSubscriptions: history,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -208,3 +240,50 @@ class RCSubscriptionResponseModel {
|
|||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
class RCSubscription {
|
||||
final String? autoResumeDate;
|
||||
final String? billingIssuesDetectedAt;
|
||||
final String expiresDate;
|
||||
final String? gracePeriodExpiresDate;
|
||||
final bool isSandbox;
|
||||
final String originalPurchaseDate;
|
||||
final String periodType;
|
||||
final String purchaseDate;
|
||||
final String? refundedAt;
|
||||
final String store;
|
||||
final String storeTransactionId;
|
||||
final String? unsubscribeDetectedAt;
|
||||
|
||||
RCSubscription({
|
||||
required this.autoResumeDate,
|
||||
required this.billingIssuesDetectedAt,
|
||||
required this.expiresDate,
|
||||
required this.gracePeriodExpiresDate,
|
||||
required this.isSandbox,
|
||||
required this.originalPurchaseDate,
|
||||
required this.periodType,
|
||||
required this.purchaseDate,
|
||||
required this.refundedAt,
|
||||
required this.store,
|
||||
required this.storeTransactionId,
|
||||
required this.unsubscribeDetectedAt,
|
||||
});
|
||||
|
||||
factory RCSubscription.fromJson(Map<String, dynamic> json) {
|
||||
return RCSubscription(
|
||||
autoResumeDate: json['auto_resume_date'],
|
||||
billingIssuesDetectedAt: json['billing_issues_detected_at'],
|
||||
expiresDate: json['expires_date'],
|
||||
gracePeriodExpiresDate: json['grace_period_expires_date'],
|
||||
isSandbox: json['is_sandbox'],
|
||||
originalPurchaseDate: json['original_purchase_date'],
|
||||
periodType: json['period_type'],
|
||||
purchaseDate: json['purchase_date'],
|
||||
refundedAt: json['refunded_at'],
|
||||
store: json['store'],
|
||||
storeTransactionId: json['store_transaction_id'],
|
||||
unsubscribeDetectedAt: json['unsubscribe_detected_at'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,14 +25,7 @@ class SubscriptionOptions extends StatelessWidget {
|
|||
? [
|
||||
SubscriptionCard(
|
||||
onTap: () => pangeaController.subscriptionController
|
||||
.submitSubscriptionChange(
|
||||
SubscriptionDetails(
|
||||
price: 0,
|
||||
id: "",
|
||||
periodType: SubscriptionPeriodType.trial,
|
||||
),
|
||||
context,
|
||||
),
|
||||
.activateNewUserTrial(),
|
||||
title: L10n.of(context).freeTrial,
|
||||
description: L10n.of(context).freeTrialDesc,
|
||||
buttonText: L10n.of(context).activateTrial,
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ class UserController extends BaseController {
|
|||
if (createdAt == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return createdAt.isAfter(
|
||||
DateTime.now().subtract(Duration(days: trialDays)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ class UserSettings {
|
|||
DateTime? dateOfBirth;
|
||||
DateTime? createdAt;
|
||||
bool? autoPlayMessages;
|
||||
// bool itAutoPlay;
|
||||
bool activatedFreeTrial;
|
||||
bool? publicProfile;
|
||||
String? targetLanguage;
|
||||
String? sourceLanguage;
|
||||
|
|
@ -26,8 +24,6 @@ class UserSettings {
|
|||
this.dateOfBirth,
|
||||
this.createdAt,
|
||||
this.autoPlayMessages,
|
||||
// this.itAutoPlay = true,
|
||||
this.activatedFreeTrial = false,
|
||||
this.publicProfile,
|
||||
this.targetLanguage,
|
||||
this.sourceLanguage,
|
||||
|
|
@ -44,8 +40,6 @@ class UserSettings {
|
|||
? DateTime.parse(json[ModelKey.userCreatedAt])
|
||||
: null,
|
||||
autoPlayMessages: json[ModelKey.autoPlayMessages],
|
||||
// itAutoPlay: json[ModelKey.itAutoPlay] ?? true,
|
||||
activatedFreeTrial: json[ModelKey.activatedTrialKey] ?? false,
|
||||
publicProfile: json[ModelKey.publicProfile],
|
||||
targetLanguage: json[ModelKey.l2LanguageKey],
|
||||
sourceLanguage: json[ModelKey.l1LanguageKey],
|
||||
|
|
@ -63,8 +57,6 @@ class UserSettings {
|
|||
data[ModelKey.userDateOfBirth] = dateOfBirth?.toIso8601String();
|
||||
data[ModelKey.userCreatedAt] = createdAt?.toIso8601String();
|
||||
data[ModelKey.autoPlayMessages] = autoPlayMessages;
|
||||
// data[ModelKey.itAutoPlay] = itAutoPlay;
|
||||
data[ModelKey.activatedTrialKey] = activatedFreeTrial;
|
||||
data[ModelKey.publicProfile] = publicProfile;
|
||||
data[ModelKey.l2LanguageKey] = targetLanguage;
|
||||
data[ModelKey.l1LanguageKey] = sourceLanguage;
|
||||
|
|
@ -111,12 +103,6 @@ class UserSettings {
|
|||
autoPlayMessages: (accountData[ModelKey.autoPlayMessages]
|
||||
?.content[ModelKey.autoPlayMessages] as bool?) ??
|
||||
false,
|
||||
// itAutoPlay: (accountData[ModelKey.itAutoPlay]
|
||||
// ?.content[ModelKey.itAutoPlay] as bool?) ??
|
||||
// true,
|
||||
activatedFreeTrial: (accountData[ModelKey.activatedTrialKey]
|
||||
?.content[ModelKey.activatedTrialKey] as bool?) ??
|
||||
false,
|
||||
publicProfile: (accountData[ModelKey.publicProfile]
|
||||
?.content[ModelKey.publicProfile] as bool?) ??
|
||||
false,
|
||||
|
|
@ -134,7 +120,6 @@ class UserSettings {
|
|||
dateOfBirth: dateOfBirth,
|
||||
createdAt: createdAt,
|
||||
autoPlayMessages: autoPlayMessages,
|
||||
activatedFreeTrial: activatedFreeTrial,
|
||||
publicProfile: publicProfile,
|
||||
targetLanguage: targetLanguage,
|
||||
sourceLanguage: sourceLanguage,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue