This commit is contained in:
poka 2020-12-21 01:05:00 +01:00
parent 5c4a029674
commit 7936de25fc
9 changed files with 355 additions and 421 deletions

36
lib/data/respository.dart Normal file
View File

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:readwenderlich/data/stores/in_memory_store.dart';
import 'package:readwenderlich/data/stores/remote/remote_store.dart';
import 'package:readwenderlich/entities/article.dart';
import 'package:readwenderlich/entities/article_category.dart';
import 'package:readwenderlich/entities/article_difficulty.dart';
import 'package:readwenderlich/entities/article_platform.dart';
import 'package:readwenderlich/entities/list_page.dart';
import 'package:readwenderlich/entities/sort_method.dart';
/// Gets data from both [RemoteStore] and [InMemoryStore].
class Repository {
const Repository({
@required this.remoteStore,
@required this.inMemoryStore,
}) : assert(remoteStore != null),
assert(inMemoryStore != null);
final RemoteStore remoteStore;
final InMemoryStore inMemoryStore;
Future<ListPage<Article>> getArticleListPage({
int number,
int size,
List<int> filteredPlatformIds,
List<int> filteredCategoryIds,
List<ArticleDifficulty> filteredDifficulties,
SortMethod sortMethod,
}) =>
remoteStore.getArticleListPage(
number: number,
size: size,
filteredPlatformIds: filteredPlatformIds,
filteredCategoryIds: filteredCategoryIds,
filteredDifficulties: filteredDifficulties,
sortMethod: sortMethod,
);

312
lib/home.dart Normal file
View File

@ -0,0 +1,312 @@
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui';
import 'package:permission_handler/permission_handler.dart';
import 'package:qrscan/qrscan.dart' as scanner;
import 'package:intl/intl.dart';
import 'api.dart';
import "package:dio/dio.dart";
import 'ui/history_list_view.dart';
/// Integrates a list of articles with [ListPreferencesScreen].
class HistoryListScreen extends StatefulWidget {
@override
_HistoryListScreenState createState() => _HistoryListScreenState();
}
// class HistoryListScreen extends StatefulWidget {
// // GeckoHome({Key key, this.title}) : super(key: key);
// // final String title;
// const HistoryListScreen({
// @required this.repository,
// final String title,
// Key key,
// }) : assert(repository != null),
// super(key: key);
// final Repository repository;
// @override
// _GeckoHomeState createState() => _GeckoHomeState();
// }
class _HistoryListScreenState extends State<HistoryListScreen> {
Uint8List bytes = Uint8List(0);
TextEditingController _outputPubkey;
TextEditingController _outputBalance;
TextEditingController _outputHistory;
@override
initState() {
super.initState();
this._outputPubkey = new TextEditingController();
this._outputBalance = new TextEditingController();
this._outputHistory = new TextEditingController();
// checkNode().then((result) {
// setState(() {
// _result = result;
// });
// });
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.grey[300],
body: SafeArea(
child: Column(
children: <Widget>[
SizedBox(height: 20),
TextField(
// enabled: false,
onChanged: (text) {
print("Clé tappé: $text");
isPubkey(text);
},
controller: this._outputPubkey,
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: 'Tappez/Collez une clé publique, ou scannez',
hintStyle: TextStyle(fontSize: 15),
contentPadding:
EdgeInsets.symmetric(horizontal: 7, vertical: 15),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
TextField(
// Affichage balance
enabled: false,
controller: this._outputBalance,
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '',
hintStyle: TextStyle(fontSize: 15),
contentPadding:
EdgeInsets.symmetric(horizontal: 7, vertical: 15),
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
style: TextStyle(fontSize: 30.0, color: Colors.black)),
Expanded(
child: HistoryListView(
repository: Provider.of<Repository>(context)
))
],
),
),
floatingActionButton: Container(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
onPressed: () => _scan(),
// label: Text('Scanner'),
child: Container(
height: 40.0,
width: 40.0,
child: Image.asset('images/scanner.png')),
backgroundColor: Color.fromARGB(500, 204, 255, 255),
),
),
)));
}
Widget buildTranscationCard(Transaction transaction) {
return Card(
// 1
elevation: 2.0,
// 2
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
// 3
child: Padding(
padding: const EdgeInsets.all(16.0),
// 4
child: Column(
children: <Widget>[
// 5
SizedBox(
height: 14.0,
),
// 6
Text(
transaction.pubkey,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w700,
fontFamily: "Palatino",
),
),
Text(transaction.date,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w700,
fontFamily: "Palatino",
))
],
),
),
);
}
Future checkNode() async {
final response = await Dio().post(graphqlEndpoint);
showHistory(response);
return response;
}
Future _scan() async {
await Permission.camera.request();
String barcode = await scanner.scan();
// this._outputPubkey.text = "";
if (barcode != null) {
isPubkey(barcode);
}
return barcode;
}
Future isPubkey(pubkey) async {
// final validCharacters = RegExp(r'^[a-zA-Z0-9]+$');
RegExp regExp = new RegExp(
r'^[a-zA-Z0-9]+$',
caseSensitive: false,
multiLine: false,
);
if (regExp.hasMatch(pubkey) == true &&
pubkey.length > 42 &&
pubkey.length < 45) {
print("C'est une pubkey !!!");
print(pubkey.length);
showHistory(pubkey);
}
}
Future showHistory(pubkey) async {
// String pubkey = await _scan();
if (pubkey == null) {
print('nothing return.');
} else {
this._outputPubkey.text = "";
this._outputBalance.text = "";
this._outputHistory.text = "";
// final udValue = await getUD();
this._outputPubkey.text = pubkey;
final myBalance = await getBalance(pubkey.toString());
this._outputBalance.text = myBalance.toString() + " Ğ1";
}
}
// Future _generateBarCode(String inputCode) async {
// if (inputCode != null && inputCode.isNotEmpty) {
// // print("Résultat du scan: " + inputCode);
// Uint8List result = await scanner.generateBarCode(inputCode);
// this.setState(() => this.bytes = result);
// } else {
// print("Veuillez renseigner une clé publique");
// }
// }
}
class Transaction {
String pubkey;
String date;
Transaction(this.pubkey, this.date);
// TODO: Build this list !!!!
// static List<Transaction> samples = List<Transaction> getHistory(pubkey.toString());
Future buildHistory() async {
final myHistory = await getHistory(pubkey.toString());
if (myHistory == false) {
return false;
}
String historyBC = "";
for (var i in myHistory[0]) {
var dateBrut = i[0];
dateBrut = DateTime.fromMillisecondsSinceEpoch(dateBrut * 1000);
final DateFormat formatter = DateFormat('dd-MM-yy - H:M');
final String date = formatter.format(dateBrut);
final issuer = i[1];
final amount = i[2];
// final amountUD = i[3];
final comment = i[4];
historyBC += date.toString() +
" \n " +
issuer.toString() +
" \n " +
amount.toString() +
" Ğ1\n " +
comment.toString() +
"\n---\n";
}
String historyMP = "";
for (var i in myHistory[1]) {
if (i == null) {
break;
}
var dateBrut = "Now";
final issuer = i[1];
final amount = i[2];
// final amountUD = i[3];
final comment = i[4];
historyMP += dateBrut.toString() +
" \n " +
issuer.toString() +
" \n " +
amount.toString() +
" Ğ1\n " +
comment.toString() +
"\n------------------\n";
}
var history;
// print(historyMP.toString());
if (historyMP == "") {
history = historyBC;
} else {
history = "EN COURS DE TRAITEMENT\n" + historyMP + "VALIDÉ\n" + historyBC;
}
// this._outputHistory.text = history;
List<Transaction> samples = List<Transaction>
return myHistory[0];
}
// static List<Transaction> samples = buildHistory();
var list = json
.decode(response.body)['results']
.map((data) => Model.fromJson(data))
.toList();
// static List<Transaction> samples = [
// Transaction(
// "Spaghetti and Meatballs",
// "assets/2126711929_ef763de2b3_w.jpg",
// ),
// Transaction(
// "Tomato Soup",
// "assets/27729023535_a57606c1be.jpg",
// )
// ];
}

