From db75b11b7554c3fdf3fe25cbf8372454e986cca5 Mon Sep 17 00:00:00 2001 From: otsmr Date: Tue, 20 May 2025 22:48:44 +0200 Subject: [PATCH] fix #173 --- lib/src/localization/app_de.arb | 2 + lib/src/localization/app_en.arb | 2 + .../generated/app_localizations.dart | 12 ++++ .../generated/app_localizations_de.dart | 10 +++ .../generated/app_localizations_en.dart | 10 +++ .../protobuf/api/server_to_client.pb.dart | 14 ++++ .../protobuf/api/server_to_client.pbjson.dart | 66 ++++++++++--------- .../manage_subscription_view.dart | 9 ++- .../subscription/subscription_view.dart | 46 +++++++++++-- 9 files changed, 132 insertions(+), 39 deletions(-) diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index ba781e0..00c7720 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -169,6 +169,8 @@ "errorSessionNotAuthenticated": "Deine Sitzung ist nicht authentifiziert. Bitte melde dich an, um fortzufahren.", "errorOnlyOneSessionAllowed": "Es ist nur eine aktive Sitzung pro Benutzer erlaubt. Bitte melde dich von anderen Geräten ab, um fortzufahren.", "upgradeToPaidPlan": "Upgrade auf einen kostenpflichtigen Plan.", + "upgradeToPaidPlanButton": "Auf {planId} upgraden", + "partOfPaidPlanOf": "Du bist Teil des bezahlten Plans von {username}!", "errorNotEnoughCredit": "Du hast nicht genügend twonly-Guthaben.", "errorPlanLimitReached": "Du hast das Limit deines Plans erreicht. Bitte upgrade deinen Plan.", "errorPlanNotAllowed": "Dieses Feature ist in deinem aktuellen Plan nicht verfügbar.", diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 7f806ba..daf63a0 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -331,6 +331,8 @@ "errorPlanNotAllowed": "This feature is not available in your current plan.", "errorPlanUpgradeNotYearly": "The plan upgrade must be paid for annually, as the current plan is also billed annually.", "upgradeToPaidPlan": "Upgrade to a paid plan.", + "upgradeToPaidPlanButton": "Upgrade subscription to {planId}", + "partOfPaidPlanOf": "You are part of the paid plan of {username}!", "year": "year", "month": "month", "proFeature1": "✓ Unlimited media file uploads", diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index 5900b8d..d8edbc9 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -1055,6 +1055,18 @@ abstract class AppLocalizations { /// **'Upgrade to a paid plan.'** String get upgradeToPaidPlan; + /// No description provided for @upgradeToPaidPlanButton. + /// + /// In en, this message translates to: + /// **'Upgrade subscription to {planId}'** + String upgradeToPaidPlanButton(Object planId); + + /// No description provided for @partOfPaidPlanOf. + /// + /// In en, this message translates to: + /// **'You are part of the paid plan of {username}!'** + String partOfPaidPlanOf(Object username); + /// No description provided for @year. /// /// In en, this message translates to: diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index 11d2d25..dbc655a 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -500,6 +500,16 @@ class AppLocalizationsDe extends AppLocalizations { @override String get upgradeToPaidPlan => 'Upgrade auf einen kostenpflichtigen Plan.'; + @override + String upgradeToPaidPlanButton(Object planId) { + return 'Auf $planId upgraden'; + } + + @override + String partOfPaidPlanOf(Object username) { + return 'Du bist Teil des bezahlten Plans von $username!'; + } + @override String get year => 'year'; diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index 0d179a5..6d5eadc 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -500,6 +500,16 @@ class AppLocalizationsEn extends AppLocalizations { @override String get upgradeToPaidPlan => 'Upgrade to a paid plan.'; + @override + String upgradeToPaidPlanButton(Object planId) { + return 'Upgrade subscription to $planId'; + } + + @override + String partOfPaidPlanOf(Object username) { + return 'You are part of the paid plan of $username!'; + } + @override String get year => 'year'; diff --git a/lib/src/model/protobuf/api/server_to_client.pb.dart b/lib/src/model/protobuf/api/server_to_client.pb.dart index af4e230..539959c 100644 --- a/lib/src/model/protobuf/api/server_to_client.pb.dart +++ b/lib/src/model/protobuf/api/server_to_client.pb.dart @@ -1069,6 +1069,7 @@ class Response_PlanBallance extends $pb.GeneratedMessage { $core.Iterable? transactions, $core.Iterable? additionalAccounts, $core.bool? autoRenewal, + $fixnum.Int64? additionalAccountOwnerId, }) { final $result = create(); if (usedDailyMediaUploadLimit != null) { @@ -1092,6 +1093,9 @@ class Response_PlanBallance extends $pb.GeneratedMessage { if (autoRenewal != null) { $result.autoRenewal = autoRenewal; } + if (additionalAccountOwnerId != null) { + $result.additionalAccountOwnerId = additionalAccountOwnerId; + } return $result; } Response_PlanBallance._() : super(); @@ -1106,6 +1110,7 @@ class Response_PlanBallance extends $pb.GeneratedMessage { ..pc(5, _omitFieldNames ? '' : 'transactions', $pb.PbFieldType.PM, subBuilder: Response_Transaction.create) ..pc(6, _omitFieldNames ? '' : 'additionalAccounts', $pb.PbFieldType.PM, subBuilder: Response_AdditionalAccount.create) ..aOB(7, _omitFieldNames ? '' : 'autoRenewal') + ..aInt64(8, _omitFieldNames ? '' : 'additionalAccountOwnerId') ..hasRequiredFields = false ; @@ -1180,6 +1185,15 @@ class Response_PlanBallance extends $pb.GeneratedMessage { $core.bool hasAutoRenewal() => $_has(6); @$pb.TagNumber(7) void clearAutoRenewal() => clearField(7); + + @$pb.TagNumber(8) + $fixnum.Int64 get additionalAccountOwnerId => $_getI64(7); + @$pb.TagNumber(8) + set additionalAccountOwnerId($fixnum.Int64 v) { $_setInt64(7, v); } + @$pb.TagNumber(8) + $core.bool hasAdditionalAccountOwnerId() => $_has(7); + @$pb.TagNumber(8) + void clearAdditionalAccountOwnerId() => clearField(8); } class Response_Location extends $pb.GeneratedMessage { diff --git a/lib/src/model/protobuf/api/server_to_client.pbjson.dart b/lib/src/model/protobuf/api/server_to_client.pbjson.dart index adbdc56..7fa696a 100644 --- a/lib/src/model/protobuf/api/server_to_client.pbjson.dart +++ b/lib/src/model/protobuf/api/server_to_client.pbjson.dart @@ -199,11 +199,13 @@ const Response_PlanBallance$json = { {'1': 'transactions', '3': 5, '4': 3, '5': 11, '6': '.server_to_client.Response.Transaction', '10': 'transactions'}, {'1': 'additional_accounts', '3': 6, '4': 3, '5': 11, '6': '.server_to_client.Response.AdditionalAccount', '10': 'additionalAccounts'}, {'1': 'auto_renewal', '3': 7, '4': 1, '5': 8, '9': 2, '10': 'autoRenewal', '17': true}, + {'1': 'additional_account_owner_id', '3': 8, '4': 1, '5': 3, '9': 3, '10': 'additionalAccountOwnerId', '17': true}, ], '8': [ {'1': '_payment_period_days'}, {'1': '_last_payment_done_unix_timestamp'}, {'1': '_auto_renewal'}, + {'1': '_additional_account_owner_id'}, ], }; @@ -321,7 +323,7 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( '1lZBgDIAEoCFIIcmVkZWVtZWQSHAoJcmVxdWVzdGVkGAQgASgIUglyZXF1ZXN0ZWQSOQoZY3Jl' 'YXRlZF9hdF91bml4X3RpbWVzdGFtcBgFIAEoA1IWY3JlYXRlZEF0VW5peFRpbWVzdGFtcBpKCg' 'hWb3VjaGVycxI+Cgh2b3VjaGVycxgBIAMoCzIiLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2Uu' - 'Vm91Y2hlclIIdm91Y2hlcnMaswQKDFBsYW5CYWxsYW5jZRJACh11c2VkX2RhaWx5X21lZGlhX3' + 'Vm91Y2hlclIIdm91Y2hlcnMalwUKDFBsYW5CYWxsYW5jZRJACh11c2VkX2RhaWx5X21lZGlhX3' 'VwbG9hZF9saW1pdBgBIAEoA1IZdXNlZERhaWx5TWVkaWFVcGxvYWRMaW1pdBI+Chx1c2VkX3Vw' 'bG9hZF9tZWRpYV9zaXplX2xpbWl0GAIgASgDUhh1c2VkVXBsb2FkTWVkaWFTaXplTGltaXQSMw' 'oTcGF5bWVudF9wZXJpb2RfZGF5cxgDIAEoA0gAUhFwYXltZW50UGVyaW9kRGF5c4gBARJLCiBs' @@ -330,34 +332,36 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( 'bnQuUmVzcG9uc2UuVHJhbnNhY3Rpb25SDHRyYW5zYWN0aW9ucxJdChNhZGRpdGlvbmFsX2FjY2' '91bnRzGAYgAygLMiwuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5BZGRpdGlvbmFsQWNjb3Vu' 'dFISYWRkaXRpb25hbEFjY291bnRzEiYKDGF1dG9fcmVuZXdhbBgHIAEoCEgCUgthdXRvUmVuZX' - 'dhbIgBAUIWChRfcGF5bWVudF9wZXJpb2RfZGF5c0IjCiFfbGFzdF9wYXltZW50X2RvbmVfdW5p' - 'eF90aW1lc3RhbXBCDwoNX2F1dG9fcmVuZXdhbBpOCghMb2NhdGlvbhIWCgZjb3VudHkYASABKA' - 'lSBmNvdW50eRIWCgZyZWdpb24YAiABKAlSBnJlZ2lvbhISCgRjaXR5GAMgASgJUgRjaXR5GjAK' - 'BlByZUtleRIOCgJpZBgBIAEoA1ICaWQSFgoGcHJla2V5GAIgASgMUgZwcmVrZXkatAMKCFVzZX' - 'JEYXRhEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBI7CgdwcmVrZXlzGAIgAygLMiEuc2VydmVy' - 'X3RvX2NsaWVudC5SZXNwb25zZS5QcmVLZXlSB3ByZWtleXMSHwoIdXNlcm5hbWUYByABKAxIAF' - 'IIdXNlcm5hbWWIAQESMwoTcHVibGljX2lkZW50aXR5X2tleRgDIAEoDEgBUhFwdWJsaWNJZGVu' - 'dGl0eUtleYgBARIoCg1zaWduZWRfcHJla2V5GAQgASgMSAJSDHNpZ25lZFByZWtleYgBARI7Ch' - 'dzaWduZWRfcHJla2V5X3NpZ25hdHVyZRgFIAEoDEgDUhVzaWduZWRQcmVrZXlTaWduYXR1cmWI' - 'AQESLQoQc2lnbmVkX3ByZWtleV9pZBgGIAEoA0gEUg5zaWduZWRQcmVrZXlJZIgBAUILCglfdX' - 'Nlcm5hbWVCFgoUX3B1YmxpY19pZGVudGl0eV9rZXlCEAoOX3NpZ25lZF9wcmVrZXlCGgoYX3Np' - 'Z25lZF9wcmVrZXlfc2lnbmF0dXJlQhMKEV9zaWduZWRfcHJla2V5X2lkGlkKC1VwbG9hZFRva2' - 'VuEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG9rZW4SJwoPZG93bmxvYWRfdG9rZW5z' - 'GAIgAygMUg5kb3dubG9hZFRva2VucxrTBQoCT2sSFAoETm9uZRgBIAEoCEgAUgROb25lEhgKBn' - 'VzZXJpZBgCIAEoA0gAUgZ1c2VyaWQSJgoNYXV0aGNoYWxsZW5nZRgDIAEoDEgAUg1hdXRoY2hh' - 'bGxlbmdlEkoKC3VwbG9hZHRva2VuGAQgASgLMiYuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS' - '5VcGxvYWRUb2tlbkgAUgt1cGxvYWR0b2tlbhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90' - 'b19jbGllbnQuUmVzcG9uc2UuVXNlckRhdGFIAFIIdXNlcmRhdGESHgoJYXV0aHRva2VuGAYgAS' - 'gMSABSCWF1dGh0b2tlbhJBCghsb2NhdGlvbhgHIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVz' - 'cG9uc2UuTG9jYXRpb25IAFIIbG9jYXRpb24SUAoNYXV0aGVudGljYXRlZBgIIAEoCzIoLnNlcn' - 'Zlcl90b19jbGllbnQuUmVzcG9uc2UuQXV0aGVudGljYXRlZEgAUg1hdXRoZW50aWNhdGVkEjgK' - 'BXBsYW5zGAkgASgLMiAuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuc0gAUgVwbGFucx' - 'JNCgxwbGFuYmFsbGFuY2UYCiABKAsyJy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlBsYW5C' - 'YWxsYW5jZUgAUgxwbGFuYmFsbGFuY2USQQoIdm91Y2hlcnMYCyABKAsyIy5zZXJ2ZXJfdG9fY2' - 'xpZW50LlJlc3BvbnNlLlZvdWNoZXJzSABSCHZvdWNoZXJzEl8KEmFkZGFjY291bnRzaW52aXRl' - 'cxgMIAEoCzItLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuQWRkQWNjb3VudHNJbnZpdGVzSA' - 'BSEmFkZGFjY291bnRzaW52aXRlc0IECgJPayKWAQoQVHJhbnNhY3Rpb25UeXBlcxIKCgZSZWZ1' - 'bmQQABITCg9Wb3VjaGVyUmVkZWVtZWQQARISCg5Wb3VjaGVyQ3JlYXRlZBACEggKBENhc2gQAx' - 'IPCgtQbGFuVXBncmFkZRAEEgsKB1Vua25vd24QBRIUChBUaGFua3NGb3JUZXN0aW5nEAYSDwoL' - 'QXV0b1JlbmV3YWwQB0IKCghSZXNwb25zZQ=='); + 'dhbIgBARJCChthZGRpdGlvbmFsX2FjY291bnRfb3duZXJfaWQYCCABKANIA1IYYWRkaXRpb25h' + 'bEFjY291bnRPd25lcklkiAEBQhYKFF9wYXltZW50X3BlcmlvZF9kYXlzQiMKIV9sYXN0X3BheW' + '1lbnRfZG9uZV91bml4X3RpbWVzdGFtcEIPCg1fYXV0b19yZW5ld2FsQh4KHF9hZGRpdGlvbmFs' + 'X2FjY291bnRfb3duZXJfaWQaTgoITG9jYXRpb24SFgoGY291bnR5GAEgASgJUgZjb3VudHkSFg' + 'oGcmVnaW9uGAIgASgJUgZyZWdpb24SEgoEY2l0eRgDIAEoCVIEY2l0eRowCgZQcmVLZXkSDgoC' + 'aWQYASABKANSAmlkEhYKBnByZWtleRgCIAEoDFIGcHJla2V5GrQDCghVc2VyRGF0YRIXCgd1c2' + 'VyX2lkGAEgASgDUgZ1c2VySWQSOwoHcHJla2V5cxgCIAMoCzIhLnNlcnZlcl90b19jbGllbnQu' + 'UmVzcG9uc2UuUHJlS2V5UgdwcmVrZXlzEh8KCHVzZXJuYW1lGAcgASgMSABSCHVzZXJuYW1liA' + 'EBEjMKE3B1YmxpY19pZGVudGl0eV9rZXkYAyABKAxIAVIRcHVibGljSWRlbnRpdHlLZXmIAQES' + 'KAoNc2lnbmVkX3ByZWtleRgEIAEoDEgCUgxzaWduZWRQcmVrZXmIAQESOwoXc2lnbmVkX3ByZW' + 'tleV9zaWduYXR1cmUYBSABKAxIA1IVc2lnbmVkUHJla2V5U2lnbmF0dXJliAEBEi0KEHNpZ25l' + 'ZF9wcmVrZXlfaWQYBiABKANIBFIOc2lnbmVkUHJla2V5SWSIAQFCCwoJX3VzZXJuYW1lQhYKFF' + '9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl9zaWduZWRfcHJla2V5QhoKGF9zaWduZWRfcHJla2V5' + 'X3NpZ25hdHVyZUITChFfc2lnbmVkX3ByZWtleV9pZBpZCgtVcGxvYWRUb2tlbhIhCgx1cGxvYW' + 'RfdG9rZW4YASABKAxSC3VwbG9hZFRva2VuEicKD2Rvd25sb2FkX3Rva2VucxgCIAMoDFIOZG93' + 'bmxvYWRUb2tlbnMa0wUKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZRIYCgZ1c2VyaWQYAiABKA' + 'NIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0aGNoYWxsZW5nZRJKCgt1' + 'cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXBsb2FkVG9rZW' + '5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJl' + 'c3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbhgGIAEoDEgAUglhdXRodG' + '9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkxvY2F0' + 'aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC5zZXJ2ZXJfdG9fY2xpZW' + '50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRlZBI4CgVwbGFucxgJIAEo' + 'CzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcGxhbnMSTQoMcGxhbmJhbG' + 'xhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuQmFsbGFuY2VIAFIM' + 'cGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3RvX2NsaWVudC5SZXNwb2' + '5zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2ludml0ZXMYDCABKAsyLS5z' + 'ZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aXRlc0gAUhJhZGRhY2NvdW' + '50c2ludml0ZXNCBAoCT2silgEKEFRyYW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91' + 'Y2hlclJlZGVlbWVkEAESEgoOVm91Y2hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3' + 'JhZGUQBBILCgdVbmtub3duEAUSFAoQVGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2Fs' + 'EAdCCgoIUmVzcG9uc2U='); diff --git a/lib/src/views/settings/subscription/manage_subscription_view.dart b/lib/src/views/settings/subscription/manage_subscription_view.dart index 48fc6e6..349e4c4 100644 --- a/lib/src/views/settings/subscription/manage_subscription_view.dart +++ b/lib/src/views/settings/subscription/manage_subscription_view.dart @@ -58,6 +58,7 @@ class _ManageSubscriptionViewState extends State { String planId = context.read().plan; Locale myLocale = Localizations.localeOf(context); bool? paidMonthly = ballance?.paymentPeriodDays == MONTHLY_PAYMENT_DAYS; + bool isAdditionalUser = planId == "Free" || planId == "Plus"; return Scaffold( appBar: AppBar( title: Text(context.lang.manageSubscription), @@ -65,14 +66,14 @@ class _ManageSubscriptionViewState extends State { body: ListView( children: [ PlanCard(planId: planId, paidMonthly: paidMonthly), - SizedBox(height: 20), - if (widget.nextPayment != null) + if (!isAdditionalUser) SizedBox(height: 20), + if (widget.nextPayment != null && !isAdditionalUser) ListTile( title: Text( "${context.lang.nextPayment}: ${DateFormat.yMMMMd(myLocale.toString()).format(widget.nextPayment!)}", ), ), - if (autoRenewal != null) + if (autoRenewal != null && !isAdditionalUser) ListTile( title: Text(context.lang.autoRenewal), subtitle: Text( @@ -87,6 +88,8 @@ class _ManageSubscriptionViewState extends State { }, ), ), + SizedBox(height: 20), + Divider(), ListTile( title: Text("Kündigen"), onTap: () async {}, diff --git a/lib/src/views/settings/subscription/subscription_view.dart b/lib/src/views/settings/subscription/subscription_view.dart index 2e7a5a2..809850e 100644 --- a/lib/src/views/settings/subscription/subscription_view.dart +++ b/lib/src/views/settings/subscription/subscription_view.dart @@ -5,6 +5,8 @@ import 'package:intl/intl.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; import 'package:twonly/globals.dart'; +import 'package:twonly/src/database/daos/contacts_dao.dart'; +import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/model/protobuf/api/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/providers/connection_provider.dart'; @@ -102,6 +104,7 @@ class SubscriptionView extends StatefulWidget { class _SubscriptionViewState extends State { bool loaded = false; Response_PlanBallance? ballance; + String? additionalOwnerName; @override void initState() { @@ -111,6 +114,17 @@ class _SubscriptionViewState extends State { Future initAsync() async { ballance = await loadPlanBallance(); + if (ballance != null && ballance!.hasAdditionalAccountOwnerId()) { + final ownerId = ballance!.additionalAccountOwnerId.toInt(); + Contact? contact = await twonlyDatabase.contactsDao + .getContactByUserId(ownerId) + .getSingleOrNull(); + if (contact != null) { + additionalOwnerName = getContactDisplayName(contact); + } else { + additionalOwnerName = ownerId.toString(); + } + } setState(() {}); } @@ -119,12 +133,15 @@ class _SubscriptionViewState extends State { Locale myLocale = Localizations.localeOf(context); String? formattedBalance; DateTime? nextPayment; + String currentPlan = context.read().plan; if (ballance != null) { DateTime lastPaymentDateTime = DateTime.fromMillisecondsSinceEpoch( ballance!.lastPaymentDoneUnixTimestamp.toInt() * 1000); - nextPayment = lastPaymentDateTime - .add(Duration(days: ballance!.paymentPeriodDays.toInt())); + if (currentPlan == "Pro" || currentPlan == "Family") { + nextPayment = lastPaymentDateTime + .add(Duration(days: ballance!.paymentPeriodDays.toInt())); + } int ballanceInCents = ballance!.transactions.map((a) => a.depositCents.toInt()).sum; formattedBalance = NumberFormat.currency( @@ -134,7 +151,6 @@ class _SubscriptionViewState extends State { ).format(ballanceInCents / 100); } - String currentPlan = context.read().plan; int refund = 0; if (currentPlan == "Pro" && ballance != null) { refund = calculateRefund(ballance!); @@ -184,6 +200,14 @@ class _SubscriptionViewState extends State { ), ), ), + if (additionalOwnerName != null) + Center( + child: Text( + context.lang.partOfPaidPlanOf(additionalOwnerName!), + textAlign: TextAlign.center, + style: TextStyle(color: Colors.orange), + ), + ), if (currentPlan != "Family" && currentPlan != "Pro") Center( child: Padding( @@ -257,7 +281,7 @@ class _SubscriptionViewState extends State { ], SizedBox(height: 10), if (currentPlan != "Family") Divider(), - if (currentPlan == "Family" || currentPlan == "Pro") + if (currentPlan != "Preview") BetterListTile( icon: FontAwesomeIcons.gears, text: context.lang.manageSubscription, @@ -269,7 +293,9 @@ class _SubscriptionViewState extends State { await Navigator.push(context, MaterialPageRoute(builder: (context) { return ManageSubscriptionView( - ballance: ballance, nextPayment: nextPayment); + ballance: ballance, + nextPayment: nextPayment, + ); })); initAsync(); }, @@ -461,6 +487,16 @@ class PlanCard extends StatelessWidget { fontSize: 12, ), ), + ), + if (onTap != null) + Padding( + padding: const EdgeInsets.only(top: 10), + child: FilledButton.icon( + onPressed: onTap, + label: (planId == "Free" || planId == "Plus") + ? Text(context.lang.redeemUserInviteCodeTitle) + : Text(context.lang.upgradeToPaidPlanButton(planId)), + ), ) ], ),