From 0ec549042c557e704fca39fe32e7b95d6c4bd470 Mon Sep 17 00:00:00 2001 From: Kherel Date: Mon, 15 Mar 2021 16:39:44 +0100 Subject: [PATCH] update --- assets/images/onboarding/logos_line-dark.png | Bin 11054 -> 13701 bytes assets/images/onboarding/logos_line-light.png | Bin 5046 -> 13740 bytes assets/translations/en.json | 45 +++++++++- assets/translations/ru.json | 48 +++++++++- ios/Podfile.lock | 2 +- lib/config/bloc_config.dart | 4 +- lib/config/bloc_observer.dart | 6 +- lib/config/hive_config.dart | 3 +- lib/config/localization.dart | 10 +-- lib/logic/api_maps/api_map.dart | 6 +- lib/logic/api_maps/backblaze.dart | 8 +- lib/logic/api_maps/cloudflare.dart | 20 ++--- lib/logic/api_maps/hetzner.dart | 27 +++--- lib/logic/api_maps/server.dart | 2 +- .../cubit/app_config/app_config_cubit.dart | 41 +++++---- .../app_config/app_config_repository.dart | 26 +++--- .../cubit/app_config/app_config_state.dart | 84 +++++++++--------- .../app_settings/app_settings_cubit.dart | 11 ++- .../app_settings/app_settings_state.dart | 4 +- .../initializing/backblaze_form_cubit.dart | 9 +- .../initializing/cloudflare_form_cubit.dart | 4 +- .../forms/initializing/domain_cloudflare.dart | 6 +- .../initializing/hetzner_form_cubit.dart | 5 +- .../initializing/root_user_form_cubit.dart | 9 +- .../cubit/forms/user/user_form_cubit.dart | 17 ++-- .../cubit/forms/validations/validations.dart | 2 +- lib/logic/cubit/users/users_cubit.dart | 4 +- lib/logic/get_it/navigation.dart | 4 +- lib/logic/models/backblaze_credential.dart | 6 +- lib/logic/models/backblaze_credential.g.dart | 4 +- lib/logic/models/cloudflare_domain.dart | 4 +- lib/logic/models/cloudflare_domain.g.dart | 4 +- lib/logic/models/dns_records.dart | 11 ++- lib/logic/models/message.dart | 4 +- lib/logic/models/provider.dart | 6 +- lib/logic/models/server_details.dart | 17 ++-- lib/logic/models/server_details.g.dart | 8 +- lib/logic/models/server_status.dart | 6 +- lib/logic/models/service.dart | 4 +- lib/logic/models/user.dart | 9 +- lib/main.dart | 6 +- .../action_button/action_button.dart | 10 +-- .../components/brand_alert/brand_alert.dart | 10 +-- .../components/brand_button/brand_button.dart | 46 +++++----- lib/ui/components/brand_card/brand_card.dart | 4 +- .../brand_divider/brand_divider.dart | 2 +- .../components/brand_header/brand_header.dart | 4 +- .../components/brand_icons/brand_icons.dart | 2 +- .../brand_modal_sheet/brand_modal_sheet.dart | 4 +- .../brand_span_button/brand_span_button.dart | 16 ++-- .../brand_tab_bar/brand_tab_bar.dart | 27 +++--- lib/ui/components/brand_text/brand_text.dart | 46 +++++----- .../components/brand_timer/brand_timer.dart | 22 ++--- .../dots_indicator/dots_indicator.dart | 6 +- lib/ui/components/error/error.dart | 6 +- .../icon_status_mask/icon_status_mask.dart | 4 +- .../not_ready_card/not_ready_card.dart | 9 +- .../components/progress_bar/progress_bar.dart | 14 +-- .../components/switch_block/switch_bloc.dart | 8 +- lib/ui/pages/initializing/initializing.dart | 72 ++++++++------- lib/ui/pages/more/about/about.dart | 2 +- .../pages/more/app_settings/app_setting.dart | 17 ++-- lib/ui/pages/more/console/console.dart | 2 +- lib/ui/pages/more/info/info.dart | 2 +- lib/ui/pages/more/more.dart | 25 +++--- lib/ui/pages/onboarding/onboarding.dart | 26 +++--- lib/ui/pages/providers/providers.dart | 46 +++++----- lib/ui/pages/providers/settings/settings.dart | 14 +-- lib/ui/pages/rootRoute.dart | 6 +- lib/ui/pages/services/services.dart | 17 ++-- lib/ui/pages/users/empty.dart | 4 +- lib/ui/pages/users/fab.dart | 2 +- lib/ui/pages/users/new_user.dart | 20 ++--- lib/ui/pages/users/user.dart | 8 +- lib/ui/pages/users/user_details.dart | 12 +-- lib/ui/pages/users/users.dart | 8 +- lib/utils/extensions/elevation_extension.dart | 16 ++-- lib/utils/password_generator.dart | 16 ++-- lib/utils/route_transitions/slide_bottom.dart | 2 +- lib/utils/route_transitions/slide_right.dart | 2 +- pubspec.yaml | 3 +- 81 files changed, 572 insertions(+), 486 deletions(-) diff --git a/assets/images/onboarding/logos_line-dark.png b/assets/images/onboarding/logos_line-dark.png index 772aff4099ab968529461d7ca133913559ea2cf4..e651ad053f454fa5221ce4282f708b99c199d239 100644 GIT binary patch literal 13701 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 U4t@$lpdJD8GAhz#?~Q!^58C=4`2YX_ literal 11054 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 D0QqTo literal 5046 zcmV;n6G`leP)X1^@s6M3W~R00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPogxTqX=qD}v^5%wOQTJTpf;&Ir9~~R<+Lyg*jmc6BiEL=6argqWO6A{BDp&=H{ZE4 zvz-0ok4?%Xy&rJ7GxvXY?tJr|bM7t$tznEO%~*u&xRS!u87}1=GP0YJxg0gnKm!f< z5VQsX0yLw-?IIyM@CIX*OYv{*Q3~)WC|xno)#o4ub^yXpvAPx~?;UHn66#EpAz`1d<>rlgUq! z8bWps=ZUClI-@H^_>Zt$xKzSznFRg(&Tzi#x(Q9Hl1BL4QSKQ&N8j1mF@zaa(T3%* z!V#fWipisQCk!(7Vew74N@b*Q+r34;co-gm4p9SZ7B*2fBHaBSWq+9o=WpNrxF)Y{ z@y9GK+rE2m9@%l2wy|6`llN+Ag~!LH8GqCa)SVEtk6#N^c;nt(kMqOSWCHwX_{}5X zF}N>kU`1n9D#Ba6Th9oR{Vu5l`vMI%hlMyupB?6nk1+!KkxSH(P zL^#DS205DKw#R>0o4Kx{0iEweEq-NkgI|fuvP_K9H-&5YrDqAXft89?rwCaIDk7^g zzg}Quq4>(-V}peU|1OV+at{3uM-r_aTR*Tac((zF zaX-#Zkz>SJE(j@yNVy#-(}Za_4oqS}AV^K5MZ*}1Dz^`=miBM%etggo#=xa)reS5Q z60AB!D3$D>C5C9d3#o;l@Fp15g2~fqD;g;dT79a&Vb-h_Y~Q`FA7nKyl{+ZdpQqe& zxYlL)Kl|t>-8A1nEpe8dJuw+*H=CGd+f^>C#R(-BeY!c^~40#Ng+2b(1`x~b5 z%EziBLRZj|FRJLiE>a)=S9O7+F1wY^Py?$T+aKHuKd?&RFstAzEQ&%KzX~sCQi5m3 zLKVVq$OMJ}%WmPTK39oh^8JTCQRc$t_NDBbLmv*GZ37`5BF~hLdBGTGQ9BtLxcyia zrZM~P3}N(u1mmCA1g=DMZx=;&e}~*(O_KWLm$j;5p4qy|;1{sj+{yXg795qXH5L;hUWRtWtt5hZ z=R8uK4YJ%0sCKxI9{P4Ct#7HgUu0VR#eWPepgmjyq6hCe2Dy|LuhP72Rx?&S5#IW1 zvr{RRg5R#@rbp5IRU%Gxz-Di~{7C#eWNdv@pUe9aL`@sZl%cxj-7heQI$BhT0V;`GOO*Zu5@I5i5RGtA;c+uu8#XCafkE?b{Z& zj^k3tq~iU79!UwI_60RR%>H-Q+eYL00R!`w&1U3lA0VF>NS+GX!1V4Uq2fY`j4S1+ z?%#Fy`Tgf^>xOE*UlOowqK~f-ZMmnsTq!QEuka%9!z`BCKlpM2gki$8jm+;@L8_c*?ySPqQD;xvsV=R^x?=WpIG zEBjR}E+W#U?PKTFg|B@}7{y}Uewz6a9*;qZZ^kYD{WAYYRhM7xd7M75tyl` zL1G6HC^_f}9m)t{?}7SzO;PzuLo_(8EdlK>3_*bm1S>+7Dccq!)dcMC4w&E_=->Nb zy-#EW{>TG#o1oPk(QH8R6A6Qp^w%sa7RIJ+H_3#$TwpWR z5b^*58HYgxPa#lp;G^L;53u?x3i%KphwEQDf3_P0c8@KL!{Pj*lr{4|%)XgMKbyV& zshbmzf#AtKw@VFbofoLV0G=wWev&~Is+aztx;@Db{Hsp=M|q%`YZH(qF49N4*WtwFu0wTc^G*D@CEznb2q(@IL>TmJOQ3vf4LTy}j(( zC*3fQxyEeZ1gem37TG^qGVd{0Q%NJCO<^SE-+hRz_tF=PBp$f=d_E3ZH-D5$E&2Y; z6-|V$D-P2#A~N)sS&_`Gx&R1BTL?$8o5&wYBtK^SH|lIicU9%- z^L)0XY(CulZL$kfNf2zi;#-)E!}m>R%j;LPzp!D~aoh*}WfN00UOBJ8*BH(#DmAe_ zx}j9Bpk`Q=bRy8uN=uDtxK|3aRlP#5(B1Ij?Wbjh`Z4}|3Kxf@r;%o(#c)oNO&s`J z@?ScdQwAU2lPwF(=Ns$?pa%KxydDc&w|&v|_O`Vgk1*9_Wq!gRMdFtvGe%W){h znCnX9!AemId94HCws27l+|k-PG&VNDU&(Ft+Nz-wC;CbRU+E*tL(7S|)Zn0}=0rEl zc16dlYCt8bV}C?9N2k8$D#LVzBu+4qnG8q7KRY#jgRIP=N**gnl`@3;jG=_Sh7MD* z+j7{IY6v9B)`1B^>M2Nf0QGt!O1#EjaeVRkF<2Zb58>F(B#3%35LlNj)c{DX3*^?u zeWFeG=2*)iSL(Ha_bHyl@o-awtwlF}^(uVguIRI+dnzIo_qhiu^L0iH zWv1UQ;h(qr=fO=I_s?JV(`COus;K{ZD8&~rr(o=N{5ochIaiKr)|u1m{#aaY(GqXy zu7IkM7F5p_V$t(bmPI^%GNns`Nt>zyD<{@FAAHAO_xhl6_fh;oL%4GjtpQG3i?>7PBzf11xHP!<WU*WxeTBuq{hK>_;>KyRLHfz**HZ*3EJhyk6>Nv`m0!%~?Ouj3_sa8Gq*WLff z9WtDDK5}P<{X7c=lOUqUZSe0g>9gOlch|RmC(ZdfEuyd4PAOeEuLmBv^MEGYih4XA zlOLZ#Ar7hacidBHjxQAi+bS-up-b%d+=^9y2FI77+WK%c_h?dl3F*hae{X@%F$MON z{*!(cSRI={vitGAQXt$*$m!(&lY_kAmu=3{Qe$|2H5fpv!r)sn;rznPPn|-<;Ns%FICz;X-TK14Rn{fyHhfG2D$+(!k1 z&ll=d4Tvpn2HFAFSiX%5d(gNw)}hE65Xw}}dqH^_)O2x=h7#Yc*vz^sTALmLfawBSy3 zss)P%HH2Z?Uwko@Vv=J2p37zH~<54*Q(PPgeDbVl&{BPIrbOga`8?Eb!RM= zVG|oq3X?0cGW>p5ml<_hb2Bp&?8E(e&`Cfl!Gt@=^Ov!2jc<}lMJPgvk@H^@LxLF!-phWyR*6a?fSN7kzzRAk#Q|UFF#_K!yfL*N^i?|0k z2|8IyeD0u50d6EtQkSy@^dwR%+Oyi+FTPLRB7ysg$<&}N$U90)jra6lvqnjk8Z3PV zf0fBWL8UA6*WZ07P2XsunaL(9OgD{e{FnTkYLHFP=H^+VL-64Zkk63qijJA0{VK{~ z;fh>=iOQIL0C2tFn9D$T*%K#HNnub7L6G$Lcz%$7+YzR42B!Bbot<5SWBG|eJbSF5 zKDR|gTF=4te1XrvADR4gJl_w+coKQz82l`PBPsX~5#Clm=egqPgy0T%Ku!$ex@`jQ zmRvEx;$)%-e0QVd5f@MXfd86AdM@-ia9*&Tf)_!j-t1OR@@=XQ6%kDl-cXG; zf6Ci`Fi(9$@V9DsbGM!gOyxq=!S4pCA9{|50IL zilXc6#9f)(oJ6?V@a(hCih}LD{NnLcEiqMf!4u>?VVFetg9t8aoXWpAUbb().navigator; + void onError(Bloc cubit, Object error, StackTrace stackTrace) { + final navigator = getIt.get().navigator!; navigator.push( materialRoute( diff --git a/lib/config/hive_config.dart b/lib/config/hive_config.dart index cf05097234..17a10fb3b1 100644 --- a/lib/config/hive_config.dart +++ b/lib/config/hive_config.dart @@ -32,7 +32,8 @@ class HiveConfig { await secureStorage.write(key: BNames.key, value: base64UrlEncode(key)); } - return base64Url.decode(await secureStorage.read(key: BNames.key)); + String? string = await secureStorage.read(key: BNames.key); + return base64Url.decode(string!); } } diff --git a/lib/config/localization.dart b/lib/config/localization.dart index b8e33be3d7..abaa24632e 100644 --- a/lib/config/localization.dart +++ b/lib/config/localization.dart @@ -3,20 +3,20 @@ import 'package:flutter/material.dart'; class Localization extends StatelessWidget { const Localization({ - Key key, + Key? key, this.child, }) : super(key: key); - final Widget child; + final Widget? child; @override Widget build(BuildContext context) { return EasyLocalization( - preloaderColor: Colors.black, supportedLocales: [Locale('ru'), Locale('en')], path: 'assets/translations', - fallbackLocale: Locale('en'), + fallbackLocale: Locale('ru'), + saveLocale: false, useOnlyLangCode: true, - child: child, + child: child!, ); } } diff --git a/lib/logic/api_maps/api_map.dart b/lib/logic/api_maps/api_map.dart index a7c8949f58..13f05e725e 100644 --- a/lib/logic/api_maps/api_map.dart +++ b/lib/logic/api_maps/api_map.dart @@ -18,9 +18,9 @@ abstract class ApiMap { }; loggedClient = client; } - String rootAddress; + String? rootAddress; - Dio loggedClient; + late Dio loggedClient; void close() { loggedClient.close(); @@ -61,7 +61,7 @@ class ConsoleInterceptor extends InterceptorsWrapper { addMessage( Message.warn( text: - 'response-uri: ${response?.request?.uri}\ncode: ${response?.statusCode}\ndata: ${response?.toString()}\n', + 'response-uri: ${response?.request.uri}\ncode: ${response?.statusCode}\ndata: ${response?.toString()}\n', ), ); return super.onError(err); diff --git a/lib/logic/api_maps/backblaze.dart b/lib/logic/api_maps/backblaze.dart index 35782fc700..5bf848633a 100644 --- a/lib/logic/api_maps/backblaze.dart +++ b/lib/logic/api_maps/backblaze.dart @@ -3,17 +3,17 @@ import 'package:dio/dio.dart'; import 'package:selfprivacy/logic/api_maps/api_map.dart'; class BackblazeApi extends ApiMap { - BackblazeApi([String token]) { + BackblazeApi([String? token]) { if (token != null) { loggedClient.options = BaseOptions( headers: {'Authorization': 'Basic $token'}, - baseUrl: rootAddress, + baseUrl: rootAddress!, ); } } @override - String rootAddress = + String? rootAddress = 'https://api.backblazeb2.com/b2api/v2/b2_authorize_account'; Future isValid(String token) async { @@ -24,7 +24,7 @@ class BackblazeApi extends ApiMap { }, ); - Response response = await loggedClient.get(rootAddress, options: options); + Response response = await loggedClient.get(rootAddress!, options: options); if (response.statusCode == HttpStatus.ok) { return true; diff --git a/lib/logic/api_maps/cloudflare.dart b/lib/logic/api_maps/cloudflare.dart index cb69cdc3c6..b78b8ee658 100644 --- a/lib/logic/api_maps/cloudflare.dart +++ b/lib/logic/api_maps/cloudflare.dart @@ -5,7 +5,7 @@ import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/dns_records.dart'; class CloudflareApi extends ApiMap { - CloudflareApi([String token]) { + CloudflareApi([String? token]) { if (token != null) { loggedClient.options = BaseOptions(headers: {'Authorization': 'Bearer $token'}); @@ -13,7 +13,7 @@ class CloudflareApi extends ApiMap { } @override - String rootAddress = 'https://api.cloudflare.com/client/v4'; + String? rootAddress = 'https://api.cloudflare.com/client/v4'; Future isValid(String token) async { var url = '$rootAddress/user/tokens/verify'; @@ -35,7 +35,7 @@ class CloudflareApi extends ApiMap { } } - Future getZoneId(String token, String domain) async { + Future getZoneId(String? token, String domain) async { var url = '$rootAddress/zones'; var options = Options( @@ -59,8 +59,8 @@ class CloudflareApi extends ApiMap { } Future removeSimilarRecords({ - String ip4, - CloudFlareDomain cloudFlareDomain, + String? ip4, + required CloudFlareDomain cloudFlareDomain, }) async { var domainName = cloudFlareDomain.domainName; var domainZoneId = cloudFlareDomain.zoneId; @@ -82,8 +82,8 @@ class CloudflareApi extends ApiMap { } Future createMultipleDnsRecords({ - String ip4, - CloudFlareDomain cloudFlareDomain, + String? ip4, + required CloudFlareDomain cloudFlareDomain, }) async { var domainName = cloudFlareDomain.domainName; var domainZoneId = cloudFlareDomain.zoneId; @@ -120,7 +120,7 @@ class CloudflareApi extends ApiMap { // ); // } - List projectDnsRecords(String domainName, String ip4) { + List projectDnsRecords(String? domainName, String? ip4) { var domainA = DnsRecords(type: 'A', name: domainName, content: ip4); var mx = DnsRecords(type: 'MX', name: '@', content: domainName); @@ -161,7 +161,7 @@ class CloudflareApi extends ApiMap { ]; } - Future> domainList() async { + Future?> domainList() async { var url = '$rootAddress/zones?per_page=50'; var response = await loggedClient.get( url, @@ -169,7 +169,7 @@ class CloudflareApi extends ApiMap { ); return response.data['result'] - .map((el) => el['name'] as String) + .map((el) => el['name'] as String?) .toList(); } } diff --git a/lib/logic/api_maps/hetzner.dart b/lib/logic/api_maps/hetzner.dart index ebff314c66..8459d31530 100644 --- a/lib/logic/api_maps/hetzner.dart +++ b/lib/logic/api_maps/hetzner.dart @@ -2,24 +2,23 @@ import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; -import 'package:flutter/foundation.dart'; import 'package:selfprivacy/logic/api_maps/api_map.dart'; import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/utils/password_generator2.dart'; class HetznerApi extends ApiMap { - HetznerApi([String token]) { + HetznerApi([String? token]) { if (token != null) { loggedClient.options = BaseOptions( headers: {'Authorization': 'Bearer $token'}, - baseUrl: rootAddress, + baseUrl: rootAddress!, ); } } @override - String rootAddress = 'https://api.hetzner.cloud/v1/servers'; + String? rootAddress = 'https://api.hetzner.cloud/v1/servers'; Future isValid(String token) async { var options = Options( @@ -29,7 +28,7 @@ class HetznerApi extends ApiMap { }, ); - Response response = await loggedClient.get(rootAddress, options: options); + Response response = await loggedClient.get(rootAddress!, options: options); if (response.statusCode == HttpStatus.ok) { return true; @@ -41,9 +40,9 @@ class HetznerApi extends ApiMap { } Future createServer({ - @required String cloudFlareKey, - @required User rootUser, - @required String domainName, + required String? cloudFlareKey, + required User rootUser, + required String? domainName, }) async { var dbPassword = getRandomString(40); @@ -52,7 +51,7 @@ class HetznerApi extends ApiMap { ); Response response = await loggedClient.post( - rootAddress, + rootAddress!, data: data, ); @@ -64,17 +63,17 @@ class HetznerApi extends ApiMap { } Future deleteSelfprivacyServer({ - @required String cloudFlareKey, + required String? cloudFlareKey, }) async { - Response response = await loggedClient.get(rootAddress); + Response response = await loggedClient.get(rootAddress!); List list = response.data['servers']; var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server'); - return await loggedClient.delete('$rootAddress/${server['id']}'); + await loggedClient.delete('$rootAddress/${server['id']}'); } Future startServer({ - HetznerServerDetails server, + required HetznerServerDetails server, }) async { await loggedClient.post('/${server.id}/actions/poweron'); @@ -84,7 +83,7 @@ class HetznerApi extends ApiMap { } Future restart({ - HetznerServerDetails server, + required HetznerServerDetails server, }) async { await loggedClient.post('/${server.id}/actions/poweron'); diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index c5db15766c..5f5abda451 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -5,7 +5,7 @@ import 'package:dio/dio.dart'; import 'api_map.dart'; class ServerApi extends ApiMap { - ServerApi(String domainName) { + ServerApi(String? domainName) { loggedClient.options = BaseOptions( baseUrl: 'https://api.$domainName', ); diff --git a/lib/logic/cubit/app_config/app_config_cubit.dart b/lib/logic/cubit/app_config/app_config_cubit.dart index bc42f4e0f7..dbe64180eb 100644 --- a/lib/logic/cubit/app_config/app_config_cubit.dart +++ b/lib/logic/cubit/app_config/app_config_cubit.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; @@ -64,23 +63,23 @@ class AppConfigCubit extends Cubit { } void startServerIfDnsIsOkay({ - AppConfigState state, + AppConfigState? state, bool isImmediate = false, }) async { state = state ?? this.state; final work = () async { - emit(TimerState(dataState: state, isLoading: true)); + emit(TimerState(dataState: state!, isLoading: true)); - var ip4 = state.hetznerServer.ip4; - var domainName = state.cloudFlareDomain.domainName; + var ip4 = state.hetznerServer!.ip4; + var domainName = state.cloudFlareDomain!.domainName; var isMatch = await repository.isDnsAddressesMatch(domainName, ip4); if (isMatch) { var server = await repository.startServer( state.hetznerKey, - state.hetznerServer, + state.hetznerServer!, ); repository.saveServerDetails(server); emit( @@ -111,16 +110,16 @@ class AppConfigCubit extends Cubit { } void resetServerIfServerIsOkay({ - AppConfigState state, + AppConfigState? state, bool isImmediate = false, }) async { state = state ?? this.state; var work = () async { - emit(TimerState(dataState: state, isLoading: true)); + emit(TimerState(dataState: state!, isLoading: true)); var isServerWorking = await repository.isHttpServerWorking( - state.cloudFlareDomain.domainName, + state.cloudFlareDomain!.domainName, ); if (isServerWorking) { @@ -133,8 +132,8 @@ class AppConfigCubit extends Cubit { )); timer = Timer(pauseDuration, () async { var hetznerServerDetails = await repository.restart( - state.hetznerKey, - state.hetznerServer, + state!.hetznerKey, + state.hetznerServer!, ); emit( state.copyWith( @@ -165,19 +164,19 @@ class AppConfigCubit extends Cubit { } } - Timer timer; + Timer? timer; void finishCheckIfServerIsOkay({ - AppConfigState state, + AppConfigState? state, bool isImmediate = false, }) async { state = state ?? this.state; var work = () async { - emit(TimerState(dataState: state, isLoading: true)); + emit(TimerState(dataState: state!, isLoading: true)); var isServerWorking = await repository.isHttpServerWorking( - state.cloudFlareDomain.domainName, + state.cloudFlareDomain!.domainName, ); if (isServerWorking) { @@ -238,12 +237,12 @@ class AppConfigCubit extends Cubit { } void createServerAndSetDnsRecords() async { - var _stateCopy = state; + AppConfigState _stateCopy = state; var onSuccess = (serverDetails) async { await repository.createDnsRecords( state.cloudFlareKey, serverDetails.ip4, - state.cloudFlareDomain, + state.cloudFlareDomain!, ); emit(state.copyWith( @@ -259,8 +258,8 @@ class AppConfigCubit extends Cubit { emit(state.copyWith(isLoading: true)); await repository.createServer( state.hetznerKey, - state.rootUser, - state.cloudFlareDomain.domainName, + state.rootUser!, + state.cloudFlareDomain!.domainName, state.cloudFlareKey, onCancel: onCancel, onSuccess: onSuccess, @@ -277,8 +276,8 @@ class AppConfigCubit extends Cubit { } void _closeTimer() { - if (timer != null && timer.isActive) { - timer.cancel(); + if (timer != null && timer!.isActive) { + timer!.cancel(); } } } diff --git a/lib/logic/cubit/app_config/app_config_repository.dart b/lib/logic/cubit/app_config/app_config_repository.dart index 2370909744..1a9f9d2b35 100644 --- a/lib/logic/cubit/app_config/app_config_repository.dart +++ b/lib/logic/cubit/app_config/app_config_repository.dart @@ -60,7 +60,7 @@ class AppConfigRepository { } Future startServer( - String hetznerKey, + String? hetznerKey, HetznerServerDetails hetznerServer, ) async { var hetznerApi = HetznerApi(hetznerKey); @@ -75,7 +75,7 @@ class AppConfigRepository { await box.put(BNames.hetznerServer, serverDetails); } - Future isDnsAddressesMatch(String domainName, String ip4) async { + Future isDnsAddressesMatch(String? domainName, String? ip4) async { print(domainName); var addresses = [ '$domainName', @@ -116,12 +116,12 @@ class AppConfigRepository { } Future createServer( - String hetznerKey, + String? hetznerKey, User rootUser, - String domainName, - String cloudFlareKey, { - void Function() onCancel, - Future Function(HetznerServerDetails serverDetails) onSuccess, + String? domainName, + String? cloudFlareKey, { + void Function()? onCancel, + required Future Function(HetznerServerDetails serverDetails) onSuccess, }) async { var hetznerApi = HetznerApi(hetznerKey); @@ -135,7 +135,7 @@ class AppConfigRepository { hetznerApi.close(); onSuccess(serverDetails); } on DioError catch (e) { - if (e.response.data['error']['code'] == 'uniqueness_error') { + if (e.response!.data['error']['code'] == 'uniqueness_error') { var nav = getIt.get(); nav.showPopUpDialog( BrandAlert( @@ -165,7 +165,7 @@ class AppConfigRepository { text: 'Отменить', onPressed: () { hetznerApi.close(); - onCancel(); + onCancel!(); }, ), ], @@ -176,8 +176,8 @@ class AppConfigRepository { } Future createDnsRecords( - String cloudFlareKey, - String ip4, + String? cloudFlareKey, + String? ip4, CloudFlareDomain cloudFlareDomain, ) async { var cloudflareApi = CloudflareApi(cloudFlareKey); @@ -195,7 +195,7 @@ class AppConfigRepository { cloudflareApi.close(); } - Future isHttpServerWorking(String domainName) async { + Future isHttpServerWorking(String? domainName) async { var api = ServerApi(domainName); var isHttpServerWorking = await api.isHttpServerWorking(); api.close(); @@ -203,7 +203,7 @@ class AppConfigRepository { } Future restart( - String hetznerKey, + String? hetznerKey, HetznerServerDetails server, ) async { var hetznerApi = HetznerApi(hetznerKey); diff --git a/lib/logic/cubit/app_config/app_config_state.dart b/lib/logic/cubit/app_config/app_config_state.dart index caedcc2c4f..d49c338288 100644 --- a/lib/logic/cubit/app_config/app_config_state.dart +++ b/lib/logic/cubit/app_config/app_config_state.dart @@ -2,21 +2,21 @@ part of 'app_config_cubit.dart'; class AppConfigState extends Equatable { const AppConfigState({ - @required this.hetznerKey, - @required this.cloudFlareKey, - @required this.backblazeCredential, - @required this.cloudFlareDomain, - @required this.rootUser, - @required this.hetznerServer, - @required this.isServerStarted, - @required this.isServerReseted, - @required this.hasFinalChecked, - @required this.isLoading, - @required this.error, + required this.hetznerKey, + required this.cloudFlareKey, + required this.backblazeCredential, + required this.cloudFlareDomain, + required this.rootUser, + required this.hetznerServer, + required this.isServerStarted, + required this.isServerReseted, + required this.hasFinalChecked, + required this.isLoading, + required this.error, }); @override - List get props => [ + List get props => [ hetznerKey, cloudFlareKey, backblazeCredential, @@ -30,31 +30,31 @@ class AppConfigState extends Equatable { error, ]; - final String hetznerKey; - final String cloudFlareKey; - final BackblazeCredential backblazeCredential; - final CloudFlareDomain cloudFlareDomain; - final User rootUser; - final HetznerServerDetails hetznerServer; - final bool isServerStarted; - final bool isServerReseted; - final bool hasFinalChecked; + final String? hetznerKey; + final String? cloudFlareKey; + final BackblazeCredential? backblazeCredential; + final CloudFlareDomain? cloudFlareDomain; + final User? rootUser; + final HetznerServerDetails? hetznerServer; + final bool? isServerStarted; + final bool? isServerReseted; + final bool? hasFinalChecked; - final bool isLoading; - final Exception error; + final bool? isLoading; + final Exception? error; AppConfigState copyWith({ - String hetznerKey, - String cloudFlareKey, - BackblazeCredential backblazeCredential, - CloudFlareDomain cloudFlareDomain, - User rootUser, - HetznerServerDetails hetznerServer, - bool isServerStarted, - bool isServerReseted, - bool hasFinalChecked, - bool isLoading, - Exception error, + String? hetznerKey, + String? cloudFlareKey, + BackblazeCredential? backblazeCredential, + CloudFlareDomain? cloudFlareDomain, + User? rootUser, + HetznerServerDetails? hetznerServer, + bool? isServerStarted, + bool? isServerReseted, + bool? hasFinalChecked, + bool? isLoading, + Exception? error, }) => AppConfigState( hetznerKey: hetznerKey ?? this.hetznerKey, @@ -77,10 +77,10 @@ class AppConfigState extends Equatable { bool get isUserFilled => rootUser != null; bool get isServerCreated => hetznerServer != null; - bool get isFullyInitilized => _fulfilementList.every((el) => el); - int get progress => _fulfilementList.where((el) => el).length; + bool get isFullyInitilized => _fulfilementList.every((el) => el!); + int get progress => _fulfilementList.where((el) => el!).length; - List get _fulfilementList => [ + List get _fulfilementList => [ isHetznerFilled, isCloudFlareFilled, isBackblazeFilled, @@ -112,10 +112,10 @@ class InitialAppConfigState extends AppConfigState { class TimerState extends AppConfigState { TimerState({ - @required this.dataState, + required this.dataState, this.timerStart, this.duration, - @required bool isLoading, + required bool isLoading, }) : super( hetznerKey: dataState.hetznerKey, cloudFlareKey: dataState.cloudFlareKey, @@ -131,11 +131,11 @@ class TimerState extends AppConfigState { ); final AppConfigState dataState; - final DateTime timerStart; - final Duration duration; + final DateTime? timerStart; + final Duration? duration; @override - List get props => [ + List get props => [ dataState, timerStart, duration, diff --git a/lib/logic/cubit/app_settings/app_settings_cubit.dart b/lib/logic/cubit/app_settings/app_settings_cubit.dart index 93f79fe151..5dcf348e52 100644 --- a/lib/logic/cubit/app_settings/app_settings_cubit.dart +++ b/lib/logic/cubit/app_settings/app_settings_cubit.dart @@ -1,6 +1,5 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flutter/widgets.dart'; import 'package:hive/hive.dart'; import 'package:selfprivacy/config/hive_config.dart'; export 'package:provider/provider.dart'; @@ -9,8 +8,8 @@ part 'app_settings_state.dart'; class AppSettingsCubit extends Cubit { AppSettingsCubit({ - @required bool isDarkModeOn, - @required bool isOnbordingShowing, + required bool isDarkModeOn, + required bool isOnbordingShowing, }) : super( AppSettingsState( isDarkModeOn: isDarkModeOn, @@ -21,15 +20,15 @@ class AppSettingsCubit extends Cubit { Box box = Hive.box(BNames.appSettings); void load() { - bool isDarkModeOn = box.get(BNames.isDarkModeOn); - bool isOnbordingShowing = box.get(BNames.isOnbordingShowing); + bool? isDarkModeOn = box.get(BNames.isDarkModeOn); + bool? isOnbordingShowing = box.get(BNames.isOnbordingShowing); emit(state.copyWith( isDarkModeOn: isDarkModeOn, isOnbordingShowing: isOnbordingShowing, )); } - void updateDarkMode({@required bool isDarkModeOn}) { + void updateDarkMode({required bool isDarkModeOn}) { box.put(BNames.isDarkModeOn, isDarkModeOn); emit(state.copyWith(isDarkModeOn: isDarkModeOn)); } diff --git a/lib/logic/cubit/app_settings/app_settings_state.dart b/lib/logic/cubit/app_settings/app_settings_state.dart index 023ad2d03f..e1dae427f1 100644 --- a/lib/logic/cubit/app_settings/app_settings_state.dart +++ b/lib/logic/cubit/app_settings/app_settings_state.dart @@ -2,8 +2,8 @@ part of 'app_settings_cubit.dart'; class AppSettingsState extends Equatable { const AppSettingsState({ - @required this.isDarkModeOn, - @required this.isOnbordingShowing, + required this.isDarkModeOn, + required this.isOnbordingShowing, }); final bool isDarkModeOn; diff --git a/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart b/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart index 0f20258486..386882a935 100644 --- a/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart @@ -42,13 +42,14 @@ class BackblazeFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - FieldCubit keyId; - - FieldCubit applicationKey; + // ignore: close_sinks + late final FieldCubit keyId; + // ignore: close_sinks + late final FieldCubit applicationKey; @override FutureOr asyncValidation() async { - bool isKeyValid; + late bool isKeyValid; try { String encodedApiKey = encodedBackblazeKey( keyId.state.value, diff --git a/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart b/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart index ff51401c88..2f8854368a 100644 --- a/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart @@ -30,11 +30,11 @@ class CloudFlareFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - FieldCubit apiKey; + late final FieldCubit apiKey; @override FutureOr asyncValidation() async { - bool isKeyValid; + late bool isKeyValid; try { isKeyValid = await apiClient.isValid(apiKey.state.value); diff --git a/lib/logic/cubit/forms/initializing/domain_cloudflare.dart b/lib/logic/cubit/forms/initializing/domain_cloudflare.dart index b526b0ce58..07616b0a10 100644 --- a/lib/logic/cubit/forms/initializing/domain_cloudflare.dart +++ b/lib/logic/cubit/forms/initializing/domain_cloudflare.dart @@ -5,7 +5,7 @@ import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; class DomainSetupCubit extends Cubit { DomainSetupCubit(this.initializingCubit) : super(Initial()) { - var token = (initializingCubit.state.cloudFlareKey); + var token = initializingCubit.state.cloudFlareKey; assert(token != null, 'no cloudflare token'); @@ -13,11 +13,11 @@ class DomainSetupCubit extends Cubit { } AppConfigCubit initializingCubit; - CloudflareApi api; + late CloudflareApi api; Future load() async { emit(Loading(LoadingTypes.loadingDomain)); - var list = await api.domainList(); + var list = await (api.domainList() as Future>); if (list.isEmpty) { emit(Empty()); } else if (list.length == 1) { diff --git a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart index 8be71e6514..2383a986ba 100644 --- a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart @@ -30,11 +30,12 @@ class HetznerFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - FieldCubit apiKey; + // ignore: close_sinks + late final FieldCubit apiKey; @override FutureOr asyncValidation() async { - bool isKeyValid; + late bool isKeyValid; try { isKeyValid = await apiClient.isValid(apiKey.state.value); } catch (e) { diff --git a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart index 2fdc6e8aa2..f651c25127 100644 --- a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart @@ -46,9 +46,12 @@ class RootUserFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - FieldCubit userName; - FieldCubit password; - FieldCubit isVisible; + // ignore: close_sinks + late final FieldCubit userName; + // ignore: close_sinks + late final FieldCubit password; + // ignore: close_sinks + late final FieldCubit isVisible; @override Future close() async { diff --git a/lib/logic/cubit/forms/user/user_form_cubit.dart b/lib/logic/cubit/forms/user/user_form_cubit.dart index c75e760d80..59bd50d3a5 100644 --- a/lib/logic/cubit/forms/user/user_form_cubit.dart +++ b/lib/logic/cubit/forms/user/user_form_cubit.dart @@ -7,8 +7,8 @@ import 'package:selfprivacy/utils/password_generator.dart'; class UserFormCubit extends FormCubit { UserFormCubit({ - this.usersCubit, - User user, + required this.usersCubit, + User? user, }) { var isEdit = user != null; @@ -16,7 +16,7 @@ class UserFormCubit extends FormCubit { var passwordRegExp = RegExp(r"[\n\r\s]+"); login = FieldCubit( - initalValue: isEdit ? user.login : '', + initalValue: isEdit ? user!.login : '', validations: [ RequiredStringValidation('required'), ValidationModel( @@ -25,7 +25,7 @@ class UserFormCubit extends FormCubit { ); password = FieldCubit( - initalValue: isEdit ? user.password : genPass(), + initalValue: isEdit ? user!.password : genPass(), validations: [ RequiredStringValidation('required'), ValidationModel( @@ -42,15 +42,16 @@ class UserFormCubit extends FormCubit { login: login.state.value, password: password.state.value, ); - usersCubit.add(user); + usersCubit.addUser(user); } - FieldCubit login; - FieldCubit password; + // ignore: close_sinks + late FieldCubit login; + late FieldCubit password; void genNewPassword() { password.externalSetValue(genPass()); } - UsersCubit usersCubit; + late UsersCubit usersCubit; } diff --git a/lib/logic/cubit/forms/validations/validations.dart b/lib/logic/cubit/forms/validations/validations.dart index bf39f78774..0c4fe493c8 100644 --- a/lib/logic/cubit/forms/validations/validations.dart +++ b/lib/logic/cubit/forms/validations/validations.dart @@ -5,7 +5,7 @@ class LegnthStringValidationWithLenghShowing extends ValidationModel { : super((n) => n.length != length, errorText); @override - String check(String val) { + String? check(String val) { var length = val.length; var errorMassage = this.errorMassage.replaceAll("[]", length.toString()); return test(val) ? errorMassage : null; diff --git a/lib/logic/cubit/users/users_cubit.dart b/lib/logic/cubit/users/users_cubit.dart index cf296f3169..6e00f7e9da 100644 --- a/lib/logic/cubit/users/users_cubit.dart +++ b/lib/logic/cubit/users/users_cubit.dart @@ -8,14 +8,14 @@ part 'users_state.dart'; class UsersCubit extends Cubit { UsersCubit() : super(UsersState([])); - void add(User user) { + void addUser(User user) { var users = [...state.users]; users.add(user); emit(UsersState(users)); } - void remove(User user) { + void remove(User? user) { var users = [...state.users]; users.remove(user); diff --git a/lib/logic/get_it/navigation.dart b/lib/logic/get_it/navigation.dart index cf5dc8ff9e..92074c9305 100644 --- a/lib/logic/get_it/navigation.dart +++ b/lib/logic/get_it/navigation.dart @@ -3,10 +3,10 @@ import 'package:flutter/widgets.dart'; class NavigationService { final GlobalKey navigatorKey = GlobalKey(); - NavigatorState get navigator => navigatorKey.currentState; + NavigatorState? get navigator => navigatorKey.currentState; void showPopUpDialog(AlertDialog dialog) { - final context = navigatorKey.currentState.overlay.context; + final context = navigatorKey.currentState!.overlay!.context; showDialog( context: context, diff --git a/lib/logic/models/backblaze_credential.dart b/lib/logic/models/backblaze_credential.dart index 28d146fe32..3496f4ced7 100644 --- a/lib/logic/models/backblaze_credential.dart +++ b/lib/logic/models/backblaze_credential.dart @@ -9,10 +9,10 @@ class BackblazeCredential { BackblazeCredential({this.keyId, this.applicationKey}); @HiveField(0) - final String keyId; + final String? keyId; @HiveField(1) - final String applicationKey; + final String? applicationKey; get encodedApiKey => encodedBackblazeKey(keyId, applicationKey); @@ -22,7 +22,7 @@ class BackblazeCredential { } } -String encodedBackblazeKey(String keyId, String applicationKey) { +String encodedBackblazeKey(String? keyId, String? applicationKey) { String _apiKey = '$keyId:$applicationKey'; String encodedApiKey = base64.encode(utf8.encode(_apiKey)); return encodedApiKey; diff --git a/lib/logic/models/backblaze_credential.g.dart b/lib/logic/models/backblaze_credential.g.dart index c6ad373e69..305b33863d 100644 --- a/lib/logic/models/backblaze_credential.g.dart +++ b/lib/logic/models/backblaze_credential.g.dart @@ -17,8 +17,8 @@ class BackblazeCredentialAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return BackblazeCredential( - keyId: fields[0] as String, - applicationKey: fields[1] as String, + keyId: fields[0] as String?, + applicationKey: fields[1] as String?, ); } diff --git a/lib/logic/models/cloudflare_domain.dart b/lib/logic/models/cloudflare_domain.dart index b050a92c03..d66e9a043d 100644 --- a/lib/logic/models/cloudflare_domain.dart +++ b/lib/logic/models/cloudflare_domain.dart @@ -7,10 +7,10 @@ class CloudFlareDomain { CloudFlareDomain({this.domainName, this.zoneId}); @HiveField(0) - final String domainName; + final String? domainName; @HiveField(1) - final String zoneId; + final String? zoneId; @override String toString() { diff --git a/lib/logic/models/cloudflare_domain.g.dart b/lib/logic/models/cloudflare_domain.g.dart index dcd95317a6..d96cf9bc06 100644 --- a/lib/logic/models/cloudflare_domain.g.dart +++ b/lib/logic/models/cloudflare_domain.g.dart @@ -17,8 +17,8 @@ class CloudFlareDomainAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return CloudFlareDomain( - domainName: fields[0] as String, - zoneId: fields[1] as String, + domainName: fields[0] as String?, + zoneId: fields[1] as String?, ); } diff --git a/lib/logic/models/dns_records.dart b/lib/logic/models/dns_records.dart index 748ec76358..80f1335ed3 100644 --- a/lib/logic/models/dns_records.dart +++ b/lib/logic/models/dns_records.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:json_annotation/json_annotation.dart'; part 'dns_records.g.dart'; @@ -6,17 +5,17 @@ part 'dns_records.g.dart'; @JsonSerializable(createToJson: true, createFactory: false) class DnsRecords { DnsRecords({ - @required this.type, - @required this.name, - @required this.content, + required this.type, + required this.name, + required this.content, this.ttl = 3600, this.priority = 10, this.proxied = false, }); final String type; - final String name; - final String content; + final String? name; + final String? content; final int ttl; final int priority; final bool proxied; diff --git a/lib/logic/models/message.dart b/lib/logic/models/message.dart index 5ec302ba2c..5ae0465e4c 100644 --- a/lib/logic/models/message.dart +++ b/lib/logic/models/message.dart @@ -5,12 +5,12 @@ final formater = new DateFormat('hh:mm'); class Message { Message({this.text, this.type = MessageType.normal}) : time = DateTime.now(); - final String text; + final String? text; final DateTime time; final MessageType type; String get timeString => formater.format(time); - static Message warn({String text}) => Message( + static Message warn({String? text}) => Message( text: text, type: MessageType.warning, ); diff --git a/lib/logic/models/provider.dart b/lib/logic/models/provider.dart index e89e145646..82af8656ef 100644 --- a/lib/logic/models/provider.dart +++ b/lib/logic/models/provider.dart @@ -10,7 +10,7 @@ enum ProviderType { } class ProviderModel extends Equatable { - const ProviderModel({this.state, this.type}); + const ProviderModel({required this.state, required this.type}); final StateType state; final ProviderType type; @@ -21,7 +21,7 @@ class ProviderModel extends Equatable { ); @override - List get props => [state, type]; + List get props => [state, type]; IconData get icon { switch (type) { @@ -31,10 +31,8 @@ class ProviderModel extends Equatable { case ProviderType.domain: return BrandIcons.globe; - break; case ProviderType.backup: return BrandIcons.save; } - return null; } } diff --git a/lib/logic/models/server_details.dart b/lib/logic/models/server_details.dart index ae0ff7e3c8..e014de1434 100644 --- a/lib/logic/models/server_details.dart +++ b/lib/logic/models/server_details.dart @@ -1,4 +1,3 @@ -import 'package:flutter/widgets.dart'; import 'package:hive/hive.dart'; part 'server_details.g.dart'; @@ -6,25 +5,25 @@ part 'server_details.g.dart'; @HiveType(typeId: 2) class HetznerServerDetails { HetznerServerDetails({ - @required this.ip4, - @required this.id, - @required this.createTime, + required this.ip4, + required this.id, + required this.createTime, this.startTime, }); @HiveField(0) - final String ip4; + final String? ip4; @HiveField(1) - final int id; + final int? id; @HiveField(3) - final DateTime createTime; + final DateTime? createTime; @HiveField(2) - final DateTime startTime; + final DateTime? startTime; - HetznerServerDetails copyWith({DateTime startTime}) { + HetznerServerDetails copyWith({DateTime? startTime}) { return HetznerServerDetails( startTime: startTime ?? this.startTime, createTime: createTime, diff --git a/lib/logic/models/server_details.g.dart b/lib/logic/models/server_details.g.dart index c5318044bb..0f08e2f248 100644 --- a/lib/logic/models/server_details.g.dart +++ b/lib/logic/models/server_details.g.dart @@ -17,10 +17,10 @@ class HetznerServerDetailsAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return HetznerServerDetails( - ip4: fields[0] as String, - id: fields[1] as int, - createTime: fields[3] as DateTime, - startTime: fields[2] as DateTime, + ip4: fields[0] as String?, + id: fields[1] as int?, + createTime: fields[3] as DateTime?, + startTime: fields[2] as DateTime?, ); } diff --git a/lib/logic/models/server_status.dart b/lib/logic/models/server_status.dart index af1165c105..1405bde392 100644 --- a/lib/logic/models/server_status.dart +++ b/lib/logic/models/server_status.dart @@ -1,12 +1,10 @@ -import 'package:flutter/foundation.dart'; - class ServerStatus { final StatusTypes http; final StatusTypes imap; final StatusTypes smtp; ServerStatus({ - @required this.http, + required this.http, this.imap = StatusTypes.nodata, this.smtp = StatusTypes.nodata, }); @@ -20,7 +18,7 @@ class ServerStatus { } } -StatusTypes statusTypeFromNumber(int number) { +StatusTypes statusTypeFromNumber(int? number) { if (number == 0) { return StatusTypes.ok; } else if (number == 1) { diff --git a/lib/logic/models/service.dart b/lib/logic/models/service.dart index 85d3868922..a799c682f8 100644 --- a/lib/logic/models/service.dart +++ b/lib/logic/models/service.dart @@ -10,7 +10,7 @@ enum ServiceTypes { } class Service extends Equatable { - const Service({this.state, this.type}); + const Service({required this.state, required this.type}); final StateType state; final ServiceTypes type; @@ -21,5 +21,5 @@ class Service extends Equatable { ); @override - List get props => [state, type]; + List get props => [state, type]; } diff --git a/lib/logic/models/user.dart b/lib/logic/models/user.dart index 3c37a356df..3df879c510 100644 --- a/lib/logic/models/user.dart +++ b/lib/logic/models/user.dart @@ -1,7 +1,6 @@ import 'dart:ui'; import 'package:equatable/equatable.dart'; -import 'package:flutter/foundation.dart'; import 'package:selfprivacy/utils/color_utils.dart'; import 'package:hive/hive.dart'; import 'package:selfprivacy/utils/crypto.dart'; @@ -11,18 +10,18 @@ part 'user.g.dart'; @HiveType(typeId: 1) class User extends Equatable { User({ - @required this.login, - @required this.password, + required this.login, + required this.password, }); @HiveField(0) final String login; - + @HiveField(1) final String password; @override - List get props => [login, password]; + List get props => [login, password]; Color get color => stringToColor(login); diff --git a/lib/main.dart b/lib/main.dart index fd6dc751ae..4d678e31e1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -36,7 +36,7 @@ void main() async { class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - var appSettings = context.watch().state; + AppSettingsState appSettings = context.watch().state; return AnnotatedRegion( value: SystemUiOverlayStyle.light, // Manually changnig appbar color @@ -51,12 +51,12 @@ class MyApp extends StatelessWidget { home: appSettings.isOnbordingShowing ? OnboardingPage(nextPage: InitializingPage()) : RootPage(), - builder: (BuildContext context, Widget widget) { + builder: (BuildContext context, Widget? widget) { Widget error = Text('...rendering error...'); if (widget is Scaffold || widget is Navigator) error = Scaffold(body: Center(child: error)); ErrorWidget.builder = (FlutterErrorDetails errorDetails) => error; - return widget; + return widget!; }, ), ); diff --git a/lib/ui/components/action_button/action_button.dart b/lib/ui/components/action_button/action_button.dart index 15565e343c..bc0393e717 100644 --- a/lib/ui/components/action_button/action_button.dart +++ b/lib/ui/components/action_button/action_button.dart @@ -3,14 +3,14 @@ import 'package:selfprivacy/config/brand_colors.dart'; class ActionButton extends StatelessWidget { const ActionButton({ - Key key, + Key? key, this.text, this.onPressed, this.isRed = false, }) : super(key: key); - final VoidCallback onPressed; - final String text; + final VoidCallback? onPressed; + final String? text; final bool isRed; @override @@ -19,12 +19,12 @@ class ActionButton extends StatelessWidget { return TextButton( child: Text( - text, + text!, style: isRed ? TextStyle(color: BrandColors.red1) : null, ), onPressed: () { navigator.pop(); - if (onPressed != null) onPressed(); + if (onPressed != null) onPressed!(); }, ); } diff --git a/lib/ui/components/brand_alert/brand_alert.dart b/lib/ui/components/brand_alert/brand_alert.dart index cf58606120..6f1a1b0f21 100644 --- a/lib/ui/components/brand_alert/brand_alert.dart +++ b/lib/ui/components/brand_alert/brand_alert.dart @@ -2,14 +2,14 @@ import 'package:flutter/material.dart'; class BrandAlert extends AlertDialog { BrandAlert({ - Key key, - String title, - String contentText, - List acitons, + Key? key, + String? title, + String? contentText, + List? acitons, }) : super( key: key, title: title != null ? Text(title) : null, - content: title != null ? Text(contentText) : null, + content: title != null ? Text(contentText!) : null, actions: acitons, ); } diff --git a/lib/ui/components/brand_button/brand_button.dart b/lib/ui/components/brand_button/brand_button.dart index d7e7fb67c6..192f8a8b29 100644 --- a/lib/ui/components/brand_button/brand_button.dart +++ b/lib/ui/components/brand_button/brand_button.dart @@ -8,10 +8,10 @@ enum BrandButtonTypes { rised, text, iconText } class BrandButton { static rised({ - Key key, - @required VoidCallback onPressed, - String title, - Widget child, + Key? key, + required VoidCallback? onPressed, + String? title, + Widget? child, }) { assert(title == null || child == null, 'required title or child'); assert(title != null || child != null, 'required title or child'); @@ -24,9 +24,9 @@ class BrandButton { } static text({ - Key key, - @required VoidCallback onPressed, - @required String title, + Key? key, + required VoidCallback onPressed, + required String title, }) => _TextButton( key: key, @@ -35,10 +35,10 @@ class BrandButton { ); static iconText({ - Key key, - @required VoidCallback onPressed, - @required String title, - @required Icon icon, + Key? key, + required VoidCallback onPressed, + required String title, + required Icon icon, }) => _IconTextButton( key: key, @@ -50,15 +50,15 @@ class BrandButton { class _RisedButton extends StatelessWidget { const _RisedButton({ - Key key, + Key? key, this.onPressed, this.title, this.child, }) : super(key: key); - final VoidCallback onPressed; - final String title; - final Widget child; + final VoidCallback? onPressed; + final String? title; + final Widget? child; @override Widget build(BuildContext context) { @@ -88,13 +88,13 @@ class _RisedButton extends StatelessWidget { class _TextButton extends StatelessWidget { const _TextButton({ - Key key, + Key? key, this.onPressed, this.title, }) : super(key: key); - final VoidCallback onPressed; - final String title; + final VoidCallback? onPressed; + final String? title; @override Widget build(BuildContext context) { @@ -106,7 +106,7 @@ class _TextButton extends StatelessWidget { alignment: Alignment.center, padding: EdgeInsets.all(12), child: Text( - title, + title!, style: TextStyle( color: BrandColors.blue, fontSize: 16, @@ -120,12 +120,12 @@ class _TextButton extends StatelessWidget { } class _IconTextButton extends StatelessWidget { - const _IconTextButton({Key key, this.onPressed, this.title, this.icon}) + const _IconTextButton({Key? key, this.onPressed, this.title, this.icon}) : super(key: key); - final VoidCallback onPressed; - final String title; - final Icon icon; + final VoidCallback? onPressed; + final String? title; + final Icon? icon; @override Widget build(BuildContext context) { diff --git a/lib/ui/components/brand_card/brand_card.dart b/lib/ui/components/brand_card/brand_card.dart index a30ef5b15d..9fcfcb6be6 100644 --- a/lib/ui/components/brand_card/brand_card.dart +++ b/lib/ui/components/brand_card/brand_card.dart @@ -4,11 +4,11 @@ import 'package:selfprivacy/utils/extensions/elevation_extension.dart'; class BrandCard extends StatelessWidget { const BrandCard({ - Key key, + Key? key, this.child, }) : super(key: key); - final Widget child; + final Widget? child; @override Widget build(BuildContext context) { diff --git a/lib/ui/components/brand_divider/brand_divider.dart b/lib/ui/components/brand_divider/brand_divider.dart index 00bd0ebf45..f031254f61 100644 --- a/lib/ui/components/brand_divider/brand_divider.dart +++ b/lib/ui/components/brand_divider/brand_divider.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; class BrandDivider extends StatelessWidget { - const BrandDivider({Key key}) : super(key: key); + const BrandDivider({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/components/brand_header/brand_header.dart b/lib/ui/components/brand_header/brand_header.dart index cff4d41a7c..fcbac7000a 100644 --- a/lib/ui/components/brand_header/brand_header.dart +++ b/lib/ui/components/brand_header/brand_header.dart @@ -4,8 +4,8 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class BrandHeader extends StatelessWidget { const BrandHeader({ - Key key, - @required this.title, + Key? key, + required this.title, this.hasBackButton = false, }) : super(key: key); diff --git a/lib/ui/components/brand_icons/brand_icons.dart b/lib/ui/components/brand_icons/brand_icons.dart index 06bad438db..9cd849415d 100644 --- a/lib/ui/components/brand_icons/brand_icons.dart +++ b/lib/ui/components/brand_icons/brand_icons.dart @@ -19,7 +19,7 @@ class BrandIcons { BrandIcons._(); static const _kFontFam = 'BrandIcons'; - static const _kFontPkg = null; + static const dynamic _kFontPkg = null; static const IconData connection = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); diff --git a/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart index 077fc0be73..681ded5317 100644 --- a/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart +++ b/lib/ui/components/brand_modal_sheet/brand_modal_sheet.dart @@ -4,11 +4,11 @@ var navigatorKey = GlobalKey(); class BrandModalSheet extends StatelessWidget { const BrandModalSheet({ - Key key, + Key? key, this.child, }) : super(key: key); - final Widget child; + final Widget? child; @override Widget build(BuildContext context) { return DraggableScrollableSheet( diff --git a/lib/ui/components/brand_span_button/brand_span_button.dart b/lib/ui/components/brand_span_button/brand_span_button.dart index ac7c53db41..d6cdcb02bf 100644 --- a/lib/ui/components/brand_span_button/brand_span_button.dart +++ b/lib/ui/components/brand_span_button/brand_span_button.dart @@ -5,21 +5,19 @@ import 'package:url_launcher/url_launcher.dart'; class BrandSpanButton extends TextSpan { BrandSpanButton({ - @required String text, - @required VoidCallback onTap, - TextStyle style, - }) : assert(text != null), - assert(onTap != null), - super( + required String text, + required VoidCallback onTap, + TextStyle? style, + }) : super( recognizer: TapGestureRecognizer()..onTap = onTap, text: text, style: (style ?? TextStyle()).copyWith(color: BrandColors.blue), ); static link({ - @required String text, - String urlString, - TextStyle style, + required String text, + String? urlString, + TextStyle? style, }) => BrandSpanButton( text: text, diff --git a/lib/ui/components/brand_tab_bar/brand_tab_bar.dart b/lib/ui/components/brand_tab_bar/brand_tab_bar.dart index 544dc6db65..2df248684b 100644 --- a/lib/ui/components/brand_tab_bar/brand_tab_bar.dart +++ b/lib/ui/components/brand_tab_bar/brand_tab_bar.dart @@ -1,37 +1,38 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; +import 'package:easy_localization/easy_localization.dart'; final _kBottomTabBarHeight = 51; class BrandTabBar extends StatefulWidget { - BrandTabBar({Key key, this.controller}) : super(key: key); + BrandTabBar({Key? key, this.controller}) : super(key: key); - final TabController controller; + final TabController? controller; @override _BrandTabBarState createState() => _BrandTabBarState(); } class _BrandTabBarState extends State { - int currentIndex; + int? currentIndex; @override void initState() { - currentIndex = widget.controller.index; - widget.controller.addListener(_listener); + currentIndex = widget.controller!.index; + widget.controller!.addListener(_listener); super.initState(); } _listener() { - if (currentIndex != widget.controller.index) { + if (currentIndex != widget.controller!.index) { setState(() { - currentIndex = widget.controller.index; + currentIndex = widget.controller!.index; }); } } @override void dispose() { - widget.controller ?? widget.controller.removeListener(_listener); + widget.controller ?? widget.controller!.removeListener(_listener); super.dispose(); } @@ -50,10 +51,10 @@ class _BrandTabBarState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _getIconButton('Провайдеры', BrandIcons.server, 0), - _getIconButton('Сервисы', BrandIcons.box, 1), - _getIconButton('Пользователи', BrandIcons.users, 2), - _getIconButton('Еще', BrandIcons.menu, 3), + _getIconButton('basis.providers'.tr(), BrandIcons.server, 0), + _getIconButton('basis.services'.tr(), BrandIcons.box, 1), + _getIconButton('basis.users'.tr(), BrandIcons.users, 2), + _getIconButton('basis.more'.tr(), BrandIcons.menu, 3), ], ), ), @@ -68,7 +69,7 @@ class _BrandTabBarState extends State { var isActive = currentIndex == index; var color = isActive ? acitivColor : BrandColors.inactive; return InkWell( - onTap: () => widget.controller.animateTo(index), + onTap: () => widget.controller!.animateTo(index), child: Padding( padding: EdgeInsets.all(6), child: ConstrainedBox( diff --git a/lib/ui/components/brand_text/brand_text.dart b/lib/ui/components/brand_text/brand_text.dart index 4440987be5..3efde9e20c 100644 --- a/lib/ui/components/brand_text/brand_text.dart +++ b/lib/ui/components/brand_text/brand_text.dart @@ -17,26 +17,26 @@ enum TextType { class BrandText extends StatelessWidget { const BrandText( this.text, { - Key key, + Key? key, this.style, - @required this.type, + required this.type, this.overflow, this.softWrap, this.textAlign, }) : super(key: key); - final String text; - final TextStyle style; + final String? text; + final TextStyle? style; final TextType type; - final TextOverflow overflow; - final bool softWrap; - final TextAlign textAlign; + final TextOverflow? overflow; + final bool? softWrap; + final TextAlign? textAlign; factory BrandText.h1( - String text, { - TextStyle style, - TextOverflow overflow, - bool softWrap, + String? text, { + TextStyle? style, + TextOverflow? overflow, + bool? softWrap, }) => BrandText( text, @@ -44,18 +44,18 @@ class BrandText extends StatelessWidget { style: style, ); - factory BrandText.onboardingTitle(String text, {TextStyle style}) => + factory BrandText.onboardingTitle(String text, {TextStyle? style}) => BrandText( text, type: TextType.onboardingTitle, style: style, ); - factory BrandText.h2(String text, {TextStyle style}) => BrandText( + factory BrandText.h2(String? text, {TextStyle? style}) => BrandText( text, type: TextType.h2, style: style, ); - factory BrandText.h3(String text, {TextStyle style, TextAlign textAlign}) => + factory BrandText.h3(String text, {TextStyle? style, TextAlign? textAlign}) => BrandText( text, type: TextType.h3, @@ -63,35 +63,35 @@ class BrandText extends StatelessWidget { textAlign: textAlign, overflow: TextOverflow.ellipsis, ); - factory BrandText.h4(String text, {TextStyle style}) => BrandText( + factory BrandText.h4(String? text, {TextStyle? style}) => BrandText( text, type: TextType.h4, style: style, ); - factory BrandText.body1(String text, {TextStyle style}) => BrandText( + factory BrandText.body1(String? text, {TextStyle? style}) => BrandText( text, type: TextType.body1, style: style, ); - factory BrandText.body2(String text, {TextStyle style}) => BrandText( + factory BrandText.body2(String? text, {TextStyle? style}) => BrandText( text, type: TextType.body2, style: style, ); - factory BrandText.medium(String text, - {TextStyle style, TextAlign textAlign}) => + factory BrandText.medium(String? text, + {TextStyle? style, TextAlign? textAlign}) => BrandText( text, type: TextType.medium, style: style, textAlign: textAlign, ); - factory BrandText.small(String text, {TextStyle style}) => BrandText( + factory BrandText.small(String text, {TextStyle? style}) => BrandText( text, type: TextType.small, style: style, ); - factory BrandText.buttonTitleText(String text, {TextStyle style}) => + factory BrandText.buttonTitleText(String? text, {TextStyle? style}) => BrandText( text, type: TextType.buttonTitleText, @@ -99,7 +99,7 @@ class BrandText extends StatelessWidget { ); @override Text build(BuildContext context) { - TextStyle style; + TextStyle? style; var isDark = Theme.of(context).brightness == Brightness.dark; switch (type) { @@ -153,7 +153,7 @@ class BrandText extends StatelessWidget { style = style.merge(this.style); } return Text( - text, + text!, style: style, overflow: overflow, softWrap: softWrap, diff --git a/lib/ui/components/brand_timer/brand_timer.dart b/lib/ui/components/brand_timer/brand_timer.dart index 17177c65e5..e1395cede3 100644 --- a/lib/ui/components/brand_timer/brand_timer.dart +++ b/lib/ui/components/brand_timer/brand_timer.dart @@ -6,21 +6,21 @@ import 'package:selfprivacy/utils/named_font_weight.dart'; class BrandTimer extends StatefulWidget { const BrandTimer({ - Key key, - @required this.startDateTime, - @required this.duration, + Key? key, + required this.startDateTime, + required this.duration, }) : super(key: key); - final DateTime startDateTime; - final Duration duration; + final DateTime? startDateTime; + final Duration? duration; @override _BrandTimerState createState() => _BrandTimerState(); } class _BrandTimerState extends State { - String _timeString; - Timer timer; + String? _timeString; + late Timer timer; @override void initState() { @@ -31,8 +31,8 @@ class _BrandTimerState extends State { _timerStart() { _timeString = diffenceFromStart; timer = Timer.periodic(Duration(seconds: 1), (Timer t) { - var timePassed = DateTime.now().difference(widget.startDateTime); - if (timePassed > widget.duration) { + var timePassed = DateTime.now().difference(widget.startDateTime!); + if (timePassed > widget.duration!) { t.cancel(); } else { _getTime(); @@ -66,12 +66,12 @@ class _BrandTimerState extends State { } String get diffenceFromStart => - _durationToString(DateTime.now().difference(widget.startDateTime)); + _durationToString(DateTime.now().difference(widget.startDateTime!)); String _durationToString(Duration duration) { String twoDigits(int n) => n.toString().padLeft(2, "0"); String twoDigitSeconds = - twoDigits(widget.duration.inSeconds - duration.inSeconds.remainder(60)); + twoDigits(widget.duration!.inSeconds - duration.inSeconds.remainder(60)); return "$twoDigitSeconds cек"; } diff --git a/lib/ui/components/dots_indicator/dots_indicator.dart b/lib/ui/components/dots_indicator/dots_indicator.dart index e95c308fed..ccf42aa5e2 100644 --- a/lib/ui/components/dots_indicator/dots_indicator.dart +++ b/lib/ui/components/dots_indicator/dots_indicator.dart @@ -3,9 +3,9 @@ import 'package:selfprivacy/config/brand_colors.dart'; class DotsIndicator extends StatelessWidget { const DotsIndicator({ - Key key, - @required this.activeIndex, - @required this.count, + Key? key, + required this.activeIndex, + required this.count, }) : super(key: key); final int activeIndex; diff --git a/lib/ui/components/error/error.dart b/lib/ui/components/error/error.dart index d6d75f2f06..4046106ef5 100644 --- a/lib/ui/components/error/error.dart +++ b/lib/ui/components/error/error.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; class BrandError extends StatelessWidget { - const BrandError({Key key, this.error, this.stackTrace}) : super(key: key); + const BrandError({Key? key, this.error, this.stackTrace}) : super(key: key); - final Object error; - final StackTrace stackTrace; + final Object? error; + final StackTrace? stackTrace; @override Widget build(BuildContext context) { diff --git a/lib/ui/components/icon_status_mask/icon_status_mask.dart b/lib/ui/components/icon_status_mask/icon_status_mask.dart index f02167da60..cf9fd1d727 100644 --- a/lib/ui/components/icon_status_mask/icon_status_mask.dart +++ b/lib/ui/components/icon_status_mask/icon_status_mask.dart @@ -3,14 +3,14 @@ import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/logic/models/state_types.dart'; class IconStatusMask extends StatelessWidget { - IconStatusMask({this.child, this.status}); + IconStatusMask({required this.child, required this.status}); final Icon child; final StateType status; @override Widget build(BuildContext context) { - List colors; + late List colors; switch (status) { case StateType.uninitialized: colors = BrandColors.uninitializedGradientColors; diff --git a/lib/ui/components/not_ready_card/not_ready_card.dart b/lib/ui/components/not_ready_card/not_ready_card.dart index 597d60317a..cd4a2fed13 100644 --- a/lib/ui/components/not_ready_card/not_ready_card.dart +++ b/lib/ui/components/not_ready_card/not_ready_card.dart @@ -2,9 +2,10 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/ui/pages/initializing/initializing.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:easy_localization/easy_localization.dart'; class NotReadyCard extends StatelessWidget { - const NotReadyCard({Key key}) : super(key: key); + const NotReadyCard({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -16,13 +17,13 @@ class NotReadyCard extends StatelessWidget { text: TextSpan( children: [ TextSpan( - text: 'Завершите настройку приложения используя ', + text: 'not_ready_card.1'.tr(), style: TextStyle(color: BrandColors.white), ), WidgetSpan( child: GestureDetector( child: Text( - 'Мастер подключения', + 'not_ready_card.2'.tr(), style: TextStyle( color: Theme.of(context).brightness == Brightness.dark ? Colors.blueAccent @@ -38,7 +39,7 @@ class NotReadyCard extends StatelessWidget { ), ), TextSpan( - text: ' для продолжения работы', + text: 'not_ready_card.3'.tr(), style: TextStyle(color: BrandColors.white), ), ], diff --git a/lib/ui/components/progress_bar/progress_bar.dart b/lib/ui/components/progress_bar/progress_bar.dart index e7cdc52492..270332397c 100644 --- a/lib/ui/components/progress_bar/progress_bar.dart +++ b/lib/ui/components/progress_bar/progress_bar.dart @@ -7,9 +7,9 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class ProgressBar extends StatefulWidget { ProgressBar({ - Key key, - @required this.steps, - @required this.activeIndex, + Key? key, + required this.steps, + required this.activeIndex, }) : super(key: key); final int activeIndex; @@ -102,14 +102,14 @@ class _ProgressBarState extends State { } Expanded _stepTitle({ - int index, - TextStyle style, - String step, + required int index, + TextStyle? style, + String? step, }) { var isActive = index == widget.activeIndex; var checked = index < widget.activeIndex; - style = isActive ? style.copyWith(fontWeight: FontWeight.w700) : style; + style = isActive ? style!.copyWith(fontWeight: FontWeight.w700) : style; return Expanded( flex: 2, child: RichText( diff --git a/lib/ui/components/switch_block/switch_bloc.dart b/lib/ui/components/switch_block/switch_bloc.dart index 57403bea3d..cddb2859c8 100644 --- a/lib/ui/components/switch_block/switch_bloc.dart +++ b/lib/ui/components/switch_block/switch_bloc.dart @@ -3,10 +3,10 @@ import 'package:selfprivacy/config/brand_colors.dart'; class SwitcherBlock extends StatelessWidget { const SwitcherBlock({ - Key key, - @required this.child, - @required this.isActive, - @required this.onChange, + Key? key, + required this.child, + required this.isActive, + required this.onChange, }) : super(key: key); final Widget child; diff --git a/lib/ui/pages/initializing/initializing.dart b/lib/ui/pages/initializing/initializing.dart index 86cea05a3e..01d47c8e9d 100644 --- a/lib/ui/pages/initializing/initializing.dart +++ b/lib/ui/pages/initializing/initializing.dart @@ -81,7 +81,7 @@ class InitializingPage extends StatelessWidget { onPressed: () { Navigator.of(context).pushAndRemoveUntil( materialRoute(RootPage()), - (predicate) => predicate == null, + (predicate) => false, ); }), SizedBox(height: 30), @@ -96,7 +96,7 @@ class InitializingPage extends StatelessWidget { return BlocProvider( create: (context) => HetznerFormCubit(initializingCubit), child: Builder(builder: (context) { - var formCubit = context.watch(); + var formCubitState = context.watch().state; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -111,7 +111,7 @@ class InitializingPage extends StatelessWidget { 'Здесь будут жить наши данные и SelfPrivacy-сервисы'), Spacer(), CubitFormTextField( - formFieldCubit: formCubit.apiKey, + formFieldCubit: context.read().apiKey, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -120,8 +120,9 @@ class InitializingPage extends StatelessWidget { ), Spacer(), BrandButton.rised( - onPressed: - formCubit.state.isSubmitting ? null : formCubit.trySubmit, + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), title: 'Подключить', ), SizedBox(height: 10), @@ -150,7 +151,7 @@ class InitializingPage extends StatelessWidget { return BlocProvider( create: (context) => CloudFlareFormCubit(initializingCubit), child: Builder(builder: (context) { - var formCubit = context.watch(); + var formCubitState = context.watch().state; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -165,7 +166,7 @@ class InitializingPage extends StatelessWidget { BrandText.body2('Для управления DNS вашего домена'), Spacer(), CubitFormTextField( - formFieldCubit: formCubit.apiKey, + formFieldCubit: context.read().apiKey, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -174,8 +175,9 @@ class InitializingPage extends StatelessWidget { ), Spacer(), BrandButton.rised( - onPressed: - formCubit.state.isSubmitting ? null : formCubit.trySubmit, + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), title: 'Подключить', ), SizedBox(height: 10), @@ -193,7 +195,7 @@ class InitializingPage extends StatelessWidget { return BlocProvider( create: (context) => BackblazeFormCubit(initializingCubit), child: Builder(builder: (context) { - var formCubit = context.watch(); + var formCubitState = context.watch().state; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -206,7 +208,7 @@ class InitializingPage extends StatelessWidget { SizedBox(height: 10), Spacer(), CubitFormTextField( - formFieldCubit: formCubit.keyId, + formFieldCubit: context.read().keyId, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -215,7 +217,7 @@ class InitializingPage extends StatelessWidget { ), Spacer(), CubitFormTextField( - formFieldCubit: formCubit.applicationKey, + formFieldCubit: context.read().applicationKey, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -224,8 +226,9 @@ class InitializingPage extends StatelessWidget { ), Spacer(), BrandButton.rised( - onPressed: - formCubit.state.isSubmitting ? null : formCubit.trySubmit, + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), title: 'Подключить', ), SizedBox(height: 10), @@ -243,8 +246,7 @@ class InitializingPage extends StatelessWidget { return BlocProvider( create: (context) => DomainSetupCubit(initializingCubit)..load(), child: Builder(builder: (context) { - var domainSetup = context.watch(); - var state = domainSetup.state; + DomainSetupState state = context.watch().state; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -283,7 +285,7 @@ class InitializingPage extends StatelessWidget { Container( width: 50, child: BrandButton.rised( - onPressed: () => domainSetup.load(), + onPressed: () => context.read().load(), child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, @@ -302,7 +304,7 @@ class InitializingPage extends StatelessWidget { if (state is Empty) ...[ SizedBox(height: 30), BrandButton.rised( - onPressed: () => domainSetup.load(), + onPressed: () => context.read().load(), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -319,7 +321,7 @@ class InitializingPage extends StatelessWidget { if (state is Loaded) ...[ SizedBox(height: 30), BrandButton.rised( - onPressed: () => domainSetup.saveDomain(), + onPressed: () => context.read().saveDomain(), title: 'Сохранить домен', ), ], @@ -340,7 +342,7 @@ class InitializingPage extends StatelessWidget { return BlocProvider( create: (context) => RootUserFormCubit(initializingCubit), child: Builder(builder: (context) { - var formCubit = context.watch(); + var formCubitState = context.watch().state; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -348,7 +350,7 @@ class InitializingPage extends StatelessWidget { Spacer(), SizedBox(height: 10), CubitFormTextField( - formFieldCubit: formCubit.userName, + formFieldCubit: context.read().userName, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -357,12 +359,12 @@ class InitializingPage extends StatelessWidget { ), SizedBox(height: 10), BlocBuilder, FieldCubitState>( - bloc: formCubit.isVisible, + bloc: context.read().isVisible, builder: (context, state) { var isVisible = state.value; return CubitFormTextField( obscureText: !isVisible, - formFieldCubit: formCubit.password, + formFieldCubit: context.read().password, textAlign: TextAlign.center, scrollPadding: EdgeInsets.only(bottom: 70), decoration: InputDecoration( @@ -371,7 +373,10 @@ class InitializingPage extends StatelessWidget { icon: Icon( isVisible ? Icons.visibility : Icons.visibility_off, ), - onPressed: () => formCubit.isVisible.setValue(!isVisible), + onPressed: () => context + .read() + .isVisible + .setValue(!isVisible), ), suffixIconConstraints: BoxConstraints(minWidth: 60), prefixIconConstraints: BoxConstraints(maxWidth: 85), @@ -382,8 +387,9 @@ class InitializingPage extends StatelessWidget { ), Spacer(), BrandButton.rised( - onPressed: - formCubit.state.isSubmitting ? null : formCubit.trySubmit, + onPressed: formCubitState.isSubmitting + ? null + : () => context.read().trySubmit(), title: 'Подключить', ), SizedBox(height: 10), @@ -410,7 +416,7 @@ class InitializingPage extends StatelessWidget { Spacer(), BrandButton.rised( onPressed: - isLoading ? null : appConfigCubit.createServerAndSetDnsRecords, + isLoading! ? null : appConfigCubit.createServerAndSetDnsRecords, title: isLoading ? 'loading' : 'Создать сервер', ), Spacer(flex: 2), @@ -427,10 +433,10 @@ class InitializingPage extends StatelessWidget { assert(appConfigCubit.state is TimerState, 'wronge state'); var state = appConfigCubit.state as TimerState; - String text; - if (state.isServerReseted) { + String? text; + if (state.isServerReseted!) { text = 'Сервер презагружен, ждем последнюю проверку'; - } else if (state.isServerStarted) { + } else if (state.isServerStarted!) { text = 'Cервер запушен, сейчас он будет проверен и перезагружен'; } else if (state.isServerCreated) { text = 'Cервер создан, идет проверка ДНС адресов и запуск сервера'; @@ -443,7 +449,7 @@ class InitializingPage extends StatelessWidget { SizedBox(height: 10), BrandText.body2(text), SizedBox(height: 10), - if (!state.isLoading) + if (!state.isLoading!) Row( children: [ BrandText.body2('До следующей проверки: '), @@ -453,7 +459,7 @@ class InitializingPage extends StatelessWidget { ) ], ), - if (state.isLoading) BrandText.body2('Проверка'), + if (state.isLoading!) BrandText.body2('Проверка'), Spacer( flex: 2, ), @@ -477,7 +483,7 @@ class InitializingPage extends StatelessWidget { class _HowHetzner extends StatelessWidget { const _HowHetzner({ - Key key, + Key? key, }) : super(key: key); @override diff --git a/lib/ui/pages/more/about/about.dart b/lib/ui/pages/more/about/about.dart index d106f9f8bd..ac31338f88 100644 --- a/lib/ui/pages/more/about/about.dart +++ b/lib/ui/pages/more/about/about.dart @@ -5,7 +5,7 @@ import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; class AboutPage extends StatelessWidget { - const AboutPage({Key key}) : super(key: key); + const AboutPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/pages/more/app_settings/app_setting.dart b/lib/ui/pages/more/app_settings/app_setting.dart index b52885b3b6..279b6443ff 100644 --- a/lib/ui/pages/more/app_settings/app_setting.dart +++ b/lib/ui/pages/more/app_settings/app_setting.dart @@ -11,7 +11,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/utils/named_font_weight.dart'; class AppSettingsPage extends StatefulWidget { - const AppSettingsPage({Key key}) : super(key: key); + const AppSettingsPage({Key? key}) : super(key: key); @override _AppSettingsPageState createState() => _AppSettingsPageState(); @@ -20,9 +20,7 @@ class AppSettingsPage extends StatefulWidget { class _AppSettingsPageState extends State { @override Widget build(BuildContext context) { - var appSettings = context.watch(); - - var isDarkModeOn = appSettings.state.isDarkModeOn; + var isDarkModeOn = context.watch().state.isDarkModeOn; return SafeArea( child: Builder(builder: (context) { @@ -57,8 +55,9 @@ class _AppSettingsPageState extends State { activeColor: BrandColors.green1, activeTrackColor: BrandColors.green2, value: Theme.of(context).brightness == Brightness.dark, - onChanged: (value) => appSettings.updateDarkMode( - isDarkModeOn: !isDarkModeOn), + onChanged: (value) => context + .read() + .updateDarkMode(isDarkModeOn: !isDarkModeOn), ), ], ), @@ -130,9 +129,9 @@ class _AppSettingsPageState extends State { class _TextColumn extends StatelessWidget { const _TextColumn({ - Key key, - @required this.title, - @required this.value, + Key? key, + required this.title, + required this.value, this.hasWarning = false, }) : super(key: key); diff --git a/lib/ui/pages/more/console/console.dart b/lib/ui/pages/more/console/console.dart index 257aa0f3d1..5b89ee87a7 100644 --- a/lib/ui/pages/more/console/console.dart +++ b/lib/ui/pages/more/console/console.dart @@ -9,7 +9,7 @@ import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; class Console extends StatefulWidget { - const Console({Key key}) : super(key: key); + const Console({Key? key}) : super(key: key); @override _ConsoleState createState() => _ConsoleState(); diff --git a/lib/ui/pages/more/info/info.dart b/lib/ui/pages/more/info/info.dart index 68cbd19712..21906e5dae 100644 --- a/lib/ui/pages/more/info/info.dart +++ b/lib/ui/pages/more/info/info.dart @@ -6,7 +6,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:package_info/package_info.dart'; class InfoPage extends StatelessWidget { - const InfoPage({Key key}) : super(key: key); + const InfoPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/pages/more/more.dart b/lib/ui/pages/more/more.dart index 88f2326f30..acd7bb0ad4 100644 --- a/lib/ui/pages/more/more.dart +++ b/lib/ui/pages/more/more.dart @@ -9,6 +9,7 @@ import 'package:selfprivacy/ui/pages/initializing/initializing.dart'; import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart'; import 'package:selfprivacy/ui/pages/rootRoute.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'about/about.dart'; import 'app_settings/app_setting.dart'; @@ -16,13 +17,13 @@ import 'console/console.dart'; import 'info/info.dart'; class MorePage extends StatelessWidget { - const MorePage({Key key}) : super(key: key); + const MorePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: PreferredSize( - child: BrandHeader(title: 'Еще'), + child: BrandHeader(title: 'basis.more'.tr()), preferredSize: Size.fromHeight(52), ), body: ListView( @@ -33,32 +34,32 @@ class MorePage extends StatelessWidget { children: [ BrandDivider(), _NavItem( - title: 'Мастер Подключения', + title: 'more.configuration_wizard'.tr(), iconData: BrandIcons.settings, goTo: InitializingPage(), ), _NavItem( - title: 'Настройки приложения', + title: 'more.settings'.tr(), iconData: BrandIcons.settings, goTo: AppSettingsPage(), ), _NavItem( - title: 'О проекте Selfprivacy', + title: 'more.about_project'.tr(), iconData: BrandIcons.triangle, goTo: AboutPage(), ), _NavItem( - title: 'О приложении', + title: 'more.about_app'.tr(), iconData: BrandIcons.help, goTo: InfoPage(), ), _NavItem( - title: 'Onboarding', + title: 'more.onboarding'.tr(), iconData: BrandIcons.triangle, goTo: OnboardingPage(nextPage: RootPage()), ), _NavItem( - title: 'Console', + title: 'more.console'.tr(), iconData: BrandIcons.triangle, goTo: Console(), ), @@ -73,10 +74,10 @@ class MorePage extends StatelessWidget { class _NavItem extends StatelessWidget { const _NavItem({ - Key key, - @required this.iconData, - @required this.goTo, - @required this.title, + Key? key, + required this.iconData, + required this.goTo, + required this.title, }) : super(key: key); final IconData iconData; diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index 3c622156fb..07790f607e 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -3,9 +3,10 @@ import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:easy_localization/easy_localization.dart'; class OnboardingPage extends StatefulWidget { - const OnboardingPage({Key key, @required this.nextPage}) : super(key: key); + const OnboardingPage({Key? key, required this.nextPage}) : super(key: key); final Widget nextPage; @override @@ -54,10 +55,10 @@ class _OnboardingPageState extends State { children: [ SizedBox(height: 30), BrandText.h2( - 'Цифровая независимость и приватность, доступная каждому'), + 'onboarding.page1_title'.tr(), + ), SizedBox(height: 20), - BrandText.body2( - 'Почта и мессенджер с открытым исходным кодом на вашем личном сервере под вашим полным контролем.'), + BrandText.body2('onboarding.page1_text'.tr()), Flexible( child: Center( child: Image.asset( @@ -78,7 +79,7 @@ class _OnboardingPageState extends State { curve: Curves.easeIn, ); }, - title: 'Далее', + title: 'basis.next'.tr(), ), SizedBox(height: 30), ], @@ -94,10 +95,9 @@ class _OnboardingPageState extends State { child: Column( children: [ SizedBox(height: 30), - BrandText.h2('Для работы понадобятся ваши аккаунты'), + BrandText.h2('onboarding.page2_title'.tr()), SizedBox(height: 20), - BrandText.body2( - 'Для максимальноей приватности и независимости SelfPrivacy не использует свои серверы. \n \n Если у вас нет домена, аккаунтов на Hetzner, AWS и Clouflare, мы поможем их создать и подключить.'), + BrandText.body2('onboarding.page2_text'.tr()), SizedBox(height: 20), Center( child: Image.asset( @@ -127,7 +127,7 @@ class _OnboardingPageState extends State { Navigator.of(context) .pushReplacement(materialRoute(widget.nextPage)); }, - title: 'Понял', + title: 'basis.got_it'.tr(), ), SizedBox(height: 30), ], @@ -137,10 +137,10 @@ class _OnboardingPageState extends State { } String _fileName({ - @required BuildContext context, - @required String path, - @required String fileName, - @required String fileExtention, + required BuildContext context, + required String path, + required String fileName, + required String fileExtention, }) { var theme = Theme.of(context); var isDark = theme.brightness == Brightness.dark; diff --git a/lib/ui/pages/providers/providers.dart b/lib/ui/pages/providers/providers.dart index c2869a0df0..16afa6d9fb 100644 --- a/lib/ui/pages/providers/providers.dart +++ b/lib/ui/pages/providers/providers.dart @@ -12,9 +12,10 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/pages/providers/settings/settings.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; +import 'package:easy_localization/easy_localization.dart'; class ProvidersPage extends StatefulWidget { - ProvidersPage({Key key}) : super(key: key); + ProvidersPage({Key? key}) : super(key: key); @override _ProvidersPageState createState() => _ProvidersPageState(); @@ -23,7 +24,8 @@ class ProvidersPage extends StatefulWidget { class _ProvidersPageState extends State { @override Widget build(BuildContext context) { - var isReady = context.watch().state.isFullyInitilized; + // var isReady = context.watch().state.isFullyInitilized; + var isReady = true; final cards = ProviderType.values .map((type) => _Card( @@ -32,7 +34,7 @@ class _ProvidersPageState extends State { .toList(); return Scaffold( appBar: PreferredSize( - child: BrandHeader(title: 'Провайдеры'), + child: BrandHeader(title: 'providers.page_title'.tr()), preferredSize: Size.fromHeight(52), ), body: ListView( @@ -50,32 +52,31 @@ class _ProvidersPageState extends State { } class _Card extends StatelessWidget { - const _Card({Key key, @required this.provider}) : super(key: key); + const _Card({Key? key, required this.provider}) : super(key: key); final ProviderModel provider; @override Widget build(BuildContext context) { - String title; - String message; - String stableText; - var appConfig = context.watch().state; + String? title; + String? message; + String? stableText; + AppConfigState appConfig = context.watch().state; var domainName = - appConfig.isDomainFilled ? appConfig.cloudFlareDomain.domainName : ''; + appConfig.isDomainFilled ? appConfig.cloudFlareDomain!.domainName : ''; switch (provider.type) { case ProviderType.server: - title = 'Сервер'; + title = 'providers.server.card_title'.tr(); stableText = 'В норме'; break; case ProviderType.domain: - title = 'Домен'; + title = 'providers.domain.card_title'.tr(); message = domainName; stableText = 'Домен настроен'; break; case ProviderType.backup: - // message = '22 янв 2021 14:30'; - title = 'Резервное копирование'; + title = 'providers.backup.card_title'.tr(); stableText = 'В норме'; break; } @@ -116,28 +117,29 @@ class _Card extends StatelessWidget { class _ProviderDetails extends StatelessWidget { const _ProviderDetails({ - Key key, - @required this.provider, - @required this.statusText, + Key? key, + required this.provider, + required this.statusText, }) : super(key: key); final ProviderModel provider; - final String statusText; + final String? statusText; @override Widget build(BuildContext context) { - String title; + late String title; switch (provider.type) { case ProviderType.server: - title = 'Сервер'; + title = 'providers.server.card_title'.tr(); break; case ProviderType.domain: - title = 'Домен'; + title = 'providers.domain.card_title'.tr(); break; case ProviderType.backup: - title = 'Резервное копирование'; + title = 'providers.backup.card_title'.tr(); + break; } return BrandModalSheet( @@ -163,7 +165,7 @@ class _ProviderDetails extends StatelessWidget { onSelected: (_PopupMenuItemType result) { switch (result) { case _PopupMenuItemType.setting: - navigatorKey.currentState + navigatorKey.currentState! .push(materialRoute(SettingsPage())); break; } diff --git a/lib/ui/pages/providers/settings/settings.dart b/lib/ui/pages/providers/settings/settings.dart index 933fff8cd9..48460786d8 100644 --- a/lib/ui/pages/providers/settings/settings.dart +++ b/lib/ui/pages/providers/settings/settings.dart @@ -7,7 +7,7 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart'; class SettingsPage extends StatelessWidget { - const SettingsPage({Key key}) : super(key: key); + const SettingsPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -62,9 +62,9 @@ class SettingsPage extends StatelessWidget { class _Button extends StatelessWidget { const _Button({ - Key key, - @required this.onTap, - @required this.child, + Key? key, + required this.onTap, + required this.child, }) : super(key: key); final Widget child; @@ -88,9 +88,9 @@ class _Button extends StatelessWidget { class _TextColumn extends StatelessWidget { const _TextColumn({ - Key key, - @required this.title, - @required this.value, + Key? key, + required this.title, + required this.value, this.hasWarning = false, }) : super(key: key); diff --git a/lib/ui/pages/rootRoute.dart b/lib/ui/pages/rootRoute.dart index 8182a5c807..f11dc73718 100644 --- a/lib/ui/pages/rootRoute.dart +++ b/lib/ui/pages/rootRoute.dart @@ -7,7 +7,7 @@ import 'package:selfprivacy/ui/pages/services/services.dart'; import 'package:selfprivacy/ui/pages/users/users.dart'; class RootPage extends StatefulWidget { - const RootPage({Key key}) : super(key: key); + const RootPage({Key? key}) : super(key: key); @override _RootPageState createState() => _RootPageState(); @@ -15,7 +15,7 @@ class RootPage extends StatefulWidget { class _RootPageState extends State with SingleTickerProviderStateMixin { - TabController tabController; + TabController? tabController; @override void initState() { @@ -26,7 +26,7 @@ class _RootPageState extends State @override void dispose() { super.dispose(); - tabController.dispose(); + tabController!.dispose(); } @override diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index 452f69a826..704e8d2542 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -12,7 +12,7 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; class ServicesPage extends StatefulWidget { - ServicesPage({Key key}) : super(key: key); + ServicesPage({Key? key}) : super(key: key); @override _ServicesPageState createState() => _ServicesPageState(); @@ -21,9 +21,10 @@ class ServicesPage extends StatefulWidget { class _ServicesPageState extends State { @override Widget build(BuildContext context) { - final serviceCubit = context.watch(); - final connected = serviceCubit.state.connected; - final uninitialized = serviceCubit.state.uninitialized; + final serviceCubitState = context.watch().state; + + final connected = serviceCubitState.connected; + final uninitialized = serviceCubitState.uninitialized; var isReady = context.watch().state.isFullyInitilized; return Scaffold( @@ -49,14 +50,14 @@ class _ServicesPageState extends State { } class _Card extends StatelessWidget { - const _Card({Key key, @required this.service}) : super(key: key); + const _Card({Key? key, required this.service}) : super(key: key); final Service service; @override Widget build(BuildContext context) { - String title; - IconData iconData; - String description; + String? title; + IconData? iconData; + String? description; switch (service.type) { case ServiceTypes.messanger: diff --git a/lib/ui/pages/users/empty.dart b/lib/ui/pages/users/empty.dart index 8f89cc6ae8..9a7c368812 100644 --- a/lib/ui/pages/users/empty.dart +++ b/lib/ui/pages/users/empty.dart @@ -1,9 +1,7 @@ part of 'users.dart'; class _NoUsers extends StatelessWidget { - const _NoUsers({Key key, @required this.text}) - : assert(text != null), - super(key: key); + const _NoUsers({Key? key, required this.text}) : super(key: key); final String text; diff --git a/lib/ui/pages/users/fab.dart b/lib/ui/pages/users/fab.dart index 7aa7222758..9919381fd9 100644 --- a/lib/ui/pages/users/fab.dart +++ b/lib/ui/pages/users/fab.dart @@ -1,7 +1,7 @@ part of 'users.dart'; class _Fab extends StatelessWidget { - const _Fab({Key key}) : super(key: key); + const _Fab({Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/ui/pages/users/new_user.dart b/lib/ui/pages/users/new_user.dart index 6847bdf7ef..2255a1f50d 100644 --- a/lib/ui/pages/users/new_user.dart +++ b/lib/ui/pages/users/new_user.dart @@ -3,13 +3,12 @@ part of 'users.dart'; class _NewUser extends StatelessWidget { @override Widget build(BuildContext context) { - final usersCubit = context.watch(); - return BrandModalSheet( child: BlocProvider( - create: (context) => UserFormCubit(usersCubit: usersCubit), + create: (context) => + UserFormCubit(usersCubit: context.watch()), child: Builder(builder: (context) { - var formCubit = context.watch(); + var formCubitState = context.watch().state; return BlocListener( listener: (context, state) { @@ -27,7 +26,7 @@ class _NewUser extends StatelessWidget { child: Column( children: [ CubitFormTextField( - formFieldCubit: formCubit.login, + formFieldCubit: context.read().login, decoration: InputDecoration( labelText: 'Логин', suffixText: '@example', @@ -35,7 +34,7 @@ class _NewUser extends StatelessWidget { ), SizedBox(height: 20), CubitFormTextField( - formFieldCubit: formCubit.password, + formFieldCubit: context.read().password, decoration: InputDecoration( alignLabelWithHint: false, labelText: 'Пароль', @@ -46,18 +45,17 @@ class _NewUser extends StatelessWidget { BrandIcons.refresh, color: BrandColors.blue, ), - onPressed: formCubit.genNewPassword, + onPressed: + context.read().genNewPassword, ), ), ), ), SizedBox(height: 30), BrandButton.rised( - onPressed: formCubit.state.isSubmitting + onPressed: formCubitState.isSubmitting ? null - : () { - formCubit.trySubmit(); - }, + : () => context.read().trySubmit(), title: 'Создать', ), SizedBox(height: 40), diff --git a/lib/ui/pages/users/user.dart b/lib/ui/pages/users/user.dart index 8084969d28..f01a362afa 100644 --- a/lib/ui/pages/users/user.dart +++ b/lib/ui/pages/users/user.dart @@ -1,9 +1,9 @@ part of 'users.dart'; class _User extends StatelessWidget { - const _User({Key key, this.user}) : super(key: key); + const _User({Key? key, this.user}) : super(key: key); - final User user; + final User? user; @override Widget build(BuildContext context) { return InkWell( @@ -26,12 +26,12 @@ class _User extends StatelessWidget { width: 17, height: 17, decoration: BoxDecoration( - color: user.color, + color: user!.color, shape: BoxShape.circle, ), ), SizedBox(width: 20), - BrandText.h4(user.login), + BrandText.h4(user!.login), ], ), ), diff --git a/lib/ui/pages/users/user_details.dart b/lib/ui/pages/users/user_details.dart index 6f90eeef4b..ceafcbd2fc 100644 --- a/lib/ui/pages/users/user_details.dart +++ b/lib/ui/pages/users/user_details.dart @@ -2,11 +2,11 @@ part of 'users.dart'; class _UserDetails extends StatelessWidget { const _UserDetails({ - Key key, + Key? key, this.user, }) : super(key: key); - final User user; + final User? user; @override Widget build(BuildContext context) { @@ -17,7 +17,7 @@ class _UserDetails extends StatelessWidget { Container( height: 200, decoration: BoxDecoration( - color: user.color, + color: user!.color, borderRadius: BorderRadius.vertical( top: Radius.circular(20), ), @@ -109,7 +109,7 @@ class _UserDetails extends StatelessWidget { horizontal: 15, ), child: BrandText.h1( - user.login, + user!.login, softWrap: true, overflow: TextOverflow.ellipsis, )), @@ -126,14 +126,14 @@ class _UserDetails extends StatelessWidget { Container( height: 40, alignment: Alignment.centerLeft, - child: BrandText.h4('${user.login}@example.com'), + child: BrandText.h4('${user!.login}@example.com'), ), SizedBox(height: 14), BrandText.small('Пароль'), Container( height: 40, alignment: Alignment.centerLeft, - child: BrandText.h4(user.password), + child: BrandText.h4(user!.password), ), SizedBox(height: 24), BrandDivider(), diff --git a/lib/ui/pages/users/users.dart b/lib/ui/pages/users/users.dart index c7f6ba88c2..003d776843 100644 --- a/lib/ui/pages/users/users.dart +++ b/lib/ui/pages/users/users.dart @@ -21,14 +21,14 @@ part 'user.dart'; part 'empty.dart'; class UsersPage extends StatelessWidget { - const UsersPage({Key key}) : super(key: key); + const UsersPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final usersCubit = context.watch(); + final usersCubitState = context.watch().state; var isReady = context.watch().state.isFullyInitilized; - final users = usersCubit.state.users; - final isEmpty = usersCubit.state.isEmpty; + final users = usersCubitState.users; + final isEmpty = usersCubitState.isEmpty; Widget child; diff --git a/lib/utils/extensions/elevation_extension.dart b/lib/utils/extensions/elevation_extension.dart index 5732c8f929..8be106fa7e 100644 --- a/lib/utils/extensions/elevation_extension.dart +++ b/lib/utils/extensions/elevation_extension.dart @@ -8,14 +8,14 @@ extension ElevationExtension on BoxDecoration { BoxDecoration get ev8 => copyWith(boxShadow: [shadow8]); BoxDecoration copyWith({ - Color color, - DecorationImage image, - BoxBorder border, - BorderRadiusGeometry borderRadius, - List boxShadow, - Gradient gradient, - BlendMode backgroundBlendMode, - BoxShape shape, + Color? color, + DecorationImage? image, + BoxBorder? border, + BorderRadiusGeometry? borderRadius, + List? boxShadow, + Gradient? gradient, + BlendMode? backgroundBlendMode, + BoxShape? shape, }) { return BoxDecoration( color: color ?? this.color, diff --git a/lib/utils/password_generator.dart b/lib/utils/password_generator.dart index 6b3e909881..a0ce627381 100644 --- a/lib/utils/password_generator.dart +++ b/lib/utils/password_generator.dart @@ -12,10 +12,10 @@ String genPass() { ///The password [_generatedValue] is of a specified length, including letters [_letterGen] of mixed cases, ///numbers [_numGen], and symbols[_symGen] depending on user choice. class PasswordGenerator { - bool _letterGen; - bool _numGen; - bool _symGen; - String _generatedValue; + late bool _letterGen; + late bool _numGen; + late bool _symGen; + late String _generatedValue; ///Constructor. /// @@ -43,7 +43,7 @@ class PasswordGenerator { ///'Randomly' selectes caracter type to generate and append [toAppend] to [_generatedValue] // ignore: unnecessary_statements for (n; n > 0; n--) { - String toAppend; + String? toAppend; var random = new Random(); ///loops until a valid character is generated, meaning the user has to check the character value @@ -67,7 +67,7 @@ class PasswordGenerator { ///Generates a letter when called. String _generateLetter() { - if (!_letterGen) return null; + if (!_letterGen) return ''; ///Finds the integer value for the range between a-z and A-Z, with [base] UTF-16 value for lowercase letters and ///[baseUpper] UTF-16 value for uppercase letters @@ -87,7 +87,7 @@ class PasswordGenerator { } ///Generates a number when called - String _generateNumber() { + String? _generateNumber() { if (!_numGen) return null; ///Finds the integer value for the range between 0-9 @@ -101,7 +101,7 @@ class PasswordGenerator { } ///Generates a symbol when called - String _generateSymbol() { + String? _generateSymbol() { if (!_symGen) return null; ///Finds the integer value for the range between symbols !-. diff --git a/lib/utils/route_transitions/slide_bottom.dart b/lib/utils/route_transitions/slide_bottom.dart index 115831f52a..607ab105e8 100644 --- a/lib/utils/route_transitions/slide_bottom.dart +++ b/lib/utils/route_transitions/slide_bottom.dart @@ -37,7 +37,7 @@ class SlideBottomRoute extends PageRouteBuilder { SlideBottomRoute(this.widget) : super( pageBuilder: pageBuilder(widget), - transitionsBuilder: transitionsBuilder, + transitionsBuilder: transitionsBuilder as Widget Function(BuildContext, Animation, Animation, Widget), ); final Widget widget; diff --git a/lib/utils/route_transitions/slide_right.dart b/lib/utils/route_transitions/slide_right.dart index 603b6bd06a..ae9129e7a0 100644 --- a/lib/utils/route_transitions/slide_right.dart +++ b/lib/utils/route_transitions/slide_right.dart @@ -37,7 +37,7 @@ class SlideRightRoute extends PageRouteBuilder { SlideRightRoute(this.widget) : super( pageBuilder: pageBuilder(widget), - transitionsBuilder: transitionsBuilder, + transitionsBuilder: transitionsBuilder as Widget Function(BuildContext, Animation, Animation, Widget), ); final Widget widget; diff --git a/pubspec.yaml b/pubspec.yaml index abbb291351..0e312fd38d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,8 @@ publish_to: 'none' version: 0.1.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' + flutter: ">=2.0.0" dependencies: flutter: