From 27fa177a2e824e372af77ff80c70001442e4060a Mon Sep 17 00:00:00 2001 From: otsmr Date: Sat, 31 May 2025 13:42:12 +0200 Subject: [PATCH] fix #79 --- .gitmodules | 3 + .vscode/settings.json | 2 +- README.md | 4 + assets/animations/failed.json | 1 + assets/animations/success.json | 1 + dependencies/flutter_zxing | 1 + ios/Podfile.lock | 6 + lib/src/localization/app_de.arb | 1 + lib/src/localization/app_en.arb | 2 + .../generated/app_localizations.dart | 6 + .../generated/app_localizations_de.dart | 3 + .../generated/app_localizations_en.dart | 3 + .../views/components/format_long_string.dart | 2 +- .../views/contact/contact_verify.view.dart | 243 ++++++++++++------ .../contact/contact_verify_qr_scan.view.dart | 43 ++++ lib/src/views/settings/help/credits.view.dart | 41 ++- pubspec.lock | 7 + pubspec.yaml | 3 +- 18 files changed, 266 insertions(+), 106 deletions(-) create mode 100644 assets/animations/failed.json create mode 100644 assets/animations/success.json create mode 160000 dependencies/flutter_zxing create mode 100644 lib/src/views/contact/contact_verify_qr_scan.view.dart diff --git a/.gitmodules b/.gitmodules index a8f566c..a09ef52 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "dependencies/flutter_secure_storage"] path = dependencies/flutter_secure_storage url = https://github.com/juliansteenbakker/flutter_secure_storage +[submodule "dependencies/flutter_zxing"] + path = dependencies/flutter_zxing + url = https://github.com/khoren93/flutter_zxing.git diff --git a/.vscode/settings.json b/.vscode/settings.json index 41c6f8e..4fbd164 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "files.exclude": { + "files.watcherExclude": { "dependencies": false } } \ No newline at end of file diff --git a/README.md b/README.md index 4a8aed4..37ab1f9 100644 --- a/README.md +++ b/README.md @@ -13,5 +13,9 @@ pub.dev or because they require some special installation. ```bash git submodule update --init --recursive + +cd dependencies/flutter_zxing +git submodule update --init --recursive +./scripts/update_ios_macos_src.s ``` diff --git a/assets/animations/failed.json b/assets/animations/failed.json new file mode 100644 index 0000000..d79f90c --- /dev/null +++ b/assets/animations/failed.json @@ -0,0 +1 @@ +{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.1.1","a":"","k":"","d":"","tc":""},"fr":29.9700012207031,"ip":0,"op":60.0000024438501,"w":1080,"h":1080,"nm":"Failed","ddd":0,"assets":[],"fonts":{"list":[{"fName":"MyriadPro-Regular","fFamily":"Myriad Pro","fStyle":"Regular","ascent":70.9991455078125}]},"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"cros1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540.21,535.925,0],"ix":2},"a":{"a":0,"k":[319.771,234.922,0],"ix":1},"s":{"a":0,"k":[119.548,119.548,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-144.75,96.16]],"o":[[0,0],[0,0],[0,0]],"v":[[114.401,-118.25],[-53.706,49.857],[30.348,22.09]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":28.346,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[277.79,280.751],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":35.0000014255792,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":35.0000014255792,"s":[54]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"cros2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[537,534.463,0],"ix":2},"a":{"a":0,"k":[313.219,323.786,0],"ix":1},"s":{"a":0,"k":[119.548,119.548,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-144.75,-96.16]],"o":[[0,0],[0,0],[0,0]],"v":[[114.401,118.249],[-53.706,-49.857],[30.348,-22.09]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":28.346,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[277.79,280.941],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":35.0000014255792,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":35.0000014255792,"s":[54]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"elipse bold","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14,"s":[81]},{"t":27.0000010997325,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,535.5,0],"ix":2},"a":{"a":0,"k":[-62,-4.5,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[91.25,91.25,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":14,"s":[582.5,582.5,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":21,"s":[536.25,536.25,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":27,"s":[558.75,558.75,100]},{"t":269.000010956595,"s":[158.75,158.75,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.305882334709,0.305882334709,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-62,-4.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"elipse light","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14,"s":[80]},{"t":27.0000010997325,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,535.5,0],"ix":2},"a":{"a":0,"k":[-60.75,-4.5,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[150,150,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":14,"s":[580,580,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":21,"s":[528,528,100]},{"t":27.0000010997325,"s":[585,585,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[122.5,122.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643137216568,0.643137216568,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-60.75,-4.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":13,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":26,"s":[50]},{"t":36.0000014663101,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[540,540,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":13,"s":[415.646,415.646,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":26,"s":[577.128,577.128,100]},{"t":36.0000014663101,"s":[370.371,370.371,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[6,6],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-73,-4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 8","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[9,9],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[42,-63],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 7","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[7.5,7.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.25,-37.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 6","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[9.5,9.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-6.75,68.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 5","np":3,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[12.5,12.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[59.75,43.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 4","np":3,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[12,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-49.5,-57.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 3","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[17,17],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-51,48.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":3,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[15,15],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":5,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.643136978149,0.643136978149,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[66.5,-49],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":5,"nm":"Payment Failed","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"t":40.0000016292334,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[313.125,893,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":64,"f":"MyriadPro-Regular","t":"","j":0,"tr":0,"lh":76.8,"ls":0,"fc":[1,0.306,0.306]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":60.0000024438501,"st":0,"bm":0}],"markers":[],"chars":[]} \ No newline at end of file diff --git a/assets/animations/success.json b/assets/animations/success.json new file mode 100644 index 0000000..69e0011 --- /dev/null +++ b/assets/animations/success.json @@ -0,0 +1 @@ +{"v":"5.0.1","fr":29.9700012207031,"ip":0,"op":45.0000018328876,"w":512,"h":512,"nm":"Comp 1","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.572],"y":[0.556]},"o":{"x":[0.167],"y":[0.167]},"n":["0p572_0p556_0p167_0p167"],"t":7,"s":[100],"e":[92.154]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.641],"y":[0.056]},"n":["0p833_0p833_0p641_0p056"],"t":13,"s":[92.154],"e":[30]},{"t":17.0000006924242}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-230,4],[214,4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.792156862745098,0.5529411764705883,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":70,"ix":5},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.588],"y":[-51709.363]},"o":{"x":[0.167],"y":[0.167]},"n":["0p588_-51709p363_0p167_0p167"],"t":7,"s":[0],"e":[0]},{"i":{"x":[0.696],"y":[0.999]},"o":{"x":[0.509],"y":[0.003]},"n":["0p696_0p999_0p509_0p003"],"t":10,"s":[0],"e":[100]},{"t":16.0000006516934}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.566],"y":[0.999]},"o":{"x":[0.457],"y":[0.063]},"n":["0p566_0p999_0p457_0p063"],"t":7,"s":[0],"e":[100]},{"t":16.0000006516934}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0,0],"y":[0.997,0.997]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0_0p997_0p167_0p167","0_0p997_0p167_0p167"],"t":24,"s":[40,40],"e":[90,90]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.574,0.574],"y":[-0.004,-0.004]},"n":["0p833_0p833_0p574_-0p004","0p833_0p833_0p574_-0p004"],"t":27,"s":[90,90],"e":[18.394,18.394]},{"t":38.0000015477717}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"n":"0p667_1_0p167_0p167","t":24,"s":[-181.074,-5.414],"e":[200,-5.414],"to":[34.0465698242188,0],"ti":[-26.72825050354,0]},{"t":38.0000015477717}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":24,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":25,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":29,"s":[100],"e":[0]},{"t":38.0000015477717}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.572],"y":[0.556]},"o":{"x":[0.167],"y":[0.167]},"n":["0p572_0p556_0p167_0p167"],"t":10,"s":[100],"e":[92.154]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.641],"y":[0.056]},"n":["0p833_0p833_0p641_0p056"],"t":16,"s":[92.154],"e":[30]},{"t":20.0000008146167}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-230,4],[214,4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.792156862745098,0.5529411764705883,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":70,"ix":5},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.588],"y":[-51709.363]},"o":{"x":[0.167],"y":[0.167]},"n":["0p588_-51709p363_0p167_0p167"],"t":10,"s":[0],"e":[0]},{"i":{"x":[0.696],"y":[0.999]},"o":{"x":[0.509],"y":[0.003]},"n":["0p696_0p999_0p509_0p003"],"t":13,"s":[0],"e":[100]},{"t":19.0000007738859}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.566],"y":[0.999]},"o":{"x":[0.457],"y":[0.063]},"n":["0p566_0p999_0p457_0p063"],"t":10,"s":[0],"e":[100]},{"t":19.0000007738859}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"trait","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[263.334,471.109,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[15,15,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"trait","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-180,"ix":10},"p":{"a":0,"k":[51.641,253.275,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[15,15,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"trait","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[266.322,44.315,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[15,15,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"trait","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[469.91,258.792,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[15,15,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"firefly","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-18.097,"ix":10},"p":{"a":0,"k":[400.635,189.708,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[20,20,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"firefly","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-72.471,"ix":10},"p":{"a":0,"k":[359.413,150.912,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[20,20,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"firefly","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45.707,"ix":10},"p":{"a":0,"k":[396.894,150.961,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[30,30,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"trait 2","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-135.205,"ix":10},"p":{"a":0,"k":[410.865,406.53,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[-19.512,19.512,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":0,"nm":"trait 2","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45.606,"ix":10},"p":{"a":0,"k":[105.535,402.598,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[-19.512,19.512,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":0,"nm":"trait 2","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-135.205,"ix":10},"p":{"a":0,"k":[104.864,111.71,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[19.512,19.512,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"trait 2","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45.606,"ix":10},"p":{"a":0,"k":[416.722,113.206,0],"ix":2},"a":{"a":0,"k":[256,256,0],"ix":1},"s":{"a":0,"k":[19.512,19.512,100],"ix":6}},"ao":0,"w":512,"h":512,"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[236.888,240.258,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[69.59,69.59,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-76.426,37.999],[12.056,114.074],[169.991,-68.635]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":35,"ix":5},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-7,11],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[-2.986]},"o":{"x":[0.167],"y":[0]},"n":["0p833_-2p986_0p167_0"],"t":0,"s":[0],"e":[0]},{"i":{"x":[0],"y":[0.973]},"o":{"x":[0.167],"y":[0.042]},"n":["0_0p973_0p167_0p042"],"t":14.791,"s":[0],"e":[32]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.828],"y":[0.011]},"n":["0p833_0p833_0p828_0p011"],"t":19.791,"s":[32],"e":[100]},{"t":24.7912510097683}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[80,80,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.976,0.976],"y":[0.968,0.968]},"o":{"x":[0.654,0.654],"y":[0.007,0.007]},"n":["0p976_0p968_0p654_0p007","0p976_0p968_0p654_0p007"],"t":0,"s":[0,0],"e":[401.025,401.025]},{"i":{"x":[0.468,0.468],"y":[1.057,1.057]},"o":{"x":[0.346,0.346],"y":[-4.83,-4.83]},"n":["0p468_1p057_0p346_-4p83","0p468_1p057_0p346_-4p83"],"t":7,"s":[401.025,401.025],"e":[372.7,372.7]},{"i":{"x":[0.375,0.375],"y":[1.543,1.543]},"o":{"x":[0.364,0.364],"y":[0.031,0.031]},"n":["0p375_1p543_0p364_0p031","0p375_1p543_0p364_0p031"],"t":12,"s":[372.7,372.7],"e":[401.025,401.025]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0.327,0.327],"y":[-8.038,-8.038]},"n":["0p833_1_0p327_-8p038","0p833_1_0p327_-8p038"],"t":16,"s":[401.025,401.025],"e":[401.025,401.025]},{"t":20.0000008146167}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.792156862745098,0.5529411764705883,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[5.992,3.49],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0}]} \ No newline at end of file diff --git a/dependencies/flutter_zxing b/dependencies/flutter_zxing new file mode 160000 index 0000000..ba65f2f --- /dev/null +++ b/dependencies/flutter_zxing @@ -0,0 +1 @@ +Subproject commit ba65f2fb4a09f4e68f6de64aa1de41ba3dc4977e diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 69e0a17..ec018ee 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -71,6 +71,8 @@ PODS: - flutter_secure_storage_darwin (10.0.0): - Flutter - FlutterMacOS + - flutter_zxing (0.0.1): + - Flutter - gal (1.0.0): - Flutter - FlutterMacOS @@ -234,6 +236,7 @@ DEPENDENCIES: - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`) + - flutter_zxing (from `.symlinks/plugins/flutter_zxing/ios`) - gal (from `.symlinks/plugins/gal/darwin`) - GoogleUtilities - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) @@ -290,6 +293,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_local_notifications/ios" flutter_secure_storage_darwin: :path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin" + flutter_zxing: + :path: ".symlinks/plugins/flutter_zxing/ios" gal: :path: ".symlinks/plugins/gal/darwin" image_picker_ios: @@ -337,6 +342,7 @@ SPEC CHECKSUMS: flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619 flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468 + flutter_zxing: e8bcc43bd3056c70c271b732ed94e7a16fd62f93 gal: baecd024ebfd13c441269ca7404792a7152fde89 GoogleAppMeasurement: 36684bfb3ee034e2b42b4321eb19da3a1b81e65d GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index a27dfb0..f8e9c23 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -131,6 +131,7 @@ "settingsAccountDeleteModalTitle": "Bist du sicher?", "settingsAccountDeleteModalBody": "Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.", "contactVerifyNumberTitle": "Sicherheitsnummer verifizieren", + "contactVerifyNumberTapToScan": "Zum Scannen tippen", "contactVerifyNumberMarkAsVerified": "Als verifiziert markieren", "contactVerifyNumberClearVerification": "Verifizierung aufheben", "contactVerifyNumberLongDesc": "Um die Ende-zu-Ende-Verschlüsselung mit {username} zu verifizieren, vergleiche die Zahlen mit ihrem Gerät. Die Person kann auch deinen Code mit ihrem Gerät scannen.", diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 806167b..59d2c20 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -231,6 +231,8 @@ "@settingsAccountDeleteModalBody": {}, "contactVerifyNumberTitle": "Verify safety number", "@contactVerifyNumberTitle": {}, + "contactVerifyNumberTapToScan": "Tap to scan", + "@contactVerifyNumberTapToScan": {}, "contactVerifyNumberMarkAsVerified": "Mark as verified", "@contactVerifyNumberMarkAsVerified": {}, "contactVerifyNumberClearVerification": "Clear verification", diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index 069726d..b511b35 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -788,6 +788,12 @@ abstract class AppLocalizations { /// **'Verify safety number'** String get contactVerifyNumberTitle; + /// No description provided for @contactVerifyNumberTapToScan. + /// + /// In en, this message translates to: + /// **'Tap to scan'** + String get contactVerifyNumberTapToScan; + /// No description provided for @contactVerifyNumberMarkAsVerified. /// /// In en, this message translates to: diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index 589fc30..f0c8ea6 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -385,6 +385,9 @@ class AppLocalizationsDe extends AppLocalizations { @override String get contactVerifyNumberTitle => 'Sicherheitsnummer verifizieren'; + @override + String get contactVerifyNumberTapToScan => 'Zum Scannen tippen'; + @override String get contactVerifyNumberMarkAsVerified => 'Als verifiziert markieren'; diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index d309214..caf40b9 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -380,6 +380,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get contactVerifyNumberTitle => 'Verify safety number'; + @override + String get contactVerifyNumberTapToScan => 'Tap to scan'; + @override String get contactVerifyNumberMarkAsVerified => 'Mark as verified'; diff --git a/lib/src/views/components/format_long_string.dart b/lib/src/views/components/format_long_string.dart index c8911bf..ca74935 100644 --- a/lib/src/views/components/format_long_string.dart +++ b/lib/src/views/components/format_long_string.dart @@ -30,7 +30,7 @@ class FormattedStringWidget extends StatelessWidget { Widget build(BuildContext context) { return SelectableText( formatString(longString), - style: TextStyle(fontSize: 18, color: Colors.black), + style: TextStyle(fontSize: 16, color: Colors.black), textAlign: TextAlign.center, ); } diff --git a/lib/src/views/contact/contact_verify.view.dart b/lib/src/views/contact/contact_verify.view.dart index 5531789..b16da39 100644 --- a/lib/src/views/contact/contact_verify.view.dart +++ b/lib/src/views/contact/contact_verify.view.dart @@ -1,8 +1,10 @@ +import 'dart:async'; import 'dart:convert'; import 'package:drift/drift.dart' hide Column; +import 'package:flutter_zxing/flutter_zxing.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; -import 'package:qr_flutter/qr_flutter.dart'; +import 'package:lottie/lottie.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/services/signal/session.signal.dart'; import 'package:twonly/src/views/components/format_long_string.dart'; @@ -10,7 +12,9 @@ import 'package:flutter/material.dart'; import 'package:twonly/src/database/daos/contacts_dao.dart'; import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/utils/misc.dart'; +import 'package:twonly/src/views/contact/contact_verify_qr_scan.view.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:image/image.dart' as imglib; class ContactVerifyView extends StatefulWidget { const ContactVerifyView(this.contact, {super.key}); @@ -20,31 +24,127 @@ class ContactVerifyView extends StatefulWidget { State createState() => _ContactVerifyViewState(); } +enum ScanResult { None, Success, Failed } + class _ContactVerifyViewState extends State { - Fingerprint? fingerprint; + Fingerprint? _fingerprint; + late Contact _contact; + late StreamSubscription _contactSub; + ScanResult _scanResult = ScanResult.None; + Uint8List? _qrCodeImageBytes; @override void initState() { super.initState(); + _contact = widget.contact; loadAsync(); } - Future loadAsync() async { - fingerprint = await generateSessionFingerPrint(widget.contact.userId); - setState(() {}); + @override + void dispose() { + _contactSub.cancel(); + super.dispose(); } - @override - Widget build(BuildContext context) { + Future loadAsync() async { + _fingerprint = await generateSessionFingerPrint(widget.contact.userId); + + if (_fingerprint != null) { + final Encode result = zx.encodeBarcode( + contents: base64Encode( + _fingerprint!.scannableFingerprint.fingerprints, + ), + params: EncodeParams( + format: Format.qrCode, + width: 150, + height: 150, + margin: 0, + eccLevel: EccLevel.low, + ), + ); + if (result.isValid && result.data != null) { + final img = imglib.Image.fromBytes( + width: 150, + height: 150, + bytes: result.data!.buffer, + numChannels: 1, + ); + _qrCodeImageBytes = imglib.encodePng(img); + } + } + Stream contact = twonlyDB.contactsDao .getContactByUserId(widget.contact.userId) .watchSingleOrNull(); + _contactSub = contact.listen((contact) { + if (contact == null) return; + setState(() { + _contact = contact; + }); + }); + setState(() {}); + } + Future openQrScanner() async { + if (_fingerprint == null) return; + bool? isValid = await Navigator.push(context, MaterialPageRoute( + builder: (context) { + return ContactVerifyQrScanView( + widget.contact, + fingerprint: _fingerprint!, + ); + }, + )); + if (isValid == null) { + return; // user just returned... + } + if (isValid) { + _scanResult = ScanResult.Success; + updateUserVerifyState(true); + } else { + _scanResult = ScanResult.Failed; + updateUserVerifyState(false); + } + setState(() {}); + } + + Future updateUserVerifyState(bool verified) async { + final update = ContactsCompanion(verified: Value(verified)); + await twonlyDB.contactsDao.updateContact(_contact.userId, update); + } + + Widget get qrWidget => (_qrCodeImageBytes == null) + ? SizedBox( + width: 150, + height: 150, + ) + : Image.memory(_qrCodeImageBytes!); + Widget get resultAnimation => SizedBox( + width: 150, + child: Lottie.asset( + (_scanResult == ScanResult.Success) + ? 'assets/animations/success.json' + : 'assets/animations/failed.json', + repeat: false, + onLoaded: (p0) { + Future.delayed(Duration(seconds: 3), () { + if (mounted) { + setState(() { + _scanResult = ScanResult.None; + }); + } + }); + }, + ), + ); + + @override + Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(context.lang.contactVerifyNumberTitle), ), - body: (fingerprint == null) + body: (_fingerprint == null) ? Center(child: CircularProgressIndicator()) : ListView( children: [ @@ -57,55 +157,57 @@ class _ContactVerifyViewState extends State { borderRadius: BorderRadius.circular(10), color: Theme.of(context).colorScheme.primary, ), - child: Column( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Colors.white, + child: GestureDetector( + onTap: openQrScanner, + child: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + ), + padding: EdgeInsets.symmetric(vertical: 20), + child: Column( + children: [ + (_scanResult == ScanResult.None) + ? qrWidget + : resultAnimation, + SizedBox(height: 10), + SizedBox( + width: 200, + child: Text( + (_scanResult == ScanResult.None) + ? context + .lang.contactVerifyNumberTapToScan + : "", + style: TextStyle( + color: Colors.black, + fontSize: 15, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), ), - child: QrImageView( - data: base64Encode(fingerprint! - .scannableFingerprint.fingerprints), - version: QrVersions.auto, - size: 150.0, + SizedBox(height: 20), + FormattedStringWidget( + _fingerprint!.displayableFingerprint + .getDisplayText(), ), - ), - SizedBox(height: 10), - SizedBox( - width: 200, - child: Text( - "QR Code scanning is coming soon. Please compare the numbers manual.", - style: - TextStyle(color: Colors.black, fontSize: 10), - textAlign: TextAlign.center, - ), - ), - SizedBox(height: 20), - FormattedStringWidget( - fingerprint!.displayableFingerprint - .getDisplayText(), - ), - ], + ], + ), ), ), ), ), - StreamBuilder( - stream: contact, - builder: (context, snapshot) { - if (!snapshot.hasData || snapshot.data == null) { - return Container(); - } - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: Text( - context.lang.contactVerifyNumberLongDesc( - getContactDisplayName(snapshot.data!)), - textAlign: TextAlign.center, - ), - ); - }, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: Text( + context.lang.contactVerifyNumberLongDesc( + getContactDisplayName(_contact)), + textAlign: TextAlign.center, + ), ), Padding( padding: @@ -133,36 +235,19 @@ class _ContactVerifyViewState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - StreamBuilder( - stream: contact, - builder: (context, snapshot) { - if (!snapshot.hasData || snapshot.data == null) { - return Container(); - } - final contact = snapshot.data!; - if (contact.verified) { - return OutlinedButton.icon( - onPressed: () { - final update = - ContactsCompanion(verified: Value(false)); - twonlyDB.contactsDao - .updateContact(contact.userId, update); - }, + (_contact.verified) + ? OutlinedButton.icon( + onPressed: () => updateUserVerifyState(false), label: Text( context.lang.contactVerifyNumberClearVerification), - ); - } - return FilledButton.icon( - icon: FaIcon(FontAwesomeIcons.shieldHeart), - onPressed: () { - final update = ContactsCompanion(verified: Value(true)); - twonlyDB.contactsDao - .updateContact(contact.userId, update); - }, - label: Text(context.lang.contactVerifyNumberMarkAsVerified), - ); - }, - ), + ) + : FilledButton.icon( + icon: FaIcon(FontAwesomeIcons.shieldHeart), + onPressed: () => updateUserVerifyState(true), + label: Text( + context.lang.contactVerifyNumberMarkAsVerified, + ), + ) ], ), ), diff --git a/lib/src/views/contact/contact_verify_qr_scan.view.dart b/lib/src/views/contact/contact_verify_qr_scan.view.dart new file mode 100644 index 0000000..e939515 --- /dev/null +++ b/lib/src/views/contact/contact_verify_qr_scan.view.dart @@ -0,0 +1,43 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_zxing/flutter_zxing.dart'; +import 'package:libsignal_protocol_dart/libsignal_protocol_dart.dart'; +import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/utils/log.dart'; + +class ContactVerifyQrScanView extends StatefulWidget { + const ContactVerifyQrScanView(this.contact, + {super.key, required this.fingerprint}); + final Fingerprint fingerprint; + final Contact contact; + + @override + State createState() => + _ContactVerifyQrScanViewState(); +} + +class _ContactVerifyQrScanViewState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ReaderWidget( + onScan: (result) async { + bool isValid = false; + try { + if (result.text != null) { + Uint8List otherFingerPrint = base64Decode(result.text!); + isValid = widget.fingerprint.scannableFingerprint.compareTo( + otherFingerPrint, + ); + } + } catch (e) { + Log.error("$e"); + } + return Navigator.pop(context, isValid); + }, + ), + ); + } +} diff --git a/lib/src/views/settings/help/credits.view.dart b/lib/src/views/settings/help/credits.view.dart index 47faeb7..4a6bd2d 100644 --- a/lib/src/views/settings/help/credits.view.dart +++ b/lib/src/views/settings/help/credits.view.dart @@ -63,40 +63,51 @@ class CreditsView extends StatelessWidget { )), ), UrlListTitle( - title: "Free selfie fast Animation", + title: "selfie fast Animation", subtitle: "Brandon Ambuila", url: "https://lottiefiles.com/free-animation/selfie-fast-JZx4Ftrg1E", ), UrlListTitle( - title: "Free Security status - Safe Animation", + title: "Security status - Safe Animation", subtitle: "Yogesh Pal", url: "https://lottiefiles.com/free-animation/security-status-safe-CePJPAwLVx", ), UrlListTitle( - title: "Free send mail Animation", + title: "send mail Animation", subtitle: "jignesh gajjar", url: "https://lottiefiles.com/free-animation/send-mail-3pvzm2kmNq", ), UrlListTitle( - title: "Free Present for you Animation", + title: "Present for you Animation", subtitle: "Tatsiana Melnikova", url: "https://lottiefiles.com/free-animation/present-for-you-QalWyuNptY", ), UrlListTitle( - title: "Free Take a photo Animation", + title: "Take a photo Animation", subtitle: "Nguyễn Như Lân", url: "https://lottiefiles.com/free-animation/take-a-photo-CzOUerxwPP?color-palette=true", ), UrlListTitle( - title: "Kostenlose Valentine's Day-Animation", + title: "Valentine's Day-Animation", subtitle: "Strezha", url: "https://lottiefiles.com/de/free-animation/valentines-day-1UiMkPHnPK?color-palette=true", ), + UrlListTitle( + title: "success-Animation", + subtitle: "Aman Awasthy", + url: + "https://lottiefiles.com/de/free-animation/success-tick-cuwjLHAR7g", + ), + UrlListTitle( + title: "Failed-Animation", + subtitle: "Ahmed Shami أحمد شامي", + url: "https://lottiefiles.com/de/free-animation/failed-e5cQFDEtLv", + ), const Divider(), ListTile( title: Center( @@ -105,18 +116,6 @@ class CreditsView extends StatelessWidget { style: TextStyle(fontWeight: FontWeight.bold), )), ), - UrlListTitle( - title: "Germany", - subtitle: "by GDJ", - url: - "https://pixabay.com/vectors/republic-germany-deutschland-map-1220652/", - ), - UrlListTitle( - title: "Frankfurt am Main", - subtitle: "by GDJ", - url: - "https://pixabay.com/vectors/frankfurt-germany-skyline-cityscape-3166262/", - ), UrlListTitle( title: "Avo Cardio", subtitle: "by RalfDesign", @@ -129,12 +128,6 @@ class CreditsView extends StatelessWidget { url: "https://pixabay.com/illustrations/sloth-swimming-summer-pool-cartoon-4575121/", ), - UrlListTitle( - title: "Sloth", - subtitle: "by RalfDesign", - url: - "https://pixabay.com/illustrations/sloth-swimming-summer-pool-cartoon-4575121/", - ), UrlListTitle( title: "Duck", subtitle: "by lachkegeetanjali", diff --git a/pubspec.lock b/pubspec.lock index b1b4648..89f26f6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -716,6 +716,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_zxing: + dependency: "direct main" + description: + path: "dependencies/flutter_zxing" + relative: true + source: path + version: "2.1.0" font_awesome_flutter: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d565540..631e3d7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,8 @@ dependencies: # flutter_secure_storage: ^10.0.0-beta.4 flutter_secure_storage: path: ./dependencies/flutter_secure_storage/flutter_secure_storage + flutter_zxing: + path: ./dependencies/flutter_zxing font_awesome_flutter: ^10.8.0 gal: ^2.3.1 hand_signature: ^3.0.3 @@ -46,7 +48,6 @@ dependencies: protobuf: ^4.0.0 cryptography_plus: ^2.7.0 provider: ^6.1.2 - qr_flutter: ^4.1.0 restart_app: ^1.3.2 screenshot: ^3.0.0 url_launcher: ^6.3.1