From 3a62efc6cc85fc23232c5774d83f010e3860dee7 Mon Sep 17 00:00:00 2001 From: mitchell Date: Sat, 29 Jun 2019 15:36:50 -0700 Subject: [PATCH 1/8] Initial commit, including README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e8bb04a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# selfpass_client + +This is the multi-platform native Selfpass client. From cad969d98c83fc7f965ea57c89e4be68759a1746 Mon Sep 17 00:00:00 2001 From: mitchell Date: Sat, 29 Jun 2019 15:56:11 -0700 Subject: [PATCH 2/8] Initial app scaffolding, including flutter files, 3 screens, and 1 widget --- .gitignore | 70 +++ .metadata | 10 + android/app/build.gradle | 61 +++ android/app/src/debug/AndroidManifest.xml | 7 + android/app/src/main/AndroidManifest.xml | 33 ++ .../example/selfpass_mobile/MainActivity.java | 13 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes android/app/src/main/res/values/styles.xml | 8 + android/app/src/profile/AndroidManifest.xml | 7 + android/build.gradle | 29 + android/gradle.properties | 1 + .../gradle/wrapper/gradle-wrapper.properties | 6 + android/settings.gradle | 15 + ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Runner.xcodeproj/project.pbxproj | 506 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Runner.xcscheme | 93 ++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.h | 6 + ios/Runner/AppDelegate.m | 13 + .../AppIcon.appiconset/Contents.json | 122 +++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 11112 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 45 ++ ios/Runner/main.m | 9 + lib/main.dart | 21 + lib/screens/authentication.dart | 72 +++ lib/screens/credentials.dart | 26 + lib/screens/home.dart | 29 + lib/widgets/tappable_text_list.dart | 35 ++ pubspec.lock | 230 ++++++++ pubspec.yaml | 41 ++ test/widget_test.dart | 30 ++ 61 files changed, 1691 insertions(+) create mode 100644 .gitignore create mode 100644 .metadata create mode 100644 android/app/build.gradle create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/java/com/example/selfpass_mobile/MainActivity.java create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.h create mode 100644 ios/Runner/AppDelegate.m create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/main.m create mode 100644 lib/main.dart create mode 100644 lib/screens/authentication.dart create mode 100644 lib/screens/credentials.dart create mode 100644 lib/screens/home.dart create mode 100644 lib/widgets/tappable_text_list.dart create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 test/widget_test.dart diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07488ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..033ad2a --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b + channel: stable + +project_type: app diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..a49d2ac --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,61 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.selfpass_mobile" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..2aa04ad --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..813275a --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/com/example/selfpass_mobile/MainActivity.java b/android/app/src/main/java/com/example/selfpass_mobile/MainActivity.java new file mode 100644 index 0000000..f31de72 --- /dev/null +++ b/android/app/src/main/java/com/example/selfpass_mobile/MainActivity.java @@ -0,0 +1,13 @@ +package com.example.selfpass_mobile; + +import android.os.Bundle; +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; + +public class MainActivity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + } +} diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..2aa04ad --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..bb8a303 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..8bd86f6 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2819f02 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9367d48 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f202b9d --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,506 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, + 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 97C146F21CF9000F007C117D /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0910; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, + 97C146F31CF9000F007C117D /* main.m in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = S8QB4VV633; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_NAME = "$(TARGET_NAME)"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..786d6aa --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..949b678 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + diff --git a/ios/Runner/AppDelegate.h b/ios/Runner/AppDelegate.h new file mode 100644 index 0000000..36e21bb --- /dev/null +++ b/ios/Runner/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : FlutterAppDelegate + +@end diff --git a/ios/Runner/AppDelegate.m b/ios/Runner/AppDelegate.m new file mode 100644 index 0000000..59a72e9 --- /dev/null +++ b/ios/Runner/AppDelegate.m @@ -0,0 +1,13 @@ +#include "AppDelegate.h" +#include "GeneratedPluginRegistrant.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + // Override point for customization after application launch. + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d43d11e66f4de3da27ed045ca4fe38ad8b48094 GIT binary patch literal 11112 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 P-1+_A+?hGkL;m(J7kc&K literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c6bf03016f6c994b70f38d1b7346e5831b531f GIT binary patch literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..f1de609 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + selfpass_mobile + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Runner/main.m b/ios/Runner/main.m new file mode 100644 index 0000000..dff6597 --- /dev/null +++ b/ios/Runner/main.m @@ -0,0 +1,9 @@ +#import +#import +#import "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..d29212b --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,21 @@ +import 'package:flutter/cupertino.dart'; + +import 'screens/authentication.dart'; +import 'screens/home.dart'; +import 'screens/credentials.dart'; + +void main() => runApp(Selfpass()); + +class Selfpass extends StatelessWidget { + @override + Widget build(BuildContext context) { + return CupertinoApp( + title: 'Selfpass', + routes: { + '/': (BuildContext context) => Authentication(), + '/home': (BuildContext context) => Home(), + '/credentials': (BuildContext context) => Credentials(), + }, + ); + } +} diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart new file mode 100644 index 0000000..4f924d0 --- /dev/null +++ b/lib/screens/authentication.dart @@ -0,0 +1,72 @@ +import 'package:flutter/cupertino.dart'; + +class Authentication extends StatefulWidget { + @override + _AuthenticationState createState() => _AuthenticationState(); +} + +class _AuthenticationState extends State { + static const String _masterpass = 'hunter#2'; + bool _invalid = false; + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 50.0), + child: Column( + children: _buildColumnChildren(context), + ), + ), + ); + } + + List _buildColumnChildren(BuildContext context) { + final children = [ + const Spacer(flex: 4), + const Flexible(child: Text('Master password:')), + Flexible( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: CupertinoTextField( + decoration: BoxDecoration( + border: Border.all(color: CupertinoColors.black), + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + ), + clearButtonMode: OverlayVisibilityMode.editing, + textAlign: TextAlign.center, + onSubmitted: _makeTextFieldOnSubmittedHandler(context), + obscureText: true, + ), + ), + ), + ]; + + if (_invalid) { + children.add(const Flexible( + child: Text( + 'invalid masterpass', + style: TextStyle(color: CupertinoColors.destructiveRed), + ), + )); + children.add(const Spacer(flex: 2)); + } else { + children.add(const Spacer(flex: 3)); + } + + return children; + } + + ValueChanged _makeTextFieldOnSubmittedHandler(BuildContext context) { + return (String pass) { + if (pass != _masterpass) { + this.setState(() { + _invalid = true; + }); + return; + } + + Navigator.of(context).pushReplacementNamed('/home'); + }; + } +} diff --git a/lib/screens/credentials.dart b/lib/screens/credentials.dart new file mode 100644 index 0000000..cf8b109 --- /dev/null +++ b/lib/screens/credentials.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; + +import '../widgets/tappable_text_list.dart'; + +class Credentials extends StatelessWidget { + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + child: TappableTextList(tappableText: _buildTappableText(context)), + navigationBar: const CupertinoNavigationBar(middle: Text('Credentials')), + ); + } + + static Map _buildTappableText( + BuildContext context) { + var handleOnTap = () {}; + + Map tappableText = { + 'm@mjfs.us': handleOnTap, + 'm-mjfs': handleOnTap, + 'mitchelljfsimon@gmail.com-mitchelljfsimon': handleOnTap, + }; + + return tappableText; + } +} diff --git a/lib/screens/home.dart b/lib/screens/home.dart new file mode 100644 index 0000000..53030d0 --- /dev/null +++ b/lib/screens/home.dart @@ -0,0 +1,29 @@ +import 'package:flutter/cupertino.dart'; +// import 'package:provider/provider.dart'; + +// import '../types/abstracts.dart'; +// import '../types/credential.dart'; +import '../widgets/tappable_text_list.dart'; + +class Home extends StatelessWidget { + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + child: TappableTextList(tappableText: _buildTappableText(context)), + navigationBar: + const CupertinoNavigationBar(middle: Text('Credentials Hosts')), + ); + } + + static Map _buildTappableText( + BuildContext context) { + var handleOnTap = () => Navigator.of(context).pushNamed('/credentials'); + Map tappableText = { + "google.com": handleOnTap, + "amazon.com": handleOnTap, + "linkedin.com": handleOnTap, + }; + + return tappableText; + } +} diff --git a/lib/widgets/tappable_text_list.dart b/lib/widgets/tappable_text_list.dart new file mode 100644 index 0000000..20b7cc2 --- /dev/null +++ b/lib/widgets/tappable_text_list.dart @@ -0,0 +1,35 @@ +import 'package:flutter/cupertino.dart'; + +class TappableTextList extends StatelessWidget { + final Map tappableText; + + TappableTextList({Key key, this.tappableText}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListView( + children: _buildListChildren(context), + ); + } + + List _buildListChildren(BuildContext context) { + List widgets = []; + + tappableText.forEach((String text, GestureTapCallback handleOnTap) { + widgets.add(GestureDetector( + onTap: handleOnTap, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 15.0), + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide(color: CupertinoColors.lightBackgroundGray), + ), + ), + child: Text(text, textAlign: TextAlign.center), + ), + )); + }); + + return widgets; + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..97dcf06 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,230 @@ +# Generated by pub +# See https://www.dartlang.org/tools/pub/glossary#lockfile +packages: + _discoveryapis_commons: + dependency: transitive + description: + name: _discoveryapis_commons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.8+1" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.9" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + googleapis: + dependency: "direct main" + description: + name: googleapis + url: "https://pub.dartlang.org" + source: hosted + version: "0.53.0" + googleapis_auth: + dependency: transitive + description: + name: googleapis_auth + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.8" + grpc: + dependency: "direct main" + description: + name: grpc + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0+2" + http2: + dependency: transitive + description: + name: http2 + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.5" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.2" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" + protobuf: + dependency: "direct main" + description: + name: protobuf + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.12" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0+1" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.5" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.4" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" +sdks: + dart: ">=2.2.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..47dd54e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,41 @@ +name: selfpass_client +description: The cross-platform Selfpass client. + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^0.1.2 + + grpc: ^1.0.3 + protobuf: ^0.13.12 + googleapis: ^0.53.0 + + provider: ^3.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..99baf66 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:selfpass_mobile/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} From d0505a4a5818d682ed16cd594f6cad0f3ac194eb Mon Sep 17 00:00:00 2001 From: mitchell Date: Thu, 4 Jul 2019 17:45:05 -0400 Subject: [PATCH 3/8] Added repositories using provider package --- ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 69 ++++ ios/Podfile.lock | 22 + ios/Runner.xcodeproj/project.pbxproj | 91 ++++- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../contents.xcworkspacedata | 3 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + ios/Runner/Info.plist | 2 + lib/main.dart | 48 ++- .../google/protobuf/timestamp.pb.dart | 61 +++ .../google/protobuf/timestamp.pbenum.dart | 6 + .../google/protobuf/timestamp.pbjson.dart | 14 + lib/protobuf/service.pb.dart | 384 ++++++++++++++++++ lib/protobuf/service.pbenum.dart | 6 + lib/protobuf/service.pbgrpc.dart | 158 +++++++ lib/protobuf/service.pbjson.dart | 90 ++++ lib/protobuf/service.proto | 75 ++++ lib/repositories/config.dart | 65 +++ lib/repositories/credentials_client.dart | 79 ++++ lib/screens/authentication.dart | 113 ++++-- lib/screens/credentials.dart | 20 +- lib/screens/home.dart | 73 +++- lib/types/abstracts.dart | 24 ++ lib/types/connection_config.dart | 27 ++ lib/types/credential.dart | 94 +++++ lib/utils/crypto.dart | 15 + lib/widgets/obfuscated_text_field.dart | 28 ++ pubspec.lock | 14 + pubspec.yaml | 3 + 30 files changed, 1539 insertions(+), 63 deletions(-) create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 lib/protobuf/google/protobuf/timestamp.pb.dart create mode 100644 lib/protobuf/google/protobuf/timestamp.pbenum.dart create mode 100644 lib/protobuf/google/protobuf/timestamp.pbjson.dart create mode 100644 lib/protobuf/service.pb.dart create mode 100644 lib/protobuf/service.pbenum.dart create mode 100644 lib/protobuf/service.pbgrpc.dart create mode 100644 lib/protobuf/service.pbjson.dart create mode 100644 lib/protobuf/service.proto create mode 100644 lib/repositories/config.dart create mode 100644 lib/repositories/credentials_client.dart create mode 100644 lib/types/abstracts.dart create mode 100644 lib/types/connection_config.dart create mode 100644 lib/types/credential.dart create mode 100644 lib/utils/crypto.dart create mode 100644 lib/widgets/obfuscated_text_field.dart diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..e8efba1 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..399e934 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..d077b08 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,69 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + pods_ary = [] + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) { |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + pods_ary.push({:name => podname, :path => podpath}); + else + puts "Invalid plugin specification: #{line}" + end + } + return pods_ary +end + +target 'Runner' do + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + + # Flutter Pods + generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') + if generated_xcode_build_settings.empty? + puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." + end + generated_xcode_build_settings.map { |p| + if p[:name] == 'FLUTTER_FRAMEWORK_DIR' + symlink = File.join('.symlinks', 'flutter') + File.symlink(File.dirname(p[:path]), symlink) + pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) + end + } + + # Plugin Pods + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.map { |p| + symlink = File.join('.symlinks', 'plugins', p[:name]) + File.symlink(p[:path], symlink) + pod p[:name], :path => File.join(symlink, 'ios') + } +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..557bbc7 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - flutter_secure_storage (3.2.0): + - Flutter + +DEPENDENCIES: + - Flutter (from `.symlinks/flutter/ios`) + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: ".symlinks/flutter/ios" + flutter_secure_storage: + :path: ".symlinks/plugins/flutter_secure_storage/ios" + +SPEC CHECKSUMS: + Flutter: 58dd7d1b27887414a370fcccb9e645c08ffd7a6a + flutter_secure_storage: 0c5779648ff644110e507909b77a57e620cbbf8b + +PODFILE CHECKSUM: aff02bfeed411c636180d6812254b2daeea14d09 + +COCOAPODS: 1.7.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index f202b9d..3b9aebf 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + F8EF57AFFF0C7C353E3604B3 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 097444538E941EBFED1976C8 /* libPods-Runner.a */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -37,13 +38,16 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 097444538E941EBFED1976C8 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 4674E99068360BD2489EC50C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 880DAEE09FC4F07D8ED7F46C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; @@ -53,6 +57,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A4F4986515B0C16B78A73BD7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +67,7 @@ files = ( 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + F8EF57AFFF0C7C353E3604B3 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -87,7 +93,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + D52790F7E6421775A2150276 /* Pods */, + E491E94631566224F7EB2248 /* Frameworks */, ); sourceTree = ""; }; @@ -123,6 +130,24 @@ name = "Supporting Files"; sourceTree = ""; }; + D52790F7E6421775A2150276 /* Pods */ = { + isa = PBXGroup; + children = ( + 880DAEE09FC4F07D8ED7F46C /* Pods-Runner.debug.xcconfig */, + A4F4986515B0C16B78A73BD7 /* Pods-Runner.release.xcconfig */, + 4674E99068360BD2489EC50C /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + E491E94631566224F7EB2248 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 097444538E941EBFED1976C8 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -130,12 +155,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 0D0C54F13DCFB588B50287A7 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 273F25DC0E60392B1958115D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -157,6 +184,8 @@ TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = D8G6NQ28ZR; + ProvisioningStyle = Automatic; }; }; }; @@ -165,6 +194,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -194,6 +224,46 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0D0C54F13DCFB588B50287A7 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 273F25DC0E60392B1958115D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -310,8 +380,10 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = S8QB4VV633; + DEVELOPMENT_TEAM = D8G6NQ28ZR; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -323,8 +395,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_BUNDLE_IDENTIFIER = com.mjfs.selfpass; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; @@ -436,7 +509,10 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = D8G6NQ28ZR; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -448,8 +524,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_BUNDLE_IDENTIFIER = com.mjfs.selfpass; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -459,7 +536,10 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = D8G6NQ28ZR; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -471,8 +551,9 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.selfpassMobile; + PRODUCT_BUNDLE_IDENTIFIER = com.mjfs.selfpass; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index f1de609..3691648 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + Selfpass CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/lib/main.dart b/lib/main.dart index d29212b..4e26e49 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,21 +1,53 @@ import 'package:flutter/cupertino.dart'; +import 'package:provider/provider.dart'; + +import 'repositories/credentials_client.dart'; +import 'repositories/config.dart'; import 'screens/authentication.dart'; -import 'screens/home.dart'; import 'screens/credentials.dart'; +import 'screens/home.dart'; + +import 'types/abstracts.dart'; void main() => runApp(Selfpass()); class Selfpass extends StatelessWidget { @override Widget build(BuildContext context) { - return CupertinoApp( - title: 'Selfpass', - routes: { - '/': (BuildContext context) => Authentication(), - '/home': (BuildContext context) => Home(), - '/credentials': (BuildContext context) => Credentials(), - }, + return Provider( + builder: (BuildContext context) => Config(), + child: CupertinoApp( + title: 'Selfpass', + onGenerateRoute: (RouteSettings settings) { + String title; + WidgetBuilder builder; + + switch (settings.name) { + case '/': + title = 'Authentication'; + builder = (BuildContext context) => Authentication(); + break; + + case '/home': + title = "Credential Hosts"; + builder = (BuildContext context) => Provider( + builder: (BuildContext context) => + CredentialsClient(settings.arguments), + child: Home(), + ); + break; + + case '/credentials': + title = "Credentials"; + builder = + (BuildContext context) => Credentials(settings.arguments); + break; + } + + return CupertinoPageRoute(builder: builder, title: title); + }, + ), ); } } diff --git a/lib/protobuf/google/protobuf/timestamp.pb.dart b/lib/protobuf/google/protobuf/timestamp.pb.dart new file mode 100644 index 0000000..be02171 --- /dev/null +++ b/lib/protobuf/google/protobuf/timestamp.pb.dart @@ -0,0 +1,61 @@ +/// +// Generated code. Do not modify. +// source: timestamp.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:fixnum/fixnum.dart'; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'dart:core' as $core show DateTime, Duration; +class Timestamp extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('Timestamp', package: const $pb.PackageName('google.protobuf')) + ..aInt64(1, 'seconds') + ..a<$core.int>(2, 'nanos', $pb.PbFieldType.O3) + ..hasRequiredFields = false + ; + + Timestamp._() : super(); + factory Timestamp() => create(); + factory Timestamp.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Timestamp.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + Timestamp clone() => Timestamp()..mergeFromMessage(this); + Timestamp copyWith(void Function(Timestamp) updates) => super.copyWith((message) => updates(message as Timestamp)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static Timestamp create() => Timestamp._(); + Timestamp createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static Timestamp getDefault() => _defaultInstance ??= create()..freeze(); + static Timestamp _defaultInstance; + + Int64 get seconds => $_getI64(0); + set seconds(Int64 v) { $_setInt64(0, v); } + $core.bool hasSeconds() => $_has(0); + void clearSeconds() => clearField(1); + + $core.int get nanos => $_get(1, 0); + set nanos($core.int v) { $_setSignedInt32(1, v); } + $core.bool hasNanos() => $_has(1); + void clearNanos() => clearField(2); + /// Converts an instance to [DateTime]. + /// + /// The result is in UTC time zone and has microsecond precision, as + /// [DateTime] does not support nanosecond precision. + $core.DateTime toDateTime() => $core.DateTime.fromMicrosecondsSinceEpoch( + seconds.toInt() * $core.Duration.microsecondsPerSecond + nanos ~/ 1000, + isUtc: true); + + /// Creates a new instance from [dateTime]. + /// + /// Time zone information will not be preserved. + static Timestamp fromDateTime($core.DateTime dateTime) { + $core.int micros = dateTime.microsecondsSinceEpoch; + return Timestamp() + ..seconds = Int64(micros ~/ $core.Duration.microsecondsPerSecond) + ..nanos = (micros % $core.Duration.microsecondsPerSecond).toInt() * 1000; + } +} + diff --git a/lib/protobuf/google/protobuf/timestamp.pbenum.dart b/lib/protobuf/google/protobuf/timestamp.pbenum.dart new file mode 100644 index 0000000..fd4e632 --- /dev/null +++ b/lib/protobuf/google/protobuf/timestamp.pbenum.dart @@ -0,0 +1,6 @@ +/// +// Generated code. Do not modify. +// source: timestamp.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + diff --git a/lib/protobuf/google/protobuf/timestamp.pbjson.dart b/lib/protobuf/google/protobuf/timestamp.pbjson.dart new file mode 100644 index 0000000..d7afdfb --- /dev/null +++ b/lib/protobuf/google/protobuf/timestamp.pbjson.dart @@ -0,0 +1,14 @@ +/// +// Generated code. Do not modify. +// source: timestamp.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + +const Timestamp$json = const { + '1': 'Timestamp', + '2': const [ + const {'1': 'seconds', '3': 1, '4': 1, '5': 3, '10': 'seconds'}, + const {'1': 'nanos', '3': 2, '4': 1, '5': 5, '10': 'nanos'}, + ], +}; + diff --git a/lib/protobuf/service.pb.dart b/lib/protobuf/service.pb.dart new file mode 100644 index 0000000..6fcd5a1 --- /dev/null +++ b/lib/protobuf/service.pb.dart @@ -0,0 +1,384 @@ +/// +// Generated code. Do not modify. +// source: service.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + +import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'google/protobuf/timestamp.pb.dart' as $1; + +class DeleteResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('DeleteResponse', package: const $pb.PackageName('selfpass.credentials')) + ..aOB(1, 'success') + ..hasRequiredFields = false + ; + + DeleteResponse._() : super(); + factory DeleteResponse() => create(); + factory DeleteResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DeleteResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + DeleteResponse clone() => DeleteResponse()..mergeFromMessage(this); + DeleteResponse copyWith(void Function(DeleteResponse) updates) => super.copyWith((message) => updates(message as DeleteResponse)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static DeleteResponse create() => DeleteResponse._(); + DeleteResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static DeleteResponse getDefault() => _defaultInstance ??= create()..freeze(); + static DeleteResponse _defaultInstance; + + $core.bool get success => $_get(0, false); + set success($core.bool v) { $_setBool(0, v); } + $core.bool hasSuccess() => $_has(0); + void clearSuccess() => clearField(1); +} + +class GetAllMetadataRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('GetAllMetadataRequest', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'sourceHost') + ..hasRequiredFields = false + ; + + GetAllMetadataRequest._() : super(); + factory GetAllMetadataRequest() => create(); + factory GetAllMetadataRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory GetAllMetadataRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + GetAllMetadataRequest clone() => GetAllMetadataRequest()..mergeFromMessage(this); + GetAllMetadataRequest copyWith(void Function(GetAllMetadataRequest) updates) => super.copyWith((message) => updates(message as GetAllMetadataRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static GetAllMetadataRequest create() => GetAllMetadataRequest._(); + GetAllMetadataRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static GetAllMetadataRequest getDefault() => _defaultInstance ??= create()..freeze(); + static GetAllMetadataRequest _defaultInstance; + + $core.String get sourceHost => $_getS(0, ''); + set sourceHost($core.String v) { $_setString(0, v); } + $core.bool hasSourceHost() => $_has(0); + void clearSourceHost() => clearField(1); +} + +class IdRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('IdRequest', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'id') + ..hasRequiredFields = false + ; + + IdRequest._() : super(); + factory IdRequest() => create(); + factory IdRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory IdRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + IdRequest clone() => IdRequest()..mergeFromMessage(this); + IdRequest copyWith(void Function(IdRequest) updates) => super.copyWith((message) => updates(message as IdRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static IdRequest create() => IdRequest._(); + IdRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static IdRequest getDefault() => _defaultInstance ??= create()..freeze(); + static IdRequest _defaultInstance; + + $core.String get id => $_getS(0, ''); + set id($core.String v) { $_setString(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); +} + +class UpdateRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('UpdateRequest', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'id') + ..a(2, 'credential', $pb.PbFieldType.OM, CredentialRequest.getDefault, CredentialRequest.create) + ..hasRequiredFields = false + ; + + UpdateRequest._() : super(); + factory UpdateRequest() => create(); + factory UpdateRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UpdateRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + UpdateRequest clone() => UpdateRequest()..mergeFromMessage(this); + UpdateRequest copyWith(void Function(UpdateRequest) updates) => super.copyWith((message) => updates(message as UpdateRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static UpdateRequest create() => UpdateRequest._(); + UpdateRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static UpdateRequest getDefault() => _defaultInstance ??= create()..freeze(); + static UpdateRequest _defaultInstance; + + $core.String get id => $_getS(0, ''); + set id($core.String v) { $_setString(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); + + CredentialRequest get credential => $_getN(1); + set credential(CredentialRequest v) { setField(2, v); } + $core.bool hasCredential() => $_has(1); + void clearCredential() => clearField(2); +} + +class DumpResponse extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('DumpResponse', package: const $pb.PackageName('selfpass.credentials')) + ..a<$core.List<$core.int>>(1, 'contents', $pb.PbFieldType.OY) + ..hasRequiredFields = false + ; + + DumpResponse._() : super(); + factory DumpResponse() => create(); + factory DumpResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DumpResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + DumpResponse clone() => DumpResponse()..mergeFromMessage(this); + DumpResponse copyWith(void Function(DumpResponse) updates) => super.copyWith((message) => updates(message as DumpResponse)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static DumpResponse create() => DumpResponse._(); + DumpResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static DumpResponse getDefault() => _defaultInstance ??= create()..freeze(); + static DumpResponse _defaultInstance; + + $core.List<$core.int> get contents => $_getN(0); + set contents($core.List<$core.int> v) { $_setBytes(0, v); } + $core.bool hasContents() => $_has(0); + void clearContents() => clearField(1); +} + +class EmptyRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('EmptyRequest', package: const $pb.PackageName('selfpass.credentials')) + ..hasRequiredFields = false + ; + + EmptyRequest._() : super(); + factory EmptyRequest() => create(); + factory EmptyRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory EmptyRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + EmptyRequest clone() => EmptyRequest()..mergeFromMessage(this); + EmptyRequest copyWith(void Function(EmptyRequest) updates) => super.copyWith((message) => updates(message as EmptyRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static EmptyRequest create() => EmptyRequest._(); + EmptyRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static EmptyRequest getDefault() => _defaultInstance ??= create()..freeze(); + static EmptyRequest _defaultInstance; +} + +class Metadata extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('Metadata', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'id') + ..a<$1.Timestamp>(2, 'createdAt', $pb.PbFieldType.OM, $1.Timestamp.getDefault, $1.Timestamp.create) + ..a<$1.Timestamp>(3, 'updatedAt', $pb.PbFieldType.OM, $1.Timestamp.getDefault, $1.Timestamp.create) + ..aOS(4, 'primary') + ..aOS(5, 'sourceHost') + ..aOS(6, 'loginUrl') + ..aOS(7, 'tag') + ..hasRequiredFields = false + ; + + Metadata._() : super(); + factory Metadata() => create(); + factory Metadata.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Metadata.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + Metadata clone() => Metadata()..mergeFromMessage(this); + Metadata copyWith(void Function(Metadata) updates) => super.copyWith((message) => updates(message as Metadata)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static Metadata create() => Metadata._(); + Metadata createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static Metadata getDefault() => _defaultInstance ??= create()..freeze(); + static Metadata _defaultInstance; + + $core.String get id => $_getS(0, ''); + set id($core.String v) { $_setString(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); + + $1.Timestamp get createdAt => $_getN(1); + set createdAt($1.Timestamp v) { setField(2, v); } + $core.bool hasCreatedAt() => $_has(1); + void clearCreatedAt() => clearField(2); + + $1.Timestamp get updatedAt => $_getN(2); + set updatedAt($1.Timestamp v) { setField(3, v); } + $core.bool hasUpdatedAt() => $_has(2); + void clearUpdatedAt() => clearField(3); + + $core.String get primary => $_getS(3, ''); + set primary($core.String v) { $_setString(3, v); } + $core.bool hasPrimary() => $_has(3); + void clearPrimary() => clearField(4); + + $core.String get sourceHost => $_getS(4, ''); + set sourceHost($core.String v) { $_setString(4, v); } + $core.bool hasSourceHost() => $_has(4); + void clearSourceHost() => clearField(5); + + $core.String get loginUrl => $_getS(5, ''); + set loginUrl($core.String v) { $_setString(5, v); } + $core.bool hasLoginUrl() => $_has(5); + void clearLoginUrl() => clearField(6); + + $core.String get tag => $_getS(6, ''); + set tag($core.String v) { $_setString(6, v); } + $core.bool hasTag() => $_has(6); + void clearTag() => clearField(7); +} + +class Credential extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('Credential', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'id') + ..a<$1.Timestamp>(2, 'createdAt', $pb.PbFieldType.OM, $1.Timestamp.getDefault, $1.Timestamp.create) + ..a<$1.Timestamp>(3, 'updatedAt', $pb.PbFieldType.OM, $1.Timestamp.getDefault, $1.Timestamp.create) + ..aOS(4, 'primary') + ..aOS(5, 'username') + ..aOS(6, 'email') + ..aOS(7, 'password') + ..aOS(8, 'sourceHost') + ..aOS(9, 'loginUrl') + ..aOS(10, 'tag') + ..aOS(11, 'otpSecret') + ..hasRequiredFields = false + ; + + Credential._() : super(); + factory Credential() => create(); + factory Credential.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory Credential.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + Credential clone() => Credential()..mergeFromMessage(this); + Credential copyWith(void Function(Credential) updates) => super.copyWith((message) => updates(message as Credential)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static Credential create() => Credential._(); + Credential createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static Credential getDefault() => _defaultInstance ??= create()..freeze(); + static Credential _defaultInstance; + + $core.String get id => $_getS(0, ''); + set id($core.String v) { $_setString(0, v); } + $core.bool hasId() => $_has(0); + void clearId() => clearField(1); + + $1.Timestamp get createdAt => $_getN(1); + set createdAt($1.Timestamp v) { setField(2, v); } + $core.bool hasCreatedAt() => $_has(1); + void clearCreatedAt() => clearField(2); + + $1.Timestamp get updatedAt => $_getN(2); + set updatedAt($1.Timestamp v) { setField(3, v); } + $core.bool hasUpdatedAt() => $_has(2); + void clearUpdatedAt() => clearField(3); + + $core.String get primary => $_getS(3, ''); + set primary($core.String v) { $_setString(3, v); } + $core.bool hasPrimary() => $_has(3); + void clearPrimary() => clearField(4); + + $core.String get username => $_getS(4, ''); + set username($core.String v) { $_setString(4, v); } + $core.bool hasUsername() => $_has(4); + void clearUsername() => clearField(5); + + $core.String get email => $_getS(5, ''); + set email($core.String v) { $_setString(5, v); } + $core.bool hasEmail() => $_has(5); + void clearEmail() => clearField(6); + + $core.String get password => $_getS(6, ''); + set password($core.String v) { $_setString(6, v); } + $core.bool hasPassword() => $_has(6); + void clearPassword() => clearField(7); + + $core.String get sourceHost => $_getS(7, ''); + set sourceHost($core.String v) { $_setString(7, v); } + $core.bool hasSourceHost() => $_has(7); + void clearSourceHost() => clearField(8); + + $core.String get loginUrl => $_getS(8, ''); + set loginUrl($core.String v) { $_setString(8, v); } + $core.bool hasLoginUrl() => $_has(8); + void clearLoginUrl() => clearField(9); + + $core.String get tag => $_getS(9, ''); + set tag($core.String v) { $_setString(9, v); } + $core.bool hasTag() => $_has(9); + void clearTag() => clearField(10); + + $core.String get otpSecret => $_getS(10, ''); + set otpSecret($core.String v) { $_setString(10, v); } + $core.bool hasOtpSecret() => $_has(10); + void clearOtpSecret() => clearField(11); +} + +class CredentialRequest extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo('CredentialRequest', package: const $pb.PackageName('selfpass.credentials')) + ..aOS(1, 'primary') + ..aOS(2, 'username') + ..aOS(3, 'email') + ..aOS(4, 'password') + ..aOS(5, 'sourceHost') + ..aOS(6, 'loginUrl') + ..aOS(7, 'tag') + ..aOS(8, 'otpSecret') + ..hasRequiredFields = false + ; + + CredentialRequest._() : super(); + factory CredentialRequest() => create(); + factory CredentialRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory CredentialRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + CredentialRequest clone() => CredentialRequest()..mergeFromMessage(this); + CredentialRequest copyWith(void Function(CredentialRequest) updates) => super.copyWith((message) => updates(message as CredentialRequest)); + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static CredentialRequest create() => CredentialRequest._(); + CredentialRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + static CredentialRequest getDefault() => _defaultInstance ??= create()..freeze(); + static CredentialRequest _defaultInstance; + + $core.String get primary => $_getS(0, ''); + set primary($core.String v) { $_setString(0, v); } + $core.bool hasPrimary() => $_has(0); + void clearPrimary() => clearField(1); + + $core.String get username => $_getS(1, ''); + set username($core.String v) { $_setString(1, v); } + $core.bool hasUsername() => $_has(1); + void clearUsername() => clearField(2); + + $core.String get email => $_getS(2, ''); + set email($core.String v) { $_setString(2, v); } + $core.bool hasEmail() => $_has(2); + void clearEmail() => clearField(3); + + $core.String get password => $_getS(3, ''); + set password($core.String v) { $_setString(3, v); } + $core.bool hasPassword() => $_has(3); + void clearPassword() => clearField(4); + + $core.String get sourceHost => $_getS(4, ''); + set sourceHost($core.String v) { $_setString(4, v); } + $core.bool hasSourceHost() => $_has(4); + void clearSourceHost() => clearField(5); + + $core.String get loginUrl => $_getS(5, ''); + set loginUrl($core.String v) { $_setString(5, v); } + $core.bool hasLoginUrl() => $_has(5); + void clearLoginUrl() => clearField(6); + + $core.String get tag => $_getS(6, ''); + set tag($core.String v) { $_setString(6, v); } + $core.bool hasTag() => $_has(6); + void clearTag() => clearField(7); + + $core.String get otpSecret => $_getS(7, ''); + set otpSecret($core.String v) { $_setString(7, v); } + $core.bool hasOtpSecret() => $_has(7); + void clearOtpSecret() => clearField(8); +} + diff --git a/lib/protobuf/service.pbenum.dart b/lib/protobuf/service.pbenum.dart new file mode 100644 index 0000000..cf0e02d --- /dev/null +++ b/lib/protobuf/service.pbenum.dart @@ -0,0 +1,6 @@ +/// +// Generated code. Do not modify. +// source: service.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + diff --git a/lib/protobuf/service.pbgrpc.dart b/lib/protobuf/service.pbgrpc.dart new file mode 100644 index 0000000..40a8c1f --- /dev/null +++ b/lib/protobuf/service.pbgrpc.dart @@ -0,0 +1,158 @@ +/// +// Generated code. Do not modify. +// source: service.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + +import 'dart:async' as $async; + +import 'dart:core' as $core show int, String, List; + +import 'package:grpc/service_api.dart' as $grpc; +import 'service.pb.dart' as $0; +export 'service.pb.dart'; + +class CredentialServiceClient extends $grpc.Client { + static final _$getAllMetadata = + $grpc.ClientMethod<$0.GetAllMetadataRequest, $0.Metadata>( + '/selfpass.credentials.CredentialService/GetAllMetadata', + ($0.GetAllMetadataRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.Metadata.fromBuffer(value)); + static final _$get = $grpc.ClientMethod<$0.IdRequest, $0.Credential>( + '/selfpass.credentials.CredentialService/Get', + ($0.IdRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.Credential.fromBuffer(value)); + static final _$create = + $grpc.ClientMethod<$0.CredentialRequest, $0.Credential>( + '/selfpass.credentials.CredentialService/Create', + ($0.CredentialRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.Credential.fromBuffer(value)); + static final _$update = $grpc.ClientMethod<$0.UpdateRequest, $0.Credential>( + '/selfpass.credentials.CredentialService/Update', + ($0.UpdateRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.Credential.fromBuffer(value)); + static final _$delete = $grpc.ClientMethod<$0.IdRequest, $0.DeleteResponse>( + '/selfpass.credentials.CredentialService/Delete', + ($0.IdRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.DeleteResponse.fromBuffer(value)); + + CredentialServiceClient($grpc.ClientChannel channel, + {$grpc.CallOptions options}) + : super(channel, options: options); + + $grpc.ResponseStream<$0.Metadata> getAllMetadata( + $0.GetAllMetadataRequest request, + {$grpc.CallOptions options}) { + final call = $createCall( + _$getAllMetadata, $async.Stream.fromIterable([request]), + options: options); + return $grpc.ResponseStream(call); + } + + $grpc.ResponseFuture<$0.Credential> get($0.IdRequest request, + {$grpc.CallOptions options}) { + final call = $createCall(_$get, $async.Stream.fromIterable([request]), + options: options); + return $grpc.ResponseFuture(call); + } + + $grpc.ResponseFuture<$0.Credential> create($0.CredentialRequest request, + {$grpc.CallOptions options}) { + final call = $createCall(_$create, $async.Stream.fromIterable([request]), + options: options); + return $grpc.ResponseFuture(call); + } + + $grpc.ResponseFuture<$0.Credential> update($0.UpdateRequest request, + {$grpc.CallOptions options}) { + final call = $createCall(_$update, $async.Stream.fromIterable([request]), + options: options); + return $grpc.ResponseFuture(call); + } + + $grpc.ResponseFuture<$0.DeleteResponse> delete($0.IdRequest request, + {$grpc.CallOptions options}) { + final call = $createCall(_$delete, $async.Stream.fromIterable([request]), + options: options); + return $grpc.ResponseFuture(call); + } +} + +abstract class CredentialServiceBase extends $grpc.Service { + $core.String get $name => 'selfpass.credentials.CredentialService'; + + CredentialServiceBase() { + $addMethod($grpc.ServiceMethod<$0.GetAllMetadataRequest, $0.Metadata>( + 'GetAllMetadata', + getAllMetadata_Pre, + false, + true, + ($core.List<$core.int> value) => + $0.GetAllMetadataRequest.fromBuffer(value), + ($0.Metadata value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.IdRequest, $0.Credential>( + 'Get', + get_Pre, + false, + false, + ($core.List<$core.int> value) => $0.IdRequest.fromBuffer(value), + ($0.Credential value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.CredentialRequest, $0.Credential>( + 'Create', + create_Pre, + false, + false, + ($core.List<$core.int> value) => $0.CredentialRequest.fromBuffer(value), + ($0.Credential value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.UpdateRequest, $0.Credential>( + 'Update', + update_Pre, + false, + false, + ($core.List<$core.int> value) => $0.UpdateRequest.fromBuffer(value), + ($0.Credential value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.IdRequest, $0.DeleteResponse>( + 'Delete', + delete_Pre, + false, + false, + ($core.List<$core.int> value) => $0.IdRequest.fromBuffer(value), + ($0.DeleteResponse value) => value.writeToBuffer())); + } + + $async.Stream<$0.Metadata> getAllMetadata_Pre( + $grpc.ServiceCall call, $async.Future request) async* { + yield* getAllMetadata(call, (await request) as $0.GetAllMetadataRequest); + } + + $async.Future<$0.Credential> get_Pre( + $grpc.ServiceCall call, $async.Future request) async { + return get(call, await request); + } + + $async.Future<$0.Credential> create_Pre( + $grpc.ServiceCall call, $async.Future request) async { + return create(call, await request); + } + + $async.Future<$0.Credential> update_Pre( + $grpc.ServiceCall call, $async.Future request) async { + return update(call, await request); + } + + $async.Future<$0.DeleteResponse> delete_Pre( + $grpc.ServiceCall call, $async.Future request) async { + return delete(call, await request); + } + + $async.Stream<$0.Metadata> getAllMetadata( + $grpc.ServiceCall call, $0.GetAllMetadataRequest request); + $async.Future<$0.Credential> get( + $grpc.ServiceCall call, $0.IdRequest request); + $async.Future<$0.Credential> create( + $grpc.ServiceCall call, $0.CredentialRequest request); + $async.Future<$0.Credential> update( + $grpc.ServiceCall call, $0.UpdateRequest request); + $async.Future<$0.DeleteResponse> delete( + $grpc.ServiceCall call, $0.IdRequest request); +} diff --git a/lib/protobuf/service.pbjson.dart b/lib/protobuf/service.pbjson.dart new file mode 100644 index 0000000..d97e434 --- /dev/null +++ b/lib/protobuf/service.pbjson.dart @@ -0,0 +1,90 @@ +/// +// Generated code. Do not modify. +// source: service.proto +/// +// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name + +const DeleteResponse$json = const { + '1': 'DeleteResponse', + '2': const [ + const {'1': 'success', '3': 1, '4': 1, '5': 8, '10': 'success'}, + ], +}; + +const GetAllMetadataRequest$json = const { + '1': 'GetAllMetadataRequest', + '2': const [ + const {'1': 'source_host', '3': 1, '4': 1, '5': 9, '10': 'sourceHost'}, + ], +}; + +const IdRequest$json = const { + '1': 'IdRequest', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + ], +}; + +const UpdateRequest$json = const { + '1': 'UpdateRequest', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'credential', '3': 2, '4': 1, '5': 11, '6': '.selfpass.credentials.CredentialRequest', '10': 'credential'}, + ], +}; + +const DumpResponse$json = const { + '1': 'DumpResponse', + '2': const [ + const {'1': 'contents', '3': 1, '4': 1, '5': 12, '10': 'contents'}, + ], +}; + +const EmptyRequest$json = const { + '1': 'EmptyRequest', +}; + +const Metadata$json = const { + '1': 'Metadata', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'created_at', '3': 2, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'createdAt'}, + const {'1': 'updated_at', '3': 3, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'updatedAt'}, + const {'1': 'primary', '3': 4, '4': 1, '5': 9, '10': 'primary'}, + const {'1': 'source_host', '3': 5, '4': 1, '5': 9, '10': 'sourceHost'}, + const {'1': 'login_url', '3': 6, '4': 1, '5': 9, '10': 'loginUrl'}, + const {'1': 'tag', '3': 7, '4': 1, '5': 9, '10': 'tag'}, + ], +}; + +const Credential$json = const { + '1': 'Credential', + '2': const [ + const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + const {'1': 'created_at', '3': 2, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'createdAt'}, + const {'1': 'updated_at', '3': 3, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'updatedAt'}, + const {'1': 'primary', '3': 4, '4': 1, '5': 9, '10': 'primary'}, + const {'1': 'username', '3': 5, '4': 1, '5': 9, '10': 'username'}, + const {'1': 'email', '3': 6, '4': 1, '5': 9, '10': 'email'}, + const {'1': 'password', '3': 7, '4': 1, '5': 9, '10': 'password'}, + const {'1': 'source_host', '3': 8, '4': 1, '5': 9, '10': 'sourceHost'}, + const {'1': 'login_url', '3': 9, '4': 1, '5': 9, '10': 'loginUrl'}, + const {'1': 'tag', '3': 10, '4': 1, '5': 9, '10': 'tag'}, + const {'1': 'otp_secret', '3': 11, '4': 1, '5': 9, '10': 'otpSecret'}, + ], +}; + +const CredentialRequest$json = const { + '1': 'CredentialRequest', + '2': const [ + const {'1': 'primary', '3': 1, '4': 1, '5': 9, '10': 'primary'}, + const {'1': 'username', '3': 2, '4': 1, '5': 9, '10': 'username'}, + const {'1': 'email', '3': 3, '4': 1, '5': 9, '10': 'email'}, + const {'1': 'password', '3': 4, '4': 1, '5': 9, '10': 'password'}, + const {'1': 'source_host', '3': 5, '4': 1, '5': 9, '10': 'sourceHost'}, + const {'1': 'login_url', '3': 6, '4': 1, '5': 9, '10': 'loginUrl'}, + const {'1': 'tag', '3': 7, '4': 1, '5': 9, '10': 'tag'}, + const {'1': 'otp_secret', '3': 8, '4': 1, '5': 9, '10': 'otpSecret'}, + ], +}; + diff --git a/lib/protobuf/service.proto b/lib/protobuf/service.proto new file mode 100644 index 0000000..c9dfa49 --- /dev/null +++ b/lib/protobuf/service.proto @@ -0,0 +1,75 @@ +syntax = "proto3"; + +package selfpass.credentials; + +option go_package = "protobuf"; + +import "google/protobuf/timestamp.proto"; + +service CredentialService { + rpc GetAllMetadata (GetAllMetadataRequest) returns (stream Metadata); + rpc Get (IdRequest) returns (Credential); + rpc Create (CredentialRequest) returns (Credential); + rpc Update (UpdateRequest) returns (Credential); + rpc Delete (IdRequest) returns (DeleteResponse); + // rpc Dump (EmptyRequest) returns (DumpResponse); +} + +message DeleteResponse { + bool success = 1; +} + +message GetAllMetadataRequest { + string source_host = 1; +} + +message IdRequest { + string id = 1; +} + +message UpdateRequest { + string id = 1; + CredentialRequest credential = 2; +} + +message DumpResponse { + bytes contents = 1; +} + +message EmptyRequest { +} + +message Metadata { + string id = 1; + google.protobuf.Timestamp created_at = 2; + google.protobuf.Timestamp updated_at = 3; + string primary = 4; + string source_host = 5; + string login_url = 6; + string tag = 7; +} + +message Credential { + string id = 1; + google.protobuf.Timestamp created_at = 2; + google.protobuf.Timestamp updated_at = 3; + string primary = 4; + string username = 5; + string email = 6; + string password = 7; + string source_host = 8; + string login_url = 9; + string tag = 10; + string otp_secret = 11; +} + +message CredentialRequest { + string primary = 1; + string username = 2; + string email = 3; + string password = 4; + string source_host = 5; + string login_url = 6; + string tag = 7; + string otp_secret = 8; +} diff --git a/lib/repositories/config.dart b/lib/repositories/config.dart new file mode 100644 index 0000000..aab0b72 --- /dev/null +++ b/lib/repositories/config.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +import '../types/abstracts.dart'; +import '../types/connection_config.dart'; + +import '../utils/crypto.dart' as crypto; + +class Config implements ConfigRepo { + static const _keyPrivateKey = "private_key"; + static const _keyConnectionConfig = "connection_config"; + static const _keyPassword = "password"; + final FlutterSecureStorage _storage = FlutterSecureStorage(); + var _passwordMatched = false; + + Future setPrivateKey(String key) { + _checkIfPasswordMatched(); + return _storage.write(key: _keyPrivateKey, value: key); + } + + Future get privateKey { + _checkIfPasswordMatched(); + return _storage.read(key: _keyPrivateKey); + } + + Future setPassword(String password) { + _checkIfPasswordMatched(); + return _storage.write( + key: _keyPassword, value: crypto.hashPassword(password)); + } + + Future get passwordSet async { + var passHash = await _storage.read(key: _keyPassword); + + if (passHash != null) { + return true; + } + + _passwordMatched = true; + + return false; + } + + Future matchesPasswordHash(String password) async => + _passwordMatched = crypto.matchHashedPassword( + await _storage.read(key: _keyPassword), password); + + Future setConnectionConfig(ConnectionConfig config) { + _checkIfPasswordMatched(); + return _storage.write( + key: _keyConnectionConfig, value: json.encode(config)); + } + + Future get connectionConfig async { + _checkIfPasswordMatched(); + return ConnectionConfig.fromJson( + json.decode(await _storage.read(key: _keyConnectionConfig))); + } + + void _checkIfPasswordMatched() { + if (_passwordMatched) return; + throw Exception('password not matched yet'); + } +} diff --git a/lib/repositories/credentials_client.dart b/lib/repositories/credentials_client.dart new file mode 100644 index 0000000..b84a757 --- /dev/null +++ b/lib/repositories/credentials_client.dart @@ -0,0 +1,79 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:grpc/grpc.dart'; + +import '../protobuf/service.pbgrpc.dart' as grpc; +import '../protobuf/service.pb.dart' as protobuf; + +import '../types/abstracts.dart'; +import '../types/connection_config.dart'; +import '../types/credential.dart'; + +class CredentialsClient implements CredentialsRepo { + grpc.CredentialServiceClient _client; + + CredentialsClient(ConnectionConfig config) { + final caCert = utf8.encode(config.caCertificate); + final cert = utf8.encode(config.certificate); + final privateCert = utf8.encode(config.privateCertificate); + + final splitHost = config.host.split(':'); + final hostname = splitHost[0]; + final port = int.parse(splitHost[1]); + + _client = grpc.CredentialServiceClient(ClientChannel( + hostname, + port: port, + options: ChannelOptions( + credentials: _ChannelCredentials(caCert, cert, privateCert), + ), + )); + } + + Stream getAllMetadata(String sourceHost) { + final request = grpc.GetAllMetadataRequest(); + request.sourceHost = sourceHost; + + return _client.getAllMetadata(request).map( + (protobuf.Metadata pbMetadata) => Metadata.fromProtobuf(pbMetadata)); + } + + Future get(String id) async { + final request = grpc.IdRequest(); + request.id = id; + + return Credential.fromProtobuf(await _client.get(request)); + } + + Future create(CredentialInput input) async { + return Credential(); + } + + Future update(String id, CredentialInput input) async { + return Credential(); + } + + Future delete(String id) { + final request = grpc.IdRequest(); + request.id = id; + + return _client.delete(request); + } +} + +class _ChannelCredentials extends ChannelCredentials { + final List _key; + final List _cert; + + const _ChannelCredentials(List caCert, this._cert, this._key) + : super.secure(certificates: caCert); + + @override + SecurityContext get securityContext { + return super.securityContext + ..usePrivateKeyBytes(_key) + ..useCertificateChainBytes(_cert); + } +} diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart index 4f924d0..eb85109 100644 --- a/lib/screens/authentication.dart +++ b/lib/screens/authentication.dart @@ -1,4 +1,9 @@ import 'package:flutter/cupertino.dart'; +import 'package:provider/provider.dart'; + +import '../types/abstracts.dart'; + +import '../widgets/obfuscated_text_field.dart'; class Authentication extends StatefulWidget { @override @@ -6,42 +11,58 @@ class Authentication extends StatefulWidget { } class _AuthenticationState extends State { - static const String _masterpass = 'hunter#2'; bool _invalid = false; + bool _passesDontMatch = false; + String _masterpass; + ConfigRepo _config; + Future _passwordIsSet; + + @override + didChangeDependencies() { + super.didChangeDependencies(); + _config = Provider.of(context); + } @override Widget build(BuildContext context) { + if (_passwordIsSet == null) { + _passwordIsSet = _config.passwordSet; + } + return CupertinoPageScaffold( child: Container( margin: const EdgeInsets.symmetric(horizontal: 50.0), - child: Column( - children: _buildColumnChildren(context), + child: FutureBuilder( + future: _passwordIsSet, + builder: (BuildContext context, AsyncSnapshot snapshot) => + snapshot.connectionState == ConnectionState.done + ? Column(children: _buildColumnChildren(snapshot.data)) + : Container(), ), ), ); } - List _buildColumnChildren(BuildContext context) { - final children = [ + List _buildColumnChildren(bool passwordIsSet) { + List children = [ const Spacer(flex: 4), const Flexible(child: Text('Master password:')), Flexible( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: CupertinoTextField( - decoration: BoxDecoration( - border: Border.all(color: CupertinoColors.black), - borderRadius: const BorderRadius.all(Radius.circular(5.0)), - ), - clearButtonMode: OverlayVisibilityMode.editing, - textAlign: TextAlign.center, - onSubmitted: _makeTextFieldOnSubmittedHandler(context), - obscureText: true, - ), - ), + child: ObfuscatedTextField( + onSubmittedBuilder: + _buildMasterpassSubmittedBuilder(passwordIsSet)), ), ]; + if (!passwordIsSet) { + children.add(const Flexible(child: Text('Re-enter password:'))); + children.add(Flexible( + child: ObfuscatedTextField( + onSubmittedBuilder: + _buildConfirmPassSubmittedBuilder(passwordIsSet)), + )); + } + if (_invalid) { children.add(const Flexible( child: Text( @@ -49,6 +70,20 @@ class _AuthenticationState extends State { style: TextStyle(color: CupertinoColors.destructiveRed), ), )); + } + + if (_passesDontMatch) { + children.add(const Flexible( + child: Text( + 'passwords don\'t match', + style: TextStyle(color: CupertinoColors.destructiveRed), + ), + )); + } + + if (_passesDontMatch) { + children.add(const Spacer(flex: 1)); + } else if (_invalid || !passwordIsSet) { children.add(const Spacer(flex: 2)); } else { children.add(const Spacer(flex: 3)); @@ -57,16 +92,40 @@ class _AuthenticationState extends State { return children; } - ValueChanged _makeTextFieldOnSubmittedHandler(BuildContext context) { - return (String pass) { - if (pass != _masterpass) { - this.setState(() { - _invalid = true; - }); - return; - } + OnSubmittedBuilder _buildMasterpassSubmittedBuilder(bool passwordIsSet) { + return (BuildContext context) { + return (String pass) async { + if (passwordIsSet) { + if (await _config.matchesPasswordHash(pass)) { + Navigator.of(context).pushReplacementNamed('/home', + arguments: await _config.connectionConfig); + return; + } - Navigator.of(context).pushReplacementNamed('/home'); + this.setState(() => _invalid = true); + return; + } + + _masterpass = pass; + }; + }; + } + + OnSubmittedBuilder _buildConfirmPassSubmittedBuilder(bool passwordIsSet) { + return (BuildContext context) { + return (String pass) async { + if (pass != _masterpass) { + this.setState(() { + _passesDontMatch = true; + }); + return; + } + + _config.setPassword(_masterpass); + _passwordIsSet = Future.value(true); + Navigator.of(context).pushReplacementNamed('/home', + arguments: await _config.connectionConfig); + }; }; } } diff --git a/lib/screens/credentials.dart b/lib/screens/credentials.dart index cf8b109..1a6efa7 100644 --- a/lib/screens/credentials.dart +++ b/lib/screens/credentials.dart @@ -1,25 +1,29 @@ import 'package:flutter/cupertino.dart'; +import '../types/credential.dart'; + import '../widgets/tappable_text_list.dart'; class Credentials extends StatelessWidget { + final List metadatas; + + const Credentials(this.metadatas); + @override Widget build(BuildContext context) { return CupertinoPageScaffold( child: TappableTextList(tappableText: _buildTappableText(context)), - navigationBar: const CupertinoNavigationBar(middle: Text('Credentials')), + navigationBar: CupertinoNavigationBar(), ); } - static Map _buildTappableText( - BuildContext context) { + Map _buildTappableText(BuildContext context) { var handleOnTap = () {}; - Map tappableText = { - 'm@mjfs.us': handleOnTap, - 'm-mjfs': handleOnTap, - 'mitchelljfsimon@gmail.com-mitchelljfsimon': handleOnTap, - }; + Map tappableText = {}; + + metadatas.forEach( + (Metadata metadata) => tappableText[metadata.id] = handleOnTap); return tappableText; } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 53030d0..f7e6643 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,28 +1,71 @@ import 'package:flutter/cupertino.dart'; -// import 'package:provider/provider.dart'; +import 'package:provider/provider.dart'; + +import '../types/abstracts.dart'; +import '../types/credential.dart'; -// import '../types/abstracts.dart'; -// import '../types/credential.dart'; import '../widgets/tappable_text_list.dart'; -class Home extends StatelessWidget { +class Home extends StatefulWidget { + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + CredentialsRepo _client; + Future> _metadatas; + + @override + didChangeDependencies() { + super.didChangeDependencies(); + _client = Provider.of(context); + } + @override Widget build(BuildContext context) { + if (_metadatas == null) { + _metadatas = _client.getAllMetadata('').toList(); + } + return CupertinoPageScaffold( - child: TappableTextList(tappableText: _buildTappableText(context)), - navigationBar: - const CupertinoNavigationBar(middle: Text('Credentials Hosts')), + child: FutureBuilder>( + future: _metadatas, + builder: (BuildContext context, + AsyncSnapshot> snapshot) => + (snapshot.connectionState == ConnectionState.done) + ? TappableTextList( + tappableText: _buildTappableText(context, snapshot.data)) + : Container(), + ), + navigationBar: CupertinoNavigationBar(), ); } - static Map _buildTappableText( - BuildContext context) { - var handleOnTap = () => Navigator.of(context).pushNamed('/credentials'); - Map tappableText = { - "google.com": handleOnTap, - "amazon.com": handleOnTap, - "linkedin.com": handleOnTap, - }; + Map _buildTappableText( + BuildContext context, + List metadatas, + ) { + final Map> metaMap = {}; + + metadatas.sort((a, b) => a.id.compareTo(b.id)); + + for (var metadata in metadatas) { + final source = metadata.sourceHost; + + if (metaMap[source] == null) { + metaMap[source] = [metadata]; + } else { + metaMap[source].add(metadata); + } + } + + final handleOnTap = (List metadatas) => () => + Navigator.of(context).pushNamed('/credentials', arguments: metadatas); + + final Map tappableText = {}; + + metaMap.forEach((String key, List value) => + tappableText[key] = handleOnTap(value)); return tappableText; } diff --git a/lib/types/abstracts.dart b/lib/types/abstracts.dart new file mode 100644 index 0000000..5ac1041 --- /dev/null +++ b/lib/types/abstracts.dart @@ -0,0 +1,24 @@ +import 'dart:async'; + +import 'credential.dart'; +import 'connection_config.dart'; + +abstract class CredentialsRepo { + Stream getAllMetadata(String sourceHost); + Future get(String id); + Future create(CredentialInput input); + Future update(String id, CredentialInput input); + Future delete(String id); +} + +abstract class ConfigRepo { + Future setPrivateKey(String key); + Future get privateKey; + + Future setPassword(String password); + Future get passwordSet; + Future matchesPasswordHash(String password); + + Future setConnectionConfig(ConnectionConfig config); + Future get connectionConfig; +} diff --git a/lib/types/connection_config.dart b/lib/types/connection_config.dart new file mode 100644 index 0000000..a9e6689 --- /dev/null +++ b/lib/types/connection_config.dart @@ -0,0 +1,27 @@ +class ConnectionConfig { + String host; + String caCertificate; + String certificate; + String privateCertificate; + + ConnectionConfig({ + this.host, + this.caCertificate, + this.certificate, + this.privateCertificate, + }); + + ConnectionConfig.fromJson(Map json) { + host = json['host']; + caCertificate = json['caCertificate']; + certificate = json['certificate']; + privateCertificate = json['privateCertificate']; + } + + Map toJson() => { + 'host': host, + 'caCertificate': caCertificate, + 'certificate': certificate, + 'privateCertificate': privateCertificate, + }; +} diff --git a/lib/types/credential.dart b/lib/types/credential.dart new file mode 100644 index 0000000..2b0956e --- /dev/null +++ b/lib/types/credential.dart @@ -0,0 +1,94 @@ +import '../protobuf/service.pb.dart' as protobuf; + +class Metadata { + String id; + String sourceHost; + DateTime createdAt; + DateTime updatedAt; + String primary; + String loginUrl; + String tag; + + Metadata({ + this.id, + this.sourceHost, + this.createdAt, + this.updatedAt, + this.primary, + this.loginUrl, + this.tag, + }); + + Metadata.fromProtobuf(protobuf.Metadata metadata) { + id = metadata.id; + createdAt = metadata.createdAt.toDateTime(); + updatedAt = metadata.updatedAt.toDateTime(); + sourceHost = metadata.sourceHost; + primary = metadata.primary; + loginUrl = metadata.loginUrl; + tag = metadata.tag; + } + + @override + String toString() => "id: $id"; +} + +class MetadataInput { + String sourceHost; + String primary; + String loginUrl; + String tag; + + MetadataInput({this.sourceHost, this.primary, this.loginUrl, this.tag}); +} + +class Credential { + Metadata meta; + String username; + String email; + String password; + String otpSecret; + + Credential({ + this.meta, + this.username, + this.email, + this.password, + this.otpSecret, + }); + + Credential.fromProtobuf(protobuf.Credential credential) { + meta = Metadata( + id: credential.id, + createdAt: credential.createdAt.toDateTime(), + updatedAt: credential.updatedAt.toDateTime(), + sourceHost: credential.sourceHost, + primary: credential.primary, + loginUrl: credential.loginUrl, + tag: credential.tag, + ); + username = credential.username; + email = credential.email; + password = credential.password; + otpSecret = credential.otpSecret; + } + + @override + String toString() => "meta: $meta\n"; +} + +class CredentialInput { + MetadataInput meta; + String username; + String email; + String password; + String otpSecret; + + CredentialInput({ + this.meta, + this.username, + this.email, + this.password, + this.otpSecret, + }); +} diff --git a/lib/utils/crypto.dart b/lib/utils/crypto.dart new file mode 100644 index 0000000..fea1395 --- /dev/null +++ b/lib/utils/crypto.dart @@ -0,0 +1,15 @@ +import 'dart:math'; +import 'dart:convert'; + +import 'package:crypt/crypt.dart'; + +String hashPassword(String password) { + final random = Random.secure(); + final saltInts = List.generate(16, (_) => random.nextInt(256)); + final salt = base64.encode(saltInts); + + return Crypt.sha256(password, salt: salt).toString(); +} + +bool matchHashedPassword(String hashedPassword, String password) => + Crypt(hashedPassword).match(password); diff --git a/lib/widgets/obfuscated_text_field.dart b/lib/widgets/obfuscated_text_field.dart new file mode 100644 index 0000000..d72a047 --- /dev/null +++ b/lib/widgets/obfuscated_text_field.dart @@ -0,0 +1,28 @@ +import 'package:flutter/cupertino.dart'; + +typedef OnSubmittedBuilder = ValueChanged Function( + BuildContext context, +); + +class ObfuscatedTextField extends StatelessWidget { + final OnSubmittedBuilder onSubmittedBuilder; + + const ObfuscatedTextField({this.onSubmittedBuilder}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: CupertinoTextField( + decoration: BoxDecoration( + border: Border.all(color: CupertinoColors.black), + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + ), + clearButtonMode: OverlayVisibilityMode.editing, + textAlign: TextAlign.center, + onSubmitted: onSubmittedBuilder(context), + obscureText: true, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 97dcf06..672b612 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -43,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.1" + crypt: + dependency: "direct main" + description: + name: crypt + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.7" crypto: dependency: transitive description: @@ -69,6 +76,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1+1" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 47dd54e..b79df69 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,6 +28,9 @@ dependencies: provider: ^3.0.0 + crypt: ^1.0.7 + flutter_secure_storage: ^3.2.1 + dev_dependencies: flutter_test: sdk: flutter From af8834f7bdc777574bcfba44cea9715bc72d7ee2 Mon Sep 17 00:00:00 2001 From: mitchell Date: Fri, 5 Jul 2019 05:15:57 -0400 Subject: [PATCH 4/8] Added new config screen and buttons for navigation --- lib/main.dart | 14 ++- lib/repositories/config.dart | 14 ++- lib/screens/authentication.dart | 86 +++++++++-------- lib/screens/config.dart | 124 +++++++++++++++++++++++++ lib/screens/home.dart | 34 +++++-- lib/types/abstracts.dart | 2 + lib/widgets/obfuscated_text_field.dart | 28 ------ lib/widgets/text_field.dart | 49 ++++++++++ 8 files changed, 267 insertions(+), 84 deletions(-) create mode 100644 lib/screens/config.dart delete mode 100644 lib/widgets/obfuscated_text_field.dart create mode 100644 lib/widgets/text_field.dart diff --git a/lib/main.dart b/lib/main.dart index 4e26e49..b16f5a8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,10 +2,11 @@ import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; import 'repositories/credentials_client.dart'; -import 'repositories/config.dart'; +import 'repositories/config.dart' as repo; import 'screens/authentication.dart'; import 'screens/credentials.dart'; +import 'screens/config.dart'; import 'screens/home.dart'; import 'types/abstracts.dart'; @@ -16,7 +17,7 @@ class Selfpass extends StatelessWidget { @override Widget build(BuildContext context) { return Provider( - builder: (BuildContext context) => Config(), + builder: (BuildContext context) => repo.Config(), child: CupertinoApp( title: 'Selfpass', onGenerateRoute: (RouteSettings settings) { @@ -30,7 +31,7 @@ class Selfpass extends StatelessWidget { break; case '/home': - title = "Credential Hosts"; + title = 'Credential Hosts'; builder = (BuildContext context) => Provider( builder: (BuildContext context) => CredentialsClient(settings.arguments), @@ -39,10 +40,15 @@ class Selfpass extends StatelessWidget { break; case '/credentials': - title = "Credentials"; + title = 'Credentials'; builder = (BuildContext context) => Credentials(settings.arguments); break; + + case '/config': + title = 'Configuration'; + builder = (BuildContext context) => Config(settings.arguments); + break; } return CupertinoPageRoute(builder: builder, title: title); diff --git a/lib/repositories/config.dart b/lib/repositories/config.dart index aab0b72..01e04ec 100644 --- a/lib/repositories/config.dart +++ b/lib/repositories/config.dart @@ -54,8 +54,18 @@ class Config implements ConfigRepo { Future get connectionConfig async { _checkIfPasswordMatched(); - return ConnectionConfig.fromJson( - json.decode(await _storage.read(key: _keyConnectionConfig))); + final connConfig = await _storage.read(key: _keyConnectionConfig); + + if (connConfig == null) { + return null; + } + + return ConnectionConfig.fromJson(json.decode(connConfig)); + } + + Future deleteAll() { + _checkIfPasswordMatched(); + return _storage.deleteAll(); } void _checkIfPasswordMatched() { diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart index eb85109..a65fecf 100644 --- a/lib/screens/authentication.dart +++ b/lib/screens/authentication.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import '../types/abstracts.dart'; -import '../widgets/obfuscated_text_field.dart'; +import '../widgets/text_field.dart'; class Authentication extends StatefulWidget { @override @@ -11,9 +11,10 @@ class Authentication extends StatefulWidget { } class _AuthenticationState extends State { + final TextEditingController _passwordController = TextEditingController(); + final TextEditingController _confirmController = TextEditingController(); bool _invalid = false; bool _passesDontMatch = false; - String _masterpass; ConfigRepo _config; Future _passwordIsSet; @@ -21,14 +22,11 @@ class _AuthenticationState extends State { didChangeDependencies() { super.didChangeDependencies(); _config = Provider.of(context); + _passwordIsSet = _config.passwordSet; } @override Widget build(BuildContext context) { - if (_passwordIsSet == null) { - _passwordIsSet = _config.passwordSet; - } - return CupertinoPageScaffold( child: Container( margin: const EdgeInsets.symmetric(horizontal: 50.0), @@ -36,30 +34,34 @@ class _AuthenticationState extends State { future: _passwordIsSet, builder: (BuildContext context, AsyncSnapshot snapshot) => snapshot.connectionState == ConnectionState.done - ? Column(children: _buildColumnChildren(snapshot.data)) - : Container(), + ? Column( + children: _buildColumnChildren(context, snapshot.data)) + : Center(child: CupertinoActivityIndicator()), ), ), ); } - List _buildColumnChildren(bool passwordIsSet) { + List _buildColumnChildren(BuildContext context, bool passwordIsSet) { List children = [ const Spacer(flex: 4), const Flexible(child: Text('Master password:')), Flexible( - child: ObfuscatedTextField( - onSubmittedBuilder: - _buildMasterpassSubmittedBuilder(passwordIsSet)), + child: TextField( + obscure: true, + autofocus: true, + controller: _passwordController, + ), ), ]; if (!passwordIsSet) { children.add(const Flexible(child: Text('Re-enter password:'))); children.add(Flexible( - child: ObfuscatedTextField( - onSubmittedBuilder: - _buildConfirmPassSubmittedBuilder(passwordIsSet)), + child: TextField( + obscure: true, + controller: _confirmController, + ), )); } @@ -81,6 +83,11 @@ class _AuthenticationState extends State { )); } + children.add(CupertinoButton( + child: Text('Enter'), + onPressed: _buildSubmitPressedBuilder(context), + )); + if (_passesDontMatch) { children.add(const Spacer(flex: 1)); } else if (_invalid || !passwordIsSet) { @@ -92,40 +99,31 @@ class _AuthenticationState extends State { return children; } - OnSubmittedBuilder _buildMasterpassSubmittedBuilder(bool passwordIsSet) { - return (BuildContext context) { - return (String pass) async { - if (passwordIsSet) { - if (await _config.matchesPasswordHash(pass)) { - Navigator.of(context).pushReplacementNamed('/home', - arguments: await _config.connectionConfig); - return; - } - - this.setState(() => _invalid = true); + VoidCallback _buildSubmitPressedBuilder(BuildContext context) { + return () async { + if (await _passwordIsSet) { + if (await _config.matchesPasswordHash(_passwordController.text)) { + Navigator.of(context).pushReplacementNamed( + '/home', + arguments: await _config.connectionConfig, + ); return; } - _masterpass = pass; - }; - }; - } + this.setState(() => _invalid = true); + return; + } - OnSubmittedBuilder _buildConfirmPassSubmittedBuilder(bool passwordIsSet) { - return (BuildContext context) { - return (String pass) async { - if (pass != _masterpass) { - this.setState(() { - _passesDontMatch = true; - }); - return; - } + if (_passwordController.text != _confirmController.text) { + this.setState(() { + _passesDontMatch = true; + }); + return; + } - _config.setPassword(_masterpass); - _passwordIsSet = Future.value(true); - Navigator.of(context).pushReplacementNamed('/home', - arguments: await _config.connectionConfig); - }; + _config.setPassword(_passwordController.text); + _passwordIsSet = Future.value(true); + Navigator.of(context).pushReplacementNamed('/config'); }; } } diff --git a/lib/screens/config.dart b/lib/screens/config.dart new file mode 100644 index 0000000..c69fce5 --- /dev/null +++ b/lib/screens/config.dart @@ -0,0 +1,124 @@ +import 'package:flutter/cupertino.dart'; +import 'package:provider/provider.dart'; + +import '../types/abstracts.dart'; +import '../types/connection_config.dart'; + +import '../widgets/text_field.dart'; + +class Config extends StatefulWidget { + final ConnectionConfig connectionConfig; + + const Config(this.connectionConfig, {Key key}) : super(key: key); + + @override + State createState() => _ConfigState(this.connectionConfig); +} + +class _ConfigState extends State { + TextEditingController _hostController; + TextEditingController _caCertController; + TextEditingController _certController; + TextEditingController _privateCertController; + ConnectionConfig _connectionConfig; + ConfigRepo _config; + + _ConfigState(this._connectionConfig) { + if (_connectionConfig == null) { + _connectionConfig = ConnectionConfig(); + } + + _hostController = TextEditingController(text: _connectionConfig.host); + _certController = + TextEditingController(text: _connectionConfig.certificate); + _caCertController = + TextEditingController(text: _connectionConfig.caCertificate); + _privateCertController = + TextEditingController(text: _connectionConfig.privateCertificate); + } + + @override + didChangeDependencies() async { + super.didChangeDependencies(); + + _config = Provider.of(context); + } + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: _connectionConfig.host == null + ? null + : CupertinoNavigationBar( + trailing: GestureDetector( + onTap: _buildResetAllHandler(context), + child: Text('Reset App', + style: TextStyle(color: CupertinoColors.destructiveRed)), + ), + ), + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 50.0), + child: Column(children: [ + Spacer(flex: 3), + Flexible(child: Text('Host:')), + Flexible(child: TextField(maxLines: 1, controller: _hostController)), + Flexible(child: Text('CA certificate:')), + Flexible( + child: TextField(maxLines: 3, controller: _caCertController)), + Flexible(child: Text('Client certificate:')), + Flexible(child: TextField(maxLines: 3, controller: _certController)), + Flexible(child: Text('Private certificate:')), + Flexible( + child: + TextField(maxLines: 3, controller: _privateCertController)), + CupertinoButton( + child: Text('Save'), onPressed: _makeSaveOnPressed(context)) + ]), + ), + ); + } + + GestureTapCallback _buildResetAllHandler(BuildContext context) { + return () { + showCupertinoDialog( + context: context, + builder: (BuildContext context) => CupertinoAlertDialog( + content: Text('Are you sure?'), + actions: [ + CupertinoDialogAction( + isDefaultAction: true, + child: Text('Cancel'), + onPressed: () => Navigator.of(context).pop(), + ), + CupertinoDialogAction( + isDestructiveAction: true, + child: Text('Confirm'), + onPressed: () async { + _connectionConfig = null; + await _config.deleteAll(); + Navigator.of(context) + .pushNamedAndRemoveUntil('/', ModalRoute.withName('/')); + }, + ), + ], + ), + ); + }; + } + + VoidCallback _makeSaveOnPressed(BuildContext context) { + return () async { + final connConfig = ConnectionConfig( + host: _hostController.text, + certificate: _certController.text, + caCertificate: _caCertController.text, + privateCertificate: _privateCertController.text, + ); + + await _config.setConnectionConfig(connConfig); + + Navigator.of(context) + .pushReplacementNamed('/home', arguments: connConfig); + }; + } +} diff --git a/lib/screens/home.dart b/lib/screens/home.dart index f7e6643..619692f 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -13,20 +13,21 @@ class Home extends StatefulWidget { class _HomeState extends State { CredentialsRepo _client; + ConfigRepo _config; Future> _metadatas; @override didChangeDependencies() { super.didChangeDependencies(); + + _config = Provider.of(context); + _client = Provider.of(context); + _metadatas = _client.getAllMetadata('').toList(); } @override Widget build(BuildContext context) { - if (_metadatas == null) { - _metadatas = _client.getAllMetadata('').toList(); - } - return CupertinoPageScaffold( child: FutureBuilder>( future: _metadatas, @@ -35,9 +36,21 @@ class _HomeState extends State { (snapshot.connectionState == ConnectionState.done) ? TappableTextList( tappableText: _buildTappableText(context, snapshot.data)) - : Container(), + : Center(child: CupertinoActivityIndicator()), + ), + navigationBar: CupertinoNavigationBar( + leading: GestureDetector( + child: Align( + child: Text('Lock', + style: TextStyle(color: CupertinoColors.destructiveRed)), + alignment: Alignment(-0.9, 0)), + onTap: _makeLockOnTapHandler(context), + ), + trailing: GestureDetector( + child: Icon(CupertinoIcons.gear), + onTap: _makeConfigOnTapHandler(context), + ), ), - navigationBar: CupertinoNavigationBar(), ); } @@ -69,4 +82,13 @@ class _HomeState extends State { return tappableText; } + + GestureTapCallback _makeLockOnTapHandler(BuildContext context) { + return () => Navigator.of(context).pushReplacementNamed('/'); + } + + GestureTapCallback _makeConfigOnTapHandler(BuildContext context) { + return () async => Navigator.of(context) + .pushNamed('/config', arguments: await _config.connectionConfig); + } } diff --git a/lib/types/abstracts.dart b/lib/types/abstracts.dart index 5ac1041..358322d 100644 --- a/lib/types/abstracts.dart +++ b/lib/types/abstracts.dart @@ -21,4 +21,6 @@ abstract class ConfigRepo { Future setConnectionConfig(ConnectionConfig config); Future get connectionConfig; + + Future deleteAll(); } diff --git a/lib/widgets/obfuscated_text_field.dart b/lib/widgets/obfuscated_text_field.dart deleted file mode 100644 index d72a047..0000000 --- a/lib/widgets/obfuscated_text_field.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/cupertino.dart'; - -typedef OnSubmittedBuilder = ValueChanged Function( - BuildContext context, -); - -class ObfuscatedTextField extends StatelessWidget { - final OnSubmittedBuilder onSubmittedBuilder; - - const ObfuscatedTextField({this.onSubmittedBuilder}); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: CupertinoTextField( - decoration: BoxDecoration( - border: Border.all(color: CupertinoColors.black), - borderRadius: const BorderRadius.all(Radius.circular(5.0)), - ), - clearButtonMode: OverlayVisibilityMode.editing, - textAlign: TextAlign.center, - onSubmitted: onSubmittedBuilder(context), - obscureText: true, - ), - ); - } -} diff --git a/lib/widgets/text_field.dart b/lib/widgets/text_field.dart new file mode 100644 index 0000000..ed52fa1 --- /dev/null +++ b/lib/widgets/text_field.dart @@ -0,0 +1,49 @@ +import 'package:flutter/cupertino.dart'; + +typedef OnSubmittedBuilder = ValueChanged Function( + BuildContext context, +); + +class TextField extends StatelessWidget { + final OnSubmittedBuilder onSubmittedBuilder; + final TextEditingController controller; + final bool obscure; + final bool autofocus; + final bool autocorrect; + final int minLines; + final int maxLines; + + const TextField({ + this.onSubmittedBuilder, + this.controller, + this.obscure = false, + this.autofocus = false, + this.minLines, + this.maxLines, + this.autocorrect = false, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: CupertinoTextField( + decoration: BoxDecoration( + border: Border.all(color: CupertinoColors.black), + borderRadius: const BorderRadius.all(Radius.circular(5.0)), + ), + clearButtonMode: OverlayVisibilityMode.editing, + textAlign: TextAlign.start, + onSubmitted: this.onSubmittedBuilder != null + ? onSubmittedBuilder(context) + : null, + controller: controller, + obscureText: obscure, + autofocus: autofocus, + autocorrect: autocorrect, + minLines: minLines, + maxLines: maxLines, + ), + ); + } +} From 910bdeae124e9d793e4d297773b1163db14485b8 Mon Sep 17 00:00:00 2001 From: mitchell Date: Sun, 7 Jul 2019 00:14:09 -0400 Subject: [PATCH 5/8] Add credential screen & screen arguments; refactor config screen --- lib/main.dart | 26 +++- lib/repositories/credentials_client.dart | 4 + lib/screens/authentication.dart | 6 +- lib/screens/config.dart | 47 ++++--- lib/screens/credential.dart | 155 +++++++++++++++++++++++ lib/screens/credentials.dart | 17 ++- lib/screens/home.dart | 8 +- lib/types/screen_arguments.dart | 8 ++ lib/widgets/text_field.dart | 6 + 9 files changed, 246 insertions(+), 31 deletions(-) create mode 100644 lib/screens/credential.dart create mode 100644 lib/types/screen_arguments.dart diff --git a/lib/main.dart b/lib/main.dart index b16f5a8..d3d417d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,11 +5,13 @@ import 'repositories/credentials_client.dart'; import 'repositories/config.dart' as repo; import 'screens/authentication.dart'; +import 'screens/credential.dart'; import 'screens/credentials.dart'; import 'screens/config.dart'; import 'screens/home.dart'; import 'types/abstracts.dart'; +import 'types/screen_arguments.dart'; void main() => runApp(Selfpass()); @@ -31,23 +33,37 @@ class Selfpass extends StatelessWidget { break; case '/home': - title = 'Credential Hosts'; + title = 'Hosts'; builder = (BuildContext context) => Provider( builder: (BuildContext context) => - CredentialsClient(settings.arguments), + CredentialsClient.cached(config: settings.arguments), child: Home(), ); break; case '/credentials': title = 'Credentials'; - builder = - (BuildContext context) => Credentials(settings.arguments); + builder = (BuildContext context) => Provider( + builder: (BuildContext context) => + CredentialsClient.cached(), + child: Credentials(settings.arguments), + ); + break; + + case '/credential': + title = 'Credential'; + builder = (BuildContext context) => Provider( + builder: (BuildContext context) => + CredentialsClient.cached(), + child: Credential(settings.arguments), + ); break; case '/config': + final ConfigScreenArguments arguments = settings.arguments; title = 'Configuration'; - builder = (BuildContext context) => Config(settings.arguments); + builder = (BuildContext context) => + Config(arguments.connectionConfig, arguments.privateKey); break; } diff --git a/lib/repositories/credentials_client.dart b/lib/repositories/credentials_client.dart index b84a757..a51de43 100644 --- a/lib/repositories/credentials_client.dart +++ b/lib/repositories/credentials_client.dart @@ -12,6 +12,7 @@ import '../types/connection_config.dart'; import '../types/credential.dart'; class CredentialsClient implements CredentialsRepo { + static CredentialsClient _cached; grpc.CredentialServiceClient _client; CredentialsClient(ConnectionConfig config) { @@ -32,6 +33,9 @@ class CredentialsClient implements CredentialsRepo { )); } + factory CredentialsClient.cached({ConnectionConfig config}) => + _cached == null ? _cached = CredentialsClient(config) : _cached; + Stream getAllMetadata(String sourceHost) { final request = grpc.GetAllMetadataRequest(); request.sourceHost = sourceHost; diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart index a65fecf..cbf51c9 100644 --- a/lib/screens/authentication.dart +++ b/lib/screens/authentication.dart @@ -48,6 +48,7 @@ class _AuthenticationState extends State { const Flexible(child: Text('Master password:')), Flexible( child: TextField( + maxLines: 1, obscure: true, autofocus: true, controller: _passwordController, @@ -59,6 +60,7 @@ class _AuthenticationState extends State { children.add(const Flexible(child: Text('Re-enter password:'))); children.add(Flexible( child: TextField( + maxLines: 1, obscure: true, controller: _confirmController, ), @@ -85,7 +87,7 @@ class _AuthenticationState extends State { children.add(CupertinoButton( child: Text('Enter'), - onPressed: _buildSubmitPressedBuilder(context), + onPressed: _buildEnterPressedBuilder(context), )); if (_passesDontMatch) { @@ -99,7 +101,7 @@ class _AuthenticationState extends State { return children; } - VoidCallback _buildSubmitPressedBuilder(BuildContext context) { + VoidCallback _buildEnterPressedBuilder(BuildContext context) { return () async { if (await _passwordIsSet) { if (await _config.matchesPasswordHash(_passwordController.text)) { diff --git a/lib/screens/config.dart b/lib/screens/config.dart index c69fce5..58b7929 100644 --- a/lib/screens/config.dart +++ b/lib/screens/config.dart @@ -8,11 +8,13 @@ import '../widgets/text_field.dart'; class Config extends StatefulWidget { final ConnectionConfig connectionConfig; + final String privateKey; - const Config(this.connectionConfig, {Key key}) : super(key: key); + const Config(this.connectionConfig, this.privateKey, {Key key}) + : super(key: key); @override - State createState() => _ConfigState(this.connectionConfig); + State createState() => _ConfigState(this.connectionConfig, this.privateKey); } class _ConfigState extends State { @@ -20,10 +22,12 @@ class _ConfigState extends State { TextEditingController _caCertController; TextEditingController _certController; TextEditingController _privateCertController; + TextEditingController _privateKeyController; ConnectionConfig _connectionConfig; + String _privateKey; ConfigRepo _config; - _ConfigState(this._connectionConfig) { + _ConfigState(this._connectionConfig, this._privateKey) { if (_connectionConfig == null) { _connectionConfig = ConnectionConfig(); } @@ -35,6 +39,8 @@ class _ConfigState extends State { TextEditingController(text: _connectionConfig.caCertificate); _privateCertController = TextEditingController(text: _connectionConfig.privateCertificate); + + _privateKeyController = TextEditingController(text: _privateKey); } @override @@ -57,22 +63,26 @@ class _ConfigState extends State { ), ), child: Container( - margin: const EdgeInsets.symmetric(horizontal: 50.0), - child: Column(children: [ - Spacer(flex: 3), - Flexible(child: Text('Host:')), - Flexible(child: TextField(maxLines: 1, controller: _hostController)), - Flexible(child: Text('CA certificate:')), - Flexible( - child: TextField(maxLines: 3, controller: _caCertController)), - Flexible(child: Text('Client certificate:')), - Flexible(child: TextField(maxLines: 3, controller: _certController)), - Flexible(child: Text('Private certificate:')), - Flexible( - child: - TextField(maxLines: 3, controller: _privateCertController)), + margin: const EdgeInsets.symmetric(horizontal: 30), + child: ListView(children: [ + Container(margin: EdgeInsets.only(top: 10), child: Text('Host:')), + TextField(maxLines: 1, controller: _hostController), + Container( + margin: EdgeInsets.only(top: 5), child: Text('Private key:')), + TextField(maxLines: 1, controller: _privateKeyController), + Container( + margin: EdgeInsets.only(top: 5), child: Text('CA certificate:')), + TextField(maxLines: 5, controller: _caCertController), + Container( + margin: EdgeInsets.only(top: 5), + child: Text('Client certificate:')), + TextField(maxLines: 5, controller: _certController), + Container( + margin: EdgeInsets.only(top: 5), + child: Text('Private certificate:')), + TextField(maxLines: 5, controller: _privateCertController), CupertinoButton( - child: Text('Save'), onPressed: _makeSaveOnPressed(context)) + child: Text('Save'), onPressed: _makeSaveOnPressed(context)), ]), ), ); @@ -116,6 +126,7 @@ class _ConfigState extends State { ); await _config.setConnectionConfig(connConfig); + await _config.setPrivateKey(_privateKeyController.text); Navigator.of(context) .pushReplacementNamed('/home', arguments: connConfig); diff --git a/lib/screens/credential.dart b/lib/screens/credential.dart new file mode 100644 index 0000000..1d4db71 --- /dev/null +++ b/lib/screens/credential.dart @@ -0,0 +1,155 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; + +import '../types/credential.dart' as types; + +import '../widgets/text_field.dart'; + +class Credential extends StatefulWidget { + final types.Credential credential; + + const Credential(this.credential, {Key key}) : super(key: key); + + @override + State createState() => _CredentialState(credential); +} + +class _CredentialState extends State { + _CredentialControllers _controllers; + Map _fieldMap; + types.Credential _credential; + + _CredentialState(this._credential) : super() { + _controllers = _CredentialControllers.fromCredential(_credential); + _fieldMap = _buildFieldMap(_controllers, _credential); + } + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: CupertinoNavigationBar(), + child: Container( + margin: const EdgeInsets.only(top: 30, left: 30), + child: ListView( + children: _buildFieldRows(context), + ), + ), + ); + } + + Map _buildFieldMap( + _CredentialControllers controllers, + types.Credential credential, + ) { + final fieldMap = { + 'Id:': _FieldBuildConfig(mutable: false, text: credential.meta.id), + 'Created: ': _FieldBuildConfig( + mutable: false, + copyable: false, + text: credential.meta.createdAt.toString(), + ), + 'Updated: ': _FieldBuildConfig( + mutable: false, + copyable: false, + text: credential.meta.updatedAt.toString(), + ), + 'Host:': _FieldBuildConfig(controller: controllers.sourceHost), + 'Primary:': _FieldBuildConfig(controller: controllers.primary), + }; + + if (credential.meta.tag != null && credential.meta.tag != '') { + fieldMap['Tag'] = _FieldBuildConfig(controller: controllers.tag); + } + + if (credential.username != null && credential.username != '') { + fieldMap['User:'] = _FieldBuildConfig(controller: controllers.username); + } + + if (credential.email != null && credential.email != '') { + fieldMap['Email:'] = _FieldBuildConfig(controller: controllers.email); + } + + return fieldMap; + } + + List _buildFieldRows(BuildContext context) { + List rows = []; + + _fieldMap.forEach((key, value) { + rows.add(Container( + margin: EdgeInsets.only(top: 10), + child: Text(key, style: TextStyle(fontWeight: FontWeight.w600)), + )); + + final List widgets = [ + Expanded( + flex: 3, + child: value.mutable + ? TextField(maxLines: 1, controller: value.controller) + : Container( + margin: EdgeInsets.symmetric(vertical: 10), + child: Text(value.text), + ), + ), + ]; + + if (value.copyable) { + widgets.add(Flexible( + child: CupertinoButton( + child: Text('Copy'), + onPressed: () => Clipboard.setData(ClipboardData( + text: value.mutable ? value.controller.text : value.text, + )), + ), + )); + } + + rows.add(Row(children: widgets)); + }); + + return rows; + } +} + +class _FieldBuildConfig { + final TextEditingController controller; + final String text; + final bool mutable; + final bool copyable; + + const _FieldBuildConfig({ + this.mutable = true, + this.copyable = true, + this.controller, + this.text, + }); +} + +class _CredentialControllers { + final TextEditingController sourceHost; + final TextEditingController primary; + final TextEditingController tag; + final TextEditingController username; + final TextEditingController email; + final TextEditingController password; + final TextEditingController otpSecret; + + const _CredentialControllers({ + this.sourceHost, + this.primary, + this.tag, + this.username, + this.email, + this.password, + this.otpSecret, + }); + + factory _CredentialControllers.fromCredential(types.Credential credential) => + _CredentialControllers( + sourceHost: TextEditingController(text: credential.meta.sourceHost), + primary: TextEditingController(text: credential.meta.primary), + tag: TextEditingController(text: credential.meta.tag), + username: TextEditingController(text: credential.username), + email: TextEditingController(text: credential.email), + ); +} diff --git a/lib/screens/credentials.dart b/lib/screens/credentials.dart index 1a6efa7..0c086ed 100644 --- a/lib/screens/credentials.dart +++ b/lib/screens/credentials.dart @@ -1,5 +1,7 @@ import 'package:flutter/cupertino.dart'; +import 'package:provider/provider.dart'; +import '../types/abstracts.dart'; import '../types/credential.dart'; import '../widgets/tappable_text_list.dart'; @@ -18,12 +20,21 @@ class Credentials extends StatelessWidget { } Map _buildTappableText(BuildContext context) { - var handleOnTap = () {}; + var makeOnTapHandler = (String id) => () async { + final credential = + await Provider.of(context).get(id); + Navigator.of(context).pushNamed('/credential', arguments: credential); + }; Map tappableText = {}; - metadatas.forEach( - (Metadata metadata) => tappableText[metadata.id] = handleOnTap); + metadatas.forEach((Metadata metadata) { + var primary = metadata.primary; + if (metadata.tag != null && metadata.tag != '') { + primary += "-" + metadata.tag; + } + tappableText[primary] = makeOnTapHandler(metadata.id); + }); return tappableText; } diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 619692f..06f63b9 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import '../types/abstracts.dart'; import '../types/credential.dart'; +import '../types/screen_arguments.dart'; import '../widgets/tappable_text_list.dart'; @@ -72,7 +73,7 @@ class _HomeState extends State { } } - final handleOnTap = (List metadatas) => () => + final handleOnTap = (List metadatas) => () async => Navigator.of(context).pushNamed('/credentials', arguments: metadatas); final Map tappableText = {}; @@ -88,7 +89,8 @@ class _HomeState extends State { } GestureTapCallback _makeConfigOnTapHandler(BuildContext context) { - return () async => Navigator.of(context) - .pushNamed('/config', arguments: await _config.connectionConfig); + return () async => Navigator.of(context).pushNamed('/config', + arguments: ConfigScreenArguments( + await _config.connectionConfig, await _config.privateKey)); } } diff --git a/lib/types/screen_arguments.dart b/lib/types/screen_arguments.dart new file mode 100644 index 0000000..3f841a2 --- /dev/null +++ b/lib/types/screen_arguments.dart @@ -0,0 +1,8 @@ +import 'connection_config.dart'; + +class ConfigScreenArguments { + final ConnectionConfig connectionConfig; + final String privateKey; + + const ConfigScreenArguments(this.connectionConfig, this.privateKey); +} diff --git a/lib/widgets/text_field.dart b/lib/widgets/text_field.dart index ed52fa1..aa18e30 100644 --- a/lib/widgets/text_field.dart +++ b/lib/widgets/text_field.dart @@ -7,6 +7,8 @@ typedef OnSubmittedBuilder = ValueChanged Function( class TextField extends StatelessWidget { final OnSubmittedBuilder onSubmittedBuilder; final TextEditingController controller; + final Widget prefix; + final Widget suffix; final bool obscure; final bool autofocus; final bool autocorrect; @@ -21,6 +23,8 @@ class TextField extends StatelessWidget { this.minLines, this.maxLines, this.autocorrect = false, + this.prefix, + this.suffix, }); @override @@ -43,6 +47,8 @@ class TextField extends StatelessWidget { autocorrect: autocorrect, minLines: minLines, maxLines: maxLines, + prefix: prefix, + suffix: suffix, ), ); } From 27215e6596b25991f967a130437e046fac566a18 Mon Sep 17 00:00:00 2001 From: mitchell Date: Mon, 8 Jul 2019 22:03:44 -0400 Subject: [PATCH 6/8] Add decryption of credential encrypted fields; refactored config; add app icon --- android/app/build.gradle | 2 +- android/app/src/debug/AndroidManifest.xml | 2 +- android/app/src/main/AndroidManifest.xml | 4 +- android/app/src/profile/AndroidManifest.xml | 2 +- app.png | Bin 0 -> 4202676 bytes app.xcf | Bin 0 -> 83796 bytes ios/Podfile.lock | 4 +- ios/Runner.xcodeproj/project.pbxproj | 2 +- .../AppIcon.appiconset/1024-1.png | Bin 0 -> 38068 bytes .../AppIcon.appiconset/1024.png | Bin 0 -> 38068 bytes .../AppIcon.appiconset/114.png | Bin 0 -> 1519 bytes .../AppIcon.appiconset/120.png | Bin 0 -> 1544 bytes .../AppIcon.appiconset/128.png | Bin 0 -> 1809 bytes .../Assets.xcassets/AppIcon.appiconset/16.png | Bin 0 -> 163 bytes .../AppIcon.appiconset/180.png | Bin 0 -> 3010 bytes .../AppIcon.appiconset/256.png | Bin 0 -> 5397 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 0 -> 233 bytes .../Assets.xcassets/AppIcon.appiconset/32.png | Bin 0 -> 276 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 0 -> 394 bytes .../AppIcon.appiconset/512.png | Bin 0 -> 17035 bytes .../Assets.xcassets/AppIcon.appiconset/57.png | Bin 0 -> 549 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 600 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 0 -> 601 bytes .../Assets.xcassets/AppIcon.appiconset/64.png | Bin 0 -> 695 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 0 -> 893 bytes .../Assets.xcassets/AppIcon.appiconset/87.png | Bin 0 -> 1032 bytes .../AppIcon.appiconset/Contents.json | 150 ++++++++++-------- .../Icon-App-1024x1024@1x.png | Bin 11112 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 564 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1588 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 1025 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1716 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 1920 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 1895 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 3831 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 1888 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 3294 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 3612 -> 0 bytes ios/Runner/Assets.xcassets/Contents.json | 6 + ios/Runner/Info.plist | 2 +- lib/main.dart | 4 +- .../google/protobuf/timestamp.pb.dart | 65 +++++--- .../google/protobuf/timestamp.pbjson.dart | 1 - lib/protobuf/service.pbjson.dart | 46 +++++- lib/repositories/config.dart | 24 ++- lib/screens/authentication.dart | 6 +- lib/screens/credential.dart | 50 ++++-- lib/screens/credentials.dart | 39 ++++- lib/screens/home.dart | 3 +- lib/types/abstracts.dart | 1 + lib/types/screen_arguments.dart | 2 +- lib/utils/crypto.dart | 29 +++- lib/widgets/text_field.dart | 4 +- pubspec.lock | 61 ++++++- pubspec.yaml | 8 +- test/widget_test.dart | 4 +- 60 files changed, 370 insertions(+), 151 deletions(-) create mode 100644 app.png create mode 100644 app.xcf create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/1024-1.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png create mode 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png mode change 100644 => 100755 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/Contents.json diff --git a/android/app/build.gradle b/android/app/build.gradle index a49d2ac..6ef7ec2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -33,7 +33,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.selfpass_mobile" + applicationId "com.mjfs.selfpass" minSdkVersion 16 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 2aa04ad..65d8d3b 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.mjfs.selfpass"> diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 813275a..868e068 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.mjfs.selfpass"> + package="com.mjfs.selfpass"> diff --git a/app.png b/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ee2b41c48127c50a115944fe6e12100b31402c9e GIT binary patch literal 4202676 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 literal 0 HcmV?d00001 diff --git a/app.xcf b/app.xcf new file mode 100644 index 0000000000000000000000000000000000000000..628cbeaf287c5ba79002d45d1f085bd6a482ff86 GIT binary patch literal 83796 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�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 Mp!(?FeE*63J0xUvdjJ3c literal 0 HcmV?d00001 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 557bbc7..f25d3cd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,12 +4,12 @@ PODS: - Flutter DEPENDENCIES: - - Flutter (from `.symlinks/flutter/ios`) + - Flutter (from `.symlinks/flutter/ios-release`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) EXTERNAL SOURCES: Flutter: - :path: ".symlinks/flutter/ios" + :path: ".symlinks/flutter/ios-release" flutter_secure_storage: :path: ".symlinks/plugins/flutter_secure_storage/ios" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 3b9aebf..8590272 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -253,7 +253,7 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", + "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024-1.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024-1.png new file mode 100644 index 0000000000000000000000000000000000000000..381444c075c07afa5214f20cee8daf6450c53afb GIT binary patch literal 38068 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 toYEz_3Em5kBme!sKmKnH{(t*`$L~ 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 T^MW@NK@K6{NN)A65h?!w*^#@} literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100755 index 0000000000000000000000000000000000000000..1d235b7ff036bdfae7f8125d4bb7f433268f67cb GIT binary patch literal 1544 zcmV+j2KV`iP) z?N8fQ6o>o&e=sEuF9E>-bra1B8Y-Pu3Sy`rRD@Oy*vcSFfHZ+g<>f;I1d{yrDaiOO ziG8l`_3?QmemwdKM|x)zy_J*3eL%IAis&5bPGQy!2x~JI=b0xDsNK+Cxo+ur>Ez%v@3!Yp|f*EutM(d@3nU9 z;^LABR)urIp;%ndl7pYz`+N1reM*cJJU{=lW9DgJOAcJ7EsYaAH8uOxnIAuHY0JY; z?(FQ3+VY8tQGyQ-kBq1mF4YSdCfJ0|43gVuG_>Uu2V(@AEH|yy3m78UgwEtB7cfw8 ztJTulJ}0?=0fKdRC}+7q#s!DT)iIK&K&#;Q?^m@5uGQ+Ha?|#sei&K>>lhZp#Bv#y zon%VzyLZ23N-mHw!9negjZG%ft`0IO*x5d(cU9DkB^T!(_)2@f~AV- z&?>l8DvM;r7&nvU-c;Poo+Y#kE|21Pfq@zJ5{4GRxr@NWU1z0j1~+4jYgwy$+_I9 z?sSdAc)?wynxl~#!2nRNpZ6_!ZS8m6=^8<*1b2~Y?w?c&27vSP3z6IhsTJHsB!`oF z!2qzgcc4vjyWJir{>zsmiRQ;baF-+{fBNK|af_RqW!WecrpR&xmTdh{f05(}Fcb^``TV$2!RP1yd16*7C!Wta1%}4|4i4i;xF1F zf(eM*fkBsB6f#6G0nW~Q{rXMs9YXdGx=f0~=;)*;Ce=#2nH3y&|1?xDAc7jzuG zRI^OZSX4sXv4)4$J@!f_*s^TQ&ksKRM@_TYB(Dm$kT`31ot;$^t6qRe@ZsS<&l0xn zaf+}5qpH(XRDt4Gp|AgtNcRl_$t}h|CO56`ju62CaHw8D1P3C5nInRkh`2zJ4#dI1saK?E~qclQqw%$euM->U9(ND#pexK%G8g4rX2nInRk uBZ8SDf|(b(yQdcb0000 z+fx%s6o>u)AA(c>Ax1z!z<67^hD!t~G^JH5OR4M{4eEj`H<#NQpa}f-!5R#cNivty z(>;C8S2a(B(YBLXl-1YnK`z#I{PIU)daL;&W9 z0L)=6!1?((9zOgHsZ`q6F)@+XoiaJ>1h{^^(|5s}9VaIzy59;3ECgs&#D#@LU;ke! zeP|dX=~yekvu8_n#mZ#*BE=jVo3c&<>jb!QO-7NydO}V^gOlNx)zpbr9Yfe!xUVtZ0#xFa%y}e6oE*%{`R*inZZ~^Y# zy?5Ek>2$a5bgWzsHdcVi$!ViH+14M0j1*vNYdaCeHzBvE7%6~B9o*YHU~TaM0|hYY z?0Rl)zG3l~mshmrMukxV3=QRs8DWcy^*<+@k{cyP31CVm=W>r&6dy21fcEyTE1kT) zzF|ZjHWwc-NB|Q$x>@0EEIwd}0DF7;+B=(L@c}~w(AnYR<9W8l2bc@cs_-T(KdXkd z0Km`9AztloZ0I=&jT>VHSX=uPYYwH-M;24Q8)F6FRtQ}fEx_BitGZLO9-{@2SwKBT z2$0S8iv*f5LI8m8LX2(_BS0#Z#{T|+?li5#7y$r(65P2nq&rQkFiL>^{R3YT$VUPl zMhO4_%gZaiB{(`d(w%PNF-`yg*xmi^TLPI4qG6-}4nZV1KR?%sx|%@8m)g2Wtdy@GHUV*MBI_WoKtM z@JG*^H*eA3KZy4BE=*0$D9Y>?)(HRrnM|KA2~_=-kjp&`bOPFJ7qW9~Z|^9{)k*;X zpi()G{lw6FQL5VT_0?)M(D}>Y;0S5HfW-nh#3@0L*rTHpm#?{bv%l`|r>Cc$@pg80 z$?^pl2mrK}pjdpVtQ{|I-MZ~tKGm}p3jqN2*Bm~5y5K8r?QQS;;JyobDn+|#hK&F~ za|u3vER)AxTl;+FHHU|Xp@dU83$PLZP`3xcPrR`0hycXs5Fkn$A^P_2w<=PUUB>S21sH%uoYlx>en-g!Y)Jlmo!IC-g;}Z7S$sgF0PbUErhwz) zla_6jN*~bH)}d{d0cds?ot>Rs`M+$oeur=zL>A!S;4pIWqaJbJ6R=f23k!>Z{-5&O zNl-|?1q=)f#aehB_W+!noUY3Q0M^$xJaf$FXR)+YL|@-P-QUXPwb=7_qii9lTCHMa zhyaXn?(^du-@pH>J0%iC0H4@6`T-HZ zHzELYL;&X07XRC~aQ6~25fQ)#qob2nj($J{@P)0@KOh45LIhw=ZSg;U{-Qe_QbYhB z*gEfH@)nb3_2wF~;^VMlwkzU#|H1DU_%1mAc9-i3a|F90rD9)jOtl)|P(*+REVR L>gTe~DWM4fEt5fN literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100755 index 0000000000000000000000000000000000000000..e0bb064a91de21fdd25dffb0cc4e1ca676f94b20 GIT binary patch literal 3010 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100755 index 0000000000000000000000000000000000000000..b66b905bb494d5bd587190c9b664d88562d4e083 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^vLMXC1|-8Kr}G1;4W2HJAs(G?uNm?+DDbcbytm)6 z!|=s}BM)?a_O#z?-X#~b^rAKh60!3gMf22WQ%mvv4FO#q&VUbz4O literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png new file mode 100755 index 0000000000000000000000000000000000000000..d84a8ef5573ed710bdd0631225fc1346e51a722b GIT binary patch literal 276 zcmV+v0qg#WP)Hs+r08

