mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-02-04 07:20:39 +00:00
Hot bug fixing of recovery flow
Co-authored-by: Inex Code <inex.code@selfprivacy.org>
This commit is contained in:
parent
a096e7e732
commit
edce25ec55
|
@ -23,7 +23,7 @@ linter:
|
|||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
|
|
|
@ -313,11 +313,25 @@
|
|||
"choose_server_description": "We couldn't figure out which server your are trying to connect to.",
|
||||
"no_servers": "There is no available servers on your account.",
|
||||
"domain_not_available_on_token": "Selected domain is not available on this token.",
|
||||
"modal_confirmation_title": "Is it really your server?",
|
||||
"modal_confirmation_description": "If you connect to a wrong server you may lose all your data.",
|
||||
"modal_confirmation_dns_valid": "Reverse DNS is valid",
|
||||
"modal_confirmation_dns_invalid": "Reverse DNS points to another domain",
|
||||
"modal_confirmation_ip_valid": "IP is the same as in DNS record",
|
||||
"modal_confirmation_ip_invalid": "IP is not the same as in DNS record",
|
||||
"confirm_cloudflare": "Connect to CloudFlare",
|
||||
"confirm_cloudflare_description": "Enter a Cloudflare token with access to {}:",
|
||||
"confirm_backblze": "Connect to Backblaze",
|
||||
"confirm_backblaze": "Connect to Backblaze",
|
||||
"confirm_backblaze_description": "Enter a Backblaze token with access to backup storage:"
|
||||
|
||||
},
|
||||
"recovery_key": {
|
||||
"key_main_header": "Recovery key",
|
||||
"key_main_description": "Is needed for SelfPrivacy authorization when all your other authorized devices aren't available.",
|
||||
"key_amount_toggle": "Limit by number of uses",
|
||||
"key_amount_field_title": "Max number of uses",
|
||||
"key_duedate_toggle": "Limit by time",
|
||||
"key_duedate_field_title": "Due date of expiration",
|
||||
"key_receive_button": "Receive key"
|
||||
},
|
||||
"modals": {
|
||||
"_comment": "messages in modals",
|
||||
|
@ -331,7 +345,8 @@
|
|||
"8": "Remove task",
|
||||
"9": "Reboot",
|
||||
"10": "You cannot use this API for domains with such TLD.",
|
||||
"yes": "Yes"
|
||||
"yes": "Yes",
|
||||
"no": "No"
|
||||
},
|
||||
"timer": {
|
||||
"sec": "{} sec"
|
||||
|
|
|
@ -315,11 +315,22 @@
|
|||
"choose_server_description": "Не удалось определить, с каким сервером вы устанавливаете связь.",
|
||||
"no_servers": "На вашем аккаунте нет доступных серверов.",
|
||||
"domain_not_available_on_token": "Введённый токен не имеет доступа к нужному домену.",
|
||||
"modal_confirmation_title": "Это действительно ваш сервер?",
|
||||
"modal_confirmation_description": "Подключение к неправильному серверу может привести к деструктивным последствиям.",
|
||||
"confirm_cloudflare": "Подключение к Cloudflare",
|
||||
"confirm_cloudflare_description": "Введите токен Cloudflare, который имеет права на {}:",
|
||||
"confirm_backblze": "Подключение к Backblaze",
|
||||
"confirm_backblaze_description": "Введите токен Backblaze, который имеет права на хранилище резервных копий:"
|
||||
},
|
||||
"recovery_key": {
|
||||
"key_main_header": "Ключ восстановления",
|
||||
"key_main_description": "Требуется для авторизации SelfPrivacy, когда авторизованные устройства недоступны.",
|
||||
"key_amount_toggle": "Ограничить использования",
|
||||
"key_amount_field_title": "Макс. кол-во использований",
|
||||
"key_duedate_toggle": "Ограничить срок использования",
|
||||
"key_duedate_field_title": "Дата окончания срока",
|
||||
"key_receive_button": "Получить ключ"
|
||||
},
|
||||
"modals": {
|
||||
"_comment": "messages in modals",
|
||||
"1": "Сервер с таким именем уже существует",
|
||||
|
@ -332,7 +343,8 @@
|
|||
"8": "Удалить задачу",
|
||||
"9": "Перезагрузить",
|
||||
"10": "API не поддерживает домены с таким TLD.",
|
||||
"yes": "Да"
|
||||
"yes": "Да",
|
||||
"no": "Нет"
|
||||
},
|
||||
"timer": {
|
||||
"sec": "{} сек"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||
|
@ -22,6 +23,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
var servicesCubit = ServicesCubit(serverInstallationCubit);
|
||||
var backupsCubit = BackupsCubit(serverInstallationCubit);
|
||||
var dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
||||
var recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
|
@ -36,6 +38,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
BlocProvider(create: (_) => servicesCubit..load(), lazy: false),
|
||||
BlocProvider(create: (_) => backupsCubit..load(), lazy: false),
|
||||
BlocProvider(create: (_) => dnsRecordsCubit..load()),
|
||||
BlocProvider(create: (_) => recoveryKeyCubit..load()),
|
||||
BlocProvider(
|
||||
create: (_) =>
|
||||
JobsCubit(usersCubit: usersCubit, servicesCubit: servicesCubit),
|
||||
|
|
|
@ -628,7 +628,7 @@ class ServerApi extends ApiMap {
|
|||
.replaceAll('"', '');
|
||||
}
|
||||
|
||||
Future<ApiResponse<RecoveryKeyStatus>> getRecoveryTokenStatus() async {
|
||||
Future<ApiResponse<RecoveryKeyStatus?>> getRecoveryTokenStatus() async {
|
||||
Response response;
|
||||
|
||||
var client = await getClient();
|
||||
|
@ -649,7 +649,7 @@ class ServerApi extends ApiMap {
|
|||
return ApiResponse(
|
||||
statusCode: code,
|
||||
data: response.data != null
|
||||
? response.data.fromJson(response.data)
|
||||
? RecoveryKeyStatus.fromJson(response.data)
|
||||
: null);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ class BackblazeFormCubit extends FormCubit {
|
|||
isKeyValid = await apiClient.isValid(encodedApiKey);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
isKeyValid = false;
|
||||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
|
|
|
@ -26,7 +26,7 @@ class RecoveryKeyCubit
|
|||
}
|
||||
|
||||
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
|
||||
final ApiResponse<RecoveryKeyStatus> response =
|
||||
final ApiResponse<RecoveryKeyStatus?> response =
|
||||
await api.getRecoveryTokenStatus();
|
||||
if (response.isSuccess) {
|
||||
return response.data;
|
||||
|
|
|
@ -64,6 +64,10 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
}
|
||||
|
||||
void setCloudflareKey(String cloudFlareKey) async {
|
||||
if (state is ServerInstallationRecovery) {
|
||||
setAndValidateCloudflareToken(cloudFlareKey);
|
||||
return;
|
||||
}
|
||||
await repository.saveCloudFlareKey(cloudFlareKey);
|
||||
emit((state as ServerInstallationNotFinished)
|
||||
.copyWith(cloudFlareKey: cloudFlareKey));
|
||||
|
@ -431,12 +435,19 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
.showSnackBar('recovering.domain_not_available_on_token'.tr());
|
||||
return;
|
||||
}
|
||||
await repository.saveDomain(ServerDomain(
|
||||
domainName: serverDomain.domainName,
|
||||
zoneId: zoneId,
|
||||
provider: DnsProvider.Cloudflare,
|
||||
));
|
||||
await repository.saveCloudFlareKey(token);
|
||||
emit(dataState.copyWith(
|
||||
serverDomain: ServerDomain(
|
||||
domainName: serverDomain.domainName,
|
||||
zoneId: zoneId,
|
||||
provider: DnsProvider.Cloudflare,
|
||||
),
|
||||
cloudFlareKey: token,
|
||||
currentStep: RecoveryStep.BackblazeToken,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -88,8 +88,9 @@ class MyApp extends StatelessWidget {
|
|||
: RootPage(),
|
||||
builder: (BuildContext context, Widget? widget) {
|
||||
Widget error = Text('...rendering error...');
|
||||
if (widget is Scaffold || widget is Navigator)
|
||||
if (widget is Scaffold || widget is Navigator) {
|
||||
error = Scaffold(body: Center(child: error));
|
||||
}
|
||||
ErrorWidget.builder =
|
||||
(FlutterErrorDetails errorDetails) => error;
|
||||
return widget!;
|
||||
|
|
14
lib/ui/pages/recovery_key/recovery_key.dart
Normal file
14
lib/ui/pages/recovery_key/recovery_key.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*import 'package:flutter/src/foundation/key.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
|
||||
class RecoveryKey extends StatefulWidget {
|
||||
const RecoveryKey({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<RecoveryKey> createState() => _RecoveryKeyState();
|
||||
}
|
||||
|
||||
class _RecoveryKeyState extends State<RecoveryKey> {
|
||||
@override
|
||||
Widget build(BuildContext context) {}
|
||||
}*/
|
1
lib/ui/pages/recovery_key/recovery_key_receiving.dart
Normal file
1
lib/ui/pages/recovery_key/recovery_key_receiving.dart
Normal file
|
@ -0,0 +1 @@
|
|||
|
|
@ -40,34 +40,44 @@ class RecoverByNewDeviceKeyInput extends StatelessWidget {
|
|||
FieldCubitFactory(context),
|
||||
ServerRecoveryMethods.newDeviceKey,
|
||||
),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
var formCubitState = context.watch<RecoveryDeviceFormCubit>().state;
|
||||
|
||||
return BrandHeroScreen(
|
||||
heroTitle: "recovering.recovery_main_header".tr(),
|
||||
heroSubtitle: "recovering.method_device_input_description".tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
children: [
|
||||
CubitFormTextField(
|
||||
formFieldCubit:
|
||||
context.read<RecoveryDeviceFormCubit>().tokenField,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: "recovering.method_device_input_placeholder".tr(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: "more.continue".tr(),
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
: () => context.read<RecoveryDeviceFormCubit>().trySubmit(),
|
||||
)
|
||||
],
|
||||
);
|
||||
child: BlocListener<ServerInstallationCubit, ServerInstallationState>(
|
||||
listener: (context, state) {
|
||||
if (state is ServerInstallationRecovery &&
|
||||
state.currentStep != RecoveryStep.NewDeviceKey) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
var formCubitState = context.watch<RecoveryDeviceFormCubit>().state;
|
||||
|
||||
return BrandHeroScreen(
|
||||
heroTitle: "recovering.recovery_main_header".tr(),
|
||||
heroSubtitle: "recovering.method_device_input_description".tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
children: [
|
||||
CubitFormTextField(
|
||||
formFieldCubit:
|
||||
context.read<RecoveryDeviceFormCubit>().tokenField,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText:
|
||||
"recovering.method_device_input_placeholder".tr(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: "more.continue".tr(),
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
: () =>
|
||||
context.read<RecoveryDeviceFormCubit>().trySubmit(),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,24 +13,33 @@ class RecoverByOldTokenInstruction extends StatelessWidget {
|
|||
RecoverByOldTokenInstruction({required this.instructionFilename});
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return BrandHeroScreen(
|
||||
heroTitle: "recovering.recovery_main_header".tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
onBackButtonPressed: () =>
|
||||
context.read<ServerInstallationCubit>().revertRecoveryStep(),
|
||||
children: [
|
||||
BrandMarkdown(
|
||||
fileName: instructionFilename,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: "recovering.method_device_button".tr(),
|
||||
onPressed: () => context
|
||||
.read<ServerInstallationCubit>()
|
||||
.selectRecoveryMethod(ServerRecoveryMethods.oldToken),
|
||||
)
|
||||
],
|
||||
return BlocListener<ServerInstallationCubit, ServerInstallationState>(
|
||||
listener: (context, state) {
|
||||
if (state is ServerInstallationRecovery &&
|
||||
state.currentStep != RecoveryStep.Selecting) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: BrandHeroScreen(
|
||||
heroTitle: "recovering.recovery_main_header".tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
onBackButtonPressed: () =>
|
||||
context.read<ServerInstallationCubit>().revertRecoveryStep(),
|
||||
children: [
|
||||
BrandMarkdown(
|
||||
fileName: instructionFilename,
|
||||
),
|
||||
SizedBox(height: 18),
|
||||
FilledButton(
|
||||
title: "recovering.method_device_button".tr(),
|
||||
onPressed: () => context
|
||||
.read<ServerInstallationCubit>()
|
||||
.selectRecoveryMethod(ServerRecoveryMethods.oldToken),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -66,7 +75,7 @@ class RecoverByOldToken extends StatelessWidget {
|
|||
labelText: "recovering.method_device_input_placeholder".tr(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
SizedBox(height: 18),
|
||||
FilledButton(
|
||||
title: "more.continue".tr(),
|
||||
onPressed: formCubitState.isSubmitting
|
||||
|
|
|
@ -30,26 +30,28 @@ class RecoveryConfirmBackblaze extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'KeyID',
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
const SizedBox(height: 18),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: context.read<BackblazeFormCubit>().applicationKey,
|
||||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'Master Application Key',
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
const SizedBox(height: 18),
|
||||
BrandButton.rised(
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
: () => context.read<BackblazeFormCubit>().trySubmit(),
|
||||
text: 'basis.connect'.tr(),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
const SizedBox(height: 18),
|
||||
BrandButton.text(
|
||||
onPressed: () => showModalBottomSheet<void>(
|
||||
context: context,
|
||||
|
|
|
@ -32,17 +32,18 @@ class RecoveryConfirmCloudflare extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'initializing.5'.tr(),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
const SizedBox(height: 18),
|
||||
BrandButton.rised(
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
: () => context.read<CloudFlareFormCubit>().trySubmit(),
|
||||
text: 'basis.connect'.tr(),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
const SizedBox(height: 18),
|
||||
BrandButton.text(
|
||||
onPressed: () => showModalBottomSheet<void>(
|
||||
context: context,
|
||||
|
|
|
@ -36,11 +36,11 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
|
|||
Widget build(BuildContext context) {
|
||||
return BrandHeroScreen(
|
||||
heroTitle: _isExtended
|
||||
? "recovering.choose_server".tr()
|
||||
: "recovering.confirm_server".tr(),
|
||||
? 'recovering.choose_server'.tr()
|
||||
: 'recovering.confirm_server'.tr(),
|
||||
heroSubtitle: _isExtended
|
||||
? "recovering.choose_server_description".tr()
|
||||
: "recovering.confirm_server_description".tr(),
|
||||
? 'recovering.choose_server_description'.tr()
|
||||
: 'recovering.confirm_server_description'.tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
children: [
|
||||
|
@ -68,7 +68,7 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
|
|||
if (servers?.isEmpty ?? true)
|
||||
Center(
|
||||
child: Text(
|
||||
"recovering.no_servers".tr(),
|
||||
'recovering.no_servers'.tr(),
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
),
|
||||
|
@ -99,7 +99,7 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
|
|||
),
|
||||
SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: "recovering.confirm_server_accept".tr(),
|
||||
title: 'recovering.confirm_server_accept'.tr(),
|
||||
onPressed: () => _showConfirmationDialog(context, server),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
|
@ -166,19 +166,65 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
|
|||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text('ssh.delete'.tr()),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Text("WOW DIALOGUE TEXT WOW :)"),
|
||||
],
|
||||
),
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.warning_amber_outlined),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'recovering.modal_confirmation_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text('recovering.modal_confirmation_description'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium),
|
||||
const Divider(),
|
||||
Text(
|
||||
server.name,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(server.isReverseDnsValid ? Icons.check : Icons.close),
|
||||
const SizedBox(width: 8),
|
||||
Text(server.isReverseDnsValid
|
||||
? 'recovering.modal_confirmation_dns_valid'.tr()
|
||||
: 'recovering.modal_confirmation_dns_invalid'.tr()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(server.isIpValid ? Icons.check : Icons.close),
|
||||
const SizedBox(width: 8),
|
||||
Text(server.isIpValid
|
||||
? 'recovering.modal_confirmation_ip_valid'.tr()
|
||||
: 'recovering.modal_confirmation_ip_invalid'.tr()),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text('basis.cancel'.tr()),
|
||||
child: Text('modals.no'.tr()),
|
||||
onPressed: () {
|
||||
Navigator.of(context)..pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text('modals.yes'.tr()),
|
||||
onPressed: () {
|
||||
context.read<ServerInstallationCubit>().setServerId(server);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
|
@ -9,6 +9,8 @@ import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.da
|
|||
import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_old_token.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_recovery_key.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_new_device_key.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_confirm_backblaze.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_confirm_server.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_hentzner_connected.dart';
|
||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_method_select.dart';
|
||||
|
@ -43,8 +45,10 @@ class RecoveryRouting extends StatelessWidget {
|
|||
currentPage = RecoveryConfirmServer();
|
||||
break;
|
||||
case RecoveryStep.CloudflareToken:
|
||||
currentPage = RecoveryConfirmCloudflare();
|
||||
break;
|
||||
case RecoveryStep.BackblazeToken:
|
||||
currentPage = RecoveryConfirmBackblaze();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
14
pubspec.lock
14
pubspec.lock
|
@ -363,6 +363,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.2"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
flutter_localizations:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -560,6 +567,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
local_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -52,6 +52,7 @@ dev_dependencies:
|
|||
flutter_launcher_icons: ^0.9.2
|
||||
hive_generator: ^1.0.0
|
||||
json_serializable: ^6.1.4
|
||||
flutter_lints: ^2.0.1
|
||||
|
||||
flutter_icons:
|
||||
android: "launcher_icon"
|
||||
|
|
Loading…
Reference in a new issue