fdroid
Kherel 2021-03-15 16:39:44 +01:00
parent afd569ba96
commit 0ec549042c
81 changed files with 572 additions and 486 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,3 +1,46 @@
{ {
"test": "en-test" "test": "en-test",
"basis": {
"_comment": "базовые элементы интерфейса",
"providers": "Провайдеры",
"services": "Сервисы",
"users": "Пользователи",
"more": "Еще",
"next": "Далее",
"got_it": "Понял"
},
"more": {
"_comment": "Элементы на странице еще",
"configuration_wizard": "Мастер Подключения",
"settings": "Настройки приложения",
"about_project": "О проекте SelfPrivacy",
"about_app": "О приложении",
"onboarding": "Onboarding",
"console": "Console"
},
"onboarding": {
"_comment": "страницы онбординга",
"page1_title": "Digital independence, available to all of us.",
"page1_text": "Mail, VPN, Messenger, social network and much more on your private server, under your control.",
"page2_title": "SelfPrivacy is not a cloud, but your personal datacenter.",
"page2_text": "SelfPrivacy works only with your provider accounts: Hetzner, Cloudflare, Backblaze. If you do not own those, we'll help you to create them."
},
"providers": {
"_comment": "вкладка провайдеры",
"page_title": "Your Data Center",
"server": {
"card_title": "Сервер"
},
"domain": {
"card_title": "Домен"
},
"backup": {
"card_title": "Резервное копирование"
}
},
"not_ready_card": {
"1": "Завершите настройку приложения используя ",
"2": "@:more.configuration_wizard",
"3": " для продолжения работы"
}
} }

View File

@ -1,7 +1,47 @@
{ {
"test": "en-test", "test": "ru-test",
"basis:": { "basis": {
"_comment": "Повторяющиеся названия", "_comment": "базовые элементы интерфейса",
"next": "Далее" "providers": "Провайдеры",
"services": "Сервисы",
"users": "Пользователи",
"more": "Еще",
"next": "Далее",
"got_it": "Понял"
},
"more": {
"_comment": "Элементы на странице еще",
"configuration_wizard": "Мастер Подключения",
"settings": "Настройки приложения",
"about_project": "О проекте SelfPrivacy",
"about_app": "О приложении",
"onboarding": "Onboarding",
"console": "Console"
},
"onboarding": {
"_comment": "страницы онбординга",
"page1_title": "Цифровая независимость доступна каждому",
"page1_text": "Почта, VPN, Мессенджер, социальная сеть и многое другое на вашем личном сервере, под вашим полным контролем.",
"page2_title": "SelfPrivacy — это не облако, а ваш личный дата-центр",
"page2_text": "У SelfPrivacy работает только с вашими сервис-провадерами: Hetzner, Cloudflare, Backblaze. Если у вас нет учетных записей, мы поможем их создать."
},
"providers": {
"_comment": "вкладка провайдеры",
"page_title": "Ваш Дата-центр",
"server": {
"card_title": "Сервер"
},
"domain": {
"card_title": "Домен"
},
"backup": {
"card_title": "Резервное копирование"
}
},
"not_ready_card": {
"_comment": "Карточка показывающая когда человек скипнул настройку, на карте текст из 3 блоков, средний содержит ссыку на мастер подключения",
"1": "Завершите настройку приложения используя ",
"2": "@:more.configuration_wizard",
"3": " для продолжения работы"
} }
} }

View File

@ -45,7 +45,7 @@ SPEC CHECKSUMS:
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
wakelock: bfc7955c418d0db797614075aabbc58a39ab5107 wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

View File

