diff --git a/lib/config/bloc_config.dart b/lib/config/bloc_config.dart index 9079ee99e6..97ca686664 100644 --- a/lib/config/bloc_config.dart +++ b/lib/config/bloc_config.dart @@ -27,6 +27,7 @@ class BlocAndProviderConfig extends StatelessWidget { )..load(), ), BlocProvider( + lazy: false, create: (_) => AppConfigCubit()..load(), ), BlocProvider(create: (_) => ServicesCubit()), diff --git a/lib/config/hive_config.dart b/lib/config/hive_config.dart index c3699d938d..cf05097234 100644 --- a/lib/config/hive_config.dart +++ b/lib/config/hive_config.dart @@ -50,8 +50,9 @@ class BNames { static String cloudFlareKey = 'cloudFlareKey'; static String rootUser = 'rootUser'; static String hetznerServer = 'hetznerServer'; - // static String isDkimSetted = 'isDkimSetted'; - static String isDnsChecked = 'isDnsChecked'; + static String hasFinalChecked = 'hasFinalChecked'; static String isServerStarted = 'isServerStarted'; static String backblazeKey = 'backblazeKey'; + static String isLoading = 'isLoading'; + static String isServerReseted = 'isServerReseted'; } diff --git a/lib/logic/cubit/app_config/app_config_cubit.dart b/lib/logic/cubit/app_config/app_config_cubit.dart index 0b996dbcef..bc42f4e0f7 100644 --- a/lib/logic/cubit/app_config/app_config_cubit.dart +++ b/lib/logic/cubit/app_config/app_config_cubit.dart @@ -46,10 +46,164 @@ class AppConfigCubit extends Cubit { void load() { var state = repository.load(); - emit(state); + + if (state.progress < 6 || state.isFullyInitilized) { + emit(state); + } else if (state.progress == 6) { + print('startServerIfDnsIsOkay'); + + startServerIfDnsIsOkay(state: state, isImmediate: true); + } else if (state.progress == 7) { + print('resetServerIfServerIsOkay'); + + resetServerIfServerIsOkay(state: state, isImmediate: true); + } else if (state.progress == 8) { + print('finishCheckIfServerIsOkay'); + finishCheckIfServerIsOkay(state: state, isImmediate: true); + } + } + + void startServerIfDnsIsOkay({ + AppConfigState state, + bool isImmediate = false, + }) async { + state = state ?? this.state; + + final work = () async { + emit(TimerState(dataState: state, isLoading: true)); + + var ip4 = state.hetznerServer.ip4; + var domainName = state.cloudFlareDomain.domainName; + + var isMatch = await repository.isDnsAddressesMatch(domainName, ip4); + + if (isMatch) { + var server = await repository.startServer( + state.hetznerKey, + state.hetznerServer, + ); + repository.saveServerDetails(server); + emit( + state.copyWith( + isServerStarted: true, + isLoading: false, + hetznerServer: server, + ), + ); + resetServerIfServerIsOkay(); + } else { + startServerIfDnsIsOkay(); + } + }; + + if (isImmediate) { + work(); + } else { + var pauseDuration = Duration(seconds: 60); + emit(TimerState( + dataState: state, + timerStart: DateTime.now(), + duration: pauseDuration, + isLoading: false, + )); + timer = Timer(pauseDuration, work); + } + } + + void resetServerIfServerIsOkay({ + AppConfigState state, + bool isImmediate = false, + }) async { + state = state ?? this.state; + + var work = () async { + emit(TimerState(dataState: state, isLoading: true)); + + var isServerWorking = await repository.isHttpServerWorking( + state.cloudFlareDomain.domainName, + ); + + if (isServerWorking) { + var pauseDuration = Duration(seconds: 30); + emit(TimerState( + dataState: state, + timerStart: DateTime.now(), + isLoading: false, + duration: pauseDuration, + )); + timer = Timer(pauseDuration, () async { + var hetznerServerDetails = await repository.restart( + state.hetznerKey, + state.hetznerServer, + ); + emit( + state.copyWith( + isServerReseted: true, + hetznerServer: hetznerServerDetails, + isLoading: false, + ), + ); + finishCheckIfServerIsOkay(); + }); + } else { + resetServerIfServerIsOkay(); + } + }; + if (isImmediate) { + work(); + } else { + var pauseDuration = Duration(seconds: 60); + emit( + TimerState( + dataState: state, + timerStart: DateTime.now(), + duration: pauseDuration, + isLoading: false, + ), + ); + timer = Timer(pauseDuration, work); + } + } + + Timer timer; + + void finishCheckIfServerIsOkay({ + AppConfigState state, + bool isImmediate = false, + }) async { + state = state ?? this.state; + + var work = () async { + emit(TimerState(dataState: state, isLoading: true)); + + var isServerWorking = await repository.isHttpServerWorking( + state.cloudFlareDomain.domainName, + ); + + if (isServerWorking) { + emit(state.copyWith(hasFinalChecked: true, isLoading: false)); + } else { + finishCheckIfServerIsOkay(); + } + }; + if (isImmediate) { + work(); + } else { + var pauseDuration = Duration(seconds: 60); + emit( + TimerState( + dataState: state, + timerStart: DateTime.now(), + duration: pauseDuration, + isLoading: false, + ), + ); + timer = Timer(pauseDuration, work); + } } void clearAppConfig() { + _closeTimer(); repository.clearAppConfig(); emit(InitialAppConfigState()); } @@ -64,6 +218,15 @@ class AppConfigCubit extends Cubit { emit(state.copyWith(cloudFlareKey: cloudFlareKey)); } + void setBackblazeKey(String keyId, String applicationKey) { + var backblazeCredential = BackblazeCredential( + keyId: keyId, + applicationKey: applicationKey, + ); + repository.saveBackblazeKey(backblazeCredential); + emit(state.copyWith(backblazeCredential: backblazeCredential)); + } + void setDomain(CloudFlareDomain cloudFlareDomain) { repository.saveDomain(cloudFlareDomain); emit(state.copyWith(cloudFlareDomain: cloudFlareDomain)); @@ -74,53 +237,8 @@ class AppConfigCubit extends Cubit { emit(state.copyWith(rootUser: rootUser)); } - void serverReset() async { - var callBack = () async { - var isServerWorking = await repository.isHttpServerWorking( - state.cloudFlareDomain.domainName, - ); - if (!isServerWorking) { - var last = DateTime.now(); - emit(state.copyWith(lastServerStatusCheckTime: last)); - return; - } - - var hetznerServerDetails = await repository.restart( - state.hetznerKey, - state.hetznerServer, - ); - emit(state.copyWith(hetznerServer: hetznerServerDetails)); - }; - - _tryOrAddError(state, callBack); - } - - void checkDnsAndStartServer() async { - var ip4 = state.hetznerServer.ip4; - var domainName = state.cloudFlareDomain.domainName; - - var isMatch = await repository.isDnsAddressesMatch(domainName, ip4); - - if (isMatch) { - var server = await repository.startServer( - state.hetznerKey, - state.hetznerServer, - ); - repository.saveServerDetails(server); - emit( - state.copyWith( - isDnsChecked: true, - isServerStarted: true, - isLoading: false, - hetznerServer: server, - ), - ); - } else { - emit(state.copyWith(lastDnsCheckTime: DateTime.now())); - } - } - void createServerAndSetDnsRecords() async { + var _stateCopy = state; var onSuccess = (serverDetails) async { await repository.createDnsRecords( state.cloudFlareKey, @@ -132,11 +250,13 @@ class AppConfigCubit extends Cubit { isLoading: false, hetznerServer: serverDetails, )); + startServerIfDnsIsOkay(); }; var onCancel = () => emit(state.copyWith(isLoading: false)); - var callback = () async { + try { + emit(state.copyWith(isLoading: true)); await repository.createServer( state.hetznerKey, state.rootUser, @@ -145,30 +265,66 @@ class AppConfigCubit extends Cubit { onCancel: onCancel, onSuccess: onSuccess, ); - }; - _tryOrAddError(state, callback); - } - - FutureOr _tryOrAddError( - AppConfigState state, - AsyncCallback callback, - ) async { - emit(state.copyWith(isLoading: true)); - - try { - await callback(); } catch (e) { addError(e); - emit(state); + emit(_stateCopy); } } - void setBackblazeKey(String keyId, String applicationKey) { - var backblazeCredential = BackblazeCredential( - keyId: keyId, - applicationKey: applicationKey, - ); - repository.saveBackblazeKey(backblazeCredential); - emit(state.copyWith(backblazeCredential: backblazeCredential)); + close() { + _closeTimer(); + return super.close(); + } + + void _closeTimer() { + if (timer != null && timer.isActive) { + timer.cancel(); + } } } + +// void checkDnsAndStartServer() async { +// var ip4 = state.hetznerServer.ip4; +// var domainName = state.cloudFlareDomain.domainName; + +// var isMatch = await repository.isDnsAddressesMatch(domainName, ip4); + +// if (isMatch) { +// var server = await repository.startServer( +// state.hetznerKey, +// state.hetznerServer, +// ); +// repository.saveServerDetails(server); +// emit( +// state.copyWith( +// hasFinalChecked: true, +// isServerStarted: true, +// isLoading: false, +// hetznerServer: server, +// ), +// ); +// } else { +// emit(state.copyWith(lastDnsCheckTime: DateTime.now())); +// } +// } + +// void serverReset() async { +// var callBack = () async { +// var isServerWorking = await repository.isHttpServerWorking( +// state.cloudFlareDomain.domainName, +// ); +// if (!isServerWorking) { +// var last = DateTime.now(); +// // emit(state.copyWith(lastServerStatusCheckTime: last)); +// return; +// } + +// var hetznerServerDetails = await repository.restart( +// state.hetznerKey, +// state.hetznerServer, +// ); +// emit(state.copyWith(hetznerServer: hetznerServerDetails)); +// }; + +// _tryOrAddError(state, callBack); +// } diff --git a/lib/logic/cubit/app_config/app_config_repository.dart b/lib/logic/cubit/app_config/app_config_repository.dart index d1da034975..2370909744 100644 --- a/lib/logic/cubit/app_config/app_config_repository.dart +++ b/lib/logic/cubit/app_config/app_config_repository.dart @@ -28,7 +28,10 @@ class AppConfigRepository { rootUser: box.get(BNames.rootUser), hetznerServer: box.get(BNames.hetznerServer), isServerStarted: box.get(BNames.isServerStarted, defaultValue: false), - isDnsChecked: box.get(BNames.isDnsChecked, defaultValue: false), + error: null, + hasFinalChecked: box.get(BNames.hasFinalChecked, defaultValue: false), + isLoading: box.get(BNames.isLoading, defaultValue: false), + isServerReseted: box.get(BNames.isServerReseted, defaultValue: false), ); } @@ -107,7 +110,7 @@ class AppConfigRepository { } } - box.put(BNames.isDnsChecked, true); + box.put(BNames.hasFinalChecked, true); return true; } diff --git a/lib/logic/cubit/app_config/app_config_state.dart b/lib/logic/cubit/app_config/app_config_state.dart index b93e3c0ed5..caedcc2c4f 100644 --- a/lib/logic/cubit/app_config/app_config_state.dart +++ b/lib/logic/cubit/app_config/app_config_state.dart @@ -2,18 +2,17 @@ part of 'app_config_cubit.dart'; class AppConfigState extends Equatable { const AppConfigState({ - this.hetznerKey, - this.cloudFlareKey, - this.backblazeCredential, - this.cloudFlareDomain, - this.rootUser, - this.hetznerServer, - this.isLoading = false, - this.error, - // this.lastDnsCheckTime, - // this.lastServerStatusCheckTime, - this.isDnsChecked = false, - this.isServerStarted = false, + @required this.hetznerKey, + @required this.cloudFlareKey, + @required this.backblazeCredential, + @required this.cloudFlareDomain, + @required this.rootUser, + @required this.hetznerServer, + @required this.isServerStarted, + @required this.isServerReseted, + @required this.hasFinalChecked, + @required this.isLoading, + @required this.error, }); @override @@ -24,11 +23,11 @@ class AppConfigState extends Equatable { cloudFlareDomain, rootUser, hetznerServer, - isDnsCheckedAndServerStarted, + isServerStarted, + isServerReseted, + hasFinalChecked, isLoading, error, - // lastDnsCheckTime, - // lastServerStatusCheckTime, ]; final String hetznerKey; @@ -38,9 +37,9 @@ class AppConfigState extends Equatable { final User rootUser; final HetznerServerDetails hetznerServer; final bool isServerStarted; - final bool isDnsChecked; - // final DateTime lastDnsCheckTime; - // final DateTime lastServerStatusCheckTime; + final bool isServerReseted; + final bool hasFinalChecked; + final bool isLoading; final Exception error; @@ -51,12 +50,11 @@ class AppConfigState extends Equatable { CloudFlareDomain cloudFlareDomain, User rootUser, HetznerServerDetails hetznerServer, + bool isServerStarted, + bool isServerReseted, + bool hasFinalChecked, bool isLoading, Exception error, - DateTime lastDnsCheckTime, - DateTime lastServerStatusCheckTime, - bool isServerStarted, - bool isDnsChecked, }) => AppConfigState( hetznerKey: hetznerKey ?? this.hetznerKey, @@ -66,12 +64,10 @@ class AppConfigState extends Equatable { rootUser: rootUser ?? this.rootUser, hetznerServer: hetznerServer ?? this.hetznerServer, isServerStarted: isServerStarted ?? this.isServerStarted, - isDnsChecked: isDnsChecked ?? this.isDnsChecked, + isServerReseted: isServerReseted ?? this.isServerReseted, + hasFinalChecked: hasFinalChecked ?? this.hasFinalChecked, isLoading: isLoading ?? this.isLoading, error: error ?? this.error, - // lastDnsCheckTime: lastDnsCheckTime ?? this.lastDnsCheckTime, - // lastServerStatusCheckTime: - // lastServerStatusCheckTime ?? this.lastServerStatusCheckTime, ); bool get isHetznerFilled => hetznerKey != null; @@ -79,13 +75,9 @@ class AppConfigState extends Equatable { bool get isBackblazeFilled => backblazeCredential != null; bool get isDomainFilled => cloudFlareDomain != null; bool get isUserFilled => rootUser != null; - bool get isServerFilled => hetznerServer != null; - bool get hasFinalChecked => isDnsCheckedAndServerStarted; - - bool get isDnsCheckedAndServerStarted => isDnsChecked && isServerStarted; + bool get isServerCreated => hetznerServer != null; bool get isFullyInitilized => _fulfilementList.every((el) => el); - int get progress => _fulfilementList.where((el) => el).length; List get _fulfilementList => [ @@ -94,21 +86,49 @@ class AppConfigState extends Equatable { isBackblazeFilled, isDomainFilled, isUserFilled, - isServerFilled, + isServerCreated, + isServerStarted, + isServerReseted, hasFinalChecked, ]; } class InitialAppConfigState extends AppConfigState { - InitialAppConfigState() : super(); + InitialAppConfigState() + : super( + hetznerKey: null, + cloudFlareKey: null, + backblazeCredential: null, + cloudFlareDomain: null, + rootUser: null, + hetznerServer: null, + isServerStarted: false, + isServerReseted: false, + hasFinalChecked: false, + isLoading: false, + error: null, + ); } class TimerState extends AppConfigState { TimerState({ - this.dataState, + @required this.dataState, this.timerStart, this.duration, - }) : super(); + @required bool isLoading, + }) : super( + hetznerKey: dataState.hetznerKey, + cloudFlareKey: dataState.cloudFlareKey, + backblazeCredential: dataState.backblazeCredential, + cloudFlareDomain: dataState.cloudFlareDomain, + rootUser: dataState.rootUser, + hetznerServer: dataState.hetznerServer, + isServerStarted: dataState.isServerStarted, + isServerReseted: dataState.isServerReseted, + hasFinalChecked: dataState.hasFinalChecked, + isLoading: isLoading, + error: dataState.error, + ); final AppConfigState dataState; final DateTime timerStart; diff --git a/lib/ui/components/progress_bar/progress_bar.dart b/lib/ui/components/progress_bar/progress_bar.dart index 2adf8a97ef..9f3ddba85c 100644 --- a/lib/ui/components/progress_bar/progress_bar.dart +++ b/lib/ui/components/progress_bar/progress_bar.dart @@ -53,12 +53,12 @@ class _ProgressBarState extends State { ..insert( 0, SizedBox( - width: 50, + width: 40, ), ) ..add( SizedBox( - width: 50, + width: 10, ), ); diff --git a/lib/ui/pages/initializing/initializing.dart b/lib/ui/pages/initializing/initializing.dart index 6a1db999db..52ccb5a594 100644 --- a/lib/ui/pages/initializing/initializing.dart +++ b/lib/ui/pages/initializing/initializing.dart @@ -16,6 +16,7 @@ import 'package:selfprivacy/ui/components/brand_card/brand_card.dart'; import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart'; import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart'; 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/rootRoute.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; @@ -25,16 +26,17 @@ class InitializingPage extends StatelessWidget { Widget build(BuildContext context) { var cubit = context.watch(); var actualPage = [ - _stepHetzner(cubit), - _stepCloudflare(cubit), - _stepBackblaze(cubit), - _stepDomain(cubit), - _stepUser(cubit), - _stepServer(cubit), - _stepCheck(cubit), - Container(child: Text('Everythigng is initialized')) - ][cubit.state.progress]; - + () => _stepHetzner(cubit), + () => _stepCloudflare(cubit), + () => _stepBackblaze(cubit), + () => _stepDomain(cubit), + () => _stepUser(cubit), + () => _stepServer(cubit), + () => _stepCheck(cubit), + () => _stepCheck(cubit), + () => _stepCheck(cubit), + () => Container(child: Text('Everythigng is initialized')) + ][cubit.state.progress](); return BlocListener( listener: (context, state) { if (state.isFullyInitilized) { @@ -420,40 +422,46 @@ class InitializingPage extends StatelessWidget { } Widget _stepCheck(AppConfigCubit appConfigCubit) { - return Text('step check'); - // var state = appConfigCubit.state as TimerState; - // var isDnsChecked = state.dataState.isDnsChecked; - // return Builder(builder: (context) { - // return Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Spacer(flex: 2), - // SizedBox(height: 10), - // BrandText.body2( - // isDnsChecked - // ? 'Dns сервера вступили в силу, мы стартанули сервер, как только он поднимется, мы закончим инициализацию.' - // : 'Мы начали процесс инциализации сервера, раз в минуту мы будем проверять наличие DNS записей, как только они вступят в силу мы продолжим инциализацию', - // ), - // SizedBox(height: 10), - // Row( - // children: [ - // BrandText.body2('До следующей проверки: '), - // BrandTimer( - // startDateTime: state.timerStart, - // duration: state.duration, - // ) - // ], - // ), - // Spacer( - // flex: 2, - // ), - // BrandButton.text( - // onPressed: () => _showModal(context, _HowHetzner()), - // title: 'Что это значит?', - // ), - // ], - // ); - // }); + assert(appConfigCubit.state is TimerState, 'wronge state'); + var state = appConfigCubit.state as TimerState; + + String text; + if (state.isServerReseted) { + text = 'Сервер презагружен, ждем последнюю проверку'; + } else if (state.isServerStarted) { + text = 'Cервер запушен, сейчас он будет проверен и перезагружен'; + } else if (state.isServerCreated) { + text = 'Cервер создан, идет проверка ДНС адресов и запуск сервера'; + } + return Builder(builder: (context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Spacer(flex: 2), + SizedBox(height: 10), + BrandText.body2(text), + SizedBox(height: 10), + if (!state.isLoading) + Row( + children: [ + BrandText.body2('До следующей проверки: '), + BrandTimer( + startDateTime: state.timerStart, + duration: state.duration, + ) + ], + ), + if (state.isLoading) BrandText.body2('Проверка'), + Spacer( + flex: 2, + ), + BrandButton.text( + onPressed: () => _showModal(context, _HowHetzner()), + title: 'Что это значит?', + ), + ], + ); + }); } Widget _addCard(Widget child) {