diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7eefa66092..5db2ddac86 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -61,4 +61,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c -COCOAPODS: 1.10.1 +COCOAPODS: 1.11.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 94528fe7e8..b22b290ff6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -157,7 +157,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140cfdb..3db53b6e1f 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ ( (s) => regExp.hasMatch(s), 'validations.key_format'.tr()), LegnthStringValidationWithLenghShowing( - 40, 'validations.length'.tr(args: ["40"])) + 40, + 'validations.length'.tr( + args: ["40"], + ), + ) ], ); diff --git a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart index 26ee8593a1..141335750d 100644 --- a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:cubit_form/cubit_form.dart'; import 'package:selfprivacy/logic/api_maps/hetzner.dart'; -import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:easy_localization/easy_localization.dart'; diff --git a/lib/logic/cubit/jobs/jobs_cubit.dart b/lib/logic/cubit/jobs/jobs_cubit.dart index a2c1b41437..b093ba082a 100644 --- a/lib/logic/cubit/jobs/jobs_cubit.dart +++ b/lib/logic/cubit/jobs/jobs_cubit.dart @@ -37,7 +37,7 @@ class JobsCubit extends Cubit { emit(newState); } - void createOrRemoveServiceToggleJob(ServiceToggleJob job) { + void createOrRemoveServiceToggleJob(ToggleJob job) { var newJobsList = []; if (state is JobsStateWithJobs) { newJobsList.addAll((state as JobsStateWithJobs).jobList); diff --git a/lib/logic/cubit/services/services_cubit.dart b/lib/logic/cubit/services/services_cubit.dart index 5bbfcecc78..6d5dfef7f1 100644 --- a/lib/logic/cubit/services/services_cubit.dart +++ b/lib/logic/cubit/services/services_cubit.dart @@ -2,7 +2,6 @@ import 'package:hive/hive.dart'; import 'package:selfprivacy/config/hive_config.dart'; import 'package:selfprivacy/logic/api_maps/server.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart'; -import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; part 'services_state.dart'; diff --git a/lib/logic/models/backup.g.dart b/lib/logic/models/backup.g.dart index c1b50d036a..c784abe14a 100644 --- a/lib/logic/models/backup.g.dart +++ b/lib/logic/models/backup.g.dart @@ -6,46 +6,16 @@ part of 'backup.dart'; // JsonSerializableGenerator // ************************************************************************** -Backup _$BackupFromJson(Map json) { - return Backup( - time: DateTime.parse(json['time'] as String), - id: json['short_id'] as String, - ); -} - -BackupStatus _$BackupStatusFromJson(Map json) { - return BackupStatus( - status: _$enumDecode(_$BackupStatusEnumEnumMap, json['status']), - progress: (json['progress'] as num).toDouble(), - errorMessage: json['error_message'] as String?, - ); -} - -K _$enumDecode( - Map enumValues, - Object? source, { - K? unknownValue, -}) { - if (source == null) { - throw ArgumentError( - 'A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}', +Backup _$BackupFromJson(Map json) => Backup( + time: DateTime.parse(json['time'] as String), + id: json['short_id'] as String, ); - } - return enumValues.entries.singleWhere( - (e) => e.value == source, - orElse: () { - if (unknownValue == null) { - throw ArgumentError( - '`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}', - ); - } - return MapEntry(unknownValue, enumValues.values.first); - }, - ).key; -} +BackupStatus _$BackupStatusFromJson(Map json) => BackupStatus( + status: $enumDecode(_$BackupStatusEnumEnumMap, json['status']), + progress: (json['progress'] as num).toDouble(), + errorMessage: json['error_message'] as String?, + ); const _$BackupStatusEnumEnumMap = { BackupStatusEnum.noKey: 'NO_KEY', diff --git a/lib/logic/models/hetzner_server_info.g.dart b/lib/logic/models/hetzner_server_info.g.dart index 40055d1955..73e6be683e 100644 --- a/lib/logic/models/hetzner_server_info.g.dart +++ b/lib/logic/models/hetzner_server_info.g.dart @@ -6,42 +6,16 @@ part of 'hetzner_server_info.dart'; // JsonSerializableGenerator // ************************************************************************** -HetznerServerInfo _$HetznerServerInfoFromJson(Map json) { - return HetznerServerInfo( - json['id'] as int, - json['name'] as String, - _$enumDecode(_$ServerStatusEnumMap, json['status']), - DateTime.parse(json['created'] as String), - HetznerServerTypeInfo.fromJson(json['server_type'] as Map), - HetznerServerInfo.locationFromJson(json['datacenter'] as Map), - ); -} - -K _$enumDecode( - Map enumValues, - Object? source, { - K? unknownValue, -}) { - if (source == null) { - throw ArgumentError( - 'A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}', +HetznerServerInfo _$HetznerServerInfoFromJson(Map json) => + HetznerServerInfo( + json['id'] as int, + json['name'] as String, + $enumDecode(_$ServerStatusEnumMap, json['status']), + DateTime.parse(json['created'] as String), + HetznerServerTypeInfo.fromJson( + json['server_type'] as Map), + HetznerServerInfo.locationFromJson(json['datacenter'] as Map), ); - } - - return enumValues.entries.singleWhere( - (e) => e.value == source, - orElse: () { - if (unknownValue == null) { - throw ArgumentError( - '`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}', - ); - } - return MapEntry(unknownValue, enumValues.values.first); - }, - ).key; -} const _$ServerStatusEnumMap = { ServerStatus.running: 'running', @@ -56,29 +30,26 @@ const _$ServerStatusEnumMap = { }; HetznerServerTypeInfo _$HetznerServerTypeInfoFromJson( - Map json) { - return HetznerServerTypeInfo( - json['cores'] as int, - json['memory'] as num, - json['disk'] as int, - (json['prices'] as List) - .map((e) => HetznerPriceInfo.fromJson(e as Map)) - .toList(), - ); -} + Map json) => + HetznerServerTypeInfo( + json['cores'] as int, + json['memory'] as num, + json['disk'] as int, + (json['prices'] as List) + .map((e) => HetznerPriceInfo.fromJson(e as Map)) + .toList(), + ); -HetznerPriceInfo _$HetznerPriceInfoFromJson(Map json) { - return HetznerPriceInfo( - HetznerPriceInfo.getPrice(json['price_hourly'] as Map), - HetznerPriceInfo.getPrice(json['price_monthly'] as Map), - ); -} +HetznerPriceInfo _$HetznerPriceInfoFromJson(Map json) => + HetznerPriceInfo( + HetznerPriceInfo.getPrice(json['price_hourly'] as Map), + HetznerPriceInfo.getPrice(json['price_monthly'] as Map), + ); -HetznerLocation _$HetznerLocationFromJson(Map json) { - return HetznerLocation( - json['country'] as String, - json['city'] as String, - json['description'] as String, - json['network_zone'] as String, - ); -} +HetznerLocation _$HetznerLocationFromJson(Map json) => + HetznerLocation( + json['country'] as String, + json['city'] as String, + json['description'] as String, + json['network_zone'] as String, + ); diff --git a/lib/logic/models/job.dart b/lib/logic/models/job.dart index e976780316..70d238a914 100644 --- a/lib/logic/models/job.dart +++ b/lib/logic/models/job.dart @@ -42,19 +42,29 @@ class DeleteUserJob extends Job { List get props => [id, title, user]; } -class ServiceToggleJob extends Job { - ServiceToggleJob({ +class ToggleJob extends Job { + ToggleJob({ required this.type, - required this.needToTurnOn, - }) : super( - title: - '${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}'); + required String title, + }) : super(title: title); - final ServiceTypes type; - final bool needToTurnOn; + final dynamic type; @override - List get props => [id, title, type, needToTurnOn]; + List get props => [...super.props, type]; +} + +class ServiceToggleJob extends ToggleJob { + ServiceToggleJob({ + required ServiceTypes type, + required this.needToTurnOn, + }) : super( + title: + '${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}', + type: type, + ); + + final bool needToTurnOn; } class CreateSSHKeyJob extends Job { diff --git a/lib/logic/models/server_configurations.dart b/lib/logic/models/server_configurations.dart new file mode 100644 index 0000000000..7391556673 --- /dev/null +++ b/lib/logic/models/server_configurations.dart @@ -0,0 +1,22 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'server_configurations.g.dart'; + +@JsonSerializable(createToJson: true) +class AutoUpgradeConfigurations extends Equatable { + const AutoUpgradeConfigurations({ + required this.enable, + required this.allowReboot, + }); + + final bool enable; + final bool allowReboot; + + factory AutoUpgradeConfigurations.fromJson(Map json) => + _$AutoUpgradeConfigurationsFromJson(json); + Map toJson() => _$AutoUpgradeConfigurationsToJson(this); + + @override + List get props => [enable, allowReboot]; +} diff --git a/lib/logic/models/server_configurations.g.dart b/lib/logic/models/server_configurations.g.dart new file mode 100644 index 0000000000..a198ae2e2e --- /dev/null +++ b/lib/logic/models/server_configurations.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'server_configurations.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AutoUpgradeConfigurations _$AutoUpgradeConfigurationsFromJson( + Map json) => + AutoUpgradeConfigurations( + enable: json['enable'] as bool, + allowReboot: json['allowReboot'] as bool, + ); + +Map _$AutoUpgradeConfigurationsToJson( + AutoUpgradeConfigurations instance) => + { + 'enable': instance.enable, + 'allowReboot': instance.allowReboot, + }; diff --git a/lib/logic/models/server_timezone.dart b/lib/logic/models/server_timezone.dart new file mode 100644 index 0000000000..7c592bd945 --- /dev/null +++ b/lib/logic/models/server_timezone.dart @@ -0,0 +1,18 @@ +import 'package:equatable/equatable.dart'; +import 'package:timezone/timezone.dart'; + +class ServerTimezone extends Equatable { + final Location timezone; + + const ServerTimezone({required this.timezone}); + + factory ServerTimezone.fromJson(Map json) { + var timezone = getLocation(json['timezone']); + return ServerTimezone(timezone: timezone); + } + + Map toJson() => {'timezone': timezone.name}; + + @override + List get props => [timezone.name]; +} diff --git a/lib/main.dart b/lib/main.dart index 028291d263..d73d51bba3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:selfprivacy/ui/pages/rootRoute.dart'; import 'package:wakelock/wakelock.dart'; +import 'package:timezone/data/latest.dart' as tz; import 'config/bloc_config.dart'; import 'config/bloc_observer.dart'; @@ -19,12 +20,15 @@ void main() async { WidgetsFlutterBinding.ensureInitialized(); await HiveConfig.init(); await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - Bloc.observer = SimpleBlocObserver(); Wakelock.enable(); await getItSetup(); await EasyLocalization.ensureInitialized(); + tz.initializeTimeZones(); - runApp(MyApp()); + BlocOverrides.runZoned( + () => runApp(Localization(child: MyApp())), + blocObserver: SimpleBlocObserver(), + ); } class MyApp extends StatelessWidget { diff --git a/lib/ui/components/brand_loader/brand_loader.dart b/lib/ui/components/brand_loader/brand_loader.dart index 52b1b820d8..9cd5b5712b 100644 --- a/lib/ui/components/brand_loader/brand_loader.dart +++ b/lib/ui/components/brand_loader/brand_loader.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; diff --git a/lib/ui/components/jobs_content/jobs_content.dart b/lib/ui/components/jobs_content/jobs_content.dart index 8f7663554b..92298a066f 100644 --- a/lib/ui/components/jobs_content/jobs_content.dart +++ b/lib/ui/components/jobs_content/jobs_content.dart @@ -5,7 +5,6 @@ import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; -import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; import 'package:selfprivacy/ui/components/action_button/action_button.dart'; import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; diff --git a/lib/ui/pages/initializing/initializing.dart b/lib/ui/pages/initializing/initializing.dart index 958637e367..33802be66c 100644 --- a/lib/ui/pages/initializing/initializing.dart +++ b/lib/ui/pages/initializing/initializing.dart @@ -1,7 +1,5 @@ import 'package:cubit_form/cubit_form.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/initializing/cloudflare_form_cubit.dart'; @@ -9,7 +7,6 @@ import 'package:selfprivacy/logic/cubit/forms/initializing/domain_cloudflare.dar import 'package:selfprivacy/logic/cubit/forms/initializing/hetzner_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/initializing/root_user_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; -import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; diff --git a/lib/ui/pages/more/console/console.dart b/lib/ui/pages/more/console/console.dart index 5b89ee87a7..2e129f7924 100644 --- a/lib/ui/pages/more/console/console.dart +++ b/lib/ui/pages/more/console/console.dart @@ -3,7 +3,6 @@ import 'dart:collection'; import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/get_it_config.dart'; -import 'package:selfprivacy/logic/get_it/console.dart'; import 'package:selfprivacy/logic/models/message.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; diff --git a/lib/ui/pages/providers/providers.dart b/lib/ui/pages/providers/providers.dart index 3d04290a9f..ed9e2ebc84 100644 --- a/lib/ui/pages/providers/providers.dart +++ b/lib/ui/pages/providers/providers.dart @@ -2,10 +2,8 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart'; -import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart'; import 'package:selfprivacy/logic/models/provider.dart'; -import 'package:selfprivacy/logic/models/state_types.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; diff --git a/lib/ui/pages/providers/settings/settings.dart b/lib/ui/pages/providers/settings/settings.dart index 04a71ab190..ad3fdfa125 100644 --- a/lib/ui/pages/providers/settings/settings.dart +++ b/lib/ui/pages/providers/settings/settings.dart @@ -1,122 +1,116 @@ -import 'package:flutter/material.dart'; -import 'package:selfprivacy/config/brand_colors.dart'; -import 'package:selfprivacy/config/brand_theme.dart'; -import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; -import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; -import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; -import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; -import 'package:easy_localization/easy_localization.dart'; +// import 'package:flutter/material.dart'; +// import 'package:selfprivacy/config/brand_colors.dart'; +// import 'package:selfprivacy/config/brand_theme.dart'; +// import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; +// import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; +// import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; +// import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; +// import 'package:easy_localization/easy_localization.dart'; +// import 'package:selfprivacy/ui/pages/providers/settings/time_zone.dart'; +// import 'package:selfprivacy/utils/route_transitions/basic.dart'; -class SettingsPage extends StatelessWidget { - const SettingsPage({Key? key}) : super(key: key); +// class SettingsPage extends StatelessWidget { +// const SettingsPage({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return ListView( - padding: paddingH15V0, - children: [ - SizedBox(height: 10), - BrandHeader(title: 'basis.settings'.tr(), hasBackButton: true), - BrandDivider(), - SwitcherBlock( - onChange: (_) {}, - child: _TextColumn( - title: 'Allow Auto-upgrade', - value: 'Wether to allow automatic packages upgrades', - ), - isActive: true, - ), - SwitcherBlock( - onChange: (_) {}, - child: _TextColumn( - title: 'Reboot after upgrade', - value: 'Reboot without prompt after applying updates', - ), - isActive: false, - ), - _Button( - onTap: () {}, - child: _TextColumn( - title: 'Server Timezone', - value: 'Europe/Kyiv', - ), - ), - _Button( - onTap: () {}, - child: _TextColumn( - title: 'Server Locale', - value: 'Default', - ), - ), - _Button( - onTap: () {}, - child: _TextColumn( - hasWarning: true, - title: 'Factory Reset', - value: 'Restore default settings on your server', - ), - ) - ], - ); - } -} +// @override +// Widget build(BuildContext context) { +// return ListView( +// padding: paddingH15V0, +// children: [ +// SizedBox(height: 10), +// BrandHeader(title: 'basis.settings'.tr(), hasBackButton: true), +// BrandDivider(), +// SwitcherBlock( +// onChange: (_) {}, +// child: _TextColumn( +// title: 'Allow Auto-upgrade', +// value: 'Wether to allow automatic packages upgrades', +// ), +// isActive: true, +// ), +// SwitcherBlock( +// onChange: (_) {}, +// child: _TextColumn( +// title: 'Reboot after upgrade', +// value: 'Reboot without prompt after applying updates', +// ), +// isActive: false, +// ), +// _Button( +// onTap: () { +// print('aaa'); +// Navigator.of(context).push( +// materialRoute( +// SelectTimezone(), +// ), +// ); +// }, +// child: _TextColumn( +// title: 'Server Timezone', +// value: 'Europe/Kyssiv', +// ), +// ), +// ], +// ); +// } +// } -class _Button extends StatelessWidget { - const _Button({ - Key? key, - required this.onTap, - required this.child, - }) : super(key: key); +// class _Button extends StatelessWidget { +// const _Button({ +// Key? key, +// required this.onTap, +// required this.child, +// }) : super(key: key); - final Widget child; - final VoidCallback onTap; +// final Widget child; +// final VoidCallback onTap; - @override - Widget build(BuildContext context) { - return InkWell( - onTap: onTap, - child: Container( - padding: EdgeInsets.only(top: 20, bottom: 5), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(width: 1, color: BrandColors.dividerColor), - )), - child: child, - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// return InkWell( +// onTap: onTap, +// child: Container( +// padding: EdgeInsets.only(top: 20, bottom: 5), +// decoration: BoxDecoration( +// border: Border( +// bottom: BorderSide(width: 1, color: BrandColors.dividerColor), +// )), +// child: child, +// ), +// ); +// } +// } -class _TextColumn extends StatelessWidget { - const _TextColumn({ - Key? key, - required this.title, - required this.value, - this.hasWarning = false, - }) : super(key: key); +// class _TextColumn extends StatelessWidget { +// const _TextColumn({ +// Key? key, +// required this.title, +// required this.value, +// this.hasWarning = false, +// }) : super(key: key); - final String title; - final String value; - final bool hasWarning; - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - BrandText.body1( - title, - style: TextStyle(color: hasWarning ? BrandColors.warning : null), - ), - SizedBox(height: 5), - BrandText.body1( - value, - style: TextStyle( - fontSize: 13, - height: 1.53, - color: hasWarning ? BrandColors.warning : BrandColors.gray1, - ), - ), - ], - ); - } -} +// final String title; +// final String value; +// final bool hasWarning; +// @override +// Widget build(BuildContext context) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// BrandText.body1( +// title, +// style: TextStyle(color: hasWarning ? BrandColors.warning : null), +// ), +// SizedBox(height: 5), +// BrandText.body1( +// value, +// style: TextStyle( +// fontSize: 13, +// height: 1.53, +// color: hasWarning ? BrandColors.warning : BrandColors.gray1, +// ), +// ), +// ], +// ); +// } +// } diff --git a/lib/ui/pages/rootRoute.dart b/lib/ui/pages/rootRoute.dart index 426c36279d..dfa3a7a28e 100644 --- a/lib/ui/pages/rootRoute.dart +++ b/lib/ui/pages/rootRoute.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart'; diff --git a/lib/ui/pages/server_details/server_details.dart b/lib/ui/pages/server_details/server_details.dart index 06d6d376f5..fe771950e0 100644 --- a/lib/ui/pages/server_details/server_details.dart +++ b/lib/ui/pages/server_details/server_details.dart @@ -8,6 +8,7 @@ import 'package:selfprivacy/logic/cubit/hetzner_metrics/hetzner_metrics_cubit.da import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart'; import 'package:selfprivacy/logic/models/state_types.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; +import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_radio_tile/brand_radio_tile.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; @@ -15,13 +16,17 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart import 'package:easy_localization/easy_localization.dart'; import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; import 'package:selfprivacy/utils/named_font_weight.dart'; +import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:timezone/timezone.dart'; import 'cpu_chart.dart'; import 'network_charts.dart'; +import 'package:selfprivacy/utils/extensions/duration.dart'; part 'server_settings.dart'; part 'text_details.dart'; part 'chart.dart'; part 'header.dart'; +part 'time_zone.dart'; var navigatorKey = GlobalKey(); diff --git a/lib/ui/pages/server_details/server_settings.dart b/lib/ui/pages/server_details/server_settings.dart index 6e2ed6b143..bde17e8433 100644 --- a/lib/ui/pages/server_details/server_settings.dart +++ b/lib/ui/pages/server_details/server_settings.dart @@ -49,27 +49,14 @@ class _ServerSettings extends StatelessWidget { isActive: false, ), _Button( - onTap: () {}, + onTap: () { + Navigator.of(context).push(materialRoute(SelectTimezone())); + }, child: _TextColumn( title: 'Server Timezone', value: 'Europe/Kyiv', ), ), - _Button( - onTap: () {}, - child: _TextColumn( - title: 'Server Locale', - value: 'Default', - ), - ), - _Button( - onTap: () {}, - child: _TextColumn( - hasWarning: true, - title: 'Factory Reset', - value: 'Restore default settings on your server', - ), - ) ], ); } diff --git a/lib/ui/pages/server_details/time_zone.dart b/lib/ui/pages/server_details/time_zone.dart new file mode 100644 index 0000000000..26f1e14bca --- /dev/null +++ b/lib/ui/pages/server_details/time_zone.dart @@ -0,0 +1,92 @@ +part of 'server_details.dart'; + +final List locations = timeZoneDatabase.locations.values.toList() + ..sort((l1, l2) => + l1.currentTimeZone.offset.compareTo(l2.currentTimeZone.offset)); + +class SelectTimezone extends StatefulWidget { + SelectTimezone({Key? key}) : super(key: key); + + @override + _SelectTimezoneState createState() => _SelectTimezoneState(); +} + +class _SelectTimezoneState extends State { + final ScrollController controller = ScrollController(); + + @override + void initState() { + WidgetsBinding.instance!.addPostFrameCallback(_afterLayout); + super.initState(); + } + + void _afterLayout(_) { + var t = DateTime.now().timeZoneOffset; + var index = locations.indexWhere((element) => + Duration(milliseconds: element.currentTimeZone.offset) == t); + if (index >= 0) { + controller.animateTo(40.0 * index, + duration: Duration(milliseconds: 300), curve: Curves.easeIn); + } + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + child: BrandHeader( + title: 'select timezone', + hasBackButton: true, + ), + preferredSize: Size.fromHeight(52), + ), + body: ListView( + controller: controller, + children: locations + .asMap() + .map((key, value) { + var duration = + Duration(milliseconds: value.currentTimeZone.offset); + var area = value.currentTimeZone.abbreviation + .replaceAll(RegExp(r'[\d+()-]'), ''); + return MapEntry( + key, + Container( + height: 40, + padding: EdgeInsets.symmetric(horizontal: 20), + alignment: Alignment.center, + child: Row( + children: [ + Expanded( + flex: 1, + child: Text( + '${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}'), + ), + Expanded( + flex: 2, + child: Text(value.name), + ), + // Text(value.toString()), + ], + ), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: BrandColors.dividerColor, + )), + ), + ), + ); + }) + .values + .toList(), + ), + ); + } +} diff --git a/lib/utils/extensions/duration.dart b/lib/utils/extensions/duration.dart new file mode 100644 index 0000000000..a81627c060 --- /dev/null +++ b/lib/utils/extensions/duration.dart @@ -0,0 +1,41 @@ +// ignore_for_file: unnecessary_this + +extension DurationFormatter on Duration { + String toDayHourMinuteSecondFormat() { + return [ + this.inHours.remainder(24), + this.inMinutes.remainder(60), + this.inSeconds.remainder(60) + ].map((seg) { + return seg.toString().padLeft(2, '0'); + }).join(':'); + } + + String toDayHourMinuteFormat() { + var designator = this >= Duration.zero ? '+' : '-'; + + var segments = [ + this.inHours.remainder(24).abs(), + this.inMinutes.remainder(60).abs(), + ].map((seg) { + return seg.toString().padLeft(2, '0'); + }); + + return '$designator${segments.first}:${segments.last}'; + } + + String toHoursMinutesSecondsFormat() { + // WAT: https://flutterigniter.com/how-to-format-duration/ + return this.toString().split('.').first.padLeft(8, "0"); + } + + String toDayHourMinuteFormat2() { + var segments = [ + this.inHours.remainder(24), + this.inMinutes.remainder(60), + ].map((seg) { + return seg.toString().padLeft(2, '0'); + }); + return segments.first + " h" + " " + segments.last + " min"; + } +} diff --git a/lib/utils/extensions/text_extensions.dart b/lib/utils/extensions/text_extensions.dart index 7e378d0cfe..26932a110a 100644 --- a/lib/utils/extensions/text_extensions.dart +++ b/lib/utils/extensions/text_extensions.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:flutter/cupertino.dart'; extension TextExtension on Text { diff --git a/pubspec.lock b/pubspec.lock index f4a8a3976c..692fbbce87 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "22.0.0" + version: "31.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "1.7.2" + version: "2.8.0" archive: dependency: transitive description: @@ -28,7 +28,7 @@ packages: name: args url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.0.0" asn1lib: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" auto_size_text: dependency: "direct main" description: @@ -56,14 +56,14 @@ packages: name: basic_utils url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.4.0" bloc: dependency: transitive description: name: bloc url: "https://pub.dartlang.org" source: hosted - version: "7.2.1" + version: "8.0.2" boolean_selector: dependency: transitive description: @@ -105,14 +105,14 @@ packages: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.5" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "7.1.0" + version: "7.2.3" built_collection: dependency: transitive description: @@ -133,7 +133,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -210,14 +210,14 @@ packages: name: cubit_form url: "https://pub.dartlang.org" source: hosted - version: "1.0.18" + version: "2.0.1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.2" dart_style: dependency: transitive description: @@ -231,7 +231,7 @@ packages: name: dio url: "https://pub.dartlang.org" source: hosted - version: "4.0.0" + version: "4.0.1" easy_localization: dependency: "direct main" description: @@ -267,13 +267,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.3" - extended_masked_text: - dependency: transitive - description: - name: extended_masked_text - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.1" fake_async: dependency: transitive description: @@ -320,14 +313,14 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "7.3.3" + version: "8.0.1" flutter_launcher_icons: dependency: "direct dev" description: name: flutter_launcher_icons url: "https://pub.dartlang.org" source: hosted - version: "0.9.2" + version: "0.9.0" flutter_localizations: dependency: transitive description: flutter @@ -339,7 +332,7 @@ packages: name: flutter_markdown url: "https://pub.dartlang.org" source: hosted - version: "0.6.5" + version: "0.6.9" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -398,7 +391,7 @@ packages: name: hive url: "https://pub.dartlang.org" source: hosted - version: "2.0.4" + version: "2.0.5" hive_flutter: dependency: "direct main" description: @@ -412,7 +405,7 @@ packages: name: hive_generator url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" http: dependency: transitive description: @@ -475,14 +468,14 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "4.0.1" + version: "4.3.0" json_serializable: dependency: "direct dev" description: name: json_serializable url: "https://pub.dartlang.org" source: hosted - version: "4.1.4" + version: "6.0.1" local_auth: dependency: "direct main" description: @@ -504,13 +497,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.0" + mask_text_input_formatter: + dependency: transitive + description: + name: mask_text_input_formatter + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: @@ -566,7 +566,7 @@ packages: name: package_info url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.0" path: dependency: transitive description: @@ -830,7 +830,7 @@ packages: name: source_helper url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.3.1" source_map_stack_trace: dependency: transitive description: @@ -900,21 +900,28 @@ packages: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.17.10" + version: "1.17.12" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.4.0" + version: "0.4.2" + timezone: + dependency: "direct main" + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" timing: dependency: transitive description: @@ -942,7 +949,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.9" + version: "6.0.2" url_launcher_linux: dependency: transitive description: @@ -984,7 +991,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" vm_service: dependency: transitive description: @@ -998,7 +1005,7 @@ packages: name: wakelock url: "https://pub.dartlang.org" source: hosted - version: "0.5.3+3" + version: "0.5.0+2" wakelock_macos: dependency: transitive description: @@ -1077,5 +1084,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.13.4 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 88a6a95df8..dc7210d6a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,46 +8,47 @@ environment: flutter: ">=2.5.0" dependencies: + auto_size_text: 3.0.0-nullsafety.0 + basic_utils: 3.4.0 + crypt: 4.0.1 + cubit_form: 2.0.1 + cupertino_icons: 1.0.2 + dio: 4.0.1 + easy_localization: 3.0.0 + either_option: 2.0.1-dev.1 + equatable: 2.0.3 + fl_chart: 0.40.0 flutter: sdk: flutter - crypt: ^4.0.1 - cubit_form: ^1.0.0-nullsafety.0 - cupertino_icons: ^1.0.2 - dio: ^4.0.0-beta7 - easy_localization: ^3.0.0 - either_option: ^2.0.1-dev.1 - equatable: ^2.0.3 - fl_chart: ^0.40.0 - flutter_bloc: ^7.3.3 - flutter_markdown: ^0.6.0 - flutter_secure_storage: ^4.1.0 - get_it: ^7.2.0 - hive: ^2.0.0 - hive_flutter: ^1.0.0 - json_annotation: ^4.0.0 - modal_bottom_sheet: ^2.0.0 - nanoid: ^1.0.0 - package_info: ^2.0.0 - pretty_dio_logger: ^1.1.1 - provider: ^6.0.0 - share_plus: ^2.1.4 - url_launcher: ^6.0.2 - wakelock: ^0.5.0+2 - basic_utils: ^3.4.0 - ionicons: ^0.1.2 - pointycastle: ^3.3.2 - rsa_encrypt: ^2.0.0 - ssh_key: ^0.7.0 - local_auth: ^1.1.7 - auto_size_text: ^3.0.0-nullsafety.0 + flutter_bloc: 8.0.1 + flutter_markdown: 0.6.9 + flutter_secure_storage: 4.2.1 + get_it: 7.2.0 + hive: 2.0.5 + hive_flutter: 1.1.0 + ionicons: 0.1.2 + json_annotation: 4.3.0 + local_auth: 1.1.7 + modal_bottom_sheet: 2.0.0 + nanoid: 1.0.0 + package_info: 2.0.0 + pointycastle: 3.3.2 + pretty_dio_logger: 1.2.0-beta-1 + provider: 6.0.0 + rsa_encrypt: 2.0.0 + share_plus: 2.1.4 + ssh_key: 0.7.0 + timezone: ^0.8.0 + url_launcher: 6.0.2 + wakelock: 0.5.0+2 dev_dependencies: + build_runner: 2.1.5 + flutter_launcher_icons: 0.9.0 flutter_test: sdk: flutter - build_runner: ^2.1.1 - flutter_launcher_icons: ^0.9.0 - hive_generator: ^1.0.0 - json_serializable: ^4.0.2 + hive_generator: 1.1.1 + json_serializable: 6.0.1 flutter_icons: android: "launcher_icon"