From ec8d08ff076f513025ed486747d40ab98448823f Mon Sep 17 00:00:00 2001 From: NaiJi Date: Mon, 13 Nov 2023 14:03:52 +0400 Subject: [PATCH 1/4] fix(api): Force DateTime to UTC where timezone naive - Solve https://git.selfprivacy.org/SelfPrivacy/selfprivacy.org.app/issues/385 --- .../api_maps/graphql_maps/server_api/server_actions_api.dart | 2 +- lib/logic/api_maps/graphql_maps/server_api/server_api.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/logic/api_maps/graphql_maps/server_api/server_actions_api.dart b/lib/logic/api_maps/graphql_maps/server_api/server_actions_api.dart index 05269d33..51a893c0 100644 --- a/lib/logic/api_maps/graphql_maps/server_api/server_actions_api.dart +++ b/lib/logic/api_maps/graphql_maps/server_api/server_actions_api.dart @@ -29,7 +29,7 @@ mixin ServerActionsApi on GraphQLApiMap { print(response.exception.toString()); } if (response.parsedData!.rebootSystem.success) { - time = DateTime.now(); + time = DateTime.now().toUtc(); } } catch (e) { print(e); diff --git a/lib/logic/api_maps/graphql_maps/server_api/server_api.dart b/lib/logic/api_maps/graphql_maps/server_api/server_api.dart index bc28a681..fcf3db05 100644 --- a/lib/logic/api_maps/graphql_maps/server_api/server_api.dart +++ b/lib/logic/api_maps/graphql_maps/server_api/server_api.dart @@ -248,7 +248,7 @@ class ServerApi extends GraphQLApiMap final GraphQLClient client = await getClient(); final input = Input$RecoveryKeyLimitsInput( - expirationDate: expirationDate, + expirationDate: expirationDate?.toUtc(), uses: numberOfUses, ); final variables = Variables$Mutation$GetNewRecoveryApiKey( From a2b28e199d97b78874473eb15c12da2a300a9bf8 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Sun, 19 Nov 2023 23:51:36 +0400 Subject: [PATCH 2/4] feat: Implement flexible precision formatting for prices --- .../initializing/server_type_picker.dart | 19 ++++++++++++++----- lib/utils/ui_helpers.dart | 11 +++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/ui/pages/setup/initializing/server_type_picker.dart b/lib/ui/pages/setup/initializing/server_type_picker.dart index 3ce0f94b..932cbd93 100644 --- a/lib/ui/pages/setup/initializing/server_type_picker.dart +++ b/lib/ui/pages/setup/initializing/server_type_picker.dart @@ -9,6 +9,7 @@ import 'package:selfprivacy/logic/models/server_type.dart'; import 'package:selfprivacy/ui/components/buttons/brand_button.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart'; import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart'; +import 'package:selfprivacy/utils/ui_helpers.dart'; class ServerTypePicker extends StatefulWidget { const ServerTypePicker({ @@ -329,7 +330,7 @@ class SelectTypePage extends StatelessWidget { 'initializing.choose_server_type_payment_per_month' .tr( args: [ - '${(type.price.value + storagePrice + publicIpPrice).toStringAsFixed(4)} ${type.price.currency.shortcode}' + '${UiHelpers.formatWithPrecision(type.price.value + storagePrice + publicIpPrice)} ${type.price.currency.shortcode}', ], ), style: Theme.of(context) @@ -370,8 +371,10 @@ class SelectTypePage extends StatelessWidget { 'initializing.choose_server_type_payment_server' .tr( args: [ - type.price.value - .toString() + UiHelpers + .formatWithPrecision( + type.price.value, + ), ], ), style: Theme.of(context) @@ -401,7 +404,10 @@ class SelectTypePage extends StatelessWidget { 'initializing.choose_server_type_payment_storage' .tr( args: [ - storagePrice.toString() + UiHelpers + .formatWithPrecision( + storagePrice, + ), ], ), style: Theme.of(context) @@ -432,7 +438,10 @@ class SelectTypePage extends StatelessWidget { 'initializing.choose_server_type_payment_ip' .tr( args: [ - publicIpPrice.toString() + UiHelpers + .formatWithPrecision( + publicIpPrice, + ), ], ), style: Theme.of(context) diff --git a/lib/utils/ui_helpers.dart b/lib/utils/ui_helpers.dart index f4d58a05..10f7419d 100644 --- a/lib/utils/ui_helpers.dart +++ b/lib/utils/ui_helpers.dart @@ -1,3 +1,4 @@ +import 'package:intl/intl.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; /// it's ui helpers use only for ui components, don't use for logic components. @@ -5,4 +6,14 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_ class UiHelpers { static String getDomainName(final ServerInstallationState config) => config.isDomainSelected ? config.serverDomain!.domainName : 'example.com'; + + static String formatWithPrecision( + final double value, { + final int fraction = 2, + }) { + final NumberFormat formatter = NumberFormat(); + formatter.minimumFractionDigits = 0; + formatter.maximumFractionDigits = fraction; + return formatter.format(value); + } } From f7afd6fd158b05929ca67d0a3f7b9c370ff3f11f Mon Sep 17 00:00:00 2001 From: NaiJi Date: Mon, 20 Nov 2023 03:32:41 +0400 Subject: [PATCH 3/4] fix(hetzner): Remove optional status enum for getVolumes of Hetzner --- .../server_providers/hetzner/hetzner_api.dart | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart index 5029561d..72df384b 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart @@ -360,20 +360,13 @@ class HetznerApi extends RestApiMap { return GenericResult(success: true, data: pricing); } - Future>> getVolumes({ - final String? status, - }) async { + Future>> getVolumes() async { final List volumes = []; Response? getVolumesResonse; final Dio client = await getClient(); try { - getVolumesResonse = await client.get( - '/volumes', - queryParameters: { - 'status': status, - }, - ); + getVolumesResonse = await client.get('/volumes'); for (final volume in getVolumesResonse.data['volumes']) { volumes.add(HetznerVolume.fromJson(volume)); } From cea2f6d8a488fdf0f554c6a64a13099225f8b4c3 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Mon, 20 Nov 2023 18:10:07 +0400 Subject: [PATCH 4/4] refactor: Correct a typo in Hetzner API --- .../server_providers/hetzner/hetzner_api.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart index 72df384b..37c825dc 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart @@ -363,11 +363,11 @@ class HetznerApi extends RestApiMap { Future>> getVolumes() async { final List volumes = []; - Response? getVolumesResonse; + Response? getVolumesResponse; final Dio client = await getClient(); try { - getVolumesResonse = await client.get('/volumes'); - for (final volume in getVolumesResonse.data['volumes']) { + getVolumesResponse = await client.get('/volumes'); + for (final volume in getVolumesResponse.data['volumes']) { volumes.add(HetznerVolume.fromJson(volume)); } } catch (e) { @@ -384,8 +384,8 @@ class HetznerApi extends RestApiMap { return GenericResult( data: volumes, success: true, - code: getVolumesResonse.statusCode, - message: getVolumesResonse.statusMessage, + code: getVolumesResponse.statusCode, + message: getVolumesResponse.statusMessage, ); }