2H5xG)JH7?^ZX!*s{xz^9tO)2CjkJMVC|IM=Zcd7Bm(~r5JPBy zkbgrh2v#Gi3Bqc{r4Ttk(Ja6Mzt`h^%vUrGQxI5oFktaGP6;iGOZxTw?HYj8O;tVt z1xOWudQ$)s#_?Vk023-ne-a?B;?iJP_2&%DfOAh#!&%pjbf#(%Uh*jYSpc;sSp(3v a2JixLH;JvdO>wRO0000|+Paksc*noh=(2Yj;X-?s}2?lbTiUSXacU&$R zYiukI2mtyt6bDM<01x2lbY?ZY-M*9I01qIyX-XUr0Bo8jS#wUj??I(Bx~`kb^N=85 z>dWX#(1ThM8MTv0K%@5J`~7EfWYV`87t*Z%owMEUrUi14CXT9^N&3Rd0ov+f!0R<9 z0ZM6P*{5}$7?5f<0Nb`@&lw^Lq{fThgT9Ex0Db2SN&1+f&bw-x&8u@=63E>hj>iwI z*Dqw9T8F#76=?3Wu462=u}W#|_iv+fNuZgsERpA5sOy@ws0ob8k>*e9Z& oogsMwW3y_k5F*=HOA?ZO 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100755 index 0000000000000000000000000000000000000000..1ebd450e2c81c9079abb001f476d558536a61d54 GIT binary patch literal 893 zcmV-@1A_dCP)==KNUy6Nae_Z3lVFxTIc2rNG=vaYBtUx4IAQCGOi4}-MTY;m|PhiabZ&Qs{0&i|U zugJN*{gT>O7m->B%qwC(pDUNBRG^H-Z>7L;xhieZTPINVVz)-%VzD4u=vD~4xVQwy zTsS|!lp0ruotRu;wOR+pTnwBuif0>Xbad)?* zdTND8W?jSilWT3??iQ8=GA0y$WTY2((#!hB)c2?Y3C;$Se$G_KWp`%fAB`!CnZiJy8`t97BdYAFyP z-;r3F^ep4^R-v&1i=bBVA(%(s;#cAofHff$4Y@(a6+#7XkT ztk;{$mf?(>a#1`*D)7 z4iDdC>MIK=6_}@u$73lANQ)om?(Q4OWd{JU3;Vt=B<$qmz07$p;ql{d;7(7wE4iD^ zHc4&(4R2#aXf|79m6er33#7Uu5WxyWVuV1ISb<0iE3nZJe*&SPumW|s{s9;uP&HN{ z5-Si%AqAGpudF}}TwWN4s;5$HfjVFXA}ORmov;FtSb<2aKqOWm5-Sji6^P^y&=3r~ T@zI3$00000NkvXXu0mjfJYJ9Y literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100755 index 0000000000000000000000000000000000000000..b27c3e60379e651f5542d3472a4e986b857dbfbd GIT binary patch literal 1032 zcmV+j1o!)iP)DP21SDSWVB&jw-^j*Jq+H5L*J`_O#NOTAlf(&%R=L#G z#HnfljdFF1U07Hqixm_taw*qX@A#am7SJF!pD&V5xKjDZQY@fB?qI^5PDlCJtE=lH zVlOV5%HxPaDwndF{FZ`3p{P8L46&5!Cw6vrUTF*!#7b_z-}e=Jcvx35zG}$i=5imD z%RM;w&i3Tx2bo+-32_h$Xq1~uWvN23g-q`Gc{5grFa_F9Xh{^TU9RJ}czSxG49f;> zcWA?n!wW=ev_7~=+A^X2k)vO0wOYE;&`Kl^%ac;Y+F$eR?~mSPdE439Z`~=85!u_{ zBvf&v-z_XIu8tM_`uZAWdeTJxQ3zme6|;~F0PE{j;{>yjJAg{?&CSikF;vH7Cl^pF zcysg9#Qs#v5=*%Nu(h?LWTKP$Pueacn5|p@Xt&$ag2(lB92d8@e*^Uufwf!!xV*el zCUo_jz^&ir~C&dt*po*$hL1?+d zZwTh*N=gzLP%JJ=Pf$dXYO#QT+~M`i+d7>`;Y8Bu86}fjSt-BCsn_dG?6bZ7MY&iY zq})_0J67&+Ycx*Y9jnne8QH(t{3AUfzdXiKDA4`kskCxMn@YUnUR_iEG{J*_i zt|-l6fYjB3->*wS+R;%%RsJLR$$WTt@Xe#!?ULmIFuxQNf$E45!6>=Q%VjoV0mI~S zs#?IxCB;a&nM^+FQ~($%mkY+o^*(0gf-!Qrt+#-cONw!FIbr1zVuW0dO9Ei!l46ux zZdkd5Sh<84A(tywE+JMfAyzISRxTk{E+JMfA^!l`alNUIe`sa^0000iT7q6h&WAVr806i~>Gqn6rM z>3}bMG&oq%DIriqR35=rtEdos5L6z)YC*Xq0U-$_+Il@RaU zXYX%+``hR28`(B*uJ6G9&iz>|)PS%!)9N`7=LcmcxH}k69HPyT-%S zH7+jBCC<%76cg_H-n41cTqnKn`u_V9p~XaTLUe3s{KRPSTeK6apP4Jg%VQ$e#72ms zxyWzmGSRwN?=fRgpx!?W&ZsrLfuhAsRxm%;_|P@3@3~BJwY4ZVBJ3f&$5x>`^fD?d zI+z!v#$!gz%FtL*%mR^Uwa*8LJFZ_;X!y$cD??W#c)31l@ervOa_Qk86R{HJiZb$f z&&&0xYmB{@D@yl~^l5IXtB_ou{xFiYP(Jr<9Ce{jCN z<3Rf2TD%}_N?y>bgWq|{`RKd}n>P4e8Z-D+(fn^4)+|pv$DcR&i+RHNhv$71F*McT zl`phYBlb;wO`b7)*10XF6UXhY9`@UR*6-#(Zp`vyU(__*te6xYtV&N0(zjMtev{tZ zapmGin===teMXjsS0>CYxUy<2izOKOPai0}!B9+6q$s3CF8W{xUwz?A0ADO5&BsiB z{SFt|KehNd-S#eiDq!y&+mW9N_!wH-i~q|oNm=mEzkx}B?Ehe%q$tK8f=QY#*6rH9 zNHHaG(9WBqzP!!TMEktSVuh$i$4A^b25LK}&1*4W?ul*5pZYjL1OZ@X9?3W7Y|T6} z1SXx0Wn-|!A;fZGGlYn9a1Jz5^8)~v#mXhmm>um{QiGG459N}L<&qyD+sy_ixD@AP zW0XV6w#3(JW>TEV}MD=O0O>k5H>p#&|O zD2mGf0Cz7+>l7`NuzGobt;(o@vb9YiOpHN8QJ9Uva|i7R?7nnq;L_iq+ZqPv*oGu! zN@GuJ9fm;yrEFga63m?1qy|5&fd32<%$yP$llh}Udrp>~fb>M>R55I@BsGYhCj8m1 zC=ziFh4@hoytpfrJlr}FsV|C(aV4PZ^8^`G29(+!Bk8APa#PemJqkF zE{IzwPaE)I&r`OxGk*vPErm6sGKaQJ&6FODW$;gAl_4b_j!oH4yE@ zP~Cl4?kp>Ccc~Nm+0kjIb`U0N7}zrQEN5!Ju|}t}LeXi!baZOyhlWha5lq{Ld2rdo zGz7hAJQt<6^cxXTe0xZjmADL85cC&H+~Lt2siIIh{$~+U#&#^{Ub22IA|ea6 z5j12XLc`~dh$$1>3o0Cgvo*ybi$c*z>n=5L&X|>Wy1~eagk;lcEnf^2^2xB=e58Z` z@Rw{1ssK)NRV+2O6c<8qFl%efHE;uy!mq(Xi1P*H2}LMi z3EqWN2U?eW{J$lSFxDJg-=&RH!=6P9!y|S~gmjg)gPKGMxq6r9cNIhW` zS})-obO}Ao_`;=>@fAwU&=|5$J;?~!s4LN2&XiMXEl>zk9M}tVEg#kkIkbKp%Ig2QJ2aCILCM1E=aN*iuz>;q#T_I7aVM=E4$m_#OWLnXQnFUnu?~(X>$@NP zBJ@Zw>@bmErSuW7SR2=6535wh-R`WZ+5dLqwTvw}Ks8~4F#hh0$Qn^l-z=;>D~St( z-1yEjCCgd*z5qXa*bJ7H2Tk54KiX&=Vd}z?%dcc z`N8oeYUKe17&|B5A-++RHh8WQ%;gN{vf%05@jZF%wn1Z_yk#M~Cn(i@MB_mpcbLj5 zR#QAtC`k=tZ*h|){Mjz`7bNL zGWOW=bjQhX@`Vw^xn#cVwn28c2D9vOb0TLLy~-?-%gOyHSeJ9a>P}5OF5$n}k-pvUa*pvLw)KvG~>QjNWS3LY1f*OkFwPZ5qC@+3^Bt=HZbf`alKY#{pn zdY}NEIgo1sd)^TPxVzO{uvU$|Z-jkK0p1x##LexgQ$zx1^bNPOG*u2RmZkIM!zFVz zz|IsP3I?qrlmjGS2w_(azCvGTnf~flqogV@Q%mH{76uLU(>UB zQZ?*ys3BO&TV{Pj_qEa-hkH7mOMe_Bnu3%CXCgu90XNKf$N)PUc3Ei-&~@tT zI^49Lm^+=TrI=h4h=W@jW{GjWd{_kVuSzAL6Pi@HKYYnnNbtcYdIRww+jY$(30=#p8*if(mzbvau z00#}4Qf+gH&ce_&8y3Z@CZV>b%&Zr7xuPSSqOmoaP@arwPrMx^jQBQQi>YvBUdpBn zI``MZ3I3HLqp)@vk^E|~)zw$0$VI_RPsL9u(kqulmS`tnb%4U)hm{)h@bG*jw@Y*#MX;Th1wu3TrO}Srn_+YWYesEgkO1 zv?P8uWB)is;#&=xBBLf+y5e4?%y>_8$1KwkAJ8UcW|0CIz89{LydfJKr^RF=JFPi}MAv|ecbuZ!YcTSxsD$(Pr#W*oytl?@+2 zXBFb32Kf_G3~EgOS7C`8w!tx}DcCT%+#qa76VSbnHo;4(oJ7)}mm?b5V65ir`7Z}s zR2)m15b#E}z_2@rf34wo!M^CnVoi# ze+S(IK({C6u=Sm{1>F~?)8t&fZpOOPcby;I3jO;7^xmLKM(<%i-nyj9mgw9F1Lq4|DZUHZ4)V9&6fQM(ZxbG{h+}(koiTu`SQw6#6q2Yg z-d+1+MRp$zYT2neIR2cKij2!R;C~ooQ3<;^8)_Gch&ZyEtiQwmF0Mb_)6)4lVEBF< zklXS7hvtu30uJR`3OzcqUNOdYsfrKSGkIQAk|4=&#ggxdU4^Y(;)$8}fQ>lTgQdJ{ zzie8+1$3@E;|a`kzuFh9Se}%RHTmBg)h$eH;gttjL_)pO^10?!bNev6{mLMaQpY<< z7M^ZXrg>tw;vU@9H=khbff?@nu)Yw4G% zGxobPTUR2p_ed7Lvx?dkrN^>Cv$Axuwk;Wj{5Z@#$sK@f4{7SHg%2bpcS{(~s;L(mz@9r$cK@m~ef&vf%1@ z@8&@LLO2lQso|bJD6}+_L1*D^}>oqg~$NipL>QlP3 zM#ATSy@ycMkKs5-0X8nFAtMhO_=$DlWR+@EaZ}`YduRD4A2@!at3NYRHmlENea9IF zN*s>mi?zy*Vv+F+&4-o`Wj}P3mLGM*&M(z|;?d82>hQkkY?e-hJ47mWOLCPL*MO04 z3lE(n2RM=IIo;Z?I=sKJ_h=iJHbQ2<}WW0b@I6Qf-{T=Qn#@N0yG5xH&ofEy^mZMPzd22nR`t!Q)VkNgf*VOxE z$XhOunG3ZN#`Ks$Hp~}`OX5vmHP={GYUJ+-g0%PS$*Qi5+-40M47zJ24vK1#? zb$s^%r?+>#lw$mpZaMa1aO%wlPm3~cno_(S%U&-R;6eK(@`CjswAW2)HfZ>ptItaZ|XqQ z&sHVVL>WCe|E4iPb2~gS5ITs6xfg(kmt&3$YcI=zTuqj37t|+9ojCr(G^ul#p{>k) zM94pI>~5VZ$!*Qurq<@RIXgP3sx-2kL$1Q~da%rnNIh?)&+c~*&e~CYPDhPYjb+Xu zKg5w^XB3(_9{Waa4E(-J-Kq_u6t_k?a8kEHqai-N-4#`SRerO!h}!cS%SMC<)tGix zOzVP^_t!HN&HIPL-ZpcgWitHM&yFRC7!k4zSI+-<_uQ}|tX)n{Ib;X>Xx>i_d*KkH zCzogKQFpP1408_2!ofU|iBq2R8hW6G zuqJs9Tyw{u%-uWczPLkM!MfKfflt+NK9Vk8E!C>AsJwNDRoe2~cL+UvqNP|5J8t)( z0$iMa!jhudJ+fqFn+um&@Oj6qXJd_3-l`S^I1#0fnt!z3?D*hAHr*u(*wR@`4O z#avrtg%s`Fh{?$FtBFM^$@@hW!8ZfF4;=n0<8In&X}-Rp=cd0TqT_ne46$j^r}FzE z26vX^!PzScuQfFfl1HEZ{zL?G88mcc76zHGizWiykBf4m83Z${So-+dZ~YGhm*RO7 zB1gdIdqnFi?qw+lPRFW5?}CQ3Me3G^muvll&4iN+*5#_mmIu;loULMwb4lu9U*dFM z-Sr**(0Ei~u=$3<6>C-G6z4_LNCx||6YtjS)<;hf)YJTPKXW+w%hhCTUAInIse9>r zl2YU6nRb$u-FJlWN*{{%sm_gi_UP5{=?5}5^D2vPzM=oPfNw~azZQ#P zl5z8RtSSiTIpEohC15i-Q1Bk{3&ElsD0uGAOxvbk29VUDmmA0w;^v`W#0`};O3DVE z&+-ca*`YcN%z*#VXWK9Qa-OEME#fykF%|7o=1Y+eF;Rtv0W4~kKRDx9YBHOWhC%^I z$Jec0cC7o37}Xt}cu)NH5R}NT+=2Nap*`^%O)vz?+{PV<2~qX%TzdJOGeKj5_QjqR&a3*K@= P-1+_A+?hGkL;m(J7kc&K diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 28c6bf03016f6c994b70f38d1b7346e5831b531f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 564 zcmV-40?Yl0P)Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f091b6b0bca859a3f474b03065bef75ba58a9e4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index d0ef06e7edb86cdfe0d15b4b0d98334a86163658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1716 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c8f9ed8f5cee1c98386d13b17e89f719e83555b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index a6d6b8609df07bf62e5100a53a01510388bd2b22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 75b2d164a5a98e212cca15ea7bf2ab5de5108680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3831 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index c4df70d39da7941ef3f6dcb7f06a192d8dcb308d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1888 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 iW8CFBundleInfoDictionaryVersion 6.0 CFBundleName - selfpass_mobile + selfpass_client CFBundlePackageType APPL CFBundleShortVersionString diff --git a/lib/main.dart b/lib/main.dart index d3d417d..898f434 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -60,7 +60,9 @@ class Selfpass extends StatelessWidget { break; case '/config': - final ConfigScreenArguments arguments = settings.arguments; + final ConfigScreenArguments arguments = settings.arguments == null + ? ConfigScreenArguments() + : settings.arguments; title = 'Configuration'; builder = (BuildContext context) => Config(arguments.connectionConfig, arguments.privateKey); diff --git a/lib/protobuf/google/protobuf/timestamp.pb.dart b/lib/protobuf/google/protobuf/timestamp.pb.dart index be02171..4cbf12f 100644 --- a/lib/protobuf/google/protobuf/timestamp.pb.dart +++ b/lib/protobuf/google/protobuf/timestamp.pb.dart @@ -4,25 +4,32 @@ /// // ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name -import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String; +import 'dart:core' as $core + show bool, Deprecated, double, int, List, Map, override, pragma, String; import 'package:fixnum/fixnum.dart'; import 'package:protobuf/protobuf.dart' as $pb; import 'dart:core' as $core show DateTime, Duration; + class Timestamp extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo('Timestamp', package: const $pb.PackageName('google.protobuf')) + static final $pb.BuilderInfo _i = $pb.BuilderInfo('Timestamp', + package: const $pb.PackageName('google.protobuf')) ..aInt64(1, 'seconds') ..a<$core.int>(2, 'nanos', $pb.PbFieldType.O3) - ..hasRequiredFields = false - ; + ..hasRequiredFields = false; Timestamp._() : super(); factory Timestamp() => create(); - factory Timestamp.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory Timestamp.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory Timestamp.fromBuffer($core.List<$core.int> i, + [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(i, r); + factory Timestamp.fromJson($core.String i, + [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(i, r); Timestamp clone() => Timestamp()..mergeFromMessage(this); - Timestamp copyWith(void Function(Timestamp) updates) => super.copyWith((message) => updates(message as Timestamp)); + Timestamp copyWith(void Function(Timestamp) updates) => + super.copyWith((message) => updates(message as Timestamp)); $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') static Timestamp create() => Timestamp._(); @@ -32,30 +39,36 @@ class Timestamp extends $pb.GeneratedMessage { static Timestamp _defaultInstance; Int64 get seconds => $_getI64(0); - set seconds(Int64 v) { $_setInt64(0, v); } + set seconds(Int64 v) { + $_setInt64(0, v); + } + $core.bool hasSeconds() => $_has(0); void clearSeconds() => clearField(1); $core.int get nanos => $_get(1, 0); - set nanos($core.int v) { $_setSignedInt32(1, v); } + set nanos($core.int v) { + $_setSignedInt32(1, v); + } + $core.bool hasNanos() => $_has(1); void clearNanos() => clearField(2); - /// Converts an instance to [DateTime]. - /// - /// The result is in UTC time zone and has microsecond precision, as - /// [DateTime] does not support nanosecond precision. - $core.DateTime toDateTime() => $core.DateTime.fromMicrosecondsSinceEpoch( - seconds.toInt() * $core.Duration.microsecondsPerSecond + nanos ~/ 1000, - isUtc: true); - /// Creates a new instance from [dateTime]. - /// - /// Time zone information will not be preserved. - static Timestamp fromDateTime($core.DateTime dateTime) { - $core.int micros = dateTime.microsecondsSinceEpoch; - return Timestamp() - ..seconds = Int64(micros ~/ $core.Duration.microsecondsPerSecond) - ..nanos = (micros % $core.Duration.microsecondsPerSecond).toInt() * 1000; - } + /// Converts an instance to [DateTime]. + /// + /// The result is in UTC time zone and has microsecond precision, as + /// [DateTime] does not support nanosecond precision. + $core.DateTime toDateTime() => $core.DateTime.fromMicrosecondsSinceEpoch( + seconds.toInt() * $core.Duration.microsecondsPerSecond + nanos ~/ 1000, + isUtc: true); + + /// Creates a new instance from [dateTime]. + /// + /// Time zone information will not be preserved. + static Timestamp fromDateTime($core.DateTime dateTime) { + $core.int micros = dateTime.microsecondsSinceEpoch; + return Timestamp() + ..seconds = Int64(micros ~/ $core.Duration.microsecondsPerSecond) + ..nanos = (micros % $core.Duration.microsecondsPerSecond).toInt() * 1000; + } } - diff --git a/lib/protobuf/google/protobuf/timestamp.pbjson.dart b/lib/protobuf/google/protobuf/timestamp.pbjson.dart index d7afdfb..a072d7e 100644 --- a/lib/protobuf/google/protobuf/timestamp.pbjson.dart +++ b/lib/protobuf/google/protobuf/timestamp.pbjson.dart @@ -11,4 +11,3 @@ const Timestamp$json = const { const {'1': 'nanos', '3': 2, '4': 1, '5': 5, '10': 'nanos'}, ], }; - diff --git a/lib/protobuf/service.pbjson.dart b/lib/protobuf/service.pbjson.dart index d97e434..0cfafe3 100644 --- a/lib/protobuf/service.pbjson.dart +++ b/lib/protobuf/service.pbjson.dart @@ -29,7 +29,14 @@ const UpdateRequest$json = const { '1': 'UpdateRequest', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'credential', '3': 2, '4': 1, '5': 11, '6': '.selfpass.credentials.CredentialRequest', '10': 'credential'}, + const { + '1': 'credential', + '3': 2, + '4': 1, + '5': 11, + '6': '.selfpass.credentials.CredentialRequest', + '10': 'credential' + }, ], }; @@ -48,8 +55,22 @@ const Metadata$json = const { '1': 'Metadata', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'created_at', '3': 2, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'createdAt'}, - const {'1': 'updated_at', '3': 3, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'updatedAt'}, + const { + '1': 'created_at', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'createdAt' + }, + const { + '1': 'updated_at', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'updatedAt' + }, const {'1': 'primary', '3': 4, '4': 1, '5': 9, '10': 'primary'}, const {'1': 'source_host', '3': 5, '4': 1, '5': 9, '10': 'sourceHost'}, const {'1': 'login_url', '3': 6, '4': 1, '5': 9, '10': 'loginUrl'}, @@ -61,8 +82,22 @@ const Credential$json = const { '1': 'Credential', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'created_at', '3': 2, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'createdAt'}, - const {'1': 'updated_at', '3': 3, '4': 1, '5': 11, '6': '.google.protobuf.Timestamp', '10': 'updatedAt'}, + const { + '1': 'created_at', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'createdAt' + }, + const { + '1': 'updated_at', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'updatedAt' + }, const {'1': 'primary', '3': 4, '4': 1, '5': 9, '10': 'primary'}, const {'1': 'username', '3': 5, '4': 1, '5': 9, '10': 'username'}, const {'1': 'email', '3': 6, '4': 1, '5': 9, '10': 'email'}, @@ -87,4 +122,3 @@ const CredentialRequest$json = const { const {'1': 'otp_secret', '3': 8, '4': 1, '5': 9, '10': 'otpSecret'}, ], }; - diff --git a/lib/repositories/config.dart b/lib/repositories/config.dart index 01e04ec..3da41df 100644 --- a/lib/repositories/config.dart +++ b/lib/repositories/config.dart @@ -12,11 +12,17 @@ class Config implements ConfigRepo { static const _keyConnectionConfig = "connection_config"; static const _keyPassword = "password"; final FlutterSecureStorage _storage = FlutterSecureStorage(); - var _passwordMatched = false; + bool _passwordMatched = false; + String _password; + + String get password { + _checkIfPasswordMatched(); + return _password; + } Future setPrivateKey(String key) { _checkIfPasswordMatched(); - return _storage.write(key: _keyPrivateKey, value: key); + return _storage.write(key: _keyPrivateKey, value: key.replaceAll('-', '')); } Future get privateKey { @@ -26,6 +32,7 @@ class Config implements ConfigRepo { Future setPassword(String password) { _checkIfPasswordMatched(); + _password = password; return _storage.write( key: _keyPassword, value: crypto.hashPassword(password)); } @@ -42,9 +49,16 @@ class Config implements ConfigRepo { return false; } - Future matchesPasswordHash(String password) async => - _passwordMatched = crypto.matchHashedPassword( - await _storage.read(key: _keyPassword), password); + Future matchesPasswordHash(String password) async { + _passwordMatched = crypto.matchHashedPassword( + await _storage.read(key: _keyPassword), password); + + if (_passwordMatched) { + _password = password; + } + + return _passwordMatched; + } Future setConnectionConfig(ConnectionConfig config) { _checkIfPasswordMatched(); diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart index cbf51c9..caac43c 100644 --- a/lib/screens/authentication.dart +++ b/lib/screens/authentication.dart @@ -105,10 +105,8 @@ class _AuthenticationState extends State { return () async { if (await _passwordIsSet) { if (await _config.matchesPasswordHash(_passwordController.text)) { - Navigator.of(context).pushReplacementNamed( - '/home', - arguments: await _config.connectionConfig, - ); + Navigator.of(context).pushReplacementNamed('/home', + arguments: await _config.connectionConfig); return; } diff --git a/lib/screens/credential.dart b/lib/screens/credential.dart index 1d4db71..74f05af 100644 --- a/lib/screens/credential.dart +++ b/lib/screens/credential.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; +import 'package:otp/otp.dart'; import '../types/credential.dart' as types; @@ -19,17 +20,14 @@ class _CredentialState extends State { Map _fieldMap; types.Credential _credential; - _CredentialState(this._credential) : super() { - _controllers = _CredentialControllers.fromCredential(_credential); - _fieldMap = _buildFieldMap(_controllers, _credential); - } + _CredentialState(this._credential) : super(); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar(), child: Container( - margin: const EdgeInsets.only(top: 30, left: 30), + padding: const EdgeInsets.only(top: 15, bottom: 30, left: 30), child: ListView( children: _buildFieldRows(context), ), @@ -43,12 +41,12 @@ class _CredentialState extends State { ) { final fieldMap = { 'Id:': _FieldBuildConfig(mutable: false, text: credential.meta.id), - 'Created: ': _FieldBuildConfig( + 'Created:': _FieldBuildConfig( mutable: false, copyable: false, text: credential.meta.createdAt.toString(), ), - 'Updated: ': _FieldBuildConfig( + 'Updated:': _FieldBuildConfig( mutable: false, copyable: false, text: credential.meta.updatedAt.toString(), @@ -69,15 +67,26 @@ class _CredentialState extends State { fieldMap['Email:'] = _FieldBuildConfig(controller: controllers.email); } + fieldMap['Password:'] = + _FieldBuildConfig(controller: controllers.password, obscured: true); + + if (credential.otpSecret != null && credential.otpSecret != '') { + fieldMap['OTP Secret:'] = _FieldBuildConfig( + controller: controllers.otpSecret, obscured: true, otp: true); + } + return fieldMap; } List _buildFieldRows(BuildContext context) { List rows = []; + _controllers = _CredentialControllers.fromCredential(_credential); + _fieldMap = _buildFieldMap(_controllers, _credential); + _fieldMap.forEach((key, value) { rows.add(Container( - margin: EdgeInsets.only(top: 10), + margin: EdgeInsets.only(top: 2.5), child: Text(key, style: TextStyle(fontWeight: FontWeight.w600)), )); @@ -85,20 +94,27 @@ class _CredentialState extends State { Expanded( flex: 3, child: value.mutable - ? TextField(maxLines: 1, controller: value.controller) + ? TextField( + maxLines: 1, + controller: value.controller, + obscure: value.obscured) : Container( margin: EdgeInsets.symmetric(vertical: 10), - child: Text(value.text), - ), + child: Text(value.text)), ), ]; if (value.copyable) { - widgets.add(Flexible( + widgets.add(Expanded( child: CupertinoButton( - child: Text('Copy'), + child: Text(value.otp ? 'OTP' : 'Copy'), onPressed: () => Clipboard.setData(ClipboardData( - text: value.mutable ? value.controller.text : value.text, + text: value.otp + ? OTP + .generateTOTPCode(value.controller.text, + DateTime.now().millisecondsSinceEpoch) + .toString() + : value.mutable ? value.controller.text : value.text, )), ), )); @@ -116,10 +132,14 @@ class _FieldBuildConfig { final String text; final bool mutable; final bool copyable; + final bool obscured; + final bool otp; const _FieldBuildConfig({ this.mutable = true, this.copyable = true, + this.obscured = false, + this.otp = false, this.controller, this.text, }); @@ -151,5 +171,7 @@ class _CredentialControllers { tag: TextEditingController(text: credential.meta.tag), username: TextEditingController(text: credential.username), email: TextEditingController(text: credential.email), + password: TextEditingController(text: credential.password), + otpSecret: TextEditingController(text: credential.otpSecret), ); } diff --git a/lib/screens/credentials.dart b/lib/screens/credentials.dart index 0c086ed..ab102ab 100644 --- a/lib/screens/credentials.dart +++ b/lib/screens/credentials.dart @@ -4,6 +4,8 @@ import 'package:provider/provider.dart'; import '../types/abstracts.dart'; import '../types/credential.dart'; +import '../utils/crypto.dart' as crypto; + import '../widgets/tappable_text_list.dart'; class Credentials extends StatelessWidget { @@ -20,10 +22,39 @@ class Credentials extends StatelessWidget { } Map _buildTappableText(BuildContext context) { - var makeOnTapHandler = (String id) => () async { - final credential = - await Provider.of(context).get(id); - Navigator.of(context).pushNamed('/credential', arguments: credential); + final makeOnTapHandler = (String id) => () async { + showCupertinoDialog( + context: context, + builder: (BuildContext context) => CupertinoAlertDialog( + content: Column( + children: [ + Text('Decrypting credential...'), + Container( + margin: EdgeInsets.only(top: 10), + child: CupertinoActivityIndicator()), + ], + )), + ); + + final config = Provider.of(context); + final client = Provider.of(context); + + final Future privateKey = config.privateKey; + final String password = config.password; + + final credential = await client.get(id); + + credential.password = crypto.decryptPassword( + password, await privateKey, credential.password); + + if (credential.otpSecret != null && credential.otpSecret != '') { + credential.otpSecret = crypto.decryptPassword( + password, await privateKey, credential.otpSecret); + } + + Navigator.of(context) + ..pop() + ..pushNamed('/credential', arguments: credential); }; Map tappableText = {}; diff --git a/lib/screens/home.dart b/lib/screens/home.dart index 06f63b9..cdccbc2 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -91,6 +91,7 @@ class _HomeState extends State { GestureTapCallback _makeConfigOnTapHandler(BuildContext context) { return () async => Navigator.of(context).pushNamed('/config', arguments: ConfigScreenArguments( - await _config.connectionConfig, await _config.privateKey)); + connectionConfig: await _config.connectionConfig, + privateKey: await _config.privateKey)); } } diff --git a/lib/types/abstracts.dart b/lib/types/abstracts.dart index 358322d..bae8c75 100644 --- a/lib/types/abstracts.dart +++ b/lib/types/abstracts.dart @@ -15,6 +15,7 @@ abstract class ConfigRepo { Future setPrivateKey(String key); Future get privateKey; + String get password; Future setPassword(String password); Future get passwordSet; Future matchesPasswordHash(String password); diff --git a/lib/types/screen_arguments.dart b/lib/types/screen_arguments.dart index 3f841a2..d7cd193 100644 --- a/lib/types/screen_arguments.dart +++ b/lib/types/screen_arguments.dart @@ -4,5 +4,5 @@ class ConfigScreenArguments { final ConnectionConfig connectionConfig; final String privateKey; - const ConfigScreenArguments(this.connectionConfig, this.privateKey); + const ConfigScreenArguments({this.connectionConfig, this.privateKey}); } diff --git a/lib/utils/crypto.dart b/lib/utils/crypto.dart index fea1395..ad572d6 100644 --- a/lib/utils/crypto.dart +++ b/lib/utils/crypto.dart @@ -1,11 +1,18 @@ import 'dart:math'; import 'dart:convert'; +import 'dart:typed_data'; import 'package:crypt/crypt.dart'; +import 'package:encrypt/encrypt.dart'; +import 'package:password_hash/password_hash.dart'; String hashPassword(String password) { + const saltSize = 16; + const saltIntMax = 256; + final random = Random.secure(); - final saltInts = List.generate(16, (_) => random.nextInt(256)); + final saltInts = + List.generate(saltSize, (_) => random.nextInt(saltIntMax)); final salt = base64.encode(saltInts); return Crypt.sha256(password, salt: salt).toString(); @@ -13,3 +20,23 @@ String hashPassword(String password) { bool matchHashedPassword(String hashedPassword, String password) => Crypt(hashedPassword).match(password); + +String decryptPassword(String masterpass, privateKey, ciphertext) { + final key = + PBKDF2().generateKey(masterpass, privateKey, pbkdf2Rounds, keySize); + + var cipherbytes = base64.decode(ciphertext); + final iv = + IV(Uint8List.fromList(cipherbytes.getRange(0, aesBlockSize).toList())); + + cipherbytes = Uint8List.fromList( + cipherbytes.getRange(aesBlockSize, cipherbytes.length).toList()); + + final encrypter = Encrypter(AES(Key(key), mode: AESMode.cbc)); + + return encrypter.decrypt(Encrypted(cipherbytes), iv: iv); +} + +const pbkdf2Rounds = 4096; +const keySize = 32; +const aesBlockSize = 16; diff --git a/lib/widgets/text_field.dart b/lib/widgets/text_field.dart index aa18e30..6ac2a24 100644 --- a/lib/widgets/text_field.dart +++ b/lib/widgets/text_field.dart @@ -7,6 +7,7 @@ typedef OnSubmittedBuilder = ValueChanged Function( class TextField extends StatelessWidget { final OnSubmittedBuilder onSubmittedBuilder; final TextEditingController controller; + final OverlayVisibilityMode clearButtonMode; final Widget prefix; final Widget suffix; final bool obscure; @@ -25,6 +26,7 @@ class TextField extends StatelessWidget { this.autocorrect = false, this.prefix, this.suffix, + this.clearButtonMode = OverlayVisibilityMode.editing, }); @override @@ -36,7 +38,7 @@ class TextField extends StatelessWidget { border: Border.all(color: CupertinoColors.black), borderRadius: const BorderRadius.all(Radius.circular(5.0)), ), - clearButtonMode: OverlayVisibilityMode.editing, + clearButtonMode: clearButtonMode, textAlign: TextAlign.start, onSubmitted: this.onSubmittedBuilder != null ? onSubmittedBuilder(context) diff --git a/pubspec.lock b/pubspec.lock index 672b612..af5081c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,5 +1,5 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: _discoveryapis_commons: dependency: transitive @@ -8,13 +8,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.8+1" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + asn1lib: + dependency: transitive + description: + name: asn1lib + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.8" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.2.0" + base32: + dependency: transitive + description: + name: base32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" boolean_selector: dependency: transitive description: @@ -64,6 +85,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.2" + encrypt: + dependency: "direct main" + description: + name: encrypt + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" fixnum: dependency: transitive description: @@ -144,6 +172,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.6" + otp: + dependency: "direct main" + description: + name: otp + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + password_hash: + dependency: "direct main" + description: + name: password_hash + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -157,7 +199,14 @@ packages: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.5.0" + version: "1.7.0" + pointycastle: + dependency: transitive + description: + name: pointycastle + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" protobuf: dependency: "direct main" description: @@ -178,7 +227,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" sky_engine: dependency: transitive description: flutter @@ -225,7 +274,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.4" + version: "0.2.5" typed_data: dependency: transitive description: @@ -241,4 +290,4 @@ packages: source: hosted version: "2.0.8" sdks: - dart: ">=2.2.0 <3.0.0" + dart: ">=2.2.2 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index b79df69..d3ef76f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,15 +30,17 @@ dependencies: crypt: ^1.0.7 flutter_secure_storage: ^3.2.1 - + password_hash: ^2.0.0 + encrypt: ^3.2.0 + + otp: ^1.0.3 + dev_dependencies: flutter_test: sdk: flutter - # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec # The following section is specific to Flutter. flutter: - diff --git a/test/widget_test.dart b/test/widget_test.dart index 99baf66..28613c3 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -8,12 +8,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:selfpass_mobile/main.dart'; +import 'package:selfpass_client/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(Selfpass()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); From 474f0c056bf3e69ec1d36477541d23d3f577181c Mon Sep 17 00:00:00 2001 From: mitchell Date: Thu, 11 Jul 2019 02:32:17 -0400 Subject: [PATCH 7/8] Add automatic background lock to home screen; refactor repo names --- ios/Podfile.lock | 4 +- ios/Runner.xcodeproj/project.pbxproj | 2 +- lib/main.dart | 13 ++--- ...ient.dart => grpc_credentials_client.dart} | 10 ++-- ...config.dart => secure_storage_config.dart} | 16 +++--- lib/screens/authentication.dart | 2 +- lib/screens/home.dart | 52 +++++++++++++++++-- lib/types/abstracts.dart | 2 +- pubspec.lock | 14 ----- pubspec.yaml | 3 +- 10 files changed, 74 insertions(+), 44 deletions(-) rename lib/repositories/{credentials_client.dart => grpc_credentials_client.dart} (87%) rename lib/repositories/{config.dart => secure_storage_config.dart} (88%) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f25d3cd..557bbc7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,12 +4,12 @@ PODS: - Flutter DEPENDENCIES: - - Flutter (from `.symlinks/flutter/ios-release`) + - Flutter (from `.symlinks/flutter/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) EXTERNAL SOURCES: Flutter: - :path: ".symlinks/flutter/ios-release" + :path: ".symlinks/flutter/ios" flutter_secure_storage: :path: ".symlinks/plugins/flutter_secure_storage/ios" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 8590272..3b9aebf 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -253,7 +253,7 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", + "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( diff --git a/lib/main.dart b/lib/main.dart index 898f434..4c84a88 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,8 @@ import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; -import 'repositories/credentials_client.dart'; -import 'repositories/config.dart' as repo; +import 'repositories/grpc_credentials_client.dart'; +import 'repositories/secure_storage_config.dart'; import 'screens/authentication.dart'; import 'screens/credential.dart'; @@ -19,7 +19,7 @@ class Selfpass extends StatelessWidget { @override Widget build(BuildContext context) { return Provider( - builder: (BuildContext context) => repo.Config(), + builder: (BuildContext context) => SecureStorageConfig(), child: CupertinoApp( title: 'Selfpass', onGenerateRoute: (RouteSettings settings) { @@ -36,7 +36,7 @@ class Selfpass extends StatelessWidget { title = 'Hosts'; builder = (BuildContext context) => Provider( builder: (BuildContext context) => - CredentialsClient.cached(config: settings.arguments), + GRPCCredentialsClient.cached(config: settings.arguments), child: Home(), ); break; @@ -45,7 +45,7 @@ class Selfpass extends StatelessWidget { title = 'Credentials'; builder = (BuildContext context) => Provider( builder: (BuildContext context) => - CredentialsClient.cached(), + GRPCCredentialsClient.cached(), child: Credentials(settings.arguments), ); break; @@ -54,7 +54,7 @@ class Selfpass extends StatelessWidget { title = 'Credential'; builder = (BuildContext context) => Provider( builder: (BuildContext context) => - CredentialsClient.cached(), + GRPCCredentialsClient.cached(), child: Credential(settings.arguments), ); break; @@ -63,6 +63,7 @@ class Selfpass extends StatelessWidget { final ConfigScreenArguments arguments = settings.arguments == null ? ConfigScreenArguments() : settings.arguments; + title = 'Configuration'; builder = (BuildContext context) => Config(arguments.connectionConfig, arguments.privateKey); diff --git a/lib/repositories/credentials_client.dart b/lib/repositories/grpc_credentials_client.dart similarity index 87% rename from lib/repositories/credentials_client.dart rename to lib/repositories/grpc_credentials_client.dart index a51de43..df1811f 100644 --- a/lib/repositories/credentials_client.dart +++ b/lib/repositories/grpc_credentials_client.dart @@ -11,11 +11,11 @@ import '../types/abstracts.dart'; import '../types/connection_config.dart'; import '../types/credential.dart'; -class CredentialsClient implements CredentialsRepo { - static CredentialsClient _cached; +class GRPCCredentialsClient implements CredentialsRepo { + static GRPCCredentialsClient _cached; grpc.CredentialServiceClient _client; - CredentialsClient(ConnectionConfig config) { + GRPCCredentialsClient(ConnectionConfig config) { final caCert = utf8.encode(config.caCertificate); final cert = utf8.encode(config.certificate); final privateCert = utf8.encode(config.privateCertificate); @@ -33,8 +33,8 @@ class CredentialsClient implements CredentialsRepo { )); } - factory CredentialsClient.cached({ConnectionConfig config}) => - _cached == null ? _cached = CredentialsClient(config) : _cached; + factory GRPCCredentialsClient.cached({ConnectionConfig config}) => + config == null ? _cached : _cached = GRPCCredentialsClient(config); Stream getAllMetadata(String sourceHost) { final request = grpc.GetAllMetadataRequest(); diff --git a/lib/repositories/config.dart b/lib/repositories/secure_storage_config.dart similarity index 88% rename from lib/repositories/config.dart rename to lib/repositories/secure_storage_config.dart index 3da41df..9d9c4cf 100644 --- a/lib/repositories/config.dart +++ b/lib/repositories/secure_storage_config.dart @@ -7,11 +7,13 @@ import '../types/connection_config.dart'; import '../utils/crypto.dart' as crypto; -class Config implements ConfigRepo { +class SecureStorageConfig implements ConfigRepo { static const _keyPrivateKey = "private_key"; static const _keyConnectionConfig = "connection_config"; static const _keyPassword = "password"; - final FlutterSecureStorage _storage = FlutterSecureStorage(); + + final _storage = FlutterSecureStorage(); + bool _passwordMatched = false; String _password; @@ -32,13 +34,15 @@ class Config implements ConfigRepo { Future setPassword(String password) { _checkIfPasswordMatched(); + _password = password; + return _storage.write( key: _keyPassword, value: crypto.hashPassword(password)); } - Future get passwordSet async { - var passHash = await _storage.read(key: _keyPassword); + Future get passwordIsSet async { + final passHash = await _storage.read(key: _keyPassword); if (passHash != null) { return true; @@ -53,9 +57,7 @@ class Config implements ConfigRepo { _passwordMatched = crypto.matchHashedPassword( await _storage.read(key: _keyPassword), password); - if (_passwordMatched) { - _password = password; - } + if (_passwordMatched) _password = password; return _passwordMatched; } diff --git a/lib/screens/authentication.dart b/lib/screens/authentication.dart index caac43c..f2da82f 100644 --- a/lib/screens/authentication.dart +++ b/lib/screens/authentication.dart @@ -22,7 +22,7 @@ class _AuthenticationState extends State { didChangeDependencies() { super.didChangeDependencies(); _config = Provider.of(context); - _passwordIsSet = _config.passwordSet; + _passwordIsSet = _config.passwordIsSet; } @override diff --git a/lib/screens/home.dart b/lib/screens/home.dart index cdccbc2..ce528c3 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; @@ -8,32 +10,56 @@ import '../types/screen_arguments.dart'; import '../widgets/tappable_text_list.dart'; class Home extends StatefulWidget { + const Home({Key key}) : super(key: key); + @override State createState() => _HomeState(); } -class _HomeState extends State { +class _HomeState extends State with WidgetsBindingObserver { CredentialsRepo _client; ConfigRepo _config; Future> _metadatas; + bool _stateIsPaused = false; + Timer _pausedStateTimer; @override - didChangeDependencies() { + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void didChangeDependencies() { super.didChangeDependencies(); _config = Provider.of(context); - _client = Provider.of(context); + _metadatas = _client.getAllMetadata('').toList(); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + _stateIsPaused = state == AppLifecycleState.paused; + + if (_stateIsPaused) { + _pausedStateTimer = _newPausedStateTimer(); + return; + } + + if (_pausedStateTimer != null) _pausedStateTimer.cancel(); + } + @override Widget build(BuildContext context) { return CupertinoPageScaffold( child: FutureBuilder>( future: _metadatas, - builder: (BuildContext context, - AsyncSnapshot> snapshot) => + builder: ( + BuildContext context, + AsyncSnapshot> snapshot, + ) => (snapshot.connectionState == ConnectionState.done) ? TappableTextList( tappableText: _buildTappableText(context, snapshot.data)) @@ -55,6 +81,22 @@ class _HomeState extends State { ); } + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + if (_pausedStateTimer != null) _pausedStateTimer.cancel(); + super.dispose(); + } + + Timer _newPausedStateTimer() { + const checkPeriod = 30; + + return Timer(Duration(seconds: checkPeriod), () { + Navigator.of(context) + .pushNamedAndRemoveUntil('/', ModalRoute.withName('/home')); + }); + } + Map _buildTappableText( BuildContext context, List metadatas, diff --git a/lib/types/abstracts.dart b/lib/types/abstracts.dart index bae8c75..b399efe 100644 --- a/lib/types/abstracts.dart +++ b/lib/types/abstracts.dart @@ -17,7 +17,7 @@ abstract class ConfigRepo { String get password; Future setPassword(String password); - Future get passwordSet; + Future get passwordIsSet; Future matchesPasswordHash(String password); Future setConnectionConfig(ConnectionConfig config); diff --git a/pubspec.lock b/pubspec.lock index af5081c..f46a501 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,13 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _discoveryapis_commons: - dependency: transitive - description: - name: _discoveryapis_commons - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.8+1" args: dependency: transitive description: @@ -116,13 +109,6 @@ packages: description: flutter source: sdk version: "0.0.0" - googleapis: - dependency: "direct main" - description: - name: googleapis - url: "https://pub.dartlang.org" - source: hosted - version: "0.53.0" googleapis_auth: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d3ef76f..b273453 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,7 +11,7 @@ description: The cross-platform Selfpass client. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 +version: 0.1.0 environment: sdk: ">=2.1.0 <3.0.0" @@ -24,7 +24,6 @@ dependencies: grpc: ^1.0.3 protobuf: ^0.13.12 - googleapis: ^0.53.0 provider: ^3.0.0 From 92f38b581074e4562102327b12425e3df4695e54 Mon Sep 17 00:00:00 2001 From: mitchell Date: Thu, 11 Jul 2019 02:38:54 -0400 Subject: [PATCH 8/8] Modify README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8bb04a..06bcb2c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # selfpass_client -This is the multi-platform native Selfpass client. +This is the multi-platform native Selfpass client built with the Flutter framework.