From fe820ef5bed4edea51fa896681cd0c61b991c9fc Mon Sep 17 00:00:00 2001 From: NaiJi Date: Sat, 15 Oct 2022 19:49:31 +0000 Subject: [PATCH] feat(initializing): Implement location selection step for initializing page --- .../server_installation_cubit.dart | 15 +++ .../server_installation_state.dart | 73 ++++++----- .../setup/initializing/initializing.dart | 18 ++- ...icker.dart => server_provider_picker.dart} | 8 +- .../initializing/server_type_picker.dart | 118 ++++++++++++++++++ 5 files changed, 194 insertions(+), 38 deletions(-) rename lib/ui/pages/setup/initializing/{provider_picker.dart => server_provider_picker.dart} (96%) create mode 100644 lib/ui/pages/setup/initializing/server_type_picker.dart diff --git a/lib/logic/cubit/server_installation/server_installation_cubit.dart b/lib/logic/cubit/server_installation/server_installation_cubit.dart index 99dd1d82..84410468 100644 --- a/lib/logic/cubit/server_installation/server_installation_cubit.dart +++ b/lib/logic/cubit/server_installation/server_installation_cubit.dart @@ -16,6 +16,8 @@ import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_repository.dart'; +import 'package:selfprivacy/logic/models/server_provider_location.dart'; +import 'package:selfprivacy/logic/models/server_type.dart'; export 'package:provider/provider.dart'; @@ -93,6 +95,19 @@ class ServerInstallationCubit extends Cubit { ) .isApiTokenValid(providerToken); + Future> fetchAvailableLocations() async { + if (repository.serverProviderApiFactory == null) { + return []; + } + + return repository.serverProviderApiFactory! + .getServerProvider( + settings: const ServerProviderApiSettings(region: 'fra1'), + ) + .getAvailableLocations(); + } + + void setServerProviderKey(final String serverProviderKey) async { await repository.saveServerProviderKey(serverProviderKey); diff --git a/lib/logic/cubit/server_installation/server_installation_state.dart b/lib/logic/cubit/server_installation/server_installation_state.dart index 82eda971..1a130baf 100644 --- a/lib/logic/cubit/server_installation/server_installation_state.dart +++ b/lib/logic/cubit/server_installation/server_installation_state.dart @@ -3,6 +3,7 @@ part of '../server_installation/server_installation_cubit.dart'; abstract class ServerInstallationState extends Equatable { const ServerInstallationState({ required this.providerApiToken, + required this.serverType, required this.cloudFlareKey, required this.backblazeCredential, required this.serverDomain, @@ -31,11 +32,13 @@ abstract class ServerInstallationState extends Equatable { final ServerDomain? serverDomain; final User? rootUser; final ServerHostingDetails? serverDetails; + final ServerType? serverType; final bool isServerStarted; final bool isServerResetedFirstTime; final bool isServerResetedSecondTime; - bool get isServerProviderFilled => providerApiToken != null; + bool get isServerProviderApiKeyFilled => providerApiToken != null; + bool get isServerTypeFilled => serverType != null; bool get isDnsProviderFilled => cloudFlareKey != null; bool get isBackupsProviderFilled => backblazeCredential != null; bool get isDomainSelected => serverDomain != null; @@ -58,7 +61,8 @@ abstract class ServerInstallationState extends Equatable { List get _fulfilementList { final List res = [ - isServerProviderFilled, + isServerProviderApiKeyFilled, + isServerTypeFilled, isDnsProviderFilled, isBackupsProviderFilled, isDomainSelected, @@ -76,11 +80,12 @@ abstract class ServerInstallationState extends Equatable { class TimerState extends ServerInstallationNotFinished { TimerState({ required this.dataState, - required final super.isLoading, + required super.isLoading, this.timerStart, this.duration, }) : super( providerApiToken: dataState.providerApiToken, + serverType: dataState.serverType, cloudFlareKey: dataState.cloudFlareKey, backblazeCredential: dataState.backblazeCredential, serverDomain: dataState.serverDomain, @@ -119,17 +124,18 @@ enum ServerSetupProgress { class ServerInstallationNotFinished extends ServerInstallationState { const ServerInstallationNotFinished({ - required final super.isServerStarted, - required final super.isServerResetedFirstTime, - required final super.isServerResetedSecondTime, - required final this.isLoading, + required super.isServerStarted, + required super.isServerResetedFirstTime, + required super.isServerResetedSecondTime, + required this.isLoading, required this.dnsMatches, - final super.providerApiToken, - final super.cloudFlareKey, - final super.backblazeCredential, - final super.serverDomain, - final super.rootUser, - final super.serverDetails, + super.providerApiToken, + super.serverType, + super.cloudFlareKey, + super.backblazeCredential, + super.serverDomain, + super.rootUser, + super.serverDetails, }); final bool isLoading; final Map? dnsMatches; @@ -137,6 +143,7 @@ class ServerInstallationNotFinished extends ServerInstallationState { @override List get props => [ providerApiToken, + serverType, cloudFlareKey, backblazeCredential, serverDomain, @@ -150,6 +157,7 @@ class ServerInstallationNotFinished extends ServerInstallationState { ServerInstallationNotFinished copyWith({ final String? providerApiToken, + final ServerType? serverType, final String? cloudFlareKey, final BackblazeCredential? backblazeCredential, final ServerDomain? serverDomain, @@ -163,6 +171,7 @@ class ServerInstallationNotFinished extends ServerInstallationState { }) => ServerInstallationNotFinished( providerApiToken: providerApiToken ?? this.providerApiToken, + serverType: serverType ?? this.serverType, cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey, backblazeCredential: backblazeCredential ?? this.backblazeCredential, serverDomain: serverDomain ?? this.serverDomain, @@ -179,6 +188,7 @@ class ServerInstallationNotFinished extends ServerInstallationState { ServerInstallationFinished finish() => ServerInstallationFinished( providerApiToken: providerApiToken!, + serverType: serverType!, cloudFlareKey: cloudFlareKey!, backblazeCredential: backblazeCredential!, serverDomain: serverDomain!, @@ -209,20 +219,22 @@ class ServerInstallationEmpty extends ServerInstallationNotFinished { class ServerInstallationFinished extends ServerInstallationState { const ServerInstallationFinished({ - required final String super.providerApiToken, - required final String super.cloudFlareKey, - required final BackblazeCredential super.backblazeCredential, - required final ServerDomain super.serverDomain, - required final User super.rootUser, - required final ServerHostingDetails super.serverDetails, - required final super.isServerStarted, - required final super.isServerResetedFirstTime, - required final super.isServerResetedSecondTime, + required String super.providerApiToken, + required ServerType super.serverType, + required String super.cloudFlareKey, + required BackblazeCredential super.backblazeCredential, + required ServerDomain super.serverDomain, + required User super.rootUser, + required ServerHostingDetails super.serverDetails, + required super.isServerStarted, + required super.isServerResetedFirstTime, + required super.isServerResetedSecondTime, }); @override List get props => [ providerApiToken, + serverType, cloudFlareKey, backblazeCredential, serverDomain, @@ -260,12 +272,13 @@ class ServerInstallationRecovery extends ServerInstallationState { const ServerInstallationRecovery({ required this.currentStep, required this.recoveryCapabilities, - final super.providerApiToken, - final super.cloudFlareKey, - final super.backblazeCredential, - final super.serverDomain, - final super.rootUser, - final super.serverDetails, + super.providerApiToken, + super.serverType, + super.cloudFlareKey, + super.backblazeCredential, + super.serverDomain, + super.rootUser, + super.serverDetails, }) : super( isServerStarted: true, isServerResetedFirstTime: true, @@ -277,6 +290,7 @@ class ServerInstallationRecovery extends ServerInstallationState { @override List get props => [ providerApiToken, + serverType, cloudFlareKey, backblazeCredential, serverDomain, @@ -289,6 +303,7 @@ class ServerInstallationRecovery extends ServerInstallationState { ServerInstallationRecovery copyWith({ final String? providerApiToken, + final ServerType? serverType, final String? cloudFlareKey, final BackblazeCredential? backblazeCredential, final ServerDomain? serverDomain, @@ -299,6 +314,7 @@ class ServerInstallationRecovery extends ServerInstallationState { }) => ServerInstallationRecovery( providerApiToken: providerApiToken ?? this.providerApiToken, + serverType: serverType ?? this.serverType, cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey, backblazeCredential: backblazeCredential ?? this.backblazeCredential, serverDomain: serverDomain ?? this.serverDomain, @@ -310,6 +326,7 @@ class ServerInstallationRecovery extends ServerInstallationState { ServerInstallationFinished finish() => ServerInstallationFinished( providerApiToken: providerApiToken!, + serverType: serverType!, cloudFlareKey: cloudFlareKey!, backblazeCredential: backblazeCredential!, serverDomain: serverDomain!, diff --git a/lib/ui/pages/setup/initializing/initializing.dart b/lib/ui/pages/setup/initializing/initializing.dart index 2904cfb8..a211588b 100644 --- a/lib/ui/pages/setup/initializing/initializing.dart +++ b/lib/ui/pages/setup/initializing/initializing.dart @@ -7,7 +7,6 @@ import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cubit.dart'; -import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; @@ -17,13 +16,14 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart'; import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart'; import 'package:selfprivacy/ui/pages/root_route.dart'; -import 'package:selfprivacy/ui/pages/setup/initializing/provider_picker.dart'; +import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart'; +import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart'; import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; class InitializingPage extends StatelessWidget { const InitializingPage({ - final super.key, + super.key, }); @override @@ -36,7 +36,8 @@ class InitializingPage extends StatelessWidget { Widget? actualInitializingPage; if (cubit.state is! ServerInstallationFinished) { actualInitializingPage = [ - () => _stepHetzner(cubit), + () => _stepServerProviderToken(cubit), + () => _stepServerType(cubit), () => _stepCloudflare(cubit), () => _stepBackblaze(cubit), () => _stepDomain(cubit), @@ -139,11 +140,16 @@ class InitializingPage extends StatelessWidget { } } - Widget _stepHetzner(final ServerInstallationCubit serverInstallationCubit) => - ProviderPicker( + Widget _stepServerProviderToken(final ServerInstallationCubit serverInstallationCubit) => + ServerProviderPicker( serverInstallationCubit: serverInstallationCubit, ); + Widget _stepServerType(final ServerInstallationCubit serverInstallationCubit) => + ServerTypePicker( + serverInstallationCubit: serverInstallationCubit, + ); + void _showModal(final BuildContext context, final Widget widget) { showModalBottomSheet( context: context, diff --git a/lib/ui/pages/setup/initializing/provider_picker.dart b/lib/ui/pages/setup/initializing/server_provider_picker.dart similarity index 96% rename from lib/ui/pages/setup/initializing/provider_picker.dart rename to lib/ui/pages/setup/initializing/server_provider_picker.dart index 6681a07b..ee0ab36a 100644 --- a/lib/ui/pages/setup/initializing/provider_picker.dart +++ b/lib/ui/pages/setup/initializing/server_provider_picker.dart @@ -9,8 +9,8 @@ import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet. import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; -class ProviderPicker extends StatefulWidget { - const ProviderPicker({ +class ServerProviderPicker extends StatefulWidget { + const ServerProviderPicker({ required this.serverInstallationCubit, super.key, }); @@ -18,10 +18,10 @@ class ProviderPicker extends StatefulWidget { final ServerInstallationCubit serverInstallationCubit; @override - State createState() => _ProviderPickerState(); + State createState() => _ServerProviderPickerState(); } -class _ProviderPickerState extends State { +class _ServerProviderPickerState extends State { ServerProvider selectedProvider = ServerProvider.unknown; void setProvider(final ServerProvider provider) { diff --git a/lib/ui/pages/setup/initializing/server_type_picker.dart b/lib/ui/pages/setup/initializing/server_type_picker.dart new file mode 100644 index 00000000..3dd7d3c9 --- /dev/null +++ b/lib/ui/pages/setup/initializing/server_type_picker.dart @@ -0,0 +1,118 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; +import 'package:selfprivacy/logic/models/hive/server_details.dart'; +import 'package:selfprivacy/logic/models/server_provider_location.dart'; + +class ServerTypePicker extends StatefulWidget { + const ServerTypePicker({ + required this.serverInstallationCubit, + super.key, + }); + + final ServerInstallationCubit serverInstallationCubit; + + @override + State createState() => _ServerTypePickerState(); +} + +class _ServerTypePickerState extends State { + ServerProviderLocation? serverProviderLocation; + + void setServerProviderLocation(final ServerProviderLocation location) { + setState(() { + serverProviderLocation = location; + }); + } + + @override + Widget build(final BuildContext context) { + + } +} + +class SelectLocationPage extends StatelessWidget { + const SelectLocationPage({ + required this.serverInstallationCubit, + super.key, + }); + + final ServerInstallationCubit serverInstallationCubit; + + @override + Widget build(final BuildContext context) => FutureBuilder( + future: serverInstallationCubit.repository.serverProviderApiFactory, + builder: ( + final BuildContext context, + final AsyncSnapshot snapshot, + ) { + if (snapshot.hasData) { + return _KeyDisplay( + newDeviceKey: snapshot.data.toString(), + ); + } else { + return const Center(child: CircularProgressIndicator()); + } + }, + ), +} + +class ProviderSelectionPage extends StatelessWidget { + const ProviderSelectionPage({ + required this.callback, + super.key, + }); + + final Function callback; + + @override + Widget build(final BuildContext context) => Column( + children: [ + Text( + 'initializing.select_provider'.tr(), + style: Theme.of(context).textTheme.titleLarge, + ), + const SizedBox(height: 10), + Text( + 'initializing.place_where_data'.tr(), + ), + const SizedBox(height: 10), + ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 320, + ), + child: Row( + children: [ + InkWell( + onTap: () { + context + .read() + .setServerProviderType(ServerProvider.hetzner); + callback(ServerProvider.hetzner); + }, + child: Image.asset( + 'assets/images/logos/hetzner.png', + width: 150, + ), + ), + const SizedBox( + width: 20, + ), + InkWell( + onTap: () { + context + .read() + .setServerProviderType(ServerProvider.digitalOcean); + callback(ServerProvider.digitalOcean); + }, + child: Image.asset( + 'assets/images/logos/digital_ocean.png', + width: 150, + ), + ), + ], + ), + ), + ], + ); +}