mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-27 11:16:45 +00:00
update
This commit is contained in:
parent
3de01fe12b
commit
25a386d511
BIN
assets/images/logos/backblaze.png
Normal file
BIN
assets/images/logos/backblaze.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
|
@ -50,6 +50,6 @@ class BNames {
|
|||
static String hetznerServer = 'hetznerServer';
|
||||
static String isDkimSetted = 'isDkimSetted';
|
||||
static String isDnsChecked = 'isDnsChecked';
|
||||
|
||||
static String isServerStarted = 'isServerStarted';
|
||||
static String backblazeKey = 'backblazeKey';
|
||||
}
|
||||
|
|
38
lib/logic/api_maps/backblaze.dart
Normal file
38
lib/logic/api_maps/backblaze.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||
|
||||
class BackblazeApi extends ApiMap {
|
||||
BackblazeApi([String token]) {
|
||||
if (token != null) {
|
||||
loggedClient.options = BaseOptions(
|
||||
headers: {'Authorization': 'Basic $token'},
|
||||
baseUrl: rootAddress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String rootAddress =
|
||||
'https://api.backblazeb2.com/b2api/v2/b2_authorize_account';
|
||||
|
||||
Future<bool> isValid(String token) async {
|
||||
var options = Options(
|
||||
headers: {'Authorization': 'Basic $token'},
|
||||
validateStatus: (status) {
|
||||
return status == HttpStatus.ok || status == HttpStatus.unauthorized;
|
||||
},
|
||||
);
|
||||
|
||||
Response response = await loggedClient.get(rootAddress, options: options);
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
print(response);
|
||||
return true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
return false;
|
||||
} else {
|
||||
throw Exception('code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,4 +69,14 @@ class HetznerApi extends ApiMap {
|
|||
startTime: DateTime.now(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> reset({
|
||||
HetznerServerDetails server,
|
||||
}) async {
|
||||
await loggedClient.post('/${server.id}/actions/poweron');
|
||||
|
||||
return server.copyWith(
|
||||
startTime: DateTime.now(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import 'app_config_repository.dart';
|
|||
|
||||
part 'app_config_state.dart';
|
||||
|
||||
/// initializeing steps:
|
||||
/// initializeing steps:
|
||||
/// 1. Hetzner key |setHetznerKey
|
||||
/// 2. Cloudflare key |setCloudflareKey
|
||||
/// 3. Set Domain address |setDomain
|
||||
|
@ -34,8 +34,8 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
emit(state);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
repository.reset();
|
||||
void clearAppConfig() {
|
||||
repository.clearAppConfig();
|
||||
emit(InitialAppConfigState());
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,16 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
state.cloudFlareKey,
|
||||
state.cloudFlareDomain.zoneId,
|
||||
);
|
||||
emit(state.copyWith(isDkimSetted: true));
|
||||
var hetznerServerDetails = await repository.reset(
|
||||
state.hetznerKey,
|
||||
state.hetznerServer,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
isDkimSetted: true,
|
||||
hetznerServer: hetznerServerDetails,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
_tryOrAddError(state, callBack);
|
||||
|
@ -143,4 +152,9 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
emit(state);
|
||||
}
|
||||
}
|
||||
|
||||
void setBackblazeKey(String backblazeKey) {
|
||||
repository.saveBackblazeKey(backblazeKey);
|
||||
emit(state.copyWith(backblazeKey: backblazeKey));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ class AppConfigRepository {
|
|||
hetznerKey: box.get(BNames.hetznerKey),
|
||||
cloudFlareKey: box.get(BNames.cloudFlareKey),
|
||||
cloudFlareDomain: box.get(BNames.cloudFlareDomain),
|
||||
backblazeKey: box.get(BNames.backblazeKey),
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
hetznerServer: box.get(BNames.hetznerServer),
|
||||
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
|
||||
|
@ -28,7 +29,7 @@ class AppConfigRepository {
|
|||
);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
void clearAppConfig() {
|
||||
box.clear();
|
||||
}
|
||||
|
||||
|
@ -36,6 +37,10 @@ class AppConfigRepository {
|
|||
box.put(BNames.hetznerKey, key);
|
||||
}
|
||||
|
||||
void saveBackblazeKey(String key) {
|
||||
box.put(BNames.backblazeKey, key);
|
||||
}
|
||||
|
||||
void saveCloudFlare(String key) {
|
||||
box.put(BNames.cloudFlareKey, key);
|
||||
}
|
||||
|
@ -104,12 +109,8 @@ class AppConfigRepository {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> createServer(
|
||||
String hetznerKey,
|
||||
User rootUser,
|
||||
String domainName,
|
||||
String cloudFlareKey
|
||||
) async {
|
||||
Future<HetznerServerDetails> createServer(String hetznerKey, User rootUser,
|
||||
String domainName, String cloudFlareKey) async {
|
||||
var hetznerApi = HetznerApi(hetznerKey);
|
||||
var serverDetails = await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
|
@ -164,4 +165,12 @@ class AppConfigRepository {
|
|||
|
||||
cloudflareApi.close();
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> reset(
|
||||
String hetznerKey,
|
||||
HetznerServerDetails server,
|
||||
) async {
|
||||
var hetznerApi = HetznerApi(hetznerKey);
|
||||
return await hetznerApi.reset(server: server);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ class AppConfigState extends Equatable {
|
|||
const AppConfigState({
|
||||
this.hetznerKey,
|
||||
this.cloudFlareKey,
|
||||
this.backblazeKey,
|
||||
this.cloudFlareDomain,
|
||||
this.rootUser,
|
||||
this.hetznerServer,
|
||||
|
@ -20,6 +21,7 @@ class AppConfigState extends Equatable {
|
|||
List<Object> get props => [
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeKey,
|
||||
cloudFlareDomain,
|
||||
rootUser,
|
||||
hetznerServer,
|
||||
|
@ -33,6 +35,7 @@ class AppConfigState extends Equatable {
|
|||
|
||||
final String hetznerKey;
|
||||
final String cloudFlareKey;
|
||||
final String backblazeKey;
|
||||
final CloudFlareDomain cloudFlareDomain;
|
||||
final User rootUser;
|
||||
final HetznerServerDetails hetznerServer;
|
||||
|
@ -47,6 +50,7 @@ class AppConfigState extends Equatable {
|
|||
AppConfigState copyWith({
|
||||
String hetznerKey,
|
||||
String cloudFlareKey,
|
||||
String backblazeKey,
|
||||
CloudFlareDomain cloudFlareDomain,
|
||||
User rootUser,
|
||||
HetznerServerDetails hetznerServer,
|
||||
|
@ -61,6 +65,7 @@ class AppConfigState extends Equatable {
|
|||
AppConfigState(
|
||||
hetznerKey: hetznerKey ?? this.hetznerKey,
|
||||
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
|
||||
backblazeKey: backblazeKey ?? this.backblazeKey,
|
||||
cloudFlareDomain: cloudFlareDomain ?? this.cloudFlareDomain,
|
||||
rootUser: rootUser ?? this.rootUser,
|
||||
hetznerServer: hetznerServer ?? this.hetznerServer,
|
||||
|
@ -76,6 +81,7 @@ class AppConfigState extends Equatable {
|
|||
|
||||
bool get isHetznerFilled => hetznerKey != null;
|
||||
bool get isCloudFlareFilled => cloudFlareKey != null;
|
||||
bool get isBackblazeFilled => backblazeKey != null;
|
||||
bool get isDomainFilled => cloudFlareDomain != null;
|
||||
bool get isUserFilled => rootUser != null;
|
||||
bool get isServerFilled => hetznerServer != null;
|
||||
|
@ -90,6 +96,7 @@ class AppConfigState extends Equatable {
|
|||
List<bool> get _fulfilementList => [
|
||||
isHetznerFilled,
|
||||
isCloudFlareFilled,
|
||||
isBackblazeFilled,
|
||||
isDomainFilled,
|
||||
isUserFilled,
|
||||
isServerFilled,
|
||||
|
|
81
lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart
Normal file
81
lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||
|
||||
class BackblazeFormCubit extends FormCubit {
|
||||
BackblazeApi apiClient = BackblazeApi();
|
||||
|
||||
BackblazeFormCubit(this.initializingCubit) {
|
||||
//var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]");
|
||||
keyId = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('required'),
|
||||
//ValidationModel<String>(
|
||||
//(s) => regExp.hasMatch(s), 'invalid key format'),
|
||||
//LegnthStringValidationWithLenghShowing(64, 'length is [] shoud be 64')
|
||||
],
|
||||
);
|
||||
|
||||
applicationKey = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
RequiredStringValidation('required'),
|
||||
//ValidationModel<String>(
|
||||
//(s) => regExp.hasMatch(s), 'invalid key format'),
|
||||
//LegnthStringValidationWithLenghShowing(64, 'length is [] shoud be 64')
|
||||
],
|
||||
);
|
||||
|
||||
super.setFields([keyId, applicationKey]);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> onSubmit() async {
|
||||
String encodedApiKey =
|
||||
encodeToBase64(keyId.state.value, applicationKey.state.value);
|
||||
|
||||
initializingCubit.setBackblazeKey(encodedApiKey);
|
||||
}
|
||||
|
||||
final AppConfigCubit initializingCubit;
|
||||
|
||||
FieldCubit<String> keyId;
|
||||
|
||||
FieldCubit<String> applicationKey;
|
||||
|
||||
@override
|
||||
FutureOr<bool> asyncValidation() async {
|
||||
bool isKeyValid;
|
||||
try {
|
||||
String encodedApiKey =
|
||||
encodeToBase64(keyId.state.value, applicationKey.state.value);
|
||||
isKeyValid = await apiClient.isValid(encodedApiKey);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
keyId.setError('bad key');
|
||||
applicationKey.setError('bad key');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
apiClient.close();
|
||||
|
||||
return super.close();
|
||||
}
|
||||
|
||||
String encodeToBase64(String keyId, String applicationKey) {
|
||||
String _apiKey = '$keyId:$applicationKey';
|
||||
String encodedApiKey = base64.encode(utf8.encode(_apiKey));
|
||||
return encodedApiKey;
|
||||
}
|
||||
}
|
|
@ -44,10 +44,23 @@ class _ProgressBarState extends State<ProgressBar> {
|
|||
} else {
|
||||
odd.add(step);
|
||||
}
|
||||
i++;
|
||||
i++;
|
||||
}
|
||||
even.add(Spacer());
|
||||
odd.insert(0, Spacer());
|
||||
// even.add(SizedBox(
|
||||
// width: 0,
|
||||
// ));
|
||||
odd
|
||||
..insert(
|
||||
0,
|
||||
SizedBox(
|
||||
width: 50,
|
||||
),
|
||||
)
|
||||
..add(
|
||||
SizedBox(
|
||||
width: 50,
|
||||
),
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/config/text_themes.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/cloudflare_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/domain_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/initializing/hetzner_form_cubit.dart';
|
||||
|
@ -27,12 +28,13 @@ class InitializingPage extends StatelessWidget {
|
|||
var actualPage = [
|
||||
_stepHetzner(cubit),
|
||||
_stepCloudflare(cubit),
|
||||
_stepBackblaze(cubit),
|
||||
_stepDomain(cubit),
|
||||
_stepUser(cubit),
|
||||
_stepServer(cubit),
|
||||
_stepCheck(cubit),
|
||||
Container(child: Text('Everythigng is initialized'))
|
||||
][cubit.state.progress];
|
||||
][2];
|
||||
return BlocListener<AppConfigCubit, AppConfigState>(
|
||||
listener: (context, state) {
|
||||
if (state.isFullyInitilized) {
|
||||
|
@ -46,12 +48,13 @@ class InitializingPage extends StatelessWidget {
|
|||
Padding(
|
||||
padding: brandPagePadding1,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ProgressBar(
|
||||
steps: [
|
||||
'Hetzner',
|
||||
'CloudFlare',
|
||||
'Backblaze',
|
||||
'Domain',
|
||||
'User',
|
||||
'Server',
|
||||
|
@ -177,6 +180,55 @@ class InitializingPage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _stepBackblaze(AppConfigCubit initializingCubit) {
|
||||
return BlocProvider(
|
||||
create: (context) => BackblazeFormCubit(initializingCubit),
|
||||
child: Builder(builder: (context) {
|
||||
var formCubit = context.watch<BackblazeFormCubit>();
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Spacer(),
|
||||
Image.asset('assets/images/logos/backblaze.png'),
|
||||
SizedBox(height: 10),
|
||||
BrandText.h2('Подключите облачное хранилище Backblaze'),
|
||||
SizedBox(height: 10),
|
||||
BrandText.body2('Здесь будут храниться данные'),
|
||||
Spacer(),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: formCubit.keyId,
|
||||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'KeyID',
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: formCubit.applicationKey,
|
||||
textAlign: TextAlign.center,
|
||||
scrollPadding: EdgeInsets.only(bottom: 70),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Master Application Key',
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
BrandButton.rised(
|
||||
onPressed:
|
||||
formCubit.state.isSubmitting ? null : formCubit.trySubmit,
|
||||
title: 'Подключить',
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
BrandButton.text(
|
||||
onPressed: () => _showModal(context, _HowHetzner()),
|
||||
title: 'Как получить API Token',
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _stepDomain(AppConfigCubit initializingCubit) {
|
||||
return BlocProvider(
|
||||
create: (context) => DomainFormCubit(initializingCubit),
|
||||
|
@ -296,8 +348,8 @@ class InitializingPage extends StatelessWidget {
|
|||
SizedBox(height: 10),
|
||||
BrandText.body2(
|
||||
isDnsChecked
|
||||
? 'Dns сервера вступили в силу, мы стартанули сервер, как только он поднимиться, мы закончим инициализацию.'
|
||||
: 'Мы начали процесс инциализации сервера, раз в минуты мы будем проверять наличие DNS записей, как только они вступят в силу мы продолжим инциализацию',
|
||||
? 'Dns сервера вступили в силу, мы стартанули сервер, как только он поднимется, мы закончим инициализацию.'
|
||||
: 'Мы начали процесс инциализации сервера, раз в минуту мы будем проверять наличие DNS записей, как только они вступят в силу мы продолжим инциализацию',
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
|
|
|
@ -108,7 +108,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
|||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.read<AppConfigCubit>().reset();
|
||||
context.read<AppConfigCubit>().clearAppConfig();
|
||||
Navigator.of(context)..pop()..pop();
|
||||
},
|
||||
),
|
||||
|
|
|
@ -1,231 +0,0 @@
|
|||
// import 'package:flutter/material.dart';
|
||||
// import 'package:selfprivacy/config/brand_theme.dart';
|
||||
// import 'package:selfprivacy/config/text_themes.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_card/brand_card.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
|
||||
// class OnboardingPage extends StatelessWidget {
|
||||
// const OnboardingPage({Key key}) : super(key: key);
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// body: ListView(
|
||||
// padding: brandPagePadding1,
|
||||
// children: [
|
||||
// BrandText.h4('Начало'),
|
||||
// BrandText.h1('SelfPrivacy'),
|
||||
// SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text:
|
||||
// 'Для устойчивости и приватности требует много учёток. Полная инструкция на ',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'selfprivacy.org/start',
|
||||
// urlString: 'https://selfprivacy.org/start',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(height: 50),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/hetzner.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('1. Подключите сервер Hetzner'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2(
|
||||
// 'Здесь будут жить наши данные и SelfPrivacy-сервисы'),
|
||||
// _MockForm(
|
||||
// hintText: 'Hetzner API Token',
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.text(
|
||||
// onPressed: () => _showModal(context, _HowHetzner()),
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/namecheap.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('2. Настройте домен'),
|
||||
// SizedBox(height: 10),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text: 'Зарегистрируйте домен в ',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'NameCheap',
|
||||
// urlString: 'https://www.namecheap.com',
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text:
|
||||
// ' или у любого другого регистратора. После этого настройте его на DNS-сервер CloudFlare',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// _MockForm(
|
||||
// hintText: 'Домен, например, selfprivacy.org',
|
||||
// submitButtonText: 'Проверить DNS',
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как настроить DNS CloudFlare',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/cloudflare.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('3. Подключите CloudFlare DNS'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2('Для управления DNS вашего домена'),
|
||||
// _MockForm(
|
||||
// hintText: 'CloudFlare API Token',
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/aws.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('4. Подключите Amazon AWS для бекапа'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2(
|
||||
// 'IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде'),
|
||||
// _MockForm(
|
||||
// hintText: 'Amazon AWS Access Key',
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
// void _showModal(BuildContext context, Widget widget) {
|
||||
// showModalBottomSheet<void>(
|
||||
// context: context,
|
||||
// isScrollControlled: true,
|
||||
// backgroundColor: Colors.transparent,
|
||||
// builder: (BuildContext context) {
|
||||
// return widget;
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// class _HowHetzner extends StatelessWidget {
|
||||
// const _HowHetzner({
|
||||
// Key key,
|
||||
// }) : super(key: key);
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return BrandModalSheet(
|
||||
// child: Padding(
|
||||
// padding: brandPagePadding2,
|
||||
// child: Column(
|
||||
// children: [
|
||||
// SizedBox(height: 40),
|
||||
// BrandText.h2('Как получить Hetzner API Token'),
|
||||
// SizedBox(height: 20),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text: '1 Переходим по ссылке ',
|
||||
// style: body1Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'hetzner.com/sdfsdfsdfsdf',
|
||||
// urlString: 'https://hetzner.com/sdfsdfsdfsdf',
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text: '''
|
||||
|
||||
// 2 Заходим в созданный нами проект. Если такового - нет, значит создаём.
|
||||
|
||||
// 3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика).
|
||||
|
||||
// 4 Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему.
|
||||
|
||||
// 5 В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же вы используете мобильную версию сайта, в нижнем правом углу вы увидите красный плюсик. Нажимаем на эту кнопку.
|
||||
|
||||
// 6 В поле Description, даём нашему токену название (это может быть любое название, которые вам нравиться. Сути оно не меняет.
|
||||
|
||||
// ''',
|
||||
// style: body1Style,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// class _MockForm extends StatelessWidget {
|
||||
// const _MockForm({
|
||||
// Key key,
|
||||
// @required this.hintText,
|
||||
// this.submitButtonText = 'Подключить',
|
||||
// }) : super(key: key);
|
||||
|
||||
// final String hintText;
|
||||
// final String submitButtonText;
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// SizedBox(height: 20),
|
||||
// TextField(decoration: InputDecoration(hintText: hintText)),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.rised(onPressed: () {}, title: submitButtonText),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
// }
|
|
@ -1,341 +0,0 @@
|
|||
// import 'package:flutter/material.dart';
|
||||
// import 'package:selfprivacy/config/brand_theme.dart';
|
||||
// import 'package:selfprivacy/config/text_themes.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_card/brand_card.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_modal_sheet/brand_modal_sheet.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_span_button/brand_span_button.dart';
|
||||
// import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
// import 'package:selfprivacy/ui/components/dots_indicator/dots_indicator.dart';
|
||||
// import 'package:selfprivacy/ui/pages/rootRoute.dart';
|
||||
// import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
// class InitializingPage extends StatefulWidget {
|
||||
// const InitializingPage({Key key}) : super(key: key);
|
||||
|
||||
// @override
|
||||
// _InitializingPageState createState() => _InitializingPageState();
|
||||
// }
|
||||
|
||||
// class _InitializingPageState extends State<InitializingPage> {
|
||||
// PageController controller;
|
||||
// var currentPage = 0;
|
||||
|
||||
// @override
|
||||
// void initState() {
|
||||
// controller = PageController(
|
||||
// initialPage: 0,
|
||||
// )..addListener(() {
|
||||
// if (currentPage != controller.page.toInt()) {
|
||||
// setState(() {
|
||||
// currentPage = controller.page.toInt();
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// super.initState();
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {});
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void dispose() {
|
||||
// controller.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// var steps = getSteps();
|
||||
|
||||
// return SafeArea(
|
||||
// child: Scaffold(
|
||||
// body: ListView(
|
||||
// shrinkWrap: true,
|
||||
// children: [
|
||||
// Padding(
|
||||
// padding: brandPagePadding1,
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// BrandText.h4('Начало'),
|
||||
// BrandText.h1('SelfPrivacy'),
|
||||
// SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text:
|
||||
// 'Для устойчивости и приватности требует много учёток. Полная инструкция на ',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'selfprivacy.org/start',
|
||||
// urlString: 'https://selfprivacy.org/start',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// Container(
|
||||
// height: 480,
|
||||
// child: PageView.builder(
|
||||
// physics: NeverScrollableScrollPhysics(),
|
||||
// allowImplicitScrolling: false,
|
||||
// controller: controller,
|
||||
// itemBuilder: (_, index) {
|
||||
// return Padding(
|
||||
// padding: brandPagePadding2,
|
||||
// child: steps[index],
|
||||
// );
|
||||
// },
|
||||
// itemCount: 4,
|
||||
// ),
|
||||
// ),
|
||||
// DotsIndicator(
|
||||
// activeIndex: currentPage,
|
||||
// count: steps.length,
|
||||
// ),
|
||||
// SizedBox(height: 50),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
// List<Widget> getSteps() => <Widget>[
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/hetzner.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('1. Подключите сервер Hetzner'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2(
|
||||
// 'Здесь будут жить наши данные и SelfPrivacy-сервисы'),
|
||||
// _MockForm(
|
||||
// onPressed: _nextPage,
|
||||
// hintText: 'Hetzner API Token',
|
||||
// length: 2,
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// Spacer(),
|
||||
// BrandButton.text(
|
||||
// onPressed: () => _showModal(context, _HowHetzner()),
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/namecheap.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('2. Настройте домен'),
|
||||
// SizedBox(height: 10),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text: 'Зарегистрируйте домен в ',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'NameCheap',
|
||||
// urlString: 'https://www.namecheap.com',
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text:
|
||||
// ' или у любого другого регистратора. После этого настройте его на DNS-сервер CloudFlare',
|
||||
// style: body2Style,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// _MockForm(
|
||||
// onPressed: _nextPage,
|
||||
// hintText: 'Домен, например, selfprivacy.org',
|
||||
// submitButtonText: 'Проверить DNS',
|
||||
// length: 2,
|
||||
// ),
|
||||
// Spacer(),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как настроить DNS CloudFlare',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/cloudflare.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('3. Подключите CloudFlare DNS'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2('Для управления DNS вашего домена'),
|
||||
// _MockForm(
|
||||
// onPressed: _nextPage,
|
||||
// hintText: 'CloudFlare API Token',
|
||||
// length: 2,
|
||||
// ),
|
||||
// Spacer(),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// BrandCard(
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Image.asset('assets/images/logos/aws.png'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.h2('4. Подключите Amazon AWS для бекапа'),
|
||||
// SizedBox(height: 10),
|
||||
// BrandText.body2(
|
||||
// 'IaaS-провайдер, для бесплатного хранения резервных копии ваших данных в зашифрованном виде'),
|
||||
// _MockForm(
|
||||
// onPressed: () {
|
||||
// Navigator.of(context)
|
||||
// .pushReplacement(materialRoute(RootPage()));
|
||||
// },
|
||||
// hintText: 'Amazon AWS Access Key',
|
||||
// length: 2,
|
||||
// ),
|
||||
// Spacer(),
|
||||
// BrandButton.text(
|
||||
// onPressed: () {},
|
||||
// title: 'Как получить API Token',
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ];
|
||||
|
||||
// void _showModal(BuildContext context, Widget widget) {
|
||||
// showModalBottomSheet<void>(
|
||||
// context: context,
|
||||
// isScrollControlled: true,
|
||||
// backgroundColor: Colors.transparent,
|
||||
// builder: (BuildContext context) {
|
||||
// return widget;
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
|
||||
// void _nextPage() => controller.nextPage(
|
||||
// duration: Duration(milliseconds: 300),
|
||||
// curve: Curves.easeIn,
|
||||
// );
|
||||
// }
|
||||
|
||||
// class _HowHetzner extends StatelessWidget {
|
||||
// const _HowHetzner({
|
||||
// Key key,
|
||||
// }) : super(key: key);
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return BrandModalSheet(
|
||||
// child: Padding(
|
||||
// padding: brandPagePadding2,
|
||||
// child: Column(
|
||||
// children: [
|
||||
// SizedBox(height: 40),
|
||||
// BrandText.h2('Как получить Hetzner API Token'),
|
||||
// SizedBox(height: 20),
|
||||
// RichText(
|
||||
// text: TextSpan(
|
||||
// children: [
|
||||
// TextSpan(
|
||||
// text: '1 Переходим по ссылке ',
|
||||
// style: body1Style,
|
||||
// ),
|
||||
// BrandSpanButton.link(
|
||||
// text: 'hetzner.com/sdfsdfsdfsdf',
|
||||
// urlString: 'https://hetzner.com/sdfsdfsdfsdf',
|
||||
// ),
|
||||
// TextSpan(
|
||||
// text: '''
|
||||
|
||||
// 2 Заходим в созданный нами проект. Если такового - нет, значит создаём.
|
||||
|
||||
// 3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика).
|
||||
|
||||
// 4 Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему.
|
||||
|
||||
// 5 В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же вы используете мобильную версию сайта, в нижнем правом углу вы увидите красный плюсик. Нажимаем на эту кнопку.
|
||||
|
||||
// 6 В поле Description, даём нашему токену название (это может быть любое название, которые вам нравиться. Сути оно не меняет.
|
||||
|
||||
// ''',
|
||||
// style: body1Style,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// class _MockForm extends StatefulWidget {
|
||||
// const _MockForm({
|
||||
// Key key,
|
||||
// @required this.hintText,
|
||||
// this.submitButtonText = 'Подключить',
|
||||
// @required this.onPressed,
|
||||
// @required this.length,
|
||||
// }) : super(key: key);
|
||||
|
||||
// final String hintText;
|
||||
// final String submitButtonText;
|
||||
// final int length;
|
||||
|
||||
// final VoidCallback onPressed;
|
||||
|
||||
// @override
|
||||
// __MockFormState createState() => __MockFormState();
|
||||
// }
|
||||
|
||||
// class __MockFormState extends State<_MockForm> {
|
||||
// String text = '';
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// SizedBox(height: 20),
|
||||
// TextField(
|
||||
// onChanged: (value) => {
|
||||
// setState(() {
|
||||
// text = value;
|
||||
// })
|
||||
// },
|
||||
// decoration: InputDecoration(hintText: widget.hintText),
|
||||
// ),
|
||||
// SizedBox(height: 20),
|
||||
// BrandButton.rised(
|
||||
// onPressed:
|
||||
// text.length == widget.length ? widget.onPressed ?? () {} : null,
|
||||
// title: widget.submitButtonText,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
// }
|
Loading…
Reference in a new issue