View File

@ -1,283 +1,20 @@
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qrscan/qrscan.dart' as scanner;
import 'package:intl/intl.dart';
// import 'package:flutter_html_view';
import 'api.dart';
import "package:dio/dio.dart";
List<String> litems = ["1", "2", "Third", "4"];
import 'home.dart';
void main() {
runApp(MyApp());
runApp(Gecko());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Uint8List bytes = Uint8List(0);
TextEditingController _outputPubkey;
TextEditingController _outputBalance;
TextEditingController _outputHistory;
@override
initState() {
super.initState();
this._outputPubkey = new TextEditingController();
this._outputBalance = new TextEditingController();
this._outputHistory = new TextEditingController();
// checkNode().then((result) {
// setState(() {
// _result = result;
// });
// });
}
class Gecko extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.grey[300],
body: Builder(
builder: (BuildContext context) {
return ListView(
children: <Widget>[
Container(
color: Colors.white,
child: Column(
children: <Widget>[
SizedBox(height: 20),
TextField(
// enabled: false,
onChanged: (text) {
print("Clé tappé: $text");
isPubkey(text);
},
controller: this._outputPubkey,
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText:
'Tappez/Collez une clé publique, ou scannez',
hintStyle: TextStyle(fontSize: 15),
contentPadding: EdgeInsets.symmetric(
horizontal: 7, vertical: 15),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
style: TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.bold)),
TextField(
// Affichage balance
enabled: false,
controller: this._outputBalance,
maxLines: 1,
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '',
hintStyle: TextStyle(fontSize: 15),
contentPadding: EdgeInsets.symmetric(
horizontal: 7, vertical: 15),
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
style: TextStyle(
fontSize: 30.0, color: Colors.black)),
TextField(
// Affichage history
enabled: false,
controller: this._outputHistory,
maxLines: null,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
prefixIcon: Icon(Icons.wrap_text),
hintText: '',
hintStyle: TextStyle(fontSize: 15),
contentPadding: EdgeInsets.symmetric(
horizontal: 7, vertical: 15),
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
style: TextStyle(
fontSize: 13.0,
height: 1.5,
color: Colors.black)),
SizedBox(height: 20),
SizedBox(height: 70),
// Expanded(
// child: ListView.builder(
// padding: const EdgeInsets.all(8),
// itemCount: names.length,
// itemBuilder: (BuildContext context, int index) {
// return Container(
// height: 50,
// margin: EdgeInsets.all(2),
// child: Center(
// child: Text(
// '${names[index]} (${msgCount[index]})',
// style: TextStyle(fontSize: 18),
// )),
// );
// }))
],
),
),
// new ListView.builder(
// itemCount: litems.length,
// itemBuilder: (BuildContext ctxt, int index) {
// return new Text(litems[index]);
// })
],
);
},
),
floatingActionButton: Container(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
onPressed: () => _scan(),
// label: Text('Scanner'),
child: Container(
height: 40.0,
width: 40.0,
child: Image.asset('images/scanner.png')),
backgroundColor: Color.fromARGB(500, 204, 255, 255),
),
),
)));
}
Future checkNode() async {
final response = await Dio().post(graphqlEndpoint);
showHistory(response);
return response;
}
Future _scan() async {
await Permission.camera.request();
String barcode = await scanner.scan();
// this._outputPubkey.text = "";
if (barcode != null) {
isPubkey(barcode);
}
return barcode;
}
Future isPubkey(pubkey) async {
// final validCharacters = RegExp(r'^[a-zA-Z0-9]+$');
RegExp regExp = new RegExp(
r'^[a-zA-Z0-9]+$',
caseSensitive: false,
multiLine: false,
title: 'Ğecko',
theme: ThemeData(primaryColor: Colors.white, accentColor: Colors.black),
home: HistoryListScreen(),
);
if (regExp.hasMatch(pubkey) == true &&
pubkey.length > 42 &&
pubkey.length < 45) {
print("C'est une pubkey !!!");
print(pubkey.length);
showHistory(pubkey);
}
}
Future showHistory(pubkey) async {
// String pubkey = await _scan();
if (pubkey == null) {
print('nothing return.');
} else {
this._outputPubkey.text = "";
this._outputBalance.text = "";
this._outputHistory.text = "";
// final udValue = await getUD();
this._outputPubkey.text = pubkey;
final myBalance = await getBalance(pubkey.toString());
this._outputBalance.text = myBalance.toString() + " Ğ1";
final myHistory = await getHistory(pubkey.toString());
if (myHistory == false) {
return false;
}
String historyBC = "";
for (var i in myHistory[0]) {
var dateBrut = i[0];
dateBrut = DateTime.fromMillisecondsSinceEpoch(dateBrut * 1000);
final DateFormat formatter = DateFormat('dd-MM-yy - H:M');
final String date = formatter.format(dateBrut);
final issuer = i[1];
final amount = i[2];
// final amountUD = i[3];
final comment = i[4];
historyBC += date.toString() +
" \n " +
issuer.toString() +
" \n " +
amount.toString() +
" Ğ1\n " +
comment.toString() +
"\n---\n";
}
String historyMP = "";
for (var i in myHistory[1]) {
if (i == null) {
break;
}
var dateBrut = "Now";
final issuer = i[1];
final amount = i[2];
// final amountUD = i[3];
final comment = i[4];
historyMP += dateBrut.toString() +
" \n " +
issuer.toString() +
" \n " +
amount.toString() +
" Ğ1\n " +
comment.toString() +
"\n------------------\n";
}
var history;
// print(historyMP.toString());
if (historyMP == "") {
history = historyBC;
} else {
history =
"EN COURS DE TRAITEMENT\n" + historyMP + "VALIDÉ\n" + historyBC;
}
this._outputHistory.text = history;
}
}
// Future _generateBarCode(String inputCode) async {
// if (inputCode != null && inputCode.isNotEmpty) {
// // print("Résultat du scan: " + inputCode);
// Uint8List result = await scanner.generateBarCode(inputCode);
// this.setState(() => this.bytes = result);
// } else {
// print("Veuillez renseigner une clé publique");
// }
// }
}

