mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-11 18:39:45 +00:00
Implement recovery domain page frontend
This commit is contained in:
parent
ce3e046f5a
commit
01b1f7462d
|
@ -22,7 +22,7 @@
|
|||
"nickname": "Nickname",
|
||||
"loading": "Loading...",
|
||||
"later": "Skip to setup later",
|
||||
"connect_to_existing": "Connect to existing server",
|
||||
"connect_to_existing": "Connect to an existing server",
|
||||
"reset": "Reset",
|
||||
"details": "Details",
|
||||
"no_data": "No data",
|
||||
|
@ -283,6 +283,11 @@
|
|||
"finish": "Everything is initialized",
|
||||
"checks": "Checks have been completed \n{} ouf of {}"
|
||||
},
|
||||
"recovering": {
|
||||
"recovery_main_header": "Connect to an existing server",
|
||||
"domain_recovery_description": "Enter a server domain you want to get access for",
|
||||
"domain_recover_placeholder": "Your domain"
|
||||
},
|
||||
"modals": {
|
||||
"_comment": "messages in modals",
|
||||
"1": "Server with such name, already exist",
|
||||
|
|
|
@ -71,4 +71,5 @@ class BNames {
|
|||
static String sshConfig = 'sshConfig';
|
||||
static String sshPrivateKey = "sshPrivateKey";
|
||||
static String sshPublicKey = "sshPublicKey";
|
||||
static String serverDomain = "serverDomain";
|
||||
}
|
||||
|
|
|
@ -239,6 +239,10 @@ class AppConfigRepository {
|
|||
await getIt<ApiConfigModel>().storeHetznerKey(key);
|
||||
}
|
||||
|
||||
Future<void> saveServerDomain(String domain) async {
|
||||
await getIt<ApiConfigModel>().storeServerDomain(domain);
|
||||
}
|
||||
|
||||
Future<void> saveBackblazeKey(BackblazeCredential backblazeCredential) async {
|
||||
await getIt<ApiConfigModel>().storeBackblazeCredential(backblazeCredential);
|
||||
}
|
||||
|
|
|
@ -240,3 +240,39 @@ class AppConfigFinished extends AppConfigState {
|
|||
isServerResetedFirstTime,
|
||||
];
|
||||
}
|
||||
|
||||
class AppRecovery extends AppConfigState {
|
||||
const AppRecovery({
|
||||
required String hetznerKey,
|
||||
required String cloudFlareKey,
|
||||
required BackblazeCredential backblazeCredential,
|
||||
required CloudFlareDomain cloudFlareDomain,
|
||||
required User rootUser,
|
||||
required HetznerServerDetails hetznerServer,
|
||||
required bool isServerStarted,
|
||||
required bool isServerResetedFirstTime,
|
||||
required bool isServerResetedSecondTime,
|
||||
}) : super(
|
||||
hetznerKey: hetznerKey,
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
backblazeCredential: backblazeCredential,
|
||||
cloudFlareDomain: cloudFlareDomain,
|
||||
rootUser: rootUser,
|
||||
hetznerServer: hetznerServer,
|
||||
isServerStarted: isServerStarted,
|
||||
isServerResetedFirstTime: isServerResetedFirstTime,
|
||||
isServerResetedSecondTime: isServerResetedSecondTime,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeCredential,
|
||||
cloudFlareDomain,
|
||||
rootUser,
|
||||
hetznerServer,
|
||||
isServerStarted,
|
||||
isServerResetedFirstTime,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart';
|
||||
|
||||
class RecoveryDomainFormCubit extends FormCubit {
|
||||
RecoveryDomainFormCubit(this.initializingCubit) {
|
||||
var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]");
|
||||
apiKey = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('validations.required'.tr()),
|
||||
ValidationModel<String>(
|
||||
(s) => regExp.hasMatch(s), 'validations.key_format'.tr()),
|
||||
LengthStringNotEqualValidation(64)
|
||||
],
|
||||
);
|
||||
|
||||
super.addFields([apiKey]);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> onSubmit() async {
|
||||
initializingCubit.setHetznerKey(apiKey.state.value);
|
||||
}
|
||||
|
||||
final AppConfigCubit initializingCubit;
|
||||
|
||||
late final FieldCubit<String> apiKey;
|
||||
|
||||
@override
|
||||
FutureOr<bool> asyncValidation() async {
|
||||
late bool isKeyValid;
|
||||
HetznerApi apiClient = HetznerApi(isWithToken: false);
|
||||
|
||||
try {
|
||||
isKeyValid = await apiClient.isValid(apiKey.state.value);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
apiKey.setError('bad key');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -11,12 +11,14 @@ class ApiConfigModel {
|
|||
HetznerServerDetails? get hetznerServer => _hetznerServer;
|
||||
String? get hetznerKey => _hetznerKey;
|
||||
String? get cloudFlareKey => _cloudFlareKey;
|
||||
String? get serverDomain => _serverDomain;
|
||||
BackblazeCredential? get backblazeCredential => _backblazeCredential;
|
||||
CloudFlareDomain? get cloudFlareDomain => _cloudFlareDomain;
|
||||
BackblazeBucket? get backblazeBucket => _backblazeBucket;
|
||||
|
||||
String? _hetznerKey;
|
||||
String? _cloudFlareKey;
|
||||
String? _serverDomain;
|
||||
HetznerServerDetails? _hetznerServer;
|
||||
BackblazeCredential? _backblazeCredential;
|
||||
CloudFlareDomain? _cloudFlareDomain;
|
||||
|
@ -32,6 +34,11 @@ class ApiConfigModel {
|
|||
_cloudFlareKey = value;
|
||||
}
|
||||
|
||||
Future<void> storeServerDomain(String value) async {
|
||||
await _box.put(BNames.serverDomain, value);
|
||||
_serverDomain = value;
|
||||
}
|
||||
|
||||
Future<void> storeBackblazeCredential(BackblazeCredential value) async {
|
||||
await _box.put(BNames.backblazeKey, value);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'package:selfprivacy/ui/components/pre_styled_buttons/pre_styled_buttons.
|
|||
class BrandHeader extends StatelessWidget {
|
||||
const BrandHeader({
|
||||
Key? key,
|
||||
required this.title,
|
||||
this.title = "",
|
||||
this.hasBackButton = false,
|
||||
this.hasFlashButton = false,
|
||||
}) : super(key: key);
|
||||
|
|
|
@ -4,11 +4,11 @@ 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/forms/factories/field_cubit_factory.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/cloudflare_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/domain_cloudflare.dart';
|
||||
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/forms/setup/initializing/backblaze_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/cloudflare_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/hetzner_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';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||
|
@ -104,10 +104,8 @@ class InitializingPage extends StatelessWidget {
|
|||
child: BrandButton.text(
|
||||
title: 'basis.connect_to_existing'.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
materialRoute(RecoveryDomain()),
|
||||
(predicate) => false,
|
||||
);
|
||||
Navigator.of(context)
|
||||
.push(materialRoute(RecoveryDomain()));
|
||||
},
|
||||
),
|
||||
)
|
||||
|
|
|
@ -1,54 +1,75 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/pages/rootRoute.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
|
||||
class RecoveryDomain extends StatelessWidget {
|
||||
class RecoveryDomain extends StatefulWidget {
|
||||
@override
|
||||
State<RecoveryDomain> createState() => _RecoveryDomainState();
|
||||
}
|
||||
|
||||
class _RecoveryDomainState extends State<RecoveryDomain> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var cubit = context.watch<AppConfigCubit>();
|
||||
return BlocListener<AppConfigCubit, AppConfigState>(
|
||||
listener: (context, state) {
|
||||
if (cubit.state is AppConfigFinished) {
|
||||
Navigator.of(context).pushReplacement(materialRoute(RootPage()));
|
||||
}
|
||||
},
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.of(context).size.height -
|
||||
MediaQuery.of(context).padding.top -
|
||||
MediaQuery.of(context).padding.bottom -
|
||||
566,
|
||||
),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
child: BrandButton.text(
|
||||
title: cubit.state is AppConfigFinished
|
||||
? 'basis.close'.tr()
|
||||
: 'basis.later'.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
materialRoute(RootPage()),
|
||||
(predicate) => false,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return BrandHeroScreen(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: "recovering.domain_recover_placeholder".tr(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
BrandButton.rised(
|
||||
onPressed: () {},
|
||||
text: "more.continue".tr(),
|
||||
),
|
||||
],
|
||||
heroTitle: "recovering.recovery_main_header".tr(),
|
||||
heroSubtitle: "recovering.domain_recovery_description".tr(),
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
heroIcon: Icons.link,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*class RecoveryDomain extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: PreferredSize(
|
||||
preferredSize: Size.fromHeight(52),
|
||||
child: BrandHeader(hasBackButton: true),
|
||||
),
|
||||
body: ListView(
|
||||
padding: EdgeInsets.all(16),
|
||||
children: [
|
||||
Text(
|
||||
"recovering.recovery_main_header".tr(),
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
SizedBox(height: 18),
|
||||
Text(
|
||||
"recovering.domain_recovery_description".tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
SizedBox(height: 18),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: "recovering.domain_recover_placeholder".tr(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 18),
|
||||
BrandButton.rised(
|
||||
onPressed: () {},
|
||||
text: "more.continue".tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}*/
|
Loading…
Reference in a new issue