service-states (#65)

Co-authored-by: Kherel <kherel@gmail.com>
Reviewed-on: kherel/selfprivacy.org.app#65
Co-authored-by: kherel <kherel@gmail.com>
Co-committed-by: kherel <kherel@gmail.com>
fdroid
kherel 2021-09-29 16:08:19 +03:00
parent a7e7d0ff05
commit 3e7d003f21
43 changed files with 372 additions and 680 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
ios/build
# Miscellaneous # Miscellaneous
*.class *.class
*.log *.log
@ -29,7 +30,7 @@
.packages .packages
.pub-cache/ .pub-cache/
.pub/ .pub/
/build/ **/build/
# Web related # Web related
lib/generated_plugin_registrant.dart lib/generated_plugin_registrant.dart

View File

@ -51,7 +51,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd local_auth: ef62030a2731330b95df7ef1331bd15f6a64b8a6
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68

View File

@ -345,7 +345,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -360,7 +360,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = UVNTKR53DD; DEVELOPMENT_TEAM = UVNTKR53DD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -380,6 +380,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };
name = Profile; name = Profile;
@ -432,7 +433,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -482,7 +483,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -499,7 +500,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = UVNTKR53DD; DEVELOPMENT_TEAM = UVNTKR53DD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -520,6 +521,7 @@
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };
name = Debug; name = Debug;
@ -530,7 +532,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = UVNTKR53DD; DEVELOPMENT_TEAM = UVNTKR53DD;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
@ -550,6 +552,7 @@
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
}; };
name = Release; name = Release;

View File

