Skip to content

Commit

Permalink
Added a developer options to the app (currently only deletes local st…
Browse files Browse the repository at this point in the history
…orage credentials), partially addresses #9  ,  dartfmt everything
  • Loading branch information
GuilhermeFreire committed Jun 11, 2020
1 parent df68f4a commit c3004c8
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 87 deletions.
45 changes: 29 additions & 16 deletions lib/CEICredentials.dart
Original file line number Diff line number Diff line change
@@ -1,53 +1,66 @@
import 'dart:convert';
import 'package:app/storage.dart';

class CEICredentials{
class CEICredentials {
String _cpf;
String _password;
final String _filename = "cei_credentials.json";

CEICredentials(this._cpf, this._password);

CEICredentials .empty(){
CEICredentials.empty() {
_cpf = "";
_password = "";
}

@override
String toString(){
String toString() {
return "CPF: $_cpf";
}

fromJson(Map<String, dynamic> json){
fromJson(Map<String, dynamic> json) {
_cpf = json['cpf'];
_password = json['password'];
}


Map<String, dynamic> toJson() =>
{
Map<String, dynamic> toJson() => {
'cpf': _cpf,
'password': _password,
};

save({bool safe_save=false}){
if (!safe_save){
Storage credStorage = Storage(_filename);
credStorage.write(jsonEncode(this.toJson()));
}
else{
save({bool safeSave = false}) {
if (!safeSave) {
Storage credStorage = Storage(_filename);
credStorage.write(jsonEncode(this.toJson()));
} else {
print("Not implemented yet.");
}
}

load() async{
load() async {
Storage credStorage = Storage(_filename);
Map<String, dynamic> credJson = jsonDecode(await credStorage.read());
this.fromJson(credJson);
}

exists() async{
exists() async {
Storage credStorage = Storage(_filename);
return await credStorage.exists();
}
}

delete() async {
Storage credStorage = Storage(_filename);
return await credStorage.delete();
}

bool validateCredentials() {
// Check if the CPF/password combo is registered in the CEI system
return validateCPF(_cpf);
}
}

bool validateCPF(String cpf) {
RegExp exp = new RegExp(r"[0-9]{3}\.?[0-9]{3}\.?[0-9]{3}[\.-]?[0-9]{2}");
RegExpMatch hasMatch = exp.firstMatch(cpf);
return hasMatch != null && ((hasMatch.end - hasMatch.start) == cpf.length);
}
13 changes: 4 additions & 9 deletions lib/appInitializer.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import 'package:flutter/material.dart';
import 'package:app/CEICredentials.dart';

redirect(BuildContext context) async{
redirect(BuildContext context) async {
CEICredentials creds = CEICredentials.empty();
bool hasCredentials = await creds.exists();
if (hasCredentials){
Navigator.of(context).pushReplacementNamed('/home');
}
else{
Navigator.of(context).pushReplacementNamed('/login');
}

}
String route = hasCredentials ? "/home" : "/login";
Navigator.of(context).pushReplacementNamed(route);
}
27 changes: 27 additions & 0 deletions lib/developerSettings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:app/CEICredentials.dart';
import 'package:flutter/material.dart';

class DeveloperSettings extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Developer Settings'),
),
body: ListView(
children: ListTile.divideTiles(context: context, tiles: [
ListTile(
title: Text("Erase CEI credentials from local storage"),
onTap: () => {CEICredentials.empty().delete()},
),
ListTile(
title: Text("Option 2"),
),
ListTile(
title: Text("Option 3"),
)
]).toList(),
),
);
}
}
87 changes: 51 additions & 36 deletions lib/login.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import 'dart:convert';

import 'package:app/CEICredentials.dart';
import 'package:flutter/material.dart';

class LoginState extends State<Login> {

// Fonts
final _normalFont = const TextStyle(fontSize: 18.0);

final _buttonFont = const TextStyle(fontSize: 18.0, color: Colors.white);

final _smallErrorFont =
const TextStyle(fontSize: 14.0, color: Colors.redAccent);

String warningMessage = "";

final _cpf = TextEditingController();
final _password = TextEditingController();

Expand All @@ -20,43 +22,56 @@ class LoginState extends State<Login> {
title: Text("Bezunca Investimentos"),
),
body: Form(
child: Padding(
padding: EdgeInsets.all(30),
child: ListView(
children: <Widget>[
TextFormField(
controller: _cpf,
keyboardType: TextInputType.text,
style: _normalFont,
decoration: InputDecoration(labelText: "CPF", labelStyle: _normalFont)
),
TextFormField(
controller: _password,
obscureText: true,
keyboardType: TextInputType.text,
style: _normalFont,
decoration: InputDecoration(labelText: "Senha", labelStyle: _normalFont)
),
Container(
height: 40.0,
margin: EdgeInsets.only(top: 30.0),
child: RaisedButton(
color: Colors.blue,
child: Text("LOGIN", style: _buttonFont),
onPressed: () { _onClickLogin(context); },
),
)
],
)
)
),
child: Padding(
padding: EdgeInsets.all(30),
child: ListView(
children: <Widget>[
TextFormField(
controller: _cpf,
keyboardType: TextInputType.text,
style: _normalFont,
decoration: InputDecoration(
labelText: "CPF", labelStyle: _normalFont)),
TextFormField(
controller: _password,
obscureText: true,
keyboardType: TextInputType.text,
style: _normalFont,
decoration: InputDecoration(
labelText: "Senha", labelStyle: _normalFont)),
Container(
margin: EdgeInsets.only(top: 20.0),
child: Text(warningMessage,
style: _smallErrorFont, textAlign: TextAlign.center)),
Container(
height: 40.0,
margin: EdgeInsets.only(top: 30.0),
child: RaisedButton(
color: Colors.blue,
child: Text("LOGIN", style: _buttonFont),
onPressed: () {
_onClickLogin(context);
},
),
)
],
))),
);
}

_onClickLogin(BuildContext context) async{
_onClickLogin(BuildContext context) async {
CEICredentials creds = CEICredentials(_cpf.text, _password.text);
creds.save();
Navigator.of(context).pushReplacementNamed('/home');
if (creds.validateCredentials()) {
setState(() {
warningMessage = "";
});
creds.save();
Navigator.of(context).pushReplacementNamed('/home');
} else {
setState(() {
warningMessage = "Credenciais inválidas";
});
}
}
}

Expand Down
8 changes: 3 additions & 5 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import 'package:flutter/material.dart';

import 'splashScreen.dart';

void main() async{

void main() async {
runApp(MaterialApp(
title: "Bezunca",
home: SplashScreen(),
Expand All @@ -14,6 +13,5 @@ void main() async{
'/home': (BuildContext context) => new Portfolio(),
'/login': (BuildContext context) => new Login()
},
)
);
}
));
}
13 changes: 12 additions & 1 deletion lib/portfolio.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'asset.dart';
import "developerSettings.dart";

