├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── app │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ └── stllpt │ │ │ └── com │ │ │ └── flutterpaginationhelper │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── 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 │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── ios ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ └── contents.xcworkspacedata └── 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 ├── demo │ ├── custom_progress_pagination.dart │ ├── default_progress_pagination.dart │ ├── hackerNewsIntegration │ │ ├── circular_progress_indicator.dart │ │ ├── error_text_widget.dart │ │ ├── hacker_news_list.dart │ │ ├── news_home.dart │ │ ├── news_ids_list.dart │ │ ├── news_ids_list.g.dart │ │ ├── news_list_bloc.dart │ │ ├── news_list_item.dart │ │ ├── news_response.dart │ │ └── news_response.g.dart │ ├── list_item.dart │ ├── main.dart │ └── pagination_error.dart └── pagination_helper │ ├── bloc_provider.dart │ ├── event_model.dart │ ├── item_list_callback.dart │ ├── list_helper.dart │ ├── list_widget.dart │ ├── pagination_bloc.dart │ ├── progressbar.dart │ └── widget_list.dart ├── pubspec.yaml └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/dart,xcode,swift,kotlin,android,flutter,cocoapods,darteditor,objective-c,androidstudio 3 | # Edit at https://www.gitignore.io/?templates=dart,xcode,swift,kotlin,android,flutter,cocoapods,darteditor,objective-c,androidstudio 4 | 5 | ### Android ### 6 | # Built application files 7 | *.apk 8 | *.ap_ 9 | *.aab 10 | 11 | # Files for the ART/Dalvik VM 12 | *.dex 13 | 14 | # Java class files 15 | *.class 16 | 17 | # Generated files 18 | bin/ 19 | gen/ 20 | out/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | 26 | # Local configuration file (sdk path, etc) 27 | local.properties 28 | 29 | # Proguard folder generated by Eclipse 30 | proguard/ 31 | 32 | # Log Files 33 | *.log 34 | 35 | # Android Studio Navigation editor temp files 36 | .navigation/ 37 | 38 | # Android Studio captures folder 39 | captures/ 40 | 41 | # IntelliJ 42 | *.iml 43 | .idea/workspace.xml 44 | .idea/tasks.xml 45 | .idea/gradle.xml 46 | .idea/assetWizardSettings.xml 47 | .idea/dictionaries 48 | .idea/libraries 49 | .idea/caches 50 | 51 | # Keystore files 52 | # Uncomment the following lines if you do not want to check your keystore files in. 53 | #*.jks 54 | #*.keystore 55 | 56 | # External native build folder generated in Android Studio 2.2 and later 57 | .externalNativeBuild 58 | 59 | # Google Services (e.g. APIs or Firebase) 60 | google-services.json 61 | 62 | # Freeline 63 | freeline.py 64 | freeline/ 65 | freeline_project_description.json 66 | 67 | # fastlane 68 | fastlane/report.xml 69 | fastlane/Preview.html 70 | fastlane/screenshots 71 | fastlane/test_output 72 | fastlane/readme.md 73 | 74 | ### Android Patch ### 75 | gen-external-apklibs 76 | 77 | ### AndroidStudio ### 78 | # Covers files to be ignored for android development using Android Studio. 79 | 80 | # Built application files 81 | 82 | # Files for the ART/Dalvik VM 83 | 84 | # Java class files 85 | 86 | # Generated files 87 | 88 | # Gradle files 89 | .gradle 90 | 91 | # Signing files 92 | .signing/ 93 | 94 | # Local configuration file (sdk path, etc) 95 | 96 | # Proguard folder generated by Eclipse 97 | 98 | # Log Files 99 | 100 | # Android Studio 101 | /*/build/ 102 | /*/local.properties 103 | /*/out 104 | /*/*/build 105 | /*/*/production 106 | *.ipr 107 | *~ 108 | *.swp 109 | 110 | # Android Patch 111 | 112 | # External native build folder generated in Android Studio 2.2 and later 113 | 114 | # NDK 115 | obj/ 116 | 117 | # IntelliJ IDEA 118 | *.iws 119 | /out/ 120 | 121 | # User-specific configurations 122 | .idea/caches/ 123 | .idea/libraries/ 124 | .idea/shelf/ 125 | .idea/.name 126 | .idea/compiler.xml 127 | .idea/copyright/profiles_settings.xml 128 | .idea/encodings.xml 129 | .idea/misc.xml 130 | .idea/modules.xml 131 | .idea/scopes/scope_settings.xml 132 | .idea/vcs.xml 133 | .idea/jsLibraryMappings.xml 134 | .idea/datasources.xml 135 | .idea/dataSources.ids 136 | .idea/sqlDataSources.xml 137 | .idea/dynamic.xml 138 | .idea/uiDesigner.xml 139 | 140 | # OS-specific files 141 | .DS_Store 142 | .DS_Store? 143 | ._* 144 | .Spotlight-V100 145 | .Trashes 146 | ehthumbs.db 147 | Thumbs.db 148 | 149 | # Legacy Eclipse project files 150 | .classpath 151 | .project 152 | .cproject 153 | .settings/ 154 | 155 | # Mobile Tools for Java (J2ME) 156 | .mtj.tmp/ 157 | 158 | # Package Files # 159 | *.war 160 | *.ear 161 | 162 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 163 | hs_err_pid* 164 | 165 | ## Plugin-specific files: 166 | 167 | # mpeltonen/sbt-idea plugin 168 | .idea_modules/ 169 | 170 | # JIRA plugin 171 | atlassian-ide-plugin.xml 172 | 173 | # Mongo Explorer plugin 174 | .idea/mongoSettings.xml 175 | 176 | # Crashlytics plugin (for Android Studio and IntelliJ) 177 | com_crashlytics_export_strings.xml 178 | crashlytics.properties 179 | crashlytics-build.properties 180 | fabric.properties 181 | 182 | ### AndroidStudio Patch ### 183 | 184 | !/gradle/wrapper/gradle-wrapper.jar 185 | 186 | ### CocoaPods ### 187 | ## CocoaPods GitIgnore Template 188 | 189 | # CocoaPods - Only use to conserve bandwidth / Save time on Pushing 190 | # - Also handy if you have a large number of dependant pods 191 | # - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE 192 | Pods/ 193 | 194 | ### Dart ### 195 | # See https://www.dartlang.org/guides/libraries/private-files 196 | 197 | # Files and directories created by pub 198 | .dart_tool/ 199 | .packages 200 | # If you're building an application, you may want to check-in your pubspec.lock 201 | pubspec.lock 202 | 203 | # Directory created by dartdoc 204 | # If you don't generate documentation locally you can remove this line. 205 | doc/api/ 206 | 207 | # Avoid committing generated Javascript files: 208 | *.dart.js 209 | *.info.json # Produced by the --dump-info flag. 210 | *.js # When generated by dart2js. Don't specify *.js if your 211 | # project includes source files written in JavaScript. 212 | *.js_ 213 | *.js.deps 214 | *.js.map 215 | 216 | ### DartEditor ### 217 | .buildlog 218 | 219 | ### Flutter ### 220 | .flutter-plugins 221 | 222 | ### Kotlin ### 223 | # Compiled class file 224 | 225 | # Log file 226 | 227 | # BlueJ files 228 | *.ctxt 229 | 230 | # Mobile Tools for Java (J2ME) 231 | 232 | # Package Files # 233 | *.jar 234 | *.nar 235 | *.zip 236 | *.tar.gz 237 | *.rar 238 | 239 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 240 | 241 | ### Objective-C ### 242 | # Xcode 243 | # 244 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 245 | 246 | ## Build generated 247 | DerivedData/ 248 | 249 | ## Various settings 250 | *.pbxuser 251 | !default.pbxuser 252 | *.mode1v3 253 | !default.mode1v3 254 | *.mode2v3 255 | !default.mode2v3 256 | *.perspectivev3 257 | !default.perspectivev3 258 | xcuserdata/ 259 | 260 | ## Other 261 | *.moved-aside 262 | *.xccheckout 263 | *.xcscmblueprint 264 | 265 | ## Obj-C/Swift specific 266 | *.hmap 267 | *.ipa 268 | *.dSYM.zip 269 | *.dSYM 270 | 271 | # CocoaPods 272 | # 273 | # We recommend against adding the Pods directory to your .gitignore. However 274 | # you should judge for yourself, the pros and cons are mentioned at: 275 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 276 | # 277 | # Pods/ 278 | # 279 | # Add this line if you want to avoid checking in source code from the Xcode workspace 280 | # *.xcworkspace 281 | 282 | # Carthage 283 | # 284 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 285 | # Carthage/Checkouts 286 | 287 | Carthage/Build 288 | 289 | # fastlane 290 | # 291 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 292 | # screenshots whenever they are needed. 293 | # For more information about the recommended setup visit: 294 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 295 | 296 | fastlane/screenshots/**/*.png 297 | 298 | # Code Injection 299 | # 300 | # After new code Injection tools there's a generated folder /iOSInjectionProject 301 | # https://github.com/johnno1962/injectionforxcode 302 | 303 | iOSInjectionProject/ 304 | 305 | ### Objective-C Patch ### 306 | 307 | ### Swift ### 308 | # Xcode 309 | # 310 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 311 | 312 | ## Build generated 313 | 314 | ## Various settings 315 | 316 | ## Other 317 | 318 | ## Obj-C/Swift specific 319 | 320 | ## Playgrounds 321 | timeline.xctimeline 322 | playground.xcworkspace 323 | 324 | # Swift Package Manager 325 | # 326 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 327 | # Packages/ 328 | # Package.pins 329 | # Package.resolved 330 | .build/ 331 | 332 | # CocoaPods 333 | # 334 | # We recommend against adding the Pods directory to your .gitignore. However 335 | # you should judge for yourself, the pros and cons are mentioned at: 336 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 337 | # 338 | # Pods/ 339 | # 340 | # Add this line if you want to avoid checking in source code from the Xcode workspace 341 | # *.xcworkspace 342 | 343 | # Carthage 344 | # 345 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 346 | # Carthage/Checkouts 347 | 348 | 349 | # fastlane 350 | # 351 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 352 | # screenshots whenever they are needed. 353 | # For more information about the recommended setup visit: 354 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 355 | 356 | 357 | # Code Injection 358 | # 359 | # After new code Injection tools there's a generated folder /iOSInjectionProject 360 | # https://github.com/johnno1962/injectionforxcode 361 | 362 | 363 | ### Xcode ### 364 | # Xcode 365 | # 366 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 367 | 368 | ## User settings 369 | 370 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 371 | 372 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 373 | 374 | ### Xcode Patch ### 375 | *.xcodeproj/* 376 | !*.xcodeproj/project.pbxproj 377 | !*.xcodeproj/xcshareddata/ 378 | !*.xcworkspace/contents.xcworkspacedata 379 | /*.gcno 380 | **/xcshareddata/WorkspaceSettings.xcsettings 381 | 382 | # End of https://www.gitignore.io/api/dart,xcode,swift,kotlin,android,flutter,cocoapods,darteditor,objective-c,androidstudio 383 | 384 | 385 | ## FLUTTER DEFAULT ## 386 | 387 | # Miscellaneous 388 | *.class 389 | *.lock 390 | *.log 391 | *.pyc 392 | *.swp 393 | .DS_Store 394 | .atom/ 395 | .buildlog/ 396 | .history 397 | .svn/ 398 | 399 | # IntelliJ related 400 | *.iml 401 | *.ipr 402 | *.iws 403 | .idea/ 404 | 405 | # Visual Studio Code related 406 | .vscode/ 407 | 408 | # Flutter/Dart/Pub related 409 | **/doc/api/ 410 | .dart_tool/ 411 | .flutter-plugins 412 | .packages 413 | .pub-cache/ 414 | .pub/ 415 | build/ 416 | 417 | # Android related 418 | **/android/**/gradle-wrapper.jar 419 | **/android/.gradle 420 | **/android/captures/ 421 | **/android/gradlew 422 | **/android/gradlew.bat 423 | **/android/local.properties 424 | **/android/**/GeneratedPluginRegistrant.java 425 | 426 | # iOS/XCode related 427 | **/ios/**/*.mode1v3 428 | **/ios/**/*.mode2v3 429 | **/ios/**/*.moved-aside 430 | **/ios/**/*.pbxuser 431 | **/ios/**/*.perspectivev3 432 | **/ios/**/*sync/ 433 | **/ios/**/.sconsign.dblite 434 | **/ios/**/.tags* 435 | **/ios/**/.vagrant/ 436 | **/ios/**/DerivedData/ 437 | **/ios/**/Icon? 438 | **/ios/**/Pods/ 439 | **/ios/**/.symlinks/ 440 | **/ios/**/profile 441 | **/ios/**/xcuserdata 442 | **/ios/.generated/ 443 | **/ios/Flutter/App.framework 444 | **/ios/Flutter/Flutter.framework 445 | **/ios/Flutter/Generated.xcconfig 446 | **/ios/Flutter/app.flx 447 | **/ios/Flutter/app.zip 448 | **/ios/Flutter/flutter_assets/ 449 | **/ios/ServiceDefinitions.json 450 | **/ios/Runner/GeneratedPluginRegistrant.* 451 | 452 | # Exceptions to above rules. 453 | !**/ios/**/default.mode1v3 454 | !**/ios/**/default.mode2v3 455 | !**/ios/**/default.pbxuser 456 | !**/ios/**/default.perspectivev3 457 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 458 | 459 | ## END OF FLUTTER DEFAULT ## -------------------------------------------------------------------------------- /.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: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.0.1+2] - 2019-01-22 8 | ### Added 9 | - Updated dependency and sdk version. 10 | 11 | ## [1.0.0+6] - 2019-01-16 12 | ### Added 13 | - Update reference gifs. 14 | 15 | ## [1.0.0+5] - 2019-01-15 16 | ### Added 17 | - Resolve minor documentation issues [@akashMehta-STL](https://github.com/akashMehta-STL). 18 | 19 | ## [1.0.0+3] - 2019-01-15 20 | ### Added 21 | - Added CHANGELOG by [@akashMehta-STL](https://github.com/akashMehta-STL). 22 | 23 | ## [1.0.0+2] - 2019-01-15 24 | ### Added 25 | - Added demo with to flutter pagination helper sdk by [@akashMehta-STL](https://github.com/akashMehta-STL). 26 | 27 | ## [1.0.0+1] - 2019-01-14 28 | ### Added 29 | - Integrated flutter pagination helper logic by [@akashMehta-STL](https://github.com/akashMehta-STL). 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Aakash Mehta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter Pagination Helper 2 | 3 | Flutter pagination helper is used to reduce boilerplate code for pagination. 4 | 5 | ## Description 6 | 7 | Here we have optimised concept of Model from model-view-intent pattern as described by [hannes dorfmann](http://hannesdorfmann.com/android/mosby3-mvi-1). So as a short note you can use this dependency for pagination by providing the state of model retrieved from your business logic. This state could be from progress bar visibility, data, error or data loading completion. Here to show paginated list you need to pass only list of widget as a data. 8 | 9 | ![custom_progress](https://cdn-images-1.medium.com/max/873/1*gd08OhXynqAR6TSeQY--2g.gif) ![default_progress](https://cdn-images-1.medium.com/max/873/1*2yJapvIy7fs7mJPpBv6zIw.gif) 10 | 11 | ## Implementation 12 | 13 | To add flutter pagination helper dependency add following dependency in pubspec.yaml 14 | ``` 15 | dependencies: 16 | flutter_pagination_helper: ^1.0.1+2 17 | ``` 18 | 19 | ### Common usage 20 | 21 | * To use this dependency you have to assign `PaginatedListWidget` to the child of parent widget. In the code the prototype is mentioned to setup a paginated list. It can be retrived from `list_helper.dart` file. 22 | * In parameter you can optionally assign `progressWidget` if you need to design your custom widget as progress. You can change color for default progress by assigning `colorSwatch` parameter to your parent material app theme. 23 | * As 2nd parameter you have to assign `itemListCallback` which will be called each time user reach to end of listview. It can be retrived from `item_list_callback.dart` file. 24 | ``` 25 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 26 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 27 | import 'package:flutter_pagination_helper/pagination_helper/list_helper.dart'; 28 | 29 | class CustomProgressWidget extends StatelessWidget { 30 | @override 31 | Widget build(BuildContext context) { 32 | return MaterialApp( 33 | home: Scaffold( 34 | body: PaginatedListWidget( 35 | progressWidget: Center( 36 | child: Text("Loading..."), 37 | ), 38 | itemListCallback: OnScrollCallback()), 39 | ), 40 | ); 41 | } 42 | } 43 | ``` 44 | * In `itemListCallback` you have to implement your custom Callback as mentioned in code. It will return Future of generic type `EventModel`. 45 | ``` 46 | class OnScrollCallback extends ItemListCallback { 47 | @override 48 | Future> getItemList() { 49 | // TODO: implement getItemList 50 | return null; 51 | } 52 | } 53 | ``` 54 | * `EventModel` is ui model to distinguish state as mentioned in code. It will be retrieved from `event_model.dart` file. 55 | - Here `progress` indicates the visibility of progress bar while loading item. 56 | - `data` will be list of widgets which will be displayed in list view. [Note : This field will contain items which are not retrieved on previous call]. 57 | - `error` is a error message when api fails and it will be displayed as SnackBar. 58 | - `stopLoading` will be true when all items are retrieved and we need to stop pagination. 59 | ``` 60 | class EventModel { 61 | final bool progress; 62 | final List data; 63 | final String error; 64 | final bool stopLoading; 65 | 66 | EventModel({this.progress, this.data, this.error, this.stopLoading}); 67 | } 68 | 69 | ``` 70 | * Get the clear understanding for flutter pagination from this [article](https://medium.com/@AakashDMehta/paginate-your-data-in-flutter-7744995febd1). 71 | * You can refer following demo for different perspactive. 72 | * [Pagination with default progress widget.](https://github.com/akashMehta-STL/FlutterPaginationHelper/blob/master/lib/demo/default_progress_pagination.dart) 73 | * [Pagination with custom progress widget.](https://github.com/akashMehta-STL/FlutterPaginationHelper/blob/master/lib/demo/custom_progress_pagination.dart) 74 | * [Pagination with error message.](https://github.com/akashMehta-STL/FlutterPaginationHelper/blob/master/lib/demo/pagination_error.dart) 75 | * [Pagination implemented with hacker rank api integration.](https://github.com/akashMehta-STL/FlutterPaginationHelper/tree/master/lib/demo/hackerNewsIntegration) 76 | - [Flutter pagination helper](https://pub.dartlang.org/packages/flutter_pagination_helper#-installing-tab-) 77 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 78 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 79 | 80 | For help getting started with Flutter, view our 81 | [online documentation](https://flutter.io/docs), which offers tutorials, 82 | samples, guidance on mobile development, and a full API reference. 83 | -------------------------------------------------------------------------------- /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 27 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 "stllpt.com.flutterpaginationhelper" 42 | minSdkVersion 16 43 | targetSdkVersion 27 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 66 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 67 | } 68 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/stllpt/com/flutterpaginationhelper/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package stllpt.com.flutterpaginationhelper 2 | 3 | import android.os.Bundle 4 | 5 | import io.flutter.app.FlutterActivity 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | GeneratedPluginRegistrant.registerWith(this) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.2.71' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.2.1' 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 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /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-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 16 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 17 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = ""; 29 | dstSubfolderSpec = 10; 30 | files = ( 31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 33 | ); 34 | name = "Embed Frameworks"; 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXCopyFilesBuildPhase section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 42 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 43 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 44 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 45 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 46 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 49 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 50 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 51 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 64 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 9740EEB11CF90186004384FC /* Flutter */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 75 | 3B80C3931E831B6300D905FE /* App.framework */, 76 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 77 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 78 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 79 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 80 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 81 | ); 82 | name = Flutter; 83 | sourceTree = ""; 84 | }; 85 | 97C146E51CF9000F007C117D = { 86 | isa = PBXGroup; 87 | children = ( 88 | 9740EEB11CF90186004384FC /* Flutter */, 89 | 97C146F01CF9000F007C117D /* Runner */, 90 | 97C146EF1CF9000F007C117D /* Products */, 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 | 97C146F11CF9000F007C117D /* Supporting Files */, 110 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 111 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 112 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 113 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 114 | ); 115 | path = Runner; 116 | sourceTree = ""; 117 | }; 118 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | ); 122 | name = "Supporting Files"; 123 | sourceTree = ""; 124 | }; 125 | /* End PBXGroup section */ 126 | 127 | /* Begin PBXNativeTarget section */ 128 | 97C146ED1CF9000F007C117D /* Runner */ = { 129 | isa = PBXNativeTarget; 130 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 131 | buildPhases = ( 132 | 9740EEB61CF901F6004384FC /* Run Script */, 133 | 97C146EA1CF9000F007C117D /* Sources */, 134 | 97C146EB1CF9000F007C117D /* Frameworks */, 135 | 97C146EC1CF9000F007C117D /* Resources */, 136 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 137 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 138 | ); 139 | buildRules = ( 140 | ); 141 | dependencies = ( 142 | ); 143 | name = Runner; 144 | productName = Runner; 145 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 146 | productType = "com.apple.product-type.application"; 147 | }; 148 | /* End PBXNativeTarget section */ 149 | 150 | /* Begin PBXProject section */ 151 | 97C146E61CF9000F007C117D /* Project object */ = { 152 | isa = PBXProject; 153 | attributes = { 154 | LastUpgradeCheck = 0910; 155 | ORGANIZATIONNAME = "The Chromium Authors"; 156 | TargetAttributes = { 157 | 97C146ED1CF9000F007C117D = { 158 | CreatedOnToolsVersion = 7.3.1; 159 | LastSwiftMigration = 0910; 160 | }; 161 | }; 162 | }; 163 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 164 | compatibilityVersion = "Xcode 3.2"; 165 | developmentRegion = English; 166 | hasScannedForEncodings = 0; 167 | knownRegions = ( 168 | en, 169 | Base, 170 | ); 171 | mainGroup = 97C146E51CF9000F007C117D; 172 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 173 | projectDirPath = ""; 174 | projectRoot = ""; 175 | targets = ( 176 | 97C146ED1CF9000F007C117D /* Runner */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXResourcesBuildPhase section */ 182 | 97C146EC1CF9000F007C117D /* Resources */ = { 183 | isa = PBXResourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 187 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 188 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 189 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 190 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 191 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | /* End PBXResourcesBuildPhase section */ 196 | 197 | /* Begin PBXShellScriptBuildPhase section */ 198 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 199 | isa = PBXShellScriptBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | ); 203 | inputPaths = ( 204 | ); 205 | name = "Thin Binary"; 206 | outputPaths = ( 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | shellPath = /bin/sh; 210 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 211 | }; 212 | 9740EEB61CF901F6004384FC /* Run Script */ = { 213 | isa = PBXShellScriptBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | ); 217 | inputPaths = ( 218 | ); 219 | name = "Run Script"; 220 | outputPaths = ( 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | shellPath = /bin/sh; 224 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 225 | }; 226 | /* End PBXShellScriptBuildPhase section */ 227 | 228 | /* Begin PBXSourcesBuildPhase section */ 229 | 97C146EA1CF9000F007C117D /* Sources */ = { 230 | isa = PBXSourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 234 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | /* End PBXSourcesBuildPhase section */ 239 | 240 | /* Begin PBXVariantGroup section */ 241 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 242 | isa = PBXVariantGroup; 243 | children = ( 244 | 97C146FB1CF9000F007C117D /* Base */, 245 | ); 246 | name = Main.storyboard; 247 | sourceTree = ""; 248 | }; 249 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 250 | isa = PBXVariantGroup; 251 | children = ( 252 | 97C147001CF9000F007C117D /* Base */, 253 | ); 254 | name = LaunchScreen.storyboard; 255 | sourceTree = ""; 256 | }; 257 | /* End PBXVariantGroup section */ 258 | 259 | /* Begin XCBuildConfiguration section */ 260 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 261 | isa = XCBuildConfiguration; 262 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_ANALYZER_NONNULL = YES; 266 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 267 | CLANG_CXX_LIBRARY = "libc++"; 268 | CLANG_ENABLE_MODULES = YES; 269 | CLANG_ENABLE_OBJC_ARC = YES; 270 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 271 | CLANG_WARN_BOOL_CONVERSION = YES; 272 | CLANG_WARN_COMMA = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INFINITE_RECURSION = YES; 278 | CLANG_WARN_INT_CONVERSION = YES; 279 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 280 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 281 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 282 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 283 | CLANG_WARN_STRICT_PROTOTYPES = YES; 284 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 285 | CLANG_WARN_UNREACHABLE_CODE = YES; 286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 287 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 288 | COPY_PHASE_STRIP = NO; 289 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 290 | ENABLE_NS_ASSERTIONS = NO; 291 | ENABLE_STRICT_OBJC_MSGSEND = YES; 292 | GCC_C_LANGUAGE_STANDARD = gnu99; 293 | GCC_NO_COMMON_BLOCKS = YES; 294 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 295 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 296 | GCC_WARN_UNDECLARED_SELECTOR = YES; 297 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 298 | GCC_WARN_UNUSED_FUNCTION = YES; 299 | GCC_WARN_UNUSED_VARIABLE = YES; 300 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 301 | MTL_ENABLE_DEBUG_INFO = NO; 302 | SDKROOT = iphoneos; 303 | TARGETED_DEVICE_FAMILY = "1,2"; 304 | VALIDATE_PRODUCT = YES; 305 | }; 306 | name = Profile; 307 | }; 308 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 309 | isa = XCBuildConfiguration; 310 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 311 | buildSettings = { 312 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 313 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 314 | DEVELOPMENT_TEAM = S8QB4VV633; 315 | ENABLE_BITCODE = NO; 316 | FRAMEWORK_SEARCH_PATHS = ( 317 | "$(inherited)", 318 | "$(PROJECT_DIR)/Flutter", 319 | ); 320 | INFOPLIST_FILE = Runner/Info.plist; 321 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 322 | LIBRARY_SEARCH_PATHS = ( 323 | "$(inherited)", 324 | "$(PROJECT_DIR)/Flutter", 325 | ); 326 | PRODUCT_BUNDLE_IDENTIFIER = stllpt.com.flutterPaginationHelper; 327 | PRODUCT_NAME = "$(TARGET_NAME)"; 328 | SWIFT_VERSION = 4.0; 329 | VERSIONING_SYSTEM = "apple-generic"; 330 | }; 331 | name = Profile; 332 | }; 333 | 97C147031CF9000F007C117D /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 336 | buildSettings = { 337 | ALWAYS_SEARCH_USER_PATHS = NO; 338 | CLANG_ANALYZER_NONNULL = YES; 339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 340 | CLANG_CXX_LIBRARY = "libc++"; 341 | CLANG_ENABLE_MODULES = YES; 342 | CLANG_ENABLE_OBJC_ARC = YES; 343 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 344 | CLANG_WARN_BOOL_CONVERSION = YES; 345 | CLANG_WARN_COMMA = YES; 346 | CLANG_WARN_CONSTANT_CONVERSION = YES; 347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 348 | CLANG_WARN_EMPTY_BODY = YES; 349 | CLANG_WARN_ENUM_CONVERSION = YES; 350 | CLANG_WARN_INFINITE_RECURSION = YES; 351 | CLANG_WARN_INT_CONVERSION = YES; 352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 356 | CLANG_WARN_STRICT_PROTOTYPES = YES; 357 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | DEBUG_INFORMATION_FORMAT = dwarf; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | ENABLE_TESTABILITY = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu99; 366 | GCC_DYNAMIC_NO_PIC = NO; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_OPTIMIZATION_LEVEL = 0; 369 | GCC_PREPROCESSOR_DEFINITIONS = ( 370 | "DEBUG=1", 371 | "$(inherited)", 372 | ); 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 375 | GCC_WARN_UNDECLARED_SELECTOR = YES; 376 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 377 | GCC_WARN_UNUSED_FUNCTION = YES; 378 | GCC_WARN_UNUSED_VARIABLE = YES; 379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 380 | MTL_ENABLE_DEBUG_INFO = YES; 381 | ONLY_ACTIVE_ARCH = YES; 382 | SDKROOT = iphoneos; 383 | TARGETED_DEVICE_FAMILY = "1,2"; 384 | }; 385 | name = Debug; 386 | }; 387 | 97C147041CF9000F007C117D /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_ANALYZER_NONNULL = YES; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_EMPTY_BODY = YES; 403 | CLANG_WARN_ENUM_CONVERSION = YES; 404 | CLANG_WARN_INFINITE_RECURSION = YES; 405 | CLANG_WARN_INT_CONVERSION = YES; 406 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 407 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 409 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 410 | CLANG_WARN_STRICT_PROTOTYPES = YES; 411 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 412 | CLANG_WARN_UNREACHABLE_CODE = YES; 413 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 414 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 415 | COPY_PHASE_STRIP = NO; 416 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 417 | ENABLE_NS_ASSERTIONS = NO; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | GCC_C_LANGUAGE_STANDARD = gnu99; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 423 | GCC_WARN_UNDECLARED_SELECTOR = YES; 424 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 425 | GCC_WARN_UNUSED_FUNCTION = YES; 426 | GCC_WARN_UNUSED_VARIABLE = YES; 427 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 428 | MTL_ENABLE_DEBUG_INFO = NO; 429 | SDKROOT = iphoneos; 430 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 431 | TARGETED_DEVICE_FAMILY = "1,2"; 432 | VALIDATE_PRODUCT = YES; 433 | }; 434 | name = Release; 435 | }; 436 | 97C147061CF9000F007C117D /* Debug */ = { 437 | isa = XCBuildConfiguration; 438 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 439 | buildSettings = { 440 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 441 | CLANG_ENABLE_MODULES = YES; 442 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 443 | ENABLE_BITCODE = NO; 444 | FRAMEWORK_SEARCH_PATHS = ( 445 | "$(inherited)", 446 | "$(PROJECT_DIR)/Flutter", 447 | ); 448 | INFOPLIST_FILE = Runner/Info.plist; 449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 450 | LIBRARY_SEARCH_PATHS = ( 451 | "$(inherited)", 452 | "$(PROJECT_DIR)/Flutter", 453 | ); 454 | PRODUCT_BUNDLE_IDENTIFIER = stllpt.com.flutterPaginationHelper; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 457 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 458 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 459 | SWIFT_VERSION = 4.0; 460 | VERSIONING_SYSTEM = "apple-generic"; 461 | }; 462 | name = Debug; 463 | }; 464 | 97C147071CF9000F007C117D /* Release */ = { 465 | isa = XCBuildConfiguration; 466 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 467 | buildSettings = { 468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 469 | CLANG_ENABLE_MODULES = YES; 470 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 471 | ENABLE_BITCODE = NO; 472 | FRAMEWORK_SEARCH_PATHS = ( 473 | "$(inherited)", 474 | "$(PROJECT_DIR)/Flutter", 475 | ); 476 | INFOPLIST_FILE = Runner/Info.plist; 477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 478 | LIBRARY_SEARCH_PATHS = ( 479 | "$(inherited)", 480 | "$(PROJECT_DIR)/Flutter", 481 | ); 482 | PRODUCT_BUNDLE_IDENTIFIER = stllpt.com.flutterPaginationHelper; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 485 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 486 | SWIFT_VERSION = 4.0; 487 | VERSIONING_SYSTEM = "apple-generic"; 488 | }; 489 | name = Release; 490 | }; 491 | /* End XCBuildConfiguration section */ 492 | 493 | /* Begin XCConfigurationList section */ 494 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | 97C147031CF9000F007C117D /* Debug */, 498 | 97C147041CF9000F007C117D /* Release */, 499 | 249021D3217E4FDB00AE95B9 /* Profile */, 500 | ); 501 | defaultConfigurationIsVisible = 0; 502 | defaultConfigurationName = Release; 503 | }; 504 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 505 | isa = XCConfigurationList; 506 | buildConfigurations = ( 507 | 97C147061CF9000F007C117D /* Debug */, 508 | 97C147071CF9000F007C117D /* Release */, 509 | 249021D4217E4FDB00AE95B9 /* Profile */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Release; 513 | }; 514 | /* End XCConfigurationList section */ 515 | 516 | }; 517 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 518 | } 519 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashMehta-STL/FlutterPaginationHelper/1bd721b2371f9e439f68d8fa7439aab18e27cf21/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_pagination_helper 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/demo/custom_progress_pagination.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/list_item.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/list_helper.dart'; 6 | 7 | const int threshold = 13; 8 | const int totalItems = 39; 9 | 10 | class CustomProgressWidget extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text("Pagination with custom progress"), 16 | ), 17 | body: PaginatedListWidget( 18 | progressWidget: Center( 19 | child: Text("Loading..."), 20 | ), 21 | itemListCallback: OnScrollCallback()), 22 | ); 23 | } 24 | } 25 | 26 | class OnScrollCallback extends ItemListCallback { 27 | int availableItems = 0; 28 | 29 | @override 30 | Future getItemList() { 31 | return Future.delayed(Duration(seconds: 3), () { 32 | List itemList = List(); 33 | if (availableItems < totalItems) { 34 | for (int i = availableItems; i < availableItems + threshold; i++) { 35 | Widget widget; 36 | if (i % 5 == 0) { 37 | widget = TitleWidget(i); 38 | } else { 39 | widget = ListItemWidget(ItemModel("Title $i", "Subtitle $i")); 40 | } 41 | itemList.add(widget); 42 | } 43 | availableItems += threshold; 44 | return EventModel(progress: false, data: itemList, error: null); 45 | } else { 46 | for (int i = availableItems; i < availableItems + 3; i++) { 47 | Widget widget = ListItemWidget(ItemModel("Title $i", "Subtitle $i")); 48 | itemList.add(widget); 49 | } 50 | availableItems += 3; 51 | return EventModel( 52 | progress: false, data: itemList, error: null, stopLoading: true); 53 | } 54 | }); 55 | } 56 | } 57 | 58 | class TitleWidget extends StatelessWidget { 59 | final int i; 60 | 61 | TitleWidget(this.i); 62 | 63 | @override 64 | Widget build(BuildContext context) { 65 | return Container( 66 | decoration: BoxDecoration( 67 | color: Colors.grey[50], 68 | boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 10)], 69 | border: Border.all(color: Colors.grey[400], width: 1.0), 70 | borderRadius: BorderRadius.circular(5)), 71 | child: Padding( 72 | padding: EdgeInsets.all(10), 73 | child: Center( 74 | child: Text( 75 | "Header $i", 76 | style: TextStyle(fontSize: 18), 77 | ), 78 | ), 79 | ), 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/demo/default_progress_pagination.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/list_item.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/list_helper.dart'; 6 | 7 | const int threshold = 13; 8 | const int totalItems = 39; 9 | 10 | class DefaultProgressWidget extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text("Pagination with default progress"), 16 | ), 17 | body: PaginatedListWidget(itemListCallback: OnScrollCallback()), 18 | ); 19 | } 20 | } 21 | 22 | class OnScrollCallback extends ItemListCallback { 23 | int availableItems = 0; 24 | 25 | @override 26 | Future getItemList() { 27 | return Future.delayed(Duration(seconds: 3), () { 28 | List itemList = List(); 29 | if (availableItems < totalItems) { 30 | for (int i = availableItems; i < availableItems + threshold; i++) { 31 | Widget widget; 32 | if (i % 5 == 0) { 33 | widget = TitleWidget(i); 34 | } else { 35 | widget = ListItemWidget(ItemModel("Title $i", "Subtitle $i")); 36 | } 37 | itemList.add(widget); 38 | } 39 | availableItems += threshold; 40 | return EventModel(progress: false, data: itemList, error: null); 41 | } else { 42 | for (int i = availableItems; i < availableItems + 3; i++) { 43 | Widget widget = ListItemWidget(ItemModel("Title $i", "Subtitle $i")); 44 | itemList.add(widget); 45 | } 46 | availableItems += 3; 47 | return EventModel( 48 | progress: false, data: itemList, error: null, stopLoading: true); 49 | } 50 | }); 51 | } 52 | } 53 | 54 | class TitleWidget extends StatelessWidget { 55 | final int i; 56 | 57 | TitleWidget(this.i); 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | return Container( 62 | decoration: BoxDecoration( 63 | color: Colors.grey[50], 64 | boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 10)], 65 | border: Border.all(color: Colors.grey[400], width: 1.0), 66 | borderRadius: BorderRadius.circular(5)), 67 | child: Padding( 68 | padding: EdgeInsets.all(10), 69 | child: Center( 70 | child: Text( 71 | "Header $i", 72 | style: TextStyle(fontSize: 18), 73 | ), 74 | ), 75 | ), 76 | ); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/circular_progress_indicator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ProgressIndicatorWidget extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Center( 7 | child: Container( 8 | height: 30, 9 | width: 30, 10 | child: CircularProgressIndicator( 11 | backgroundColor: Colors.teal, 12 | strokeWidth: 3, 13 | ), 14 | ), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/error_text_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ErrorTextWidget extends StatelessWidget { 4 | final String message; 5 | 6 | ErrorTextWidget(this.message); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Center( 11 | child: Text( 12 | message, 13 | style: TextStyle(color: Colors.red, fontSize: 12), 14 | ), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/hacker_news_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_list_bloc.dart'; 3 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_response.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 6 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 7 | import 'package:flutter_pagination_helper/pagination_helper/list_helper.dart'; 8 | 9 | // ignore: must_be_immutable 10 | class HackerNewsListWidget extends StatefulWidget { 11 | final String type; 12 | EventModel model; 13 | 14 | HackerNewsListWidget(this.type) : assert(type != null); 15 | 16 | @override 17 | _HackerNewsListWidgetState createState() => _HackerNewsListWidgetState(); 18 | } 19 | 20 | class _HackerNewsListWidgetState extends State 21 | with AutomaticKeepAliveClientMixin { 22 | NewsListBloc newsListBloc; 23 | List itemList = List(); 24 | bool isLoading = false; 25 | 26 | @override 27 | void initState() { 28 | super.initState(); 29 | newsListBloc = BlocProvider.of(context); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return PaginatedListWidget(itemListCallback: OnScrollCallback(newsListBloc, widget.type)); 35 | } 36 | 37 | @override 38 | bool get wantKeepAlive => true; 39 | } 40 | 41 | class OnScrollCallback extends ItemListCallback { 42 | final NewsListBloc _newsListBloc; 43 | final String type; 44 | 45 | OnScrollCallback(this._newsListBloc, this.type); 46 | 47 | @override 48 | Future getItemList() { 49 | return _newsListBloc.fetchNewsItems(type).first; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/hacker_news_list.dart'; 3 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_list_bloc.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 5 | 6 | class NewsHomeWidget extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return NewsTabController(); 10 | } 11 | } 12 | 13 | class NewsTabController extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return DefaultTabController( 17 | length: 3, 18 | child: Scaffold( 19 | appBar: AppBar( 20 | title: Text("Hacker News"), 21 | centerTitle: true, 22 | bottom: TabBar( 23 | tabs: [Tab(text: "New"), Tab(text: "Top"), Tab(text: "Best")]), 24 | ), 25 | body: TabBarView(children: [ 26 | BlocProvider( 27 | bloc: NewsListBloc(), 28 | child: HackerNewsListWidget("New"), 29 | ), 30 | BlocProvider( 31 | bloc: NewsListBloc(), 32 | child: HackerNewsListWidget("Top"), 33 | ), 34 | BlocProvider( 35 | bloc: NewsListBloc(), child: HackerNewsListWidget("Best")) 36 | ]), 37 | )); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_ids_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'news_ids_list.g.dart'; 4 | /* 5 | * run 6 | * flutter packages pub run build_runner build 7 | * to auto generate model file 8 | */ 9 | 10 | @JsonSerializable() 11 | class NewsIdList { 12 | final List ids; 13 | 14 | NewsIdList(this.ids); 15 | 16 | factory NewsIdList.fromJson(Map jsonMap) => _$NewsIdListFromJson(jsonMap); 17 | 18 | Map toJson() => _$NewsIdListToJson(this); 19 | } 20 | 21 | class NewsIdApiModel { 22 | final bool isLoading; 23 | final List idList; 24 | final String error; 25 | 26 | NewsIdApiModel(this.isLoading, this.idList, this.error); 27 | } 28 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_ids_list.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'news_ids_list.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | NewsIdList _$NewsIdListFromJson(Map json) { 10 | return NewsIdList((json['ids'] as List)?.map((e) => e as int)?.toList()); 11 | } 12 | 13 | Map _$NewsIdListToJson(NewsIdList instance) => 14 | {'ids': instance.ids}; 15 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_list_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_list_item.dart'; 5 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_response.dart'; 6 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 7 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 8 | import 'package:http/http.dart'; 9 | import 'package:rxdart/rxdart.dart'; 10 | 11 | class NewsListBloc extends BaseBloc { 12 | int _skipCount = 0; 13 | 14 | List idList = List(); 15 | 16 | Observable fetchNewsItems(String newsType) { 17 | if (idList.isEmpty) { 18 | Observable> _newsIdFuture = Observable.fromFuture(fetchNewsIds(newsType)); 19 | Observable _newsItem = _newsIdFuture.concatMap((idList) { 20 | this.idList.addAll(idList); 21 | return displayNewsItems(); 22 | }); 23 | return _newsItem; 24 | } else { 25 | return displayNewsItems(); 26 | } 27 | 28 | } 29 | 30 | Observable displayNewsItems() { 31 | return Observable.just(idList) 32 | .flatMapIterable((id) => Observable.just(id)) 33 | .skip(_skipCount) 34 | .take(10) 35 | .flatMap((id) => Observable.fromFuture(_fetchNewsItems(id))) 36 | .toList().asObservable().map((data) { return EventModel(progress: false, data: data, error: null);}); 37 | } 38 | 39 | Future _fetchNewsItems(int id) async { 40 | final response = 41 | await get("https://hacker-news.firebaseio.com/v0/item/$id.json"); 42 | if (response.statusCode == 200) { 43 | return NewsListItem(NewsResponseItem.fromJson(JsonDecoder().convert(response.body))); 44 | } else { 45 | throw Exception(response.body); 46 | } 47 | } 48 | 49 | Future> fetchNewsIds(String newsType) async { 50 | final response = await get( 51 | "https://hacker-news.firebaseio.com/v0/${newsType.toLowerCase() + "stories"}.json"); 52 | if (response.statusCode == 200) { 53 | List idList = List(); 54 | List responseList = JsonDecoder().convert(response.body); 55 | for (var value in responseList) { 56 | if (value is int) { 57 | idList.add(value); 58 | } 59 | } 60 | return idList; 61 | } else { 62 | throw Exception(response.body); 63 | } 64 | } 65 | 66 | @override 67 | void dispose() { 68 | } 69 | } -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_list_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/circular_progress_indicator.dart'; 3 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_response.dart'; 4 | 5 | class NewsListItem extends StatelessWidget { 6 | final NewsResponseItem newsResponseItem; 7 | 8 | NewsListItem(this.newsResponseItem); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Container(child: _rowWidget(context, newsResponseItem)); 13 | } 14 | 15 | Widget _rowWidget(BuildContext context, NewsResponseItem newsResponseItem) { 16 | if (newsResponseItem == null) { 17 | return Center( 18 | child: ProgressIndicatorWidget(), 19 | ); 20 | } else { 21 | return Material( 22 | child: InkWell( 23 | child: Padding( 24 | padding: EdgeInsets.only(top: 16, bottom: 16, left: 10, right: 10), 25 | child: Container( 26 | decoration: BoxDecoration( 27 | color: Colors.grey[50], 28 | boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 10)], 29 | border: Border.all(color: Colors.grey[400], width: 1.0), 30 | borderRadius: BorderRadius.circular(5)), 31 | child: Padding( 32 | padding: EdgeInsets.all(10), 33 | child: Text( 34 | newsResponseItem.title, 35 | style: TextStyle(fontSize: 18), 36 | ), 37 | ), 38 | ), 39 | ), 40 | ), 41 | ); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_response.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'news_response.g.dart'; 4 | /* 5 | * run 6 | * flutter packages pub run build_runner build 7 | * to auto generate model file 8 | */ 9 | 10 | @JsonSerializable() 11 | class NewsResponseItem { 12 | final String by; 13 | final int descendants; 14 | final int id; 15 | final int score; 16 | final int time; 17 | final String title; 18 | final String type; 19 | final String url; 20 | 21 | NewsResponseItem(this.by, this.descendants, this.id, this.score, this.time, 22 | this.title, this.type, this.url); 23 | 24 | factory NewsResponseItem.fromJson(Map jsonMap) => 25 | _$NewsResponseItemFromJson(jsonMap); 26 | 27 | Map toJson() => _$NewsResponseItemToJson(this); 28 | } 29 | 30 | class NewsResponseApiModel { 31 | final bool isLoading; 32 | final List idList; 33 | final String error; 34 | 35 | NewsResponseApiModel(this.isLoading, this.idList, this.error); 36 | } 37 | -------------------------------------------------------------------------------- /lib/demo/hackerNewsIntegration/news_response.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'news_response.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | NewsResponseItem _$NewsResponseItemFromJson(Map json) { 10 | return NewsResponseItem( 11 | json['by'] as String, 12 | json['descendants'] as int, 13 | json['id'] as int, 14 | json['score'] as int, 15 | json['time'] as int, 16 | json['title'] as String, 17 | json['type'] as String, 18 | json['url'] as String); 19 | } 20 | 21 | Map _$NewsResponseItemToJson(NewsResponseItem instance) => 22 | { 23 | 'by': instance.by, 24 | 'descendants': instance.descendants, 25 | 'id': instance.id, 26 | 'score': instance.score, 27 | 'time': instance.time, 28 | 'title': instance.title, 29 | 'type': instance.type, 30 | 'url': instance.url 31 | }; 32 | -------------------------------------------------------------------------------- /lib/demo/list_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ListItemWidget extends StatelessWidget { 4 | 5 | final ItemModel itemModel; 6 | ListItemWidget(this.itemModel); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | child: Padding( 12 | padding: EdgeInsets.all(10), 13 | child: Column( 14 | children: [ 15 | Padding( 16 | padding: EdgeInsets.all(10), 17 | child: Text( 18 | itemModel.title, 19 | style: TextStyle(fontSize: 18), 20 | ), 21 | ), 22 | Padding( 23 | padding: EdgeInsets.all(10), 24 | child: Text( 25 | itemModel.subTitle, 26 | style: TextStyle(fontSize: 14), 27 | ), 28 | ), 29 | ], 30 | ), 31 | )); 32 | } 33 | } 34 | 35 | class ItemModel { 36 | final String title; 37 | final String subTitle; 38 | 39 | ItemModel(this.title, this.subTitle); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /lib/demo/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/custom_progress_pagination.dart'; 3 | import 'package:flutter_pagination_helper/demo/default_progress_pagination.dart'; 4 | import 'package:flutter_pagination_helper/demo/hackerNewsIntegration/news_home.dart'; 5 | import 'package:flutter_pagination_helper/demo/pagination_error.dart'; 6 | 7 | void main() => runApp(MyApp()); 8 | 9 | const DEFAULT_PROGRESS_PAGINATION = 0; 10 | const CUSTOM_PROGRESS_PAGINATION = 1; 11 | const ERROR_PAGINATION = 2; 12 | const HACKER_NEWS = 3; 13 | 14 | class MyApp extends StatelessWidget { 15 | // This widget is the root of your application. 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | theme: ThemeData( 20 | primarySwatch: Colors.red, 21 | ), 22 | home: Builder( 23 | builder: (context) { 24 | return Scaffold( 25 | appBar: AppBar( 26 | title: Text("Pagination Sample"), 27 | ), 28 | body: Center( 29 | child: Column( 30 | children: [ 31 | PaginationButton( 32 | "Custom progress pagination", CUSTOM_PROGRESS_PAGINATION), 33 | PaginationButton("Default progress pagination", 34 | DEFAULT_PROGRESS_PAGINATION), 35 | PaginationButton("Error pagination", ERROR_PAGINATION), 36 | PaginationButton("Hacker news", HACKER_NEWS), 37 | ], 38 | ), 39 | ), 40 | ); 41 | }, 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class PaginationButton extends StatelessWidget { 48 | final String title; 49 | final int page; 50 | 51 | PaginationButton(this.title, this.page); 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Padding( 56 | padding: EdgeInsets.all(10), 57 | child: RaisedButton( 58 | onPressed: () { 59 | _navigateToPagination(context, page); 60 | }, 61 | child: Padding( 62 | padding: EdgeInsets.all(10), 63 | child: Text(title), 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | void _navigateToPagination(BuildContext context, int page) { 70 | Navigator.of(context) 71 | .push(MaterialPageRoute(builder: (BuildContext context) { 72 | switch (page) { 73 | case DEFAULT_PROGRESS_PAGINATION: 74 | return DefaultProgressWidget(); 75 | case CUSTOM_PROGRESS_PAGINATION: 76 | return CustomProgressWidget(); 77 | case ERROR_PAGINATION: 78 | return PaginationErrorWidget(); 79 | case HACKER_NEWS: 80 | return NewsHomeWidget(); 81 | } 82 | })); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/demo/pagination_error.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/demo/list_item.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/list_helper.dart'; 6 | 7 | const int threshold = 13; 8 | const int errorIndex = 20; 9 | 10 | class PaginationErrorWidget extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text("Pagination with error"), 16 | ), 17 | body: PaginatedListWidget(itemListCallback: OnScrollCallback()), 18 | ); 19 | } 20 | } 21 | 22 | class OnScrollCallback extends ItemListCallback { 23 | int availableItems = 0; 24 | 25 | @override 26 | Future getItemList() { 27 | if (availableItems > errorIndex) { // manage error scenario 28 | // return error message when available item exceed error index 29 | return Future.value(EventModel(progress: false, data: null, error: "Error message")); 30 | } else { 31 | // return data 32 | return Future.delayed(Duration(seconds: 3), () { 33 | List itemList = List(); 34 | for (int i = availableItems; i < availableItems + threshold; i++) { 35 | Widget widget; 36 | if (i % 5 == 0) { 37 | widget = TitleWidget(i); 38 | } else { 39 | widget = ListItemWidget(ItemModel("Title $i", "Subtitle $i")); 40 | } 41 | itemList.add(widget); 42 | } 43 | availableItems += threshold; 44 | return EventModel(progress: false, data: itemList, error: null); 45 | }); 46 | } 47 | } 48 | } 49 | 50 | class TitleWidget extends StatelessWidget { 51 | final int i; 52 | 53 | TitleWidget(this.i); 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return Container( 58 | decoration: BoxDecoration( 59 | color: Colors.grey[50], 60 | boxShadow: [BoxShadow(color: Colors.grey, blurRadius: 10)], 61 | border: Border.all(color: Colors.grey[400], width: 1.0), 62 | borderRadius: BorderRadius.circular(5)), 63 | child: Padding( 64 | padding: EdgeInsets.all(10), 65 | child: Center( 66 | child: Text( 67 | "Header $i", 68 | style: TextStyle(fontSize: 18), 69 | ), 70 | ), 71 | ), 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/pagination_helper/bloc_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | abstract class BaseBloc { 4 | void dispose(); 5 | } 6 | 7 | class BlocProvider extends StatelessWidget { 8 | final T bloc; 9 | final Widget child; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return child; 14 | } 15 | 16 | static T of(BuildContext context) { 17 | final type = typeOf>(); 18 | BlocProvider blocProvider = context.ancestorWidgetOfExactType(type); 19 | return blocProvider.bloc; 20 | } 21 | 22 | BlocProvider({Key key, @required this.bloc, @required this.child}) 23 | : super(key: key); 24 | 25 | static Type typeOf() => T; 26 | } 27 | -------------------------------------------------------------------------------- /lib/pagination_helper/event_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class EventModel { 4 | final bool progress; 5 | final List data; 6 | final String error; 7 | final bool stopLoading; 8 | 9 | EventModel({this.progress, this.data, this.error, this.stopLoading}); 10 | } 11 | -------------------------------------------------------------------------------- /lib/pagination_helper/item_list_callback.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 2 | 3 | abstract class ItemListCallback { 4 | Future getItemList(); 5 | } 6 | -------------------------------------------------------------------------------- /lib/pagination_helper/list_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/pagination_bloc.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/list_widget.dart'; 6 | 7 | class PaginatedListWidget extends StatelessWidget { 8 | final ItemListCallback itemListCallback; 9 | final Widget progressWidget; 10 | final GlobalKey scaffoldKey = new GlobalKey(); 11 | 12 | PaginatedListWidget({this.progressWidget, this.itemListCallback}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | key: scaffoldKey, 18 | body: BlocProvider( 19 | bloc: PaginationBloc(itemListCallback: itemListCallback), 20 | child: ListWidget( 21 | progressWidget: progressWidget, 22 | scaffoldKey: scaffoldKey, 23 | )), 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/pagination_helper/list_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 2 | import 'package:flutter_pagination_helper/pagination_helper/progressbar.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/widget_list.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 6 | import 'package:flutter_pagination_helper/pagination_helper/pagination_bloc.dart'; 7 | 8 | class ListWidget extends StatelessWidget { 9 | final _itemList = List(); 10 | 11 | final Widget progressWidget; 12 | final GlobalKey scaffoldKey; 13 | 14 | ListWidget({this.progressWidget, this.scaffoldKey}); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | bool isLoading = false; 19 | bool isLoadComplete = false; 20 | PaginationBloc bloc = BlocProvider.of(context); 21 | bloc.setAsyncCallback(); 22 | 23 | Function _onScrollListener = () { 24 | if (!isLoading && !isLoadComplete) { 25 | isLoading = !isLoading; 26 | bloc.setAsyncCallback(); 27 | } 28 | }; 29 | 30 | return StreamBuilder( 31 | initialData: EventModel(progress: true, data: _itemList, error: null), 32 | stream: bloc.eventStream, 33 | builder: (BuildContext context, AsyncSnapshot snapshot) { 34 | EventModel model = snapshot.data; 35 | isLoading = false; 36 | if (model.progress) { 37 | // Handle progress state 38 | if (model.data.isEmpty) { 39 | return progressWidget ?? ProgressWidget(); 40 | } else { 41 | return WidgetList(model.data, progressWidget, _onScrollListener); 42 | } 43 | } else if (model.error != null) { 44 | // Handle error state 45 | if (_itemList.contains(null)) { 46 | _itemList.remove(null); 47 | } 48 | 49 | // Show SnackBar on error. 50 | Future.delayed(Duration(milliseconds: 500), () { 51 | scaffoldKey.currentState 52 | .showSnackBar(SnackBar(content: Text(model.error))); 53 | }); 54 | 55 | return WidgetList(_itemList, progressWidget, _onScrollListener); 56 | } else { 57 | // Handle data state 58 | if (_itemList.contains(null)) { 59 | _itemList.remove(null); 60 | } 61 | _itemList.addAll(model.data); 62 | 63 | // If list reach to the bottom of the page then model.stopLoading flag will become 64 | // true and after displaying remaining data progress will not be shown. 65 | if (model.stopLoading != null && model.stopLoading) { 66 | isLoadComplete = true; 67 | } else { 68 | _itemList.add(null); 69 | } 70 | return WidgetList(_itemList, progressWidget, _onScrollListener); 71 | } 72 | }, 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/pagination_helper/pagination_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter_pagination_helper/pagination_helper/bloc_provider.dart'; 3 | import 'package:flutter_pagination_helper/pagination_helper/event_model.dart'; 4 | import 'package:flutter_pagination_helper/pagination_helper/item_list_callback.dart'; 5 | 6 | class PaginationBloc extends BaseBloc { 7 | StreamController eventController = StreamController(); 8 | 9 | Stream get eventStream => eventController.stream; 10 | 11 | Sink get eventSink => eventController.sink; 12 | 13 | final ItemListCallback itemListCallback; 14 | 15 | PaginationBloc({this.itemListCallback}); 16 | 17 | void setAsyncCallback() async { 18 | try { 19 | EventModel model = await itemListCallback.getItemList(); 20 | eventSink.add(model); 21 | } catch (e) { 22 | eventSink 23 | .add(EventModel(progress: false, data: null, error: e.toString())); 24 | } 25 | } 26 | 27 | @override 28 | void dispose() { 29 | eventController.close(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/pagination_helper/progressbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ProgressWidget extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Center( 7 | child: Container( 8 | height: 30, 9 | width: 30, 10 | child: CircularProgressIndicator( 11 | backgroundColor: Colors.primaries[0], 12 | strokeWidth: 3, 13 | ), 14 | ), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/pagination_helper/widget_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_pagination_helper/pagination_helper/progressbar.dart'; 3 | 4 | class WidgetList extends StatelessWidget { 5 | final List widgetList; 6 | final Function onScrollListener; 7 | final Widget _progressWidget; 8 | 9 | WidgetList(this.widgetList, this._progressWidget, this.onScrollListener); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | ScrollController _scrollController = ScrollController(); 14 | _scrollController.addListener(() { 15 | if (_scrollController.position.maxScrollExtent == 16 | _scrollController.position.pixels) { 17 | onScrollListener(); 18 | } 19 | }); 20 | return ListView.builder( 21 | controller: _scrollController, 22 | itemCount: widgetList.length, 23 | itemBuilder: (BuildContext context, int index) => ListItem( 24 | model: widgetList[index], 25 | progressWidget: _progressWidget, 26 | ), 27 | ); 28 | } 29 | } 30 | 31 | class ListItem extends StatelessWidget { 32 | final T model; 33 | final Widget progressWidget; 34 | ListItem({Key key, this.model, this.progressWidget}); 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | if (model == null) { 39 | return Center( 40 | child: Padding( 41 | padding: EdgeInsets.all(5), 42 | child: progressWidget ?? ProgressWidget(), 43 | ), 44 | ); 45 | } else { 46 | return model; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_pagination_helper 2 | description: >- 3 | Reduce your boilerplate code to implement pagination in flutter project. 4 | User ListHelper widget and pass call back method to listen scroll event 5 | using your custom ItemListCallback. 6 | author: akashMehta-STL 7 | repository: https://github.com/akashMehta-STL/FlutterPaginationHelper.git 8 | issue_tracker: https://github.com/akashMehta-STL/FlutterPaginationHelper/issues 9 | homepage: https://github.com/akashMehta-STL/FlutterPaginationHelper.git 10 | # The following defines the version and build number for your application. 11 | # A version number is three numbers separated by dots, like 1.2.43 12 | # followed by an optional build number separated by a +. 13 | # Both the version and the builder number may be overridden in flutter 14 | # build by specifying --build-name and --build-number, respectively. 15 | # Read more about versioning at semver.org. 16 | version: 1.0.1+2 17 | 18 | environment: 19 | sdk: ">=2.1.0-dev.9.4 <3.0.0" 20 | 21 | dependencies: 22 | flutter: 23 | sdk: flutter 24 | 25 | # The following adds the Cupertino Icons font to your application. 26 | # Use with the CupertinoIcons class for iOS style icons. 27 | cupertino_icons: ^0.1.2 28 | 29 | dev_dependencies: 30 | flutter_test: 31 | sdk: flutter 32 | 33 | 34 | # For information on the generic Dart part of this file, see the 35 | # following page: https://www.dartlang.org/tools/pub/pubspec 36 | 37 | # The following section is specific to Flutter. 38 | flutter: 39 | 40 | # The following line ensures that the Material Icons font is 41 | # included with your application, so that you can use the icons in 42 | # the material Icons class. 43 | uses-material-design: true 44 | 45 | # To add assets to your application, add an assets section, like this: 46 | # assets: 47 | # - images/a_dot_burr.jpeg 48 | # - images/a_dot_ham.jpeg 49 | 50 | # An image asset can refer to one or more resolution-specific "variants", see 51 | # https://flutter.io/assets-and-images/#resolution-aware. 52 | 53 | # For details regarding adding assets from package dependencies, see 54 | # https://flutter.io/assets-and-images/#from-packages 55 | 56 | # To add custom fonts to your application, add a fonts section here, 57 | # in this "flutter" section. Each entry in this list should have a 58 | # "family" key with the font family name, and a "fonts" key with a 59 | # list giving the asset and other descriptors for the font. For 60 | # example: 61 | # fonts: 62 | # - family: Schyler 63 | # fonts: 64 | # - asset: fonts/Schyler-Regular.ttf 65 | # - asset: fonts/Schyler-Italic.ttf 66 | # style: italic 67 | # - family: Trajan Pro 68 | # fonts: 69 | # - asset: fonts/TrajanPro.ttf 70 | # - asset: fonts/TrajanPro_Bold.ttf 71 | # weight: 700 72 | # 73 | # For details regarding fonts from package dependencies, 74 | # see https://flutter.io/custom-fonts/#from-packages 75 | -------------------------------------------------------------------------------- /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 | void main() { 9 | } 10 | --------------------------------------------------------------------------------