@ -7,9 +7,9 @@ import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
class BlocAndProviderConfig extends StatelessWidget { class BlocAndProviderConfig extends StatelessWidget {
const BlocAndProviderConfig({Key key, this.child}) : super(key: key); const BlocAndProviderConfig({Key? key, this.child}) : super(key: key);
final Widget child; final Widget? child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -2,14 +2,14 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:selfprivacy/ui/components/error/error.dart'; import 'package:selfprivacy/ui/components/error/error.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'get_it_config.dart'; import './get_it_config.dart';
class SimpleBlocObserver extends BlocObserver { class SimpleBlocObserver extends BlocObserver {
SimpleBlocObserver(); SimpleBlocObserver();
@override @override
void onError(Cubit cubit, Object error, StackTrace stackTrace) { void onError(Bloc cubit, Object error, StackTrace stackTrace) {
final navigator = getIt.get<NavigationService>().navigator; final navigator = getIt.get<NavigationService>().navigator!;
navigator.push( navigator.push(
materialRoute( materialRoute(

View File

@ -32,7 +32,8 @@ class HiveConfig {
await secureStorage.write(key: BNames.key, value: base64UrlEncode(key)); await secureStorage.write(key: BNames.key, value: base64UrlEncode(key));
} }
return base64Url.decode(await secureStorage.read(key: BNames.key)); String? string = await secureStorage.read(key: BNames.key);
return base64Url.decode(string!);
} }
} }

View File

@ -3,20 +3,20 @@ import 'package:flutter/material.dart';
class Localization extends StatelessWidget { class Localization extends StatelessWidget {
const Localization({ const Localization({
Key key, Key? key,
this.child, this.child,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget? child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return EasyLocalization( return EasyLocalization(
preloaderColor: Colors.black,
supportedLocales: [Locale('ru'), Locale('en')], supportedLocales: [Locale('ru'), Locale('en')],
path: 'assets/translations', path: 'assets/translations',
fallbackLocale: Locale('en'), fallbackLocale: Locale('ru'),
saveLocale: false,
useOnlyLangCode: true, useOnlyLangCode: true,
child: child, child: child!,
); );
} }
} }

View File

@ -18,9 +18,9 @@ abstract class ApiMap {
}; };
loggedClient = client; loggedClient = client;
} }
String rootAddress; String? rootAddress;
Dio loggedClient; late Dio loggedClient;
void close() { void close() {
loggedClient.close(); loggedClient.close();
@ -61,7 +61,7 @@ class ConsoleInterceptor extends InterceptorsWrapper {
addMessage( addMessage(
Message.warn( Message.warn(
text: text:
'response-uri: ${response?.request?.uri}\ncode: ${response?.statusCode}\ndata: ${response?.toString()}\n', 'response-uri: ${response?.request.uri}\ncode: ${response?.statusCode}\ndata: ${response?.toString()}\n',
), ),
); );
return super.onError(err); return super.onError(err);

View File

@ -3,17 +3,17 @@ import 'package:dio/dio.dart';
import 'package:selfprivacy/logic/api_maps/api_map.dart'; import 'package:selfprivacy/logic/api_maps/api_map.dart';
class BackblazeApi extends ApiMap { class BackblazeApi extends ApiMap {
BackblazeApi([String token]) { BackblazeApi([String? token]) {
if (token != null) { if (token != null) {
loggedClient.options = BaseOptions( loggedClient.options = BaseOptions(
headers: {'Authorization': 'Basic $token'}, headers: {'Authorization': 'Basic $token'},
baseUrl: rootAddress, baseUrl: rootAddress!,
); );
} }
} }
@override @override
String rootAddress = String? rootAddress =
'https://api.backblazeb2.com/b2api/v2/b2_authorize_account'; 'https://api.backblazeb2.com/b2api/v2/b2_authorize_account';
Future<bool> isValid(String token) async { Future<bool> isValid(String token) async {
@ -24,7 +24,7 @@ class BackblazeApi extends ApiMap {
}, },
); );
Response response = await loggedClient.get(rootAddress, options: options); Response response = await loggedClient.get(rootAddress!, options: options);
if (response.statusCode == HttpStatus.ok) { if (response.statusCode == HttpStatus.ok) {
return true; return true;

View File

@ -5,7 +5,7 @@ import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
import 'package:selfprivacy/logic/models/dns_records.dart'; import 'package:selfprivacy/logic/models/dns_records.dart';
class CloudflareApi extends ApiMap { class CloudflareApi extends ApiMap {
CloudflareApi([String token]) { CloudflareApi([String? token]) {
if (token != null) { if (token != null) {
loggedClient.options = loggedClient.options =
BaseOptions(headers: {'Authorization': 'Bearer $token'}); BaseOptions(headers: {'Authorization': 'Bearer $token'});
@ -13,7 +13,7 @@ class CloudflareApi extends ApiMap {
} }
@override @override
String rootAddress = 'https://api.cloudflare.com/client/v4'; String? rootAddress = 'https://api.cloudflare.com/client/v4';
Future<bool> isValid(String token) async { Future<bool> isValid(String token) async {
var url = '$rootAddress/user/tokens/verify'; var url = '$rootAddress/user/tokens/verify';
@ -35,7 +35,7 @@ class CloudflareApi extends ApiMap {
} }
} }
Future<String> getZoneId(String token, String domain) async { Future<String?> getZoneId(String? token, String domain) async {
var url = '$rootAddress/zones'; var url = '$rootAddress/zones';
var options = Options( var options = Options(
@ -59,8 +59,8 @@ class CloudflareApi extends ApiMap {
} }
Future<void> removeSimilarRecords({ Future<void> removeSimilarRecords({
String ip4, String? ip4,
CloudFlareDomain cloudFlareDomain, required CloudFlareDomain cloudFlareDomain,
}) async { }) async {
var domainName = cloudFlareDomain.domainName; var domainName = cloudFlareDomain.domainName;
var domainZoneId = cloudFlareDomain.zoneId; var domainZoneId = cloudFlareDomain.zoneId;
@ -82,8 +82,8 @@ class CloudflareApi extends ApiMap {
} }
Future<void> createMultipleDnsRecords({ Future<void> createMultipleDnsRecords({
String ip4, String? ip4,
CloudFlareDomain cloudFlareDomain, required CloudFlareDomain cloudFlareDomain,
}) async { }) async {
var domainName = cloudFlareDomain.domainName; var domainName = cloudFlareDomain.domainName;
var domainZoneId = cloudFlareDomain.zoneId; var domainZoneId = cloudFlareDomain.zoneId;
@ -120,7 +120,7 @@ class CloudflareApi extends ApiMap {
// ); // );
// } // }
List<DnsRecords> projectDnsRecords(String domainName, String ip4) { List<DnsRecords> projectDnsRecords(String? domainName, String? ip4) {
var domainA = DnsRecords(type: 'A', name: domainName, content: ip4); var domainA = DnsRecords(type: 'A', name: domainName, content: ip4);
var mx = DnsRecords(type: 'MX', name: '@', content: domainName); var mx = DnsRecords(type: 'MX', name: '@', content: domainName);
@ -161,7 +161,7 @@ class CloudflareApi extends ApiMap {
]; ];
} }
Future<List<String>> domainList() async { Future<List<String>?> domainList() async {
var url = '$rootAddress/zones?per_page=50'; var url = '$rootAddress/zones?per_page=50';
var response = await loggedClient.get( var response = await loggedClient.get(
url, url,
@ -169,7 +169,7 @@ class CloudflareApi extends ApiMap {
); );
return response.data['result'] return response.data['result']
.map<String>((el) => el['name'] as String) .map<String>((el) => el['name'] as String?)
.toList(); .toList();
} }
} }

View File

@ -2,24 +2,23 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:selfprivacy/logic/api_maps/api_map.dart'; import 'package:selfprivacy/logic/api_maps/api_map.dart';
import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/server_details.dart';
import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/logic/models/user.dart';
import 'package:selfprivacy/utils/password_generator2.dart'; import 'package:selfprivacy/utils/password_generator2.dart';
class HetznerApi extends ApiMap { class HetznerApi extends ApiMap {
HetznerApi([String token]) { HetznerApi([String? token]) {
if (token != null) { if (token != null) {
loggedClient.options = BaseOptions( loggedClient.options = BaseOptions(
headers: {'Authorization': 'Bearer $token'}, headers: {'Authorization': 'Bearer $token'},
baseUrl: rootAddress, baseUrl: rootAddress!,
); );
} }
} }
@override @override
String rootAddress = 'https://api.hetzner.cloud/v1/servers'; String? rootAddress = 'https://api.hetzner.cloud/v1/servers';
Future<bool> isValid(String token) async { Future<bool> isValid(String token) async {
var options = Options( var options = Options(
@ -29,7 +28,7 @@ class HetznerApi extends ApiMap {
}, },
); );
Response response = await loggedClient.get(rootAddress, options: options); Response response = await loggedClient.get(rootAddress!, options: options);
if (response.statusCode == HttpStatus.ok) { if (response.statusCode == HttpStatus.ok) {
return true; return true;
@ -41,9 +40,9 @@ class HetznerApi extends ApiMap {
} }
Future<HetznerServerDetails> createServer({ Future<HetznerServerDetails> createServer({
@required String cloudFlareKey, required String? cloudFlareKey,
@required User rootUser, required User rootUser,
@required String domainName, required String? domainName,
}) async { }) async {
var dbPassword = getRandomString(40); var dbPassword = getRandomString(40);
@ -52,7 +51,7 @@ class HetznerApi extends ApiMap {
); );
Response response = await loggedClient.post( Response response = await loggedClient.post(
rootAddress, rootAddress!,
data: data, data: data,
); );
@ -64,17 +63,17 @@ class HetznerApi extends ApiMap {
} }
Future<void> deleteSelfprivacyServer({ Future<void> deleteSelfprivacyServer({
@required String cloudFlareKey, required String? cloudFlareKey,
}) async { }) async {
Response response = await loggedClient.get(rootAddress); Response response = await loggedClient.get(rootAddress!);
List list = response.data['servers']; List list = response.data['servers'];
var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server'); var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server');
return await loggedClient.delete('$rootAddress/${server['id']}'); await loggedClient.delete('$rootAddress/${server['id']}');
} }
Future<HetznerServerDetails> startServer({ Future<HetznerServerDetails> startServer({
HetznerServerDetails server, required HetznerServerDetails server,
}) async { }) async {
await loggedClient.post('/${server.id}/actions/poweron'); await loggedClient.post('/${server.id}/actions/poweron');
@ -84,7 +83,7 @@ class HetznerApi extends ApiMap {
} }
Future<HetznerServerDetails> restart({ Future<HetznerServerDetails> restart({
HetznerServerDetails server, required HetznerServerDetails server,
}) async { }) async {
await loggedClient.post('/${server.id}/actions/poweron'); await loggedClient.post('/${server.id}/actions/poweron');

View File

@ -5,7 +5,7 @@ import 'package:dio/dio.dart';
import 'api_map.dart'; import 'api_map.dart';
class ServerApi extends ApiMap { class ServerApi extends ApiMap {
ServerApi(String domainName) { ServerApi(String? domainName) {
loggedClient.options = BaseOptions( loggedClient.options = BaseOptions(
baseUrl: 'https://api.$domainName', baseUrl: 'https://api.$domainName',
); );

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
@ -64,23 +63,23 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void startServerIfDnsIsOkay({ void startServerIfDnsIsOkay({
AppConfigState state, AppConfigState? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
state = state ?? this.state; state = state ?? this.state;
final work = () async { final work = () async {
emit(TimerState(dataState: state, isLoading: true)); emit(TimerState(dataState: state!, isLoading: true));
var ip4 = state.hetznerServer.ip4; var ip4 = state.hetznerServer!.ip4;
var domainName = state.cloudFlareDomain.domainName; var domainName = state.cloudFlareDomain!.domainName;
var isMatch = await repository.isDnsAddressesMatch(domainName, ip4); var isMatch = await repository.isDnsAddressesMatch(domainName, ip4);
if (isMatch) { if (isMatch) {
var server = await repository.startServer( var server = await repository.startServer(
state.hetznerKey, state.hetznerKey,
state.hetznerServer, state.hetznerServer!,
); );
repository.saveServerDetails(server); repository.saveServerDetails(server);
emit( emit(
@ -111,16 +110,16 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void resetServerIfServerIsOkay({ void resetServerIfServerIsOkay({
AppConfigState state, AppConfigState? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
state = state ?? this.state; state = state ?? this.state;
var work = () async { var work = () async {
emit(TimerState(dataState: state, isLoading: true)); emit(TimerState(dataState: state!, isLoading: true));
var isServerWorking = await repository.isHttpServerWorking( var isServerWorking = await repository.isHttpServerWorking(
state.cloudFlareDomain.domainName, state.cloudFlareDomain!.domainName,
); );
if (isServerWorking) { if (isServerWorking) {
@ -133,8 +132,8 @@ class AppConfigCubit extends Cubit<AppConfigState> {
)); ));
timer = Timer(pauseDuration, () async { timer = Timer(pauseDuration, () async {
var hetznerServerDetails = await repository.restart( var hetznerServerDetails = await repository.restart(
state.hetznerKey, state!.hetznerKey,
state.hetznerServer, state.hetznerServer!,
); );
emit( emit(
state.copyWith( state.copyWith(
@ -165,19 +164,19 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
} }
Timer timer; Timer? timer;
void finishCheckIfServerIsOkay({ void finishCheckIfServerIsOkay({
AppConfigState state, AppConfigState? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
state = state ?? this.state; state = state ?? this.state;
var work = () async { var work = () async {
emit(TimerState(dataState: state, isLoading: true)); emit(TimerState(dataState: state!, isLoading: true));
var isServerWorking = await repository.isHttpServerWorking( var isServerWorking = await repository.isHttpServerWorking(
state.cloudFlareDomain.domainName, state.cloudFlareDomain!.domainName,
); );
if (isServerWorking) { if (isServerWorking) {
@ -238,12 +237,12 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void createServerAndSetDnsRecords() async { void createServerAndSetDnsRecords() async {
var _stateCopy = state; AppConfigState _stateCopy = state;
var onSuccess = (serverDetails) async { var onSuccess = (serverDetails) async {
await repository.createDnsRecords( await repository.createDnsRecords(
state.cloudFlareKey, state.cloudFlareKey,
serverDetails.ip4, serverDetails.ip4,
state.cloudFlareDomain, state.cloudFlareDomain!,
); );
emit(state.copyWith( emit(state.copyWith(
@ -259,8 +258,8 @@ class AppConfigCubit extends Cubit<AppConfigState> {
emit(state.copyWith(isLoading: true)); emit(state.copyWith(isLoading: true));
await repository.createServer( await repository.createServer(
state.hetznerKey, state.hetznerKey,
state.rootUser, state.rootUser!,
state.cloudFlareDomain.domainName, state.cloudFlareDomain!.domainName,
state.cloudFlareKey, state.cloudFlareKey,
onCancel: onCancel, onCancel: onCancel,
onSuccess: onSuccess, onSuccess: onSuccess,
@ -277,8 +276,8 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void _closeTimer() { void _closeTimer() {
if (timer != null && timer.isActive) { if (timer != null && timer!.isActive) {
timer.cancel(); timer!.cancel();
} }
} }
} }

View File

@ -60,7 +60,7 @@ class AppConfigRepository {
} }
Future<HetznerServerDetails> startServer( Future<HetznerServerDetails> startServer(
String hetznerKey, String? hetznerKey,
HetznerServerDetails hetznerServer, HetznerServerDetails hetznerServer,
) async { ) async {
var hetznerApi = HetznerApi(hetznerKey); var hetznerApi = HetznerApi(hetznerKey);
@ -75,7 +75,7 @@ class AppConfigRepository {
await box.put(BNames.hetznerServer, serverDetails); await box.put(BNames.hetznerServer, serverDetails);
} }
Future<bool> isDnsAddressesMatch(String domainName, String ip4) async { Future<bool> isDnsAddressesMatch(String? domainName, String? ip4) async {
print(domainName); print(domainName);
var addresses = <String>[ var addresses = <String>[
'$domainName', '$domainName',
@ -116,12 +116,12 @@ class AppConfigRepository {
} }
Future<void> createServer( Future<void> createServer(
String hetznerKey, String? hetznerKey,
User rootUser, User rootUser,
String domainName, String? domainName,
String cloudFlareKey, { String? cloudFlareKey, {
void Function() onCancel, void Function()? onCancel,
Future<void> Function(HetznerServerDetails serverDetails) onSuccess, required Future<void> Function(HetznerServerDetails serverDetails) onSuccess,
}) async { }) async {
var hetznerApi = HetznerApi(hetznerKey); var hetznerApi = HetznerApi(hetznerKey);
@ -135,7 +135,7 @@ class AppConfigRepository {
hetznerApi.close(); hetznerApi.close();
onSuccess(serverDetails); onSuccess(serverDetails);
} on DioError catch (e) { } on DioError catch (e) {
if (e.response.data['error']['code'] == 'uniqueness_error') { if (e.response!.data['error']['code'] == 'uniqueness_error') {
var nav = getIt.get<NavigationService>(); var nav = getIt.get<NavigationService>();
nav.showPopUpDialog( nav.showPopUpDialog(
BrandAlert( BrandAlert(
@ -165,7 +165,7 @@ class AppConfigRepository {
text: 'Отменить', text: 'Отменить',
onPressed: () { onPressed: () {
hetznerApi.close(); hetznerApi.close();
onCancel(); onCancel!();
}, },
), ),
], ],
@ -176,8 +176,8 @@ class AppConfigRepository {
} }
Future<void> createDnsRecords( Future<void> createDnsRecords(
String cloudFlareKey, String? cloudFlareKey,
String ip4, String? ip4,
CloudFlareDomain cloudFlareDomain, CloudFlareDomain cloudFlareDomain,
) async { ) async {
var cloudflareApi = CloudflareApi(cloudFlareKey); var cloudflareApi = CloudflareApi(cloudFlareKey);
@ -195,7 +195,7 @@ class AppConfigRepository {
cloudflareApi.close(); cloudflareApi.close();
} }
Future<bool> isHttpServerWorking(String domainName) async { Future<bool> isHttpServerWorking(String? domainName) async {
var api = ServerApi(domainName); var api = ServerApi(domainName);
var isHttpServerWorking = await api.isHttpServerWorking(); var isHttpServerWorking = await api.isHttpServerWorking();
api.close(); api.close();
@ -203,7 +203,7 @@ class AppConfigRepository {
} }
Future<HetznerServerDetails> restart( Future<HetznerServerDetails> restart(
String hetznerKey, String? hetznerKey,
HetznerServerDetails server, HetznerServerDetails server,
) async { ) async {
var hetznerApi = HetznerApi(hetznerKey); var hetznerApi = HetznerApi(hetznerKey);

View File

@ -2,21 +2,21 @@ part of 'app_config_cubit.dart';
class AppConfigState extends Equatable { class AppConfigState extends Equatable {
const AppConfigState({ const AppConfigState({
@required this.hetznerKey, required this.hetznerKey,
@required this.cloudFlareKey, required this.cloudFlareKey,
@required this.backblazeCredential, required this.backblazeCredential,
@required this.cloudFlareDomain, required this.cloudFlareDomain,
@required this.rootUser, required this.rootUser,
@required this.hetznerServer, required this.hetznerServer,
@required this.isServerStarted, required this.isServerStarted,
@required this.isServerReseted, required this.isServerReseted,
@required this.hasFinalChecked, required this.hasFinalChecked,
@required this.isLoading, required this.isLoading,
@required this.error, required this.error,
}); });
@override @override
List<Object> get props => [ List<Object?> get props => [
hetznerKey, hetznerKey,
cloudFlareKey, cloudFlareKey,
backblazeCredential, backblazeCredential,
@ -30,31 +30,31 @@ class AppConfigState extends Equatable {
error, error,
]; ];
final String hetznerKey; final String? hetznerKey;
final String cloudFlareKey; final String? cloudFlareKey;
final BackblazeCredential backblazeCredential; final BackblazeCredential? backblazeCredential;
final CloudFlareDomain cloudFlareDomain; final CloudFlareDomain? cloudFlareDomain;
final User rootUser; final User? rootUser;
final HetznerServerDetails hetznerServer; final HetznerServerDetails? hetznerServer;
final bool isServerStarted; final bool? isServerStarted;
final bool isServerReseted; final bool? isServerReseted;
final bool hasFinalChecked; final bool? hasFinalChecked;
final bool isLoading; final bool? isLoading;
final Exception error; final Exception? error;
AppConfigState copyWith({ AppConfigState copyWith({
String hetznerKey, String? hetznerKey,
String cloudFlareKey, String? cloudFlareKey,
BackblazeCredential backblazeCredential, BackblazeCredential? backblazeCredential,
CloudFlareDomain cloudFlareDomain, CloudFlareDomain? cloudFlareDomain,
User rootUser, User? rootUser,
HetznerServerDetails hetznerServer, HetznerServerDetails? hetznerServer,
bool isServerStarted, bool? isServerStarted,
bool isServerReseted, bool? isServerReseted,
bool hasFinalChecked, bool? hasFinalChecked,
bool isLoading, bool? isLoading,
Exception error, Exception? error,
}) => }) =>
AppConfigState( AppConfigState(
hetznerKey: hetznerKey ?? this.hetznerKey, hetznerKey: hetznerKey ?? this.hetznerKey,
@ -77,10 +77,10 @@ class AppConfigState extends Equatable {
bool get isUserFilled => rootUser != null; bool get isUserFilled => rootUser != null;
bool get isServerCreated => hetznerServer != null; bool get isServerCreated => hetznerServer != null;
bool get isFullyInitilized => _fulfilementList.every((el) => el); bool get isFullyInitilized => _fulfilementList.every((el) => el!);
int get progress => _fulfilementList.where((el) => el).length; int get progress => _fulfilementList.where((el) => el!).length;
List<bool> get _fulfilementList => [ List<bool?> get _fulfilementList => [
isHetznerFilled, isHetznerFilled,
isCloudFlareFilled, isCloudFlareFilled,
isBackblazeFilled, isBackblazeFilled,
@ -112,10 +112,10 @@ class InitialAppConfigState extends AppConfigState {
class TimerState extends AppConfigState { class TimerState extends AppConfigState {
TimerState({ TimerState({
@required this.dataState, required this.dataState,
this.timerStart, this.timerStart,
this.duration, this.duration,
@required bool isLoading, required bool isLoading,
}) : super( }) : super(
hetznerKey: dataState.hetznerKey, hetznerKey: dataState.hetznerKey,
cloudFlareKey: dataState.cloudFlareKey, cloudFlareKey: dataState.cloudFlareKey,
@ -131,11 +131,11 @@ class TimerState extends AppConfigState {
); );
final AppConfigState dataState; final AppConfigState dataState;
final DateTime timerStart; final DateTime? timerStart;
final Duration duration; final Duration? duration;
@override @override
List<Object> get props => [ List<Object?> get props => [
dataState, dataState,
timerStart, timerStart,
duration, duration,

View File

@ -1,6 +1,5 @@
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/widgets.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:selfprivacy/config/hive_config.dart'; import 'package:selfprivacy/config/hive_config.dart';
export 'package:provider/provider.dart'; export 'package:provider/provider.dart';
@ -9,8 +8,8 @@ part 'app_settings_state.dart';
class AppSettingsCubit extends Cubit<AppSettingsState> { class AppSettingsCubit extends Cubit<AppSettingsState> {
AppSettingsCubit({ AppSettingsCubit({
@required bool isDarkModeOn, required bool isDarkModeOn,
@required bool isOnbordingShowing, required bool isOnbordingShowing,
}) : super( }) : super(
AppSettingsState( AppSettingsState(
isDarkModeOn: isDarkModeOn, isDarkModeOn: isDarkModeOn,
@ -21,15 +20,15 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
Box box = Hive.box(BNames.appSettings); Box box = Hive.box(BNames.appSettings);
void load() { void load() {
bool isDarkModeOn = box.get(BNames.isDarkModeOn); bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
bool isOnbordingShowing = box.get(BNames.isOnbordingShowing); bool? isOnbordingShowing = box.get(BNames.isOnbordingShowing);
emit(state.copyWith( emit(state.copyWith(
isDarkModeOn: isDarkModeOn, isDarkModeOn: isDarkModeOn,
isOnbordingShowing: isOnbordingShowing, isOnbordingShowing: isOnbordingShowing,
)); ));
} }
void updateDarkMode({@required bool isDarkModeOn}) { void updateDarkMode({required bool isDarkModeOn}) {
box.put(BNames.isDarkModeOn, isDarkModeOn); box.put(BNames.isDarkModeOn, isDarkModeOn);
emit(state.copyWith(isDarkModeOn: isDarkModeOn)); emit(state.copyWith(isDarkModeOn: isDarkModeOn));
} }

View File

@ -2,8 +2,8 @@ part of 'app_settings_cubit.dart';
class AppSettingsState extends Equatable { class AppSettingsState extends Equatable {
const AppSettingsState({ const AppSettingsState({
@required this.isDarkModeOn, required this.isDarkModeOn,
@required this.isOnbordingShowing, required this.isOnbordingShowing,
}); });
final bool isDarkModeOn; final bool isDarkModeOn;

View File

@ -42,13 +42,14 @@ class BackblazeFormCubit extends FormCubit {
final AppConfigCubit initializingCubit; final AppConfigCubit initializingCubit;
FieldCubit<String> keyId; // ignore: close_sinks
late final FieldCubit<String> keyId;
FieldCubit<String> applicationKey; // ignore: close_sinks
late final FieldCubit<String> applicationKey;
@override @override
FutureOr<bool> asyncValidation() async { FutureOr<bool> asyncValidation() async {
bool isKeyValid; late bool isKeyValid;
try { try {
String encodedApiKey = encodedBackblazeKey( String encodedApiKey = encodedBackblazeKey(
keyId.state.value, keyId.state.value,

View File

@ -30,11 +30,11 @@ class CloudFlareFormCubit extends FormCubit {
final AppConfigCubit initializingCubit; final AppConfigCubit initializingCubit;
FieldCubit<String> apiKey; late final FieldCubit<String> apiKey;
@override @override
FutureOr<bool> asyncValidation() async { FutureOr<bool> asyncValidation() async {
bool isKeyValid; late bool isKeyValid;
try { try {
isKeyValid = await apiClient.isValid(apiKey.state.value); isKeyValid = await apiClient.isValid(apiKey.state.value);

View File

@ -5,7 +5,7 @@ import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
class DomainSetupCubit extends Cubit<DomainSetupState> { class DomainSetupCubit extends Cubit<DomainSetupState> {
DomainSetupCubit(this.initializingCubit) : super(Initial()) { DomainSetupCubit(this.initializingCubit) : super(Initial()) {
var token = (initializingCubit.state.cloudFlareKey); var token = initializingCubit.state.cloudFlareKey;
assert(token != null, 'no cloudflare token'); assert(token != null, 'no cloudflare token');
@ -13,11 +13,11 @@ class DomainSetupCubit extends Cubit<DomainSetupState> {
} }
AppConfigCubit initializingCubit; AppConfigCubit initializingCubit;
CloudflareApi api; late CloudflareApi api;
Future<void> load() async { Future<void> load() async {
emit(Loading(LoadingTypes.loadingDomain)); emit(Loading(LoadingTypes.loadingDomain));
var list = await api.domainList(); var list = await (api.domainList() as Future<List<String>>);
if (list.isEmpty) { if (list.isEmpty) {
emit(Empty()); emit(Empty());
} else if (list.length == 1) { } else if (list.length == 1) {

View File

@ -30,11 +30,12 @@ class HetznerFormCubit extends FormCubit {
final AppConfigCubit initializingCubit; final AppConfigCubit initializingCubit;
FieldCubit<String> apiKey; // ignore: close_sinks
late final FieldCubit<String> apiKey;
@override @override
FutureOr<bool> asyncValidation() async { FutureOr<bool> asyncValidation() async {
bool isKeyValid; late bool isKeyValid;
try { try {
isKeyValid = await apiClient.isValid(apiKey.state.value); isKeyValid = await apiClient.isValid(apiKey.state.value);
} catch (e) { } catch (e) {

View File

@ -46,9 +46,12 @@ class RootUserFormCubit extends FormCubit {
final AppConfigCubit initializingCubit; final AppConfigCubit initializingCubit;
FieldCubit<String> userName; // ignore: close_sinks
FieldCubit<String> password; late final FieldCubit<String> userName;
FieldCubit<bool> isVisible; // ignore: close_sinks
late final FieldCubit<String> password;
// ignore: close_sinks
late final FieldCubit<bool> isVisible;
@override @override
Future<void> close() async { Future<void> close() async {

View File

@ -7,8 +7,8 @@ import 'package:selfprivacy/utils/password_generator.dart';
class UserFormCubit extends FormCubit { class UserFormCubit extends FormCubit {
UserFormCubit({ UserFormCubit({
this.usersCubit, required this.usersCubit,
User user, User? user,
}) { }) {
var isEdit = user != null; var isEdit = user != null;
@ -16,7 +16,7 @@ class UserFormCubit extends FormCubit {
var passwordRegExp = RegExp(r"[\n\r\s]+"); var passwordRegExp = RegExp(r"[\n\r\s]+");
login = FieldCubit( login = FieldCubit(
initalValue: isEdit ? user.login : '', initalValue: isEdit ? user!.login : '',
validations: [ validations: [
RequiredStringValidation('required'), RequiredStringValidation('required'),
ValidationModel<String>( ValidationModel<String>(
@ -25,7 +25,7 @@ class UserFormCubit extends FormCubit {
); );
password = FieldCubit( password = FieldCubit(
initalValue: isEdit ? user.password : genPass(), initalValue: isEdit ? user!.password : genPass(),
validations: [ validations: [
RequiredStringValidation('required'), RequiredStringValidation('required'),
ValidationModel<String>( ValidationModel<String>(
@ -42,15 +42,16 @@ class UserFormCubit extends FormCubit {
login: login.state.value, login: login.state.value,
password: password.state.value, password: password.state.value,
); );
usersCubit.add(user); usersCubit.addUser(user);
} }
FieldCubit<String> login; // ignore: close_sinks
FieldCubit<String> password; late FieldCubit<String> login;
late FieldCubit<String> password;
void genNewPassword() { void genNewPassword() {
password.externalSetValue(genPass()); password.externalSetValue(genPass());
} }
UsersCubit usersCubit; late UsersCubit usersCubit;
} }

View File

@ -5,7 +5,7 @@ class LegnthStringValidationWithLenghShowing extends ValidationModel<String> {
: super((n) => n.length != length, errorText); : super((n) => n.length != length, errorText);
@override @override
String check(String val) { String? check(String val) {
var length = val.length; var length = val.length;
var errorMassage = this.errorMassage.replaceAll("[]", length.toString()); var errorMassage = this.errorMassage.replaceAll("[]", length.toString());
return test(val) ? errorMassage : null; return test(val) ? errorMassage : null;

View File

@ -8,14 +8,14 @@ part 'users_state.dart';
class UsersCubit extends Cubit<UsersState> { class UsersCubit extends Cubit<UsersState> {
UsersCubit() : super(UsersState([])); UsersCubit() : super(UsersState([]));
void add(User user) { void addUser(User user) {
var users = [...state.users]; var users = [...state.users];
users.add(user); users.add(user);
emit(UsersState(users)); emit(UsersState(users));
} }
void remove(User user) { void remove(User? user) {
var users = [...state.users]; var users = [...state.users];
users.remove(user); users.remove(user);

View File

@ -3,10 +3,10 @@ import 'package:flutter/widgets.dart';
class NavigationService { class NavigationService {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
NavigatorState get navigator => navigatorKey.currentState; NavigatorState? get navigator => navigatorKey.currentState;
void showPopUpDialog(AlertDialog dialog) { void showPopUpDialog(AlertDialog dialog) {
final context = navigatorKey.currentState.overlay.context; final context = navigatorKey.currentState!.overlay!.context;
showDialog( showDialog(
context: context, context: context,

View File

@ -9,10 +9,10 @@ class BackblazeCredential {
BackblazeCredential({this.keyId, this.applicationKey}); BackblazeCredential({this.keyId, this.applicationKey});
@HiveField(0) @HiveField(0)
final String keyId; final String? keyId;
@HiveField(1) @HiveField(1)
final String applicationKey; final String? applicationKey;
get encodedApiKey => encodedBackblazeKey(keyId, applicationKey); get encodedApiKey => encodedBackblazeKey(keyId, applicationKey);
@ -22,7 +22,7 @@ class BackblazeCredential {
} }
} }
String encodedBackblazeKey(String keyId, String applicationKey) { String encodedBackblazeKey(String? keyId, String? applicationKey) {
String _apiKey = '$keyId:$applicationKey'; String _apiKey = '$keyId:$applicationKey';
String encodedApiKey = base64.encode(utf8.encode(_apiKey)); String encodedApiKey = base64.encode(utf8.encode(_apiKey));
return encodedApiKey; return encodedApiKey;

View File

@ -17,8 +17,8 @@ class BackblazeCredentialAdapter extends TypeAdapter<BackblazeCredential> {
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return BackblazeCredential( return BackblazeCredential(
keyId: fields[0] as String, keyId: fields[0] as String?,
applicationKey: fields[1] as String, applicationKey: fields[1] as String?,
); );
} }

View File

@ -7,10 +7,10 @@ class CloudFlareDomain {
CloudFlareDomain({this.domainName, this.zoneId}); CloudFlareDomain({this.domainName, this.zoneId});
@HiveField(0) @HiveField(0)
final String domainName; final String? domainName;
@HiveField(1) @HiveField(1)
final String zoneId; final String? zoneId;
@override @override
String toString() { String toString() {

View File

@ -17,8 +17,8 @@ class CloudFlareDomainAdapter extends TypeAdapter<CloudFlareDomain> {
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return CloudFlareDomain( return CloudFlareDomain(
domainName: fields[0] as String, domainName: fields[0] as String?,
zoneId: fields[1] as String, zoneId: fields[1] as String?,
); );
} }

View File

@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'dns_records.g.dart'; part 'dns_records.g.dart';
@ -6,17 +5,17 @@ part 'dns_records.g.dart';
@JsonSerializable(createToJson: true, createFactory: false) @JsonSerializable(createToJson: true, createFactory: false)
class DnsRecords { class DnsRecords {
DnsRecords({ DnsRecords({
@required this.type, required this.type,
@required this.name, required this.name,
@required this.content, required this.content,
this.ttl = 3600, this.ttl = 3600,
this.priority = 10, this.priority = 10,
this.proxied = false, this.proxied = false,
}); });
final String type; final String type;
final String name; final String? name;
final String content; final String? content;
final int ttl; final int ttl;
final int priority; final int priority;
final bool proxied; final bool proxied;

View File

@ -5,12 +5,12 @@ final formater = new DateFormat('hh:mm');
class Message { class Message {
Message({this.text, this.type = MessageType.normal}) : time = DateTime.now(); Message({this.text, this.type = MessageType.normal}) : time = DateTime.now();
final String text; final String? text;
final DateTime time; final DateTime time;
final MessageType type; final MessageType type;
String get timeString => formater.format(time); String get timeString => formater.format(time);
static Message warn({String text}) => Message( static Message warn({String? text}) => Message(
text: text, text: text,
type: MessageType.warning, type: MessageType.warning,
); );

View File

@ -10,7 +10,7 @@ enum ProviderType {
} }
class ProviderModel extends Equatable { class ProviderModel extends Equatable {
const ProviderModel({this.state, this.type}); const ProviderModel({required this.state, required this.type});
final StateType state; final StateType state;
final ProviderType type; final ProviderType type;
@ -21,7 +21,7 @@ class ProviderModel extends Equatable {
); );
@override @override
List<Object> get props => [state, type]; List<Object?> get props => [state, type];
IconData get icon { IconData get icon {
switch (type) { switch (type) {
@ -31,10 +31,8 @@ class ProviderModel extends Equatable {
case ProviderType.domain: case ProviderType.domain:
return BrandIcons.globe; return BrandIcons.globe;
break;
case ProviderType.backup: case ProviderType.backup:
return BrandIcons.save; return BrandIcons.save;
} }
return null;
} }
} }

View File

@ -1,4 +1,3 @@
import 'package:flutter/widgets.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
part 'server_details.g.dart'; part 'server_details.g.dart';
@ -6,25 +5,25 @@ part 'server_details.g.dart';
@HiveType(typeId: 2) @HiveType(typeId: 2)
class HetznerServerDetails { class HetznerServerDetails {
HetznerServerDetails({ HetznerServerDetails({
@required this.ip4, required this.ip4,
@required this.id, required this.id,
@required this.createTime, required this.createTime,
this.startTime, this.startTime,
}); });
@HiveField(0) @HiveField(0)
final String ip4; final String? ip4;
@HiveField(1) @HiveField(1)
final int id; final int? id;
@HiveField(3) @HiveField(3)
final DateTime createTime; final DateTime? createTime;
@HiveField(2) @HiveField(2)
final DateTime startTime; final DateTime? startTime;
HetznerServerDetails copyWith({DateTime startTime}) { HetznerServerDetails copyWith({DateTime? startTime}) {
return HetznerServerDetails( return HetznerServerDetails(
startTime: startTime ?? this.startTime, startTime: startTime ?? this.startTime,
createTime: createTime, createTime: createTime,

View File

@ -17,10 +17,10 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return HetznerServerDetails( return HetznerServerDetails(
ip4: fields[0] as String, ip4: fields[0] as String?,
id: fields[1] as int, id: fields[1] as int?,
createTime: fields[3] as DateTime, createTime: fields[3] as DateTime?,
startTime: fields[2] as DateTime, startTime: fields[2] as DateTime?,
); );
} }

View File

@ -1,12 +1,10 @@
import 'package:flutter/foundation.dart';
class ServerStatus { class ServerStatus {
final StatusTypes http; final StatusTypes http;
final StatusTypes imap; final StatusTypes imap;
final StatusTypes smtp; final StatusTypes smtp;
ServerStatus({ ServerStatus({
@required this.http, required this.http,
this.imap = StatusTypes.nodata, this.imap = StatusTypes.nodata,
this.smtp = StatusTypes.nodata, this.smtp = StatusTypes.nodata,
}); });
@ -20,7 +18,7 @@ class ServerStatus {
} }
} }
StatusTypes statusTypeFromNumber(int number) { StatusTypes statusTypeFromNumber(int? number) {
if (number == 0) { if (number == 0) {
return StatusTypes.ok; return StatusTypes.ok;
} else if (number == 1) { } else if (number == 1) {

View File

@ -10,7 +10,7 @@ enum ServiceTypes {
} }
class Service extends Equatable { class Service extends Equatable {
const Service({this.state, this.type}); const Service({required this.state, required this.type});
final StateType state; final StateType state;
final ServiceTypes type; final ServiceTypes type;
@ -21,5 +21,5 @@ class Service extends Equatable {
); );
@override @override
List<Object> get props => [state, type]; List<Object?> get props => [state, type];
} }

View File

@ -1,7 +1,6 @@
import 'dart:ui'; import 'dart:ui';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:selfprivacy/utils/color_utils.dart'; import 'package:selfprivacy/utils/color_utils.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:selfprivacy/utils/crypto.dart'; import 'package:selfprivacy/utils/crypto.dart';
@ -11,18 +10,18 @@ part 'user.g.dart';
@HiveType(typeId: 1) @HiveType(typeId: 1)
class User extends Equatable { class User extends Equatable {
User({ User({
@required this.login, required this.login,
@required this.password, required this.password,
}); });
@HiveField(0) @HiveField(0)
final String login; final String login;
@HiveField(1) @HiveField(1)
final String password; final String password;
@override @override
List<Object> get props => [login, password]; List<Object?> get props => [login, password];
Color get color => stringToColor(login); Color get color => stringToColor(login);

View File

@ -36,7 +36,7 @@ void main() async {
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var appSettings = context.watch<AppSettingsCubit>().state; AppSettingsState appSettings = context.watch<AppSettingsCubit>().state;
return AnnotatedRegion<SystemUiOverlayStyle>( return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light, // Manually changnig appbar color value: SystemUiOverlayStyle.light, // Manually changnig appbar color
@ -51,12 +51,12 @@ class MyApp extends StatelessWidget {
home: appSettings.isOnbordingShowing home: appSettings.isOnbordingShowing
? OnboardingPage(nextPage: InitializingPage()) ? OnboardingPage(nextPage: InitializingPage())
: RootPage(), : RootPage(),
builder: (BuildContext context, Widget widget) { builder: (BuildContext context, Widget? widget) {
Widget error = Text('...rendering error...'); Widget error = Text('...rendering error...');
if (widget is Scaffold || widget is Navigator) if (widget is Scaffold || widget is Navigator)
error = Scaffold(body: Center(child: error)); error = Scaffold(body: Center(child: error));
ErrorWidget.builder = (FlutterErrorDetails errorDetails) => error; ErrorWidget.builder = (FlutterErrorDetails errorDetails) => error;
return widget; return widget!;
}, },
), ),
); );

View File

@ -3,14 +3,14 @@ import 'package:selfprivacy/config/brand_colors.dart';
class ActionButton extends StatelessWidget { class ActionButton extends StatelessWidget {
const ActionButton({ const ActionButton({
Key key, Key? key,
this.text, this.text,
this.onPressed, this.onPressed,
this.isRed = false, this.isRed = false,
}) : super(key: key); }) : super(key: key);
final VoidCallback onPressed; final VoidCallback? onPressed;
final String text; final String? text;
final bool isRed; final bool isRed;
@override @override
@ -19,12 +19,12 @@ class ActionButton extends StatelessWidget {
return TextButton( return TextButton(
child: Text( child: Text(
text, text!,
style: isRed ? TextStyle(color: BrandColors.red1) : null, style: isRed ? TextStyle(color: BrandColors.red1) : null,
), ),
onPressed: () { onPressed: () {
navigator.pop(); navigator.pop();
if (onPressed != null) onPressed(); if (onPressed != null) onPressed!();
}, },
); );
} }

View File

@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
class BrandAlert extends AlertDialog { class BrandAlert extends AlertDialog {
BrandAlert({ BrandAlert({
Key key, Key? key,
String title, String? title,
String contentText, String? contentText,
List<Widget> acitons, List<Widget>? acitons,
}) : super( }) : super(
key: key, key: key,
title: title != null ? Text(title) : null, title: title != null ? Text(title) : null,
content: title != null ? Text(contentText) : null, content: title != null ? Text(contentText!) : null,
actions: acitons, actions: acitons,
); );
} }

View File

@ -8,10 +8,10 @@ enum BrandButtonTypes { rised, text, iconText }
class BrandButton { class BrandButton {
static rised({ static rised({
Key key, Key? key,
@required VoidCallback onPressed, required VoidCallback? onPressed,
String title, String? title,
Widget child, Widget? child,
}) { }) {
assert(title == null || child == null, 'required title or child'); assert(title == null || child == null, 'required title or child');
assert(title != null || child != null, 'required title or child'); assert(title != null || child != null, 'required title or child');
@ -24,9 +24,9 @@ class BrandButton {
} }
static text({ static text({
Key key, Key? key,
@required VoidCallback onPressed, required VoidCallback onPressed,
@required String title, required String title,
}) => }) =>
_TextButton( _TextButton(
key: key, key: key,
@ -35,10 +35,10 @@ class BrandButton {
); );
static iconText({ static iconText({
Key key, Key? key,
@required VoidCallback onPressed, required VoidCallback onPressed,
@required String title, required String title,
@required Icon icon, required Icon icon,
}) => }) =>
_IconTextButton( _IconTextButton(
key: key, key: key,
@ -50,15 +50,15 @@ class BrandButton {
class _RisedButton extends StatelessWidget { class _RisedButton extends StatelessWidget {
const _RisedButton({ const _RisedButton({
Key key, Key? key,
this.onPressed, this.onPressed,
this.title, this.title,
this.child, this.child,
}) : super(key: key); }) : super(key: key);
final VoidCallback onPressed; final VoidCallback? onPressed;
final String title; final String? title;
final Widget child; final Widget? child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -88,13 +88,13 @@ class _RisedButton extends StatelessWidget {
class _TextButton extends StatelessWidget { class _TextButton extends StatelessWidget {
const _TextButton({ const _TextButton({
Key key, Key? key,
this.onPressed, this.onPressed,
this.title, this.title,
}) : super(key: key); }) : super(key: key);
final VoidCallback onPressed; final VoidCallback? onPressed;
final String title; final String? title;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -106,7 +106,7 @@ class _TextButton extends StatelessWidget {
alignment: Alignment.center, alignment: Alignment.center,
padding: EdgeInsets.all(12), padding: EdgeInsets.all(12),
child: Text( child: Text(
title, title!,
style: TextStyle( style: TextStyle(
color: BrandColors.blue, color: BrandColors.blue,
fontSize: 16, fontSize: 16,
@ -120,12 +120,12 @@ class _TextButton extends StatelessWidget {
} }
class _IconTextButton extends StatelessWidget { class _IconTextButton extends StatelessWidget {
const _IconTextButton({Key key, this.onPressed, this.title, this.icon}) const _IconTextButton({Key? key, this.onPressed, this.title, this.icon})
: super(key: key); : super(key: key);
final VoidCallback onPressed; final VoidCallback? onPressed;
final String title; final String? title;
final Icon icon; final Icon? icon;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -4,11 +4,11 @@ import 'package:selfprivacy/utils/extensions/elevation_extension.dart';
class BrandCard extends StatelessWidget { class BrandCard extends StatelessWidget {
const BrandCard({ const BrandCard({
Key key, Key? key,
this.child, this.child,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget? child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
class BrandDivider extends StatelessWidget { class BrandDivider extends StatelessWidget {
const BrandDivider({Key key}) : super(key: key); const BrandDivider({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -4,8 +4,8 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
class BrandHeader extends StatelessWidget { class BrandHeader extends StatelessWidget {
const BrandHeader({ const BrandHeader({
Key key, Key? key,
@required this.title, required this.title,
this.hasBackButton = false, this.hasBackButton = false,
}) : super(key: key); }) : super(key: key);

View File

@ -19,7 +19,7 @@ class BrandIcons {
BrandIcons._(); BrandIcons._();
static const _kFontFam = 'BrandIcons'; static const _kFontFam = 'BrandIcons';
static const _kFontPkg = null; static const dynamic _kFontPkg = null;
static const IconData connection = static const IconData connection =
IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);

View File

@ -4,11 +4,11 @@ var navigatorKey = GlobalKey<NavigatorState>();
class BrandModalSheet extends StatelessWidget { class BrandModalSheet extends StatelessWidget {
const BrandModalSheet({ const BrandModalSheet({
Key key, Key? key,
this.child, this.child,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget? child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DraggableScrollableSheet( return DraggableScrollableSheet(

View File

@ -5,21 +5,19 @@ import 'package:url_launcher/url_launcher.dart';
class BrandSpanButton extends TextSpan { class BrandSpanButton extends TextSpan {
BrandSpanButton({ BrandSpanButton({
@required String text, required String text,
@required VoidCallback onTap, required VoidCallback onTap,
TextStyle style, TextStyle? style,
}) : assert(text != null), }) : super(
assert(onTap != null),
super(
recognizer: TapGestureRecognizer()..onTap = onTap, recognizer: TapGestureRecognizer()..onTap = onTap,
text: text, text: text,
style: (style ?? TextStyle()).copyWith(color: BrandColors.blue), style: (style ?? TextStyle()).copyWith(color: BrandColors.blue),
); );
static link({ static link({
@required String text, required String text,
String urlString, String? urlString,
TextStyle style, TextStyle? style,
}) => }) =>
BrandSpanButton( BrandSpanButton(
text: text, text: text,

View File

@ -1,37 +1,38 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
import 'package:easy_localization/easy_localization.dart';
final _kBottomTabBarHeight = 51; final _kBottomTabBarHeight = 51;
class BrandTabBar extends StatefulWidget { class BrandTabBar extends StatefulWidget {
BrandTabBar({Key key, this.controller}) : super(key: key); BrandTabBar({Key? key, this.controller}) : super(key: key);
final TabController controller; final TabController? controller;
@override @override
_BrandTabBarState createState() => _BrandTabBarState(); _BrandTabBarState createState() => _BrandTabBarState();
} }
class _BrandTabBarState extends State<BrandTabBar> { class _BrandTabBarState extends State<BrandTabBar> {
int currentIndex; int? currentIndex;
@override @override
void initState() { void initState() {
currentIndex = widget.controller.index; currentIndex = widget.controller!.index;
widget.controller.addListener(_listener); widget.controller!.addListener(_listener);
super.initState(); super.initState();
} }
_listener() { _listener() {
if (currentIndex != widget.controller.index) { if (currentIndex != widget.controller!.index) {
setState(() { setState(() {
currentIndex = widget.controller.index; currentIndex = widget.controller!.index;
}); });
} }
} }
@override @override
void dispose() { void dispose() {
widget.controller ?? widget.controller.removeListener(_listener); widget.controller ?? widget.controller!.removeListener(_listener);
super.dispose(); super.dispose();
} }
@ -50,10 +51,10 @@ class _BrandTabBarState extends State<BrandTabBar> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
_getIconButton('Провайдеры', BrandIcons.server, 0), _getIconButton('basis.providers'.tr(), BrandIcons.server, 0),
_getIconButton('Сервисы', BrandIcons.box, 1), _getIconButton('basis.services'.tr(), BrandIcons.box, 1),
_getIconButton('Пользователи', BrandIcons.users, 2), _getIconButton('basis.users'.tr(), BrandIcons.users, 2),
_getIconButton('Еще', BrandIcons.menu, 3), _getIconButton('basis.more'.tr(), BrandIcons.menu, 3),
], ],
), ),
), ),
@ -68,7 +69,7 @@ class _BrandTabBarState extends State<BrandTabBar> {
var isActive = currentIndex == index; var isActive = currentIndex == index;
var color = isActive ? acitivColor : BrandColors.inactive; var color = isActive ? acitivColor : BrandColors.inactive;
return InkWell( return InkWell(
onTap: () => widget.controller.animateTo(index), onTap: () => widget.controller!.animateTo(index),
child: Padding( child: Padding(
padding: EdgeInsets.all(6), padding: EdgeInsets.all(6),
child: ConstrainedBox( child: ConstrainedBox(

View File

@ -17,26 +17,26 @@ enum TextType {
class BrandText extends StatelessWidget { class BrandText extends StatelessWidget {
const BrandText( const BrandText(
this.text, { this.text, {
Key key, Key? key,
this.style, this.style,
@required this.type, required this.type,
this.overflow, this.overflow,
this.softWrap, this.softWrap,
this.textAlign, this.textAlign,
}) : super(key: key); }) : super(key: key);
final String text; final String? text;
final TextStyle style; final TextStyle? style;
final TextType type; final TextType type;
final TextOverflow overflow; final TextOverflow? overflow;
final bool softWrap; final bool? softWrap;
final TextAlign textAlign; final TextAlign? textAlign;
factory BrandText.h1( factory BrandText.h1(
String text, { String? text, {
TextStyle style, TextStyle? style,
TextOverflow overflow, TextOverflow? overflow,
bool softWrap, bool? softWrap,
}) => }) =>
BrandText( BrandText(
text, text,
@ -44,18 +44,18 @@ class BrandText extends StatelessWidget {
style: style, style: style,
); );
factory BrandText.onboardingTitle(String text, {TextStyle style}) => factory BrandText.onboardingTitle(String text, {TextStyle? style}) =>
BrandText( BrandText(
text, text,
type: TextType.onboardingTitle, type: TextType.onboardingTitle,
style: style, style: style,
); );
factory BrandText.h2(String text, {TextStyle style}) => BrandText( factory BrandText.h2(String? text, {TextStyle? style}) => BrandText(
text, text,
type: TextType.h2, type: TextType.h2,
style: style, style: style,
); );
factory BrandText.h3(String text, {TextStyle style, TextAlign textAlign}) => factory BrandText.h3(String text, {TextStyle? style, TextAlign? textAlign}) =>
BrandText( BrandText(
text, text,
type: TextType.h3, type: TextType.h3,
@ -63,35 +63,35 @@ class BrandText extends StatelessWidget {
textAlign: textAlign, textAlign: textAlign,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
); );
factory BrandText.h4(String text, {TextStyle style}) => BrandText( factory BrandText.h4(String? text, {TextStyle? style}) => BrandText(
text, text,
type: TextType.h4, type: TextType.h4,
style: style, style: style,
); );
factory BrandText.body1(String text, {TextStyle style}) => BrandText( factory BrandText.body1(String? text, {TextStyle? style}) => BrandText(
text, text,
type: TextType.body1, type: TextType.body1,
style: style, style: style,
); );
factory BrandText.body2(String text, {TextStyle style}) => BrandText( factory BrandText.body2(String? text, {TextStyle? style}) => BrandText(
text, text,
type: TextType.body2, type: TextType.body2,
style: style, style: style,
); );
factory BrandText.medium(String text, factory BrandText.medium(String? text,
{TextStyle style, TextAlign textAlign}) => {TextStyle? style, TextAlign? textAlign}) =>
BrandText( BrandText(
text, text,
type: TextType.medium, type: TextType.medium,
style: style, style: style,
textAlign: textAlign, textAlign: textAlign,
); );
factory BrandText.small(String text, {TextStyle style}) => BrandText( factory BrandText.small(String text, {TextStyle? style}) => BrandText(
text, text,
type: TextType.small, type: TextType.small,
style: style, style: style,
); );
factory BrandText.buttonTitleText(String text, {TextStyle style}) => factory BrandText.buttonTitleText(String? text, {TextStyle? style}) =>
BrandText( BrandText(
text, text,
type: TextType.buttonTitleText, type: TextType.buttonTitleText,
@ -99,7 +99,7 @@ class BrandText extends StatelessWidget {
); );
@override @override
Text build(BuildContext context) { Text build(BuildContext context) {
TextStyle style; TextStyle? style;
var isDark = Theme.of(context).brightness == Brightness.dark; var isDark = Theme.of(context).brightness == Brightness.dark;
switch (type) { switch (type) {
@ -153,7 +153,7 @@ class BrandText extends StatelessWidget {
style = style.merge(this.style); style = style.merge(this.style);
} }
return Text( return Text(
text, text!,
style: style, style: style,
overflow: overflow, overflow: overflow,
softWrap: softWrap, softWrap: softWrap,

View File

@ -6,21 +6,21 @@ import 'package:selfprivacy/utils/named_font_weight.dart';
class BrandTimer extends StatefulWidget { class BrandTimer extends StatefulWidget {
const BrandTimer({ const BrandTimer({
Key key, Key? key,
@required this.startDateTime, required this.startDateTime,
@required this.duration, required this.duration,
}) : super(key: key); }) : super(key: key);
final DateTime startDateTime; final DateTime? startDateTime;
final Duration duration; final Duration? duration;
@override @override
_BrandTimerState createState() => _BrandTimerState(); _BrandTimerState createState() => _BrandTimerState();
} }
class _BrandTimerState extends State<BrandTimer> { class _BrandTimerState extends State<BrandTimer> {
String _timeString; String? _timeString;
Timer timer; late Timer timer;
@override @override
void initState() { void initState() {
@ -31,8 +31,8 @@ class _BrandTimerState extends State<BrandTimer> {
_timerStart() { _timerStart() {
_timeString = diffenceFromStart; _timeString = diffenceFromStart;
timer = Timer.periodic(Duration(seconds: 1), (Timer t) { timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
var timePassed = DateTime.now().difference(widget.startDateTime); var timePassed = DateTime.now().difference(widget.startDateTime!);
if (timePassed > widget.duration) { if (timePassed > widget.duration!) {
t.cancel(); t.cancel();
} else { } else {
_getTime(); _getTime();
@ -66,12 +66,12 @@ class _BrandTimerState extends State<BrandTimer> {
} }
String get diffenceFromStart => String get diffenceFromStart =>
_durationToString(DateTime.now().difference(widget.startDateTime)); _durationToString(DateTime.now().difference(widget.startDateTime!));
String _durationToString(Duration duration) { String _durationToString(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0"); String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitSeconds = String twoDigitSeconds =
twoDigits(widget.duration.inSeconds - duration.inSeconds.remainder(60)); twoDigits(widget.duration!.inSeconds - duration.inSeconds.remainder(60));
return "$twoDigitSeconds cек"; return "$twoDigitSeconds cек";
} }

View File

@ -3,9 +3,9 @@ import 'package:selfprivacy/config/brand_colors.dart';
class DotsIndicator extends StatelessWidget { class DotsIndicator extends StatelessWidget {
const DotsIndicator({ const DotsIndicator({
Key key, Key? key,
@required this.activeIndex, required this.activeIndex,
@required this.count, required this.count,
}) : super(key: key); }) : super(key: key);
final int activeIndex; final int activeIndex;

View File

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
class BrandError extends StatelessWidget { class BrandError extends StatelessWidget {
const BrandError({Key key, this.error, this.stackTrace}) : super(key: key); const BrandError({Key? key, this.error, this.stackTrace}) : super(key: key);
final Object error; final Object? error;
final StackTrace stackTrace; final StackTrace? stackTrace;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -3,14 +3,14 @@ import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/logic/models/state_types.dart'; import 'package:selfprivacy/logic/models/state_types.dart';
class IconStatusMask extends StatelessWidget { class IconStatusMask extends StatelessWidget {
IconStatusMask({this.child, this.status}); IconStatusMask({required this.child, required this.status});
final Icon child; final Icon child;
final StateType status; final StateType status;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<Color> colors; late List<Color> colors;
switch (status) { switch (status) {
case StateType.uninitialized: case StateType.uninitialized:
colors = BrandColors.uninitializedGradientColors; colors = BrandColors.uninitializedGradientColors;

View File

@ -2,9 +2,10 @@ import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/ui/pages/initializing/initializing.dart'; import 'package:selfprivacy/ui/pages/initializing/initializing.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
class NotReadyCard extends StatelessWidget { class NotReadyCard extends StatelessWidget {
const NotReadyCard({Key key}) : super(key: key); const NotReadyCard({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -16,13 +17,13 @@ class NotReadyCard extends StatelessWidget {
text: TextSpan( text: TextSpan(
children: [ children: [
TextSpan( TextSpan(
text: 'Завершите настройку приложения используя ', text: 'not_ready_card.1'.tr(),
style: TextStyle(color: BrandColors.white), style: TextStyle(color: BrandColors.white),
), ),
WidgetSpan( WidgetSpan(
child: GestureDetector( child: GestureDetector(
child: Text( child: Text(
'Мастер подключения', 'not_ready_card.2'.tr(),
style: TextStyle( style: TextStyle(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.blueAccent ? Colors.blueAccent
@ -38,7 +39,7 @@ class NotReadyCard extends StatelessWidget {
), ),
), ),
TextSpan( TextSpan(
text: ' для продолжения работы', text: 'not_ready_card.3'.tr(),
style: TextStyle(color: BrandColors.white), style: TextStyle(color: BrandColors.white),
), ),
], ],

View File

@ -7,9 +7,9 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
class ProgressBar extends StatefulWidget { class ProgressBar extends StatefulWidget {
ProgressBar({ ProgressBar({
Key key, Key? key,
@required this.steps, required this.steps,
@required this.activeIndex, required this.activeIndex,
}) : super(key: key); }) : super(key: key);
final int activeIndex; final int activeIndex;
@ -102,14 +102,14 @@ class _ProgressBarState extends State<ProgressBar> {
} }
Expanded _stepTitle({ Expanded _stepTitle({
int index, required int index,
TextStyle style, TextStyle? style,
String step, String? step,
}) { }) {
var isActive = index == widget.activeIndex; var isActive = index == widget.activeIndex;
var checked = index < widget.activeIndex; var checked = index < widget.activeIndex;
style = isActive ? style.copyWith(fontWeight: FontWeight.w700) : style; style = isActive ? style!.copyWith(fontWeight: FontWeight.w700) : style;
return Expanded( return Expanded(
flex: 2, flex: 2,
child: RichText( child: RichText(

View File

@ -3,10 +3,10 @@ import 'package:selfprivacy/config/brand_colors.dart';
class SwitcherBlock extends StatelessWidget { class SwitcherBlock extends StatelessWidget {
const SwitcherBlock({ const SwitcherBlock({
Key key, Key? key,
@required this.child, required this.child,
@required this.isActive, required this.isActive,
@required this.onChange, required this.onChange,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget child;

View File

@ -81,7 +81,7 @@ class InitializingPage extends StatelessWidget {
onPressed: () { onPressed: () {
Navigator.of(context).pushAndRemoveUntil( Navigator.of(context).pushAndRemoveUntil(
materialRoute(RootPage()), materialRoute(RootPage()),
(predicate) => predicate == null, (predicate) => false,
); );
}), }),
SizedBox(height: 30), SizedBox(height: 30),
@ -96,7 +96,7 @@ class InitializingPage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => HetznerFormCubit(initializingCubit), create: (context) => HetznerFormCubit(initializingCubit),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var formCubit = context.watch<HetznerFormCubit>(); var formCubitState = context.watch<HetznerFormCubit>().state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -111,7 +111,7 @@ class InitializingPage extends StatelessWidget {
'Здесь будут жить наши данные и SelfPrivacy-сервисы'), 'Здесь будут жить наши данные и SelfPrivacy-сервисы'),
Spacer(), Spacer(),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.apiKey, formFieldCubit: context.read<HetznerFormCubit>().apiKey,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -120,8 +120,9 @@ class InitializingPage extends StatelessWidget {
), ),
Spacer(), Spacer(),
BrandButton.rised( BrandButton.rised(
onPressed: onPressed: formCubitState.isSubmitting
formCubit.state.isSubmitting ? null : formCubit.trySubmit, ? null
: () => context.read<HetznerFormCubit>().trySubmit(),
title: 'Подключить', title: 'Подключить',
), ),
SizedBox(height: 10), SizedBox(height: 10),
@ -150,7 +151,7 @@ class InitializingPage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => CloudFlareFormCubit(initializingCubit), create: (context) => CloudFlareFormCubit(initializingCubit),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var formCubit = context.watch<CloudFlareFormCubit>(); var formCubitState = context.watch<CloudFlareFormCubit>().state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -165,7 +166,7 @@ class InitializingPage extends StatelessWidget {
BrandText.body2('Для управления DNS вашего домена'), BrandText.body2('Для управления DNS вашего домена'),
Spacer(), Spacer(),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.apiKey, formFieldCubit: context.read<CloudFlareFormCubit>().apiKey,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -174,8 +175,9 @@ class InitializingPage extends StatelessWidget {
), ),
Spacer(), Spacer(),
BrandButton.rised( BrandButton.rised(
onPressed: onPressed: formCubitState.isSubmitting
formCubit.state.isSubmitting ? null : formCubit.trySubmit, ? null
: () => context.read<CloudFlareFormCubit>().trySubmit(),
title: 'Подключить', title: 'Подключить',
), ),
SizedBox(height: 10), SizedBox(height: 10),
@ -193,7 +195,7 @@ class InitializingPage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => BackblazeFormCubit(initializingCubit), create: (context) => BackblazeFormCubit(initializingCubit),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var formCubit = context.watch<BackblazeFormCubit>(); var formCubitState = context.watch<BackblazeFormCubit>().state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -206,7 +208,7 @@ class InitializingPage extends StatelessWidget {
SizedBox(height: 10), SizedBox(height: 10),
Spacer(), Spacer(),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.keyId, formFieldCubit: context.read<BackblazeFormCubit>().keyId,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -215,7 +217,7 @@ class InitializingPage extends StatelessWidget {
), ),
Spacer(), Spacer(),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.applicationKey, formFieldCubit: context.read<BackblazeFormCubit>().applicationKey,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -224,8 +226,9 @@ class InitializingPage extends StatelessWidget {
), ),
Spacer(), Spacer(),
BrandButton.rised( BrandButton.rised(
onPressed: onPressed: formCubitState.isSubmitting
formCubit.state.isSubmitting ? null : formCubit.trySubmit, ? null
: () => context.read<BackblazeFormCubit>().trySubmit(),
title: 'Подключить', title: 'Подключить',
), ),
SizedBox(height: 10), SizedBox(height: 10),
@ -243,8 +246,7 @@ class InitializingPage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => DomainSetupCubit(initializingCubit)..load(), create: (context) => DomainSetupCubit(initializingCubit)..load(),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var domainSetup = context.watch<DomainSetupCubit>(); DomainSetupState state = context.watch<DomainSetupCubit>().state;
var state = domainSetup.state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -283,7 +285,7 @@ class InitializingPage extends StatelessWidget {
Container( Container(
width: 50, width: 50,
child: BrandButton.rised( child: BrandButton.rised(
onPressed: () => domainSetup.load(), onPressed: () => context.read<DomainSetupCubit>().load(),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -302,7 +304,7 @@ class InitializingPage extends StatelessWidget {
if (state is Empty) ...[ if (state is Empty) ...[
SizedBox(height: 30), SizedBox(height: 30),
BrandButton.rised( BrandButton.rised(
onPressed: () => domainSetup.load(), onPressed: () => context.read<DomainSetupCubit>().load(),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -319,7 +321,7 @@ class InitializingPage extends StatelessWidget {
if (state is Loaded) ...[ if (state is Loaded) ...[
SizedBox(height: 30), SizedBox(height: 30),
BrandButton.rised( BrandButton.rised(
onPressed: () => domainSetup.saveDomain(), onPressed: () => context.read<DomainSetupCubit>().saveDomain(),
title: 'Сохранить домен', title: 'Сохранить домен',
), ),
], ],
@ -340,7 +342,7 @@ class InitializingPage extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (context) => RootUserFormCubit(initializingCubit), create: (context) => RootUserFormCubit(initializingCubit),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var formCubit = context.watch<RootUserFormCubit>(); var formCubitState = context.watch<RootUserFormCubit>().state;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -348,7 +350,7 @@ class InitializingPage extends StatelessWidget {
Spacer(), Spacer(),
SizedBox(height: 10), SizedBox(height: 10),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.userName, formFieldCubit: context.read<RootUserFormCubit>().userName,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -357,12 +359,12 @@ class InitializingPage extends StatelessWidget {
), ),
SizedBox(height: 10), SizedBox(height: 10),
BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>( BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>(
bloc: formCubit.isVisible, bloc: context.read<RootUserFormCubit>().isVisible,
builder: (context, state) { builder: (context, state) {
var isVisible = state.value; var isVisible = state.value;
return CubitFormTextField( return CubitFormTextField(
obscureText: !isVisible, obscureText: !isVisible,
formFieldCubit: formCubit.password, formFieldCubit: context.read<RootUserFormCubit>().password,
textAlign: TextAlign.center, textAlign: TextAlign.center,
scrollPadding: EdgeInsets.only(bottom: 70), scrollPadding: EdgeInsets.only(bottom: 70),
decoration: InputDecoration( decoration: InputDecoration(
@ -371,7 +373,10 @@ class InitializingPage extends StatelessWidget {
icon: Icon( icon: Icon(
isVisible ? Icons.visibility : Icons.visibility_off, isVisible ? Icons.visibility : Icons.visibility_off,
), ),
onPressed: () => formCubit.isVisible.setValue(!isVisible), onPressed: () => context
.read<RootUserFormCubit>()
.isVisible
.setValue(!isVisible),
), ),
suffixIconConstraints: BoxConstraints(minWidth: 60), suffixIconConstraints: BoxConstraints(minWidth: 60),
prefixIconConstraints: BoxConstraints(maxWidth: 85), prefixIconConstraints: BoxConstraints(maxWidth: 85),
@ -382,8 +387,9 @@ class InitializingPage extends StatelessWidget {
), ),
Spacer(), Spacer(),
BrandButton.rised( BrandButton.rised(
onPressed: onPressed: formCubitState.isSubmitting
formCubit.state.isSubmitting ? null : formCubit.trySubmit, ? null
: () => context.read<RootUserFormCubit>().trySubmit(),
title: 'Подключить', title: 'Подключить',
), ),
SizedBox(height: 10), SizedBox(height: 10),
@ -410,7 +416,7 @@ class InitializingPage extends StatelessWidget {
Spacer(), Spacer(),
BrandButton.rised( BrandButton.rised(
onPressed: onPressed:
isLoading ? null : appConfigCubit.createServerAndSetDnsRecords, isLoading! ? null : appConfigCubit.createServerAndSetDnsRecords,
title: isLoading ? 'loading' : 'Создать сервер', title: isLoading ? 'loading' : 'Создать сервер',
), ),
Spacer(flex: 2), Spacer(flex: 2),
@ -427,10 +433,10 @@ class InitializingPage extends StatelessWidget {
assert(appConfigCubit.state is TimerState, 'wronge state'); assert(appConfigCubit.state is TimerState, 'wronge state');
var state = appConfigCubit.state as TimerState; var state = appConfigCubit.state as TimerState;
String text; String? text;
if (state.isServerReseted) { if (state.isServerReseted!) {
text = 'Сервер презагружен, ждем последнюю проверку'; text = 'Сервер презагружен, ждем последнюю проверку';
} else if (state.isServerStarted) { } else if (state.isServerStarted!) {
text = 'Cервер запушен, сейчас он будет проверен и перезагружен'; text = 'Cервер запушен, сейчас он будет проверен и перезагружен';
} else if (state.isServerCreated) { } else if (state.isServerCreated) {
text = 'Cервер создан, идет проверка ДНС адресов и запуск сервера'; text = 'Cервер создан, идет проверка ДНС адресов и запуск сервера';
@ -443,7 +449,7 @@ class InitializingPage extends StatelessWidget {
SizedBox(height: 10), SizedBox(height: 10),
BrandText.body2(text), BrandText.body2(text),
SizedBox(height: 10), SizedBox(height: 10),
if (!state.isLoading) if (!state.isLoading!)
Row( Row(
children: [ children: [
BrandText.body2('До следующей проверки: '), BrandText.body2('До следующей проверки: '),
@ -453,7 +459,7 @@ class InitializingPage extends StatelessWidget {
) )
], ],
), ),
if (state.isLoading) BrandText.body2('Проверка'), if (state.isLoading!) BrandText.body2('Проверка'),
Spacer( Spacer(
flex: 2, flex: 2,
), ),
@ -477,7 +483,7 @@ class InitializingPage extends StatelessWidget {
class _HowHetzner extends StatelessWidget { class _HowHetzner extends StatelessWidget {
const _HowHetzner({ const _HowHetzner({
Key key, Key? key,
}) : super(key: key); }) : super(key: key);
@override @override

View File

@ -5,7 +5,7 @@ import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
class AboutPage extends StatelessWidget { class AboutPage extends StatelessWidget {
const AboutPage({Key key}) : super(key: key); const AboutPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -11,7 +11,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/utils/named_font_weight.dart'; import 'package:selfprivacy/utils/named_font_weight.dart';
class AppSettingsPage extends StatefulWidget { class AppSettingsPage extends StatefulWidget {
const AppSettingsPage({Key key}) : super(key: key); const AppSettingsPage({Key? key}) : super(key: key);
@override @override
_AppSettingsPageState createState() => _AppSettingsPageState(); _AppSettingsPageState createState() => _AppSettingsPageState();
@ -20,9 +20,7 @@ class AppSettingsPage extends StatefulWidget {
class _AppSettingsPageState extends State<AppSettingsPage> { class _AppSettingsPageState extends State<AppSettingsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var appSettings = context.watch<AppSettingsCubit>(); var isDarkModeOn = context.watch<AppSettingsCubit>().state.isDarkModeOn;
var isDarkModeOn = appSettings.state.isDarkModeOn;
return SafeArea( return SafeArea(
child: Builder(builder: (context) { child: Builder(builder: (context) {
@ -57,8 +55,9 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
activeColor: BrandColors.green1, activeColor: BrandColors.green1,
activeTrackColor: BrandColors.green2, activeTrackColor: BrandColors.green2,
value: Theme.of(context).brightness == Brightness.dark, value: Theme.of(context).brightness == Brightness.dark,
onChanged: (value) => appSettings.updateDarkMode( onChanged: (value) => context
isDarkModeOn: !isDarkModeOn), .read<AppSettingsCubit>()
.updateDarkMode(isDarkModeOn: !isDarkModeOn),
), ),
], ],
), ),
@ -130,9 +129,9 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
class _TextColumn extends StatelessWidget { class _TextColumn extends StatelessWidget {
const _TextColumn({ const _TextColumn({
Key key, Key? key,
@required this.title, required this.title,
@required this.value, required this.value,
this.hasWarning = false, this.hasWarning = false,
}) : super(key: key); }) : super(key: key);

View File

@ -9,7 +9,7 @@ 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_header/brand_header.dart';
class Console extends StatefulWidget { class Console extends StatefulWidget {
const Console({Key key}) : super(key: key); const Console({Key? key}) : super(key: key);
@override @override
_ConsoleState createState() => _ConsoleState(); _ConsoleState createState() => _ConsoleState();

View File

@ -6,7 +6,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';
class InfoPage extends StatelessWidget { class InfoPage extends StatelessWidget {
const InfoPage({Key key}) : super(key: key); const InfoPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -9,6 +9,7 @@ import 'package:selfprivacy/ui/pages/initializing/initializing.dart';
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart'; import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
import 'package:selfprivacy/ui/pages/rootRoute.dart'; import 'package:selfprivacy/ui/pages/rootRoute.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
import 'about/about.dart'; import 'about/about.dart';
import 'app_settings/app_setting.dart'; import 'app_settings/app_setting.dart';
@ -16,13 +17,13 @@ import 'console/console.dart';
import 'info/info.dart'; import 'info/info.dart';
class MorePage extends StatelessWidget { class MorePage extends StatelessWidget {
const MorePage({Key key}) : super(key: key); const MorePage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: PreferredSize( appBar: PreferredSize(
child: BrandHeader(title: 'Еще'), child: BrandHeader(title: 'basis.more'.tr()),
preferredSize: Size.fromHeight(52), preferredSize: Size.fromHeight(52),
), ),
body: ListView( body: ListView(
@ -33,32 +34,32 @@ class MorePage extends StatelessWidget {
children: [ children: [
BrandDivider(), BrandDivider(),
_NavItem( _NavItem(
title: 'Мастер Подключения', title: 'more.configuration_wizard'.tr(),
iconData: BrandIcons.settings, iconData: BrandIcons.settings,
goTo: InitializingPage(), goTo: InitializingPage(),
), ),
_NavItem( _NavItem(
title: 'Настройки приложения', title: 'more.settings'.tr(),
iconData: BrandIcons.settings, iconData: BrandIcons.settings,
goTo: AppSettingsPage(), goTo: AppSettingsPage(),
), ),
_NavItem( _NavItem(
title: 'О проекте Selfprivacy', title: 'more.about_project'.tr(),
iconData: BrandIcons.triangle, iconData: BrandIcons.triangle,
goTo: AboutPage(), goTo: AboutPage(),
), ),
_NavItem( _NavItem(
title: 'О приложении', title: 'more.about_app'.tr(),
iconData: BrandIcons.help, iconData: BrandIcons.help,
goTo: InfoPage(), goTo: InfoPage(),
), ),
_NavItem( _NavItem(
title: 'Onboarding', title: 'more.onboarding'.tr(),
iconData: BrandIcons.triangle, iconData: BrandIcons.triangle,
goTo: OnboardingPage(nextPage: RootPage()), goTo: OnboardingPage(nextPage: RootPage()),
), ),
_NavItem( _NavItem(
title: 'Console', title: 'more.console'.tr(),
iconData: BrandIcons.triangle, iconData: BrandIcons.triangle,
goTo: Console(), goTo: Console(),
), ),
@ -73,10 +74,10 @@ class MorePage extends StatelessWidget {
class _NavItem extends StatelessWidget { class _NavItem extends StatelessWidget {
const _NavItem({ const _NavItem({
Key key, Key? key,
@required this.iconData, required this.iconData,
@required this.goTo, required this.goTo,
@required this.title, required this.title,
}) : super(key: key); }) : super(key: key);
final IconData iconData; final IconData iconData;

View File

@ -3,9 +3,10 @@ import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
class OnboardingPage extends StatefulWidget { class OnboardingPage extends StatefulWidget {
const OnboardingPage({Key key, @required this.nextPage}) : super(key: key); const OnboardingPage({Key? key, required this.nextPage}) : super(key: key);
final Widget nextPage; final Widget nextPage;
@override @override
@ -54,10 +55,10 @@ class _OnboardingPageState extends State<OnboardingPage> {
children: [ children: [
SizedBox(height: 30), SizedBox(height: 30),
BrandText.h2( BrandText.h2(
'Цифровая независимость и приватность, доступная каждому'), 'onboarding.page1_title'.tr(),
),
SizedBox(height: 20), SizedBox(height: 20),
BrandText.body2( BrandText.body2('onboarding.page1_text'.tr()),
'Почта и мессенджер с открытым исходным кодом на вашем личном сервере под вашим полным контролем.'),
Flexible( Flexible(
child: Center( child: Center(
child: Image.asset( child: Image.asset(
@ -78,7 +79,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
curve: Curves.easeIn, curve: Curves.easeIn,
); );
}, },
title: 'Далее', title: 'basis.next'.tr(),
), ),
SizedBox(height: 30), SizedBox(height: 30),
], ],
@ -94,10 +95,9 @@ class _OnboardingPageState extends State<OnboardingPage> {
child: Column( child: Column(
children: [ children: [
SizedBox(height: 30), SizedBox(height: 30),
BrandText.h2('Для работы понадобятся ваши аккаунты'), BrandText.h2('onboarding.page2_title'.tr()),
SizedBox(height: 20), SizedBox(height: 20),
BrandText.body2( BrandText.body2('onboarding.page2_text'.tr()),
'Для максимальноей приватности и независимости SelfPrivacy не использует свои серверы. \n \n Если у вас нет домена, аккаунтов на Hetzner, AWS и Clouflare, мы поможем их создать и подключить.'),
SizedBox(height: 20), SizedBox(height: 20),
Center( Center(
child: Image.asset( child: Image.asset(
@ -127,7 +127,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
Navigator.of(context) Navigator.of(context)
.pushReplacement(materialRoute(widget.nextPage)); .pushReplacement(materialRoute(widget.nextPage));
}, },
title: 'Понял', title: 'basis.got_it'.tr(),
), ),
SizedBox(height: 30), SizedBox(height: 30),
], ],
@ -137,10 +137,10 @@ class _OnboardingPageState extends State<OnboardingPage> {
} }
String _fileName({ String _fileName({
@required BuildContext context, required BuildContext context,
@required String path, required String path,
@required String fileName, required String fileName,
@required String fileExtention, required String fileExtention,
}) { }) {
var theme = Theme.of(context); var theme = Theme.of(context);
var isDark = theme.brightness == Brightness.dark; var isDark = theme.brightness == Brightness.dark;

View File

@ -12,9 +12,10 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:selfprivacy/ui/pages/providers/settings/settings.dart'; import 'package:selfprivacy/ui/pages/providers/settings/settings.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
import 'package:easy_localization/easy_localization.dart';
class ProvidersPage extends StatefulWidget { class ProvidersPage extends StatefulWidget {
ProvidersPage({Key key}) : super(key: key); ProvidersPage({Key? key}) : super(key: key);
@override @override
_ProvidersPageState createState() => _ProvidersPageState(); _ProvidersPageState createState() => _ProvidersPageState();
@ -23,7 +24,8 @@ class ProvidersPage extends StatefulWidget {
class _ProvidersPageState extends State<ProvidersPage> { class _ProvidersPageState extends State<ProvidersPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; // var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
var isReady = true;
final cards = ProviderType.values final cards = ProviderType.values
.map((type) => _Card( .map((type) => _Card(
@ -32,7 +34,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
.toList(); .toList();
return Scaffold( return Scaffold(
appBar: PreferredSize( appBar: PreferredSize(
child: BrandHeader(title: 'Провайдеры'), child: BrandHeader(title: 'providers.page_title'.tr()),
preferredSize: Size.fromHeight(52), preferredSize: Size.fromHeight(52),
), ),
body: ListView( body: ListView(
@ -50,32 +52,31 @@ class _ProvidersPageState extends State<ProvidersPage> {
} }
class _Card extends StatelessWidget { class _Card extends StatelessWidget {
const _Card({Key key, @required this.provider}) : super(key: key); const _Card({Key? key, required this.provider}) : super(key: key);
final ProviderModel provider; final ProviderModel provider;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String title; String? title;
String message; String? message;
String stableText; String? stableText;
var appConfig = context.watch<AppConfigCubit>().state; AppConfigState appConfig = context.watch<AppConfigCubit>().state;
var domainName = var domainName =
appConfig.isDomainFilled ? appConfig.cloudFlareDomain.domainName : ''; appConfig.isDomainFilled ? appConfig.cloudFlareDomain!.domainName : '';
switch (provider.type) { switch (provider.type) {
case ProviderType.server: case ProviderType.server:
title = 'Сервер'; title = 'providers.server.card_title'.tr();
stableText = 'В норме'; stableText = 'В норме';
break; break;
case ProviderType.domain: case ProviderType.domain:
title = 'Домен'; title = 'providers.domain.card_title'.tr();
message = domainName; message = domainName;
stableText = 'Домен настроен'; stableText = 'Домен настроен';
break; break;
case ProviderType.backup: case ProviderType.backup:
// message = '22 янв 2021 14:30'; title = 'providers.backup.card_title'.tr();
title = 'Резервное копирование';
stableText = 'В норме'; stableText = 'В норме';
break; break;
} }
@ -116,28 +117,29 @@ class _Card extends StatelessWidget {
class _ProviderDetails extends StatelessWidget { class _ProviderDetails extends StatelessWidget {
const _ProviderDetails({ const _ProviderDetails({
Key key, Key? key,
@required this.provider, required this.provider,
@required this.statusText, required this.statusText,
}) : super(key: key); }) : super(key: key);
final ProviderModel provider; final ProviderModel provider;
final String statusText; final String? statusText;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String title; late String title;
switch (provider.type) { switch (provider.type) {
case ProviderType.server: case ProviderType.server:
title = 'Сервер'; title = 'providers.server.card_title'.tr();
break; break;
case ProviderType.domain: case ProviderType.domain:
title = 'Домен'; title = 'providers.domain.card_title'.tr();
break; break;
case ProviderType.backup: case ProviderType.backup:
title = 'Резервное копирование'; title = 'providers.backup.card_title'.tr();
break; break;
} }
return BrandModalSheet( return BrandModalSheet(
@ -163,7 +165,7 @@ class _ProviderDetails extends StatelessWidget {
onSelected: (_PopupMenuItemType result) { onSelected: (_PopupMenuItemType result) {
switch (result) { switch (result) {
case _PopupMenuItemType.setting: case _PopupMenuItemType.setting:
navigatorKey.currentState navigatorKey.currentState!
.push(materialRoute(SettingsPage())); .push(materialRoute(SettingsPage()));
break; break;
} }

View File

@ -7,7 +7,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart';
class SettingsPage extends StatelessWidget { class SettingsPage extends StatelessWidget {
const SettingsPage({Key key}) : super(key: key); const SettingsPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -62,9 +62,9 @@ class SettingsPage extends StatelessWidget {
class _Button extends StatelessWidget { class _Button extends StatelessWidget {
const _Button({ const _Button({
Key key, Key? key,
@required this.onTap, required this.onTap,
@required this.child, required this.child,
}) : super(key: key); }) : super(key: key);
final Widget child; final Widget child;
@ -88,9 +88,9 @@ class _Button extends StatelessWidget {
class _TextColumn extends StatelessWidget { class _TextColumn extends StatelessWidget {
const _TextColumn({ const _TextColumn({
Key key, Key? key,
@required this.title, required this.title,
@required this.value, required this.value,
this.hasWarning = false, this.hasWarning = false,
}) : super(key: key); }) : super(key: key);

View File

@ -7,7 +7,7 @@ import 'package:selfprivacy/ui/pages/services/services.dart';
import 'package:selfprivacy/ui/pages/users/users.dart'; import 'package:selfprivacy/ui/pages/users/users.dart';
class RootPage extends StatefulWidget { class RootPage extends StatefulWidget {
const RootPage({Key key}) : super(key: key); const RootPage({Key? key}) : super(key: key);
@override @override
_RootPageState createState() => _RootPageState(); _RootPageState createState() => _RootPageState();
@ -15,7 +15,7 @@ class RootPage extends StatefulWidget {
class _RootPageState extends State<RootPage> class _RootPageState extends State<RootPage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
TabController tabController; TabController? tabController;
@override @override
void initState() { void initState() {
@ -26,7 +26,7 @@ class _RootPageState extends State<RootPage>
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
tabController.dispose(); tabController!.dispose();
} }
@override @override

View File

@ -12,7 +12,7 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
class ServicesPage extends StatefulWidget { class ServicesPage extends StatefulWidget {
ServicesPage({Key key}) : super(key: key); ServicesPage({Key? key}) : super(key: key);
@override @override
_ServicesPageState createState() => _ServicesPageState(); _ServicesPageState createState() => _ServicesPageState();
@ -21,9 +21,10 @@ class ServicesPage extends StatefulWidget {
class _ServicesPageState extends State<ServicesPage> { class _ServicesPageState extends State<ServicesPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serviceCubit = context.watch<ServicesCubit>(); final serviceCubitState = context.watch<ServicesCubit>().state;
final connected = serviceCubit.state.connected;
final uninitialized = serviceCubit.state.uninitialized; final connected = serviceCubitState.connected;
final uninitialized = serviceCubitState.uninitialized;
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
return Scaffold( return Scaffold(
@ -49,14 +50,14 @@ class _ServicesPageState extends State<ServicesPage> {
} }
class _Card extends StatelessWidget { class _Card extends StatelessWidget {
const _Card({Key key, @required this.service}) : super(key: key); const _Card({Key? key, required this.service}) : super(key: key);
final Service service; final Service service;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String title; String? title;
IconData iconData; IconData? iconData;
String description; String? description;
switch (service.type) { switch (service.type) {
case ServiceTypes.messanger: case ServiceTypes.messanger:

View File

@ -1,9 +1,7 @@
part of 'users.dart'; part of 'users.dart';
class _NoUsers extends StatelessWidget { class _NoUsers extends StatelessWidget {
const _NoUsers({Key key, @required this.text}) const _NoUsers({Key? key, required this.text}) : super(key: key);
: assert(text != null),
super(key: key);
final String text; final String text;

View File

@ -1,7 +1,7 @@
part of 'users.dart'; part of 'users.dart';
class _Fab extends StatelessWidget { class _Fab extends StatelessWidget {
const _Fab({Key key}) : super(key: key); const _Fab({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -3,13 +3,12 @@ part of 'users.dart';
class _NewUser extends StatelessWidget { class _NewUser extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final usersCubit = context.watch<UsersCubit>();
return BrandModalSheet( return BrandModalSheet(
child: BlocProvider( child: BlocProvider(
create: (context) => UserFormCubit(usersCubit: usersCubit), create: (context) =>
UserFormCubit(usersCubit: context.watch<UsersCubit>()),
child: Builder(builder: (context) { child: Builder(builder: (context) {
var formCubit = context.watch<UserFormCubit>(); var formCubitState = context.watch<UserFormCubit>().state;
return BlocListener<UserFormCubit, FormCubitState>( return BlocListener<UserFormCubit, FormCubitState>(
listener: (context, state) { listener: (context, state) {
@ -27,7 +26,7 @@ class _NewUser extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.login, formFieldCubit: context.read<UserFormCubit>().login,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Логин', labelText: 'Логин',
suffixText: '@example', suffixText: '@example',
@ -35,7 +34,7 @@ class _NewUser extends StatelessWidget {
), ),
SizedBox(height: 20), SizedBox(height: 20),
CubitFormTextField( CubitFormTextField(
formFieldCubit: formCubit.password, formFieldCubit: context.read<UserFormCubit>().password,
decoration: InputDecoration( decoration: InputDecoration(
alignLabelWithHint: false, alignLabelWithHint: false,
labelText: 'Пароль', labelText: 'Пароль',
@ -46,18 +45,17 @@ class _NewUser extends StatelessWidget {
BrandIcons.refresh, BrandIcons.refresh,
color: BrandColors.blue, color: BrandColors.blue,
), ),
onPressed: formCubit.genNewPassword, onPressed:
context.read<UserFormCubit>().genNewPassword,
), ),
), ),
), ),
), ),
SizedBox(height: 30), SizedBox(height: 30),
BrandButton.rised( BrandButton.rised(
onPressed: formCubit.state.isSubmitting onPressed: formCubitState.isSubmitting
? null ? null
: () { : () => context.read<UserFormCubit>().trySubmit(),
formCubit.trySubmit();
},
title: 'Создать', title: 'Создать',
), ),
SizedBox(height: 40), SizedBox(height: 40),

View File

@ -1,9 +1,9 @@
part of 'users.dart'; part of 'users.dart';
class _User extends StatelessWidget { class _User extends StatelessWidget {
const _User({Key key, this.user}) : super(key: key); const _User({Key? key, this.user}) : super(key: key);
final User user; final User? user;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
@ -26,12 +26,12 @@ class _User extends StatelessWidget {
width: 17, width: 17,
height: 17, height: 17,
decoration: BoxDecoration( decoration: BoxDecoration(
color: user.color, color: user!.color,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
SizedBox(width: 20), SizedBox(width: 20),
BrandText.h4(user.login), BrandText.h4(user!.login),
], ],
), ),
), ),

View File

@ -2,11 +2,11 @@ part of 'users.dart';
class _UserDetails extends StatelessWidget { class _UserDetails extends StatelessWidget {
const _UserDetails({ const _UserDetails({
Key key, Key? key,
this.user, this.user,
}) : super(key: key); }) : super(key: key);
final User user; final User? user;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -17,7 +17,7 @@ class _UserDetails extends StatelessWidget {
Container( Container(
height: 200, height: 200,
decoration: BoxDecoration( decoration: BoxDecoration(
color: user.color, color: user!.color,
borderRadius: BorderRadius.vertical( borderRadius: BorderRadius.vertical(
top: Radius.circular(20), top: Radius.circular(20),
), ),
@ -109,7 +109,7 @@ class _UserDetails extends StatelessWidget {
horizontal: 15, horizontal: 15,
), ),
child: BrandText.h1( child: BrandText.h1(
user.login, user!.login,
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
)), )),
@ -126,14 +126,14 @@ class _UserDetails extends StatelessWidget {
Container( Container(
height: 40, height: 40,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: BrandText.h4('${user.login}@example.com'), child: BrandText.h4('${user!.login}@example.com'),
), ),
SizedBox(height: 14), SizedBox(height: 14),
BrandText.small('Пароль'), BrandText.small('Пароль'),
Container( Container(
height: 40, height: 40,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: BrandText.h4(user.password), child: BrandText.h4(user!.password),
), ),
SizedBox(height: 24), SizedBox(height: 24),
BrandDivider(), BrandDivider(),

View File

@ -21,14 +21,14 @@ part 'user.dart';
part 'empty.dart'; part 'empty.dart';
class UsersPage extends StatelessWidget { class UsersPage extends StatelessWidget {
const UsersPage({Key key}) : super(key: key); const UsersPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final usersCubit = context.watch<UsersCubit>(); final usersCubitState = context.watch<UsersCubit>().state;
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
final users = usersCubit.state.users; final users = usersCubitState.users;
final isEmpty = usersCubit.state.isEmpty; final isEmpty = usersCubitState.isEmpty;
Widget child; Widget child;

View File

@ -8,14 +8,14 @@ extension ElevationExtension on BoxDecoration {
BoxDecoration get ev8 => copyWith(boxShadow: [shadow8]); BoxDecoration get ev8 => copyWith(boxShadow: [shadow8]);
BoxDecoration copyWith({ BoxDecoration copyWith({
Color color, Color? color,
DecorationImage image, DecorationImage? image,
BoxBorder border, BoxBorder? border,
BorderRadiusGeometry borderRadius, BorderRadiusGeometry? borderRadius,
List<BoxShadow> boxShadow, List<BoxShadow>? boxShadow,
Gradient gradient, Gradient? gradient,
BlendMode backgroundBlendMode, BlendMode? backgroundBlendMode,
BoxShape shape, BoxShape? shape,
}) { }) {
return BoxDecoration( return BoxDecoration(
color: color ?? this.color, color: color ?? this.color,

View File

@ -12,10 +12,10 @@ String genPass() {
///The password [_generatedValue] is of a specified length, including letters [_letterGen] of mixed cases, ///The password [_generatedValue] is of a specified length, including letters [_letterGen] of mixed cases,
///numbers [_numGen], and symbols[_symGen] depending on user choice. ///numbers [_numGen], and symbols[_symGen] depending on user choice.
class PasswordGenerator { class PasswordGenerator {
bool _letterGen; late bool _letterGen;
bool _numGen; late bool _numGen;
bool _symGen; late bool _symGen;
String _generatedValue; late String _generatedValue;
///Constructor. ///Constructor.
/// ///
@ -43,7 +43,7 @@ class PasswordGenerator {
///'Randomly' selectes caracter type to generate and append [toAppend] to [_generatedValue] ///'Randomly' selectes caracter type to generate and append [toAppend] to [_generatedValue]
// ignore: unnecessary_statements // ignore: unnecessary_statements
for (n; n > 0; n--) { for (n; n > 0; n--) {
String toAppend; String? toAppend;
var random = new Random(); var random = new Random();
///loops until a valid character is generated, meaning the user has to check the character value ///loops until a valid character is generated, meaning the user has to check the character value
@ -67,7 +67,7 @@ class PasswordGenerator {
///Generates a letter when called. ///Generates a letter when called.
String _generateLetter() { String _generateLetter() {
if (!_letterGen) return null; if (!_letterGen) return '';
///Finds the integer value for the range between a-z and A-Z, with [base] UTF-16 value for lowercase letters and ///Finds the integer value for the range between a-z and A-Z, with [base] UTF-16 value for lowercase letters and
///[baseUpper] UTF-16 value for uppercase letters ///[baseUpper] UTF-16 value for uppercase letters
@ -87,7 +87,7 @@ class PasswordGenerator {
} }
///Generates a number when called ///Generates a number when called
String _generateNumber() { String? _generateNumber() {
if (!_numGen) return null; if (!_numGen) return null;
///Finds the integer value for the range between 0-9 ///Finds the integer value for the range between 0-9
@ -101,7 +101,7 @@ class PasswordGenerator {
} }
///Generates a symbol when called ///Generates a symbol when called
String _generateSymbol() { String? _generateSymbol() {
if (!_symGen) return null; if (!_symGen) return null;
///Finds the integer value for the range between symbols !-. ///Finds the integer value for the range between symbols !-.

View File

@ -37,7 +37,7 @@ class SlideBottomRoute extends PageRouteBuilder {
SlideBottomRoute(this.widget) SlideBottomRoute(this.widget)
: super( : super(
pageBuilder: pageBuilder(widget), pageBuilder: pageBuilder(widget),
transitionsBuilder: transitionsBuilder, transitionsBuilder: transitionsBuilder as Widget Function(BuildContext, Animation<double>, Animation<double>, Widget),
); );
final Widget widget; final Widget widget;

View File

@ -37,7 +37,7 @@ class SlideRightRoute extends PageRouteBuilder {
SlideRightRoute(this.widget) SlideRightRoute(this.widget)
: super( : super(
pageBuilder: pageBuilder(widget), pageBuilder: pageBuilder(widget),
transitionsBuilder: transitionsBuilder, transitionsBuilder: transitionsBuilder as Widget Function(BuildContext, Animation<double>, Animation<double>, Widget),
); );
final Widget widget; final Widget widget;

View File

@ -4,7 +4,8 @@ publish_to: 'none'
version: 0.1.0+1 version: 0.1.0+1
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: '>=2.12.0 <3.0.0'
flutter: ">=2.0.0"
dependencies: dependencies:
flutter: flutter: