├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .metadata ├── 1.png ├── 4.png ├── 5.png ├── 6.png ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example ├── .gitignore ├── .metadata ├── .vscode │ └── launch.json ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── chizi │ │ │ │ │ └── thepeer_flutter_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ └── main.dart ├── macos │ └── Flutter │ │ ├── GeneratedPluginRegistrant.swift │ │ └── ephemeral │ │ ├── Flutter-Generated.xcconfig │ │ └── flutter_export_environment.sh ├── pubspec.lock ├── pubspec.yaml ├── test │ └── widget_test.dart └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ └── Icon-512.png │ ├── index.html │ └── manifest.json ├── lib ├── assets │ ├── fonts │ │ ├── Gilroy-Bold.ttf │ │ ├── Gilroy-Medium.ttf │ │ └── Gilroy-SemiBold.ttf │ └── images │ │ ├── close.svg │ │ ├── logo.png │ │ └── warning_badge.svg ├── src │ ├── const │ │ └── const.dart │ ├── model │ │ ├── the_peer_event_model.dart │ │ ├── thepeer_data.dart │ │ └── thepeer_success_model.dart │ ├── utils │ │ ├── colors.dart │ │ ├── css.dart │ │ ├── extensions.dart │ │ ├── functions.dart │ │ └── the_peer_error_view.dart │ ├── views │ │ ├── the_peer_checkout_view.dart │ │ ├── the_peer_direct_charge_view.dart │ │ ├── the_peer_error_view.dart │ │ └── the_peer_send_view.dart │ └── widgets │ │ ├── the_peer_button.dart │ │ ├── the_peer_loader.dart │ │ └── touchable_opacity.dart └── thepeer_flutter.dart ├── pubspec.lock ├── pubspec.yaml └── test └── flutter_thepeer_test.dart /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/publish.yml 2 | name: Publish to pub.dev 3 | 4 | on: 5 | push: 6 | branches: ["main"] 7 | tags: 8 | - "v[0-9]+.[0-9]+.[0-9]+*" # tag pattern on pub.dev: 'v' 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Clone repository 15 | uses: actions/checkout@v3 16 | 17 | - name: Install Dart 18 | uses: dart-lang/setup-dart@v1 19 | with: 20 | sdk: stable 21 | 22 | - name: Install Flutter 23 | uses: subosito/flutter-action@v2 24 | 25 | - name: Install dependencies 26 | run: flutter pub get 27 | 28 | - name: Analyze and fix issues 29 | run: dart fix --apply . 30 | 31 | - name: Prepare pub credentials 32 | run: | 33 | mkdir -p $XDG_CONFIG_HOME/dart/ 34 | cat < $XDG_CONFIG_HOME/dart/pub-credentials.json 35 | { 36 | "accessToken":"${{ secrets.PUB_OAUTH_ACCESS_TOKEN }}", 37 | "refreshToken":"${{ secrets.PUB_OAUTH_REFRESH_TOKEN }}", 38 | "idToken":"${{ secrets.PUB_OAUTH_ID_TOKEN }}", 39 | "tokenEndpoint":"https://accounts.google.com/o/oauth2/token", 40 | "scopes": [ "openid", "https://www.googleapis.com/auth/userinfo.email" ], 41 | "expiration": 1679810599352 42 | } 43 | EOF 44 | 45 | - name: Publish 46 | run: flutter pub publish --force 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: db6e2d8aa5bb9a0bd3e75fc7470268b5a56fd0b0 8 | channel: dev 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/1.png -------------------------------------------------------------------------------- /4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/4.png -------------------------------------------------------------------------------- /5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/5.png -------------------------------------------------------------------------------- /6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/6.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.0.11] 2 | Minor changes 3 | - Redirect external links to the browser 4 | - Changed widget height to fullscreen for better user experience 5 | - Removed reference to test/dev domain and created a dynamic base url 6 | 7 | Breaking changes 8 | - Migration from `WebView` to `WebViewWidget` 9 | - Replaced instances of `ThePeer` with `Thepeer` 10 | 11 | ## [2.0.10] 12 | Bumped up dependency versions 13 | 14 | ## [2.0.9] 15 | Added Checkout 16 | 17 | ## [2.0.8] 18 | 19 | Non Dismissible by default 20 | Fixed Scroll bug 21 | 22 | ## [2.0.7+8] 23 | 24 | Added JS Log override for package 25 | Minor Uri bug fix 26 | Long press bug fix 27 | Metadata bug fix 28 | Dismissible by default 29 | 30 | ## [2.0.7] 31 | 32 | Major refactor and fixes for JSCLientinterface and more 33 | 34 | ## [2.0.6+2] 35 | 36 | update readme 37 | minor bug fixes 38 | 39 | ## [2.0.4] 40 | 41 | Add direct charge + bug fixes 42 | 43 | ## [2.0.2] 44 | 45 | Add direct charge 46 | 47 | ## [2.0.0-beta.9] 48 | 49 | Add direct charge 50 | 51 | ## [2.0.0-beta.8] 52 | 53 | Revert to depend on web 54 | 55 | ## [2.0.0-beta.7] 56 | 57 | Fixed image cache bugs 58 | 59 | ## [2.0.0-beta.6] 60 | 61 | Fixed kobo conversion bugs 62 | 63 | ## [2.0.0-beta.4] 64 | 65 | Fixed all major bugs 66 | 67 | ## [2.0.0-beta.2] 68 | 69 | Major fixes 70 | 71 | ## [2.0.0-beta.1] 72 | 73 | Major refactor 74 | 75 | ## [1.0.6] 76 | 77 | fixed home url 78 | 79 | ## [1.0.5] 80 | 81 | refactor to thepeer 82 | 83 | ## [1.0.4] 84 | 85 | modify readme 86 | 87 | ## [1.0.3] 88 | 89 | modify description 90 | 91 | ## [1.0.2] 92 | 93 | version bump to 1.0.2 94 | 95 | ## [1.0.1] 96 | 97 | minor bug fixes 98 | 99 | ## [1.0.0] 100 | 101 | first release 102 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | tCopyright (c) 2021 Thepeer LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter Thepeer 2 | 3 | This package makes it easy to use the Thepeer in a flutter project. 4 | 5 | ## 📸 Screen Shots 6 | 7 |

8 | 9 | 10 | 11 | 12 |

