mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-11 18:39:45 +00:00
update
This commit is contained in:
parent
a07a7247f5
commit
20166647ea
Binary file not shown.
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 23 KiB |
|
@ -49,4 +49,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||
|
||||
COCOAPODS: 1.10.0
|
||||
COCOAPODS: 1.10.1
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/ui/components/error/error.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
class SimpleBlocObserver extends BlocObserver {
|
||||
final GlobalKey<NavigatorState> navigatorKey;
|
||||
import 'get_it_config.dart';
|
||||
|
||||
SimpleBlocObserver({this.navigatorKey});
|
||||
class SimpleBlocObserver extends BlocObserver {
|
||||
SimpleBlocObserver();
|
||||
|
||||
@override
|
||||
void onError(Cubit cubit, Object error, StackTrace stackTrace) {
|
||||
navigatorKey.currentState.push(
|
||||
final navigator = getIt.get<NavigationService>().navigator;
|
||||
|
||||
navigator.push(
|
||||
materialRoute(
|
||||
BrandError(
|
||||
error: error,
|
||||
|
|
|
@ -56,6 +56,7 @@ var darkTheme = ligtTheme.copyWith(
|
|||
scaffoldBackgroundColor: Color(0xFF202120),
|
||||
iconTheme: IconThemeData(color: BrandColors.gray3),
|
||||
cardColor: BrandColors.gray1,
|
||||
dialogBackgroundColor: Color(0xFF202120),
|
||||
textTheme: GoogleFonts.interTextTheme(
|
||||
TextTheme(
|
||||
headline1: headline1Style.copyWith(color: BrandColors.white),
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
import 'package:get_it/get_it.dart';
|
||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||
import 'package:selfprivacy/logic/get_it/timer.dart';
|
||||
|
||||
export 'package:selfprivacy/logic/get_it/console.dart';
|
||||
export 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||
export 'package:selfprivacy/logic/get_it/timer.dart';
|
||||
|
||||
final getIt = GetIt.instance;
|
||||
|
||||
void getItSetup() {
|
||||
getIt.registerSingleton<NavigationService>(NavigationService());
|
||||
|
||||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||
getIt.registerSingleton<TimerModel>(TimerModel());
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ class BNames {
|
|||
static String cloudFlareKey = 'cloudFlareKey';
|
||||
static String rootUser = 'rootUser';
|
||||
static String hetznerServer = 'hetznerServer';
|
||||
static String isDkimSetted = 'isDkimSetted';
|
||||
// static String isDkimSetted = 'isDkimSetted';
|
||||
static String isDnsChecked = 'isDnsChecked';
|
||||
static String isServerStarted = 'isServerStarted';
|
||||
static String backblazeKey = 'backblazeKey';
|
||||
|
|
|
@ -46,6 +46,13 @@ final body2Style = defaultTextStyle.copyWith(
|
|||
color: BrandColors.textColor2,
|
||||
);
|
||||
|
||||
final buttonTitleText = defaultTextStyle.copyWith(
|
||||
color: BrandColors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1,
|
||||
);
|
||||
|
||||
final mediumStyle = defaultTextStyle.copyWith(fontSize: 13, height: 1.53);
|
||||
|
||||
final smallStyle = defaultTextStyle.copyWith(fontSize: 11, height: 1.45);
|
||||
|
|
|
@ -27,7 +27,6 @@ class BackblazeApi extends ApiMap {
|
|||
Response response = await loggedClient.get(rootAddress, options: options);
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
print(response);
|
||||
return true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
return false;
|
||||
|
|
|
@ -105,20 +105,20 @@ class CloudflareApi extends ApiMap {
|
|||
await Future.wait(allCreateFutures);
|
||||
}
|
||||
|
||||
setDkim(String dkimRecordString, String domainZoneId) {
|
||||
var txt3 = DnsRecords(
|
||||
type: 'TXT',
|
||||
name: 'selector._domainkey',
|
||||
content: dkimRecordString,
|
||||
ttl: 18000,
|
||||
);
|
||||
// setDkim(String dkimRecordString, String domainZoneId) {
|
||||
// var txt3 = DnsRecords(
|
||||
// type: 'TXT',
|
||||
// name: 'selector._domainkey',
|
||||
// content: dkimRecordString,
|
||||
// ttl: 18000,
|
||||
// );
|
||||
|
||||
var url = '$rootAddress/zones/$domainZoneId/dns_records';
|
||||
loggedClient.post(
|
||||
url,
|
||||
data: txt3.toJson(),
|
||||
);
|
||||
}
|
||||
// var url = '$rootAddress/zones/$domainZoneId/dns_records';
|
||||
// loggedClient.post(
|
||||
// url,
|
||||
// data: txt3.toJson(),
|
||||
// );
|
||||
// }
|
||||
|
||||
List<DnsRecords> projectDnsRecords(String domainName, String ip4) {
|
||||
var domainA = DnsRecords(type: 'A', name: domainName, content: ip4);
|
||||
|
@ -160,4 +160,16 @@ class CloudflareApi extends ApiMap {
|
|||
vpn
|
||||
];
|
||||
}
|
||||
|
||||
Future<List<String>> domainList() async {
|
||||
var url = '$rootAddress/zones?per_page=50';
|
||||
var response = await loggedClient.get(
|
||||
url,
|
||||
queryParameters: {'per_page': 50},
|
||||
);
|
||||
|
||||
return response.data['result']
|
||||
.map<String>((el) => el['name'] as String)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,16 @@ class HetznerApi extends ApiMap {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> deleteSelfprivacyServer({
|
||||
@required String cloudFlareKey,
|
||||
}) async {
|
||||
Response response = await loggedClient.get(rootAddress);
|
||||
|
||||
List list = response.data['servers'];
|
||||
var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server');
|
||||
return await loggedClient.delete('$rootAddress/${server['id']}');
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> startServer({
|
||||
HetznerServerDetails server,
|
||||
}) async {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
@ -26,22 +25,22 @@ class ServerApi extends ApiMap {
|
|||
return res;
|
||||
}
|
||||
|
||||
Future<String> getDkim(String domainName) async {
|
||||
var response = await loggedClient.get(
|
||||
'/getDKIM',
|
||||
options: Options(responseType: ResponseType.plain),
|
||||
);
|
||||
return _decodeAndCutData(response.data, domainName);
|
||||
}
|
||||
// Future<String> getDkim(String domainName) async {
|
||||
// var response = await loggedClient.get(
|
||||
// '/getDKIM',
|
||||
// options: Options(responseType: ResponseType.plain),
|
||||
// );
|
||||
// return _decodeAndCutData(response.data, domainName);
|
||||
// }
|
||||
}
|
||||
|
||||
String _decodeAndCutData(String text, String domainName) {
|
||||
var decodedTextString = text.substring(1, text.length - 1);
|
||||
var stringToBase64 = utf8.fuse(base64);
|
||||
// String _decodeAndCutData(String text, String domainName) {
|
||||
// var decodedTextString = text.substring(1, text.length - 1);
|
||||
// var stringToBase64 = utf8.fuse(base64);
|
||||
|
||||
return stringToBase64
|
||||
.decode(decodedTextString)
|
||||
.replaceAll("selector._domainkey IN TXT ( ", "")
|
||||
.replaceAll("\"\n \"", "")
|
||||
.replaceAll(' ) ; ----- DKIM key selector for $domainName\n', '');
|
||||
}
|
||||
// return stringToBase64
|
||||
// .decode(decodedTextString)
|
||||
// .replaceAll("selector._domainkey IN TXT ( ", "")
|
||||
// .replaceAll("\"\n \"", "")
|
||||
// .replaceAll(' ) ; ----- DKIM key selector for $domainName\n', '');
|
||||
// }
|
||||
|
|
|
@ -14,22 +14,30 @@ import 'app_config_repository.dart';
|
|||
part 'app_config_state.dart';
|
||||
|
||||
/// Initializing steps:
|
||||
/// 1. Hetzner key |setHetznerKey
|
||||
/// 2. Cloudflare key |setCloudflareKey
|
||||
/// 3. Backblaze Id + Key |setBackblazeKey
|
||||
|
||||
/// 4. Set Domain address |setDomain
|
||||
/// 5. Set Root user name password |setRootUser
|
||||
/// 6. Set Create server ans set DNS-Records |createServerAndSetDnsRecords
|
||||
///
|
||||
/// The set phase.
|
||||
/// 1.1. Hetzner key |setHetznerKey
|
||||
/// 1.2. Cloudflare key |setCloudflareKey
|
||||
/// 1.3. Backblaze Id + Key |setBackblazeKey
|
||||
/// 1.4. Set Domain address |setDomain
|
||||
/// 1.5. Set Root user name password |setRootUser
|
||||
/// 1.6. Set Create server ans set DNS-Records |createServerAndSetDnsRecords
|
||||
/// (without start)
|
||||
/// 7. ChecksAndSets:
|
||||
/// 7.1 checkDnsAndStartServer |checkDnsAndStartServer
|
||||
/// 7.2 setDkim |setDkim
|
||||
/// a. checkServer
|
||||
/// b. getDkim
|
||||
/// c. Set DKIM
|
||||
/// d. server restart
|
||||
|
||||
///
|
||||
/// The check phase.
|
||||
///
|
||||
/// 2.1. a. wait 60sec checkDnsAndStartServer |startServerIfDnsIsOkay
|
||||
/// b. checkDns
|
||||
/// c. if dns is okay start server
|
||||
///
|
||||
/// 2.2. a. wait 60sec |resetServerIfServerIsOkay
|
||||
/// b. checkServer
|
||||
/// c. if server is ok wait 30 sec
|
||||
/// d. reset server
|
||||
///
|
||||
/// 2.3. a. wait 60sec |finishCheckIfServerIsOkay
|
||||
/// b. checkServer
|
||||
/// c. if server is okay set that fully checked
|
||||
|
||||
class AppConfigCubit extends Cubit<AppConfigState> {
|
||||
AppConfigCubit() : super(InitialAppConfigState());
|
||||
|
@ -66,34 +74,22 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
emit(state.copyWith(rootUser: rootUser));
|
||||
}
|
||||
|
||||
void setDkim() async {
|
||||
void serverReset() async {
|
||||
var callBack = () async {
|
||||
var isServerWorking = await repository.isHttpServerWorking(
|
||||
state.cloudFlareDomain.domainName,
|
||||
);
|
||||
if (!isServerWorking) {
|
||||
var last = DateTime.now();
|
||||
print(last);
|
||||
emit(state.copyWith(lastServerStatusCheckTime: last));
|
||||
return;
|
||||
}
|
||||
|
||||
await repository.setDkim(
|
||||
state.cloudFlareDomain.domainName,
|
||||
state.cloudFlareKey,
|
||||
state.cloudFlareDomain.zoneId,
|
||||
);
|
||||
|
||||
var hetznerServerDetails = await repository.restart(
|
||||
state.hetznerKey,
|
||||
state.hetznerServer,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
isDkimSetted: true,
|
||||
hetznerServer: hetznerServerDetails,
|
||||
),
|
||||
);
|
||||
emit(state.copyWith(hetznerServer: hetznerServerDetails));
|
||||
};
|
||||
|
||||
_tryOrAddError(state, callBack);
|
||||
|
@ -125,14 +121,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
}
|
||||
|
||||
void createServerAndSetDnsRecords() async {
|
||||
var callback = () async {
|
||||
var serverDetails = await repository.createServer(
|
||||
state.hetznerKey,
|
||||
state.rootUser,
|
||||
state.cloudFlareDomain.domainName,
|
||||
state.cloudFlareKey,
|
||||
);
|
||||
|
||||
var onSuccess = (serverDetails) async {
|
||||
await repository.createDnsRecords(
|
||||
state.cloudFlareKey,
|
||||
serverDetails.ip4,
|
||||
|
@ -144,6 +133,19 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
hetznerServer: serverDetails,
|
||||
));
|
||||
};
|
||||
|
||||
var onCancel = () => emit(state.copyWith(isLoading: false));
|
||||
|
||||
var callback = () async {
|
||||
await repository.createServer(
|
||||
state.hetznerKey,
|
||||
state.rootUser,
|
||||
state.cloudFlareDomain.domainName,
|
||||
state.cloudFlareKey,
|
||||
onCancel: onCancel,
|
||||
onSuccess: onSuccess,
|
||||
);
|
||||
};
|
||||
_tryOrAddError(state, callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:dio/dio.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
|
@ -11,6 +12,8 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/get_it/console.dart';
|
||||
import 'package:selfprivacy/logic/models/message.dart';
|
||||
import 'package:basic_utils/basic_utils.dart';
|
||||
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
||||
import 'app_config_cubit.dart';
|
||||
|
||||
class AppConfigRepository {
|
||||
|
@ -26,7 +29,6 @@ class AppConfigRepository {
|
|||
hetznerServer: box.get(BNames.hetznerServer),
|
||||
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
|
||||
isDnsChecked: box.get(BNames.isDnsChecked, defaultValue: false),
|
||||
isDkimSetted: box.get(BNames.isDkimSetted, defaultValue: false),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -110,19 +112,64 @@ class AppConfigRepository {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> createServer(String hetznerKey, User rootUser,
|
||||
String domainName, String cloudFlareKey) async {
|
||||
Future<void> createServer(
|
||||
String hetznerKey,
|
||||
User rootUser,
|
||||
String domainName,
|
||||
String cloudFlareKey, {
|
||||
void Function() onCancel,
|
||||
Future<void> Function(HetznerServerDetails serverDetails) onSuccess,
|
||||
}) async {
|
||||
var hetznerApi = HetznerApi(hetznerKey);
|
||||
|
||||
try {
|
||||
var serverDetails = await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
);
|
||||
await box.put(BNames.hetznerServer, serverDetails);
|
||||
hetznerApi.close();
|
||||
onSuccess(serverDetails);
|
||||
} on DioError catch (e) {
|
||||
if (e.response.data['error']['code'] == 'uniqueness_error') {
|
||||
var nav = getIt.get<NavigationService>();
|
||||
nav.showPopUpDialog(
|
||||
BrandAlert(
|
||||
title: 'Сервер с таким именем уже существует',
|
||||
contentText: 'Уничтожить сервер и создать новый?',
|
||||
acitons: [
|
||||
ActionButton(
|
||||
text: 'Удалить',
|
||||
isRed: true,
|
||||
onPressed: () async {
|
||||
await hetznerApi.deleteSelfprivacyServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
);
|
||||
|
||||
var serverDetails = await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
);
|
||||
hetznerApi.close();
|
||||
|
||||
return serverDetails;
|
||||
await box.put(BNames.hetznerServer, serverDetails);
|
||||
onSuccess(serverDetails);
|
||||
},
|
||||
),
|
||||
ActionButton(
|
||||
text: 'Отменить',
|
||||
onPressed: () {
|
||||
hetznerApi.close();
|
||||
onCancel();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createDnsRecords(
|
||||
|
@ -152,21 +199,6 @@ class AppConfigRepository {
|
|||
return isHttpServerWorking;
|
||||
}
|
||||
|
||||
Future<void> setDkim(
|
||||
String domainName,
|
||||
String cloudFlareKey,
|
||||
String zoneId,
|
||||
) async {
|
||||
var api = ServerApi(domainName);
|
||||
var dkimRecordString = await api.getDkim(domainName);
|
||||
var cloudflareApi = CloudflareApi(cloudFlareKey);
|
||||
|
||||
await cloudflareApi.setDkim(dkimRecordString, zoneId);
|
||||
box.put(BNames.isDkimSetted, true);
|
||||
|
||||
cloudflareApi.close();
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> restart(
|
||||
String hetznerKey,
|
||||
HetznerServerDetails server,
|
||||
|
|
|
@ -10,11 +10,10 @@ class AppConfigState extends Equatable {
|
|||
this.hetznerServer,
|
||||
this.isLoading = false,
|
||||
this.error,
|
||||
this.lastDnsCheckTime,
|
||||
this.lastServerStatusCheckTime,
|
||||
// this.lastDnsCheckTime,
|
||||
// this.lastServerStatusCheckTime,
|
||||
this.isDnsChecked = false,
|
||||
this.isServerStarted = false,
|
||||
this.isDkimSetted = false,
|
||||
});
|
||||
|
||||
@override
|
||||
|
@ -28,9 +27,8 @@ class AppConfigState extends Equatable {
|
|||
isDnsCheckedAndServerStarted,
|
||||
isLoading,
|
||||
error,
|
||||
lastDnsCheckTime,
|
||||
lastServerStatusCheckTime,
|
||||
isDkimSetted,
|
||||
// lastDnsCheckTime,
|
||||
// lastServerStatusCheckTime,
|
||||
];
|
||||
|
||||
final String hetznerKey;
|
||||
|
@ -39,11 +37,10 @@ class AppConfigState extends Equatable {
|
|||
final CloudFlareDomain cloudFlareDomain;
|
||||
final User rootUser;
|
||||
final HetznerServerDetails hetznerServer;
|
||||
final bool isDkimSetted;
|
||||
final bool isServerStarted;
|
||||
final bool isDnsChecked;
|
||||
final DateTime lastDnsCheckTime;
|
||||
final DateTime lastServerStatusCheckTime;
|
||||
// final DateTime lastDnsCheckTime;
|
||||
// final DateTime lastServerStatusCheckTime;
|
||||
final bool isLoading;
|
||||
final Exception error;
|
||||
|
||||
|
@ -58,7 +55,6 @@ class AppConfigState extends Equatable {
|
|||
Exception error,
|
||||
DateTime lastDnsCheckTime,
|
||||
DateTime lastServerStatusCheckTime,
|
||||
bool isDkimSetted,
|
||||
bool isServerStarted,
|
||||
bool isDnsChecked,
|
||||
}) =>
|
||||
|
@ -73,10 +69,9 @@ class AppConfigState extends Equatable {
|
|||
isDnsChecked: isDnsChecked ?? this.isDnsChecked,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
error: error ?? this.error,
|
||||
lastDnsCheckTime: lastDnsCheckTime ?? this.lastDnsCheckTime,
|
||||
lastServerStatusCheckTime:
|
||||
lastServerStatusCheckTime ?? this.lastServerStatusCheckTime,
|
||||
isDkimSetted: isDkimSetted ?? this.isDkimSetted,
|
||||
// lastDnsCheckTime: lastDnsCheckTime ?? this.lastDnsCheckTime,
|
||||
// lastServerStatusCheckTime:
|
||||
// lastServerStatusCheckTime ?? this.lastServerStatusCheckTime,
|
||||
);
|
||||
|
||||
bool get isHetznerFilled => hetznerKey != null;
|
||||
|
@ -85,7 +80,7 @@ class AppConfigState extends Equatable {
|
|||
bool get isDomainFilled => cloudFlareDomain != null;
|
||||
bool get isUserFilled => rootUser != null;
|
||||
bool get isServerFilled => hetznerServer != null;
|
||||
bool get hasFinalChecked => isDnsCheckedAndServerStarted && isDkimSetted;
|
||||
bool get hasFinalChecked => isDnsCheckedAndServerStarted;
|
||||
|
||||
bool get isDnsCheckedAndServerStarted => isDnsChecked && isServerStarted;
|
||||
|
||||
|
@ -107,3 +102,22 @@ class AppConfigState extends Equatable {
|
|||
class InitialAppConfigState extends AppConfigState {
|
||||
InitialAppConfigState() : super();
|
||||
}
|
||||
|
||||
class TimerState extends AppConfigState {
|
||||
TimerState({
|
||||
this.dataState,
|
||||
this.timerStart,
|
||||
this.duration,
|
||||
}) : super();
|
||||
|
||||
final AppConfigState dataState;
|
||||
final DateTime timerStart;
|
||||
final Duration duration;
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
dataState,
|
||||
timerStart,
|
||||
duration,
|
||||
];
|
||||
}
|
||||
|
|
78
lib/logic/cubit/forms/initializing/domain_cloudflare.dart
Normal file
78
lib/logic/cubit/forms/initializing/domain_cloudflare.dart
Normal file
|
@ -0,0 +1,78 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
|
||||
|
||||
class DomainSetupCubit extends Cubit<DomainSetupState> {
|
||||
DomainSetupCubit(this.initializingCubit) : super(Initial()) {
|
||||
var token = (initializingCubit.state.cloudFlareKey);
|
||||
|
||||
assert(token != null, 'no cloudflare token');
|
||||
|
||||
api = CloudflareApi(token);
|
||||
}
|
||||
|
||||
AppConfigCubit initializingCubit;
|
||||
CloudflareApi api;
|
||||
|
||||
Future<void> load() async {
|
||||
emit(Loading(LoadingTypes.loadingDomain));
|
||||
var list = await api.domainList();
|
||||
if (list.isEmpty) {
|
||||
emit(Empty());
|
||||
} else if (list.length == 1) {
|
||||
emit(Loaded(list.first));
|
||||
} else {
|
||||
emit(MoreThenOne());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
api.close();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<void> saveDomain() async {
|
||||
assert(state is Loaded, 'wrong state');
|
||||
var domainName = (state as Loaded).domain;
|
||||
|
||||
emit(Loading(LoadingTypes.saving));
|
||||
|
||||
var zoneId = await api.getZoneId(
|
||||
initializingCubit.state.cloudFlareKey,
|
||||
domainName,
|
||||
);
|
||||
|
||||
var domain = CloudFlareDomain(
|
||||
domainName: domainName,
|
||||
zoneId: zoneId,
|
||||
);
|
||||
|
||||
initializingCubit.setDomain(domain);
|
||||
emit(DomainSetted());
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DomainSetupState {}
|
||||
|
||||
class Initial extends DomainSetupState {}
|
||||
|
||||
class Empty extends DomainSetupState {}
|
||||
|
||||
class MoreThenOne extends DomainSetupState {}
|
||||
|
||||
class Loading extends DomainSetupState {
|
||||
Loading(this.type);
|
||||
final LoadingTypes type;
|
||||
}
|
||||
|
||||
enum LoadingTypes { loadingDomain, saving }
|
||||
|
||||
class Loaded extends DomainSetupState {
|
||||
final String domain;
|
||||
|
||||
Loaded(this.domain);
|
||||
}
|
||||
|
||||
class DomainSetted extends DomainSetupState {}
|
|
@ -1,68 +1,68 @@
|
|||
import 'dart:async';
|
||||
// import 'dart:async';
|
||||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
|
||||
// import 'package:cubit_form/cubit_form.dart';
|
||||
// import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
// import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
// import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
|
||||
|
||||
class DomainFormCubit extends FormCubit {
|
||||
CloudflareApi apiClient = CloudflareApi();
|
||||
// class DomainFormCubit extends FormCubit {
|
||||
// CloudflareApi apiClient = CloudflareApi();
|
||||
|
||||
DomainFormCubit(this.initializingCubit) {
|
||||
var regExp =
|
||||
RegExp(r"^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}");
|
||||
domainName = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('required'),
|
||||
ValidationModel<String>(
|
||||
(s) => !regExp.hasMatch(s),
|
||||
'invalid domain format',
|
||||
),
|
||||
],
|
||||
);
|
||||
// DomainFormCubit(this.initializingCubit) {
|
||||
// var regExp =
|
||||
// RegExp(r"^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}");
|
||||
// domainName = FieldCubit(
|
||||
// initalValue: '',
|
||||
// validations: [
|
||||
// RequiredStringValidation('required'),
|
||||
// ValidationModel<String>(
|
||||
// (s) => !regExp.hasMatch(s),
|
||||
// 'invalid domain format',
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
|
||||
super.setFields([domainName]);
|
||||
}
|
||||
// super.setFields([domainName]);
|
||||
// }
|
||||
|
||||
@override
|
||||
FutureOr<void> onSubmit() async {
|
||||
var domain = CloudFlareDomain(
|
||||
domainName: domainName.state.value,
|
||||
zoneId: zoneId,
|
||||
);
|
||||
initializingCubit.setDomain(domain);
|
||||
}
|
||||
// @override
|
||||
// FutureOr<void> onSubmit() async {
|
||||
// var domain = CloudFlareDomain(
|
||||
// domainName: domainName.state.value,
|
||||
// zoneId: zoneId,
|
||||
// );
|
||||
// initializingCubit.setDomain(domain);
|
||||
// }
|
||||
|
||||
final AppConfigCubit initializingCubit;
|
||||
// final AppConfigCubit initializingCubit;
|
||||
|
||||
FieldCubit<String> domainName;
|
||||
String zoneId;
|
||||
// FieldCubit<String> domainName;
|
||||
// String zoneId;
|
||||
|
||||
@override
|
||||
FutureOr<bool> asyncValidation() async {
|
||||
var key = initializingCubit.state.cloudFlareKey;
|
||||
// @override
|
||||
// FutureOr<bool> asyncValidation() async {
|
||||
// var key = initializingCubit.state.cloudFlareKey;
|
||||
|
||||
String zoneId;
|
||||
// String zoneId;
|
||||
|
||||
try {
|
||||
zoneId = await apiClient.getZoneId(key, domainName.state.value);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
}
|
||||
// try {
|
||||
// zoneId = await apiClient.getZoneId(key, domainName.state.value);
|
||||
// } catch (e) {
|
||||
// addError(e);
|
||||
// }
|
||||
|
||||
if (zoneId == null) {
|
||||
domainName.setError('Domain not in the list');
|
||||
return false;
|
||||
}
|
||||
this.zoneId = zoneId;
|
||||
return true;
|
||||
}
|
||||
// if (zoneId == null) {
|
||||
// domainName.setError('Domain not in the list');
|
||||
// return false;
|
||||
// }
|
||||
// this.zoneId = zoneId;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
apiClient.close();
|
||||
// @override
|
||||
// Future<void> close() async {
|
||||
// apiClient.close();
|
||||
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
// return super.close();
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -30,7 +30,9 @@ class RootUserFormCubit extends FormCubit {
|
|||
],
|
||||
);
|
||||
|
||||
super.setFields([userName, password]);
|
||||
isVisible = FieldCubit(initalValue: false);
|
||||
|
||||
super.setFields([userName, password, isVisible]);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -46,6 +48,7 @@ class RootUserFormCubit extends FormCubit {
|
|||
|
||||
FieldCubit<String> userName;
|
||||
FieldCubit<String> password;
|
||||
FieldCubit<bool> isVisible;
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
|
|
16
lib/logic/get_it/navigation.dart
Normal file
16
lib/logic/get_it/navigation.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class NavigationService {
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
NavigatorState get navigator => navigatorKey.currentState;
|
||||
|
||||
void showPopUpDialog(AlertDialog dialog) {
|
||||
final context = navigatorKey.currentState.overlay.context;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => dialog,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -15,11 +15,10 @@ import 'config/get_it_config.dart';
|
|||
import 'config/localization.dart';
|
||||
import 'logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
|
||||
final navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
void main() async {
|
||||
await HiveConfig.init();
|
||||
Bloc.observer = SimpleBlocObserver(navigatorKey: navigatorKey);
|
||||
Bloc.observer = SimpleBlocObserver();
|
||||
Wakelock.enable();
|
||||
getItSetup();
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
@ -41,7 +40,7 @@ class MyApp extends StatelessWidget {
|
|||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
||||
child: MaterialApp(
|
||||
navigatorKey: navigatorKey,
|
||||
navigatorKey: getIt.get<NavigationService>().navigatorKey,
|
||||
localizationsDelegates: context.localizationDelegates,
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
|
|
31
lib/ui/components/action_button/action_button.dart
Normal file
31
lib/ui/components/action_button/action_button.dart
Normal file
|
@ -0,0 +1,31 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
|
||||
class ActionButton extends StatelessWidget {
|
||||
const ActionButton({
|
||||
Key key,
|
||||
this.text,
|
||||
this.onPressed,
|
||||
this.isRed = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onPressed;
|
||||
final String text;
|
||||
final bool isRed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var navigator = Navigator.of(context);
|
||||
|
||||
return TextButton(
|
||||
child: Text(
|
||||
text,
|
||||
style: isRed ? TextStyle(color: BrandColors.red1) : null,
|
||||
),
|
||||
onPressed: () {
|
||||
navigator.pop();
|
||||
if (onPressed != null) onPressed();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
15
lib/ui/components/brand_alert/brand_alert.dart
Normal file
15
lib/ui/components/brand_alert/brand_alert.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class BrandAlert extends AlertDialog {
|
||||
BrandAlert({
|
||||
Key key,
|
||||
String title,
|
||||
String contentText,
|
||||
List<Widget> acitons,
|
||||
}) : super(
|
||||
key: key,
|
||||
title: title != null ? Text(title) : null,
|
||||
content: title != null ? Text(contentText) : null,
|
||||
actions: acitons,
|
||||
);
|
||||
}
|
|
@ -6,42 +6,32 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
|||
|
||||
enum BrandButtonTypes { rised, text, iconText }
|
||||
|
||||
class BrandButton extends StatelessWidget {
|
||||
const BrandButton({
|
||||
Key key,
|
||||
this.onPressed,
|
||||
this.type,
|
||||
this.title,
|
||||
this.icon,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onPressed;
|
||||
final BrandButtonTypes type;
|
||||
final String title;
|
||||
final Icon icon;
|
||||
|
||||
class BrandButton {
|
||||
static rised({
|
||||
Key key,
|
||||
@required VoidCallback onPressed,
|
||||
@required String title,
|
||||
}) =>
|
||||
BrandButton(
|
||||
String title,
|
||||
Widget child,
|
||||
}) {
|
||||
assert(title == null || child == null, 'required title or child');
|
||||
assert(title != null || child != null, 'required title or child');
|
||||
return _RisedButton(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
title: title,
|
||||
type: BrandButtonTypes.rised,
|
||||
onPressed: onPressed,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
static text({
|
||||
Key key,
|
||||
@required VoidCallback onPressed,
|
||||
@required String title,
|
||||
}) =>
|
||||
BrandButton(
|
||||
_TextButton(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
title: title,
|
||||
type: BrandButtonTypes.text,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
|
||||
static iconText({
|
||||
|
@ -50,38 +40,12 @@ class BrandButton extends StatelessWidget {
|
|||
@required String title,
|
||||
@required Icon icon,
|
||||
}) =>
|
||||
BrandButton(
|
||||
_IconTextButton(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
title: title,
|
||||
type: BrandButtonTypes.iconText,
|
||||
icon: icon,
|
||||
);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (type) {
|
||||
case BrandButtonTypes.rised:
|
||||
return _RisedButton(
|
||||
title: title,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
case BrandButtonTypes.text:
|
||||
return _TextButton(
|
||||
title: title,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
break;
|
||||
case BrandButtonTypes.iconText:
|
||||
return _IconTextButton(
|
||||
title: title,
|
||||
onPressed: onPressed,
|
||||
icon: icon,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class _RisedButton extends StatelessWidget {
|
||||
|
@ -89,10 +53,12 @@ class _RisedButton extends StatelessWidget {
|
|||
Key key,
|
||||
this.onPressed,
|
||||
this.title,
|
||||
this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
final VoidCallback onPressed;
|
||||
final String title;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -111,15 +77,7 @@ class _RisedButton extends StatelessWidget {
|
|||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(12),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: BrandColors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
child: child ?? BrandText.buttonTitleText(title),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -10,18 +10,20 @@ enum TextType {
|
|||
body2, // with opacity
|
||||
medium,
|
||||
small,
|
||||
onboardingTitle
|
||||
onboardingTitle,
|
||||
buttonTitleText // risen button title text,
|
||||
}
|
||||
|
||||
class BrandText extends StatelessWidget {
|
||||
const BrandText(this.text,
|
||||
{Key key,
|
||||
const BrandText(
|
||||
this.text, {
|
||||
Key key,
|
||||
this.style,
|
||||
@required this.type,
|
||||
this.overflow,
|
||||
this.softWrap,
|
||||
this.textAlign})
|
||||
: super(key: key);
|
||||
this.textAlign,
|
||||
}) : super(key: key);
|
||||
|
||||
final String text;
|
||||
final TextStyle style;
|
||||
|
@ -53,10 +55,13 @@ class BrandText extends StatelessWidget {
|
|||
type: TextType.h2,
|
||||
style: style,
|
||||
);
|
||||
factory BrandText.h3(String text, {TextStyle style}) => BrandText(
|
||||
factory BrandText.h3(String text, {TextStyle style, TextAlign textAlign}) =>
|
||||
BrandText(
|
||||
text,
|
||||
type: TextType.h3,
|
||||
style: style,
|
||||
textAlign: textAlign,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
factory BrandText.h4(String text, {TextStyle style}) => BrandText(
|
||||
text,
|
||||
|
@ -75,13 +80,23 @@ class BrandText extends StatelessWidget {
|
|||
);
|
||||
factory BrandText.medium(String text,
|
||||
{TextStyle style, TextAlign textAlign}) =>
|
||||
BrandText(text,
|
||||
type: TextType.medium, style: style, textAlign: textAlign);
|
||||
BrandText(
|
||||
text,
|
||||
type: TextType.medium,
|
||||
style: style,
|
||||
textAlign: textAlign,
|
||||
);
|
||||
factory BrandText.small(String text, {TextStyle style}) => BrandText(
|
||||
text,
|
||||
type: TextType.small,
|
||||
style: style,
|
||||
);
|
||||
factory BrandText.buttonTitleText(String text, {TextStyle style}) =>
|
||||
BrandText(
|
||||
text,
|
||||
type: TextType.buttonTitleText,
|
||||
style: style,
|
||||
);
|
||||
@override
|
||||
Text build(BuildContext context) {
|
||||
TextStyle style;
|
||||
|
@ -128,6 +143,11 @@ class BrandText extends StatelessWidget {
|
|||
style =
|
||||
isDark ? mediumStyle.copyWith(color: Colors.white) : mediumStyle;
|
||||
break;
|
||||
case TextType.buttonTitleText:
|
||||
style = !isDark
|
||||
? buttonTitleText.copyWith(color: Colors.white)
|
||||
: buttonTitleText;
|
||||
break;
|
||||
}
|
||||
if (this.style != null) {
|
||||
style = style.merge(this.style);
|
||||
|
|
|
@ -9,12 +9,10 @@ class BrandTimer extends StatefulWidget {
|
|||
Key key,
|
||||
@required this.startDateTime,
|
||||
@required this.duration,
|
||||
@required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final DateTime startDateTime;
|
||||
final Duration duration;
|
||||
final VoidCallback callback;
|
||||
|
||||
@override
|
||||
_BrandTimerState createState() => _BrandTimerState();
|
||||
|
@ -36,7 +34,6 @@ class _BrandTimerState extends State<BrandTimer> {
|
|||
var timePassed = DateTime.now().difference(widget.startDateTime);
|
||||
if (timePassed > widget.duration) {
|
||||
t.cancel();
|
||||
widget.callback();
|
||||
} else {
|
||||
_getTime();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'package:selfprivacy/config/brand_theme.dart';
|
|||
import 'package:selfprivacy/config/text_themes.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_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/app_config/app_config_cubit.dart';
|
||||
|
@ -16,7 +16,6 @@ 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';
|
||||
|
@ -34,7 +33,8 @@ class InitializingPage extends StatelessWidget {
|
|||
_stepServer(cubit),
|
||||
_stepCheck(cubit),
|
||||
Container(child: Text('Everythigng is initialized'))
|
||||
][2];
|
||||
][cubit.state.progress];
|
||||
|
||||
return BlocListener<AppConfigCubit, AppConfigState>(
|
||||
listener: (context, state) {
|
||||
if (state.isFullyInitilized) {
|
||||
|
@ -96,8 +96,10 @@ class InitializingPage extends StatelessWidget {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Spacer(),
|
||||
Image.asset('assets/images/logos/hetzner.png'),
|
||||
Image.asset(
|
||||
'assets/images/logos/hetzner.png',
|
||||
width: 150,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
BrandText.h2('Подключите сервер Hetzner'),
|
||||
SizedBox(height: 10),
|
||||
|
@ -149,8 +151,11 @@ class InitializingPage extends StatelessWidget {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Spacer(),
|
||||
Image.asset('assets/images/logos/cloudflare.png'),
|
||||
Image.asset(
|
||||
'assets/images/logos/cloudflare.png',
|
||||
width: 150,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
BrandText.h2('Подключите CloudFlare'),
|
||||
SizedBox(height: 10),
|
||||
BrandText.body2('Для управления DNS вашего домена'),
|
||||
|
@ -188,12 +193,13 @@ class InitializingPage extends StatelessWidget {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Spacer(),
|
||||
Image.asset('assets/images/logos/backblaze.png'),
|
||||
Image.asset(
|
||||
'assets/images/logos/backblaze.png',
|
||||
height: 50,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
BrandText.h2('Подключите облачное хранилище Backblaze'),
|
||||
SizedBox(height: 10),
|
||||
BrandText.body2('Здесь будут храниться данные'),
|
||||
Spacer(),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: formCubit.keyId,
|
||||
|
@ -231,30 +237,90 @@ class InitializingPage extends StatelessWidget {
|
|||
|
||||
Widget _stepDomain(AppConfigCubit initializingCubit) {
|
||||
return BlocProvider(
|
||||
create: (context) => DomainFormCubit(initializingCubit),
|
||||
create: (context) => DomainSetupCubit(initializingCubit)..load(),
|
||||
child: Builder(builder: (context) {
|
||||
var formCubit = context.watch<DomainFormCubit>();
|
||||
var domainSetup = context.watch<DomainSetupCubit>();
|
||||
var state = domainSetup.state;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Spacer(),
|
||||
BrandText.h2('Введите домен:'),
|
||||
Image.asset(
|
||||
'assets/images/logos/cloudflare.png',
|
||||
width: 150,
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
BrandText.h2('Домен'),
|
||||
SizedBox(height: 10),
|
||||
CubitFormTextField(
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
formFieldCubit: formCubit.domainName,
|
||||
if (state is Empty)
|
||||
BrandText.body2('На данный момент подлюченных доменов нет'),
|
||||
if (state is Loading)
|
||||
BrandText.body2(
|
||||
state.type == LoadingTypes.loadingDomain
|
||||
? 'Загружаем список доменов'
|
||||
: 'Сохранение..',
|
||||
),
|
||||
if (state is MoreThenOne)
|
||||
BrandText.body2(
|
||||
'Найдено больше одного домена, для вашей безопастности, просим вам удалить не нужные домены',
|
||||
),
|
||||
if (state is Loaded) ...[
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: BrandText.h3(
|
||||
'${state.domain}',
|
||||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Домен',
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Container(
|
||||
width: 50,
|
||||
child: BrandButton.rised(
|
||||
onPressed: () => domainSetup.load(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.refresh,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
if (state is Empty) ...[
|
||||
SizedBox(height: 30),
|
||||
BrandButton.rised(
|
||||
onPressed:
|
||||
formCubit.state.isSubmitting ? null : formCubit.trySubmit,
|
||||
title: 'Подключить',
|
||||
onPressed: () => domainSetup.load(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.refresh,
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
BrandText.buttonTitleText('Обновить cписок'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (state is Loaded) ...[
|
||||
SizedBox(height: 30),
|
||||
BrandButton.rised(
|
||||
onPressed: () => domainSetup.saveDomain(),
|
||||
title: 'Сохранить домен',
|
||||
),
|
||||
],
|
||||
SizedBox(height: 10),
|
||||
Spacer(),
|
||||
SizedBox(height: 10),
|
||||
BrandButton.text(
|
||||
onPressed: () => _showModal(context, _HowHetzner()),
|
||||
|
@ -286,13 +352,29 @@ class InitializingPage extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
CubitFormTextField(
|
||||
BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>(
|
||||
cubit: formCubit.isVisible,
|
||||
builder: (context, state) {
|
||||
var isVisible = state.value;
|
||||
return CubitFormTextField(
|
||||
obscureText: !isVisible,
|
||||
formFieldCubit: formCubit.password,
|
||||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Пароль',
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
isVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () => formCubit.isVisible.setValue(!isVisible),
|
||||
),
|
||||
suffixIconConstraints: BoxConstraints(minWidth: 60),
|
||||
prefixIconConstraints: BoxConstraints(maxWidth: 85),
|
||||
prefixIcon: Container(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
BrandButton.rised(
|
||||
|
@ -338,52 +420,40 @@ class InitializingPage extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget _stepCheck(AppConfigCubit appConfigCubit) {
|
||||
var state = appConfigCubit.state;
|
||||
var isDnsChecked = state.isDnsCheckedAndServerStarted;
|
||||
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('До следующей проверки: '),
|
||||
isDnsChecked
|
||||
? BrandTimer(
|
||||
startDateTime: state.lastServerStatusCheckTime ??
|
||||
state.hetznerServer.startTime,
|
||||
duration: Duration(minutes: 1),
|
||||
callback: () {
|
||||
appConfigCubit.setDkim();
|
||||
},
|
||||
)
|
||||
: BrandTimer(
|
||||
startDateTime: state.lastDnsCheckTime ??
|
||||
state.hetznerServer.createTime,
|
||||
duration: Duration(minutes: 1),
|
||||
callback: () {
|
||||
appConfigCubit.checkDnsAndStartServer();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
BrandButton.text(
|
||||
onPressed: () => _showModal(context, _HowHetzner()),
|
||||
title: 'Что это значит?',
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
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: 'Что это значит?',
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// });
|
||||
}
|
||||
|
||||
Widget _addCard(Widget child) {
|
||||
|
|
|
@ -3,6 +3,8 @@ import 'package:selfprivacy/config/brand_colors.dart';
|
|||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
|
@ -90,36 +92,25 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
|||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
child: AlertDialog(
|
||||
title: Text('Are you sure?'),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Text('Reset all keys?'),
|
||||
child: BrandAlert(
|
||||
title: 'Вы уверенны',
|
||||
contentText: 'Сбросить все ключи?',
|
||||
acitons: [
|
||||
ActionButton(
|
||||
text: 'Да, сбросить',
|
||||
isRed: true,
|
||||
onPressed: () {
|
||||
context
|
||||
.read<AppConfigCubit>()
|
||||
.clearAppConfig();
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
ActionButton(
|
||||
text: 'Отмена',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(
|
||||
'Reset',
|
||||
style: TextStyle(
|
||||
color: BrandColors.red1,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<AppConfigCubit>().clearAppConfig();
|
||||
Navigator.of(context)..pop()..pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text('Cancel'),
|
||||
onPressed: () {
|
||||
Navigator.of(context)..pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
));
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
87
pubspec.lock
87
pubspec.lock
|
@ -7,14 +7,14 @@ packages:
|
|||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "14.0.0"
|
||||
version: "12.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.41.1"
|
||||
version: "0.40.6"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -169,6 +169,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.2"
|
||||
crypto:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -225,6 +232,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.3"
|
||||
either_option:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: either_option
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
email_validator:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -419,7 +433,7 @@ packages:
|
|||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.2"
|
||||
version: "0.6.3-nullsafety.2"
|
||||
json_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -490,6 +504,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.13"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -552,7 +573,7 @@ packages:
|
|||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.2"
|
||||
version: "1.10.0-nullsafety.2"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -587,7 +608,7 @@ packages:
|
|||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.5.0-nullsafety.2"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -672,6 +693,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.9"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.9+2"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -698,6 +733,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.10+1"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.10-nullsafety.2"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -740,6 +789,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety.1"
|
||||
test:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.16.0-nullsafety.5"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -747,6 +803,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.19-nullsafety.2"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.12-nullsafety.5"
|
||||
time:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -824,6 +887,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.3"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
wakelock:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -859,6 +929,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.7.5"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
cupertino_icons: ^1.0.0
|
||||
dio: ^3.0.10
|
||||
easy_localization: ^2.3.3
|
||||
either_option: ^1.0.6
|
||||
equatable: ^1.2.5
|
||||
flutter_bloc: ^6.1.1
|
||||
flutter_secure_storage: ^3.3.5
|
||||
|
|
Loading…
Reference in a new issue