fdroid
Kherel 2021-02-16 19:48:15 +01:00
parent 20166647ea
commit 4f6137eaa1
7 changed files with 342 additions and 153 deletions

View File

@ -27,6 +27,7 @@ class BlocAndProviderConfig extends StatelessWidget {
)..load(),
),
BlocProvider(
lazy: false,
create: (_) => AppConfigCubit()..load(),
),
BlocProvider(create: (_) => ServicesCubit()),

View File

@ -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';
}

View File

@ -46,10 +46,164 @@ class AppConfigCubit extends Cubit<AppConfigState> {
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<AppConfigState> {
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<AppConfigState> {
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<AppConfigState> {
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<AppConfigState> {
onCancel: onCancel,
onSuccess: onSuccess,
);
};
_tryOrAddError(state, callback);
}
FutureOr<void> _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);
// }

View File

@ -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;
}

View File

@ -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<bool> 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;

View File

@ -53,12 +53,12 @@ class _ProgressBarState extends State<ProgressBar> {
..insert(
0,
SizedBox(
width: 50,
width: 40,
),
)
..add(
SizedBox(
width: 50,
width: 10,
),
);

View File

@ -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<AppConfigCubit>();
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<AppConfigCubit, AppConfigState>(
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) {