View File

@ -1,12 +0,0 @@
import 'package:flutter/cupertino.dart';
// import 'package:readwenderlich/ui/exception_indicators/exception_indicator.dart';
/// Indicates that no items were found.
class EmptyListIndicator extends StatelessWidget {
@override
Widget build(BuildContext context) => const ExceptionIndicator(
title: 'Too much filtering',
message: 'We couldn\'t find any results matching your applied filters.',
assetName: 'assets/empty-box.png',
);
}

View File

@ -1,28 +0,0 @@
import 'dart:io';
import 'package:flutter/material.dart';
// import 'package:readwenderlich/ui/exception_indicators/generic_error_indicator.dart';
// import 'package:readwenderlich/ui/exception_indicators/no_connection_indicator.dart';
/// Based on the received error, displays either a [NoConnectionIndicator] or
/// a [GenericErrorIndicator].
class ErrorIndicator extends StatelessWidget {
const ErrorIndicator({
@required this.error,
this.onTryAgain,
Key key,
}) : assert(error != null),
super(key: key);
final dynamic error;
final VoidCallback onTryAgain;
@override
Widget build(BuildContext context) => error is SocketException
? NoConnectionIndicator(
onTryAgain: onTryAgain,
)
: GenericErrorIndicator(
onTryAgain: onTryAgain,
);
}

