criada a conexão com a api na api_get_pass.dart na tela tela login_screen.dart e feito a encrypt_password.dart
This commit is contained in:
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
|
|||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion flutter.compileSdkVersion
|
compileSdkVersion 32
|
||||||
ndkVersion flutter.ndkVersion
|
ndkVersion flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -47,7 +47,7 @@ android {
|
|||||||
applicationId "com.ab.rkm.rkm"
|
applicationId "com.ab.rkm.rkm"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 19
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|||||||
BIN
assets/images/desenvolvimento.png
Normal file
BIN
assets/images/desenvolvimento.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
BIN
assets/images/homologacao.png
Normal file
BIN
assets/images/homologacao.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
BIN
assets/images/loading.gif
Normal file
BIN
assets/images/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -1,5 +1,7 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:rkm/service/url_api_const.dart';
|
||||||
import 'package:rkm/utils/color_palette.dart';
|
import 'package:rkm/utils/color_palette.dart';
|
||||||
import 'package:rkm/utils/const_variable.dart';
|
import 'package:rkm/utils/const_variable.dart';
|
||||||
import 'package:rkm/widgets/button_default.dart';
|
import 'package:rkm/widgets/button_default.dart';
|
||||||
@@ -7,6 +9,8 @@ import 'package:rkm/widgets/dropdown_button_city.dart';
|
|||||||
import 'package:rkm/widgets/input_text.dart';
|
import 'package:rkm/widgets/input_text.dart';
|
||||||
import 'package:rkm/widgets/text_default.dart';
|
import 'package:rkm/widgets/text_default.dart';
|
||||||
|
|
||||||
|
import '../service/api_get_pass.dart';
|
||||||
|
import '../service/encrypt_password.dart';
|
||||||
class LoginScreen extends StatefulWidget {
|
class LoginScreen extends StatefulWidget {
|
||||||
const LoginScreen({Key? key}) : super(key: key);
|
const LoginScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@@ -22,24 +26,45 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
String? now;
|
String? now;
|
||||||
String? selectCity;
|
String? selectCity;
|
||||||
bool validatorDropDown= false;
|
bool validatorDropDown= false;
|
||||||
|
int contLogo = 0;
|
||||||
|
String mode = 'online';
|
||||||
|
String url = UrlApiConst.ApiUrlOnline;
|
||||||
|
|
||||||
checkLogin(){
|
checkLogin()async{
|
||||||
// if(inputUser.text.isNotEmpty && inputPassword.text.isNotEmpty && inputUser.text == 'teste' && inputPassword.text == '123'){
|
if(inputUser.text.isNotEmpty && inputPassword.text.isNotEmpty && inputUser.text.length>3 && inputPassword.text.length>3){
|
||||||
// if(selectCity!=null){
|
if(selectCity!=null){
|
||||||
setState(() {
|
setState(() {
|
||||||
error = '';
|
error = '';
|
||||||
});
|
});
|
||||||
Navigator.pushNamed(context, '/home');
|
await ApiGetPass().apiConect(selectCity,mode,inputUser.text,url).then((response){
|
||||||
// }else{
|
print(response);
|
||||||
// setState(() {
|
print(inputUser.text);
|
||||||
// error = 'Selecione sua cidade';
|
print(inputPassword.text);
|
||||||
// });
|
if(inputUser.text == inputPassword.text || response['bloqueio']==1){
|
||||||
// }
|
setState(() {
|
||||||
// }else{
|
error = 'Usuário bloqueado/senha incorreta';
|
||||||
// setState(() {
|
});
|
||||||
// error = 'Usuário/senha inválido(s)';
|
}else if(response['status']==0) {
|
||||||
// });
|
setState(() {
|
||||||
// }
|
error = 'Usuário não encontrado';
|
||||||
|
});
|
||||||
|
}else if(response['status']==1) {
|
||||||
|
setState((){
|
||||||
|
error = '';
|
||||||
|
print(EncryptPassword().encrypt(inputPassword.text,response['userPass']));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
setState(() {
|
||||||
|
error = 'Selecione sua cidade';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
setState(() {
|
||||||
|
error = 'Usuário/senha inválido(s)';
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -61,15 +86,15 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: TextDefault(text: 'RKM AB - Carga Inicial',fontSize: ConstVariable().fontSizeTitleAppBar,color: ColorPalette.white),
|
title: TextDefault(text: 'RKM AB - Carga Inicial',fontSize: ConstVariable().fontSizeTitleAppBar,color: ColorPalette.white),
|
||||||
),
|
),
|
||||||
bottomSheet: Container(
|
// bottomSheet: Container(
|
||||||
color: ColorPalette.secundary,
|
// color: ColorPalette.secundary,
|
||||||
padding: EdgeInsets.all(8.0),
|
// padding: EdgeInsets.all(8.0),
|
||||||
child: TextDefault(
|
// child: TextDefault(
|
||||||
text: 'Última sincronização $now',
|
// text: 'Última sincronização $now',
|
||||||
fontSize: 15,
|
// fontSize: 15,
|
||||||
color: ColorPalette.gray,
|
// color: ColorPalette.gray,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.only(top: height*0.2),
|
padding: EdgeInsets.only(top: height*0.2),
|
||||||
@@ -80,7 +105,27 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Image.asset('assets/images/logo.PNG',width: width*0.4),
|
GestureDetector(
|
||||||
|
onTap: ()=>setState((){
|
||||||
|
contLogo++;
|
||||||
|
if(contLogo>=5 && contLogo<=10){
|
||||||
|
mode = 'homologacao';
|
||||||
|
url = UrlApiConst.ApiUrlHomologacao;
|
||||||
|
}
|
||||||
|
if(contLogo>10){
|
||||||
|
mode = 'desenvolvimento';
|
||||||
|
url = UrlApiConst.ApiUrlDesenvolvimento;
|
||||||
|
if(contLogo==15){
|
||||||
|
contLogo=0;
|
||||||
|
mode = 'online';
|
||||||
|
url = UrlApiConst.ApiUrlOnline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
child: Image.asset('assets/images/logo.PNG',width: width*0.4)
|
||||||
|
),
|
||||||
|
mode == 'homologacao'?Image.asset('assets/images/homologacao.png',width: width*0.4):Container(),
|
||||||
|
mode == 'desenvolvimento'?Image.asset('assets/images/desenvolvimento.png',width: width*0.4):Container(),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
Form(
|
Form(
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
@@ -91,18 +136,22 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
children: [
|
children: [
|
||||||
InputText(
|
InputText(
|
||||||
hint: 'Usuário',
|
hint: 'Usuário',
|
||||||
label: 'Usuário',
|
label: inputUser.text.isNotEmpty?'':'Usuário',
|
||||||
error: 'Campo obrigatório',
|
error: 'Campo obrigatório',
|
||||||
controller: inputUser,
|
controller: inputUser,
|
||||||
width: width*0.6
|
width: width*0.6,
|
||||||
|
colorBorder: Colors.white,
|
||||||
|
onChanged: (v)=>setState((){}),
|
||||||
),
|
),
|
||||||
InputText(
|
InputText(
|
||||||
hint: 'Senha',
|
hint: 'Senha',
|
||||||
label: 'Senha',
|
label: inputPassword.text.isNotEmpty?'':'Senha',
|
||||||
error: 'Campo obrigatório',
|
error: 'Campo obrigatório',
|
||||||
obscure: true,
|
obscure: true,
|
||||||
controller: inputPassword,
|
controller: inputPassword,
|
||||||
width: width*0.6
|
width: width*0.6,
|
||||||
|
colorBorder: Colors.white,
|
||||||
|
onChanged: (v)=>setState((){}),
|
||||||
),
|
),
|
||||||
DropDownButtonCity(
|
DropDownButtonCity(
|
||||||
error: 'Campo obrigatório',
|
error: 'Campo obrigatório',
|
||||||
|
|||||||
20
lib/service/api_get_pass.dart
Normal file
20
lib/service/api_get_pass.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
class ApiGetPass{
|
||||||
|
Future apiConect(String? selectCity,String mode,String inputUser,String urlApi)async{
|
||||||
|
String city = '';
|
||||||
|
city = selectCity!.toLowerCase()
|
||||||
|
.replaceAll('ú', 'u')
|
||||||
|
.replaceAll('ç', 'c')
|
||||||
|
.replaceAll('ó', 'o')
|
||||||
|
.replaceAll('ô', 'o')
|
||||||
|
.replaceAll('í', 'i')
|
||||||
|
.replaceAll('ã','a');
|
||||||
|
|
||||||
|
final url = '$urlApi$mode/$city/pass/$inputUser';
|
||||||
|
final response = await http.get(Uri.parse(url));
|
||||||
|
final map = json.decode(response.body);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
lib/service/encrypt_password.dart
Normal file
43
lib/service/encrypt_password.dart
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import 'package:gainer_crypto/crypto.dart';
|
||||||
|
|
||||||
|
class EncryptPassword{
|
||||||
|
encrypt(String senhaDigitada,String senhaUsuario) {
|
||||||
|
// Deixa e senha digitada em maiuscula
|
||||||
|
var senha = senhaDigitada.toUpperCase();
|
||||||
|
// Faz a criptografia da senha inserida
|
||||||
|
String senhaMD5 = grHashString(GRCryptoType.md5, senha);
|
||||||
|
// Retira o tipo (1, 2 ou 3) da senha do Usuário
|
||||||
|
int tipo = int.parse(senhaUsuario.substring(0, 1));
|
||||||
|
// Define a possição inicial da quebra da senha
|
||||||
|
int posI = 0;
|
||||||
|
int posF = 0;
|
||||||
|
int posMax = 0;
|
||||||
|
// Pra cada tipo (1, 2 ou 3) define a posição inicial da quebra da senha
|
||||||
|
if(tipo == 1){
|
||||||
|
posI = 0;
|
||||||
|
posF = 16;
|
||||||
|
posMax = 16;
|
||||||
|
} else if(tipo == 2){
|
||||||
|
posI = 16;
|
||||||
|
posF = 0;
|
||||||
|
posMax = 16;
|
||||||
|
} else if(tipo == 3){
|
||||||
|
posI = 0;
|
||||||
|
posF = 31;
|
||||||
|
posMax = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print('posI $posI posF $posF PosMax $posMax');
|
||||||
|
print('inicio ${senhaMD5.substring(0, 16)}');
|
||||||
|
print('meio ${senhaMD5.substring(16, 32)}');
|
||||||
|
print('fim ${senhaMD5.substring(posF, posMax)}');
|
||||||
|
print('senha: ${senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax)}');
|
||||||
|
print('${grHashString(GRCryptoType.sha1, senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax))}');
|
||||||
|
|
||||||
|
|
||||||
|
// Faz a criptografia e concatena ela com sha1 e md5
|
||||||
|
String senhaCriptogradafa = tipo.toString() + '\$'+ grHashString(GRCryptoType.sha1, senhaMD5.substring(posI, posMax) + senha + senhaMD5.substring(posF, posMax));
|
||||||
|
// Retorna a senha criptografada
|
||||||
|
return senhaCriptogradafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
lib/service/url_api_const.dart
Normal file
5
lib/service/url_api_const.dart
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class UrlApiConst{
|
||||||
|
static const String ApiUrlOnline = 'https://saude.rkmsistemas.com.br/api/atb/';
|
||||||
|
static const String ApiUrlHomologacao = 'https://app0.rkmsistemas.com.br/api/atb/';
|
||||||
|
static const String ApiUrlDesenvolvimento = 'http://192.168.0.42:8010/api/atb/';
|
||||||
|
}
|
||||||
@@ -221,13 +221,18 @@ class ConstVariable{
|
|||||||
'Anhembi',
|
'Anhembi',
|
||||||
'Aparecida',
|
'Aparecida',
|
||||||
'Batatais',
|
'Batatais',
|
||||||
|
'Biritiba Mirim',
|
||||||
'Cabreúva',
|
'Cabreúva',
|
||||||
|
'Cachoeira Paulista',
|
||||||
|
'Caconde',
|
||||||
'Casa Branca',
|
'Casa Branca',
|
||||||
|
'Corumbataí',
|
||||||
'Descalvado',
|
'Descalvado',
|
||||||
'Extrema',
|
'Extrema',
|
||||||
'Francisco Morato',
|
|
||||||
'Franco da Rocha',
|
'Franco da Rocha',
|
||||||
'Igaraçu do Tiete',
|
'Igaraçu do Tiete',
|
||||||
|
'Iracemápolis',
|
||||||
|
'Itapeva',
|
||||||
'Itápolis',
|
'Itápolis',
|
||||||
'Itirapina',
|
'Itirapina',
|
||||||
'Ituverava',
|
'Ituverava',
|
||||||
@@ -242,7 +247,8 @@ class ConstVariable{
|
|||||||
'Piracicaba',
|
'Piracicaba',
|
||||||
'Porto Ferreira',
|
'Porto Ferreira',
|
||||||
'Santa Rita',
|
'Santa Rita',
|
||||||
'Santo Antonio da Alegria',
|
'Santo Antônio da Alegria',
|
||||||
|
'São Sabastião da Grama',
|
||||||
'Tapiratiba'
|
'Tapiratiba'
|
||||||
];
|
];
|
||||||
var backgroundGradient = BoxDecoration(
|
var backgroundGradient = BoxDecoration(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class InputText extends StatelessWidget {
|
|||||||
TextInputType textInputType;
|
TextInputType textInputType;
|
||||||
int maxLines;
|
int maxLines;
|
||||||
Color colorBorder;
|
Color colorBorder;
|
||||||
|
var onChanged;
|
||||||
|
|
||||||
InputText({
|
InputText({
|
||||||
required this.controller,
|
required this.controller,
|
||||||
@@ -26,7 +27,8 @@ class InputText extends StatelessWidget {
|
|||||||
this.enable = true,
|
this.enable = true,
|
||||||
this.textInputType = TextInputType.text,
|
this.textInputType = TextInputType.text,
|
||||||
this.maxLines = 1,
|
this.maxLines = 1,
|
||||||
this.colorBorder = ColorPalette.black54
|
this.colorBorder = ColorPalette.black54,
|
||||||
|
this.onChanged = null
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -38,6 +40,7 @@ class InputText extends StatelessWidget {
|
|||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
keyboardType: textInputType,
|
keyboardType: textInputType,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
|
onChanged: onChanged,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value!=null && value!.length==0) {
|
if (value!=null && value!.length==0) {
|
||||||
return error;
|
return error;
|
||||||
@@ -54,19 +57,19 @@ class InputText extends StatelessWidget {
|
|||||||
fillColor: ColorPalette.appBar,
|
fillColor: ColorPalette.appBar,
|
||||||
labelText: label,
|
labelText: label,
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 2,color: colorBorder)
|
borderSide: BorderSide(width: 1,color: colorBorder)
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 3, color: colorBorder),
|
borderSide: BorderSide(width: 1, color: colorBorder),
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(3),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 3, color: colorBorder),
|
borderSide: BorderSide(width: 1, color: colorBorder),
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(3),
|
||||||
),
|
),
|
||||||
disabledBorder: OutlineInputBorder(
|
disabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(width: 3, color: colorBorder),
|
borderSide: BorderSide(width: 1, color: colorBorder),
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(3),
|
||||||
),
|
),
|
||||||
hintText: this.hint,
|
hintText: this.hint,
|
||||||
enabled: enable,
|
enabled: enable,
|
||||||
|
|||||||
51
pubspec.lock
51
pubspec.lock
@@ -1,6 +1,20 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
|
asn1lib:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: asn1lib
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -36,6 +50,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.16.0"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -43,6 +71,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
|
encrypt:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: encrypt
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -79,8 +114,15 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
gainer_crypto:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: gainer_crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.6"
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
@@ -170,6 +212,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
pointycastle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pointycastle
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.7.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ dependencies:
|
|||||||
intl:
|
intl:
|
||||||
package_info_plus: ^3.0.2
|
package_info_plus: ^3.0.2
|
||||||
line_icons: ^2.0.1
|
line_icons: ^2.0.1
|
||||||
|
http:
|
||||||
|
gainer_crypto: ^0.0.6
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user