diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index 92b1a0c..2ca2ec3 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -128,6 +128,9 @@ "settingsHelpTerms": "Nutzungsbedingungen", "settingsAppearanceTheme": "Theme", "settingsAccountDeleteAccount": "Konto löschen", + "settingsAccountDeleteAccountWithBallance": "Im nächsten Schritt kannst du auswählen, was du mit dem Restguthaben ({credit}) machen willst.", + "settingsAccountDeleteAccountNoInternet": "Zum Löschen deines Accounts ist eine Internetverbindung erforderlich.", + "settingsAccountDeleteAccountNoBallance": "Wenn du dein Konto gelöscht hast, gibt es keinen Weg zurück.", "settingsAccountDeleteModalTitle": "Bist du sicher?", "settingsAccountDeleteModalBody": "Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.", "contactVerifyNumberTitle": "Sicherheitsnummer verifizieren", diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 937fd6e..aa19003 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -224,6 +224,9 @@ "settingsAppearanceTheme": "Theme", "@settingsAppearanceTheme": {}, "settingsAccountDeleteAccount": "Delete account", + "settingsAccountDeleteAccountWithBallance": "In the next step, you can select what you want to to with the remaining credit ({credit}).", + "settingsAccountDeleteAccountNoBallance": "Once you delete your account, there is no going back.", + "settingsAccountDeleteAccountNoInternet": "An Internet connection is required to delete your account.", "@settingsAccountDeleteAccount": {}, "settingsAccountDeleteModalTitle": "Are you sure?", "@settingsAccountDeleteModalTitle": {}, diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index 3a7eae5..6485154 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -770,6 +770,24 @@ abstract class AppLocalizations { /// **'Delete account'** String get settingsAccountDeleteAccount; + /// No description provided for @settingsAccountDeleteAccountWithBallance. + /// + /// In en, this message translates to: + /// **'In the next step, you can select what you want to to with the remaining credit ({credit}).'** + String settingsAccountDeleteAccountWithBallance(Object credit); + + /// No description provided for @settingsAccountDeleteAccountNoBallance. + /// + /// In en, this message translates to: + /// **'Once you delete your account, there is no going back.'** + String get settingsAccountDeleteAccountNoBallance; + + /// No description provided for @settingsAccountDeleteAccountNoInternet. + /// + /// In en, this message translates to: + /// **'An Internet connection is required to delete your account.'** + String get settingsAccountDeleteAccountNoInternet; + /// No description provided for @settingsAccountDeleteModalTitle. /// /// 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 56a3e97..4343676 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -375,6 +375,19 @@ class AppLocalizationsDe extends AppLocalizations { @override String get settingsAccountDeleteAccount => 'Konto löschen'; + @override + String settingsAccountDeleteAccountWithBallance(Object credit) { + return 'Im nächsten Schritt kannst du auswählen, was du mit dem Restguthaben ($credit) machen willst.'; + } + + @override + String get settingsAccountDeleteAccountNoBallance => + 'Wenn du dein Konto gelöscht hast, gibt es keinen Weg zurück.'; + + @override + String get settingsAccountDeleteAccountNoInternet => + 'Zum Löschen deines Accounts ist eine Internetverbindung erforderlich.'; + @override String get settingsAccountDeleteModalTitle => 'Bist du sicher?'; diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index cfb1902..48cb229 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -370,6 +370,19 @@ class AppLocalizationsEn extends AppLocalizations { @override String get settingsAccountDeleteAccount => 'Delete account'; + @override + String settingsAccountDeleteAccountWithBallance(Object credit) { + return 'In the next step, you can select what you want to to with the remaining credit ($credit).'; + } + + @override + String get settingsAccountDeleteAccountNoBallance => + 'Once you delete your account, there is no going back.'; + + @override + String get settingsAccountDeleteAccountNoInternet => + 'An Internet connection is required to delete your account.'; + @override String get settingsAccountDeleteModalTitle => 'Are you sure?'; diff --git a/lib/src/model/protobuf/api/client_to_server.pb.dart b/lib/src/model/protobuf/api/client_to_server.pb.dart index e1560e0..e42a96a 100644 --- a/lib/src/model/protobuf/api/client_to_server.pb.dart +++ b/lib/src/model/protobuf/api/client_to_server.pb.dart @@ -1851,6 +1851,38 @@ class ApplicationData_DownloadDone extends $pb.GeneratedMessage { void clearDownloadToken() => clearField(1); } +class ApplicationData_DeleteAccount extends $pb.GeneratedMessage { + factory ApplicationData_DeleteAccount() => create(); + ApplicationData_DeleteAccount._() : super(); + factory ApplicationData_DeleteAccount.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ApplicationData_DeleteAccount.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.DeleteAccount', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ApplicationData_DeleteAccount clone() => ApplicationData_DeleteAccount()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ApplicationData_DeleteAccount copyWith(void Function(ApplicationData_DeleteAccount) updates) => super.copyWith((message) => updates(message as ApplicationData_DeleteAccount)) as ApplicationData_DeleteAccount; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ApplicationData_DeleteAccount create() => ApplicationData_DeleteAccount._(); + ApplicationData_DeleteAccount createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ApplicationData_DeleteAccount getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ApplicationData_DeleteAccount? _defaultInstance; +} + enum ApplicationData_ApplicationData { textmessage, getuserbyusername, @@ -1875,6 +1907,7 @@ enum ApplicationData_ApplicationData { uploaddone, getsignedprekeybyuserid, updatesignedprekey, + deleteaccount, notSet } @@ -1903,6 +1936,7 @@ class ApplicationData extends $pb.GeneratedMessage { ApplicationData_UploadDone? uploaddone, ApplicationData_GetSignedPreKeyByUserId? getsignedprekeybyuserid, ApplicationData_UpdateSignedPreKey? updatesignedprekey, + ApplicationData_DeleteAccount? deleteaccount, }) { final $result = create(); if (textmessage != null) { @@ -1974,6 +2008,9 @@ class ApplicationData extends $pb.GeneratedMessage { if (updatesignedprekey != null) { $result.updatesignedprekey = updatesignedprekey; } + if (deleteaccount != null) { + $result.deleteaccount = deleteaccount; + } return $result; } ApplicationData._() : super(); @@ -2004,10 +2041,11 @@ class ApplicationData extends $pb.GeneratedMessage { 21 : ApplicationData_ApplicationData.uploaddone, 22 : ApplicationData_ApplicationData.getsignedprekeybyuserid, 23 : ApplicationData_ApplicationData.updatesignedprekey, + 24 : ApplicationData_ApplicationData.deleteaccount, 0 : ApplicationData_ApplicationData.notSet }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) + ..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]) ..aOM(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create) ..aOM(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create) ..aOM(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create) @@ -2031,6 +2069,7 @@ class ApplicationData extends $pb.GeneratedMessage { ..aOM(21, _omitFieldNames ? '' : 'uploaddone', subBuilder: ApplicationData_UploadDone.create) ..aOM(22, _omitFieldNames ? '' : 'getsignedprekeybyuserid', subBuilder: ApplicationData_GetSignedPreKeyByUserId.create) ..aOM(23, _omitFieldNames ? '' : 'updatesignedprekey', subBuilder: ApplicationData_UpdateSignedPreKey.create) + ..aOM(24, _omitFieldNames ? '' : 'deleteaccount', subBuilder: ApplicationData_DeleteAccount.create) ..hasRequiredFields = false ; @@ -2310,6 +2349,17 @@ class ApplicationData extends $pb.GeneratedMessage { void clearUpdatesignedprekey() => clearField(23); @$pb.TagNumber(23) ApplicationData_UpdateSignedPreKey ensureUpdatesignedprekey() => $_ensure(22); + + @$pb.TagNumber(24) + ApplicationData_DeleteAccount get deleteaccount => $_getN(23); + @$pb.TagNumber(24) + set deleteaccount(ApplicationData_DeleteAccount v) { setField(24, v); } + @$pb.TagNumber(24) + $core.bool hasDeleteaccount() => $_has(23); + @$pb.TagNumber(24) + void clearDeleteaccount() => clearField(24); + @$pb.TagNumber(24) + ApplicationData_DeleteAccount ensureDeleteaccount() => $_ensure(23); } class Response_PreKey extends $pb.GeneratedMessage { diff --git a/lib/src/model/protobuf/api/client_to_server.pbjson.dart b/lib/src/model/protobuf/api/client_to_server.pbjson.dart index 2211b82..851e03c 100644 --- a/lib/src/model/protobuf/api/client_to_server.pbjson.dart +++ b/lib/src/model/protobuf/api/client_to_server.pbjson.dart @@ -159,8 +159,9 @@ const ApplicationData$json = { {'1': 'uploaddone', '3': 21, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UploadDone', '9': 0, '10': 'uploaddone'}, {'1': 'getsignedprekeybyuserid', '3': 22, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.GetSignedPreKeyByUserId', '9': 0, '10': 'getsignedprekeybyuserid'}, {'1': 'updatesignedprekey', '3': 23, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdateSignedPreKey', '9': 0, '10': 'updatesignedprekey'}, + {'1': 'deleteaccount', '3': 24, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.DeleteAccount', '9': 0, '10': 'deleteaccount'}, ], - '3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_RedeemVoucher$json, ApplicationData_SwitchToPayedPlan$json, ApplicationData_UpdatePlanOptions$json, ApplicationData_CreateVoucher$json, ApplicationData_GetLocation$json, ApplicationData_GetVouchers$json, ApplicationData_GetAvailablePlans$json, ApplicationData_GetAddAccountsInvites$json, ApplicationData_GetCurrentPlanInfos$json, ApplicationData_RedeemAdditionalCode$json, ApplicationData_RemoveAdditionalUser$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetSignedPreKeyByUserId$json, ApplicationData_UpdateSignedPreKey$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_UploadDone$json, ApplicationData_DownloadData$json, ApplicationData_DownloadDone$json], + '3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_RedeemVoucher$json, ApplicationData_SwitchToPayedPlan$json, ApplicationData_UpdatePlanOptions$json, ApplicationData_CreateVoucher$json, ApplicationData_GetLocation$json, ApplicationData_GetVouchers$json, ApplicationData_GetAvailablePlans$json, ApplicationData_GetAddAccountsInvites$json, ApplicationData_GetCurrentPlanInfos$json, ApplicationData_RedeemAdditionalCode$json, ApplicationData_RemoveAdditionalUser$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetSignedPreKeyByUserId$json, ApplicationData_UpdateSignedPreKey$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_UploadDone$json, ApplicationData_DownloadData$json, ApplicationData_DownloadDone$json, ApplicationData_DeleteAccount$json], '8': [ {'1': 'ApplicationData'}, ], @@ -352,6 +353,11 @@ const ApplicationData_DownloadDone$json = { ], }; +@$core.Deprecated('Use applicationDataDescriptor instead') +const ApplicationData_DeleteAccount$json = { + '1': 'DeleteAccount', +}; + /// Descriptor for `ApplicationData`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode( 'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dG1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm' @@ -394,32 +400,34 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode( '9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5HZXRTaWduZWRQcmVLZXlCeVVzZXJJZEgAUhdnZXRz' 'aWduZWRwcmVrZXlieXVzZXJpZBJmChJ1cGRhdGVzaWduZWRwcmVrZXkYFyABKAsyNC5jbGllbn' 'RfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGRhdGVTaWduZWRQcmVLZXlIAFISdXBkYXRl' - 'c2lnbmVkcHJla2V5GmoKC1RleHRNZXNzYWdlEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBISCg' - 'Rib2R5GAMgASgMUgRib2R5EiAKCXB1c2hfZGF0YRgEIAEoDEgAUghwdXNoRGF0YYgBAUIMCgpf' - 'cHVzaF9kYXRhGi8KEUdldFVzZXJCeVVzZXJuYW1lEhoKCHVzZXJuYW1lGAEgASgJUgh1c2Vybm' - 'FtZRo1ChRVcGRhdGVHb29nbGVGY21Ub2tlbhIdCgpnb29nbGVfZmNtGAEgASgJUglnb29nbGVG' - 'Y20aJgoLR2V0VXNlckJ5SWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGikKDVJlZGVlbVZvdW' - 'NoZXISGAoHdm91Y2hlchgBIAEoCVIHdm91Y2hlchpwChFTd2l0Y2hUb1BheWVkUGxhbhIXCgdw' - 'bGFuX2lkGAEgASgJUgZwbGFuSWQSHwoLcGF5X21vbnRobHkYAiABKAhSCnBheU1vbnRobHkSIQ' - 'oMYXV0b19yZW5ld2FsGAMgASgIUgthdXRvUmVuZXdhbBo2ChFVcGRhdGVQbGFuT3B0aW9ucxIh' - 'CgxhdXRvX3JlbmV3YWwYASABKAhSC2F1dG9SZW5ld2FsGjAKDUNyZWF0ZVZvdWNoZXISHwoLdm' - 'FsdWVfY2VudHMYASABKA1SCnZhbHVlQ2VudHMaDQoLR2V0TG9jYXRpb24aDQoLR2V0Vm91Y2hl' - 'cnMaEwoRR2V0QXZhaWxhYmxlUGxhbnMaFwoVR2V0QWRkQWNjb3VudHNJbnZpdGVzGhUKE0dldE' - 'N1cnJlbnRQbGFuSW5mb3MaNwoUUmVkZWVtQWRkaXRpb25hbENvZGUSHwoLaW52aXRlX2NvZGUY' - 'AiABKAlSCmludml0ZUNvZGUaLwoUUmVtb3ZlQWRkaXRpb25hbFVzZXISFwoHdXNlcl9pZBgBIA' - 'EoA1IGdXNlcklkGi0KEkdldFByZWtleXNCeVVzZXJJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2Vy' - 'SWQaMgoXR2V0U2lnbmVkUHJlS2V5QnlVc2VySWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkGp' - 'sBChJVcGRhdGVTaWduZWRQcmVLZXkSKAoQc2lnbmVkX3ByZWtleV9pZBgBIAEoA1IOc2lnbmVk' - 'UHJla2V5SWQSIwoNc2lnbmVkX3ByZWtleRgCIAEoDFIMc2lnbmVkUHJla2V5EjYKF3NpZ25lZF' - '9wcmVrZXlfc2lnbmF0dXJlGAMgASgMUhVzaWduZWRQcmVrZXlTaWduYXR1cmUaOwoOR2V0VXBs' - 'b2FkVG9rZW4SKQoQcmVjaXBpZW50c19jb3VudBgBIAEoDVIPcmVjaXBpZW50c0NvdW50GokBCg' - 'pVcGxvYWREYXRhEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG9rZW4SFgoGb2Zmc2V0' - 'GAIgASgNUgZvZmZzZXQSEgoEZGF0YRgDIAEoDFIEZGF0YRIfCghjaGVja3N1bRgEIAEoDEgAUg' - 'hjaGVja3N1bYgBAUILCglfY2hlY2tzdW0aWgoKVXBsb2FkRG9uZRIhCgx1cGxvYWRfdG9rZW4Y' - 'ASABKAxSC3VwbG9hZFRva2VuEikKEHJlY2lwaWVudHNfY291bnQYAiABKA1SD3JlY2lwaWVudH' - 'NDb3VudBpNCgxEb3dubG9hZERhdGESJQoOZG93bmxvYWRfdG9rZW4YASABKAxSDWRvd25sb2Fk' - 'VG9rZW4SFgoGb2Zmc2V0GAIgASgNUgZvZmZzZXQaNQoMRG93bmxvYWREb25lEiUKDmRvd25sb2' - 'FkX3Rva2VuGAEgASgMUg1kb3dubG9hZFRva2VuQhEKD0FwcGxpY2F0aW9uRGF0YQ=='); + 'c2lnbmVkcHJla2V5ElcKDWRlbGV0ZWFjY291bnQYGCABKAsyLy5jbGllbnRfdG9fc2VydmVyLk' + 'FwcGxpY2F0aW9uRGF0YS5EZWxldGVBY2NvdW50SABSDWRlbGV0ZWFjY291bnQaagoLVGV4dE1l' + 'c3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBGJvZHkYAyABKAxSBGJvZHkSIAoJcH' + 'VzaF9kYXRhGAQgASgMSABSCHB1c2hEYXRhiAEBQgwKCl9wdXNoX2RhdGEaLwoRR2V0VXNlckJ5' + 'VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW1lGjUKFFVwZGF0ZUdvb2dsZUZjbV' + 'Rva2VuEh0KCmdvb2dsZV9mY20YASABKAlSCWdvb2dsZUZjbRomCgtHZXRVc2VyQnlJZBIXCgd1' + 'c2VyX2lkGAEgASgDUgZ1c2VySWQaKQoNUmVkZWVtVm91Y2hlchIYCgd2b3VjaGVyGAEgASgJUg' + 'd2b3VjaGVyGnAKEVN3aXRjaFRvUGF5ZWRQbGFuEhcKB3BsYW5faWQYASABKAlSBnBsYW5JZBIf' + 'CgtwYXlfbW9udGhseRgCIAEoCFIKcGF5TW9udGhseRIhCgxhdXRvX3JlbmV3YWwYAyABKAhSC2' + 'F1dG9SZW5ld2FsGjYKEVVwZGF0ZVBsYW5PcHRpb25zEiEKDGF1dG9fcmVuZXdhbBgBIAEoCFIL' + 'YXV0b1JlbmV3YWwaMAoNQ3JlYXRlVm91Y2hlchIfCgt2YWx1ZV9jZW50cxgBIAEoDVIKdmFsdW' + 'VDZW50cxoNCgtHZXRMb2NhdGlvbhoNCgtHZXRWb3VjaGVycxoTChFHZXRBdmFpbGFibGVQbGFu' + 'cxoXChVHZXRBZGRBY2NvdW50c0ludml0ZXMaFQoTR2V0Q3VycmVudFBsYW5JbmZvcxo3ChRSZW' + 'RlZW1BZGRpdGlvbmFsQ29kZRIfCgtpbnZpdGVfY29kZRgCIAEoCVIKaW52aXRlQ29kZRovChRS' + 'ZW1vdmVBZGRpdGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaLQoSR2V0UHJla2' + 'V5c0J5VXNlcklkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBoyChdHZXRTaWduZWRQcmVLZXlC' + 'eVVzZXJJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQamwEKElVwZGF0ZVNpZ25lZFByZUtleR' + 'IoChBzaWduZWRfcHJla2V5X2lkGAEgASgDUg5zaWduZWRQcmVrZXlJZBIjCg1zaWduZWRfcHJl' + 'a2V5GAIgASgMUgxzaWduZWRQcmVrZXkSNgoXc2lnbmVkX3ByZWtleV9zaWduYXR1cmUYAyABKA' + 'xSFXNpZ25lZFByZWtleVNpZ25hdHVyZRo7Cg5HZXRVcGxvYWRUb2tlbhIpChByZWNpcGllbnRz' + 'X2NvdW50GAEgASgNUg9yZWNpcGllbnRzQ291bnQaiQEKClVwbG9hZERhdGESIQoMdXBsb2FkX3' + 'Rva2VuGAEgASgMUgt1cGxvYWRUb2tlbhIWCgZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRh' + 'GAMgASgMUgRkYXRhEh8KCGNoZWNrc3VtGAQgASgMSABSCGNoZWNrc3VtiAEBQgsKCV9jaGVja3' + 'N1bRpaCgpVcGxvYWREb25lEiEKDHVwbG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG9rZW4SKQoQ' + 'cmVjaXBpZW50c19jb3VudBgCIAEoDVIPcmVjaXBpZW50c0NvdW50Gk0KDERvd25sb2FkRGF0YR' + 'IlCg5kb3dubG9hZF90b2tlbhgBIAEoDFINZG93bmxvYWRUb2tlbhIWCgZvZmZzZXQYAiABKA1S' + 'Bm9mZnNldBo1CgxEb3dubG9hZERvbmUSJQoOZG93bmxvYWRfdG9rZW4YASABKAxSDWRvd25sb2' + 'FkVG9rZW4aDwoNRGVsZXRlQWNjb3VudEIRCg9BcHBsaWNhdGlvbkRhdGE='); @$core.Deprecated('Use responseDescriptor instead') const Response$json = { diff --git a/lib/src/model/protobuf/api/error.pbenum.dart b/lib/src/model/protobuf/api/error.pbenum.dart index 972085a..434e359 100644 --- a/lib/src/model/protobuf/api/error.pbenum.dart +++ b/lib/src/model/protobuf/api/error.pbenum.dart @@ -44,6 +44,7 @@ class ErrorCode extends $pb.ProtobufEnum { static const ErrorCode PlanDowngrade = ErrorCode._(1025, _omitEnumNames ? '' : 'PlanDowngrade'); static const ErrorCode PlanUpgradeNotYearly = ErrorCode._(1026, _omitEnumNames ? '' : 'PlanUpgradeNotYearly'); static const ErrorCode InvalidSignedPreKey = ErrorCode._(1027, _omitEnumNames ? '' : 'InvalidSignedPreKey'); + static const ErrorCode UserIdNotFound = ErrorCode._(1028, _omitEnumNames ? '' : 'UserIdNotFound'); static const $core.List values = [ Unknown, @@ -76,6 +77,7 @@ class ErrorCode extends $pb.ProtobufEnum { PlanDowngrade, PlanUpgradeNotYearly, InvalidSignedPreKey, + UserIdNotFound, ]; static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/lib/src/model/protobuf/api/error.pbjson.dart b/lib/src/model/protobuf/api/error.pbjson.dart index c721fc6..b8c7bdb 100644 --- a/lib/src/model/protobuf/api/error.pbjson.dart +++ b/lib/src/model/protobuf/api/error.pbjson.dart @@ -47,6 +47,7 @@ const ErrorCode$json = { {'1': 'PlanDowngrade', '2': 1025}, {'1': 'PlanUpgradeNotYearly', '2': 1026}, {'1': 'InvalidSignedPreKey', '2': 1027}, + {'1': 'UserIdNotFound', '2': 1028}, ], }; @@ -65,5 +66,5 @@ final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode( 'Cg5JbnZhbGlkUHJlS2V5cxD8BxITCg5Wb3VjaGVySW5WYWxpZBD9BxITCg5QbGFuTm90QWxsb3' 'dlZBD+BxIVChBQbGFuTGltaXRSZWFjaGVkEP8HEhQKD05vdEVub3VnaENyZWRpdBCACBISCg1Q' 'bGFuRG93bmdyYWRlEIEIEhkKFFBsYW5VcGdyYWRlTm90WWVhcmx5EIIIEhgKE0ludmFsaWRTaW' - 'duZWRQcmVLZXkQgwg='); + 'duZWRQcmVLZXkQgwgSEwoOVXNlcklkTm90Rm91bmQQhAg='); diff --git a/lib/src/services/api.service.dart b/lib/src/services/api.service.dart index 35710c6..0743e92 100644 --- a/lib/src/services/api.service.dart +++ b/lib/src/services/api.service.dart @@ -532,6 +532,13 @@ class ApiService { return await sendRequestSync(req); } + Future deleteAccount() async { + var get = ApplicationData_DeleteAccount(); + var appData = ApplicationData()..deleteaccount = get; + var req = createClientToServerFromApplicationData(appData); + return await sendRequestSync(req); + } + Future redeemUserInviteCode(String inviteCode) async { var get = ApplicationData_RedeemAdditionalCode()..inviteCode = inviteCode; var appData = ApplicationData()..redeemadditionalcode = get; diff --git a/lib/src/views/settings/account.view.dart b/lib/src/views/settings/account.view.dart index a021b77..9603b9c 100644 --- a/lib/src/views/settings/account.view.dart +++ b/lib/src/views/settings/account.view.dart @@ -1,12 +1,55 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/foundation.dart'; +import 'package:intl/intl.dart'; import 'package:restart_app/restart_app.dart'; import 'package:flutter/material.dart'; +import 'package:twonly/globals.dart'; +import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart'; import 'package:twonly/src/views/components/alert_dialog.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; +import 'package:twonly/src/views/settings/account/refund_credits.view.dart'; +import 'package:twonly/src/views/settings/subscription/subscription.view.dart'; -class AccountView extends StatelessWidget { +class AccountView extends StatefulWidget { const AccountView({super.key}); + @override + State createState() => _AccountViewState(); +} + +class _AccountViewState extends State { + String? formattedBallance; + bool hasRemainingBallance = false; + + @override + void initState() { + initAsync(); + super.initState(); + } + + Future initAsync() async { + final ballance = await loadPlanBalance(useCache: false); + if (ballance == null || !mounted) return; + int ballanceInCents = ballance.transactions + .where((x) => + (x.transactionType != Response_TransactionTypes.ThanksForTesting || + kDebugMode)) + .map((a) => a.depositCents.toInt()) + .sum; + if (ballanceInCents < 0) { + ballanceInCents = 0; + } + hasRemainingBallance = (ballanceInCents > 0); + Locale myLocale = Localizations.localeOf(context); + formattedBallance = NumberFormat.currency( + locale: myLocale.toString(), + symbol: '€', + decimalDigits: 2, + ).format(ballanceInCents / 100); + setState(() {}); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -19,27 +62,79 @@ class AccountView extends StatelessWidget { title: Text("Transfer account"), subtitle: Text("Coming soon"), onTap: () async { - showAlertDialog(context, "Coming soon", - "This feature is not yet implemented!"); + showAlertDialog( + context, + "Coming soon", + "This feature is not yet implemented!", + ); }, ), + Divider(), + Container( + alignment: Alignment.center, + padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20), + child: Text( + "Danger Zone", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + color: Colors.red, + fontWeight: FontWeight.bold, + ), + ), + ), ListTile( - title: Text(context.lang.settingsAccountDeleteAccount, - style: TextStyle(color: Colors.red)), - onTap: () async { - bool ok = await showAlertDialog( - context, - context.lang.settingsAccountDeleteModalTitle, - context.lang.settingsAccountDeleteModalBody); - - if (ok) { - await deleteLocalUserData(); - Restart.restartApp( - notificationTitle: 'Successfully logged out', - notificationBody: 'Click here to open the app again', - ); - } - }, + title: Text( + context.lang.settingsAccountDeleteAccount, + style: TextStyle(color: Colors.red), + ), + subtitle: (formattedBallance == null) + ? Text(context.lang.settingsAccountDeleteAccountNoInternet) + : (hasRemainingBallance) + ? Text(context.lang + .settingsAccountDeleteAccountWithBallance( + formattedBallance!)) + : Text(context.lang.settingsAccountDeleteAccountNoBallance), + onTap: (formattedBallance == null) + ? null + : () async { + if (hasRemainingBallance) { + bool? canGoNext = await Navigator.push(context, + MaterialPageRoute(builder: (context) { + return RefundCreditsView( + formattedBalance: formattedBallance!, + ); + })); + initAsync(); + if (canGoNext == null || !canGoNext) return; + } + if (!context.mounted) return; + bool ok = await showAlertDialog( + context, + context.lang.settingsAccountDeleteModalTitle, + context.lang.settingsAccountDeleteModalBody, + ); + if (ok) { + final res = await apiService.deleteAccount(); + if (res.isError) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + "Could not delete the account. Please ensure you have a internet connection!", + ), + duration: Duration(seconds: 3), + ), + ); + return; + } + await deleteLocalUserData(); + Restart.restartApp( + notificationTitle: 'Account successfully deleted', + notificationBody: 'Click here to open the app again', + ); + } + }, ), ], ), diff --git a/lib/src/views/settings/account/refund_credits.view.dart b/lib/src/views/settings/account/refund_credits.view.dart new file mode 100644 index 0000000..2d8b1d8 --- /dev/null +++ b/lib/src/views/settings/account/refund_credits.view.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:twonly/src/views/settings/subscription/voucher.view.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class RefundCreditsView extends StatefulWidget { + const RefundCreditsView({super.key, required this.formattedBalance}); + final String formattedBalance; + + @override + State createState() => _RefundCreditsViewState(); +} + +class _RefundCreditsViewState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Refund Credits'), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Text( + 'Remaining balance: ${widget.formattedBalance}', + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: 20), // Space between balance and options + + ListTile( + title: Text("Create a Voucher"), + onTap: () async { + await Navigator.push(context, + MaterialPageRoute(builder: (context) { + return VoucherView(); + })); + Navigator.pop(context, false); + }, + ), + ListTile( + title: Text("Spend to an Open Source Project"), + onTap: () async {}, + ), + ListTile( + title: Text("Spend to an NGO"), + onTap: () async {}, + ), + ListTile( + title: Text("Spend to twonly"), + onTap: () async {}, + ), + Divider(), + ListTile( + title: Text( + "Learn more about your donation", + ), + subtitle: Text( + "This will open our webpage which will provide you more informations where we will donate your remaining ballance if you choose this option.", + ), + onTap: () { + launchUrl(Uri.parse("https://twonly.eu/de/donation/")); + }, + trailing: FaIcon( + FontAwesomeIcons.arrowUpRightFromSquare, + size: 15, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/src/views/settings/subscription/additional_users.view.dart b/lib/src/views/settings/subscription/additional_users.view.dart index 24b2807..2527af8 100644 --- a/lib/src/views/settings/subscription/additional_users.view.dart +++ b/lib/src/views/settings/subscription/additional_users.view.dart @@ -57,7 +57,7 @@ class _AdditionalUsersViewState extends State { Future initAsync(bool force) async { additionalInvites = await loadAdditionalUserInvites(); if (force) { - ballance = await loadPlanBallance(); + ballance = await loadPlanBalance(); } setState(() {}); } diff --git a/lib/src/views/settings/subscription/manage_subscription.view.dart b/lib/src/views/settings/subscription/manage_subscription.view.dart index 517802f..7de41c8 100644 --- a/lib/src/views/settings/subscription/manage_subscription.view.dart +++ b/lib/src/views/settings/subscription/manage_subscription.view.dart @@ -35,7 +35,7 @@ class _ManageSubscriptionViewState extends State { Future initAsync(bool force) async { if (force) { - ballance = await loadPlanBallance(); + ballance = await loadPlanBalance(); if (ballance != null) { autoRenewal = ballance!.autoRenewal; } @@ -90,12 +90,6 @@ class _ManageSubscriptionViewState extends State { }, ), ), - // SizedBox(height: 20), - // Divider(), - // ListTile( - // title: Text("Cancel subscription"), - // onTap: () async {}, - // ), ], ), ); diff --git a/lib/src/views/settings/subscription/select_payment.view.dart b/lib/src/views/settings/subscription/select_payment.view.dart index a9b0c60..17a0f76 100644 --- a/lib/src/views/settings/subscription/select_payment.view.dart +++ b/lib/src/views/settings/subscription/select_payment.view.dart @@ -10,12 +10,13 @@ import 'package:twonly/src/views/settings/subscription/voucher.view.dart'; import 'package:url_launcher/url_launcher.dart'; class SelectPaymentView extends StatefulWidget { - const SelectPaymentView( - {super.key, - this.planId, - this.payMonthly, - this.valueInCents, - this.refund}); + const SelectPaymentView({ + super.key, + this.planId, + this.payMonthly, + this.valueInCents, + this.refund, + }); final String? planId; final bool? payMonthly; @@ -33,7 +34,7 @@ enum PaymentMethods { } class _SelectPaymentViewState extends State { - int? ballanceInCents; + int? balanceInCents; int checkoutInCents = 0; bool tryAutoRenewal = true; @@ -47,9 +48,9 @@ class _SelectPaymentViewState extends State { } Future initAsync() async { - final ballance = await loadPlanBallance(); - ballanceInCents = - ballance!.transactions.map((a) => a.depositCents.toInt()).sum; + final balance = await loadPlanBalance(); + balanceInCents = + balance!.transactions.map((a) => a.depositCents.toInt()).sum; setState(() {}); } @@ -74,7 +75,7 @@ class _SelectPaymentViewState extends State { ? "${localePrizing(context, checkoutInCents)}/${(widget.payMonthly!) ? context.lang.month : context.lang.year}" : localePrizing(context, checkoutInCents); bool canPay = (paymentMethods == PaymentMethods.twonlyCredit && - (ballanceInCents == null || ballanceInCents! >= checkoutInCents)); + (balanceInCents == null || balanceInCents! >= checkoutInCents)); return Scaffold( appBar: AppBar( title: Text(context.lang.selectPaymentMethode), @@ -98,9 +99,9 @@ class _SelectPaymentViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(context.lang.twonlyCredit), - if (ballanceInCents != null) + if (balanceInCents != null) Text( - "${context.lang.currentBalance}: ${localePrizing(context, ballanceInCents!)}", + "${context.lang.currentBalance}: ${localePrizing(context, balanceInCents!)}", style: TextStyle(fontSize: 10), ) ], diff --git a/lib/src/views/settings/subscription/subscription.view.dart b/lib/src/views/settings/subscription/subscription.view.dart index c00f912..0e3ecce 100644 --- a/lib/src/views/settings/subscription/subscription.view.dart +++ b/lib/src/views/settings/subscription/subscription.view.dart @@ -35,7 +35,7 @@ String localePrizing(BuildContext context, int cents) { ).format(cents / 100); } -Future loadPlanBallance() async { +Future loadPlanBalance({bool useCache = true}) async { Response_PlanBallance? ballance; final user = await getUser(); if (user == null) return ballance; @@ -43,7 +43,7 @@ Future loadPlanBallance() async { if (ballance != null) { user.lastPlanBallance = ballance.writeToJson(); await updateUser(user); - } else if (user.lastPlanBallance != null) { + } else if (user.lastPlanBallance != null && useCache) { try { ballance = Response_PlanBallance.fromJson( user.lastPlanBallance!, @@ -113,7 +113,7 @@ class _SubscriptionViewState extends State { } Future initAsync() async { - ballance = await loadPlanBallance(); + ballance = await loadPlanBalance(); if (ballance != null && ballance!.hasAdditionalAccountOwnerId()) { final ownerId = ballance!.additionalAccountOwnerId.toInt(); Contact? contact = await twonlyDB.contactsDao