feat: Implement DNS provider picker page

pull/213/head
NaiJi ✨ 2022-12-30 07:25:18 +04:00
parent d333787f37
commit e560de58e7
11 changed files with 267 additions and 70 deletions

View File

@ -268,9 +268,10 @@
"no_ssh_notice": "Only email and SSH accounts are created for this user. Single Sign On for all services is coming soon." "no_ssh_notice": "Only email and SSH accounts are created for this user. Single Sign On for all services is coming soon."
}, },
"initializing": { "initializing": {
"connect_to_server": "Connect a server", "connect_to_server": "Connect the server provider",
"select_provider": "Select your provider", "select_provider": "Select your provider",
"place_where_data": "A place where your data and SelfPrivacy services will reside:", "server_provider_description": "A place where your data and SelfPrivacy services will reside:",
"dns_provider_description": "A service which lets your IP point towards domain names:",
"how": "How to obtain API token", "how": "How to obtain API token",
"provider_bad_key_error": "Provider API key is invalid", "provider_bad_key_error": "Provider API key is invalid",
"could_not_connect": "Counldn't connect to the provider.", "could_not_connect": "Counldn't connect to the provider.",
@ -280,7 +281,7 @@
"no_server_types_found": "No available server types found. Make sure your account is accessible and try to change your server location.", "no_server_types_found": "No available server types found. Make sure your account is accessible and try to change your server location.",
"cloudflare_bad_key_error": "Cloudflare API key is invalid", "cloudflare_bad_key_error": "Cloudflare API key is invalid",
"backblaze_bad_key_error": "Backblaze storage information is invalid", "backblaze_bad_key_error": "Backblaze storage information is invalid",
"connect_cloudflare": "Connect CloudFlare", "connect_to_dns": "Connect the DNS provider",
"manage_domain_dns": "To manage your domain's DNS", "manage_domain_dns": "To manage your domain's DNS",
"cloudflare_api_token": "CloudFlare API Token", "cloudflare_api_token": "CloudFlare API Token",
"connect_backblaze_storage": "Connect Backblaze storage", "connect_backblaze_storage": "Connect Backblaze storage",

View File

@ -269,7 +269,8 @@
}, },
"initializing": { "initializing": {
"connect_to_server": "Подключите сервер", "connect_to_server": "Подключите сервер",
"place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:", "server_provider_description": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:",
"dns_provider_description": "Это позволит связать ваш домен с IP адресом:",
"how": "Как получить API Token", "how": "Как получить API Token",
"provider_bad_key_error": "API ключ провайдера неверен", "provider_bad_key_error": "API ключ провайдера неверен",
"could_not_connect": "Не удалось соединиться с провайдером.", "could_not_connect": "Не удалось соединиться с провайдером.",
@ -279,7 +280,7 @@
"no_server_types_found": "Не удалось получить список серверов. Убедитесь, что ваш аккаунт доступен и попытайтесь сменить локацию сервера.", "no_server_types_found": "Не удалось получить список серверов. Убедитесь, что ваш аккаунт доступен и попытайтесь сменить локацию сервера.",
"cloudflare_bad_key_error": "Cloudflare API ключ неверен", "cloudflare_bad_key_error": "Cloudflare API ключ неверен",
"backblaze_bad_key_error": "Информация о Backblaze хранилище неверна", "backblaze_bad_key_error": "Информация о Backblaze хранилище неверна",
"connect_cloudflare": "Подключите CloudFlare", "connect_to_dns": "Подключите DNS провайдер",
"manage_domain_dns": "Для управления DNS вашего домена", "manage_domain_dns": "Для управления DNS вашего домена",
"cloudflare_api_token": "CloudFlare API ключ", "cloudflare_api_token": "CloudFlare API ключ",
"connect_backblaze_storage": "Подключите облачное хранилище Backblaze", "connect_backblaze_storage": "Подключите облачное хранилище Backblaze",

View File

@ -90,6 +90,9 @@ class BNames {
/// A String field of [serverInstallationBox] box. /// A String field of [serverInstallationBox] box.
static String serverProvider = 'serverProvider'; static String serverProvider = 'serverProvider';
/// A String field of [serverInstallationBox] box.
static String dnsProvider = 'dnsProvider';
/// A String field of [serverLocation] box. /// A String field of [serverLocation] box.
static String serverLocation = 'serverLocation'; static String serverLocation = 'serverLocation';

View File

@ -4,8 +4,8 @@ import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
class ProviderFormCubit extends FormCubit { class ServerProviderFormCubit extends FormCubit {
ProviderFormCubit(this.serverInstallationCubit) { ServerProviderFormCubit(this.serverInstallationCubit) {
//final int tokenLength = //final int tokenLength =
// serverInstallationCubit.serverProviderApiTokenValidation().length; // serverInstallationCubit.serverProviderApiTokenValidation().length;
apiKey = FieldCubit( apiKey = FieldCubit(

View File

@ -66,6 +66,15 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
); );
} }
void setDnsProviderType(final DnsProvider providerType) async {
await repository.saveDnsProviderType(providerType);
ApiController.initDnsProviderApiFactory(
DnsProviderApiFactorySettings(
provider: providerType,
),
);
}
ProviderApiTokenValidation serverProviderApiTokenValidation() => ProviderApiTokenValidation serverProviderApiTokenValidation() =>
ApiController.currentServerProviderApiFactory! ApiController.currentServerProviderApiFactory!
.getServerProvider() .getServerProvider()
@ -101,16 +110,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
Future<bool?> isDnsProviderApiTokenValid( Future<bool?> isDnsProviderApiTokenValid(
final String providerToken, final String providerToken,
) async { ) async {
if (ApiController.currentDnsProviderApiFactory == null) {
// No other DNS provider is supported for now,
// so it's safe to hardcode Cloudflare
ApiController.initDnsProviderApiFactory(
DnsProviderApiFactorySettings(
provider: DnsProvider.cloudflare,
),
);
}
final APIGenericResult<bool> apiResponse = final APIGenericResult<bool> apiResponse =
await ApiController.currentDnsProviderApiFactory! await ApiController.currentDnsProviderApiFactory!
.getDnsProvider( .getDnsProvider(

View File

@ -688,6 +688,10 @@ class ServerInstallationRepository {
await getIt<ApiConfigModel>().storeServerProviderType(type); await getIt<ApiConfigModel>().storeServerProviderType(type);
} }
Future<void> saveDnsProviderType(final DnsProvider type) async {
await getIt<ApiConfigModel>().storeDnsProviderType(type);
}
Future<void> saveServerProviderKey(final String key) async { Future<void> saveServerProviderKey(final String key) async {
await getIt<ApiConfigModel>().storeServerProviderKey(key); await getIt<ApiConfigModel>().storeServerProviderKey(key);
} }

View File

@ -14,6 +14,7 @@ class ApiConfigModel {
String? get serverType => _serverType; String? get serverType => _serverType;
String? get dnsProviderKey => _dnsProviderKey; String? get dnsProviderKey => _dnsProviderKey;
ServerProvider? get serverProvider => _serverProvider; ServerProvider? get serverProvider => _serverProvider;
DnsProvider? get dnsProvider => _dnsProvider;
BackblazeCredential? get backblazeCredential => _backblazeCredential; BackblazeCredential? get backblazeCredential => _backblazeCredential;
ServerDomain? get serverDomain => _serverDomain; ServerDomain? get serverDomain => _serverDomain;
BackblazeBucket? get backblazeBucket => _backblazeBucket; BackblazeBucket? get backblazeBucket => _backblazeBucket;
@ -23,6 +24,7 @@ class ApiConfigModel {
String? _dnsProviderKey; String? _dnsProviderKey;
String? _serverType; String? _serverType;
ServerProvider? _serverProvider; ServerProvider? _serverProvider;
DnsProvider? _dnsProvider;
ServerHostingDetails? _serverDetails; ServerHostingDetails? _serverDetails;
BackblazeCredential? _backblazeCredential; BackblazeCredential? _backblazeCredential;
ServerDomain? _serverDomain; ServerDomain? _serverDomain;
@ -33,6 +35,11 @@ class ApiConfigModel {
_serverProvider = value; _serverProvider = value;
} }
Future<void> storeDnsProviderType(final DnsProvider value) async {
await _box.put(BNames.dnsProvider, value);
_dnsProvider = value;
}
Future<void> storeServerProviderKey(final String value) async { Future<void> storeServerProviderKey(final String value) async {
await _box.put(BNames.hetznerKey, value); await _box.put(BNames.hetznerKey, value);
_serverProviderKey = value; _serverProviderKey = value;
@ -75,6 +82,7 @@ class ApiConfigModel {
void clear() { void clear() {
_serverProviderKey = null; _serverProviderKey = null;
_dnsProvider = null;
_serverLocation = null; _serverLocation = null;
_dnsProviderKey = null; _dnsProviderKey = null;
_backblazeCredential = null; _backblazeCredential = null;
@ -95,5 +103,6 @@ class ApiConfigModel {
_backblazeBucket = _box.get(BNames.backblazeBucket); _backblazeBucket = _box.get(BNames.backblazeBucket);
_serverType = _box.get(BNames.serverTypeIdentifier); _serverType = _box.get(BNames.serverTypeIdentifier);
_serverProvider = _box.get(BNames.serverProvider); _serverProvider = _box.get(BNames.serverProvider);
_dnsProvider = _box.get(BNames.dnsProvider);
} }
} }

View File

@ -0,0 +1,205 @@
import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
import 'package:selfprivacy/logic/models/hive/server_details.dart';
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
class DnsProviderPicker extends StatefulWidget {
const DnsProviderPicker({
required this.formCubit,
required this.serverInstallationCubit,
super.key,
});
final DnsProviderFormCubit formCubit;
final ServerInstallationCubit serverInstallationCubit;
@override
State<DnsProviderPicker> createState() => _DnsProviderPickerState();
}
class _DnsProviderPickerState extends State<DnsProviderPicker> {
DnsProvider selectedProvider = DnsProvider.unknown;
void setProvider(final DnsProvider provider) {
setState(() {
selectedProvider = provider;
});
}
@override
Widget build(final BuildContext context) {
switch (selectedProvider) {
case DnsProvider.unknown:
return ProviderSelectionPage(
serverInstallationCubit: widget.serverInstallationCubit,
callback: setProvider,
);
case DnsProvider.cloudflare:
return ProviderInputDataPage(
providerCubit: widget.formCubit,
providerInfo: ProviderPageInfo(
providerType: DnsProvider.cloudflare,
pathToHow: 'how_cloudflare',
image: Image.asset(
'assets/images/logos/cloudflare.png',
width: 150,
),
),
);
case DnsProvider.digitalOcean:
return ProviderInputDataPage(
providerCubit: widget.formCubit,
providerInfo: ProviderPageInfo(
providerType: DnsProvider.digitalOcean,
pathToHow: 'how_cloudflare',
image: Image.asset(
'assets/images/logos/digital_ocean.png',
width: 150,
),
),
);
}
}
}
class ProviderPageInfo {
const ProviderPageInfo({
required this.providerType,
required this.pathToHow,
required this.image,
});
final String pathToHow;
final Image image;
final DnsProvider providerType;
}
class ProviderInputDataPage extends StatelessWidget {
const ProviderInputDataPage({
required this.providerInfo,
required this.providerCubit,
super.key,
});
final ProviderPageInfo providerInfo;
final DnsProviderFormCubit providerCubit;
@override
Widget build(final BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
providerInfo.image,
const SizedBox(height: 10),
Text(
'initializing.connect_to_dns'.tr(),
style: Theme.of(context).textTheme.titleLarge,
),
const Spacer(),
CubitFormTextField(
formFieldCubit: providerCubit.apiKey,
textAlign: TextAlign.center,
scrollPadding: const EdgeInsets.only(bottom: 70),
decoration: const InputDecoration(
hintText: 'Provider API Token',
),
),
const Spacer(),
FilledButton(
title: 'basis.connect'.tr(),
onPressed: () => providerCubit.trySubmit(),
),
const SizedBox(height: 10),
OutlinedButton(
child: Text('initializing.how'.tr()),
onPressed: () => showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (final BuildContext context) => BrandBottomSheet(
isExpended: true,
child: Padding(
padding: paddingH15V0,
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 16),
children: [
BrandMarkdown(
fileName: providerInfo.pathToHow,
),
],
),
),
),
),
),
],
);
}
class ProviderSelectionPage extends StatelessWidget {
const ProviderSelectionPage({
required this.callback,
required this.serverInstallationCubit,
super.key,
});
final Function callback;
final ServerInstallationCubit serverInstallationCubit;
@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.dns_provider_description'.tr(),
),
const SizedBox(height: 10),
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 320,
),
child: Row(
children: [
InkWell(
onTap: () {
serverInstallationCubit
.setDnsProviderType(DnsProvider.cloudflare);
callback(DnsProvider.cloudflare);
},
child: Image.asset(
'assets/images/logos/cloudflare.png',
width: 150,
),
),
const SizedBox(
width: 20,
),
InkWell(
onTap: () {
serverInstallationCubit
.setDnsProviderType(DnsProvider.digitalOcean);
callback(DnsProvider.digitalOcean);
},
child: Image.asset(
'assets/images/logos/digital_ocean.png',
width: 150,
),
),
],
),
),
],
);
}

View File

@ -2,7 +2,7 @@ import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/server_provider_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart'; 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/backblaze_form_cubit.dart';
@ -17,6 +17,7 @@ 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/brand_timer/brand_timer.dart';
import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart'; import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart';
import 'package:selfprivacy/ui/pages/root_route.dart'; import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/dns_provider_picker.dart';
import 'package:selfprivacy/ui/pages/setup/initializing/server_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/initializing/server_type_picker.dart';
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart'; import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart';
@ -37,7 +38,7 @@ class InitializingPage extends StatelessWidget {
actualInitializingPage = [ actualInitializingPage = [
() => _stepServerProviderToken(cubit), () => _stepServerProviderToken(cubit),
() => _stepServerType(cubit), () => _stepServerType(cubit),
() => _stepCloudflare(cubit), () => _stepDnsProviderToken(cubit),
() => _stepBackblaze(cubit), () => _stepBackblaze(cubit),
() => _stepDomain(cubit), () => _stepDomain(cubit),
() => _stepUser(cubit), () => _stepUser(cubit),
@ -149,10 +150,11 @@ class InitializingPage extends StatelessWidget {
final ServerInstallationCubit serverInstallationCubit, final ServerInstallationCubit serverInstallationCubit,
) => ) =>
BlocProvider( BlocProvider(
create: (final context) => ProviderFormCubit(serverInstallationCubit), create: (final context) =>
ServerProviderFormCubit(serverInstallationCubit),
child: Builder( child: Builder(
builder: (final context) { builder: (final context) {
final providerCubit = context.watch<ProviderFormCubit>(); final providerCubit = context.watch<ServerProviderFormCubit>();
return ServerProviderPicker( return ServerProviderPicker(
formCubit: providerCubit, formCubit: providerCubit,
serverInstallationCubit: serverInstallationCubit, serverInstallationCubit: serverInstallationCubit,
@ -165,7 +167,8 @@ class InitializingPage extends StatelessWidget {
final ServerInstallationCubit serverInstallationCubit, final ServerInstallationCubit serverInstallationCubit,
) => ) =>
BlocProvider( BlocProvider(
create: (final context) => ProviderFormCubit(serverInstallationCubit), create: (final context) =>
ServerProviderFormCubit(serverInstallationCubit),
child: Builder( child: Builder(
builder: (final context) => ServerTypePicker( builder: (final context) => ServerTypePicker(
serverInstallationCubit: serverInstallationCubit, serverInstallationCubit: serverInstallationCubit,
@ -182,48 +185,19 @@ class InitializingPage extends StatelessWidget {
); );
} }
Widget _stepCloudflare(final ServerInstallationCubit initializingCubit) => Widget _stepDnsProviderToken(
final ServerInstallationCubit initializingCubit,
) =>
BlocProvider( BlocProvider(
create: (final context) => DnsProviderFormCubit(initializingCubit), create: (final context) => DnsProviderFormCubit(initializingCubit),
child: Builder( child: Builder(
builder: (final context) => Column( builder: (final context) {
crossAxisAlignment: CrossAxisAlignment.start, final providerCubit = context.watch<DnsProviderFormCubit>();
children: [ return DnsProviderPicker(
Image.asset( formCubit: providerCubit,
'assets/images/logos/cloudflare.png', serverInstallationCubit: initializingCubit,
width: 150, );
), },
const SizedBox(height: 10),
BrandText.h2('initializing.connect_cloudflare'.tr()),
const SizedBox(height: 10),
BrandText.body2('initializing.manage_domain_dns'.tr()),
const Spacer(),
CubitFormTextField(
formFieldCubit: context.read<DnsProviderFormCubit>().apiKey,
textAlign: TextAlign.center,
scrollPadding: const EdgeInsets.only(bottom: 70),
decoration: InputDecoration(
hintText: 'initializing.cloudflare_api_token'.tr(),
),
),
const Spacer(),
BrandButton.rised(
onPressed: () =>
context.read<DnsProviderFormCubit>().trySubmit(),
text: 'basis.connect'.tr(),
),
const SizedBox(height: 10),
BrandButton.text(
onPressed: () => _showModal(
context,
const _HowTo(
fileName: 'how_cloudflare',
),
),
title: 'initializing.how'.tr(),
),
],
),
), ),
); );

View File

@ -3,7 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/server_provider_form_cubit.dart';
import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/server_details.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
@ -16,7 +16,7 @@ class ServerProviderPicker extends StatefulWidget {
super.key, super.key,
}); });
final ProviderFormCubit formCubit; final ServerProviderFormCubit formCubit;
final ServerInstallationCubit serverInstallationCubit; final ServerInstallationCubit serverInstallationCubit;
@override @override
@ -90,7 +90,7 @@ class ProviderInputDataPage extends StatelessWidget {
}); });
final ProviderPageInfo providerInfo; final ProviderPageInfo providerInfo;
final ProviderFormCubit providerCubit; final ServerProviderFormCubit providerCubit;
@override @override
Widget build(final BuildContext context) => Column( Widget build(final BuildContext context) => Column(
@ -162,7 +162,7 @@ class ProviderSelectionPage extends StatelessWidget {
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
'initializing.place_where_data'.tr(), 'initializing.server_provider_description'.tr(),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
ConstrainedBox( ConstrainedBox(

View File

@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/setup/initializing/server_provider_form_cubit.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
@ -19,11 +19,12 @@ class RecoveryServerProviderConnected extends StatelessWidget {
context.watch<ServerInstallationCubit>(); context.watch<ServerInstallationCubit>();
return BlocProvider( return BlocProvider(
create: (final BuildContext context) => ProviderFormCubit(appConfig), create: (final BuildContext context) =>
ServerProviderFormCubit(appConfig),
child: Builder( child: Builder(
builder: (final BuildContext context) { builder: (final BuildContext context) {
final FormCubitState formCubitState = final FormCubitState formCubitState =
context.watch<ProviderFormCubit>().state; context.watch<ServerProviderFormCubit>().state;
return BrandHeroScreen( return BrandHeroScreen(
heroTitle: 'recovering.server_provider_connected'.tr(), heroTitle: 'recovering.server_provider_connected'.tr(),
@ -37,7 +38,7 @@ class RecoveryServerProviderConnected extends StatelessWidget {
}, },
children: [ children: [
CubitFormTextField( CubitFormTextField(
formFieldCubit: context.read<ProviderFormCubit>().apiKey, formFieldCubit: context.read<ServerProviderFormCubit>().apiKey,
decoration: InputDecoration( decoration: InputDecoration(
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
labelText: labelText:
@ -49,7 +50,7 @@ class RecoveryServerProviderConnected extends StatelessWidget {
title: 'basis.continue'.tr(), title: 'basis.continue'.tr(),
onPressed: formCubitState.isSubmitting onPressed: formCubitState.isSubmitting
? null ? null
: () => context.read<ProviderFormCubit>().trySubmit(), : () => context.read<ServerProviderFormCubit>().trySubmit(),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
BrandButton.text( BrandButton.text(