13 | 14 | ### 🚀 How to Use plugin 15 | 16 | ### Adding MaterialSupport 17 | 18 | Add the dependency on Android’s Material in /android/app/build.gradle: 19 | 20 | ``` 21 | dependencies { 22 | // ... 23 | implementation 'com.google.android.material:material:' 24 | // ... 25 | } 26 | ``` 27 | 28 | ### Thepeer Send 29 | 30 | - Launch ThepeerSendView in a bottom_sheet 31 | 32 | ```dart 33 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 34 | 35 | void launch() async { 36 | await ThepeerSendView( 37 | data: ThepeerData( 38 | amount: 400000, 39 | publicKey: "pspk_one_more_thing", 40 | userReference: "stay-foolish-stay-hungry-forever", 41 | currency: 'NGN', 42 | meta: { 43 | "city": "San Fransisco", 44 | "state": "california" 45 | } 46 | ), 47 | showLogs: true, 48 | onClosed: () { 49 | print('closed'); 50 | Navigator.pop(context); 51 | }, 52 | onSuccess: (data) { 53 | print(data); // ThepeerSuccessModel 54 | Navigator.pop(context); 55 | }, 56 | onError: print, 57 | ).show(context); 58 | } 59 | ``` 60 | 61 | - Use ThepeerSendView widget 62 | 63 | ```dart 64 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 65 | 66 | ... 67 | 68 | ThepeerSendView( 69 | data: ThepeerData( 70 | amount: 10000, 71 | publicKey: "pspk_one_more_thing", 72 | userReference: "stay-foolish-stay-hungry-forever", 73 | currency: 'NGN', 74 | meta: { 75 | "city": "San Fransisco", 76 | "state": "california" 77 | } 78 | ), 79 | onClosed: () { 80 | Navigator.pop(context); 81 | print('Widget closed') 82 | }, 83 | onSuccess: (data) { 84 | print(data); // ThepeerSuccessModel 85 | Navigator.pop(context); 86 | }, 87 | onError: print, 88 | error: Text('Error'), 89 | ) 90 | 91 | ... 92 | 93 | ``` 94 | 95 | --- 96 | 97 | ### Thepeer DirectCharge 98 | 99 | - Launch ThepeerDirectChargeView in a bottom_sheet 100 | 101 | ```dart 102 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 103 | 104 | void launch() async { 105 | await ThepeerDirectChargeView( 106 | data: ThepeerData( 107 | amount: 10000, 108 | publicKey: "pspk_one_more_thing", 109 | userReference: "stay-foolish-stay-hungry-forever", 110 | currency: 'NGN', 111 | meta: { 112 | "city": "San Fransisco", 113 | "state": "california" 114 | } 115 | ), 116 | showLogs: true, 117 | onClosed: () { 118 | Navigator.pop(context); 119 | print('Widget closed'); 120 | }, 121 | onSuccess: () { 122 | print(data); 123 | Navigator.pop(context); 124 | }, 125 | onError: print, 126 | ).show(context); 127 | } 128 | ``` 129 | 130 | - Use ThepeerDirectChargeView widget 131 | 132 | ```dart 133 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 134 | 135 | ... 136 | 137 | await ThepeerDirectChargeView( 138 | data: ThepeerData( 139 | amount: 10000, 140 | publicKey: "pspk_one_more_thing", 141 | userReference: "stay-foolish-stay-hungry-forever", 142 | currency: 'NGN' 143 | meta: { 144 | "city": "San Fransisco", 145 | "state": "california" 146 | } 147 | ), 148 | showLogs: true, 149 | onClosed: () { 150 | Navigator.pop(context); 151 | print('Widget closed') 152 | }, 153 | onSuccess: (data) { 154 | print(data); // ThepeerSuccessModel 155 | Navigator.pop(context); 156 | }, 157 | onError: print, 158 | ) 159 | 160 | ... 161 | 162 | ``` 163 | 164 | --- 165 | 166 | ### Thepeer Checkout 167 | 168 | - Launch ThepeerCheckoutView in a bottom_sheet 169 | 170 | ```dart 171 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 172 | 173 | void launch() async { 174 | await ThepeerCheckoutView( 175 | data: ThepeerData( 176 | amount: 10000, 177 | publicKey: "pspk_one_more_thing", 178 | userReference: "stay-foolish-stay-hungry-forever", 179 | currency: 'NGN', 180 | meta: { 181 | "city": "San Fransisco", 182 | "state": "california" 183 | } 184 | ), 185 | showLogs: true, 186 | onClosed: () { 187 | Navigator.pop(context); 188 | print('Widget closed') 189 | }, 190 | onSuccess: () { 191 | print(data); // ThepeerSuccessModel 192 | Navigator.pop(context); 193 | }, 194 | onError: print, 195 | ).show(context); 196 | } 197 | ``` 198 | 199 | - Use ThepeerCheckoutView widget 200 | 201 | ```dart 202 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 203 | 204 | ... 205 | 206 | await ThepeerCheckoutView( 207 | data: ThepeerData( 208 | amount: 10000, 209 | publicKey: "pspk_one_more_thing", 210 | userReference: "stay-foolish-stay-hungry-forever", 211 | currency: 'NGN' 212 | meta: { 213 | "city": "San Fransisco", 214 | "state": "california" 215 | } 216 | ), 217 | showLogs: true, 218 | onClosed: () { 219 | Navigator.pop(context); 220 | print('Widget closed') 221 | }, 222 | onSuccess: (data) { 223 | print(data); // ThepeerSuccessModel 224 | Navigator.pop(context); 225 | }, 226 | onError: print, 227 | ) 228 | 229 | ... 230 | 231 | ``` 232 | 233 | ## Configuration Options 234 | 235 | - [`publicKey`](#publicKey) 236 | - [`userReference`](#userReference) 237 | - [`amount`](#amount) 238 | - [`onSuccess`](#onSuccess) 239 | - [`onError`](#onError) 240 | - [`onClose`](#onClose) 241 | - [`meta`](#meta) 242 | 243 | ### `publicKey` 244 | 245 | **String: required** 246 | 247 | Your public key can be found on your [dashboard](https://dashboard.thepeer.co) settings. 248 | 249 | ### `userReference` 250 | 251 | **String: required** 252 | 253 | The user reference returned by Thepeer API when a user has been indexed 254 | 255 | ### `amount` 256 | 257 | **String: required** 258 | 259 | The amount you intend to send in kobo 260 | 261 | ### `currency` 262 | 263 | **String: required** 264 | 265 | The currency of the `amount` to be paid 266 | 267 | ### `onSuccess` 268 | 269 | **(ThepeerSuccessModel) =>: optional** 270 | 271 | `returns ThepeerSuccessModel` 272 | 273 | This is called when a transaction is successfully. It returns a response with event type and transaction details. 274 | 275 | See the [event details](#thepeerEvent) below. 276 | 277 | ### `onError ` 278 | 279 | **VoidCallback: optional** 280 | 281 | `returns dynamic` 282 | 283 | This is called when a transaction fails. It returns a response with event type 284 | 285 | See the [event details](#thepeerEvent) below. 286 | 287 | ### `onClose ` 288 | 289 | **VoidCallback: optional** 290 | 291 | This is called when a user clicks on the close button. 292 | 293 | ### `meta` 294 | 295 | **Map: optional** 296 | This object should contain additional/optional attributes you would like to have on your transaction response 297 | 298 | #### `transaction: ThepeerSuccessModel` 299 | 300 | The transaction ThepeerSuccessModel object returned from the success events. 301 | 302 | ## ✨ Contribution 303 | 304 | Lots of PR's would be needed to improve this plugin. So lots of suggestions and PRs are welcome. 305 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: db6e2d8aa5bb9a0bd3e75fc7470268b5a56fd0b0 8 | channel: dev 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "example", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "example (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 29 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.chizi.thepeer_flutter_example" 42 | minSdkVersion 19 43 | targetSdkVersion 29 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | implementation 'com.google.android.material:material:1.0.0' 64 | } 65 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 10 | 17 | 21 | 25 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/chizi/thepeer_flutter_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.chizi.thepeer_flutter_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - connectivity_plus (0.0.1): 3 | - Flutter 4 | - ReachabilitySwift 5 | - Flutter (1.0.0) 6 | - ReachabilitySwift (5.0.0) 7 | - url_launcher (0.0.1): 8 | - Flutter 9 | - webview_flutter_wkwebview (0.0.1): 10 | - Flutter 11 | 12 | DEPENDENCIES: 13 | - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) 14 | - Flutter (from `Flutter`) 15 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`) 16 | - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) 17 | 18 | SPEC REPOS: 19 | trunk: 20 | - ReachabilitySwift 21 | 22 | EXTERNAL SOURCES: 23 | connectivity_plus: 24 | :path: ".symlinks/plugins/connectivity_plus/ios" 25 | Flutter: 26 | :path: Flutter 27 | url_launcher: 28 | :path: ".symlinks/plugins/url_launcher/ios" 29 | webview_flutter_wkwebview: 30 | :path: ".symlinks/plugins/webview_flutter_wkwebview/ios" 31 | 32 | SPEC CHECKSUMS: 33 | connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e 34 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a 35 | ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 36 | url_launcher: b6e016d912f04be9f5bf6e8e82dc599b7ba59649 37 | webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162 38 | 39 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c 40 | 41 | COCOAPODS: 1.11.2 42 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 8FCB448E340C9A1B9EACCEF9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C661E4141BEFA2A86FE280F /* Pods_Runner.framework */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = ""; 24 | dstSubfolderSpec = 10; 25 | files = ( 26 | ); 27 | name = "Embed Frameworks"; 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXCopyFilesBuildPhase section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 35 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 36 | 6C661E4141BEFA2A86FE280F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 38 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 40 | 870866C041C92891C3AAF9B1 /* 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 = ""; }; 41 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 42 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 43 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | A2859C688AC44105F847E09D /* 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 = ""; }; 49 | BDF8BDE7CC79A33A91E13610 /* 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 = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | 8FCB448E340C9A1B9EACCEF9 /* Pods_Runner.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 211A509C4A741156CBE3147C /* Frameworks */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 6C661E4141BEFA2A86FE280F /* Pods_Runner.framework */, 68 | ); 69 | name = Frameworks; 70 | sourceTree = ""; 71 | }; 72 | 9740EEB11CF90186004384FC /* Flutter */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 76 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 77 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 78 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 79 | ); 80 | name = Flutter; 81 | sourceTree = ""; 82 | }; 83 | 97C146E51CF9000F007C117D = { 84 | isa = PBXGroup; 85 | children = ( 86 | 9740EEB11CF90186004384FC /* Flutter */, 87 | 97C146F01CF9000F007C117D /* Runner */, 88 | 97C146EF1CF9000F007C117D /* Products */, 89 | CD0B5DF9B63B28AD5B505F5D /* Pods */, 90 | 211A509C4A741156CBE3147C /* Frameworks */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | 97C146EF1CF9000F007C117D /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 97C146EE1CF9000F007C117D /* Runner.app */, 98 | ); 99 | name = Products; 100 | sourceTree = ""; 101 | }; 102 | 97C146F01CF9000F007C117D /* Runner */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 106 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 107 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 108 | 97C147021CF9000F007C117D /* Info.plist */, 109 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 110 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 111 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 112 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 113 | ); 114 | path = Runner; 115 | sourceTree = ""; 116 | }; 117 | CD0B5DF9B63B28AD5B505F5D /* Pods */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | A2859C688AC44105F847E09D /* Pods-Runner.debug.xcconfig */, 121 | 870866C041C92891C3AAF9B1 /* Pods-Runner.release.xcconfig */, 122 | BDF8BDE7CC79A33A91E13610 /* Pods-Runner.profile.xcconfig */, 123 | ); 124 | path = Pods; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 97C146ED1CF9000F007C117D /* Runner */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 133 | buildPhases = ( 134 | 3AD31F39BD38CC9065F437B4 /* [CP] Check Pods Manifest.lock */, 135 | 9740EEB61CF901F6004384FC /* Run Script */, 136 | 97C146EA1CF9000F007C117D /* Sources */, 137 | 97C146EB1CF9000F007C117D /* Frameworks */, 138 | 97C146EC1CF9000F007C117D /* Resources */, 139 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 140 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 141 | D49B7B106A25EFC0970CC3D3 /* [CP] Embed Pods Frameworks */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | ); 147 | name = Runner; 148 | productName = Runner; 149 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 150 | productType = "com.apple.product-type.application"; 151 | }; 152 | /* End PBXNativeTarget section */ 153 | 154 | /* Begin PBXProject section */ 155 | 97C146E61CF9000F007C117D /* Project object */ = { 156 | isa = PBXProject; 157 | attributes = { 158 | LastUpgradeCheck = 1300; 159 | ORGANIZATIONNAME = ""; 160 | TargetAttributes = { 161 | 97C146ED1CF9000F007C117D = { 162 | CreatedOnToolsVersion = 7.3.1; 163 | LastSwiftMigration = 1100; 164 | }; 165 | }; 166 | }; 167 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 168 | compatibilityVersion = "Xcode 9.3"; 169 | developmentRegion = en; 170 | hasScannedForEncodings = 0; 171 | knownRegions = ( 172 | en, 173 | Base, 174 | ); 175 | mainGroup = 97C146E51CF9000F007C117D; 176 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 177 | projectDirPath = ""; 178 | projectRoot = ""; 179 | targets = ( 180 | 97C146ED1CF9000F007C117D /* Runner */, 181 | ); 182 | }; 183 | /* End PBXProject section */ 184 | 185 | /* Begin PBXResourcesBuildPhase section */ 186 | 97C146EC1CF9000F007C117D /* Resources */ = { 187 | isa = PBXResourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 191 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 192 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 193 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXResourcesBuildPhase section */ 198 | 199 | /* Begin PBXShellScriptBuildPhase section */ 200 | 3AD31F39BD38CC9065F437B4 /* [CP] Check Pods Manifest.lock */ = { 201 | isa = PBXShellScriptBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | ); 205 | inputFileListPaths = ( 206 | ); 207 | inputPaths = ( 208 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 209 | "${PODS_ROOT}/Manifest.lock", 210 | ); 211 | name = "[CP] Check Pods Manifest.lock"; 212 | outputFileListPaths = ( 213 | ); 214 | outputPaths = ( 215 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | shellPath = /bin/sh; 219 | 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"; 220 | showEnvVarsInLog = 0; 221 | }; 222 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 223 | isa = PBXShellScriptBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | ); 227 | inputPaths = ( 228 | ); 229 | name = "Thin Binary"; 230 | outputPaths = ( 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | shellPath = /bin/sh; 234 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 235 | }; 236 | 9740EEB61CF901F6004384FC /* Run Script */ = { 237 | isa = PBXShellScriptBuildPhase; 238 | buildActionMask = 2147483647; 239 | files = ( 240 | ); 241 | inputPaths = ( 242 | ); 243 | name = "Run Script"; 244 | outputPaths = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | shellPath = /bin/sh; 248 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 249 | }; 250 | D49B7B106A25EFC0970CC3D3 /* [CP] Embed Pods Frameworks */ = { 251 | isa = PBXShellScriptBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | inputFileListPaths = ( 256 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 257 | ); 258 | name = "[CP] Embed Pods Frameworks"; 259 | outputFileListPaths = ( 260 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | shellPath = /bin/sh; 264 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 265 | showEnvVarsInLog = 0; 266 | }; 267 | /* End PBXShellScriptBuildPhase section */ 268 | 269 | /* Begin PBXSourcesBuildPhase section */ 270 | 97C146EA1CF9000F007C117D /* Sources */ = { 271 | isa = PBXSourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 275 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | /* End PBXSourcesBuildPhase section */ 280 | 281 | /* Begin PBXVariantGroup section */ 282 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 283 | isa = PBXVariantGroup; 284 | children = ( 285 | 97C146FB1CF9000F007C117D /* Base */, 286 | ); 287 | name = Main.storyboard; 288 | sourceTree = ""; 289 | }; 290 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 291 | isa = PBXVariantGroup; 292 | children = ( 293 | 97C147001CF9000F007C117D /* Base */, 294 | ); 295 | name = LaunchScreen.storyboard; 296 | sourceTree = ""; 297 | }; 298 | /* End PBXVariantGroup section */ 299 | 300 | /* Begin XCBuildConfiguration section */ 301 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 302 | isa = XCBuildConfiguration; 303 | buildSettings = { 304 | ALWAYS_SEARCH_USER_PATHS = NO; 305 | CLANG_ANALYZER_NONNULL = YES; 306 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 307 | CLANG_CXX_LIBRARY = "libc++"; 308 | CLANG_ENABLE_MODULES = YES; 309 | CLANG_ENABLE_OBJC_ARC = YES; 310 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_COMMA = YES; 313 | CLANG_WARN_CONSTANT_CONVERSION = YES; 314 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INFINITE_RECURSION = YES; 319 | CLANG_WARN_INT_CONVERSION = YES; 320 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 321 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 322 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 323 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 324 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 325 | CLANG_WARN_STRICT_PROTOTYPES = YES; 326 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 327 | CLANG_WARN_UNREACHABLE_CODE = YES; 328 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 329 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 330 | COPY_PHASE_STRIP = NO; 331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 332 | ENABLE_NS_ASSERTIONS = NO; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | GCC_C_LANGUAGE_STANDARD = gnu99; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 343 | MTL_ENABLE_DEBUG_INFO = NO; 344 | SDKROOT = iphoneos; 345 | SUPPORTED_PLATFORMS = iphoneos; 346 | TARGETED_DEVICE_FAMILY = "1,2"; 347 | VALIDATE_PRODUCT = YES; 348 | }; 349 | name = Profile; 350 | }; 351 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 352 | isa = XCBuildConfiguration; 353 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 354 | buildSettings = { 355 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 356 | CLANG_ENABLE_MODULES = YES; 357 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 358 | DEVELOPMENT_TEAM = X7RF9AP744; 359 | ENABLE_BITCODE = NO; 360 | FRAMEWORK_SEARCH_PATHS = ( 361 | "$(inherited)", 362 | "$(PROJECT_DIR)/Flutter", 363 | ); 364 | INFOPLIST_FILE = Runner/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = ( 366 | "$(inherited)", 367 | "@executable_path/Frameworks", 368 | ); 369 | LIBRARY_SEARCH_PATHS = ( 370 | "$(inherited)", 371 | "$(PROJECT_DIR)/Flutter", 372 | ); 373 | PRODUCT_BUNDLE_IDENTIFIER = com.chizi.thepeer_flutter_example; 374 | PRODUCT_NAME = "$(TARGET_NAME)"; 375 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 376 | SWIFT_VERSION = 5.0; 377 | VERSIONING_SYSTEM = "apple-generic"; 378 | }; 379 | name = Profile; 380 | }; 381 | 97C147031CF9000F007C117D /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | ALWAYS_SEARCH_USER_PATHS = NO; 385 | CLANG_ANALYZER_NONNULL = YES; 386 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 387 | CLANG_CXX_LIBRARY = "libc++"; 388 | CLANG_ENABLE_MODULES = YES; 389 | CLANG_ENABLE_OBJC_ARC = YES; 390 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 391 | CLANG_WARN_BOOL_CONVERSION = YES; 392 | CLANG_WARN_COMMA = YES; 393 | CLANG_WARN_CONSTANT_CONVERSION = YES; 394 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_EMPTY_BODY = YES; 397 | CLANG_WARN_ENUM_CONVERSION = YES; 398 | CLANG_WARN_INFINITE_RECURSION = YES; 399 | CLANG_WARN_INT_CONVERSION = YES; 400 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 401 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 402 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 404 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 405 | CLANG_WARN_STRICT_PROTOTYPES = YES; 406 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 407 | CLANG_WARN_UNREACHABLE_CODE = YES; 408 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 409 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 410 | COPY_PHASE_STRIP = NO; 411 | DEBUG_INFORMATION_FORMAT = dwarf; 412 | ENABLE_STRICT_OBJC_MSGSEND = YES; 413 | ENABLE_TESTABILITY = YES; 414 | GCC_C_LANGUAGE_STANDARD = gnu99; 415 | GCC_DYNAMIC_NO_PIC = NO; 416 | GCC_NO_COMMON_BLOCKS = YES; 417 | GCC_OPTIMIZATION_LEVEL = 0; 418 | GCC_PREPROCESSOR_DEFINITIONS = ( 419 | "DEBUG=1", 420 | "$(inherited)", 421 | ); 422 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 423 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 424 | GCC_WARN_UNDECLARED_SELECTOR = YES; 425 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 426 | GCC_WARN_UNUSED_FUNCTION = YES; 427 | GCC_WARN_UNUSED_VARIABLE = YES; 428 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 429 | MTL_ENABLE_DEBUG_INFO = YES; 430 | ONLY_ACTIVE_ARCH = YES; 431 | SDKROOT = iphoneos; 432 | TARGETED_DEVICE_FAMILY = "1,2"; 433 | }; 434 | name = Debug; 435 | }; 436 | 97C147041CF9000F007C117D /* Release */ = { 437 | isa = XCBuildConfiguration; 438 | buildSettings = { 439 | ALWAYS_SEARCH_USER_PATHS = NO; 440 | CLANG_ANALYZER_NONNULL = YES; 441 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 442 | CLANG_CXX_LIBRARY = "libc++"; 443 | CLANG_ENABLE_MODULES = YES; 444 | CLANG_ENABLE_OBJC_ARC = YES; 445 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 446 | CLANG_WARN_BOOL_CONVERSION = YES; 447 | CLANG_WARN_COMMA = YES; 448 | CLANG_WARN_CONSTANT_CONVERSION = YES; 449 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 451 | CLANG_WARN_EMPTY_BODY = YES; 452 | CLANG_WARN_ENUM_CONVERSION = YES; 453 | CLANG_WARN_INFINITE_RECURSION = YES; 454 | CLANG_WARN_INT_CONVERSION = YES; 455 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 456 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 457 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 458 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 459 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 460 | CLANG_WARN_STRICT_PROTOTYPES = YES; 461 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 462 | CLANG_WARN_UNREACHABLE_CODE = YES; 463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 465 | COPY_PHASE_STRIP = NO; 466 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 467 | ENABLE_NS_ASSERTIONS = NO; 468 | ENABLE_STRICT_OBJC_MSGSEND = YES; 469 | GCC_C_LANGUAGE_STANDARD = gnu99; 470 | GCC_NO_COMMON_BLOCKS = YES; 471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 473 | GCC_WARN_UNDECLARED_SELECTOR = YES; 474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 475 | GCC_WARN_UNUSED_FUNCTION = YES; 476 | GCC_WARN_UNUSED_VARIABLE = YES; 477 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 478 | MTL_ENABLE_DEBUG_INFO = NO; 479 | SDKROOT = iphoneos; 480 | SUPPORTED_PLATFORMS = iphoneos; 481 | SWIFT_COMPILATION_MODE = wholemodule; 482 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 483 | TARGETED_DEVICE_FAMILY = "1,2"; 484 | VALIDATE_PRODUCT = YES; 485 | }; 486 | name = Release; 487 | }; 488 | 97C147061CF9000F007C117D /* Debug */ = { 489 | isa = XCBuildConfiguration; 490 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 491 | buildSettings = { 492 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 493 | CLANG_ENABLE_MODULES = YES; 494 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 495 | DEVELOPMENT_TEAM = X7RF9AP744; 496 | ENABLE_BITCODE = NO; 497 | FRAMEWORK_SEARCH_PATHS = ( 498 | "$(inherited)", 499 | "$(PROJECT_DIR)/Flutter", 500 | ); 501 | INFOPLIST_FILE = Runner/Info.plist; 502 | LD_RUNPATH_SEARCH_PATHS = ( 503 | "$(inherited)", 504 | "@executable_path/Frameworks", 505 | ); 506 | LIBRARY_SEARCH_PATHS = ( 507 | "$(inherited)", 508 | "$(PROJECT_DIR)/Flutter", 509 | ); 510 | PRODUCT_BUNDLE_IDENTIFIER = com.chizi.thepeer_flutter_example; 511 | PRODUCT_NAME = "$(TARGET_NAME)"; 512 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 513 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 514 | SWIFT_VERSION = 5.0; 515 | VERSIONING_SYSTEM = "apple-generic"; 516 | }; 517 | name = Debug; 518 | }; 519 | 97C147071CF9000F007C117D /* Release */ = { 520 | isa = XCBuildConfiguration; 521 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 522 | buildSettings = { 523 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 524 | CLANG_ENABLE_MODULES = YES; 525 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 526 | DEVELOPMENT_TEAM = X7RF9AP744; 527 | ENABLE_BITCODE = NO; 528 | FRAMEWORK_SEARCH_PATHS = ( 529 | "$(inherited)", 530 | "$(PROJECT_DIR)/Flutter", 531 | ); 532 | INFOPLIST_FILE = Runner/Info.plist; 533 | LD_RUNPATH_SEARCH_PATHS = ( 534 | "$(inherited)", 535 | "@executable_path/Frameworks", 536 | ); 537 | LIBRARY_SEARCH_PATHS = ( 538 | "$(inherited)", 539 | "$(PROJECT_DIR)/Flutter", 540 | ); 541 | PRODUCT_BUNDLE_IDENTIFIER = com.chizi.thepeer_flutter_example; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 544 | SWIFT_VERSION = 5.0; 545 | VERSIONING_SYSTEM = "apple-generic"; 546 | }; 547 | name = Release; 548 | }; 549 | /* End XCBuildConfiguration section */ 550 | 551 | /* Begin XCConfigurationList section */ 552 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 553 | isa = XCConfigurationList; 554 | buildConfigurations = ( 555 | 97C147031CF9000F007C117D /* Debug */, 556 | 97C147041CF9000F007C117D /* Release */, 557 | 249021D3217E4FDB00AE95B9 /* Profile */, 558 | ); 559 | defaultConfigurationIsVisible = 0; 560 | defaultConfigurationName = Release; 561 | }; 562 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 563 | isa = XCConfigurationList; 564 | buildConfigurations = ( 565 | 97C147061CF9000F007C117D /* Debug */, 566 | 97C147071CF9000F007C117D /* Release */, 567 | 249021D4217E4FDB00AE95B9 /* Profile */, 568 | ); 569 | defaultConfigurationIsVisible = 0; 570 | defaultConfigurationName = Release; 571 | }; 572 | /* End XCConfigurationList section */ 573 | }; 574 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 575 | } 576 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | 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. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UIBackgroundModes 31 | 32 | fetch 33 | processing 34 | 35 | UILaunchStoryboardName 36 | LaunchScreen 37 | UIMainStoryboardFile 38 | Main 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UIInterfaceOrientationPortrait 48 | UIInterfaceOrientationPortraitUpsideDown 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:thepeer_flutter/thepeer_flutter.dart'; 5 | 6 | void main() { 7 | runApp(MyApp()); 8 | } 9 | 10 | class MyApp extends StatelessWidget { 11 | // This widget is the root of your application. 12 | @override 13 | Widget build(BuildContext context) { 14 | return AnnotatedRegion( 15 | value: SystemUiOverlayStyle( 16 | statusBarColor: Colors.transparent, 17 | systemNavigationBarColor: Colors.white, 18 | ), 19 | child: MaterialApp( 20 | title: 'Thepeer Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | debugShowCheckedModeBanner: false, 25 | home: MyHomePage(title: 'Thepeer Demo'), 26 | ), 27 | ); 28 | } 29 | } 30 | 31 | class MyHomePage extends StatefulWidget { 32 | MyHomePage({Key? key, this.title}) : super(key: key); 33 | 34 | final String? title; 35 | 36 | @override 37 | _MyHomePageState createState() => _MyHomePageState(); 38 | } 39 | 40 | class _MyHomePageState extends State { 41 | @override 42 | Widget build(BuildContext context) { 43 | return CupertinoPageScaffold( 44 | navigationBar: CupertinoNavigationBar( 45 | middle: Text( 46 | widget.title ?? '', 47 | style: TextStyle( 48 | color: Colors.black, 49 | fontSize: 18, 50 | ), 51 | ), 52 | backgroundColor: Colors.white, 53 | ), 54 | backgroundColor: Colors.white, 55 | child: Center( 56 | child: Column( 57 | mainAxisAlignment: MainAxisAlignment.center, 58 | children: [ 59 | const SizedBox(height: 60), 60 | Column( 61 | mainAxisAlignment: MainAxisAlignment.center, 62 | children: [ 63 | Container( 64 | height: 60, 65 | margin: EdgeInsets.symmetric(horizontal: 30), 66 | child: CupertinoButton( 67 | color: Colors.green, 68 | child: Center( 69 | child: Text( 70 | 'Launch Checkout', 71 | style: TextStyle( 72 | color: Colors.white, 73 | fontSize: 13, 74 | fontWeight: FontWeight.bold, 75 | ), 76 | ), 77 | ), 78 | onPressed: () async { 79 | await ThepeerCheckoutView( 80 | email: 'test@gmail.com', 81 | data: ThepeerData( 82 | publicKey: 83 | "pspk_test_2aj8xasztf4domzd2nphinvzkvecpbuyxldkvr3pkuvko", 84 | amount: 400000, 85 | userReference: "73f03de5-1043-4ad1-bc2e-aa4d94ebee4f", 86 | currency: 'NGN', 87 | meta: { 88 | 'slug': 'F1rstm3ssag!ngSl0g', 89 | 'type': 'chat', 90 | 'paymentType': 'subscription', 91 | 'channel': 'thePeer', 92 | }, 93 | ), 94 | showLogs: true, 95 | onClosed: () { 96 | print('closed'); 97 | Navigator.pop(context); 98 | }, 99 | onSuccess: (v) { 100 | print(v.toString()); 101 | Navigator.pop(context); 102 | }, 103 | onError: print, 104 | ).show(context); 105 | }, 106 | ), 107 | ), 108 | const SizedBox(height: 60), 109 | Container( 110 | height: 60, 111 | margin: EdgeInsets.symmetric(horizontal: 30), 112 | child: CupertinoButton( 113 | color: thepeerColor, 114 | child: Center( 115 | child: Text( 116 | 'Launch Send', 117 | style: TextStyle( 118 | color: Colors.white, 119 | fontSize: 13, 120 | fontWeight: FontWeight.bold, 121 | ), 122 | ), 123 | ), 124 | onPressed: () async { 125 | await ThepeerSendView( 126 | data: ThepeerData( 127 | publicKey: 128 | "pspk_test_2aj8xasztf4domzd2nphinvzkvecpbuyxldkvr3pkuvko", 129 | amount: 400000, 130 | userReference: "73f03de5-1043-4ad1-bc2e-aa4d94ebee4f", 131 | currency: 'NGN', 132 | meta: { 133 | 'slug': 'F1rstm3ssag!ngSl0g', 134 | 'type': 'chat', 135 | 'paymentType': 'subscription', 136 | 'channel': 'thePeer', 137 | }, 138 | ), 139 | showLogs: true, 140 | onClosed: () { 141 | print('closed'); 142 | Navigator.pop(context); 143 | }, 144 | onSuccess: (v) { 145 | print(v.toString()); 146 | Navigator.pop(context); 147 | }, 148 | onError: print, 149 | ).show(context); 150 | }, 151 | ), 152 | ), 153 | const SizedBox(height: 60), 154 | Container( 155 | height: 60, 156 | margin: EdgeInsets.symmetric(horizontal: 30), 157 | child: CupertinoButton( 158 | color: Colors.black, 159 | child: Center( 160 | child: Text( 161 | 'Launch Direct Charge', 162 | style: TextStyle( 163 | color: Colors.white, 164 | fontSize: 13, 165 | fontWeight: FontWeight.bold, 166 | ), 167 | ), 168 | ), 169 | onPressed: () async { 170 | await ThepeerDirectChargeView( 171 | data: ThepeerData( 172 | publicKey: 173 | "pspk_test_2aj8xasztf4domzd2nphinvzkvecpbuyxldkvr3pkuvko", 174 | amount: 400000, 175 | userReference: "73f03de5-1043-4ad1-bc2e-aa4d94ebee4f", 176 | currency: 'NGN', 177 | meta: { 178 | 'slug': 'F1rstm3ssag!ngSl0g', 179 | 'type': 'chat', 180 | 'paymentType': 'subscription', 181 | 'channel': 'thePeer', 182 | }, 183 | ), 184 | showLogs: true, 185 | onClosed: () { 186 | print('closed'); 187 | Navigator.pop(context); 188 | }, 189 | onSuccess: (v) { 190 | print(v.toString()); 191 | Navigator.pop(context); 192 | }, 193 | onError: print, 194 | ).show(context); 195 | }, 196 | ), 197 | ), 198 | ], 199 | ), 200 | ], 201 | ), 202 | ), 203 | ); 204 | } 205 | } 206 | 207 | final thepeerColor = Color(0xff1890ff); 208 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import connectivity_plus_macos 9 | import url_launcher_macos 10 | 11 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 12 | ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) 13 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 14 | } 15 | -------------------------------------------------------------------------------- /example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig: -------------------------------------------------------------------------------- 1 | // This is a generated file; do not edit or check into version control. 2 | FLUTTER_ROOT=/Users/chiziaruhoma/flutter 3 | FLUTTER_APPLICATION_PATH=/Users/chiziaruhoma/projects/packages/thepeer/example 4 | COCOAPODS_PARALLEL_CODE_SIGN=true 5 | FLUTTER_BUILD_DIR=build 6 | FLUTTER_BUILD_NAME=1.0.0 7 | FLUTTER_BUILD_NUMBER=1 8 | EXCLUDED_ARCHS=arm64 9 | DART_OBFUSCATION=false 10 | TRACK_WIDGET_CREATION=false 11 | TREE_SHAKE_ICONS=false 12 | PACKAGE_CONFIG=.packages 13 | -------------------------------------------------------------------------------- /example/macos/Flutter/ephemeral/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Users/chiziaruhoma/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/chiziaruhoma/projects/packages/thepeer/example" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "FLUTTER_BUILD_NAME=1.0.0" 8 | export "FLUTTER_BUILD_NUMBER=1" 9 | export "EXCLUDED_ARCHS=arm64" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=false" 12 | export "TREE_SHAKE_ICONS=false" 13 | export "PACKAGE_CONFIG=.packages" 14 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | args: 5 | dependency: transitive 6 | description: 7 | name: args 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.3.0" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.8.2" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.3.1" 39 | clock: 40 | dependency: transitive 41 | description: 42 | name: clock 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.1.0" 46 | collection: 47 | dependency: transitive 48 | description: 49 | name: collection 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.15.0" 53 | connectivity_plus: 54 | dependency: transitive 55 | description: 56 | name: connectivity_plus 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.3.0" 60 | connectivity_plus_linux: 61 | dependency: transitive 62 | description: 63 | name: connectivity_plus_linux 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "1.3.0" 67 | connectivity_plus_macos: 68 | dependency: transitive 69 | description: 70 | name: connectivity_plus_macos 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.2" 74 | connectivity_plus_platform_interface: 75 | dependency: transitive 76 | description: 77 | name: connectivity_plus_platform_interface 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.2.0" 81 | connectivity_plus_web: 82 | dependency: transitive 83 | description: 84 | name: connectivity_plus_web 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.2.0" 88 | connectivity_plus_windows: 89 | dependency: transitive 90 | description: 91 | name: connectivity_plus_windows 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.2.0" 95 | cupertino_icons: 96 | dependency: "direct main" 97 | description: 98 | name: cupertino_icons 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.0.2" 102 | dbus: 103 | dependency: transitive 104 | description: 105 | name: dbus 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "0.7.1" 109 | equatable: 110 | dependency: transitive 111 | description: 112 | name: equatable 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "2.0.3" 116 | fake_async: 117 | dependency: transitive 118 | description: 119 | name: fake_async 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.2.0" 123 | ffi: 124 | dependency: transitive 125 | description: 126 | name: ffi 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "1.1.2" 130 | flutter: 131 | dependency: "direct main" 132 | description: flutter 133 | source: sdk 134 | version: "0.0.0" 135 | flutter_svg: 136 | dependency: transitive 137 | description: 138 | name: flutter_svg 139 | url: "https://pub.dartlang.org" 140 | source: hosted 141 | version: "1.0.3" 142 | flutter_test: 143 | dependency: "direct dev" 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | flutter_web_plugins: 148 | dependency: transitive 149 | description: flutter 150 | source: sdk 151 | version: "0.0.0" 152 | gap: 153 | dependency: transitive 154 | description: 155 | name: gap 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "2.0.0" 159 | js: 160 | dependency: transitive 161 | description: 162 | name: js 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "0.6.3" 166 | matcher: 167 | dependency: transitive 168 | description: 169 | name: matcher 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "0.12.11" 173 | material_color_utilities: 174 | dependency: transitive 175 | description: 176 | name: material_color_utilities 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "0.1.3" 180 | meta: 181 | dependency: transitive 182 | description: 183 | name: meta 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "1.7.0" 187 | modal_bottom_sheet: 188 | dependency: transitive 189 | description: 190 | name: modal_bottom_sheet 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "2.0.1" 194 | nm: 195 | dependency: transitive 196 | description: 197 | name: nm 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "0.5.0" 201 | path: 202 | dependency: transitive 203 | description: 204 | name: path 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "1.8.0" 208 | path_drawing: 209 | dependency: transitive 210 | description: 211 | name: path_drawing 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "1.0.0" 215 | path_parsing: 216 | dependency: transitive 217 | description: 218 | name: path_parsing 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "1.0.0" 222 | petitparser: 223 | dependency: transitive 224 | description: 225 | name: petitparser 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "4.1.0" 229 | plugin_platform_interface: 230 | dependency: transitive 231 | description: 232 | name: plugin_platform_interface 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "2.0.2" 236 | sky_engine: 237 | dependency: transitive 238 | description: flutter 239 | source: sdk 240 | version: "0.0.99" 241 | source_span: 242 | dependency: transitive 243 | description: 244 | name: source_span 245 | url: "https://pub.dartlang.org" 246 | source: hosted 247 | version: "1.8.1" 248 | stack_trace: 249 | dependency: transitive 250 | description: 251 | name: stack_trace 252 | url: "https://pub.dartlang.org" 253 | source: hosted 254 | version: "1.10.0" 255 | stream_channel: 256 | dependency: transitive 257 | description: 258 | name: stream_channel 259 | url: "https://pub.dartlang.org" 260 | source: hosted 261 | version: "2.1.0" 262 | string_scanner: 263 | dependency: transitive 264 | description: 265 | name: string_scanner 266 | url: "https://pub.dartlang.org" 267 | source: hosted 268 | version: "1.1.0" 269 | term_glyph: 270 | dependency: transitive 271 | description: 272 | name: term_glyph 273 | url: "https://pub.dartlang.org" 274 | source: hosted 275 | version: "1.2.0" 276 | test_api: 277 | dependency: transitive 278 | description: 279 | name: test_api 280 | url: "https://pub.dartlang.org" 281 | source: hosted 282 | version: "0.4.8" 283 | thepeer_flutter: 284 | dependency: "direct main" 285 | description: 286 | path: ".." 287 | relative: true 288 | source: path 289 | version: "2.0.10" 290 | typed_data: 291 | dependency: transitive 292 | description: 293 | name: typed_data 294 | url: "https://pub.dartlang.org" 295 | source: hosted 296 | version: "1.3.0" 297 | url_launcher: 298 | dependency: transitive 299 | description: 300 | name: url_launcher 301 | url: "https://pub.dartlang.org" 302 | source: hosted 303 | version: "6.1.0" 304 | url_launcher_android: 305 | dependency: transitive 306 | description: 307 | name: url_launcher_android 308 | url: "https://pub.dartlang.org" 309 | source: hosted 310 | version: "6.0.16" 311 | url_launcher_ios: 312 | dependency: transitive 313 | description: 314 | name: url_launcher_ios 315 | url: "https://pub.dartlang.org" 316 | source: hosted 317 | version: "6.0.15" 318 | url_launcher_linux: 319 | dependency: transitive 320 | description: 321 | name: url_launcher_linux 322 | url: "https://pub.dartlang.org" 323 | source: hosted 324 | version: "2.0.2" 325 | url_launcher_macos: 326 | dependency: transitive 327 | description: 328 | name: url_launcher_macos 329 | url: "https://pub.dartlang.org" 330 | source: hosted 331 | version: "2.0.2" 332 | url_launcher_platform_interface: 333 | dependency: transitive 334 | description: 335 | name: url_launcher_platform_interface 336 | url: "https://pub.dartlang.org" 337 | source: hosted 338 | version: "2.0.4" 339 | url_launcher_web: 340 | dependency: transitive 341 | description: 342 | name: url_launcher_web 343 | url: "https://pub.dartlang.org" 344 | source: hosted 345 | version: "2.0.4" 346 | url_launcher_windows: 347 | dependency: transitive 348 | description: 349 | name: url_launcher_windows 350 | url: "https://pub.dartlang.org" 351 | source: hosted 352 | version: "2.0.2" 353 | vector_math: 354 | dependency: transitive 355 | description: 356 | name: vector_math 357 | url: "https://pub.dartlang.org" 358 | source: hosted 359 | version: "2.1.1" 360 | webview_flutter: 361 | dependency: transitive 362 | description: 363 | name: webview_flutter 364 | url: "https://pub.dartlang.org" 365 | source: hosted 366 | version: "3.0.2" 367 | webview_flutter_android: 368 | dependency: transitive 369 | description: 370 | name: webview_flutter_android 371 | url: "https://pub.dartlang.org" 372 | source: hosted 373 | version: "2.8.3" 374 | webview_flutter_platform_interface: 375 | dependency: transitive 376 | description: 377 | name: webview_flutter_platform_interface 378 | url: "https://pub.dartlang.org" 379 | source: hosted 380 | version: "1.8.0" 381 | webview_flutter_wkwebview: 382 | dependency: transitive 383 | description: 384 | name: webview_flutter_wkwebview 385 | url: "https://pub.dartlang.org" 386 | source: hosted 387 | version: "2.7.1" 388 | xml: 389 | dependency: transitive 390 | description: 391 | name: xml 392 | url: "https://pub.dartlang.org" 393 | source: hosted 394 | version: "5.1.2" 395 | sdks: 396 | dart: ">=2.15.0 <3.0.0" 397 | flutter: ">=2.8.0" 398 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | 7 | # The following defines the version and build number for your application. 8 | # A version number is three numbers separated by dots, like 1.2.43 9 | # followed by an optional build number separated by a +. 10 | # Both the version and the builder number may be overridden in flutter 11 | # build by specifying --build-name and --build-number, respectively. 12 | # In Android, build-name is used as versionName while build-number used as versionCode. 13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 15 | # Read more about iOS versioning at 16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 17 | version: 1.0.0+1 18 | 19 | 20 | environment: 21 | sdk: '>=2.12.0 <3.0.0' 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | thepeer_flutter: 27 | path: '../' 28 | 29 | 30 | # The following adds the Cupertino Icons font to your application. 31 | # Use with the CupertinoIcons class for iOS style icons. 32 | cupertino_icons: ^1.0.2 33 | 34 | dev_dependencies: 35 | flutter_test: 36 | sdk: flutter 37 | 38 | # For information on the generic Dart part of this file, see the 39 | # following page: https://dart.dev/tools/pub/pubspec 40 | 41 | # The following section is specific to Flutter. 42 | flutter: 43 | 44 | # The following line ensures that the Material Icons font is 45 | # included with your application, so that you can use the icons in 46 | # the material Icons class. 47 | uses-material-design: true 48 | 49 | # To add assets to your application, add an assets section, like this: 50 | # assets: 51 | # - images/a_dot_burr.jpeg 52 | # - images/a_dot_ham.jpeg 53 | 54 | # An image asset can refer to one or more resolution-specific "variants", see 55 | # https://flutter.dev/assets-and-images/#resolution-aware. 56 | 57 | # For details regarding adding assets from package dependencies, see 58 | # https://flutter.dev/assets-and-images/#from-packages 59 | 60 | # To add custom fonts to your application, add a fonts section here, 61 | # in this "flutter" section. Each entry in this list should have a 62 | # "family" key with the font family name, and a "fonts" key with a 63 | # list giving the asset and other descriptors for the font. For 64 | # example: 65 | # fonts: 66 | # - family: Schyler 67 | # fonts: 68 | # - asset: fonts/Schyler-Regular.ttf 69 | # - asset: fonts/Schyler-Italic.ttf 70 | # style: italic 71 | # - family: Trajan Pro 72 | # fonts: 73 | # - asset: fonts/TrajanPro.ttf 74 | # - asset: fonts/TrajanPro_Bold.ttf 75 | # weight: 700 76 | # 77 | # For details regarding fonts from package dependencies, 78 | # see https://flutter.dev/custom-fonts/#from-packages 79 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /lib/assets/fonts/Gilroy-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/lib/assets/fonts/Gilroy-Bold.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Gilroy-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/lib/assets/fonts/Gilroy-Medium.ttf -------------------------------------------------------------------------------- /lib/assets/fonts/Gilroy-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/lib/assets/fonts/Gilroy-SemiBold.ttf -------------------------------------------------------------------------------- /lib/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lib/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepeerstack/flutter-sdk/7bdbd76f5cb481105f7f24cace5a74a406095331/lib/assets/images/logo.png -------------------------------------------------------------------------------- /lib/assets/images/warning_badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/src/const/const.dart: -------------------------------------------------------------------------------- 1 | const package = 'thepeer_flutter'; 2 | const baseUrl = 'https://chain.thepeer.co?'; 3 | 4 | const SEND_SUCCESS = 'send.success'; 5 | const SEND_ERROR = 'send.server_error'; 6 | const SEND_CLOSE = 'send.close'; 7 | 8 | const CHECKOUT_SUCCESS = 'checkout.success'; 9 | const CHECKOUT_ERROR = 'checkout.server_error'; 10 | const CHECKOUT_CLOSE = 'checkout.close'; 11 | 12 | const DIRECT_DEBIT_SUCCESS = 'direct_debit.success'; 13 | const DIRECT_DEBIT_ERROR = 'direct_debit.server_error'; 14 | const DIRECT_DEBIT_CLOSE = 'direct_debit.close'; 15 | -------------------------------------------------------------------------------- /lib/src/model/the_peer_event_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:equatable/equatable.dart'; 4 | 5 | class ThepeerEventModel with EquatableMixin { 6 | final String type; 7 | ThepeerEventModel({ 8 | required this.type, 9 | }); 10 | 11 | ThepeerEventModel copyWith({ 12 | String? type, 13 | }) { 14 | return ThepeerEventModel( 15 | type: type ?? this.type, 16 | ); 17 | } 18 | 19 | Map toMap() { 20 | return { 21 | 'type': type, 22 | }; 23 | } 24 | 25 | factory ThepeerEventModel.fromMap(Map map) { 26 | return ThepeerEventModel( 27 | type: map['type'] as String, 28 | ); 29 | } 30 | 31 | String toJson() => json.encode(toMap()); 32 | 33 | factory ThepeerEventModel.fromJson(String source) => 34 | ThepeerEventModel.fromMap( 35 | json.decode(source), 36 | ); 37 | 38 | @override 39 | bool get stringify => true; 40 | 41 | @override 42 | List get props => [type]; 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/model/thepeer_data.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:equatable/equatable.dart'; 4 | 5 | class ThepeerData with EquatableMixin { 6 | /// Your public key an be found on your dashboard settings 7 | final String publicKey; 8 | 9 | /// The user reference returned by the Thepeer API when a user has been indexed 10 | final String userReference; 11 | 12 | /// The amount you intend to send and must be pass as an integer in kobo 13 | final int amount; 14 | 15 | /// The currency of the `amount` to be paid 16 | final String currency; 17 | 18 | /// Optional Medata data needed 19 | final Map meta; 20 | 21 | bool get isProd => publicKey.contains('test') == false; 22 | 23 | ThepeerData({ 24 | required this.publicKey, 25 | required this.userReference, 26 | required this.currency, 27 | required this.amount, 28 | this.meta = const {}, 29 | }); 30 | 31 | ThepeerData copyWith({ 32 | String? publicKey, 33 | String? userReference, 34 | String? currency, 35 | String? receiptUrl, 36 | Map? meta, 37 | int? amount, 38 | }) { 39 | return ThepeerData( 40 | publicKey: publicKey ?? this.publicKey, 41 | userReference: userReference ?? this.userReference, 42 | amount: amount ?? this.amount, 43 | currency: currency ?? this.currency, 44 | meta: meta ?? this.meta, 45 | ); 46 | } 47 | 48 | Map toMap() { 49 | return { 50 | 'publicKey': publicKey, 51 | 'userReference': userReference, 52 | 'amount': amount, 53 | 'meta': meta, 54 | }; 55 | } 56 | 57 | factory ThepeerData.fromMap(Map map) { 58 | return ThepeerData( 59 | publicKey: map['publicKey'], 60 | userReference: map['userReference'], 61 | amount: map['amount'], 62 | currency: map['currency'], 63 | meta: map['meta'], 64 | ); 65 | } 66 | 67 | String toJson() => json.encode(toMap()); 68 | 69 | factory ThepeerData.fromJson(String source) => 70 | ThepeerData.fromMap(json.decode(source)); 71 | 72 | @override 73 | bool? get stringify => true; 74 | 75 | @override 76 | List get props => [ 77 | publicKey, 78 | userReference, 79 | amount, 80 | currency, 81 | meta, 82 | ]; 83 | } 84 | -------------------------------------------------------------------------------- /lib/src/model/thepeer_success_model.dart: -------------------------------------------------------------------------------- 1 | /* import 'dart:convert'; 2 | 3 | import 'package:equatable/equatable.dart'; 4 | 5 | class ThepeerSuccessModel with EquatableMixin { 6 | final String type; 7 | final ThepeerSuccessData data; 8 | ThepeerSuccessModel({ 9 | required this.type, 10 | required this.data, 11 | }); 12 | 13 | ThepeerSuccessModel copyWith({ 14 | String? type, 15 | ThepeerSuccessData? data, 16 | }) { 17 | return ThepeerSuccessModel( 18 | type: type ?? this.type, 19 | data: data ?? this.data, 20 | ); 21 | } 22 | 23 | Map toMap() { 24 | return { 25 | 'type': type, 26 | 'data': data.toMap(), 27 | }; 28 | } 29 | 30 | factory ThepeerSuccessModel.fromMap(Map map) { 31 | return ThepeerSuccessModel( 32 | type: map['type'], 33 | data: ThepeerSuccessData.fromMap(map['data']), 34 | ); 35 | } 36 | 37 | String toJson() => json.encode(toMap()); 38 | 39 | factory ThepeerSuccessModel.fromJson(String source) => 40 | ThepeerSuccessModel.fromMap(json.decode(source)); 41 | 42 | @override 43 | bool get stringify => true; 44 | 45 | @override 46 | List get props => [type, data]; 47 | } 48 | 49 | class ThepeerSuccessData with EquatableMixin { 50 | final String id; 51 | final String remark; 52 | final int amount; 53 | final String type; 54 | final bool directDebit; 55 | final String status; 56 | final User user; 57 | final String mode; 58 | final String reference; 59 | final dynamic meta; 60 | final Peer peer; 61 | final String createdAt; 62 | final String updatedAt; 63 | 64 | ThepeerSuccessData({ 65 | required this.id, 66 | required this.remark, 67 | required this.amount, 68 | required this.type, 69 | required this.directDebit, 70 | required this.status, 71 | required this.user, 72 | required this.mode, 73 | required this.reference, 74 | required this.peer, 75 | required this.meta, 76 | required this.createdAt, 77 | required this.updatedAt, 78 | }); 79 | 80 | ThepeerSuccessData copyWith({ 81 | String? id, 82 | String? remark, 83 | int? amount, 84 | String? type, 85 | bool? directDebit, 86 | String? status, 87 | User? user, 88 | String? mode, 89 | String? reference, 90 | Peer? peer, 91 | dynamic meta, 92 | String? createdAt, 93 | String? updatedAt, 94 | }) { 95 | return ThepeerSuccessData( 96 | id: id ?? this.id, 97 | remark: remark ?? this.remark, 98 | amount: amount ?? this.amount, 99 | type: type ?? this.type, 100 | directDebit: directDebit ?? this.directDebit, 101 | status: status ?? this.status, 102 | user: user ?? this.user, 103 | mode: mode ?? this.mode, 104 | reference: reference ?? this.reference, 105 | peer: peer ?? this.peer, 106 | meta: meta ?? this.meta, 107 | createdAt: createdAt ?? this.createdAt, 108 | updatedAt: updatedAt ?? this.updatedAt, 109 | ); 110 | } 111 | 112 | Map toMap() { 113 | return { 114 | 'id': id, 115 | 'remark': remark, 116 | 'amount': amount, 117 | 'type': type, 118 | 'direct_debit': directDebit, 119 | 'status': status, 120 | 'user': user.toMap(), 121 | 'meta': meta, 122 | 'mode': mode, 123 | 'reference': reference, 124 | 'peer': peer.toMap(), 125 | 'created_at': createdAt, 126 | 'updated_at': updatedAt, 127 | }; 128 | } 129 | 130 | factory ThepeerSuccessData.fromMap(Map map) { 131 | return ThepeerSuccessData( 132 | id: map['id'], 133 | remark: map['remark'], 134 | amount: map['amount'], 135 | type: map['type'], 136 | directDebit: map['direct_debit'], 137 | status: map['status'], 138 | user: User.fromMap(map['user']), 139 | mode: map['mode'], 140 | reference: map['reference'], 141 | peer: Peer.fromMap(map['peer']), 142 | meta: map['meta'], 143 | createdAt: map['created_at'], 144 | updatedAt: map['updated_at'], 145 | ); 146 | } 147 | 148 | String toJson() => json.encode(toMap()); 149 | 150 | factory ThepeerSuccessData.fromJson(String source) => 151 | ThepeerSuccessData.fromMap( 152 | json.decode(source), 153 | ); 154 | 155 | @override 156 | bool get stringify => true; 157 | 158 | @override 159 | List get props { 160 | return [ 161 | id, 162 | remark, 163 | amount, 164 | type, 165 | directDebit, 166 | status, 167 | user, 168 | mode, 169 | reference, 170 | peer, 171 | createdAt, 172 | updatedAt, 173 | ]; 174 | } 175 | } 176 | 177 | class User with EquatableMixin { 178 | final String name; 179 | final String identifier; 180 | final String identifierType; 181 | final String email; 182 | final String reference; 183 | final String createdAt; 184 | final String updatedAt; 185 | User({ 186 | required this.name, 187 | required this.identifier, 188 | required this.identifierType, 189 | required this.email, 190 | required this.reference, 191 | required this.createdAt, 192 | required this.updatedAt, 193 | }); 194 | 195 | User copyWith({ 196 | String? name, 197 | String? identifier, 198 | String? identifierType, 199 | String? email, 200 | String? reference, 201 | String? createdAt, 202 | String? updatedAt, 203 | }) { 204 | return User( 205 | name: name ?? this.name, 206 | identifier: identifier ?? this.identifier, 207 | identifierType: identifierType ?? this.identifierType, 208 | email: email ?? this.email, 209 | reference: reference ?? this.reference, 210 | createdAt: createdAt ?? this.createdAt, 211 | updatedAt: updatedAt ?? this.updatedAt, 212 | ); 213 | } 214 | 215 | Map toMap() { 216 | return { 217 | 'name': name, 218 | 'identifier': identifier, 219 | 'identifier_type': identifierType, 220 | 'email': email, 221 | 'reference': reference, 222 | 'created_at': createdAt, 223 | 'updated_at': updatedAt, 224 | }; 225 | } 226 | 227 | factory User.fromMap(Map map) { 228 | return User( 229 | name: map['name'], 230 | identifier: map['identifier'], 231 | identifierType: map['identifier_type'], 232 | email: map['email'], 233 | reference: map['reference'], 234 | createdAt: map['created_at'], 235 | updatedAt: map['updated_at'], 236 | ); 237 | } 238 | 239 | String toJson() => json.encode(toMap()); 240 | 241 | factory User.fromJson(String source) => User.fromMap(json.decode(source)); 242 | 243 | @override 244 | bool get stringify => true; 245 | 246 | @override 247 | List get props { 248 | return [ 249 | name, 250 | identifier, 251 | identifierType, 252 | email, 253 | reference, 254 | createdAt, 255 | updatedAt, 256 | ]; 257 | } 258 | } 259 | 260 | class Peer with EquatableMixin { 261 | final Business business; 262 | final User user; 263 | Peer({ 264 | required this.business, 265 | required this.user, 266 | }); 267 | 268 | Peer copyWith({ 269 | Business? business, 270 | User? user, 271 | }) { 272 | return Peer( 273 | business: business ?? this.business, 274 | user: user ?? this.user, 275 | ); 276 | } 277 | 278 | Map toMap() { 279 | return { 280 | 'business': business.toMap(), 281 | 'user': user.toMap(), 282 | }; 283 | } 284 | 285 | factory Peer.fromMap(Map map) { 286 | return Peer( 287 | business: Business.fromMap(map['business']), 288 | user: User.fromMap(map['user']), 289 | ); 290 | } 291 | 292 | String toJson() => json.encode(toMap()); 293 | 294 | factory Peer.fromJson(String source) => Peer.fromMap(json.decode(source)); 295 | 296 | @override 297 | List get props => [business, user]; 298 | } 299 | 300 | class Business with EquatableMixin { 301 | final String id; 302 | final String name; 303 | final String logo; 304 | final String logoColour; 305 | final String identifierType; 306 | Business({ 307 | required this.id, 308 | required this.name, 309 | required this.logo, 310 | required this.logoColour, 311 | required this.identifierType, 312 | }); 313 | 314 | Business copyWith({ 315 | String? id, 316 | String? name, 317 | String? logo, 318 | String? logoColour, 319 | String? identifierType, 320 | }) { 321 | return Business( 322 | id: id ?? this.id, 323 | name: name ?? this.name, 324 | logo: logo ?? this.logo, 325 | logoColour: logoColour ?? this.logoColour, 326 | identifierType: identifierType ?? this.identifierType, 327 | ); 328 | } 329 | 330 | Map toMap() { 331 | return { 332 | 'id': id, 333 | 'name': name, 334 | 'logo': logo, 335 | 'logo_colour': logoColour, 336 | 'identifier_type': identifierType, 337 | }; 338 | } 339 | 340 | factory Business.fromMap(Map map) { 341 | return Business( 342 | id: map['id'], 343 | name: map['name'], 344 | logo: map['logo'], 345 | logoColour: map['logo_colour'], 346 | identifierType: map['identifier_type'], 347 | ); 348 | } 349 | 350 | String toJson() => json.encode(toMap()); 351 | 352 | factory Business.fromJson(String source) => 353 | Business.fromMap(json.decode(source)); 354 | 355 | @override 356 | bool? get stringify => true; 357 | 358 | @override 359 | List get props { 360 | return [ 361 | id, 362 | name, 363 | logo, 364 | logoColour, 365 | identifierType, 366 | ]; 367 | } 368 | } 369 | */ -------------------------------------------------------------------------------- /lib/src/utils/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const peerPeach = Color(0xFFFBE9E9); 4 | const peerBlue = Color(0xFF0066FF); 5 | const peerLightPeach = Color(0xFFF7F7F7); 6 | const peerRed = Color(0xFFDB3838); 7 | const peerTextColor = Color(0xFF586283); 8 | const peerLightTextColor = Color(0xFF727EA3); 9 | const peerBoldTextColor = Color(0xFF24366B); 10 | const peerTextFieldBorderColor = Color(0xFFE9EEF7); 11 | const peerTextFieldEnabledBorderColor = Color(0xFF3862DB); 12 | -------------------------------------------------------------------------------- /lib/src/utils/css.dart: -------------------------------------------------------------------------------- 1 | /// Raw Thepeer html formation 2 | const String noSelectCssSheet = '''* { 3 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 4 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 5 | -webkit-touch-callout: none; 6 | -webkit-user-select: none; 7 | -khtml-user-select: none; 8 | -moz-user-select: none; 9 | -ms-user-select: none; 10 | user-select: none; 11 | }'''; 12 | -------------------------------------------------------------------------------- /lib/src/utils/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension CustomContext on BuildContext { 4 | double screenHeight([double percent = 1]) => 5 | MediaQuery.of(this).size.height * percent; 6 | 7 | double screenWidth([double percent = 1]) => 8 | MediaQuery.of(this).size.width * percent; 9 | } 10 | 11 | extension Slice on String { 12 | String slice([int start = 0, int? end]) { 13 | int _realEnd; 14 | final _realStart = start < 0 ? length + start : start; 15 | if (end is! int) { 16 | _realEnd = length; 17 | } else { 18 | _realEnd = end < 0 ? length + end : end; 19 | } 20 | 21 | return substring(_realStart, _realEnd); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/utils/functions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:thepeer_flutter/src/const/const.dart'; 5 | import 'package:thepeer_flutter/src/model/thepeer_data.dart'; 6 | import 'package:thepeer_flutter/src/utils/extensions.dart'; 7 | import 'package:url_launcher/url_launcher.dart'; 8 | 9 | class ThepeerFunctions { 10 | /// `[JS]` Create EventListener config for message client 11 | static String peerMessageHandler(String clientName) => ''' 12 | 13 | 14 | // Create our shared stylesheet: 15 | var style = document.createElement("style"); 16 | 17 | // Add EventListener for onMessage Event 18 | window.addEventListener('message', (event) => { 19 | sendMessage(event.data) 20 | }); 21 | 22 | // Override default JS Console function 23 | console._log_old = console.log 24 | console.log = function(msg) { 25 | sendMessageRaw(msg); 26 | console._log_old(msg); 27 | } 28 | 29 | console._error_old = console.error 30 | console.error = function(msg) { 31 | sendMessageRaw(msg); 32 | console._error_old(msg); 33 | } 34 | 35 | // Send callback to dart JSMessageClient 36 | function sendMessage(message) { 37 | if (window.$clientName && window.$clientName.postMessage) { 38 | $clientName.postMessage(JSON.stringify(message)); 39 | } 40 | } 41 | 42 | // Send raw callback to dart JSMessageClient 43 | function sendMessageRaw(message) { 44 | if (window.$clientName && window.$clientName.postMessage) { 45 | $clientName.postMessage(message); 46 | } 47 | } 48 | '''; 49 | 50 | /// Log data from thepeer sdk 51 | static void log(String data) => debugPrint('ThepeerLog: $data'); 52 | 53 | /// converts the base url to only domain name e.g [https://chain.thepeer.co?] returns [chain.thepeer.co] 54 | static String domainName = Uri.parse(baseUrl).host; 55 | 56 | /// Create peer url 57 | static Uri createUrl({ 58 | required ThepeerData data, 59 | String? email, 60 | required String sdkType, 61 | }) { 62 | var base = baseUrl; 63 | 64 | final params = { 65 | 'publicKey': data.publicKey, 66 | 'amount': '${data.amount}', 67 | 'currency': data.currency, 68 | if (email != null) 'email': email, 69 | 'userReference': data.userReference, 70 | 'sdkType': sdkType, 71 | }; 72 | 73 | for (final k in params.keys) { 74 | if (params[k] != null && params[k] is String) { 75 | final value = params[k]; 76 | base = '$base$k=$value&'; 77 | } 78 | } 79 | 80 | final tempUri = Uri.parse(base.slice(0, -1)); 81 | 82 | return Uri( 83 | scheme: tempUri.scheme, 84 | host: tempUri.host, 85 | path: tempUri.path, 86 | queryParameters: { 87 | ...tempUri.queryParameters, 88 | 'meta': jsonEncode(data.meta), 89 | }, 90 | ); 91 | } 92 | 93 | /// Open url in an external browser 94 | static void launchExternalUrl( 95 | {required String url, required bool showLogs}) async { 96 | try { 97 | await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication); 98 | } catch (e) { 99 | // handle failure 100 | if (showLogs == true) ThepeerFunctions.log(e.toString()); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/src/utils/the_peer_error_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:gap/gap.dart'; 4 | import 'package:thepeer_flutter/src/const/const.dart'; 5 | import 'package:thepeer_flutter/src/utils/colors.dart'; 6 | import 'package:thepeer_flutter/src/widgets/the_peer_button.dart'; 7 | import 'package:thepeer_flutter/src/widgets/touchable_opacity.dart'; 8 | 9 | /// ThepeerErrorView States Widget 10 | class ThepeerErrorView extends StatelessWidget { 11 | final VoidCallback reload; 12 | final VoidCallback? onClosed; 13 | 14 | const ThepeerErrorView({ 15 | Key? key, 16 | this.onClosed, 17 | required this.reload, 18 | }) : super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Container( 25 | padding: const EdgeInsets.only( 26 | left: 20, 27 | right: 20, 28 | top: 38, 29 | ), 30 | child: Column( 31 | crossAxisAlignment: CrossAxisAlignment.start, 32 | children: [ 33 | PeerHeader( 34 | onClosed: onClosed, 35 | showClose: true, 36 | ), 37 | ], 38 | ), 39 | ), 40 | Flexible( 41 | child: ListView( 42 | padding: const EdgeInsets.all(16), 43 | physics: const BouncingScrollPhysics(), 44 | children: [ 45 | const Gap(80), 46 | SvgPicture.asset( 47 | 'assets/images/warning_badge.svg', 48 | package: package, 49 | ), 50 | const Gap(45), 51 | const Center( 52 | child: Text( 53 | 'Something went wrong', 54 | style: TextStyle( 55 | fontFamily: 'Gilroy-Bold', 56 | package: package, 57 | fontSize: 24, 58 | color: peerBoldTextColor, 59 | ), 60 | ), 61 | ), 62 | const Gap(14), 63 | const Center( 64 | child: Padding( 65 | padding: EdgeInsets.symmetric(horizontal: 30), 66 | child: Text( 67 | 'Please check your internet connection', 68 | textAlign: TextAlign.center, 69 | style: TextStyle( 70 | fontFamily: 'Gilroy-Medium', 71 | package: package, 72 | fontSize: 15, 73 | color: peerTextColor, 74 | ), 75 | ), 76 | ), 77 | ), 78 | const Gap(32), 79 | PeerButton( 80 | title: 'Reload', 81 | buttonColor: Colors.white, 82 | textColor: peerBlue, 83 | isUnderlined: true, 84 | onTap: reload, 85 | ) 86 | ], 87 | ), 88 | ), 89 | Row( 90 | mainAxisAlignment: MainAxisAlignment.center, 91 | children: [ 92 | const Text( 93 | 'Powered by', 94 | style: TextStyle( 95 | fontFamily: 'Gilroy-Medium', 96 | package: package, 97 | fontSize: 14, 98 | color: peerLightTextColor, 99 | ), 100 | ), 101 | const Gap(4), 102 | Image.asset( 103 | 'assets/images/logo.png', 104 | package: package, 105 | height: 18, 106 | ), 107 | ], 108 | ), 109 | const Gap(32), 110 | ], 111 | ); 112 | } 113 | } 114 | 115 | /// Peer Header Widget 116 | class PeerHeader extends StatelessWidget { 117 | final bool showClose; 118 | final VoidCallback? onClosed; 119 | 120 | const PeerHeader({ 121 | Key? key, 122 | this.showClose = false, 123 | this.onClosed, 124 | }) : super(key: key); 125 | 126 | @override 127 | Widget build(BuildContext context) { 128 | return Row( 129 | children: [ 130 | const Spacer(), 131 | TouchableOpacity( 132 | onTap: onClosed ?? () {}, 133 | child: SizedBox( 134 | height: 40, 135 | width: 40, 136 | child: Column( 137 | crossAxisAlignment: CrossAxisAlignment.end, 138 | children: [ 139 | SvgPicture.asset( 140 | 'assets/images/close.svg', 141 | package: package, 142 | ), 143 | ], 144 | ), 145 | ), 146 | ), 147 | ], 148 | ); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /lib/src/views/the_peer_checkout_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:connectivity_plus/connectivity_plus.dart'; 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; 8 | import 'package:thepeer_flutter/src/const/const.dart'; 9 | import 'package:thepeer_flutter/src/model/the_peer_event_model.dart'; 10 | import 'package:thepeer_flutter/src/utils/functions.dart'; 11 | import 'package:thepeer_flutter/src/widgets/the_peer_loader.dart'; 12 | import 'package:webview_flutter/webview_flutter.dart'; 13 | 14 | import 'package:thepeer_flutter/src/model/thepeer_data.dart'; 15 | import 'package:thepeer_flutter/src/utils/extensions.dart'; 16 | 17 | import 'package:thepeer_flutter/src/views/the_peer_error_view.dart'; 18 | 19 | class ThepeerCheckoutView extends StatefulWidget { 20 | /// Public Key from your https://app.withThepeer.com/apps 21 | final ThepeerData data; 22 | 23 | /// User email 24 | final String email; 25 | 26 | /// Success callback 27 | final ValueChanged? onSuccess; 28 | 29 | /// Error callback 30 | final ValueChanged? onError; 31 | 32 | /// Thepeer popup Close callback 33 | final VoidCallback? onClosed; 34 | 35 | /// Error Widget will show if loading fails 36 | final Widget? errorWidget; 37 | 38 | /// Show [ThepeerCheckoutView] Logs 39 | final bool showLogs; 40 | 41 | /// Toggle dismissible mode 42 | final bool isDismissible; 43 | 44 | const ThepeerCheckoutView({ 45 | Key? key, 46 | required this.data, 47 | required this.email, 48 | this.errorWidget, 49 | this.onSuccess, 50 | this.onClosed, 51 | this.onError, 52 | this.showLogs = false, 53 | this.isDismissible = false, 54 | }) : super(key: key); 55 | 56 | /// Show Dialog with a custom child 57 | Future show(BuildContext context) => showCupertinoModalBottomSheet( 58 | backgroundColor: Colors.white, 59 | shape: const RoundedRectangleBorder( 60 | borderRadius: BorderRadius.only( 61 | topLeft: Radius.circular(10), 62 | topRight: Radius.circular(10), 63 | ), 64 | ), 65 | isDismissible: isDismissible, 66 | enableDrag: isDismissible, 67 | context: context, 68 | builder: (context) => ClipRRect( 69 | borderRadius: const BorderRadius.only( 70 | topLeft: Radius.circular(10), 71 | topRight: Radius.circular(10), 72 | ), 73 | child: SizedBox( 74 | height: MediaQuery.of(context).size.height, 75 | child: Column( 76 | mainAxisAlignment: MainAxisAlignment.center, 77 | children: [ 78 | Center( 79 | child: SizedBox( 80 | height: context.screenHeight(.9), 81 | child: ThepeerCheckoutView( 82 | data: data, 83 | onClosed: onClosed, 84 | email: email, 85 | onSuccess: onSuccess, 86 | onError: onError, 87 | showLogs: showLogs, 88 | errorWidget: errorWidget, 89 | ), 90 | ), 91 | ), 92 | ], 93 | ), 94 | ), 95 | ), 96 | ); 97 | 98 | @override 99 | _ThepeerCheckoutViewState createState() => _ThepeerCheckoutViewState(); 100 | } 101 | 102 | class _ThepeerCheckoutViewState extends State { 103 | late final WebViewController _controller; 104 | 105 | bool _isLoading = true; 106 | bool get isLoading => _isLoading; 107 | set isLoading(bool val) { 108 | setState(() { 109 | _isLoading = val; 110 | }); 111 | } 112 | 113 | bool _hasError = false; 114 | bool get hasError => _hasError; 115 | set hasError(bool val) { 116 | setState(() { 117 | _hasError = val; 118 | }); 119 | } 120 | 121 | @override 122 | void initState() { 123 | super.initState(); 124 | _handleInit(); 125 | } 126 | 127 | String get createUrl => ThepeerFunctions.createUrl( 128 | data: widget.data, 129 | email: widget.email, 130 | sdkType: 'checkout', 131 | ).toString(); 132 | 133 | @override 134 | Widget build(BuildContext context) { 135 | return Scaffold( 136 | backgroundColor: Colors.transparent, 137 | body: FutureBuilder( 138 | future: Connectivity().checkConnectivity(), 139 | builder: (context, snapshot) { 140 | /// Show error view 141 | if (hasError == true) { 142 | return Center( 143 | child: widget.errorWidget ?? 144 | ThepeerErrorView( 145 | onClosed: widget.onClosed, 146 | reload: () async { 147 | await _controller.reload(); 148 | }, 149 | ), 150 | ); 151 | } 152 | 153 | if (snapshot.hasData == true && 154 | snapshot.data != ConnectivityResult.none) { 155 | return Stack( 156 | alignment: Alignment.center, 157 | children: [ 158 | if (isLoading == true && hasError == false) ...[ 159 | const PeerLoader(), 160 | ], 161 | 162 | /// Thepeer Webview 163 | WebViewWidget( 164 | controller: _controller, 165 | ), 166 | ], 167 | ); 168 | } else { 169 | return const Center(child: CupertinoActivityIndicator()); 170 | } 171 | }, 172 | ), 173 | ); 174 | } 175 | 176 | /// Inject JS code to be run in webview 177 | Future _injectPeerStack(WebViewController controller) async { 178 | await controller.runJavaScript( 179 | ThepeerFunctions.peerMessageHandler( 180 | 'ThepeerSendClientInterface', 181 | ), 182 | ); 183 | } 184 | 185 | /// Parse event from javascript channel 186 | void _handleResponse(String res) async { 187 | try { 188 | final data = ThepeerEventModel.fromJson(res); 189 | switch (data.type) { 190 | case CHECKOUT_SUCCESS: 191 | if (widget.onSuccess != null) { 192 | widget.onSuccess!(data); 193 | } 194 | return; 195 | case CHECKOUT_CLOSE: 196 | if (mounted && widget.onClosed != null) widget.onClosed!(); 197 | return; 198 | default: 199 | if (mounted && widget.onError != null) widget.onError!(res); 200 | return; 201 | } 202 | } catch (e) { 203 | if (widget.showLogs == true) ThepeerFunctions.log(e.toString()); 204 | } 205 | } 206 | 207 | /// Handle WebView initialization 208 | void _handleInit() async { 209 | await SystemChannels.textInput.invokeMethod('TextInput.hide'); 210 | 211 | final WebViewController controller = 212 | WebViewController.fromPlatformCreationParams( 213 | PlatformWebViewControllerCreationParams()); 214 | 215 | controller 216 | ..enableZoom(false) 217 | ..setJavaScriptMode(JavaScriptMode.unrestricted) 218 | ..addJavaScriptChannel('ThepeerSendClientInterface', 219 | onMessageReceived: _onMessageReceived) 220 | ..setNavigationDelegate(NavigationDelegate( 221 | onPageStarted: (_) async { 222 | isLoading = true; 223 | }, 224 | onWebResourceError: (e) { 225 | hasError = true; 226 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 227 | }, 228 | onPageFinished: (_) async { 229 | isLoading = false; 230 | await _injectPeerStack(_controller); 231 | }, 232 | onNavigationRequest: _handleNavigationInterceptor)) 233 | ..loadRequest(Uri.parse('$createUrl')); 234 | 235 | _controller = controller; 236 | } 237 | 238 | /// Javascript channel onMessageRecieved for events sent by Thepeer 239 | void _onMessageReceived(JavaScriptMessage data) { 240 | try { 241 | if (widget.showLogs) ThepeerFunctions.log('Event: -> ${data.message}'); 242 | _handleResponse(data.message); 243 | } on Exception { 244 | if (mounted && widget.onClosed != null) widget.onClosed!(); 245 | } catch (e) { 246 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 247 | } 248 | } 249 | 250 | NavigationDecision _handleNavigationInterceptor(NavigationRequest request) { 251 | final url = request.url.toLowerCase(); 252 | 253 | if (url.contains(ThepeerFunctions.domainName)) { 254 | // Navigate to all urls contianing Thepeer domain 255 | return NavigationDecision.navigate; 256 | } else { 257 | //Prevent external navigations from opening in the webview and open in an external browser instead. 258 | ThepeerFunctions.launchExternalUrl(url: url, showLogs: (widget.showLogs)); 259 | return NavigationDecision.prevent; 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /lib/src/views/the_peer_direct_charge_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:connectivity_plus/connectivity_plus.dart'; 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; 8 | import 'package:thepeer_flutter/src/const/const.dart'; 9 | import 'package:thepeer_flutter/src/model/the_peer_event_model.dart'; 10 | import 'package:thepeer_flutter/src/utils/functions.dart'; 11 | import 'package:thepeer_flutter/src/widgets/the_peer_loader.dart'; 12 | import 'package:webview_flutter/webview_flutter.dart'; 13 | 14 | import 'package:thepeer_flutter/src/model/thepeer_data.dart'; 15 | import 'package:thepeer_flutter/src/utils/extensions.dart'; 16 | 17 | import 'package:thepeer_flutter/src/views/the_peer_error_view.dart'; 18 | 19 | class ThepeerDirectChargeView extends StatefulWidget { 20 | /// Public Key from your https://app.withThepeer.com/apps 21 | final ThepeerData data; 22 | 23 | /// Success callback 24 | final ValueChanged? onSuccess; 25 | 26 | /// Error callback 27 | final ValueChanged? onError; 28 | 29 | /// Thepeer popup Close callback 30 | final VoidCallback? onClosed; 31 | 32 | /// Error Widget will show if loading fails 33 | final Widget? errorWidget; 34 | 35 | /// Show [ThepeerDirectChargeView] Logs 36 | final bool showLogs; 37 | 38 | /// Toggle dismissible mode 39 | final bool isDismissible; 40 | 41 | const ThepeerDirectChargeView({ 42 | Key? key, 43 | required this.data, 44 | this.errorWidget, 45 | this.onSuccess, 46 | this.onClosed, 47 | this.onError, 48 | this.showLogs = false, 49 | this.isDismissible = false, 50 | }) : super(key: key); 51 | 52 | /// Show Dialog with a custom child 53 | Future show(BuildContext context) => showCupertinoModalBottomSheet( 54 | backgroundColor: Colors.white, 55 | shape: const RoundedRectangleBorder( 56 | borderRadius: BorderRadius.only( 57 | topLeft: Radius.circular(10), 58 | topRight: Radius.circular(10), 59 | ), 60 | ), 61 | isDismissible: isDismissible, 62 | enableDrag: isDismissible, 63 | context: context, 64 | builder: (context) => ClipRRect( 65 | borderRadius: const BorderRadius.only( 66 | topLeft: Radius.circular(10), 67 | topRight: Radius.circular(10), 68 | ), 69 | child: SizedBox( 70 | height: MediaQuery.of(context).size.height, 71 | child: Column( 72 | mainAxisAlignment: MainAxisAlignment.center, 73 | children: [ 74 | Center( 75 | child: SizedBox( 76 | height: context.screenHeight(.9), 77 | child: ThepeerDirectChargeView( 78 | data: data, 79 | onClosed: onClosed, 80 | onSuccess: onSuccess, 81 | onError: onError, 82 | showLogs: showLogs, 83 | errorWidget: errorWidget, 84 | ), 85 | ), 86 | ), 87 | ], 88 | ), 89 | ), 90 | ), 91 | ); 92 | 93 | @override 94 | _ThepeerDirectChargeViewState createState() => 95 | _ThepeerDirectChargeViewState(); 96 | } 97 | 98 | class _ThepeerDirectChargeViewState extends State { 99 | late final WebViewController _controller; 100 | 101 | bool _isLoading = true; 102 | bool get isLoading => _isLoading; 103 | set isLoading(bool val) { 104 | _isLoading = val; 105 | setState(() {}); 106 | } 107 | 108 | bool _hasError = false; 109 | bool get hasError => _hasError; 110 | set hasError(bool val) { 111 | _hasError = val; 112 | setState(() {}); 113 | } 114 | 115 | int? _loadingPercent; 116 | int? get loadingPercent => _loadingPercent; 117 | set loadingPercent(int? val) { 118 | _loadingPercent = val; 119 | setState(() {}); 120 | } 121 | 122 | String get createUrl => ThepeerFunctions.createUrl( 123 | data: widget.data, 124 | sdkType: 'directCharge', 125 | ).toString(); 126 | 127 | @override 128 | void initState() { 129 | super.initState(); 130 | _handleInit(); 131 | } 132 | 133 | @override 134 | Widget build(BuildContext context) { 135 | return Scaffold( 136 | backgroundColor: Colors.transparent, 137 | body: FutureBuilder( 138 | future: Connectivity().checkConnectivity(), 139 | builder: (context, snapshot) { 140 | /// Show error view 141 | if (hasError == true) { 142 | return Center( 143 | child: widget.errorWidget ?? 144 | ThepeerErrorView( 145 | onClosed: widget.onClosed, 146 | reload: () async { 147 | setState(() {}); 148 | await _controller.reload(); 149 | }, 150 | ), 151 | ); 152 | } 153 | 154 | if (snapshot.hasData == true && 155 | snapshot.data != ConnectivityResult.none) { 156 | return Stack( 157 | alignment: Alignment.center, 158 | children: [ 159 | if (isLoading == true) ...[ 160 | const PeerLoader(), 161 | ], 162 | 163 | /// Thepeer Webview 164 | AnimatedOpacity( 165 | duration: const Duration(milliseconds: 400), 166 | opacity: isLoading == true ? 0 : 1, 167 | child: WebViewWidget( 168 | controller: _controller, 169 | ), 170 | ), 171 | ], 172 | ); 173 | } else { 174 | return CupertinoActivityIndicator(); 175 | } 176 | }, 177 | ), 178 | ); 179 | } 180 | 181 | /// Inject JS code to be run in webview 182 | Future _injectPeerStack(WebViewController controller) { 183 | return controller.runJavaScript( 184 | ThepeerFunctions.peerMessageHandler( 185 | 'ThepeerDirectChargeClientInterface', 186 | ), 187 | ); 188 | } 189 | 190 | /// Parse event from javascript channel 191 | void _handleResponse(String res) async { 192 | try { 193 | final data = ThepeerEventModel.fromJson(res); 194 | switch (data.type) { 195 | case DIRECT_DEBIT_SUCCESS: 196 | if (widget.onSuccess != null) { 197 | widget.onSuccess!(data); 198 | } 199 | 200 | return; 201 | case DIRECT_DEBIT_CLOSE: 202 | if (mounted && widget.onClosed != null) widget.onClosed!(); 203 | 204 | return; 205 | default: 206 | if (mounted && widget.onError != null) widget.onError!(res); 207 | return; 208 | } 209 | } catch (e) { 210 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 211 | } 212 | } 213 | 214 | /// Handle WebView initialization 215 | void _handleInit() async { 216 | await SystemChannels.textInput.invokeMethod('TextInput.hide'); 217 | 218 | final WebViewController controller = 219 | WebViewController.fromPlatformCreationParams( 220 | PlatformWebViewControllerCreationParams()); 221 | 222 | controller 223 | ..enableZoom(false) 224 | ..setJavaScriptMode(JavaScriptMode.unrestricted) 225 | ..addJavaScriptChannel('ThepeerDirectChargeClientInterface', 226 | onMessageReceived: _onMessageReceived) 227 | ..setNavigationDelegate(NavigationDelegate( 228 | onPageStarted: (_) async { 229 | isLoading = true; 230 | }, 231 | onWebResourceError: (e) { 232 | hasError = true; 233 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 234 | }, 235 | onPageFinished: (_) async { 236 | isLoading = false; 237 | await _injectPeerStack(_controller); 238 | }, 239 | onNavigationRequest: _handleNavigationInterceptor)) 240 | ..loadRequest(Uri.parse('$createUrl')); 241 | _controller = controller; 242 | } 243 | 244 | /// Javascript channel onMessageRecieved for events sent by Thepeer 245 | void _onMessageReceived(JavaScriptMessage data) { 246 | try { 247 | if (widget.showLogs) ThepeerFunctions.log('Event: -> ${data.message}'); 248 | _handleResponse(data.message); 249 | } on Exception { 250 | if (mounted && widget.onClosed != null) widget.onClosed!(); 251 | } catch (e) { 252 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 253 | } 254 | } 255 | 256 | NavigationDecision _handleNavigationInterceptor(NavigationRequest request) { 257 | final url = request.url.toLowerCase(); 258 | 259 | if (url.contains(ThepeerFunctions.domainName)) { 260 | // Navigate to all urls contianing Thepeer 261 | return NavigationDecision.navigate; 262 | } else { 263 | //Prevent external navigations from opening in the webview and open in an external browser instead. 264 | ThepeerFunctions.launchExternalUrl(url: url, showLogs: (widget.showLogs)); 265 | return NavigationDecision.prevent; 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /lib/src/views/the_peer_error_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:gap/gap.dart'; 4 | import 'package:thepeer_flutter/src/const/const.dart'; 5 | import 'package:thepeer_flutter/src/utils/colors.dart'; 6 | import 'package:thepeer_flutter/src/widgets/the_peer_button.dart'; 7 | import 'package:thepeer_flutter/src/widgets/touchable_opacity.dart'; 8 | 9 | /// ThepeerErrorView States Widget 10 | class ThepeerErrorView extends StatelessWidget { 11 | final VoidCallback reload; 12 | final VoidCallback? onClosed; 13 | 14 | const ThepeerErrorView({ 15 | Key? key, 16 | this.onClosed, 17 | required this.reload, 18 | }) : super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Container( 25 | padding: const EdgeInsets.only( 26 | left: 20, 27 | right: 20, 28 | top: 38, 29 | ), 30 | child: Column( 31 | crossAxisAlignment: CrossAxisAlignment.start, 32 | children: [ 33 | PeerHeader( 34 | onClosed: onClosed, 35 | showClose: true, 36 | ), 37 | ], 38 | ), 39 | ), 40 | Flexible( 41 | child: ListView( 42 | padding: const EdgeInsets.all(16), 43 | physics: const BouncingScrollPhysics(), 44 | children: [ 45 | const Gap(80), 46 | SvgPicture.asset( 47 | 'assets/images/warning_badge.svg', 48 | package: package, 49 | ), 50 | const Gap(45), 51 | const Center( 52 | child: Text( 53 | 'Something went wrong', 54 | style: TextStyle( 55 | fontFamily: 'Gilroy-Bold', 56 | package: package, 57 | fontSize: 24, 58 | color: peerBoldTextColor, 59 | ), 60 | ), 61 | ), 62 | const Gap(14), 63 | const Center( 64 | child: Padding( 65 | padding: EdgeInsets.symmetric(horizontal: 30), 66 | child: Text( 67 | 'Please check your internet connection', 68 | textAlign: TextAlign.center, 69 | style: TextStyle( 70 | fontFamily: 'Gilroy-Medium', 71 | package: package, 72 | fontSize: 15, 73 | color: peerTextColor, 74 | ), 75 | ), 76 | ), 77 | ), 78 | const Gap(32), 79 | PeerButton( 80 | title: 'Reload', 81 | buttonColor: Colors.white, 82 | textColor: peerBlue, 83 | isUnderlined: true, 84 | onTap: reload, 85 | ) 86 | ], 87 | ), 88 | ), 89 | Row( 90 | mainAxisAlignment: MainAxisAlignment.center, 91 | children: [ 92 | const Text( 93 | 'Powered by', 94 | style: TextStyle( 95 | fontFamily: 'Gilroy-Medium', 96 | package: package, 97 | fontSize: 14, 98 | color: peerLightTextColor, 99 | ), 100 | ), 101 | const Gap(4), 102 | Image.asset( 103 | 'assets/images/logo.png', 104 | package: package, 105 | height: 18, 106 | ), 107 | ], 108 | ), 109 | const Gap(32), 110 | ], 111 | ); 112 | } 113 | } 114 | 115 | /// Peer Header Widget 116 | class PeerHeader extends StatelessWidget { 117 | final bool showClose; 118 | final VoidCallback? onClosed; 119 | 120 | const PeerHeader({ 121 | Key? key, 122 | this.showClose = false, 123 | this.onClosed, 124 | }) : super(key: key); 125 | 126 | @override 127 | Widget build(BuildContext context) { 128 | return Row( 129 | children: [ 130 | const Spacer(), 131 | TouchableOpacity( 132 | onTap: onClosed ?? () {}, 133 | child: SizedBox( 134 | height: 40, 135 | width: 40, 136 | child: Column( 137 | crossAxisAlignment: CrossAxisAlignment.end, 138 | children: [ 139 | SvgPicture.asset( 140 | 'assets/images/close.svg', 141 | package: package, 142 | ), 143 | ], 144 | ), 145 | ), 146 | ), 147 | ], 148 | ); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /lib/src/views/the_peer_send_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:connectivity_plus/connectivity_plus.dart'; 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; 8 | import 'package:thepeer_flutter/src/const/const.dart'; 9 | import 'package:thepeer_flutter/src/model/the_peer_event_model.dart'; 10 | import 'package:thepeer_flutter/src/utils/functions.dart'; 11 | import 'package:thepeer_flutter/src/widgets/the_peer_loader.dart'; 12 | import 'package:webview_flutter/webview_flutter.dart'; 13 | 14 | import 'package:thepeer_flutter/src/model/thepeer_data.dart'; 15 | import 'package:thepeer_flutter/src/utils/extensions.dart'; 16 | 17 | import 'package:thepeer_flutter/src/views/the_peer_error_view.dart'; 18 | 19 | class ThepeerSendView extends StatefulWidget { 20 | /// Public Key from your https://app.withThepeer.com/apps 21 | final ThepeerData data; 22 | 23 | /// Success callback 24 | final ValueChanged? onSuccess; 25 | 26 | /// Error callback 27 | final ValueChanged? onError; 28 | 29 | /// Thepeer popup Close callback 30 | final VoidCallback? onClosed; 31 | 32 | /// Error Widget will show if loading fails 33 | final Widget? errorWidget; 34 | 35 | /// Show [ThepeerSendView] Logs 36 | final bool showLogs; 37 | 38 | /// Toggle dismissible mode 39 | final bool isDismissible; 40 | 41 | const ThepeerSendView({ 42 | Key? key, 43 | required this.data, 44 | this.errorWidget, 45 | this.onSuccess, 46 | this.onClosed, 47 | this.onError, 48 | this.showLogs = false, 49 | this.isDismissible = false, 50 | }) : super(key: key); 51 | 52 | /// Show Dialog with a custom child 53 | Future show(BuildContext context) => showCupertinoModalBottomSheet( 54 | backgroundColor: Colors.white, 55 | shape: const RoundedRectangleBorder( 56 | borderRadius: BorderRadius.only( 57 | topLeft: Radius.circular(10), 58 | topRight: Radius.circular(10), 59 | ), 60 | ), 61 | isDismissible: isDismissible, 62 | enableDrag: isDismissible, 63 | context: context, 64 | builder: (context) => ClipRRect( 65 | borderRadius: const BorderRadius.only( 66 | topLeft: Radius.circular(10), 67 | topRight: Radius.circular(10), 68 | ), 69 | child: SizedBox( 70 | height: MediaQuery.of(context).size.height, 71 | child: Column( 72 | mainAxisAlignment: MainAxisAlignment.center, 73 | children: [ 74 | Center( 75 | child: SizedBox( 76 | height: context.screenHeight(.9), 77 | child: ThepeerSendView( 78 | data: data, 79 | onClosed: onClosed, 80 | onSuccess: onSuccess, 81 | onError: onError, 82 | showLogs: showLogs, 83 | errorWidget: errorWidget, 84 | ), 85 | ), 86 | ), 87 | ], 88 | ), 89 | ), 90 | ), 91 | ); 92 | 93 | @override 94 | _ThepeerSendViewState createState() => _ThepeerSendViewState(); 95 | } 96 | 97 | class _ThepeerSendViewState extends State { 98 | late final WebViewController _controller; 99 | 100 | bool _isLoading = true; 101 | bool get isLoading => _isLoading; 102 | set isLoading(bool val) { 103 | setState(() { 104 | _isLoading = val; 105 | }); 106 | } 107 | 108 | bool _hasError = false; 109 | bool get hasError => _hasError; 110 | set hasError(bool val) { 111 | setState(() { 112 | _hasError = val; 113 | }); 114 | } 115 | 116 | @override 117 | void initState() { 118 | super.initState(); 119 | _handleInit(); 120 | } 121 | 122 | String get createUrl => ThepeerFunctions.createUrl( 123 | data: widget.data, 124 | sdkType: 'send', 125 | ).toString(); 126 | 127 | @override 128 | Widget build(BuildContext context) { 129 | return Scaffold( 130 | backgroundColor: Colors.transparent, 131 | body: FutureBuilder( 132 | future: Connectivity().checkConnectivity(), 133 | builder: (context, snapshot) { 134 | /// Show error view 135 | if (hasError == true) { 136 | return Center( 137 | child: widget.errorWidget ?? 138 | ThepeerErrorView( 139 | onClosed: widget.onClosed, 140 | reload: () async { 141 | await _controller.reload(); 142 | }, 143 | ), 144 | ); 145 | } 146 | 147 | if (snapshot.hasData == true && 148 | snapshot.data != ConnectivityResult.none) { 149 | return Stack( 150 | alignment: Alignment.center, 151 | children: [ 152 | if (isLoading == true && hasError == false) ...[ 153 | const PeerLoader(), 154 | ], 155 | 156 | /// Thepeer Webview 157 | WebViewWidget( 158 | controller: _controller, 159 | ), 160 | ], 161 | ); 162 | } else { 163 | return const Center(child: CupertinoActivityIndicator()); 164 | } 165 | }, 166 | ), 167 | ); 168 | } 169 | 170 | /// Inject JS code to be run in webview 171 | Future _injectPeerStack(WebViewController controller) async { 172 | await controller.runJavaScript( 173 | ThepeerFunctions.peerMessageHandler( 174 | 'ThepeerSendClientInterface', 175 | ), 176 | ); 177 | } 178 | 179 | /// Parse event from javascript channel 180 | void _handleResponse(String res) async { 181 | try { 182 | final data = ThepeerEventModel.fromJson(res); 183 | switch (data.type) { 184 | case SEND_SUCCESS: 185 | if (widget.onSuccess != null) { 186 | widget.onSuccess!(data); 187 | } 188 | return; 189 | case SEND_CLOSE: 190 | if (mounted && widget.onClosed != null) widget.onClosed!(); 191 | return; 192 | default: 193 | if (mounted && widget.onError != null) widget.onError!(res); 194 | return; 195 | } 196 | } catch (e) { 197 | if (widget.showLogs == true) ThepeerFunctions.log(e.toString()); 198 | } 199 | } 200 | 201 | /// Handle WebView initialization 202 | void _handleInit() async { 203 | await SystemChannels.textInput.invokeMethod('TextInput.hide'); 204 | 205 | final WebViewController controller = 206 | WebViewController.fromPlatformCreationParams( 207 | PlatformWebViewControllerCreationParams()); 208 | 209 | controller 210 | ..enableZoom(false) 211 | ..setJavaScriptMode(JavaScriptMode.unrestricted) 212 | ..addJavaScriptChannel('ThepeerSendClientInterface', 213 | onMessageReceived: _onMessageReceived) 214 | ..setNavigationDelegate(NavigationDelegate( 215 | onPageStarted: (_) async { 216 | isLoading = true; 217 | }, 218 | onWebResourceError: (e) { 219 | hasError = true; 220 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 221 | }, 222 | onPageFinished: (_) async { 223 | isLoading = false; 224 | await _injectPeerStack(_controller); 225 | }, 226 | onNavigationRequest: _handleNavigationInterceptor)) 227 | ..loadRequest(Uri.parse('$createUrl')); 228 | _controller = controller; 229 | } 230 | 231 | /// Javascript channel onMessageRecieved for events sent by Thepeer 232 | 233 | void _onMessageReceived(JavaScriptMessage data) { 234 | try { 235 | if (widget.showLogs) ThepeerFunctions.log('Event: -> ${data.message}'); 236 | _handleResponse(data.message); 237 | } on Exception { 238 | if (mounted && widget.onClosed != null) widget.onClosed!(); 239 | } catch (e) { 240 | if (widget.showLogs) ThepeerFunctions.log(e.toString()); 241 | } 242 | } 243 | 244 | NavigationDecision _handleNavigationInterceptor(NavigationRequest request) { 245 | final url = request.url.toLowerCase(); 246 | 247 | if (url.contains(ThepeerFunctions.domainName)) { 248 | // Navigate to all urls contianing Thepeer 249 | return NavigationDecision.navigate; 250 | } else { 251 | //Prevent external navigations from opening in the webview and open in an external browser instead. 252 | ThepeerFunctions.launchExternalUrl(url: url, showLogs: (widget.showLogs)); 253 | return NavigationDecision.prevent; 254 | } 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /lib/src/widgets/the_peer_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:thepeer_flutter/src/const/const.dart'; 3 | import 'package:thepeer_flutter/src/utils/colors.dart'; 4 | 5 | import 'package:thepeer_flutter/src/widgets/touchable_opacity.dart'; 6 | 7 | /// Peer Button Widget 8 | class PeerButton extends StatelessWidget { 9 | final String title; 10 | final VoidCallback? onTap; 11 | final bool enabled, isUnderlined; 12 | final Color? textColor, buttonColor; 13 | 14 | const PeerButton({ 15 | required this.title, 16 | Key? key, 17 | this.enabled = true, 18 | this.isUnderlined = false, 19 | this.onTap, 20 | this.textColor, 21 | this.buttonColor, 22 | }) : super(key: key); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return TouchableOpacity( 27 | onTap: onTap, 28 | disabled: enabled == false, 29 | child: ClipRRect( 30 | borderRadius: BorderRadius.circular(6), 31 | child: Container( 32 | color: 33 | (buttonColor ?? peerBlue).withOpacity(enabled == true ? 1 : 0.3), 34 | padding: const EdgeInsets.all(18), 35 | child: Center( 36 | child: Text( 37 | title, 38 | style: TextStyle( 39 | fontFamily: 'Gilroy-SemiBold', 40 | package: package, 41 | fontSize: 16, 42 | color: textColor ?? Colors.white, 43 | decoration: isUnderlined ? TextDecoration.underline : null, 44 | ), 45 | ), 46 | ), 47 | ), 48 | ), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/widgets/the_peer_loader.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | /// Platform-aware activity indicator 6 | class PeerLoader extends StatelessWidget { 7 | const PeerLoader({ 8 | Key? key, 9 | this.materialStrokeWidth = 1.5, 10 | this.height, 11 | }) : super(key: key); 12 | 13 | final double? height; 14 | final double materialStrokeWidth; 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | if (defaultTargetPlatform == TargetPlatform.android) { 19 | return SizedBox( 20 | height: height ?? 20, 21 | width: height ?? 20, 22 | child: Center( 23 | child: AspectRatio( 24 | aspectRatio: 1.0, 25 | child: CircularProgressIndicator(strokeWidth: materialStrokeWidth), 26 | ), 27 | ), 28 | ); 29 | } 30 | 31 | return const CupertinoActivityIndicator(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/widgets/touchable_opacity.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | /// Recreates a touchable opacity from React Native. On tap down, the opacity of the 4 | /// child is decreased, dimming it. Use this in place of a Container and it will include 5 | /// tap events. 6 | /// 7 | /// [child] (required) is what will be displayed within the touchable highlight on top of the background color. 8 | /// 9 | /// [onTap] is the callback which will execute when tapped. 10 | /// 11 | /// [onLongPress] callback executed on long press event. 12 | /// 13 | /// [width] width supplied to the enclosing container. 14 | /// 15 | /// [height] height supplied to the enclosing container 16 | /// 17 | /// [decoration] decoration supplied to the enclosing container. 18 | class TouchableOpacity extends StatefulWidget { 19 | const TouchableOpacity({ 20 | required this.child, 21 | this.onTap, 22 | this.onLongPress, 23 | this.decoration, 24 | this.width, 25 | this.height, 26 | Key? key, 27 | this.behavior = HitTestBehavior.opaque, 28 | this.disabled = false, 29 | this.onTapDown, 30 | this.onTapUp, 31 | this.onTapCancel, 32 | }) : super(key: key); 33 | final Widget child; 34 | final double? width; 35 | final double? height; 36 | final VoidCallback? onTap; 37 | final VoidCallback? onLongPress; 38 | final BoxDecoration? decoration; 39 | final HitTestBehavior behavior; 40 | final bool disabled; 41 | final VoidCallback? onTapDown; 42 | final VoidCallback? onTapUp; 43 | final VoidCallback? onTapCancel; 44 | 45 | @override 46 | _TouchableOpacityState createState() => _TouchableOpacityState(); 47 | } 48 | 49 | class _TouchableOpacityState extends State { 50 | bool isTappedDown = false; 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return RepaintBoundary( 55 | child: GestureDetector( 56 | behavior: widget.behavior, 57 | onTapDown: (tapDownDetails) { 58 | if (widget.disabled) { 59 | return; 60 | } 61 | 62 | setState(() { 63 | isTappedDown = true; 64 | }); 65 | 66 | if (widget.onTapDown != null) { 67 | widget.onTapDown!(); 68 | } 69 | }, 70 | onTapUp: (tapUpDetails) { 71 | setState(() { 72 | isTappedDown = false; 73 | }); 74 | 75 | if (widget.onTapUp != null) { 76 | widget.onTapUp!(); 77 | } 78 | }, 79 | onTapCancel: () { 80 | setState(() { 81 | isTappedDown = false; 82 | }); 83 | 84 | if (widget.onTapCancel != null) { 85 | widget.onTapCancel!(); 86 | } 87 | }, 88 | onTap: widget.disabled ? null : widget.onTap, 89 | onLongPress: widget.disabled ? null : widget.onLongPress, 90 | child: AnimatedOpacity( 91 | opacity: isTappedDown ? 0.6 : 1.0, 92 | duration: const Duration(milliseconds: 300), 93 | child: Container( 94 | width: widget.width, 95 | height: widget.height, 96 | decoration: widget.decoration, 97 | child: widget.child, 98 | ), 99 | ), 100 | ), 101 | ); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/thepeer_flutter.dart: -------------------------------------------------------------------------------- 1 | library thepeer_flutter; 2 | 3 | export 'src/model/thepeer_data.dart'; 4 | export 'src/views/the_peer_send_view.dart'; 5 | export 'src/views/the_peer_checkout_view.dart'; 6 | export 'src/views/the_peer_direct_charge_view.dart'; 7 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | args: 5 | dependency: transitive 6 | description: 7 | name: args 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.3.0" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.9.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.1" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.16.0" 46 | connectivity_plus: 47 | dependency: "direct main" 48 | description: 49 | name: connectivity_plus 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "3.0.2" 53 | connectivity_plus_platform_interface: 54 | dependency: transitive 55 | description: 56 | name: connectivity_plus_platform_interface 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.3" 60 | dbus: 61 | dependency: transitive 62 | description: 63 | name: dbus 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.7.1" 67 | equatable: 68 | dependency: "direct main" 69 | description: 70 | name: equatable 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.0.3" 74 | fake_async: 75 | dependency: transitive 76 | description: 77 | name: fake_async 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.3.1" 81 | ffi: 82 | dependency: transitive 83 | description: 84 | name: ffi 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "1.1.2" 88 | flutter: 89 | dependency: "direct main" 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | flutter_svg: 94 | dependency: "direct main" 95 | description: 96 | name: flutter_svg 97 | url: "https://pub.dartlang.org" 98 | source: hosted 99 | version: "1.0.3" 100 | flutter_test: 101 | dependency: "direct dev" 102 | description: flutter 103 | source: sdk 104 | version: "0.0.0" 105 | flutter_web_plugins: 106 | dependency: transitive 107 | description: flutter 108 | source: sdk 109 | version: "0.0.0" 110 | gap: 111 | dependency: "direct main" 112 | description: 113 | name: gap 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "2.0.0" 117 | js: 118 | dependency: transitive 119 | description: 120 | name: js 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "0.6.4" 124 | matcher: 125 | dependency: transitive 126 | description: 127 | name: matcher 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "0.12.12" 131 | material_color_utilities: 132 | dependency: transitive 133 | description: 134 | name: material_color_utilities 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "0.1.5" 138 | meta: 139 | dependency: transitive 140 | description: 141 | name: meta 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.8.0" 145 | modal_bottom_sheet: 146 | dependency: "direct main" 147 | description: 148 | name: modal_bottom_sheet 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.0.1" 152 | nm: 153 | dependency: transitive 154 | description: 155 | name: nm 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "0.5.0" 159 | path: 160 | dependency: transitive 161 | description: 162 | name: path 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.8.2" 166 | path_drawing: 167 | dependency: transitive 168 | description: 169 | name: path_drawing 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.0.0" 173 | path_parsing: 174 | dependency: transitive 175 | description: 176 | name: path_parsing 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.0.0" 180 | petitparser: 181 | dependency: transitive 182 | description: 183 | name: petitparser 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "4.1.0" 187 | plugin_platform_interface: 188 | dependency: transitive 189 | description: 190 | name: plugin_platform_interface 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "2.1.3" 194 | sky_engine: 195 | dependency: transitive 196 | description: flutter 197 | source: sdk 198 | version: "0.0.99" 199 | source_span: 200 | dependency: transitive 201 | description: 202 | name: source_span 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "1.9.0" 206 | stack_trace: 207 | dependency: transitive 208 | description: 209 | name: stack_trace 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "1.10.0" 213 | stream_channel: 214 | dependency: transitive 215 | description: 216 | name: stream_channel 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "2.1.0" 220 | string_scanner: 221 | dependency: transitive 222 | description: 223 | name: string_scanner 224 | url: "https://pub.dartlang.org" 225 | source: hosted 226 | version: "1.1.1" 227 | term_glyph: 228 | dependency: transitive 229 | description: 230 | name: term_glyph 231 | url: "https://pub.dartlang.org" 232 | source: hosted 233 | version: "1.2.1" 234 | test_api: 235 | dependency: transitive 236 | description: 237 | name: test_api 238 | url: "https://pub.dartlang.org" 239 | source: hosted 240 | version: "0.4.12" 241 | url_launcher: 242 | dependency: "direct main" 243 | description: 244 | name: url_launcher 245 | url: "https://pub.dartlang.org" 246 | source: hosted 247 | version: "6.1.0" 248 | url_launcher_android: 249 | dependency: transitive 250 | description: 251 | name: url_launcher_android 252 | url: "https://pub.dartlang.org" 253 | source: hosted 254 | version: "6.0.16" 255 | url_launcher_ios: 256 | dependency: transitive 257 | description: 258 | name: url_launcher_ios 259 | url: "https://pub.dartlang.org" 260 | source: hosted 261 | version: "6.0.15" 262 | url_launcher_linux: 263 | dependency: transitive 264 | description: 265 | name: url_launcher_linux 266 | url: "https://pub.dartlang.org" 267 | source: hosted 268 | version: "2.0.2" 269 | url_launcher_macos: 270 | dependency: transitive 271 | description: 272 | name: url_launcher_macos 273 | url: "https://pub.dartlang.org" 274 | source: hosted 275 | version: "2.0.2" 276 | url_launcher_platform_interface: 277 | dependency: transitive 278 | description: 279 | name: url_launcher_platform_interface 280 | url: "https://pub.dartlang.org" 281 | source: hosted 282 | version: "2.0.4" 283 | url_launcher_web: 284 | dependency: transitive 285 | description: 286 | name: url_launcher_web 287 | url: "https://pub.dartlang.org" 288 | source: hosted 289 | version: "2.0.4" 290 | url_launcher_windows: 291 | dependency: transitive 292 | description: 293 | name: url_launcher_windows 294 | url: "https://pub.dartlang.org" 295 | source: hosted 296 | version: "2.0.2" 297 | vector_math: 298 | dependency: transitive 299 | description: 300 | name: vector_math 301 | url: "https://pub.dartlang.org" 302 | source: hosted 303 | version: "2.1.2" 304 | webview_flutter: 305 | dependency: "direct main" 306 | description: 307 | name: webview_flutter 308 | url: "https://pub.dartlang.org" 309 | source: hosted 310 | version: "4.0.1" 311 | webview_flutter_android: 312 | dependency: transitive 313 | description: 314 | name: webview_flutter_android 315 | url: "https://pub.dartlang.org" 316 | source: hosted 317 | version: "3.1.3" 318 | webview_flutter_platform_interface: 319 | dependency: transitive 320 | description: 321 | name: webview_flutter_platform_interface 322 | url: "https://pub.dartlang.org" 323 | source: hosted 324 | version: "2.0.1" 325 | webview_flutter_wkwebview: 326 | dependency: transitive 327 | description: 328 | name: webview_flutter_wkwebview 329 | url: "https://pub.dartlang.org" 330 | source: hosted 331 | version: "3.0.2" 332 | xml: 333 | dependency: transitive 334 | description: 335 | name: xml 336 | url: "https://pub.dartlang.org" 337 | source: hosted 338 | version: "5.1.2" 339 | sdks: 340 | dart: ">=2.17.0 <3.0.0" 341 | flutter: ">=3.0.0" 342 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: thepeer_flutter 2 | description: Official plugin for using Thepeer SDK with flutter https://thepeer.co 3 | version: 2.0.12 4 | homepage: https://github.com/thepeerstack/flutter-sdk 5 | 6 | environment: 7 | sdk: ">=2.17.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | connectivity_plus: ^3.0.2 13 | equatable: ^2.0.3 14 | flutter_svg: ^1.0.3 15 | gap: ^2.0.1 16 | modal_bottom_sheet: ^3.0.0-pre 17 | webview_flutter: ^4.0.6 18 | webview_flutter_android: ^3.1.3 19 | url_launcher: ^6.1.0 20 | 21 | dev_dependencies: 22 | flutter_test: 23 | sdk: flutter 24 | 25 | flutter: 26 | assets: 27 | - packages/thepeer_flutter/assets/images/logo.png 28 | - packages/thepeer_flutter/assets/images/close.svg 29 | - packages/thepeer_flutter/assets/images/warning_badge.svg 30 | 31 | fonts: 32 | - family: Gilroy-Bold 33 | fonts: 34 | - asset: packages/thepeer_flutter/assets/fonts/Gilroy-Bold.ttf 35 | weight: 700 36 | 37 | - family: Gilroy-SemiBold 38 | fonts: 39 | - asset: packages/thepeer_flutter/assets/fonts/Gilroy-SemiBold.ttf 40 | weight: 600 41 | 42 | - family: Gilroy-Medium 43 | fonts: 44 | - asset: packages/thepeer_flutter/assets/fonts/Gilroy-Medium.ttf 45 | weight: 500 46 | -------------------------------------------------------------------------------- /test/flutter_thepeer_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | test('adds one to input values', () {}); 5 | } 6 | --------------------------------------------------------------------------------