@ -2,11 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleLocalizations</key>
<array>
<string>ru</string>
<string>en</string>
</array>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -15,6 +10,11 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>ru</string>
<string>en</string>
</array>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>selfprivacy</string> <string>selfprivacy</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
@ -24,7 +24,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
@ -34,8 +34,6 @@
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UISupportedInterfaceOrientations~ipad</key> <key>UISupportedInterfaceOrientations~ipad</key>
<array> <array>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -16,7 +16,8 @@ class BlocAndProviderConfig extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isDark = false; var isDark = false;
var usersCubit = UsersCubit(); var usersCubit = UsersCubit();
var servicesCubit = ServicesCubit(); var appConfigCubit = AppConfigCubit()..load();
var servicesCubit = ServicesCubit(appConfigCubit);
return MultiProvider( return MultiProvider(
providers: [ providers: [
BlocProvider( BlocProvider(
@ -25,18 +26,13 @@ class BlocAndProviderConfig extends StatelessWidget {
isOnbordingShowing: true, isOnbordingShowing: true,
)..load(), )..load(),
), ),
BlocProvider( BlocProvider(lazy: false, create: (_) => appConfigCubit),
lazy: false,
create: (_) => AppConfigCubit(servicesCubit)..load(),
),
BlocProvider(create: (_) => ProvidersCubit()), BlocProvider(create: (_) => ProvidersCubit()),
BlocProvider(create: (_) => usersCubit..load(), lazy: false), BlocProvider(create: (_) => usersCubit..load(), lazy: false),
BlocProvider(create: (_) => servicesCubit..load(), lazy: false), BlocProvider(create: (_) => servicesCubit..load(), lazy: false),
BlocProvider( BlocProvider(
create: (_) => JobsCubit( create: (_) =>
usersCubit: usersCubit, JobsCubit(usersCubit: usersCubit, servicesCubit: servicesCubit),
servicesCubit: servicesCubit,
),
), ),
], ],
child: child, child: child,

View File

@ -94,7 +94,7 @@ class HetznerApi extends ApiMap {
/// check the branch name, it could be "development" or "master". /// 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} 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/development/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',

View File

@ -105,6 +105,20 @@ class ServerApi extends ApiMap {
); );
client.close(); client.close();
} }
Future<Map<ServiceTypes, bool>> servicesPowerCheck() async {
var client = await getClient();
Response response = await client.get('/services/status');
close(client);
return {
ServiceTypes.passwordManager: response.data['bitwarden'] == 0,
ServiceTypes.git: response.data['gitea'] == 0,
ServiceTypes.cloud: response.data['nextcloud'] == 0,
ServiceTypes.vpn: response.data['ocserv'] == 0,
ServiceTypes.socialNetwork: response.data['pleroma'] == 0,
};
}
} }
extension UrlServerExt on ServiceTypes { extension UrlServerExt on ServiceTypes {

View File

@ -3,7 +3,6 @@ import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/get_it/ssh.dart'; import 'package:selfprivacy/logic/get_it/ssh.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';
@ -46,32 +45,35 @@ 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(this.servicesCubit) : super(InitialAppConfigState()); AppConfigCubit() : super(AppConfigEmpty());
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();
if (state.progress < 6 || state.isFullyInitilized) { if (state is AppConfigFinished) {
emit(state); emit(state);
} else if (state.progress == 6) { } else if (state is AppConfigNotFinished) {
startServerIfDnsIsOkay(state: state, isImmediate: true); if (state.progress == 6) {
} else if (state.progress == 7) { startServerIfDnsIsOkay(state: state, isImmediate: true);
resetServerIfServerIsOkay(state: state, isImmediate: true); } else if (state.progress == 7) {
} else if (state.progress == 8) { resetServerIfServerIsOkay(state: state, isImmediate: true);
oneMoreReset(state: state, isImmediate: true); } else if (state.progress == 8) {
} else if (state.progress == 9) { oneMoreReset(state: state, isImmediate: true);
finishCheckIfServerIsOkay(state: state, isImmediate: true); } else if (state.progress == 9) {
finishCheckIfServerIsOkay(state: state, isImmediate: true);
}
} else {
throw 'wrong state';
} }
} }
void startServerIfDnsIsOkay({ void startServerIfDnsIsOkay({
AppConfigState? state, AppConfigNotFinished? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
state = state ?? this.state; state = state ?? this.state as AppConfigNotFinished;
final work = () async { final work = () async {
emit(TimerState(dataState: state!, isLoading: true)); emit(TimerState(dataState: state!, isLoading: true));
@ -116,10 +118,10 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void oneMoreReset({ void oneMoreReset({
AppConfigState? state, AppConfigNotFinished? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
var dataState = state ?? this.state; var dataState = state ?? this.state as AppConfigNotFinished;
var work = () async { var work = () async {
emit(TimerState(dataState: dataState, isLoading: true)); emit(TimerState(dataState: dataState, isLoading: true));
@ -169,10 +171,10 @@ class AppConfigCubit extends Cubit<AppConfigState> {
} }
void resetServerIfServerIsOkay({ void resetServerIfServerIsOkay({
AppConfigState? state, AppConfigNotFinished? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
var dataState = state ?? this.state; var dataState = state ?? this.state as AppConfigNotFinished;
var work = () async { var work = () async {
emit(TimerState(dataState: dataState, isLoading: true)); emit(TimerState(dataState: dataState, isLoading: true));
@ -224,10 +226,10 @@ class AppConfigCubit extends Cubit<AppConfigState> {
Timer? timer; Timer? timer;
void finishCheckIfServerIsOkay({ void finishCheckIfServerIsOkay({
AppConfigState? state, AppConfigNotFinished? state,
bool isImmediate = false, bool isImmediate = false,
}) async { }) async {
state = state ?? this.state; state = state ?? this.state as AppConfigNotFinished;
var work = () async { var work = () async {
emit(TimerState(dataState: state!, isLoading: true)); emit(TimerState(dataState: state!, isLoading: true));
@ -236,12 +238,8 @@ class AppConfigCubit extends Cubit<AppConfigState> {
if (isServerWorking) { if (isServerWorking) {
await repository.saveHasFinalChecked(true); await repository.saveHasFinalChecked(true);
servicesCubit.allOn();
emit(state.copyWith( emit(state.finish());
hasFinalChecked: true,
isLoading: false,
));
} else { } else {
finishCheckIfServerIsOkay(); finishCheckIfServerIsOkay();
} }
@ -264,45 +262,31 @@ class AppConfigCubit extends Cubit<AppConfigState> {
void clearAppConfig() { void clearAppConfig() {
closeTimer(); closeTimer();
servicesCubit.allOff();
repository.clearAppConfig(); repository.clearAppConfig();
emit(InitialAppConfigState()); emit(AppConfigEmpty());
} }
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!);
await getIt<SSHModel>().clear(); await getIt<SSHModel>().clear();
} }
await repository.deleteRecords(); await repository.deleteRecords();
emit(AppConfigState( emit(AppConfigEmpty());
hetznerKey: state.hetznerKey,
cloudFlareKey: state.cloudFlareKey,
backblazeCredential: state.backblazeCredential,
cloudFlareDomain: state.cloudFlareDomain,
rootUser: state.rootUser,
hetznerServer: null,
isServerStarted: false,
isServerResetedFirstTime: false,
isServerResetedSecondTime: false,
hasFinalChecked: false,
isLoading: false,
error: null,
));
} }
void setHetznerKey(String hetznerKey) async { void setHetznerKey(String hetznerKey) async {
await repository.saveHetznerKey(hetznerKey); await repository.saveHetznerKey(hetznerKey);
emit(state.copyWith(hetznerKey: hetznerKey)); emit((state as AppConfigNotFinished).copyWith(hetznerKey: hetznerKey));
} }
void setCloudflareKey(String cloudFlareKey) async { void setCloudflareKey(String cloudFlareKey) async {
await repository.saveCloudFlareKey(cloudFlareKey); await repository.saveCloudFlareKey(cloudFlareKey);
emit(state.copyWith(cloudFlareKey: cloudFlareKey)); emit(
(state as AppConfigNotFinished).copyWith(cloudFlareKey: cloudFlareKey));
} }
void setBackblazeKey(String keyId, String applicationKey) async { void setBackblazeKey(String keyId, String applicationKey) async {
@ -311,38 +295,41 @@ class AppConfigCubit extends Cubit<AppConfigState> {
applicationKey: applicationKey, applicationKey: applicationKey,
); );
await repository.saveBackblazeKey(backblazeCredential); await repository.saveBackblazeKey(backblazeCredential);
emit(state.copyWith(backblazeCredential: backblazeCredential)); emit((state as AppConfigNotFinished)
.copyWith(backblazeCredential: backblazeCredential));
} }
void setDomain(CloudFlareDomain cloudFlareDomain) async { void setDomain(CloudFlareDomain cloudFlareDomain) async {
await repository.saveDomain(cloudFlareDomain); await repository.saveDomain(cloudFlareDomain);
emit(state.copyWith(cloudFlareDomain: cloudFlareDomain)); emit((state as AppConfigNotFinished)
.copyWith(cloudFlareDomain: cloudFlareDomain));
} }
void setRootUser(User rootUser) async { void setRootUser(User rootUser) async {
await repository.saveRootUser(rootUser); await repository.saveRootUser(rootUser);
emit(state.copyWith(rootUser: rootUser)); emit((state as AppConfigNotFinished).copyWith(rootUser: rootUser));
} }
void createServerAndSetDnsRecords() async { void createServerAndSetDnsRecords() async {
AppConfigState _stateCopy = state; AppConfigNotFinished _stateCopy = state as AppConfigNotFinished;
var onSuccess = (HetznerServerDetails serverDetails) async { var onSuccess = (HetznerServerDetails serverDetails) async {
await repository.createDnsRecords( await repository.createDnsRecords(
serverDetails.ip4, serverDetails.ip4,
state.cloudFlareDomain!, state.cloudFlareDomain!,
); );
emit(state.copyWith( emit((state as AppConfigNotFinished).copyWith(
isLoading: false, isLoading: false,
hetznerServer: serverDetails, hetznerServer: serverDetails,
)); ));
startServerIfDnsIsOkay(); startServerIfDnsIsOkay();
}; };
var onCancel = () => emit(state.copyWith(isLoading: false)); var onCancel =
() => emit((state as AppConfigNotFinished).copyWith(isLoading: false));
try { try {
emit(state.copyWith(isLoading: true)); emit((state as AppConfigNotFinished).copyWith(isLoading: true));
await repository.createServer( await repository.createServer(
state.rootUser!, state.rootUser!,
state.cloudFlareDomain!.domainName, state.cloudFlareDomain!.domainName,

View File

@ -22,22 +22,37 @@ class AppConfigRepository {
Box box = Hive.box(BNames.appConfig); Box box = Hive.box(BNames.appConfig);
Future<AppConfigState> load() async { Future<AppConfigState> load() async {
var res = AppConfigState( late AppConfigState res;
hetznerKey: getIt<ApiConfigModel>().hetznerKey, if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey, res = AppConfigFinished(
cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain, hetznerKey: getIt<ApiConfigModel>().hetznerKey!,
backblazeCredential: getIt<ApiConfigModel>().backblazeCredential, cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey!,
hetznerServer: getIt<ApiConfigModel>().hetznerServer, cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain!,
rootUser: box.get(BNames.rootUser), backblazeCredential: getIt<ApiConfigModel>().backblazeCredential!,
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false), hetznerServer: getIt<ApiConfigModel>().hetznerServer!,
isServerResetedFirstTime: rootUser: box.get(BNames.rootUser),
box.get(BNames.isServerResetedFirstTime, defaultValue: false), isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
isServerResetedSecondTime: isServerResetedFirstTime:
box.get(BNames.isServerResetedSecondTime, defaultValue: false), box.get(BNames.isServerResetedFirstTime, defaultValue: false),
hasFinalChecked: box.get(BNames.hasFinalChecked, defaultValue: false), isServerResetedSecondTime:
error: null, box.get(BNames.isServerResetedSecondTime, defaultValue: false),
isLoading: box.get(BNames.isLoading, defaultValue: false), );
); } else {
res = AppConfigNotFinished(
hetznerKey: getIt<ApiConfigModel>().hetznerKey,
cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey,
cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain,
backblazeCredential: getIt<ApiConfigModel>().backblazeCredential,
hetznerServer: getIt<ApiConfigModel>().hetznerServer,
rootUser: box.get(BNames.rootUser),
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
isServerResetedFirstTime:
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
isServerResetedSecondTime:
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
isLoading: box.get(BNames.isLoading, defaultValue: false),
);
}
return res; return res;
} }

View File

@ -11,9 +11,6 @@ class AppConfigState extends Equatable {
required this.isServerStarted, required this.isServerStarted,
required this.isServerResetedFirstTime, required this.isServerResetedFirstTime,
required this.isServerResetedSecondTime, required this.isServerResetedSecondTime,
required this.hasFinalChecked,
required this.isLoading,
required this.error,
}); });
@override @override
@ -26,9 +23,6 @@ class AppConfigState extends Equatable {
hetznerServer, hetznerServer,
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
hasFinalChecked,
isLoading,
error,
]; ];
final String? hetznerKey; final String? hetznerKey;
@ -41,42 +35,6 @@ class AppConfigState extends Equatable {
final bool isServerResetedFirstTime; final bool isServerResetedFirstTime;
final bool isServerResetedSecondTime; final bool isServerResetedSecondTime;
final bool hasFinalChecked;
final bool isLoading;
final Exception? error;
AppConfigState copyWith({
String? hetznerKey,
String? cloudFlareKey,
BackblazeCredential? backblazeCredential,
CloudFlareDomain? cloudFlareDomain,
User? rootUser,
HetznerServerDetails? hetznerServer,
bool? isServerStarted,
bool? isServerResetedFirstTime,
bool? isServerResetedSecondTime,
bool? hasFinalChecked,
bool? isLoading,
Exception? error,
}) =>
AppConfigState(
hetznerKey: hetznerKey ?? this.hetznerKey,
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
cloudFlareDomain: cloudFlareDomain ?? this.cloudFlareDomain,
rootUser: rootUser ?? this.rootUser,
hetznerServer: hetznerServer ?? this.hetznerServer,
isServerStarted: isServerStarted ?? this.isServerStarted,
isServerResetedFirstTime:
isServerResetedFirstTime ?? this.isServerResetedFirstTime,
isServerResetedSecondTime:
isServerResetedSecondTime ?? this.isServerResetedSecondTime,
hasFinalChecked: hasFinalChecked ?? this.hasFinalChecked,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
bool get isHetznerFilled => hetznerKey != null; bool get isHetznerFilled => hetznerKey != null;
bool get isCloudFlareFilled => cloudFlareKey != null; bool get isCloudFlareFilled => cloudFlareKey != null;
bool get isBackblazeFilled => backblazeCredential != null; bool get isBackblazeFilled => backblazeCredential != null;
@ -84,8 +42,8 @@ class AppConfigState extends Equatable {
bool get isUserFilled => rootUser != null; bool get isUserFilled => rootUser != null;
bool get isServerCreated => hetznerServer != null; bool get isServerCreated => hetznerServer != null;
bool get isFullyInitilized => _fulfilementList.every((el) => el!); // bool get isFullyInitilized => _fulfilementList.every((el) => el!);
int get progress => _fulfilementList.where((el) => el!).length ; int get progress => _fulfilementList.where((el) => el!).length;
int get porgressBar { int get porgressBar {
if (progress < 6) { if (progress < 6) {
@ -108,32 +66,13 @@ class AppConfigState extends Equatable {
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
isServerResetedSecondTime, isServerResetedSecondTime,
hasFinalChecked,
]; ];
return res; return res;
} }
} }
class InitialAppConfigState extends AppConfigState { class TimerState extends AppConfigNotFinished {
InitialAppConfigState()
: super(
hetznerKey: null,
cloudFlareKey: null,
backblazeCredential: null,
cloudFlareDomain: null,
rootUser: null,
hetznerServer: null,
isServerStarted: false,
isServerResetedFirstTime: false,
isServerResetedSecondTime: false,
hasFinalChecked: false,
isLoading: false,
error: null,
);
}
class TimerState extends AppConfigState {
TimerState({ TimerState({
required this.dataState, required this.dataState,
this.timerStart, this.timerStart,
@ -149,12 +88,10 @@ class TimerState extends AppConfigState {
isServerStarted: dataState.isServerStarted, isServerStarted: dataState.isServerStarted,
isServerResetedFirstTime: dataState.isServerResetedFirstTime, isServerResetedFirstTime: dataState.isServerResetedFirstTime,
isServerResetedSecondTime: dataState.isServerResetedSecondTime, isServerResetedSecondTime: dataState.isServerResetedSecondTime,
hasFinalChecked: dataState.hasFinalChecked,
isLoading: isLoading, isLoading: isLoading,
error: dataState.error,
); );
final AppConfigState dataState; final AppConfigNotFinished dataState;
final DateTime? timerStart; final DateTime? timerStart;
final Duration? duration; final Duration? duration;
@ -165,3 +102,134 @@ class TimerState extends AppConfigState {
duration, duration,
]; ];
} }
class AppConfigNotFinished extends AppConfigState {
final bool isLoading;
AppConfigNotFinished({
String? hetznerKey,
String? cloudFlareKey,
BackblazeCredential? backblazeCredential,
CloudFlareDomain? cloudFlareDomain,
User? rootUser,
HetznerServerDetails? hetznerServer,
required bool isServerStarted,
required bool isServerResetedFirstTime,
required bool isServerResetedSecondTime,
required this.isLoading,
}) : super(
hetznerKey: hetznerKey,
cloudFlareKey: cloudFlareKey,
backblazeCredential: backblazeCredential,
cloudFlareDomain: cloudFlareDomain,
rootUser: rootUser,
hetznerServer: hetznerServer,
isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime,
);
@override
List<Object?> get props => [
hetznerKey,
cloudFlareKey,
backblazeCredential,
cloudFlareDomain,
rootUser,
hetznerServer,
isServerStarted,
isServerResetedFirstTime,
isLoading
];
AppConfigNotFinished copyWith({
String? hetznerKey,
String? cloudFlareKey,
BackblazeCredential? backblazeCredential,
CloudFlareDomain? cloudFlareDomain,
User? rootUser,
HetznerServerDetails? hetznerServer,
bool? isServerStarted,
bool? isServerResetedFirstTime,
bool? isServerResetedSecondTime,
bool? isLoading,
}) =>
AppConfigNotFinished(
hetznerKey: hetznerKey ?? this.hetznerKey,
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
cloudFlareDomain: cloudFlareDomain ?? this.cloudFlareDomain,
rootUser: rootUser ?? this.rootUser,
hetznerServer: hetznerServer ?? this.hetznerServer,
isServerStarted: isServerStarted ?? this.isServerStarted,
isServerResetedFirstTime:
isServerResetedFirstTime ?? this.isServerResetedFirstTime,
isServerResetedSecondTime:
isServerResetedSecondTime ?? this.isServerResetedSecondTime,
isLoading: isLoading ?? this.isLoading,
);
AppConfigFinished finish() => AppConfigFinished(
hetznerKey: hetznerKey!,
cloudFlareKey: cloudFlareKey!,
backblazeCredential: backblazeCredential!,
cloudFlareDomain: cloudFlareDomain!,
rootUser: rootUser!,
hetznerServer: hetznerServer!,
isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime,
);
}
class AppConfigEmpty extends AppConfigNotFinished {
AppConfigEmpty()
: super(
hetznerKey: null,
cloudFlareKey: null,
backblazeCredential: null,
cloudFlareDomain: null,
rootUser: null,
hetznerServer: null,
isServerStarted: false,
isServerResetedFirstTime: false,
isServerResetedSecondTime: false,
isLoading: false,
);
}
class AppConfigFinished extends AppConfigState {
const AppConfigFinished({
required String hetznerKey,
required String cloudFlareKey,
required BackblazeCredential backblazeCredential,
required CloudFlareDomain cloudFlareDomain,
required User rootUser,
required HetznerServerDetails hetznerServer,
required bool isServerStarted,
required bool isServerResetedFirstTime,
required bool isServerResetedSecondTime,
}) : super(
hetznerKey: hetznerKey,
cloudFlareKey: cloudFlareKey,
backblazeCredential: backblazeCredential,
cloudFlareDomain: cloudFlareDomain,
rootUser: rootUser,
hetznerServer: hetznerServer,
isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime,
);
@override
List<Object?> get props => [
hetznerKey,
cloudFlareKey,
backblazeCredential,
cloudFlareDomain,
rootUser,
hetznerServer,
isServerStarted,
isServerResetedFirstTime,
];
}

View File

@ -0,0 +1,39 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
export 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
part 'authentication_dependend_state.dart';
abstract class AppConfigDependendCubit<T extends AppConfigDependendState>
extends Cubit<T> {
AppConfigDependendCubit(
this.appConfigCubit,
T initState,
) : super(initState) {
authCubitSubscription = appConfigCubit.stream.listen(checkAuthStatus);
checkAuthStatus(appConfigCubit.state);
}
void checkAuthStatus(AppConfigState state) {
if (state is AppConfigFinished) {
load();
} else if (state is AppConfigEmpty) {
clear();
}
}
late StreamSubscription authCubitSubscription;
final AppConfigCubit appConfigCubit;
void load();
void clear();
@override
Future<void> close() {
authCubitSubscription.cancel();
return super.close();
}
}

View File

@ -0,0 +1,5 @@
part of 'authentication_dependend_cubit.dart';
abstract class AppConfigDependendState extends Equatable {
const AppConfigDependendState();
}

View File

@ -1,8 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/config/text_themes.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/services/services_cubit.dart';
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart'; import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
@ -76,17 +73,14 @@ class JobsCubit extends Cubit<JobsState> {
var jobs = (state as JobsStateWithJobs).jobList; var jobs = (state as JobsStateWithJobs).jobList;
emit(JobsStateLoading()); emit(JobsStateLoading());
var newUsers = <User>[]; var newUsers = <User>[];
var hasServiceJobs = false;
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) { } else if (job is ServiceToggleJob) {
hasServiceJobs = true;
await api.switchService(job.type, job.needToTurnOn); await api.switchService(job.type, job.needToTurnOn);
if (job.needToTurnOn) {
servicesCubit.turnOnist([job.type]);
} else {
servicesCubit.turnOffList([job.type]);
}
} }
if (job is CreateSSHKeyJob) { if (job is CreateSSHKeyJob) {
await getIt<SSHModel>().generateKeys(); await getIt<SSHModel>().generateKeys();
@ -96,6 +90,9 @@ class JobsCubit extends Cubit<JobsState> {
usersCubit.addUsers(newUsers); usersCubit.addUsers(newUsers);
await api.apply(); await api.apply();
if (hasServiceJobs) {
await servicesCubit.load();
}
emit(JobsStateEmpty()); emit(JobsStateEmpty());

View File

@ -1,63 +1,34 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:selfprivacy/config/hive_config.dart'; import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/logic/api_maps/server.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.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_dependent/authentication_dependend_cubit.dart';
part 'services_state.dart'; part 'services_state.dart';
class ServicesCubit extends Cubit<ServicesState> { class ServicesCubit extends AppConfigDependendCubit<ServicesState> {
ServicesCubit() : super(ServicesState.allOff()); ServicesCubit(AppConfigCubit appConfigCubit)
: super(appConfigCubit, ServicesState.allOff());
Box box = Hive.box(BNames.servicesState); Box box = Hive.box(BNames.servicesState);
final api = ServerApi();
void load() { Future<void> load() async {
var statuses = await api.servicesPowerCheck();
emit( emit(
ServicesState( ServicesState(
isPasswordManagerEnable: isPasswordManagerEnable: statuses[ServiceTypes.passwordManager]!,
box.get(ServiceTypes.passwordManager.txt, defaultValue: false), isCloudEnable: statuses[ServiceTypes.cloud]!,
isCloudEnable: box.get(ServiceTypes.cloud.txt, defaultValue: false), isGitEnable: statuses[ServiceTypes.git]!,
isGitEnable: box.get(ServiceTypes.git.txt, defaultValue: false), isSocialNetworkEnable: statuses[ServiceTypes.socialNetwork]!,
isSocialNetworkEnable: isVpnEnable: statuses[ServiceTypes.vpn]!,
box.get(ServiceTypes.socialNetwork.txt, defaultValue: false),
isVpnEnable: box.get(ServiceTypes.vpn.txt, defaultValue: false),
), ),
); );
} }
void allOn() { @override
box.put(ServiceTypes.passwordManager.txt, true); void clear() async {
box.put(ServiceTypes.cloud.txt, true); box.clear();
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()); 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));
}
} }

View File

@ -1,6 +1,6 @@
part of 'services_cubit.dart'; part of 'services_cubit.dart';
class ServicesState extends Equatable { class ServicesState extends AppConfigDependendState {
const ServicesState({ const ServicesState({
required this.isPasswordManagerEnable, required this.isPasswordManagerEnable,
required this.isCloudEnable, required this.isCloudEnable,

View File

@ -40,7 +40,7 @@ class InitializingPage extends StatelessWidget {
][cubit.state.progress](); ][cubit.state.progress]();
return BlocListener<AppConfigCubit, AppConfigState>( return BlocListener<AppConfigCubit, AppConfigState>(
listener: (context, state) { listener: (context, state) {
if (state.isFullyInitilized) { if (cubit.state is AppConfigFinished) {
Navigator.of(context).pushReplacement(materialRoute(RootPage())); Navigator.of(context).pushReplacement(materialRoute(RootPage()));
} }
}, },
@ -80,7 +80,7 @@ class InitializingPage extends StatelessWidget {
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
child: BrandButton.text( child: BrandButton.text(
title: cubit.state.isFullyInitilized title: cubit.state is AppConfigFinished
? 'basis.close'.tr() ? 'basis.close'.tr()
: 'basis.later'.tr(), : 'basis.later'.tr(),
onPressed: () { onPressed: () {
@ -411,7 +411,7 @@ class InitializingPage extends StatelessWidget {
} }
Widget _stepServer(AppConfigCubit appConfigCubit) { Widget _stepServer(AppConfigCubit appConfigCubit) {
var isLoading = appConfigCubit.state.isLoading; var isLoading = (appConfigCubit.state as AppConfigNotFinished).isLoading;
return Builder(builder: (context) { return Builder(builder: (context) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -438,7 +438,7 @@ class InitializingPage extends StatelessWidget {
} }
Widget _stepCheck(AppConfigCubit appConfigCubit) { Widget _stepCheck(AppConfigCubit appConfigCubit) {
assert(appConfigCubit.state is TimerState, 'wronge state'); assert(appConfigCubit.state is AppConfigNotFinished, 'wronge state');
var state = appConfigCubit.state as TimerState; var state = appConfigCubit.state as TimerState;
late int doneCount; late int doneCount;
late String? text; late String? text;

View File

@ -36,7 +36,7 @@ class MorePage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var jobsCubit = context.watch<JobsCubit>(); var jobsCubit = context.watch<JobsCubit>();
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
return Scaffold( return Scaffold(
appBar: PreferredSize( appBar: PreferredSize(

View File

@ -28,7 +28,7 @@ class ProvidersPage extends StatefulWidget {
class _ProvidersPageState extends State<ProvidersPage> { class _ProvidersPageState extends State<ProvidersPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
final cards = ProviderType.values final cards = ProviderType.values
.map( .map(
@ -75,7 +75,7 @@ class _Card extends StatelessWidget {
String? message; String? message;
late String stableText; late String stableText;
late VoidCallback onTap; late VoidCallback onTap;
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
AppConfigState appConfig = context.watch<AppConfigCubit>().state; AppConfigState appConfig = context.watch<AppConfigCubit>().state;
var domainName = var domainName =

View File

@ -53,7 +53,7 @@ class _ServerDetailsState extends State<ServerDetails>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
var providerState = isReady ? StateType.stable : StateType.uninitialized; var providerState = isReady ? StateType.stable : StateType.uninitialized;
return Scaffold( return Scaffold(

View File

@ -41,7 +41,7 @@ class ServicesPage extends StatefulWidget {
class _ServicesPageState extends State<ServicesPage> { class _ServicesPageState extends State<ServicesPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
return Scaffold( return Scaffold(
appBar: PreferredSize( appBar: PreferredSize(
@ -77,7 +77,7 @@ class _Card extends StatelessWidget {
final ServiceTypes serviceType; final ServiceTypes serviceType;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
var changeTab = context.read<ChangeTab>().onPress; var changeTab = context.read<ChangeTab>().onPress;
var serviceState = context.watch<ServicesCubit>().state; var serviceState = context.watch<ServicesCubit>().state;

View File

@ -32,7 +32,7 @@ class UsersPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final usersCubitState = context.watch<UsersCubit>().state; final usersCubitState = context.watch<UsersCubit>().state;
var isReady = context.watch<AppConfigCubit>().state.isFullyInitilized; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
final users = usersCubitState.users; final users = usersCubitState.users;
final isEmpty = usersCubitState.isEmpty; final isEmpty = usersCubitState.isEmpty;
Widget child; Widget child;

View File

@ -28,7 +28,7 @@ packages:
name: args name: args
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.0" version: "2.0.0"
asn1lib: asn1lib:
dependency: transitive dependency: transitive
description: description:
@ -49,14 +49,14 @@ packages:
name: basic_utils name: basic_utils
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.5.0" version: "3.6.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.1.0" version: "7.2.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -91,14 +91,14 @@ packages:
name: build_resolvers name: build_resolvers
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.3"
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: "2.1.1" version: "2.1.2"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
@ -119,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.2" version: "8.1.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -147,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.3" version: "0.3.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -175,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.1" version: "3.0.0"
coverage: coverage:
dependency: transitive dependency: transitive
description: description:
@ -203,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.18" version: "1.0.16"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -217,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.3" version: "2.0.1"
dio: dio:
dependency: "direct main" dependency: "direct main"
description: description:
@ -266,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.3.1" version: "2.2.1"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -313,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.2.0" version: "7.3.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.2" version: "0.9.0"
flutter_localizations: flutter_localizations:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -332,7 +332,7 @@ packages:
name: flutter_markdown name: flutter_markdown
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.5" version: "0.6.2"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
@ -346,7 +346,7 @@ packages:
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.1" version: "4.2.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -384,7 +384,7 @@ packages:
name: graphs name: graphs
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
hive: hive:
dependency: "direct main" dependency: "direct main"
description: description:
@ -447,7 +447,7 @@ packages:
name: io name: io
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.0.0"
ionicons: ionicons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -475,14 +475,14 @@ packages:
name: json_serializable name: json_serializable
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.4" version: "4.1.3"
local_auth: local_auth:
dependency: "direct main" dependency: "direct main"
description: description:
name: local_auth name: local_auth
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.7" version: "1.1.8"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -580,14 +580,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.2" version: "2.0.0"
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.2" version: "2.0.0"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -601,7 +601,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.3" version: "2.0.1"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -622,21 +622,21 @@ packages:
name: platform name: platform
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.2" version: "3.0.0"
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.1" version: "2.0.0"
pointycastle: pointycastle:
dependency: "direct main" 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.3.2" version: "3.3.4"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -657,7 +657,7 @@ packages:
name: process name: process
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.2.3" version: "4.2.1"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -706,7 +706,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.4" version: "2.0.3"
share_plus_macos: share_plus_macos:
dependency: transitive dependency: transitive
description: description:
@ -741,21 +741,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.7" version: "2.0.6"
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.2" version: "2.0.0"
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.2" version: "2.0.0"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -769,21 +769,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.2" version: "2.0.0"
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.2" version: "2.0.0"
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.2.0" version: "1.1.4"
shelf_packages_handler: shelf_packages_handler:
dependency: transitive dependency: transitive
description: description:
@ -797,7 +797,7 @@ packages:
name: shelf_static name: shelf_static
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.0.0"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@ -816,14 +816,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.3" version: "1.0.2"
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.2.1" version: "1.1.0"
source_map_stack_trace: source_map_stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -935,42 +935,42 @@ packages:
name: url_launcher name: url_launcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.9" version: "6.0.6"
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.1" version: "2.0.0"
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.1" version: "2.0.0"
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.4" version: "2.0.3"
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.4" version: "2.0.1"
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.2" version: "2.0.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -991,35 +991,35 @@ packages:
name: wakelock name: wakelock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.5.3+3" version: "0.5.2"
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+2" version: "0.1.0+1"
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+2" version: "0.2.1+1"
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+2" version: "0.2.0+1"
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+1" version: "0.1.0"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@ -1047,7 +1047,7 @@ packages:
name: win32 name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.7" version: "2.2.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@ -1070,5 +1070,5 @@ packages:
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
sdks: sdks:
dart: ">=2.13.4 <3.0.0" dart: ">=2.14.0 <3.0.0"
flutter: ">=2.2.3" flutter: ">=2.5.0"

View File

@ -5,7 +5,7 @@ version: 0.1.3+5
environment: environment:
sdk: '>=2.13.4 <3.0.0' sdk: '>=2.13.4 <3.0.0'
flutter: ">=2.2.3" flutter: ">=2.5.0"
dependencies: dependencies:
flutter: flutter:
@ -18,7 +18,7 @@ dependencies:
either_option: ^2.0.1-dev.1 either_option: ^2.0.1-dev.1
equatable: ^2.0.3 equatable: ^2.0.3
fl_chart: ^0.40.0 fl_chart: ^0.40.0
flutter_bloc: ^7.1.0 flutter_bloc: ^7.3.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: ^7.2.0 get_it: ^7.2.0