class PortfolioState extends State<Portfolio> {
final _portfolio = <Asset>[
Expand Down Expand Up @@ -28,7 +29,7 @@ class PortfolioState extends State<Portfolio> {
appBar: AppBar(
title: Text("Bezunca Investimentos"),
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () => {}),
IconButton(icon: Icon(Icons.adb), onPressed: _pushSaved),
],
),
body: _buildPortfolio(),
Expand Down Expand Up @@ -62,6 +63,16 @@ class PortfolioState extends State<Portfolio> {
style: _normalFont,
));
}

void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return DeveloperSettings();
},
),
);
}
}

class Portfolio extends StatefulWidget {
Expand Down
10 changes: 4 additions & 6 deletions lib/splashScreen.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import 'package:flutter/material.dart';
import "appInitializer.dart";

class SplashScreen extends StatelessWidget{
class SplashScreen extends StatelessWidget {
@override
Widget build(BuildContext context){
Widget build(BuildContext context) {
redirect(context);
return Scaffold(
body: Center(child: Text("Loading..."))
);
return Scaffold(body: Center(child: Text("Loading...")));
}
}
}
12 changes: 9 additions & 3 deletions lib/storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@ class Storage {

Future<File> write(String content) async {
final file = await _localFile;

// Write the file
return file.writeAsString(content);
}
}

Future<File> delete() async {
final file = await _localFile;
if (await file.exists()) {
return file.delete();
}
return null;
}
}
9 changes: 1 addition & 8 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
english_words:
dependency: "direct dev"
description:
name: english_words
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.5"
fake_async:
dependency: transitive
description:
Expand Down Expand Up @@ -103,7 +96,7 @@ packages:
source: hosted
version: "1.7.0"
path_provider:
dependency: "direct dev"
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
Expand Down
5 changes: 2 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3
path_provider: ^1.6.10

dev_dependencies:
flutter_test:
sdk: flutter
cupertino_icons: ^0.1.2
english_words: ^3.1.0
path_provider: ^1.6.10


# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
Expand Down

0 comments on commit c3004c8

Please sign in to comment.