View File

@ -1,70 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Basic layout for indicating that an exception occurred.
class ExceptionIndicator extends StatelessWidget {
const ExceptionIndicator({
@required this.title,
@required this.assetName,
this.message,
this.onTryAgain,
Key key,
}) : assert(title != null),
assert(assetName != null),
super(key: key);
final String title;
final String message;
final String assetName;
final VoidCallback onTryAgain;
@override
Widget build(BuildContext context) => Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 16),
child: Column(
children: [
Image.asset(
assetName,
),
const SizedBox(
height: 32,
),
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6,
),
if (message != null)
const SizedBox(
height: 16,
),
if (message != null)
Text(
message,
textAlign: TextAlign.center,
),
if (onTryAgain != null) const Spacer(),
if (onTryAgain != null)
SizedBox(
height: 50,
width: double.infinity,
child: RaisedButton.icon(
onPressed: onTryAgain,
icon: const Icon(
Icons.refresh,
color: Colors.white,
),
label: const Text(
'Try Again',
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
),
),
],
),
),
);
}

View File

@ -1,21 +0,0 @@
import 'package:flutter/cupertino.dart';
// import 'package:readwenderlich/ui/exception_indicators/exception_indicator.dart';
/// Indicates that an unknown error occurred.
class GenericErrorIndicator extends StatelessWidget {
const GenericErrorIndicator({
Key key,
this.onTryAgain,
}) : super(key: key);
final VoidCallback onTryAgain;
@override
Widget build(BuildContext context) => ExceptionIndicator(
title: 'Something went wrong',
message: 'The application has encountered an unknown error.\n'
'Please try again later.',
assetName: 'assets/confused-face.png',
onTryAgain: onTryAgain,
);
}

View File

@ -1,20 +0,0 @@
import 'package:flutter/cupertino.dart';
// import 'package:readwenderlich/ui/exception_indicators/exception_indicator.dart';
/// Indicates that a connection error occurred.
class NoConnectionIndicator extends StatelessWidget {
const NoConnectionIndicator({
Key key,
this.onTryAgain,
}) : super(key: key);
final VoidCallback onTryAgain;
@override
Widget build(BuildContext context) => ExceptionIndicator(
title: 'No connection',
message: 'Please check internet connection and try again.',
assetName: 'assets/frustrated-face.png',
onTryAgain: onTryAgain,
);
}

View File

@ -13,7 +13,7 @@ import 'package:gecko/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());
await tester.pumpWidget(Gecko());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);