Change icon (no); Add commented checknode functions.
|
@ -11,8 +11,8 @@
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<application
|
<application
|
||||||
android:name="io.flutter.app.FlutterApplication"
|
android:name="io.flutter.app.FlutterApplication"
|
||||||
android:label="gecko"
|
android:label="gecko">
|
||||||
android:icon="@mipmap/ic_launcher">
|
<!-- android:icon="@mipmap/launcher_icon"> -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
|
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 307 KiB |
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 26 KiB |
98
lib/api.dart
|
@ -8,21 +8,45 @@ import "package:gql_link/gql_link.dart";
|
||||||
// Configure node
|
// Configure node
|
||||||
const graphqlEndpoint = "https://g1.librelois.fr/gva";
|
const graphqlEndpoint = "https://g1.librelois.fr/gva";
|
||||||
|
|
||||||
|
// // Check node connection
|
||||||
|
// Future getHttp() async {
|
||||||
|
// try {
|
||||||
|
// final client = await dio.Dio().get(graphqlEndpoint);
|
||||||
|
// print(client);
|
||||||
|
// return 0;
|
||||||
|
// } catch (e) {
|
||||||
|
// print(e);
|
||||||
|
// return e;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// Build queries
|
// Build queries
|
||||||
Future buildQ(query) async {
|
Future buildQ(query) async {
|
||||||
final client = dio.Dio();
|
var client;
|
||||||
final Link link = DioLink(
|
try {
|
||||||
|
client = dio.Dio();
|
||||||
|
print(client);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
// final client = dio.Dio();
|
||||||
|
Link link;
|
||||||
|
link = DioLink(
|
||||||
graphqlEndpoint,
|
graphqlEndpoint,
|
||||||
client: client,
|
client: client,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
final res = await link
|
final res = await link
|
||||||
.request(Request(
|
.request(Request(
|
||||||
operation: Operation(document: gqlLang.parseString(query)),
|
operation: Operation(document: gqlLang.parseString(query)),
|
||||||
))
|
))
|
||||||
.first;
|
.first;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
print("Erreur: Noeud injoingnable.");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Requests functions */
|
/* Requests functions */
|
||||||
|
@ -65,6 +89,14 @@ Future getHistory(String pubkey) async {
|
||||||
comment
|
comment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
txsHistoryMp(pubkey: "$pubkey") {
|
||||||
|
receiving {
|
||||||
|
writtenTime
|
||||||
|
issuers
|
||||||
|
outputs
|
||||||
|
comment
|
||||||
|
}
|
||||||
|
}
|
||||||
currentUd {
|
currentUd {
|
||||||
amount
|
amount
|
||||||
base
|
base
|
||||||
|
@ -74,9 +106,10 @@ Future getHistory(String pubkey) async {
|
||||||
final res = await buildQ(query);
|
final res = await buildQ(query);
|
||||||
|
|
||||||
// Parse history
|
// Parse history
|
||||||
var result;
|
var resBC, resMP;
|
||||||
try {
|
try {
|
||||||
result = res.data["txsHistoryBc"]["received"];
|
resBC = res.data["txsHistoryBc"]["received"];
|
||||||
|
resMP = res.data["txsHistoryMp"]["receiving"];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("DEBUG: " + e.toString());
|
print("DEBUG: " + e.toString());
|
||||||
print(res.data);
|
print(res.data);
|
||||||
|
@ -84,32 +117,63 @@ Future getHistory(String pubkey) async {
|
||||||
}
|
}
|
||||||
var i = 0;
|
var i = 0;
|
||||||
// String outPubkey;
|
// String outPubkey;
|
||||||
var trans = [];
|
var transBC = [];
|
||||||
final currentBase = res.data['currentUd']['base'];
|
final currentBase = res.data['currentUd']['base'];
|
||||||
final currentUD = res.data['currentUd']['amount'] / 100;
|
final currentUD = res.data['currentUd']['amount'] / 100;
|
||||||
|
|
||||||
for (var bloc in result) {
|
// Get tx received
|
||||||
|
for (var bloc in resBC) {
|
||||||
var output = bloc['outputs'][0];
|
var output = bloc['outputs'][0];
|
||||||
// outPubkey = output.split("SIG(")[1].replaceAll(')', '');
|
// outPubkey = output.split("SIG(")[1].replaceAll(')', '');
|
||||||
trans.add(i);
|
transBC.add(i);
|
||||||
trans[i] = [];
|
transBC[i] = [];
|
||||||
trans[i].add(bloc['writtenTime']);
|
transBC[i].add(bloc['writtenTime']);
|
||||||
trans[i].add(bloc['issuers'][0]);
|
transBC[i].add(bloc['issuers'][0]);
|
||||||
var amountBrut = int.parse(output.split(':')[0]);
|
var amountBrut = int.parse(output.split(':')[0]);
|
||||||
final base = int.parse(output.split(':')[1]);
|
final base = int.parse(output.split(':')[1]);
|
||||||
final applyBase = base - currentBase;
|
final applyBase = base - currentBase;
|
||||||
final amount = amountBrut * pow(10, applyBase) / 100;
|
final amount = amountBrut * pow(10, applyBase) / 100;
|
||||||
trans[i].add(amount);
|
transBC[i].add(amount);
|
||||||
final amountUD = amount / currentUD;
|
final amountUD = amount / currentUD;
|
||||||
trans[i].add(amountUD.toStringAsFixed(2));
|
transBC[i].add(amountUD.toStringAsFixed(2));
|
||||||
trans[i].add(bloc['comment']);
|
transBC[i].add(bloc['comment']);
|
||||||
trans[i].add(base);
|
transBC[i].add(base);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get tx receving
|
||||||
|
var transMP = [];
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (var bloc in resMP) {
|
||||||
|
if (transMP == null) {
|
||||||
|
print("DEBUG:: " + resMP.toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var output = bloc['outputs'][0];
|
||||||
|
var outPubkey = output.split("SIG(")[1].replaceAll(')', '');
|
||||||
|
transMP.add(i);
|
||||||
|
transMP[i] = [];
|
||||||
|
transMP[i].add(bloc['writtenTime']);
|
||||||
|
transMP[i].add(bloc['issuers'][0]);
|
||||||
|
var amountBrut = int.parse(output.split(':')[0]);
|
||||||
|
final base = int.parse(output.split(':')[1]);
|
||||||
|
final applyBase = base - currentBase;
|
||||||
|
final amount = amountBrut * pow(10, applyBase) / 100;
|
||||||
|
transMP[i].add(amount);
|
||||||
|
final amountUD = amount / currentUD;
|
||||||
|
transMP[i].add(amountUD.toStringAsFixed(2));
|
||||||
|
transMP[i].add(bloc['comment']);
|
||||||
|
transMP[i].add(base);
|
||||||
|
transMP[i].add(outPubkey);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order transactions by date
|
// Order transactions by date
|
||||||
trans.sort((b, a) => Comparable.compare(a[0], b[0]));
|
transBC.sort((b, a) => Comparable.compare(a[0], b[0]));
|
||||||
|
transMP.sort((b, a) => Comparable.compare(a[0], b[0]));
|
||||||
|
|
||||||
// // Keep only base if there is base change
|
// // Keep only base if there is base change
|
||||||
// var lastBase = 0;
|
// var lastBase = 0;
|
||||||
|
@ -122,5 +186,5 @@ Future getHistory(String pubkey) async {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// print(trans);
|
// print(trans);
|
||||||
return trans;
|
return [transBC, transMP];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
import 'dart:ui';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:image_gallery_saver/image_gallery_saver.dart';
|
// import 'package:image_gallery_saver/image_gallery_saver.dart';
|
||||||
|
@ -8,6 +9,7 @@ import 'package:qrscan/qrscan.dart' as scanner;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
// import 'package:flutter_html_view';
|
// import 'package:flutter_html_view';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
|
import "package:dio/dio.dart";
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
|
@ -30,21 +32,15 @@ class _MyAppState extends State<MyApp> {
|
||||||
this._outputPubkey = new TextEditingController();
|
this._outputPubkey = new TextEditingController();
|
||||||
this._outputBalance = new TextEditingController();
|
this._outputBalance = new TextEditingController();
|
||||||
this._outputHistory = new TextEditingController();
|
this._outputHistory = new TextEditingController();
|
||||||
|
// checkNode().then((result) {
|
||||||
|
// setState(() {
|
||||||
|
// _result = result;
|
||||||
|
// });
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// final List<String> names = <String>[
|
|
||||||
// 'Aby',
|
|
||||||
// 'Aish',
|
|
||||||
// 'Ayan',
|
|
||||||
// 'Ben',
|
|
||||||
// 'Bob',
|
|
||||||
// 'Charlie',
|
|
||||||
// 'Cook',
|
|
||||||
// 'Carline'
|
|
||||||
// ];
|
|
||||||
// final List<int> msgCount = <int>[2, 0, 10, 6, 52, 4, 0, 2];
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
backgroundColor: Colors.grey[300],
|
backgroundColor: Colors.grey[300],
|
||||||
|
@ -163,13 +159,17 @@ class _MyAppState extends State<MyApp> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future checkNode() async {
|
||||||
|
final response = await Dio().post(graphqlEndpoint);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future _scan() async {
|
Future _scan() async {
|
||||||
await Permission.camera.request();
|
await Permission.camera.request();
|
||||||
String barcode = await scanner.scan();
|
String barcode = await scanner.scan();
|
||||||
if (barcode == null) {
|
if (barcode == null) {
|
||||||
print('nothing return.');
|
print('nothing return.');
|
||||||
} else {
|
} else {
|
||||||
print("Debug: " + barcode);
|
|
||||||
this._outputPubkey.text = "";
|
this._outputPubkey.text = "";
|
||||||
this._outputBalance.text = "";
|
this._outputBalance.text = "";
|
||||||
this._outputHistory.text = "";
|
this._outputHistory.text = "";
|
||||||
|
@ -183,10 +183,9 @@ class _MyAppState extends State<MyApp> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String historyBloc = "";
|
String historyBC = "";
|
||||||
var j = 0;
|
var j = 0;
|
||||||
for (var i in myHistory) {
|
for (var i in myHistory[0]) {
|
||||||
// print(i);
|
|
||||||
var dateBrut = i[0];
|
var dateBrut = i[0];
|
||||||
dateBrut = DateTime.fromMillisecondsSinceEpoch(dateBrut * 1000);
|
dateBrut = DateTime.fromMillisecondsSinceEpoch(dateBrut * 1000);
|
||||||
final DateFormat formatter = DateFormat('dd-MM-yy - H:M');
|
final DateFormat formatter = DateFormat('dd-MM-yy - H:M');
|
||||||
|
@ -195,7 +194,7 @@ class _MyAppState extends State<MyApp> {
|
||||||
final amount = i[2];
|
final amount = i[2];
|
||||||
// final amountUD = i[3];
|
// final amountUD = i[3];
|
||||||
final comment = i[4];
|
final comment = i[4];
|
||||||
historyBloc += date.toString() +
|
historyBC += date.toString() +
|
||||||
" \n " +
|
" \n " +
|
||||||
issuer.toString() +
|
issuer.toString() +
|
||||||
" \n " +
|
" \n " +
|
||||||
|
@ -208,7 +207,37 @@ class _MyAppState extends State<MyApp> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._outputHistory.text = historyBloc;
|
|
||||||
|
String historyMP = "";
|
||||||
|
j = 0;
|
||||||
|
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 += "EN COURS DE RECEPTION\n" +
|
||||||
|
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 = historyMP + '\n' + historyBC;
|
||||||
|
}
|
||||||
|
this._outputHistory.text = history;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
64
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:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.13"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -43,13 +57,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0-nullsafety.3"
|
version: "1.15.0-nullsafety.3"
|
||||||
cupertino_icons:
|
convert:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: convert
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "2.1.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.5"
|
||||||
dio:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -69,6 +90,13 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_launcher_icons:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_launcher_icons
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.1"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -123,6 +151,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.4"
|
version: "3.1.4"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.19"
|
||||||
image_gallery_saver:
|
image_gallery_saver:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -193,6 +228,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -268,6 +310,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.3"
|
version: "2.1.0-nullsafety.3"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.10.0-110 <2.11.0"
|
dart: ">=2.10.0-110 <2.11.0"
|
||||||
flutter: ">=1.12.13+hotfix.5 <2.0.0"
|
flutter: ">=1.12.13+hotfix.5 <2.0.0"
|
||||||
|
|
|
@ -32,6 +32,12 @@ dependencies:
|
||||||
gql_exec:
|
gql_exec:
|
||||||
gql_link:
|
gql_link:
|
||||||
intl:
|
intl:
|
||||||
|
flutter_launcher_icons: "^0.8.0"
|
||||||
|
|
||||||
|
flutter_icons:
|
||||||
|
android: "launcher_icon"
|
||||||
|
ios: true
|
||||||
|
image_path: "assets/icon/gecko-bb-36.png"
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
|
|
@ -2,3 +2,18 @@
|
||||||
|
|
||||||
flutter build apk --split-per-abi
|
flutter build apk --split-per-abi
|
||||||
|
|
||||||
|
APPNAME = "gecko"
|
||||||
|
VERSION="dev1"
|
||||||
|
ori_app="app.apk"
|
||||||
|
|
||||||
|
if [[ -d $HOME/Téléchargements ]]; then
|
||||||
|
DL="$HOME/Téléchargements"
|
||||||
|
elif [[ -d $HOME/Downloads ]]; then
|
||||||
|
DL="$HOME/Downloads"
|
||||||
|
else
|
||||||
|
DL="/tmp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv build/app/outputs/flutter-apk/$ori_app "$DL/gecko-$VERSION" && echo "L'app se trouve ici: $DL/${APPNAME}-${VERSION}.apk" || exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|