mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-08 17:11:14 +00:00
Merge pull request 'services-switchers' (#32) from services-switchers into master
Reviewed-on: https://git.selfprivacy.org/kherel/selfprivacy.org.app/pulls/32
This commit is contained in:
commit
e064598c73
16
.editorconfig
Normal file
16
.editorconfig
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.dart]
|
||||||
|
max_line_length = 150
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -26,7 +26,8 @@
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"no_data": "No data",
|
"no_data": "No data",
|
||||||
"wait": "Wait",
|
"wait": "Wait",
|
||||||
"remove": "Remove"
|
"remove": "Remove",
|
||||||
|
"apply": "Apply"
|
||||||
},
|
},
|
||||||
"more": {
|
"more": {
|
||||||
"_comment": "'More' tab",
|
"_comment": "'More' tab",
|
||||||
|
@ -34,6 +35,9 @@
|
||||||
"about_project": "About us",
|
"about_project": "About us",
|
||||||
"about_app": "About application",
|
"about_app": "About application",
|
||||||
"onboarding": "Onboarding",
|
"onboarding": "Onboarding",
|
||||||
|
"create_ssh_key": "Create ssh key",
|
||||||
|
"generate_key": "Generate key",
|
||||||
|
"generate_key_text": "You can generate ssh key",
|
||||||
"console": "Console",
|
"console": "Console",
|
||||||
"about_app_page": {
|
"about_app_page": {
|
||||||
"text": "Application version v.{}"
|
"text": "Application version v.{}"
|
||||||
|
@ -147,6 +151,13 @@
|
||||||
"bottom_sheet": {
|
"bottom_sheet": {
|
||||||
"1": "You can connect and create a new user here:"
|
"1": "You can connect and create a new user here:"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"vpn": {
|
||||||
|
"title": "VPN Server",
|
||||||
|
"subtitle": "Private VPN server",
|
||||||
|
"bottom_sheet": {
|
||||||
|
"1": "Openconnect VPN Server. Engine for secure and scalable VPN infrastructure"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
|
@ -212,7 +223,12 @@
|
||||||
"_comment": "Jobs list",
|
"_comment": "Jobs list",
|
||||||
"title": "Jobs list",
|
"title": "Jobs list",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
"empty": "No jobs"
|
"empty": "No jobs",
|
||||||
|
"createUser": "Create",
|
||||||
|
"serviceTurnOff": "Turn off",
|
||||||
|
"serviceTurnOn": "Turn on",
|
||||||
|
"jobAdded": "Job added",
|
||||||
|
"runJobs": "Run jobs"
|
||||||
},
|
},
|
||||||
"validations": {
|
"validations": {
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
"details": "Детальная информация",
|
"details": "Детальная информация",
|
||||||
"no_data": "Нет данных",
|
"no_data": "Нет данных",
|
||||||
"wait": "Ожидайте",
|
"wait": "Ожидайте",
|
||||||
"remove": "Удалить"
|
"remove": "Удалить",
|
||||||
|
"apply": "Подать"
|
||||||
},
|
},
|
||||||
"more": {
|
"more": {
|
||||||
"_comment": "вкладка еще",
|
"_comment": "вкладка еще",
|
||||||
|
@ -35,6 +36,9 @@
|
||||||
"about_app": "О приложении",
|
"about_app": "О приложении",
|
||||||
"onboarding": "Приветствие",
|
"onboarding": "Приветствие",
|
||||||
"console": "Консоль",
|
"console": "Консоль",
|
||||||
|
"create_ssh_key": "Создать ssh ключ",
|
||||||
|
"generate_key": "Сгенерировать ключ",
|
||||||
|
"generate_key_text": "Вы сможете сгенерировать ключ",
|
||||||
"about_app_page": {
|
"about_app_page": {
|
||||||
"text": "Версия приложения: v.{}"
|
"text": "Версия приложения: v.{}"
|
||||||
},
|
},
|
||||||
|
@ -212,7 +216,12 @@
|
||||||
"_comment": "Jobs list",
|
"_comment": "Jobs list",
|
||||||
"title": "Задачи",
|
"title": "Задачи",
|
||||||
"start": "Начать выполенение",
|
"start": "Начать выполенение",
|
||||||
"empty": "Пусто"
|
"empty": "Пусто",
|
||||||
|
"createUser": "Создать запись",
|
||||||
|
"serviceTurnOff": "Остановить",
|
||||||
|
"serviceTurnOn": "Запустить",
|
||||||
|
"jobAdded": "Задача добавленна",
|
||||||
|
"runJobs": "Запустите задачи"
|
||||||
},
|
},
|
||||||
"validations": {
|
"validations": {
|
||||||
"required": "обязательное поле",
|
"required": "обязательное поле",
|
||||||
|
|
|
@ -21,6 +21,6 @@
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>8.0</string>
|
<string>9.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -44,7 +44,7 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/wakelock/ios"
|
:path: ".symlinks/plugins/wakelock/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||||
|
|
BIN
ios/build/Pods.build/Release-iphonesimulator/Flutter.build/dgph
Normal file
BIN
ios/build/Pods.build/Release-iphonesimulator/Flutter.build/dgph
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ios/build/Pods.build/Release-iphonesimulator/wakelock.build/dgph
Normal file
BIN
ios/build/Pods.build/Release-iphonesimulator/wakelock.build/dgph
Normal file
Binary file not shown.
|
@ -4,6 +4,7 @@ import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||||
|
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 {
|
||||||
|
@ -13,11 +14,9 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// var platformBrightness =
|
|
||||||
// SchedulerBinding.instance.window.platformBrightness;
|
|
||||||
// var isDark = platformBrightness == Brightness.dark;
|
|
||||||
var isDark = false;
|
var isDark = false;
|
||||||
var usersCubit = UsersCubit();
|
var usersCubit = UsersCubit();
|
||||||
|
var servicesCubit = ServicesCubit();
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
|
@ -28,11 +27,17 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
lazy: false,
|
lazy: false,
|
||||||
create: (_) => AppConfigCubit()..load(),
|
create: (_) => AppConfigCubit(servicesCubit)..load(),
|
||||||
),
|
),
|
||||||
BlocProvider(create: (_) => ProvidersCubit()),
|
BlocProvider(create: (_) => ProvidersCubit()),
|
||||||
BlocProvider(create: (_) => usersCubit..load(), lazy: false),
|
BlocProvider(create: (_) => usersCubit..load(), lazy: false),
|
||||||
BlocProvider(create: (_) => JobsCubit(usersCubit)),
|
BlocProvider(create: (_) => servicesCubit..load(), lazy: false),
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => JobsCubit(
|
||||||
|
usersCubit: usersCubit,
|
||||||
|
servicesCubit: servicesCubit,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:get_it/get_it.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/api_config.dart';
|
import 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
import 'package:selfprivacy/logic/get_it/console.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||||
|
import 'package:selfprivacy/logic/get_it/ssh_helper.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/timer.dart';
|
import 'package:selfprivacy/logic/get_it/timer.dart';
|
||||||
|
|
||||||
export 'package:selfprivacy/logic/get_it/api_config.dart';
|
export 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||||
|
@ -9,7 +10,6 @@ export 'package:selfprivacy/logic/get_it/console.dart';
|
||||||
export 'package:selfprivacy/logic/get_it/navigation.dart';
|
export 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||||
export 'package:selfprivacy/logic/get_it/timer.dart';
|
export 'package:selfprivacy/logic/get_it/timer.dart';
|
||||||
|
|
||||||
|
|
||||||
final getIt = GetIt.instance;
|
final getIt = GetIt.instance;
|
||||||
|
|
||||||
Future<void> getItSetup() async {
|
Future<void> getItSetup() async {
|
||||||
|
@ -17,6 +17,7 @@ Future<void> getItSetup() async {
|
||||||
|
|
||||||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||||
getIt.registerSingleton<TimerModel>(TimerModel());
|
getIt.registerSingleton<TimerModel>(TimerModel());
|
||||||
|
getIt.registerSingleton<SSHModel>(SSHModel()..init());
|
||||||
getIt.registerSingleton<ApiConfigModel>(ApiConfigModel()..init());
|
getIt.registerSingleton<ApiConfigModel>(ApiConfigModel()..init());
|
||||||
|
|
||||||
await getIt.allReady();
|
await getIt.allReady();
|
||||||
|
|
|
@ -20,22 +20,23 @@ class HiveConfig {
|
||||||
|
|
||||||
await Hive.openBox(BNames.appSettings);
|
await Hive.openBox(BNames.appSettings);
|
||||||
await Hive.openBox<User>(BNames.users);
|
await Hive.openBox<User>(BNames.users);
|
||||||
|
await Hive.openBox(BNames.servicesState);
|
||||||
|
|
||||||
var cipher = HiveAesCipher(await getEncriptedKey());
|
var cipher = HiveAesCipher(await getEncriptedKey(BNames.key));
|
||||||
|
|
||||||
await Hive.openBox(BNames.appConfig, encryptionCipher: cipher);
|
await Hive.openBox(BNames.appConfig, encryptionCipher: cipher);
|
||||||
|
var sshCipher = HiveAesCipher(await getEncriptedKey(BNames.sshEnckey));
|
||||||
|
await Hive.openBox(BNames.sshConfig, encryptionCipher: sshCipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> getEncriptedKey() async {
|
static Future<Uint8List> getEncriptedKey(String encKey) async {
|
||||||
final FlutterSecureStorage secureStorage = FlutterSecureStorage();
|
final secureStorage = FlutterSecureStorage();
|
||||||
var containsEncryptionKey =
|
var hasEncryptionKey = await secureStorage.containsKey(key: encKey);
|
||||||
await secureStorage.containsKey(key: BNames.key);
|
if (!hasEncryptionKey) {
|
||||||
if (!containsEncryptionKey) {
|
|
||||||
var key = Hive.generateSecureKey();
|
var key = Hive.generateSecureKey();
|
||||||
await secureStorage.write(key: BNames.key, value: base64UrlEncode(key));
|
await secureStorage.write(key: encKey, value: base64UrlEncode(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
String? string = await secureStorage.read(key: BNames.key);
|
String? string = await secureStorage.read(key: encKey);
|
||||||
return base64Url.decode(string!);
|
return base64Url.decode(string!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +48,10 @@ class BNames {
|
||||||
static String users = 'users';
|
static String users = 'users';
|
||||||
|
|
||||||
static String appSettings = 'appSettings';
|
static String appSettings = 'appSettings';
|
||||||
|
static String servicesState = 'servicesState';
|
||||||
|
|
||||||
static String key = 'key';
|
static String key = 'key';
|
||||||
|
static String sshEnckey = 'sshEngkey';
|
||||||
|
|
||||||
static String cloudFlareDomain = 'cloudFlareDomain';
|
static String cloudFlareDomain = 'cloudFlareDomain';
|
||||||
static String hetznerKey = 'hetznerKey';
|
static String hetznerKey = 'hetznerKey';
|
||||||
|
@ -61,4 +64,7 @@ class BNames {
|
||||||
static String isLoading = 'isLoading';
|
static String isLoading = 'isLoading';
|
||||||
static String isServerResetedFirstTime = 'isServerResetedFirstTime';
|
static String isServerResetedFirstTime = 'isServerResetedFirstTime';
|
||||||
static String isServerResetedSecondTime = 'isServerResetedSecondTime';
|
static String isServerResetedSecondTime = 'isServerResetedSecondTime';
|
||||||
|
static String sshConfig = 'sshConfig';
|
||||||
|
static String sshPrivateKey = "sshPrivateKey";
|
||||||
|
static String sshPublicKey = "sshPublicKey";
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
import 'package:selfprivacy/logic/models/hetzner_server_info.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_generator.dart';
|
||||||
|
|
||||||
class HetznerApi extends ApiMap {
|
class HetznerApi extends ApiMap {
|
||||||
bool hasLoger;
|
bool hasLoger;
|
||||||
|
@ -73,30 +73,28 @@ class HetznerApi extends ApiMap {
|
||||||
required User rootUser,
|
required User rootUser,
|
||||||
required String domainName,
|
required String domainName,
|
||||||
}) async {
|
}) async {
|
||||||
var dbPassword = getRandomString(40);
|
|
||||||
|
|
||||||
const chars =
|
|
||||||
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
|
||||||
|
|
||||||
var dbStorageName = getRandomString(6, chars);
|
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
|
|
||||||
Response dbCreateResponse = await client.post(
|
Response dbCreateResponse = await client.post(
|
||||||
'/volumes',
|
'/volumes',
|
||||||
data: {
|
data: {
|
||||||
"size": 10,
|
"size": 10,
|
||||||
"name": dbStorageName,
|
"name": StringGenerators.dbStorageName(),
|
||||||
"labels": {"labelkey": "value"},
|
"labels": {"labelkey": "value"},
|
||||||
"location": "fsn1",
|
"location": "fsn1",
|
||||||
"automount": false,
|
"automount": false,
|
||||||
"format": "ext4"
|
"format": "ext4"
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var dbPassword = StringGenerators.dbPassword();
|
||||||
var dbId = dbCreateResponse.data['volume']['id'];
|
var dbId = dbCreateResponse.data['volume']['id'];
|
||||||
|
|
||||||
|
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
|
||||||
|
/// check the branch name, it could be "development" or "master".
|
||||||
|
|
||||||
var data = jsonDecode(
|
var data = jsonDecode(
|
||||||
'''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[], "user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword.hash} SALT=${rootUser.hashPassword.salt} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}'''
|
'''{"name":"$domainName","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId], "networks":[], "user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''');
|
||||||
);
|
|
||||||
|
|
||||||
Response serverCreateResponse = await client.post(
|
Response serverCreateResponse = await client.post(
|
||||||
'/servers',
|
'/servers',
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
|
|
||||||
import 'api_map.dart';
|
import 'api_map.dart';
|
||||||
|
@ -89,4 +90,44 @@ class ServerApi extends ApiMap {
|
||||||
close(client);
|
close(client);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> switchService(ServiceTypes type, bool needToTurnOn) async {
|
||||||
|
var client = await getClient();
|
||||||
|
client.post('/services/${type.url}/${needToTurnOn ? 'enable' : 'disable'}');
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> sendSsh(String ssh) async {
|
||||||
|
var client = await getClient();
|
||||||
|
client.post(
|
||||||
|
'/services/ssh/enable',
|
||||||
|
data: {"public_key": ssh},
|
||||||
|
);
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UrlServerExt on ServiceTypes {
|
||||||
|
String get url {
|
||||||
|
switch (this) {
|
||||||
|
// case ServiceTypes.mail:
|
||||||
|
// return ''; // cannot be swithch off
|
||||||
|
// case ServiceTypes.messenger:
|
||||||
|
// return ''; // external service
|
||||||
|
// case ServiceTypes.video:
|
||||||
|
// return ''; // jeetsu meet not working
|
||||||
|
case ServiceTypes.passwordManager:
|
||||||
|
return 'bitwarden';
|
||||||
|
case ServiceTypes.cloud:
|
||||||
|
return 'nextcloud';
|
||||||
|
case ServiceTypes.socialNetwork:
|
||||||
|
return 'pleroma';
|
||||||
|
case ServiceTypes.git:
|
||||||
|
return 'gitea';
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
return 'ocserv';
|
||||||
|
default:
|
||||||
|
throw Exception('wrong state');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:ionicons/ionicons.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||||
|
|
||||||
enum InitializingSteps {
|
enum InitializingSteps {
|
||||||
setHeznerKey,
|
setHeznerKey,
|
||||||
setCloudFlareKey,
|
setCloudFlareKey,
|
||||||
|
@ -10,3 +15,80 @@ enum InitializingSteps {
|
||||||
}
|
}
|
||||||
enum Period { hour, day, month }
|
enum Period { hour, day, month }
|
||||||
|
|
||||||
|
enum ServiceTypes {
|
||||||
|
mail,
|
||||||
|
messenger,
|
||||||
|
passwordManager,
|
||||||
|
video,
|
||||||
|
cloud,
|
||||||
|
socialNetwork,
|
||||||
|
git,
|
||||||
|
vpn,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ServiceTypesExt on ServiceTypes {
|
||||||
|
String get title {
|
||||||
|
switch (this) {
|
||||||
|
case ServiceTypes.mail:
|
||||||
|
return 'services.mail.title'.tr();
|
||||||
|
case ServiceTypes.messenger:
|
||||||
|
return 'services.messenger.title'.tr();
|
||||||
|
case ServiceTypes.passwordManager:
|
||||||
|
return 'services.password_manager.title'.tr();
|
||||||
|
case ServiceTypes.video:
|
||||||
|
return 'services.video.title'.tr();
|
||||||
|
case ServiceTypes.cloud:
|
||||||
|
return 'services.cloud.title'.tr();
|
||||||
|
case ServiceTypes.socialNetwork:
|
||||||
|
return 'services.social_network.title'.tr();
|
||||||
|
case ServiceTypes.git:
|
||||||
|
return 'services.git.title'.tr();
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
return 'services.vpn.title'.tr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String get subtitle {
|
||||||
|
switch (this) {
|
||||||
|
case ServiceTypes.mail:
|
||||||
|
return 'services.mail.subtitle'.tr();
|
||||||
|
case ServiceTypes.messenger:
|
||||||
|
return 'services.messenger.subtitle'.tr();
|
||||||
|
case ServiceTypes.passwordManager:
|
||||||
|
return 'services.password_manager.subtitle'.tr();
|
||||||
|
case ServiceTypes.video:
|
||||||
|
return 'services.video.subtitle'.tr();
|
||||||
|
case ServiceTypes.cloud:
|
||||||
|
return 'services.cloud.subtitle'.tr();
|
||||||
|
case ServiceTypes.socialNetwork:
|
||||||
|
return 'services.social_network.subtitle'.tr();
|
||||||
|
case ServiceTypes.git:
|
||||||
|
return 'services.git.subtitle'.tr();
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
return 'services.vpn.subtitle'.tr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData get icon {
|
||||||
|
switch (this) {
|
||||||
|
case ServiceTypes.mail:
|
||||||
|
return BrandIcons.envelope;
|
||||||
|
case ServiceTypes.messenger:
|
||||||
|
return BrandIcons.messanger;
|
||||||
|
case ServiceTypes.passwordManager:
|
||||||
|
return BrandIcons.key;
|
||||||
|
case ServiceTypes.video:
|
||||||
|
return BrandIcons.webcam;
|
||||||
|
case ServiceTypes.cloud:
|
||||||
|
return BrandIcons.upload;
|
||||||
|
case ServiceTypes.socialNetwork:
|
||||||
|
return BrandIcons.social;
|
||||||
|
case ServiceTypes.git:
|
||||||
|
return BrandIcons.git;
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
return Ionicons.shield_checkmark_outline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String get txt => this.toString().split('.')[1];
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ 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:selfprivacy/logic/cubit/services/services_cubit.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';
|
||||||
|
|
||||||
|
@ -43,9 +44,10 @@ part 'app_config_state.dart';
|
||||||
/// c. if server is okay set that fully checked
|
/// c. if server is okay set that fully checked
|
||||||
|
|
||||||
class AppConfigCubit extends Cubit<AppConfigState> {
|
class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
AppConfigCubit() : super(InitialAppConfigState());
|
AppConfigCubit(this.servicesCubit) : super(InitialAppConfigState());
|
||||||
|
|
||||||
final repository = AppConfigRepository();
|
final repository = AppConfigRepository();
|
||||||
|
final ServicesCubit servicesCubit;
|
||||||
|
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
var state = await repository.load();
|
var state = await repository.load();
|
||||||
|
@ -232,6 +234,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
|
|
||||||
if (isServerWorking) {
|
if (isServerWorking) {
|
||||||
await repository.saveHasFinalChecked(true);
|
await repository.saveHasFinalChecked(true);
|
||||||
|
servicesCubit.allOn();
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
hasFinalChecked: true,
|
hasFinalChecked: true,
|
||||||
|
@ -259,12 +262,16 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
|
|
||||||
void clearAppConfig() {
|
void clearAppConfig() {
|
||||||
closeTimer();
|
closeTimer();
|
||||||
|
servicesCubit.allOff();
|
||||||
|
|
||||||
repository.clearAppConfig();
|
repository.clearAppConfig();
|
||||||
emit(InitialAppConfigState());
|
emit(InitialAppConfigState());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> serverDelete() async {
|
Future<void> serverDelete() async {
|
||||||
closeTimer();
|
closeTimer();
|
||||||
|
servicesCubit.allOff();
|
||||||
|
|
||||||
if (state.hetznerServer != null) {
|
if (state.hetznerServer != null) {
|
||||||
await repository.deleteServer(state.cloudFlareDomain!);
|
await repository.deleteServer(state.cloudFlareDomain!);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:cubit_form/cubit_form.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/jobs/job.dart';
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
import 'package:selfprivacy/utils/password_generator.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:selfprivacy/utils/password_generator.dart';
|
||||||
|
|
||||||
class UserFormCubit extends FormCubit {
|
class UserFormCubit extends FormCubit {
|
||||||
UserFormCubit({
|
UserFormCubit({
|
||||||
|
@ -32,7 +32,7 @@ class UserFormCubit extends FormCubit {
|
||||||
);
|
);
|
||||||
|
|
||||||
password = FieldCubit(
|
password = FieldCubit(
|
||||||
initalValue: isEdit ? user!.password : genPass(),
|
initalValue: isEdit ? user!.password : StringGenerators.userPassword(),
|
||||||
validations: [
|
validations: [
|
||||||
RequiredStringValidation('validations.required'.tr()),
|
RequiredStringValidation('validations.required'.tr()),
|
||||||
ValidationModel<String>((s) => passwordRegExp.hasMatch(s),
|
ValidationModel<String>((s) => passwordRegExp.hasMatch(s),
|
||||||
|
@ -56,7 +56,7 @@ class UserFormCubit extends FormCubit {
|
||||||
late FieldCubit<String> password;
|
late FieldCubit<String> password;
|
||||||
|
|
||||||
void genNewPassword() {
|
void genNewPassword() {
|
||||||
password.externalSetValue(genPass());
|
password.externalSetValue(StringGenerators.userPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
final JobsCubit jobsCubit;
|
final JobsCubit jobsCubit;
|
||||||
|
|
|
@ -1,19 +1,27 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
|
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';
|
||||||
import 'package:selfprivacy/logic/models/jobs/job.dart';
|
import 'package:selfprivacy/logic/get_it/ssh_helper.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
export 'package:provider/provider.dart';
|
export 'package:provider/provider.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
part 'jobs_state.dart';
|
part 'jobs_state.dart';
|
||||||
|
|
||||||
class JobsCubit extends Cubit<JobsState> {
|
class JobsCubit extends Cubit<JobsState> {
|
||||||
JobsCubit(this.usersCubit) : super(JobsStateEmpty());
|
JobsCubit({
|
||||||
|
required this.usersCubit,
|
||||||
|
required this.servicesCubit,
|
||||||
|
}) : super(JobsStateEmpty());
|
||||||
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
final UsersCubit usersCubit;
|
final UsersCubit usersCubit;
|
||||||
|
final ServicesCubit servicesCubit;
|
||||||
|
|
||||||
void addJob(Job job) {
|
void addJob(Job job) {
|
||||||
var newJobsList = <Job>[];
|
var newJobsList = <Job>[];
|
||||||
|
@ -21,6 +29,10 @@ class JobsCubit extends Cubit<JobsState> {
|
||||||
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||||
}
|
}
|
||||||
newJobsList.add(job);
|
newJobsList.add(job);
|
||||||
|
getIt<NavigationService>().showSnackBar(SnackBar(
|
||||||
|
content: Text('jobs.jobAdded'.tr()),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
|
));
|
||||||
emit(JobsStateWithJobs(newJobsList));
|
emit(JobsStateWithJobs(newJobsList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,16 +41,63 @@ class JobsCubit extends Cubit<JobsState> {
|
||||||
emit(newState);
|
emit(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createOrRemoveServiceToggleJob(ServiceToggleJob job) {
|
||||||
|
var newJobsList = <Job>[];
|
||||||
|
if (state is JobsStateWithJobs) {
|
||||||
|
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||||
|
}
|
||||||
|
var needToRemoveJob =
|
||||||
|
newJobsList.any((el) => el is ServiceToggleJob && el.type == job.type);
|
||||||
|
if (needToRemoveJob) {
|
||||||
|
var removingJob = newJobsList
|
||||||
|
.firstWhere(((el) => el is ServiceToggleJob && el.type == job.type));
|
||||||
|
removeJob(removingJob.id);
|
||||||
|
} else {
|
||||||
|
newJobsList.add(job);
|
||||||
|
getIt<NavigationService>().showSnackBar(SnackBar(
|
||||||
|
content: Text('jobs.jobAdded'.tr()),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
|
));
|
||||||
|
emit(JobsStateWithJobs(newJobsList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createShhJobIfNotExist(CreateSSHKeyJob job) {
|
||||||
|
var newJobsList = <Job>[];
|
||||||
|
if (state is JobsStateWithJobs) {
|
||||||
|
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||||
|
}
|
||||||
|
var isExistInJobList = newJobsList.any((el) => el is CreateSSHKeyJob);
|
||||||
|
if (!isExistInJobList) {
|
||||||
|
newJobsList.add(job);
|
||||||
|
getIt<NavigationService>().showSnackBar(SnackBar(
|
||||||
|
content: Text('jobs.jobAdded'.tr()),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
|
));
|
||||||
|
emit(JobsStateWithJobs(newJobsList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> applyAll() async {
|
Future<void> applyAll() async {
|
||||||
if (state is JobsStateWithJobs) {
|
if (state is JobsStateWithJobs) {
|
||||||
var jobs = (state as JobsStateWithJobs).jobList;
|
var jobs = (state as JobsStateWithJobs).jobList;
|
||||||
emit(JobsStateLoading());
|
emit(JobsStateLoading());
|
||||||
|
|
||||||
var newUsers = <User>[];
|
var newUsers = <User>[];
|
||||||
for (var job in jobs) {
|
for (var job in jobs) {
|
||||||
if (job is CreateUserJob) {
|
if (job is CreateUserJob) {
|
||||||
newUsers.add(job.user);
|
newUsers.add(job.user);
|
||||||
await api.createUser(job.user);
|
await api.createUser(job.user);
|
||||||
|
} else if (job is ServiceToggleJob) {
|
||||||
|
await api.switchService(job.type, job.needToTurnOn);
|
||||||
|
if (job.needToTurnOn) {
|
||||||
|
servicesCubit.turnOnist([job.type]);
|
||||||
|
} else {
|
||||||
|
servicesCubit.turnOffList([job.type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (job is CreateSSHKeyJob) {
|
||||||
|
await getIt<SSHModel>().generateKeys();
|
||||||
|
api.sendSsh(getIt<SSHModel>().savedPubKey!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
63
lib/logic/cubit/services/services_cubit.dart
Normal file
63
lib/logic/cubit/services/services_cubit.dart
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
|
|
||||||
|
part 'services_state.dart';
|
||||||
|
|
||||||
|
class ServicesCubit extends Cubit<ServicesState> {
|
||||||
|
ServicesCubit() : super(ServicesState.allOff());
|
||||||
|
|
||||||
|
Box box = Hive.box(BNames.servicesState);
|
||||||
|
|
||||||
|
void load() {
|
||||||
|
emit(
|
||||||
|
ServicesState(
|
||||||
|
isPasswordManagerEnable:
|
||||||
|
box.get(ServiceTypes.passwordManager.txt, defaultValue: false),
|
||||||
|
isCloudEnable: box.get(ServiceTypes.cloud.txt, defaultValue: false),
|
||||||
|
isGitEnable: box.get(ServiceTypes.git.txt, defaultValue: false),
|
||||||
|
isSocialNetworkEnable:
|
||||||
|
box.get(ServiceTypes.socialNetwork.txt, defaultValue: false),
|
||||||
|
isVpnEnable: box.get(ServiceTypes.vpn.txt, defaultValue: false),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void allOn() {
|
||||||
|
box.put(ServiceTypes.passwordManager.txt, true);
|
||||||
|
box.put(ServiceTypes.cloud.txt, true);
|
||||||
|
box.put(ServiceTypes.git.txt, true);
|
||||||
|
box.put(ServiceTypes.socialNetwork.txt, true);
|
||||||
|
box.put(ServiceTypes.vpn.txt, true);
|
||||||
|
|
||||||
|
emit(ServicesState.allOn());
|
||||||
|
}
|
||||||
|
|
||||||
|
void allOff() {
|
||||||
|
box.put(ServiceTypes.passwordManager.txt, false);
|
||||||
|
box.put(ServiceTypes.cloud.txt, false);
|
||||||
|
box.put(ServiceTypes.git.txt, false);
|
||||||
|
box.put(ServiceTypes.socialNetwork.txt, false);
|
||||||
|
box.put(ServiceTypes.vpn.txt, false);
|
||||||
|
|
||||||
|
emit(ServicesState.allOff());
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnOffList(List<ServiceTypes> list) {
|
||||||
|
for (final service in list) {
|
||||||
|
box.put(service.txt, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(state.disableList(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnOnist(List<ServiceTypes> list) {
|
||||||
|
for (final service in list) {
|
||||||
|
box.put(service.txt, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(state.enableList(list));
|
||||||
|
}
|
||||||
|
}
|
93
lib/logic/cubit/services/services_state.dart
Normal file
93
lib/logic/cubit/services/services_state.dart
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
part of 'services_cubit.dart';
|
||||||
|
|
||||||
|
class ServicesState extends Equatable {
|
||||||
|
const ServicesState({
|
||||||
|
required this.isPasswordManagerEnable,
|
||||||
|
required this.isCloudEnable,
|
||||||
|
required this.isGitEnable,
|
||||||
|
required this.isSocialNetworkEnable,
|
||||||
|
required this.isVpnEnable,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool isPasswordManagerEnable;
|
||||||
|
final bool isCloudEnable;
|
||||||
|
final bool isGitEnable;
|
||||||
|
final bool isSocialNetworkEnable;
|
||||||
|
final bool isVpnEnable;
|
||||||
|
|
||||||
|
factory ServicesState.allOff() => ServicesState(
|
||||||
|
isPasswordManagerEnable: false,
|
||||||
|
isCloudEnable: false,
|
||||||
|
isGitEnable: false,
|
||||||
|
isSocialNetworkEnable: false,
|
||||||
|
isVpnEnable: false,
|
||||||
|
);
|
||||||
|
factory ServicesState.allOn() => ServicesState(
|
||||||
|
isPasswordManagerEnable: true,
|
||||||
|
isCloudEnable: true,
|
||||||
|
isGitEnable: true,
|
||||||
|
isSocialNetworkEnable: true,
|
||||||
|
isVpnEnable: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
ServicesState enableList(
|
||||||
|
List<ServiceTypes> list,
|
||||||
|
) =>
|
||||||
|
ServicesState(
|
||||||
|
isPasswordManagerEnable: list.contains(ServiceTypes.passwordManager)
|
||||||
|
? true
|
||||||
|
: isPasswordManagerEnable,
|
||||||
|
isCloudEnable: list.contains(ServiceTypes.cloud) ? true : isCloudEnable,
|
||||||
|
isGitEnable:
|
||||||
|
list.contains(ServiceTypes.git) ? true : isPasswordManagerEnable,
|
||||||
|
isSocialNetworkEnable: list.contains(ServiceTypes.socialNetwork)
|
||||||
|
? true
|
||||||
|
: isPasswordManagerEnable,
|
||||||
|
isVpnEnable:
|
||||||
|
list.contains(ServiceTypes.vpn) ? true : isPasswordManagerEnable,
|
||||||
|
);
|
||||||
|
|
||||||
|
ServicesState disableList(
|
||||||
|
List<ServiceTypes> list,
|
||||||
|
) =>
|
||||||
|
ServicesState(
|
||||||
|
isPasswordManagerEnable: list.contains(ServiceTypes.passwordManager)
|
||||||
|
? false
|
||||||
|
: isPasswordManagerEnable,
|
||||||
|
isCloudEnable:
|
||||||
|
list.contains(ServiceTypes.cloud) ? false : isCloudEnable,
|
||||||
|
isGitEnable:
|
||||||
|
list.contains(ServiceTypes.git) ? false : isPasswordManagerEnable,
|
||||||
|
isSocialNetworkEnable: list.contains(ServiceTypes.socialNetwork)
|
||||||
|
? false
|
||||||
|
: isPasswordManagerEnable,
|
||||||
|
isVpnEnable:
|
||||||
|
list.contains(ServiceTypes.vpn) ? false : isPasswordManagerEnable,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [
|
||||||
|
isPasswordManagerEnable,
|
||||||
|
isCloudEnable,
|
||||||
|
isGitEnable,
|
||||||
|
isSocialNetworkEnable,
|
||||||
|
isVpnEnable
|
||||||
|
];
|
||||||
|
|
||||||
|
bool isEnableByType(ServiceTypes type) {
|
||||||
|
switch (type) {
|
||||||
|
case ServiceTypes.passwordManager:
|
||||||
|
return isPasswordManagerEnable;
|
||||||
|
case ServiceTypes.cloud:
|
||||||
|
return isCloudEnable;
|
||||||
|
case ServiceTypes.socialNetwork:
|
||||||
|
return isSocialNetworkEnable;
|
||||||
|
case ServiceTypes.git:
|
||||||
|
return isGitEnable;
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
return isVpnEnable;
|
||||||
|
default:
|
||||||
|
throw Exception('wrong state');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,21 +34,3 @@ class UsersCubit extends Cubit<UsersState> {
|
||||||
emit(UsersState(users));
|
emit(UsersState(users));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// final initMockUsers = <User>[
|
|
||||||
// User(login: 'Heartbreaking.Goose', password: genPass()),
|
|
||||||
// User(login: 'Alma.lawson', password: genPass()),
|
|
||||||
// User(login: 'Bee.gees', password: genPass()),
|
|
||||||
// User(login: 'Bim.jennings', password: genPass()),
|
|
||||||
// User(login: 'Debra.holt', password: genPass()),
|
|
||||||
// User(login: 'Georgia.young', password: genPass()),
|
|
||||||
// User(login: 'Kenzi.lawson', password: genPass()),
|
|
||||||
// User(login: 'Le.jennings', password: genPass()),
|
|
||||||
// User(login: 'Kirill.Zh', password: genPass()),
|
|
||||||
// User(login: 'Tina.Bolton', password: genPass()),
|
|
||||||
// User(login: 'Rebekah.Lynn', password: genPass()),
|
|
||||||
// User(login: 'Aleena.Armstrong', password: genPass()),
|
|
||||||
// User(login: 'Rosemary.Williams', password: genPass()),
|
|
||||||
// User(login: 'Sullivan.Nixon', password: genPass()),
|
|
||||||
// User(login: 'Aleena.Armstrong', password: genPass()),
|
|
||||||
// ];
|
|
||||||
|
|
|
@ -2,7 +2,10 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
class NavigationService {
|
class NavigationService {
|
||||||
|
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
|
||||||
|
GlobalKey<ScaffoldMessengerState>();
|
||||||
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) {
|
||||||
|
@ -13,4 +16,10 @@ class NavigationService {
|
||||||
builder: (_) => dialog,
|
builder: (_) => dialog,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showSnackBar(SnackBar snackBar) {
|
||||||
|
final state = scaffoldMessengerKey.currentState!;
|
||||||
|
|
||||||
|
state.showSnackBar(snackBar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
33
lib/logic/get_it/ssh_helper.dart
Normal file
33
lib/logic/get_it/ssh_helper.dart
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pointycastle/pointycastle.dart';
|
||||||
|
import 'package:rsa_encrypt/rsa_encrypt.dart';
|
||||||
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
|
import 'package:pointycastle/api.dart' as crypto;
|
||||||
|
import 'package:ssh_key/ssh_key.dart' as ssh_key;
|
||||||
|
|
||||||
|
class SSHModel {
|
||||||
|
Box _box = Hive.box(BNames.sshConfig);
|
||||||
|
String? savedPrivateKey;
|
||||||
|
String? savedPubKey;
|
||||||
|
|
||||||
|
Future<void> generateKeys() async {
|
||||||
|
var helper = RsaKeyHelper();
|
||||||
|
crypto.AsymmetricKeyPair pair =
|
||||||
|
await helper.computeRSAKeyPair(helper.getSecureRandom());
|
||||||
|
var privateKey = pair.privateKey as RSAPrivateKey;
|
||||||
|
var publicKey = pair.publicKey as RSAPublicKey;
|
||||||
|
|
||||||
|
savedPrivateKey = helper.encodePrivateKeyToPemPKCS1(privateKey);
|
||||||
|
savedPubKey = publicKey.encode(ssh_key.PubKeyEncoding.openSsh);
|
||||||
|
|
||||||
|
await _box.put(BNames.sshPrivateKey, savedPrivateKey);
|
||||||
|
await _box.put(BNames.sshPublicKey, savedPubKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
savedPrivateKey = _box.get(BNames.sshPrivateKey);
|
||||||
|
savedPubKey = _box.get(BNames.sshPublicKey);
|
||||||
|
}
|
||||||
|
}
|
54
lib/logic/models/job.dart
Normal file
54
lib/logic/models/job.dart
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
|
import 'package:selfprivacy/utils/password_generator.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
import 'user.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class Job extends Equatable {
|
||||||
|
Job({
|
||||||
|
String? id,
|
||||||
|
required this.title,
|
||||||
|
}) : id = id ?? StringGenerators.simpleId();
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, title];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateUserJob extends Job {
|
||||||
|
CreateUserJob({
|
||||||
|
required this.user,
|
||||||
|
}) : super(title: '${"jobs.createUser".tr()} ${user.login}');
|
||||||
|
|
||||||
|
final User user;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, title, user];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServiceToggleJob extends Job {
|
||||||
|
ServiceToggleJob({
|
||||||
|
required this.type,
|
||||||
|
required this.needToTurnOn,
|
||||||
|
}) : super(
|
||||||
|
title:
|
||||||
|
'${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}');
|
||||||
|
|
||||||
|
final ServiceTypes type;
|
||||||
|
final bool needToTurnOn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, title, type, needToTurnOn];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateSSHKeyJob extends Job {
|
||||||
|
CreateSSHKeyJob() : super(title: '${"more.create_ssh_key".tr()}');
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id, title];
|
||||||
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/utils/password_generator2.dart';
|
|
||||||
|
|
||||||
import '../user.dart';
|
|
||||||
|
|
||||||
@immutable
|
|
||||||
class Job extends Equatable {
|
|
||||||
Job({
|
|
||||||
String? id,
|
|
||||||
required this.title,
|
|
||||||
}) : id = id ?? getRandomString(5);
|
|
||||||
|
|
||||||
final String title;
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [id, title];
|
|
||||||
}
|
|
||||||
|
|
||||||
class CreateUserJob extends Job {
|
|
||||||
CreateUserJob({
|
|
||||||
required this.user,
|
|
||||||
}) : super(title: 'Create ${user.login}');
|
|
||||||
|
|
||||||
final User user;
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [id, title];
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ import 'package:crypt/crypt.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.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/password_generator.dart';
|
||||||
|
|
||||||
part 'user.g.dart';
|
part 'user.g.dart';
|
||||||
|
|
||||||
|
@ -25,7 +26,10 @@ class User extends Equatable {
|
||||||
|
|
||||||
Color get color => stringToColor(login);
|
Color get color => stringToColor(login);
|
||||||
|
|
||||||
Crypt get hashPassword => Crypt.sha512(password);
|
Crypt get hashPassword => Crypt.sha512(
|
||||||
|
password,
|
||||||
|
salt: StringGenerators.passwordSalt(),
|
||||||
|
);
|
||||||
|
|
||||||
String toString() {
|
String toString() {
|
||||||
return login;
|
return login;
|
||||||
|
|
|
@ -16,11 +16,11 @@ import 'config/localization.dart';
|
||||||
import 'logic/cubit/app_settings/app_settings_cubit.dart';
|
import 'logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await HiveConfig.init();
|
await HiveConfig.init();
|
||||||
Bloc.observer = SimpleBlocObserver();
|
Bloc.observer = SimpleBlocObserver();
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
await getItSetup();
|
await getItSetup();
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
|
@ -37,6 +37,8 @@ class MyApp extends StatelessWidget {
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
value: SystemUiOverlayStyle.light, // Manually changnig appbar color
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
|
scaffoldMessengerKey:
|
||||||
|
getIt.get<NavigationService>().scaffoldMessengerKey,
|
||||||
navigatorKey: getIt.get<NavigationService>().navigatorKey,
|
navigatorKey: getIt.get<NavigationService>().navigatorKey,
|
||||||
localizationsDelegates: context.localizationDelegates,
|
localizationsDelegates: context.localizationDelegates,
|
||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
|
|
24
lib/ui/components/brand_switch/brand_switch.dart
Normal file
24
lib/ui/components/brand_switch/brand_switch.dart
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
|
|
||||||
|
class BrandSwitch extends StatelessWidget {
|
||||||
|
const BrandSwitch({
|
||||||
|
Key? key,
|
||||||
|
required this.onChanged,
|
||||||
|
required this.value,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final ValueChanged<bool> onChanged;
|
||||||
|
final bool value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Switch(
|
||||||
|
activeColor: BrandColors.green1,
|
||||||
|
activeTrackColor: BrandColors.green2,
|
||||||
|
value: value,
|
||||||
|
onChanged: onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,10 +52,16 @@ class BrandText extends StatelessWidget {
|
||||||
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,
|
||||||
|
TextAlign? textAlign,
|
||||||
|
}) =>
|
||||||
|
BrandText(
|
||||||
text,
|
text,
|
||||||
type: TextType.h2,
|
type: TextType.h2,
|
||||||
style: style,
|
style: style,
|
||||||
|
textAlign: textAlign,
|
||||||
);
|
);
|
||||||
factory BrandText.h3(String text, {TextStyle? style, TextAlign? textAlign}) =>
|
factory BrandText.h3(String text, {TextStyle? style, TextAlign? textAlign}) =>
|
||||||
BrandText(
|
BrandText(
|
||||||
|
|
|
@ -36,11 +36,7 @@ class JobsContent extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: BrandCards.small(
|
child: BrandCards.small(
|
||||||
child: Row(
|
child: Text(j.title),
|
||||||
children: [
|
|
||||||
BrandText.body1(j.title),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_switch/brand_switch.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/named_font_weight.dart';
|
import 'package:selfprivacy/utils/named_font_weight.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
@ -52,9 +53,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
Switch(
|
BrandSwitch(
|
||||||
activeColor: BrandColors.green1,
|
|
||||||
activeTrackColor: BrandColors.green2,
|
|
||||||
value: Theme.of(context).brightness == Brightness.dark,
|
value: Theme.of(context).brightness == Brightness.dark,
|
||||||
onChanged: (value) => context
|
onChanged: (value) => context
|
||||||
.read<AppSettingsCubit>()
|
.read<AppSettingsCubit>()
|
||||||
|
@ -120,7 +119,17 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
// deleteServer(context)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget deleteServer(BuildContext context) {
|
||||||
|
// todo: need to check
|
||||||
|
return Container(
|
||||||
padding: EdgeInsets.only(top: 20, bottom: 5),
|
padding: EdgeInsets.only(top: 20, bottom: 5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
|
@ -160,9 +169,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
||||||
text: 'modals.7'.tr(),
|
text: 'modals.7'.tr(),
|
||||||
isRed: true,
|
isRed: true,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await context
|
await context.read<AppConfigCubit>().serverDelete();
|
||||||
.read<AppConfigCubit>()
|
|
||||||
.serverDelete();
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}),
|
}),
|
||||||
ActionButton(
|
ActionButton(
|
||||||
|
@ -176,11 +183,6 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:ionicons/ionicons.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
|
import 'package:selfprivacy/config/text_themes.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
||||||
import 'package:selfprivacy/ui/pages/initializing/initializing.dart';
|
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';
|
||||||
|
@ -21,9 +28,14 @@ class MorePage extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var jobsCubit = context.watch<JobsCubit>();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: PreferredSize(
|
||||||
child: BrandHeader(title: 'basis.more'.tr()),
|
child: BrandHeader(
|
||||||
|
title: 'basis.more'.tr(),
|
||||||
|
hasFlashButton: true,
|
||||||
|
),
|
||||||
preferredSize: Size.fromHeight(52),
|
preferredSize: Size.fromHeight(52),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
|
@ -63,6 +75,25 @@ class MorePage extends StatelessWidget {
|
||||||
iconData: BrandIcons.terminal,
|
iconData: BrandIcons.terminal,
|
||||||
goTo: Console(),
|
goTo: Console(),
|
||||||
),
|
),
|
||||||
|
_MoreMenuTapItem(
|
||||||
|
title: 'more.create_ssh_key'.tr(),
|
||||||
|
iconData: Ionicons.key_outline,
|
||||||
|
onTap: () {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return _MoreDetails(
|
||||||
|
title: 'more.create_ssh_key'.tr(),
|
||||||
|
icon: Ionicons.key_outline,
|
||||||
|
onTap: () {
|
||||||
|
jobsCubit.createShhJobIfNotExist(CreateSSHKeyJob());
|
||||||
|
},
|
||||||
|
text: 'more.generate_key_text'.tr(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -72,6 +103,73 @@ class MorePage extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _MoreDetails extends StatelessWidget {
|
||||||
|
const _MoreDetails({
|
||||||
|
Key? key,
|
||||||
|
required this.icon,
|
||||||
|
required this.title,
|
||||||
|
required this.onTap,
|
||||||
|
required this.text,
|
||||||
|
}) : super(key: key);
|
||||||
|
final String title;
|
||||||
|
final IconData icon;
|
||||||
|
final Function onTap;
|
||||||
|
final String text;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var textStyle = body1Style.copyWith(
|
||||||
|
color: Theme.of(context).brightness == Brightness.dark
|
||||||
|
? Colors.white
|
||||||
|
: BrandColors.black);
|
||||||
|
return Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Container(
|
||||||
|
width: 350,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: paddingH15V30,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
IconStatusMask(
|
||||||
|
status: StateType.stable,
|
||||||
|
child: Icon(icon, size: 40, color: Colors.white),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
BrandText.h2(title),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
text,
|
||||||
|
style: textStyle,
|
||||||
|
),
|
||||||
|
SizedBox(height: 40),
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
child: BrandButton.rised(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
onTap();
|
||||||
|
},
|
||||||
|
text: 'more.generate_key'.tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _NavItem extends StatelessWidget {
|
class _NavItem extends StatelessWidget {
|
||||||
const _NavItem({
|
const _NavItem({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -88,7 +186,52 @@ class _NavItem extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => Navigator.of(context).push(materialRoute(goTo)),
|
onTap: () => Navigator.of(context).push(materialRoute(goTo)),
|
||||||
child: Container(
|
child: _MoreMenuItem(
|
||||||
|
iconData: iconData,
|
||||||
|
title: title,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MoreMenuTapItem extends StatelessWidget {
|
||||||
|
const _MoreMenuTapItem({
|
||||||
|
Key? key,
|
||||||
|
required this.iconData,
|
||||||
|
required this.onTap,
|
||||||
|
required this.title,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final IconData iconData;
|
||||||
|
final Function onTap;
|
||||||
|
final String title;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
onTap();
|
||||||
|
},
|
||||||
|
child: _MoreMenuItem(
|
||||||
|
iconData: iconData,
|
||||||
|
title: title,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MoreMenuItem extends StatelessWidget {
|
||||||
|
const _MoreMenuItem({
|
||||||
|
Key? key,
|
||||||
|
required this.iconData,
|
||||||
|
required this.title,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final IconData iconData;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 24),
|
padding: EdgeInsets.symmetric(vertical: 24),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
|
@ -111,7 +254,6 @@ class _NavItem extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class CpuChart extends StatelessWidget {
|
||||||
interval: 20,
|
interval: 20,
|
||||||
rotateAngle: 90.0,
|
rotateAngle: 90.0,
|
||||||
showTitles: true,
|
showTitles: true,
|
||||||
getTextStyles: (value) => const TextStyle(
|
getTextStyles: (_, __) => const TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.purple,
|
color: Colors.purple,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
@ -60,7 +60,7 @@ class CpuChart extends StatelessWidget {
|
||||||
return bottomTitle(value.toInt());
|
return bottomTitle(value.toInt());
|
||||||
}),
|
}),
|
||||||
leftTitles: SideTitles(
|
leftTitles: SideTitles(
|
||||||
getTextStyles: (value) => progressTextStyleLight.copyWith(
|
getTextStyles: (_, __) => progressTextStyleLight.copyWith(
|
||||||
color: Theme.of(context).brightness == Brightness.dark
|
color: Theme.of(context).brightness == Brightness.dark
|
||||||
? BrandColors.gray4
|
? BrandColors.gray4
|
||||||
: null,
|
: null,
|
||||||
|
|
|
@ -71,7 +71,7 @@ class NetworkChart extends StatelessWidget {
|
||||||
interval: 20,
|
interval: 20,
|
||||||
rotateAngle: 90.0,
|
rotateAngle: 90.0,
|
||||||
showTitles: true,
|
showTitles: true,
|
||||||
getTextStyles: (value) => const TextStyle(
|
getTextStyles: (_, __) => const TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: Colors.purple,
|
color: Colors.purple,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
@ -87,7 +87,7 @@ class NetworkChart extends StatelessWidget {
|
||||||
].reduce(max) *
|
].reduce(max) *
|
||||||
1.2 /
|
1.2 /
|
||||||
10,
|
10,
|
||||||
getTextStyles: (value) => progressTextStyleLight.copyWith(
|
getTextStyles: (_, __) => progressTextStyleLight.copyWith(
|
||||||
color: Theme.of(context).brightness == Brightness.dark
|
color: Theme.of(context).brightness == Brightness.dark
|
||||||
? BrandColors.gray4
|
? BrandColors.gray4
|
||||||
: null,
|
: null,
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
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/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
import 'package:selfprivacy/config/text_themes.dart';
|
||||||
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.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_cards/brand_cards.dart';
|
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/components/brand_switch/brand_switch.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||||
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
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';
|
||||||
|
@ -17,6 +23,14 @@ import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../rootRoute.dart';
|
import '../rootRoute.dart';
|
||||||
|
|
||||||
|
const switchableServices = [
|
||||||
|
ServiceTypes.passwordManager,
|
||||||
|
ServiceTypes.cloud,
|
||||||
|
ServiceTypes.socialNetwork,
|
||||||
|
ServiceTypes.git,
|
||||||
|
ServiceTypes.vpn,
|
||||||
|
];
|
||||||
|
|
||||||
class ServicesPage extends StatefulWidget {
|
class ServicesPage extends StatefulWidget {
|
||||||
ServicesPage({Key? key}) : super(key: key);
|
ServicesPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -63,52 +77,25 @@ class _Card extends StatelessWidget {
|
||||||
final ServiceTypes serviceType;
|
final ServiceTypes serviceType;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
String title;
|
|
||||||
IconData iconData;
|
|
||||||
String subtitle;
|
|
||||||
|
|
||||||
switch (serviceType) {
|
|
||||||
case ServiceTypes.mail:
|
|
||||||
iconData = BrandIcons.envelope;
|
|
||||||
title = 'services.mail.title'.tr();
|
|
||||||
subtitle = 'services.mail.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.messenger:
|
|
||||||
iconData = BrandIcons.messanger;
|
|
||||||
title = 'services.messenger.title'.tr();
|
|
||||||
subtitle = 'services.messenger.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.passwordManager:
|
|
||||||
iconData = BrandIcons.key;
|
|
||||||
title = 'services.password_manager.title'.tr();
|
|
||||||
subtitle = 'services.password_manager.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.video:
|
|
||||||
iconData = BrandIcons.webcam;
|
|
||||||
title = 'services.video.title'.tr();
|
|
||||||
subtitle = 'services.video.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.cloud:
|
|
||||||
iconData = BrandIcons.upload;
|
|
||||||
title = 'services.cloud.title'.tr();
|
|
||||||
subtitle = 'services.cloud.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.socialNetwork:
|
|
||||||
iconData = BrandIcons.social;
|
|
||||||
title = 'services.social_network.title'.tr();
|
|
||||||
subtitle = 'services.social_network.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
case ServiceTypes.git:
|
|
||||||
iconData = BrandIcons.git;
|
|
||||||
title = 'services.git.title'.tr();
|
|
||||||
subtitle = 'services.git.subtitle'.tr();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
|
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized;
|
||||||
var changeTab = context.read<ChangeTab>().onPress;
|
var changeTab = context.read<ChangeTab>().onPress;
|
||||||
|
|
||||||
|
var serviceState = context.watch<ServicesCubit>().state;
|
||||||
|
var jobsCubit = context.watch<JobsCubit>();
|
||||||
|
var jobState = jobsCubit.state;
|
||||||
|
|
||||||
|
var switchebleService = switchableServices.contains(serviceType);
|
||||||
|
var hasSwitchJob = switchebleService &&
|
||||||
|
jobState is JobsStateWithJobs &&
|
||||||
|
jobState.jobList
|
||||||
|
.any((el) => el is ServiceToggleJob && el.type == serviceType);
|
||||||
|
|
||||||
|
var isSwithOn = isReady &&
|
||||||
|
(!switchableServices.contains(serviceType) ||
|
||||||
|
serviceState.isEnableByType(serviceType));
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: isReady
|
onTap: isSwithOn
|
||||||
? () => showDialog<void>(
|
? () => showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
// isScrollControlled: true,
|
// isScrollControlled: true,
|
||||||
|
@ -117,9 +104,9 @@ class _Card extends StatelessWidget {
|
||||||
return _ServiceDetails(
|
return _ServiceDetails(
|
||||||
serviceType: serviceType,
|
serviceType: serviceType,
|
||||||
status:
|
status:
|
||||||
isReady ? StateType.stable : StateType.uninitialized,
|
isSwithOn ? StateType.stable : StateType.uninitialized,
|
||||||
title: title,
|
title: serviceType.title,
|
||||||
icon: iconData,
|
icon: serviceType.icon,
|
||||||
changeTab: changeTab,
|
changeTab: changeTab,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -128,33 +115,84 @@ class _Card extends StatelessWidget {
|
||||||
child: BrandCards.big(
|
child: BrandCards.big(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
children: [
|
children: [
|
||||||
IconStatusMask(
|
IconStatusMask(
|
||||||
status: isReady ? StateType.stable : StateType.uninitialized,
|
status:
|
||||||
child: Icon(iconData, size: 30, color: Colors.white),
|
isSwithOn ? StateType.stable : StateType.uninitialized,
|
||||||
|
child: Icon(serviceType.icon, size: 30, color: Colors.white),
|
||||||
),
|
),
|
||||||
|
if (isReady && switchebleService) ...[
|
||||||
|
Spacer(),
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
late bool isActive;
|
||||||
|
if (hasSwitchJob) {
|
||||||
|
isActive = ((jobState as JobsStateWithJobs)
|
||||||
|
.jobList
|
||||||
|
.firstWhere((el) =>
|
||||||
|
el is ServiceToggleJob &&
|
||||||
|
el.type == serviceType) as ServiceToggleJob)
|
||||||
|
.needToTurnOn;
|
||||||
|
} else {
|
||||||
|
isActive = serviceState.isEnableByType(serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BrandSwitch(
|
||||||
|
value: isActive,
|
||||||
|
onChanged: (value) =>
|
||||||
|
jobsCubit.createOrRemoveServiceToggleJob(
|
||||||
|
ServiceToggleJob(
|
||||||
|
type: serviceType,
|
||||||
|
needToTurnOn: value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ClipRect(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
BrandText.h2(title),
|
BrandText.h2(serviceType.title),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
BrandText.body2(subtitle),
|
BrandText.body2(serviceType.subtitle),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (hasSwitchJob)
|
||||||
|
Positioned(
|
||||||
|
bottom: 30,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(
|
||||||
|
sigmaX: 3,
|
||||||
|
sigmaY: 2,
|
||||||
|
),
|
||||||
|
child: BrandText.h2(
|
||||||
|
'jobs.runJobs'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ServiceTypes {
|
|
||||||
mail,
|
|
||||||
messenger,
|
|
||||||
passwordManager,
|
|
||||||
video,
|
|
||||||
cloud,
|
|
||||||
socialNetwork,
|
|
||||||
git,
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ServiceDetails extends StatelessWidget {
|
class _ServiceDetails extends StatelessWidget {
|
||||||
const _ServiceDetails({
|
const _ServiceDetails({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -353,7 +391,12 @@ class _ServiceDetails extends StatelessWidget {
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
|
case ServiceTypes.vpn:
|
||||||
|
child = Text(
|
||||||
|
'services.vpn.bottom_sheet.1'.tr(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Dialog(
|
return Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
@ -413,252 +456,3 @@ class _ServiceDetails extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// class _ServiceDetails extends StatelessWidget {
|
|
||||||
// const _ServiceDetails({
|
|
||||||
// Key? key,
|
|
||||||
// required this.serviceType,
|
|
||||||
// required this.icon,
|
|
||||||
// required this.status,
|
|
||||||
// required this.title,
|
|
||||||
// required this.changeTab,
|
|
||||||
// }) : super(key: key);
|
|
||||||
|
|
||||||
// final ServiceTypes serviceType;
|
|
||||||
// final IconData icon;
|
|
||||||
// final StateType status;
|
|
||||||
// final String title;
|
|
||||||
// final ValueChanged<int> changeTab;
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context) {
|
|
||||||
// late Widget child;
|
|
||||||
|
|
||||||
// var config = context.watch<AppConfigCubit>().state;
|
|
||||||
// var domainName = UiHelpers.getDomainName(config);
|
|
||||||
|
|
||||||
// var linksStyle = body1Style.copyWith(
|
|
||||||
// fontSize: 15,
|
|
||||||
// color: Theme.of(context).brightness == Brightness.dark
|
|
||||||
// ? Colors.white
|
|
||||||
// : BrandColors.black,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// decoration: TextDecoration.underline,
|
|
||||||
// // height: 1.1,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// var textStyle = body1Style.copyWith(
|
|
||||||
// color: Theme.of(context).brightness == Brightness.dark
|
|
||||||
// ? Colors.white
|
|
||||||
// : BrandColors.black,
|
|
||||||
// );
|
|
||||||
// switch (serviceType) {
|
|
||||||
// case ServiceTypes.mail:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.mail.bottom_sheet.1'.tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// child: Text(
|
|
||||||
// 'services.mail.bottom_sheet.2'.tr(),
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// onTap: () {
|
|
||||||
// Navigator.of(context).pop();
|
|
||||||
// changeTab(2);
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.messenger:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.messenger.bottom_sheet.1'.tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.passwordManager:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.password_manager.bottom_sheet.1'
|
|
||||||
// .tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// onTap: () => _launchURL('https://password.$domainName'),
|
|
||||||
// child: Text(
|
|
||||||
// 'password.$domainName',
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.video:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.video.bottom_sheet.1'.tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// onTap: () => _launchURL('https://meet.$domainName'),
|
|
||||||
// child: Text(
|
|
||||||
// 'meet.$domainName',
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.cloud:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.cloud.bottom_sheet.1'.tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// onTap: () => _launchURL('https://cloud.$domainName'),
|
|
||||||
// child: Text(
|
|
||||||
// 'cloud.$domainName',
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.socialNetwork:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.social_network.bottom_sheet.1'
|
|
||||||
// .tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// onTap: () => _launchURL('https://social.$domainName'),
|
|
||||||
// child: Text(
|
|
||||||
// 'social.$domainName',
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// case ServiceTypes.git:
|
|
||||||
// child = RichText(
|
|
||||||
// text: TextSpan(
|
|
||||||
// children: [
|
|
||||||
// TextSpan(
|
|
||||||
// text: 'services.git.bottom_sheet.1'.tr(args: [domainName]),
|
|
||||||
// style: textStyle,
|
|
||||||
// ),
|
|
||||||
// WidgetSpan(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: EdgeInsets.only(bottom: 0.8, left: 5),
|
|
||||||
// child: GestureDetector(
|
|
||||||
// onTap: () => _launchURL('https://git.$domainName'),
|
|
||||||
// child: Text(
|
|
||||||
// 'git.$domainName',
|
|
||||||
// style: linksStyle,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return BrandModalSheet(
|
|
||||||
// child: Navigator(
|
|
||||||
// key: navigatorKey,
|
|
||||||
// initialRoute: '/',
|
|
||||||
// onGenerateRoute: (_) {
|
|
||||||
// return materialRoute(
|
|
||||||
// Column(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
// children: [
|
|
||||||
// Padding(
|
|
||||||
// padding: brandPagePadding1,
|
|
||||||
// child: Column(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
// children: [
|
|
||||||
// SizedBox(height: 13),
|
|
||||||
// IconStatusMask(
|
|
||||||
// status: status,
|
|
||||||
// child: Icon(icon, size: 40, color: Colors.white),
|
|
||||||
// ),
|
|
||||||
// SizedBox(height: 10),
|
|
||||||
// BrandText.h1(title),
|
|
||||||
// SizedBox(height: 10),
|
|
||||||
// child,
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void _launchURL(url) async {
|
|
||||||
// var _possible = await canLaunch(url);
|
|
||||||
|
|
||||||
// if (_possible) {
|
|
||||||
// try {
|
|
||||||
// await launch(
|
|
||||||
// url,
|
|
||||||
// forceSafariVC: true,
|
|
||||||
// enableJavaScript: true,
|
|
||||||
// );
|
|
||||||
// } catch (e) {
|
|
||||||
// print(e);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// throw 'Could not launch $url';
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/user/user_form_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/jobs/job.dart';
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||||
|
|
|
@ -1,138 +1,99 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
var generator = PasswordGenerator();
|
Random _rnd = Random();
|
||||||
|
|
||||||
String genPass() {
|
typedef StringGeneratorFunction = String Function();
|
||||||
generator.generate(8);
|
|
||||||
return generator.getGeneratedValue();
|
class StringGenerators {
|
||||||
}
|
static const letters = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
|
static const numbers = '1234567890';
|
||||||
///Generates a password.
|
static const symbols = '_';
|
||||||
///
|
|
||||||
///The password [_generatedValue] is of a specified length, including letters [_letterGen] of mixed cases,
|
static String getRandomString(
|
||||||
///numbers [_numGen], and symbols[_symGen] depending on user choice.
|
int length, {
|
||||||
class PasswordGenerator {
|
hasLowercaseLetters = false,
|
||||||
late bool _letterGen;
|
hasUppercaseLetters = false,
|
||||||
late bool _numGen;
|
hasNumbers = false,
|
||||||
late bool _symGen;
|
hasSymbols = false,
|
||||||
late String _generatedValue;
|
isStrict = false,
|
||||||
|
}) {
|
||||||
///Constructor.
|
var chars = '';
|
||||||
///
|
if (hasLowercaseLetters) chars += letters;
|
||||||
///[_letterGen] is true to make password generation possible from the opening of the application, and
|
if (hasUppercaseLetters) chars += letters.toUpperCase();
|
||||||
///[_generatedValue] is intialized to the value below so the text containing it can be first generated
|
if (hasNumbers) chars += numbers;
|
||||||
///upon users request
|
if (hasSymbols) chars += symbols;
|
||||||
PasswordGenerator() {
|
|
||||||
_letterGen = true;
|
assert(chars.isNotEmpty, 'chart empty');
|
||||||
_numGen = true;
|
|
||||||
_symGen = false;
|
if (!isStrict) {
|
||||||
_generatedValue = "Press Generate";
|
return genString(length, chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Call to generate a value, of [n] length
|
var res = '';
|
||||||
void generate(int n) {
|
var loose = length;
|
||||||
//Discards the old value
|
if (hasLowercaseLetters) {
|
||||||
_generatedValue = "";
|
loose -= 1;
|
||||||
|
res += genString(1, letters);
|
||||||
///Cannot generate a value without any character types selected
|
}
|
||||||
if (!_letterGen && !_numGen && !_symGen) {
|
if (hasUppercaseLetters) {
|
||||||
_generatedValue = "No character type selected";
|
loose -= 1;
|
||||||
return;
|
res += genString(1, letters.toUpperCase());
|
||||||
}
|
}
|
||||||
|
if (hasNumbers) {
|
||||||
///'Randomly' selectes caracter type to generate and append [toAppend] to [_generatedValue]
|
loose -= 1;
|
||||||
// ignore: unnecessary_statements
|
res += genString(1, numbers.toUpperCase());
|
||||||
for (n; n > 0; n--) {
|
}
|
||||||
String? toAppend;
|
if (hasSymbols) {
|
||||||
var random = new Random();
|
loose -= 1;
|
||||||
|
res += genString(1, symbols);
|
||||||
///loops until a valid character is generated, meaning the user has to check the character value
|
}
|
||||||
///to be generated. 'Randomly' picks a character type.
|
res += genString(loose, chars);
|
||||||
while (toAppend == null) {
|
|
||||||
int selector = random.nextInt(3);
|
var shuffledlist = res.split('')..shuffle();
|
||||||
|
return shuffledlist.join();
|
||||||
if (selector == 0) {
|
}
|
||||||
toAppend = _generateLetter();
|
|
||||||
} else if (selector == 1) {
|
static String genString(int length, String chars) {
|
||||||
toAppend = _generateNumber();
|
return String.fromCharCodes(
|
||||||
} else {
|
Iterable.generate(
|
||||||
toAppend = _generateSymbol();
|
length,
|
||||||
}
|
(_) => chars.codeUnitAt(
|
||||||
}
|
_rnd.nextInt(chars.length),
|
||||||
|
),
|
||||||
_generatedValue += toAppend;
|
),
|
||||||
toAppend = null;
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
static StringGeneratorFunction userPassword = () => getRandomString(
|
||||||
///Generates a letter when called.
|
8,
|
||||||
String _generateLetter() {
|
hasLowercaseLetters: true,
|
||||||
if (!_letterGen) return '';
|
hasUppercaseLetters: true,
|
||||||
|
hasNumbers: true,
|
||||||
///Finds the integer value for the range between a-z and A-Z, with [base] UTF-16 value for lowercase letters and
|
isStrict: true,
|
||||||
///[baseUpper] UTF-16 value for uppercase letters
|
);
|
||||||
int base = "a".codeUnitAt(0);
|
|
||||||
int baseUpper = "A".codeUnitAt(0);
|
static StringGeneratorFunction passwordSalt = () => getRandomString(
|
||||||
int maxRand = ("z".codeUnitAt(0) - base) + 1;
|
8,
|
||||||
Random random = new Random();
|
hasLowercaseLetters: true,
|
||||||
|
);
|
||||||
///Randomly selects between upper and lower case generation, randomly generates value from [maxRand], then adding base,
|
|
||||||
///which creates a UTF-16 encoded character to be converted into a string of one character between a-z/A-Z.
|
static StringGeneratorFunction simpleId = () => getRandomString(
|
||||||
///This string is then returned.
|
5,
|
||||||
if (random.nextInt(2) == 0) {
|
hasLowercaseLetters: true,
|
||||||
return String.fromCharCodes([random.nextInt(maxRand) + base]);
|
);
|
||||||
} else {
|
|
||||||
return String.fromCharCodes([random.nextInt(maxRand) + baseUpper]);
|
static StringGeneratorFunction dbPassword = () => getRandomString(
|
||||||
}
|
40,
|
||||||
}
|
hasLowercaseLetters: true,
|
||||||
|
hasUppercaseLetters: true,
|
||||||
///Generates a number when called
|
hasNumbers: true,
|
||||||
String? _generateNumber() {
|
hasSymbols: true,
|
||||||
if (!_numGen) return null;
|
);
|
||||||
|
|
||||||
///Finds the integer value for the range between 0-9
|
static StringGeneratorFunction dbStorageName = () => getRandomString(
|
||||||
int base = "0".codeUnitAt(0);
|
6,
|
||||||
int maxRand = ("9".codeUnitAt(0) - base) + 1;
|
hasLowercaseLetters: true,
|
||||||
Random random = new Random();
|
hasUppercaseLetters: true,
|
||||||
|
hasNumbers: true,
|
||||||
///Randomly generates value from [maxRand], then adding base, which creates a UTF-16 encoded character to be converted into a
|
);
|
||||||
///string of one character between 0-9. This string is then returned.
|
|
||||||
return String.fromCharCodes([random.nextInt(maxRand) + base]);
|
|
||||||
}
|
|
||||||
|
|
||||||
///Generates a symbol when called
|
|
||||||
String? _generateSymbol() {
|
|
||||||
if (!_symGen) return null;
|
|
||||||
|
|
||||||
///Finds the integer value for the range between symbols !-.
|
|
||||||
|
|
||||||
///(note) which includes symbols !"#$%&'()*+,=.
|
|
||||||
int base = "!".codeUnitAt(0);
|
|
||||||
int maxRand = (".".codeUnitAt(0) - base) + 1;
|
|
||||||
Random random = new Random();
|
|
||||||
|
|
||||||
///Randomly generates value from [maxRand], then adding base, which creates a UTF-16 encoded character to be
|
|
||||||
///converted into a string of one character between !-. . This string is then returned.
|
|
||||||
return String.fromCharCodes([random.nextInt(maxRand) + base]);
|
|
||||||
}
|
|
||||||
|
|
||||||
///Toggles letter generation
|
|
||||||
void checkLetterGen(bool value) {
|
|
||||||
_letterGen = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Toggles number generation
|
|
||||||
void checkNumGen(bool value) {
|
|
||||||
_numGen = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Toggles symbol generation
|
|
||||||
void checkSymGen(bool value) {
|
|
||||||
_symGen = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Returns the generated value to be used by generator app
|
|
||||||
String getGeneratedValue() {
|
|
||||||
return _generatedValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
const _chars =
|
|
||||||
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890_';
|
|
||||||
Random _rnd = Random();
|
|
||||||
|
|
||||||
String getRandomString(int length, [chars = _chars]) => String.fromCharCodes(
|
|
||||||
Iterable.generate(
|
|
||||||
length,
|
|
||||||
(_) => chars.codeUnitAt(
|
|
||||||
_rnd.nextInt(chars.length),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
181
pubspec.lock
181
pubspec.lock
|
@ -14,7 +14,7 @@ packages:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.1"
|
version: "1.7.2"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -28,28 +28,35 @@ packages:
|
||||||
name: args
|
name: args
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.2.0"
|
||||||
|
asn1lib:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: asn1lib
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.2"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.6.1"
|
version: "2.8.1"
|
||||||
basic_utils:
|
basic_utils:
|
||||||
dependency: "direct dev"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: basic_utils
|
name: basic_utils
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.5.0"
|
||||||
bloc:
|
bloc:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: bloc
|
name: bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
version: "7.1.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -63,42 +70,42 @@ packages:
|
||||||
name: build
|
name: build
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.1.0"
|
||||||
build_config:
|
build_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_config
|
name: build_config
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.7"
|
version: "1.0.0"
|
||||||
build_daemon:
|
build_daemon:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_daemon
|
name: build_daemon
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.10"
|
version: "3.0.0"
|
||||||
build_resolvers:
|
build_resolvers:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.4"
|
||||||
build_runner:
|
build_runner:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.2"
|
version: "2.1.1"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_runner_core
|
name: build_runner_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.12"
|
version: "7.1.0"
|
||||||
built_collection:
|
built_collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -112,7 +119,7 @@ packages:
|
||||||
name: built_value
|
name: built_value
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.0"
|
version: "8.1.2"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -126,7 +133,7 @@ packages:
|
||||||
name: charcode
|
name: charcode
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.1"
|
||||||
checked_yaml:
|
checked_yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -140,7 +147,7 @@ packages:
|
||||||
name: cli_util
|
name: cli_util
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.3"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -154,7 +161,7 @@ packages:
|
||||||
name: code_builder
|
name: code_builder
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.0"
|
version: "4.1.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -168,7 +175,7 @@ packages:
|
||||||
name: convert
|
name: convert
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.1"
|
||||||
coverage:
|
coverage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -196,7 +203,7 @@ packages:
|
||||||
name: cubit_form
|
name: cubit_form
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.16"
|
version: "1.0.18"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -210,7 +217,7 @@ packages:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.3"
|
||||||
dio:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -259,7 +266,7 @@ packages:
|
||||||
name: extended_masked_text
|
name: extended_masked_text
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.3.1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -294,7 +301,7 @@ packages:
|
||||||
name: fl_chart
|
name: fl_chart
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.35.0"
|
version: "0.40.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -306,14 +313,14 @@ packages:
|
||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.1"
|
version: "7.2.0"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_launcher_icons
|
name: flutter_launcher_icons
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.0"
|
version: "0.9.2"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -325,14 +332,14 @@ packages:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.2"
|
version: "0.6.5"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_secure_storage
|
name: flutter_secure_storage
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.0"
|
version: "4.2.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -343,13 +350,20 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
get_it:
|
get_it:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: get_it
|
name: get_it
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.1"
|
version: "7.2.0"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -363,7 +377,7 @@ packages:
|
||||||
name: graphs
|
name: graphs
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "2.0.0"
|
||||||
hive:
|
hive:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -426,7 +440,7 @@ packages:
|
||||||
name: io
|
name: io
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.3"
|
||||||
ionicons:
|
ionicons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -454,7 +468,7 @@ packages:
|
||||||
name: json_serializable
|
name: json_serializable
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.3"
|
version: "4.1.4"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -482,7 +496,7 @@ packages:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.7.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -552,14 +566,14 @@ packages:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
path_provider_macos:
|
path_provider_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_macos
|
name: path_provider_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -573,7 +587,7 @@ packages:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.3"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -594,21 +608,21 @@ packages:
|
||||||
name: platform
|
name: platform
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.2"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: plugin_platform_interface
|
name: plugin_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.1"
|
||||||
pointycastle:
|
pointycastle:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: pointycastle
|
name: pointycastle
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.3.2"
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -629,14 +643,14 @@ packages:
|
||||||
name: process
|
name: process
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.1"
|
version: "4.2.3"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "6.0.0"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -651,6 +665,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
quiver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quiver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
rsa_encrypt:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: rsa_encrypt
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
share_plus:
|
share_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -664,7 +692,7 @@ packages:
|
||||||
name: share_plus_linux
|
name: share_plus_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.4"
|
||||||
share_plus_macos:
|
share_plus_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -699,21 +727,21 @@ packages:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.0.7"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_linux
|
name: shared_preferences_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
shared_preferences_macos:
|
shared_preferences_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_macos
|
name: shared_preferences_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
shared_preferences_platform_interface:
|
shared_preferences_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -727,21 +755,21 @@ packages:
|
||||||
name: shared_preferences_web
|
name: shared_preferences_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
shared_preferences_windows:
|
shared_preferences_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_windows
|
name: shared_preferences_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf
|
name: shelf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.4"
|
version: "1.2.0"
|
||||||
shelf_packages_handler:
|
shelf_packages_handler:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -755,7 +783,7 @@ packages:
|
||||||
name: shelf_static
|
name: shelf_static
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
shelf_web_socket:
|
shelf_web_socket:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -774,14 +802,14 @@ packages:
|
||||||
name: source_gen
|
name: source_gen
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.3"
|
||||||
source_helper:
|
source_helper:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_helper
|
name: source_helper
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.1"
|
||||||
source_map_stack_trace:
|
source_map_stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -803,6 +831,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.1"
|
version: "1.8.1"
|
||||||
|
ssh_key:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: ssh_key
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -844,21 +879,21 @@ packages:
|
||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.8"
|
version: "1.17.10"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.4.2"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.19"
|
version: "0.4.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -866,6 +901,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
tuple:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: tuple
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -873,55 +915,48 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
unicons:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: unicons
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
url_launcher:
|
url_launcher:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.6"
|
version: "6.0.9"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_linux
|
name: url_launcher_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.1"
|
||||||
url_launcher_macos:
|
url_launcher_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_macos
|
name: url_launcher_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.1"
|
||||||
url_launcher_platform_interface:
|
url_launcher_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_platform_interface
|
name: url_launcher_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.4"
|
||||||
url_launcher_web:
|
url_launcher_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_web
|
name: url_launcher_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.4"
|
||||||
url_launcher_windows:
|
url_launcher_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_windows
|
name: url_launcher_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.2"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -942,35 +977,35 @@ packages:
|
||||||
name: wakelock
|
name: wakelock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.2"
|
version: "0.5.3+3"
|
||||||
wakelock_macos:
|
wakelock_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_macos
|
name: wakelock_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0+1"
|
version: "0.1.0+2"
|
||||||
wakelock_platform_interface:
|
wakelock_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_platform_interface
|
name: wakelock_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1+1"
|
version: "0.2.1+2"
|
||||||
wakelock_web:
|
wakelock_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_web
|
name: wakelock_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0+1"
|
version: "0.2.0+2"
|
||||||
wakelock_windows:
|
wakelock_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_windows
|
name: wakelock_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0"
|
version: "0.1.0+1"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -998,7 +1033,7 @@ packages:
|
||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.2.7"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1021,5 +1056,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.13.0 <3.0.0"
|
dart: ">=2.13.4 <3.0.0"
|
||||||
flutter: ">=2.0.0"
|
flutter: ">=2.2.3"
|
||||||
|
|
24
pubspec.yaml
24
pubspec.yaml
|
@ -4,8 +4,8 @@ publish_to: 'none'
|
||||||
version: 0.1.3+5
|
version: 0.1.3+5
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.13.4 <3.0.0'
|
||||||
flutter: ">=2.0.0"
|
flutter: ">=2.2.3"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
@ -16,31 +16,33 @@ dependencies:
|
||||||
dio: ^4.0.0-beta7
|
dio: ^4.0.0-beta7
|
||||||
easy_localization: ^3.0.0
|
easy_localization: ^3.0.0
|
||||||
either_option: ^2.0.1-dev.1
|
either_option: ^2.0.1-dev.1
|
||||||
equatable: ^2.0.0
|
equatable: ^2.0.3
|
||||||
fl_chart: ^0.35.0
|
fl_chart: ^0.40.0
|
||||||
flutter_bloc: ^7.0.0
|
flutter_bloc: ^7.1.0
|
||||||
flutter_markdown: ^0.6.0
|
flutter_markdown: ^0.6.0
|
||||||
flutter_secure_storage: ^4.1.0
|
flutter_secure_storage: ^4.1.0
|
||||||
get_it: ^6.0.0
|
get_it: ^7.2.0
|
||||||
hive: ^2.0.0
|
hive: ^2.0.0
|
||||||
hive_flutter: ^1.0.0
|
hive_flutter: ^1.0.0
|
||||||
ionicons: ^0.1.2
|
|
||||||
json_annotation: ^4.0.0
|
json_annotation: ^4.0.0
|
||||||
modal_bottom_sheet: ^2.0.0
|
modal_bottom_sheet: ^2.0.0
|
||||||
nanoid: ^1.0.0
|
nanoid: ^1.0.0
|
||||||
package_info: ^2.0.0
|
package_info: ^2.0.0
|
||||||
pretty_dio_logger: ^1.1.1
|
pretty_dio_logger: ^1.1.1
|
||||||
provider: ^5.0.0
|
provider: ^6.0.0
|
||||||
share_plus: ^2.1.4
|
share_plus: ^2.1.4
|
||||||
unicons: ^1.0.2
|
|
||||||
url_launcher: ^6.0.2
|
url_launcher: ^6.0.2
|
||||||
wakelock: ^0.5.0+2
|
wakelock: ^0.5.0+2
|
||||||
|
basic_utils: ^3.4.0
|
||||||
|
ionicons: ^0.1.2
|
||||||
|
pointycastle: ^3.3.2
|
||||||
|
rsa_encrypt: ^2.0.0
|
||||||
|
ssh_key: ^0.7.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
basic_utils: ^3.0.0-nullsafety.1
|
build_runner: ^2.1.1
|
||||||
build_runner: ^1.11.5
|
|
||||||
flutter_launcher_icons: ^0.9.0
|
flutter_launcher_icons: ^0.9.0
|
||||||
hive_generator: ^1.0.0
|
hive_generator: ^1.0.0
|
||||||
json_serializable: ^4.0.2
|
json_serializable: ^4.0.2
|
||||||
|
|
|
@ -1,30 +1,122 @@
|
||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility that Flutter provides. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:selfprivacy/main.dart';
|
import 'package:selfprivacy/utils/password_generator.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
group('StringGenerators', () {
|
||||||
// Build our app and trigger a frame.
|
group('Basic', () {
|
||||||
await tester.pumpWidget(MyApp());
|
test('assert chart empty', () {
|
||||||
|
expect(() {
|
||||||
|
StringGenerators.getRandomString(8);
|
||||||
|
}, throwsAssertionError);
|
||||||
|
});
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
test('only lowercase string', () {
|
||||||
expect(find.text('0'), findsOneWidget);
|
var length = 8;
|
||||||
expect(find.text('1'), findsNothing);
|
var generatedString =
|
||||||
|
StringGenerators.getRandomString(length, hasLowercaseLetters: true);
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
await tester.pump();
|
expect(generatedString, isNot(matches(regExpNumbers)));
|
||||||
|
expect(generatedString, isNot(matches(regExpUppercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpSymbols)));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
expect(generatedString, matches(regExpLowercaseLetters));
|
||||||
|
});
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
test('only uppercase string', () {
|
||||||
expect(find.text('0'), findsNothing);
|
var length = 8;
|
||||||
expect(find.text('1'), findsOneWidget);
|
var generatedString = StringGenerators.getRandomString(length,
|
||||||
|
hasLowercaseLetters: false, hasUppercaseLetters: true);
|
||||||
|
|
||||||
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
|
expect(generatedString, isNot(matches(regExpNumbers)));
|
||||||
|
expect(generatedString, isNot(matches(regExpLowercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpSymbols)));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
expect(generatedString, matches(regExpUppercaseLetters));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('only numbers string', () {
|
||||||
|
var length = 8;
|
||||||
|
var generatedString = StringGenerators.getRandomString(length,
|
||||||
|
hasLowercaseLetters: false,
|
||||||
|
hasUppercaseLetters: false,
|
||||||
|
hasNumbers: true);
|
||||||
|
|
||||||
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
|
expect(generatedString, isNot(matches(regExpUppercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpLowercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpSymbols)));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
expect(generatedString, matches(regExpNumbers));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('only symbols string', () {
|
||||||
|
var length = 8;
|
||||||
|
var generatedString = StringGenerators.getRandomString(
|
||||||
|
length,
|
||||||
|
hasLowercaseLetters: false,
|
||||||
|
hasUppercaseLetters: false,
|
||||||
|
hasNumbers: false,
|
||||||
|
hasSymbols: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
|
expect(generatedString, isNot(matches(regExpUppercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpLowercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpNumbers)));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
expect(generatedString, matches(regExpSymbols));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Strict mode', () {
|
||||||
|
test('All', () {
|
||||||
|
var length = 5;
|
||||||
|
var generatedString = StringGenerators.getRandomString(length,
|
||||||
|
hasLowercaseLetters: true,
|
||||||
|
hasUppercaseLetters: true,
|
||||||
|
hasNumbers: true,
|
||||||
|
hasSymbols: true,
|
||||||
|
isStrict: true);
|
||||||
|
|
||||||
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
|
expect(generatedString, matches(regExpLowercaseLetters));
|
||||||
|
expect(generatedString, matches(regExpUppercaseLetters));
|
||||||
|
expect(generatedString, matches(regExpNumbers));
|
||||||
|
expect(generatedString, matches(regExpSymbols));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
});
|
||||||
|
test('Lowercase letters and numbers', () {
|
||||||
|
var length = 3;
|
||||||
|
var generatedString = StringGenerators.getRandomString(length,
|
||||||
|
hasLowercaseLetters: true,
|
||||||
|
hasUppercaseLetters: false,
|
||||||
|
hasNumbers: true,
|
||||||
|
hasSymbols: false,
|
||||||
|
isStrict: true);
|
||||||
|
|
||||||
|
expect(generatedString, isNot(matches(regExpNewLines)));
|
||||||
|
expect(generatedString, isNot(matches(regExpWhiteSpaces)));
|
||||||
|
expect(generatedString, isNot(matches(regExpUppercaseLetters)));
|
||||||
|
expect(generatedString, isNot(matches(regExpSymbols)));
|
||||||
|
expect(generatedString, matches(regExpLowercaseLetters));
|
||||||
|
expect(generatedString, matches(regExpNumbers));
|
||||||
|
expect(generatedString.length, equals(length));
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var regExpNewLines = RegExp(r"[\n\r]+");
|
||||||
|
var regExpWhiteSpaces = RegExp(r"[\s]+");
|
||||||
|
var regExpUppercaseLetters = RegExp(r"[A-Z]");
|
||||||
|
var regExpLowercaseLetters = RegExp(r"[a-z]");
|
||||||
|
var regExpNumbers = RegExp(r"[0-9]");
|
||||||
|
var regExpSymbols = RegExp(r'(?:_|[^\w\s])+');
|
||||||
|
|
Loading…
Reference in a new issue