├── .fvmrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── documentation_update.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE │ ├── bug_fix.md │ ├── documentation_update.md │ └── new_feature.md └── workflows │ ├── on_close_issue_add_comment_to_pyrus_task.yml │ ├── on_close_pr_add_comment_to_pyrus_task.yml │ ├── on_open_issue_create_pyrus_task.yml │ ├── on_open_pr_create_pyrus_task.yml │ ├── on_pull_request.yml │ └── publish_to_pub.yml ├── .gitignore ├── .markdownlint.json ├── .metadata ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── dart_dependency_validator.yaml ├── example ├── .gitignore ├── .metadata ├── analysis_options.yaml ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── 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.h │ │ ├── AppDelegate.m │ │ ├── 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 │ │ └── main.m ├── lib │ ├── main.dart │ └── screens │ │ ├── main_page.dart │ │ └── my_app.dart ├── pubspec.lock ├── pubspec.yaml └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json ├── lib ├── src │ ├── cupertino_swipe_refresh.dart │ ├── material_swipe_refresh.dart │ ├── swipe_refresh.dart │ ├── swipe_refresh_base.dart │ ├── swipe_refresh_state.dart │ ├── swipe_refresh_style.dart │ └── widgets │ │ ├── conditional_wrapper.dart │ │ └── scroll_behavior_in_web.dart ├── swipe_refresh.dart └── utills │ └── platform_wrapper.dart ├── pubspec.lock ├── pubspec.yaml └── test ├── platform_wrapper_test.dart ├── swipe_refresh_adaptive_test.dart ├── swipe_refresh_builder_test.dart ├── swipe_refresh_cupertino_test.dart ├── swipe_refresh_material_test.dart └── test_utils.dart /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "3.19.0" 3 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Something is wrong. 4 | title: "[BUG] " 5 | labels: bug 6 | --- 7 | 11 | ## Expected behavior 12 | 13 | 14 | ## Actual behavior 15 | 16 | 17 | ## Video/Screenshot 18 | 19 | 20 | ## Steps to reproduce 21 | 27 | 28 | ## Details 29 | 30 | Flutter version: 31 | 32 | Dart version: 33 | 34 | Platform: 35 | 36 | ## Logs and stacktrace 37 | 40 | 41 | ## Any possible solutions 42 | 46 | 47 | ## What did you try to solve 48 | 52 | 53 | ## Checklist for self-check 54 | 55 | - [ ] Added expected and actual behavior. 56 | - [ ] Added video or screenshot of bug. 57 | - [ ] Added isolated way to reproduce the bug. 58 | - [ ] Specified Flutter, Dart version and platforms. 59 | - [ ] Attached error code and logs. 60 | - [ ] All unspecified fields in the Issue description are deleted. 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: SurfGear telegram chat 4 | url: https://t.me/SurfGear 5 | about: Please ask and answer questions here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_update.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation update 3 | about: Fixing a problem or improve in an existing docs page. 4 | labels: documentation 5 | --- 6 | 10 | ## Describe what scenario you think is uncovered by the existing examples / articles 11 | 12 | 13 | ## Describe why existing examples / articles do not cover this case 14 | 15 | 16 | ## Additional context 17 | 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: I'd like SurfGear team to do something new. 4 | labels: enhancement 5 | --- 6 | 12 | ## What is the new or updated feature that you are suggesting? 13 | 14 | 15 | ## Why should this feature be included? 16 | 17 | 18 | ## Additional context 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Tap on "Preview" ⤴ 2 | 3 | And choose one of the templates: 4 | 5 | * [Bugfix PR](?expand=1&template=bug_fix.md) 6 | * [New feature PR](?expand=1&template=new_feature.md) 7 | * [Documentation update PR](?expand=1&template=documentation_update.md) 8 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bug_fix.md: -------------------------------------------------------------------------------- 1 | 6 | ## Checklist 7 | 8 | - [ ] Have you added an explanation of what your changes do and why you'd like us to include them? 9 | - [ ] Is there an existing issue for this PR? 10 | - _link issue here_ (use keywords like `fix`, `close`, `resolve` etc. if necessary) 11 | - [ ] Have the files been linted and formatted? 12 | - [ ] Have the docs been updated to match the changes in the PR? 13 | - [ ] Have the tests been updated to match the changes in the PR? 14 | - [ ] Attached videos/screenshots demonstrating the fix/feature. 15 | - [ ] Have you run the tests locally to confirm they pass? 16 | 17 | ## Changes 18 | 19 | ### What is the current behavior, and the steps to reproduce the issue? 20 | 21 | ### What is the expected behavior? 22 | 23 | ### How does this PR fix the problem? 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/documentation_update.md: -------------------------------------------------------------------------------- 1 | 6 | ## Checklist 7 | 8 | - [ ] Is there an existing issue for this PR? 9 | - _link issue here_ (use keywords like `fix`, `close`, `resolve` etc. if necessary) 10 | - [ ] Have the files been linted and formatted? 11 | 12 | ## Changes 13 | 14 | ### What docs page needs to be fixed? 15 | 16 | - **Section**: 17 | - **Page**: 18 | 19 | ## What is the problem? 20 | 21 | ## What changes does this PR make to fix the problem? 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/new_feature.md: -------------------------------------------------------------------------------- 1 | 6 | ## Checklist 7 | 8 | - [ ] Have you added an explanation of what your changes do and why you'd like us to include them? 9 | - [ ] Is there an existing issue for this PR? 10 | - _link issue here_ (use keywords like `fix`, `close`, `resolve` etc. if necessary) 11 | - [ ] Have the files been linted and formatted? 12 | - [ ] Have the docs been updated to match the changes in the PR? 13 | - [ ] Have the tests been updated to match the changes in the PR? 14 | - [ ] Attached videos/screenshots demonstrating the fix/feature. 15 | - [ ] Have you run the tests locally to confirm they pass? 16 | 17 | ## New Features 18 | 19 | ### What new capabilities does this PR add? 20 | 21 | ### What docs changes are needed to explain this? 22 | -------------------------------------------------------------------------------- /.github/workflows/on_close_issue_add_comment_to_pyrus_task.yml: -------------------------------------------------------------------------------- 1 | name: Add comment to Pyrus task on issue close 2 | 3 | on: 4 | issues: 5 | types: 6 | - closed 7 | 8 | jobs: 9 | get_pyrus_task_id: 10 | name: Get Pyrus task ID from special comment in issue 11 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_pyrus_task_id_from_issue_or_pr_comment.yml@main 12 | with: 13 | ISSUE_NUMBER: ${{ github.event.issue.number }} 14 | 15 | add_comment_to_pyrus_task: 16 | name: Add comment to Pyrus task 17 | needs: get_pyrus_task_id 18 | uses: surfstudio/flutter-ci-workflows/.github/workflows/add_comment_to_pyrus_task.yml@main 19 | with: 20 | PYRUS_TASK_ID: ${{ needs.get_pyrus_task_id.outputs.PYRUS_TASK_ID }} 21 | COMMENT_TEXT: The issue is closed. 22 | secrets: 23 | LOGIN: ${{ secrets.PYRUS_BOT_LOGIN }} 24 | SECURITY_KEY: ${{ secrets.PYRUS_BOT_SECRET_KEY }} 25 | -------------------------------------------------------------------------------- /.github/workflows/on_close_pr_add_comment_to_pyrus_task.yml: -------------------------------------------------------------------------------- 1 | name: Add comment to Pyrus task on PR close 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - closed 7 | 8 | jobs: 9 | get_pyrus_task_id: 10 | name: Get Pyrus task ID from special comment in issue 11 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_pyrus_task_id_from_issue_or_pr_comment.yml@main 12 | with: 13 | ISSUE_NUMBER: ${{ github.event.pull_request.number }} 14 | 15 | add_comment_to_pyrus_task: 16 | name: Add comment to Pyrus task 17 | needs: get_pyrus_task_id 18 | uses: surfstudio/flutter-ci-workflows/.github/workflows/add_comment_to_pyrus_task.yml@main 19 | with: 20 | PYRUS_TASK_ID: ${{ needs.get_pyrus_task_id.outputs.PYRUS_TASK_ID }} 21 | COMMENT_TEXT: The pull request is closed. 22 | secrets: 23 | LOGIN: ${{ secrets.PYRUS_BOT_LOGIN }} 24 | SECURITY_KEY: ${{ secrets.PYRUS_BOT_SECRET_KEY }} 25 | -------------------------------------------------------------------------------- /.github/workflows/on_open_issue_create_pyrus_task.yml: -------------------------------------------------------------------------------- 1 | name: Create Pyrus task from new issue 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | - reopened 8 | 9 | jobs: 10 | get_package_name: 11 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_package_name.yml@main 12 | 13 | create_pyrus_task: 14 | name: Create Pyrus task from issue 15 | needs: get_package_name 16 | uses: surfstudio/flutter-ci-workflows/.github/workflows/create_pyrus_task_from_issue_or_pr.yml@main 17 | with: 18 | TYPE: Issue 19 | PACKAGE_NAME: ${{ needs.get_package_name.outputs.package_name }} 20 | TITLE: ${{ github.event.issue.title }} 21 | LINK: ${{ github.event.issue.html_url }} 22 | secrets: 23 | LOGIN: ${{ secrets.PYRUS_BOT_LOGIN }} 24 | SECURITY_KEY: ${{ secrets.PYRUS_BOT_SECRET_KEY }} 25 | 26 | add_pyrus_task_link: 27 | name: Add Pyrus task link 28 | needs: create_pyrus_task 29 | uses: surfstudio/flutter-ci-workflows/.github/workflows/add_comment_to_issue_or_pr.yml@main 30 | with: 31 | ISSUE_NUMBER: ${{ github.event.issue.number }} 32 | # Don't change the comment link, because the Pyrus task ID is searched by the link text 33 | COMMENT_TEXT: "[Link to Pyrus task](https://pyrus.com/t#id${{ needs.create_pyrus_task.outputs.PYRUS_TASK_ID }})" 34 | REACTIONS: rocket 35 | -------------------------------------------------------------------------------- /.github/workflows/on_open_pr_create_pyrus_task.yml: -------------------------------------------------------------------------------- 1 | name: Create Pyrus task from new PR 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - reopened 8 | 9 | jobs: 10 | get_package_name: 11 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_package_name.yml@main 12 | 13 | create_pyrus_task: 14 | name: Create Pyrus task from pull request 15 | needs: get_package_name 16 | uses: surfstudio/flutter-ci-workflows/.github/workflows/create_pyrus_task_from_issue_or_pr.yml@main 17 | with: 18 | TYPE: Pull request 19 | PACKAGE_NAME: ${{ needs.get_package_name.outputs.package_name }} 20 | TITLE: ${{ github.event.pull_request.title }} 21 | LINK: ${{ github.event.pull_request.html_url }} 22 | secrets: 23 | LOGIN: ${{ secrets.PYRUS_BOT_LOGIN }} 24 | SECURITY_KEY: ${{ secrets.PYRUS_BOT_SECRET_KEY }} 25 | 26 | add_pyrus_task_link: 27 | name: Add Pyrus task link 28 | needs: create_pyrus_task 29 | uses: surfstudio/flutter-ci-workflows/.github/workflows/add_comment_to_issue_or_pr.yml@main 30 | with: 31 | ISSUE_NUMBER: ${{ github.event.pull_request.number }} 32 | # Don't change the comment link, because the Pyrus task ID is searched by the link text 33 | COMMENT_TEXT: "[Link to Pyrus task](https://pyrus.com/t#id${{ needs.create_pyrus_task.outputs.PYRUS_TASK_ID }})" 34 | REACTIONS: rocket 35 | -------------------------------------------------------------------------------- /.github/workflows/on_pull_request.yml: -------------------------------------------------------------------------------- 1 | name: On pull request 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | get_flutter_version: 8 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_flutter_version.yml@main 9 | 10 | analysis: 11 | needs: get_flutter_version 12 | uses: surfstudio/flutter-ci-workflows/.github/workflows/analysis.yml@main 13 | with: 14 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 15 | 16 | testing: 17 | needs: [analysis, get_flutter_version] 18 | uses: surfstudio/flutter-ci-workflows/.github/workflows/testing.yml@main 19 | with: 20 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 21 | secrets: 22 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 23 | 24 | build_android_example: 25 | needs: [analysis, get_flutter_version] 26 | uses: surfstudio/flutter-ci-workflows/.github/workflows/build_android_example.yml@main 27 | with: 28 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 29 | 30 | build_ios_example: 31 | needs: [analysis, get_flutter_version] 32 | uses: surfstudio/flutter-ci-workflows/.github/workflows/build_ios_example.yml@main 33 | with: 34 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 35 | -------------------------------------------------------------------------------- /.github/workflows/publish_to_pub.yml: -------------------------------------------------------------------------------- 1 | name: Publishing 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | get_flutter_version: 10 | uses: surfstudio/flutter-ci-workflows/.github/workflows/get_flutter_version.yml@main 11 | 12 | analysis: 13 | needs: get_flutter_version 14 | uses: surfstudio/flutter-ci-workflows/.github/workflows/analysis.yml@main 15 | with: 16 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 17 | 18 | testing: 19 | needs: [analysis, get_flutter_version] 20 | uses: surfstudio/flutter-ci-workflows/.github/workflows/testing.yml@main 21 | with: 22 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 23 | secrets: 24 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 25 | 26 | package-publishing: 27 | needs: [analysis, testing, get_flutter_version] 28 | uses: surfstudio/flutter-ci-workflows/.github/workflows/publish_to_pub.yml@main 29 | with: 30 | FLUTTER_VERSION: ${{ needs.get_flutter_version.outputs.FLUTTER_VERSION }} 31 | PANA_TOTAL: "100" 32 | secrets: 33 | PUB_CREDENTIAL_JSON: ${{ secrets.SURF_PUB_CREDENTIAL_JSON }} 34 | PUB_OAUTH_ACCESS_TOKEN: ${{ secrets.SURF_PUB_OAUTH_ACCESS_TOKEN }} 35 | PUB_OAUTH_REFRESH_TOKEN: ${{ secrets.SURF_PUB_OAUTH_REFRESH_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .classpath 21 | .project 22 | .settings/ 23 | .vscode/ 24 | 25 | # Flutter/Dart/Pub related 26 | **/doc/api/ 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | build/ 34 | 35 | # FVM 36 | .fvm/ 37 | 38 | # Android related 39 | **/android/**/gradle-wrapper.jar 40 | **/android/.gradle 41 | **/android/captures/ 42 | **/android/gradlew 43 | **/android/gradlew.bat 44 | **/android/local.properties 45 | **/android/**/GeneratedPluginRegistrant.java 46 | 47 | # iOS/XCode related 48 | **/ios/**/*.mode1v3 49 | **/ios/**/*.mode2v3 50 | **/ios/**/*.moved-aside 51 | **/ios/**/*.pbxuser 52 | **/ios/**/*.perspectivev3 53 | **/ios/**/*sync/ 54 | **/ios/**/.sconsign.dblite 55 | **/ios/**/.tags* 56 | **/ios/**/.vagrant/ 57 | **/ios/**/DerivedData/ 58 | **/ios/**/Icon? 59 | **/ios/**/Pods/ 60 | **/ios/**/.symlinks/ 61 | **/ios/**/profile 62 | **/ios/**/xcuserdata 63 | **/ios/.generated/ 64 | **/ios/Flutter/App.framework 65 | **/ios/Flutter/Flutter.framework 66 | **/ios/Flutter/Generated.xcconfig 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/Flutter/app.flx 69 | **/ios/Flutter/app.zip 70 | **/ios/Flutter/flutter_assets/ 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Coverage 75 | coverage/ 76 | 77 | # Exceptions to above rules. 78 | !**/ios/**/default.mode1v3 79 | !**/ios/**/default.mode2v3 80 | !**/ios/**/default.pbxuser 81 | !**/ios/**/default.perspectivev3 82 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD041": false, 3 | "MD033": false, 4 | "MD013": false 5 | } -------------------------------------------------------------------------------- /.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: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: unknown 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.1.2 4 | 5 | * Correct logo position. 6 | 7 | ## 1.1.1 8 | 9 | * Rebranding. 10 | 11 | ## 1.1.0 12 | 13 | * Added support for all TargetPlatform. 14 | * Added cacheExtent property. 15 | * SDK version is up. 16 | 17 | ## 1.0.2 18 | 19 | * Internal improvements. 20 | 21 | ## 1.0.1 22 | 23 | * Stable release 24 | 25 | ## 1.0.1-dev.1 26 | 27 | * Apply new lint rules. 28 | 29 | ## 1.0.0 30 | 31 | * Migrate this package to null safety. 32 | 33 | ## 0.0.1-dev.9 34 | 35 | * Added keyboardDismissBehavior (Material) and scroll physics 36 | 37 | ## 0.0.1-dev.7 38 | 39 | * Added shrinkWrap to Refreshers 40 | 41 | ## 0.0.1-dev.6 42 | 43 | * Added Scroll controller to Refreshers 44 | 45 | ## 0.0.1-dev.5 46 | 47 | * Fix lint hints 48 | 49 | ## 0.0.1-dev.0 50 | 51 | * Initial release 52 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing rules 2 | 3 | Thank you for your help! Before you start, let's take a look at some agreements. 4 | 5 | ## Pull request rules 6 | 7 | Make sure that your code: 8 | 9 | 1. Does not contain analyzer errors. 10 | 2. Follows a [official style](https://dart.dev/guides/language/effective-dart/style). 11 | 3. Follows the official [style of formatting](https://flutter.dev/docs/development/tools/formatting). 12 | 4. Contains no errors. 13 | 5. New functionality is covered by tests. New functionality passes old tests. 14 | 6. Create example that demonstrate new functionality if it is possible. 15 | 16 | ## Accepting the changes 17 | 18 | After your pull request passes the review code, the project maintainers will merge the changes 19 | into the branch to which the pull request was sent. 20 | 21 | ## Issues 22 | 23 | Feel free to report any issues and bugs. 24 | 25 | 1. To report about the problem, create an issue on GitHub. 26 | 2. In the issue add the description of the problem. 27 | 3. Do not forget to mention your development environment, Flutter version, libraries required for 28 | illustration of the problem. 29 | 4. It is necessary to attach the code part that causes an issue or to make a small demo project 30 | that shows the issue. 31 | 5. Attach stack trace so it helps us to deal with the issue. 32 | 6. If the issue is related to graphics, screen recording is required. 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "{}" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2019 SurfStudio LLC 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swipe Refresh 2 | 3 | 4 | 5 | 6 | [![Build Status](https://shields.io/github/actions/workflow/status/surfstudio/flutter-swipe-refresh/on_pull_request.yml?logo=github&logoColor=white)](https://github.com/surfstudio/flutter-swipe-refresh) 7 | [![Coverage Status](https://img.shields.io/codecov/c/github/surfstudio/flutter-swipe-refresh?logo=codecov&logoColor=white)](https://app.codecov.io/gh/surfstudio/flutter-swipe-refresh) 8 | [![Pub Version](https://img.shields.io/pub/v/swipe_refresh?logo=dart&logoColor=white)](https://pub.dev/packages/swipe_refresh) 9 | [![Pub Likes](https://badgen.net/pub/likes/swipe_refresh)](https://pub.dev/packages/swipe_refresh) 10 | [![Pub popularity](https://badgen.net/pub/popularity/swipe_refresh)](https://pub.dev/packages/swipe_refresh/score) 11 | ![Flutter Platform](https://badgen.net/pub/flutter-platform/swipe_refresh) 12 | 13 | ## Overview 14 | 15 | Widget for refresh by swipe. 16 | 17 | - :1234: Enabled on every platform - the package is fully written on Flutter side and enabled on every platform. 18 | - :recycle: Fully covered by tests - guaranteeing the result and expectations from this package. 19 | - :notebook_with_decorative_cover: End-to-end documentation - every aspect of implementation is documented, so there is full understanding. 20 | - :cow2: Support from the best Flutter experts - we are open to any enhancement ideas and contributions. 21 | 22 | ![material](https://i.ibb.co/7Kmy91f/material.gif) 23 | ![cupertino](https://i.ibb.co/smPxRp7/cupertino.gif) 24 | 25 | Main classes: 26 | 27 | 1. [Refresh state](lib/src/swipe_refresh_state.dart) 28 | 2. [Widget for indicate swipe refresh](lib/src/swipe_refresh.dart) 29 | 3. [Widget for indicate swipe refresh Material style](lib/src/material_swipe_refresh.dart) 30 | 4. [Widget for indicate swipe refresh Cupertino style](lib/src/cupertino_swipe_refresh.dart) 31 | 32 | ## Example 33 | 34 | ### Material 35 | 36 | Refresh indicator widget with Material Design style. 37 | 38 | ```dart 39 | SwipeRefresh.material( 40 | stateStream: Stream(), 41 | onRefresh: _refresh, 42 | padding: const EdgeInsets.symmetric(vertical: 10), 43 | children: [ ... ], 44 | ); 45 | 46 | Future _refresh() async { 47 | // When all needed is done change state. 48 | _controller.sink.add(SwipeRefreshState.hidden); 49 | } 50 | ``` 51 | 52 | ### Cupertino 53 | 54 | Refresh indicator widget with Cupertino Design style. 55 | 56 | ```dart 57 | SwipeRefresh.cupertino( 58 | stateStream: Stream(), 59 | onRefresh: _refresh, 60 | padding: const EdgeInsets.symmetric(vertical: 10), 61 | children: [ ... ], 62 | ); 63 | 64 | Future _refresh() async { 65 | // When all needed is done change state. 66 | _controller.sink.add(SwipeRefreshState.hidden); 67 | } 68 | ``` 69 | 70 | ### Adaptive 71 | 72 | Refresh indicator widget with adaptive to platform style. 73 | 74 | ```dart 75 | SwipeRefresh.adaptive( 76 | stateStream: Stream(), 77 | onRefresh: _refresh, 78 | padding: const EdgeInsets.symmetric(vertical: 10), 79 | children: [ ... ], 80 | ); 81 | 82 | Future _refresh() async { 83 | // When all needed is done change state. 84 | _controller.sink.add(SwipeRefreshState.hidden); 85 | } 86 | ``` 87 | 88 | ### Builder 89 | 90 | Refresh indicator widget with adaptive to platform style, and with SliverChildBuilderDelegate in childDelegate(so as not to create more child elements than are visible through Viewport). 91 | 92 | ```dart 93 | SwipeRefresh.builder( 94 | stateStream: Stream(), 95 | onRefresh: _refresh, 96 | padding: const EdgeInsets.symmetric(vertical: 10), 97 | itemCount: Colors.primaries.length, 98 | itemBuilder: (context, index) { 99 | return Container( 100 | ... 101 | ); 102 | }, 103 | ), 104 | 105 | Future _refresh() async { 106 | // When all needed is done change state. 107 | _controller.sink.add(SwipeRefreshState.hidden); 108 | } 109 | ``` 110 | 111 | ## Installation 112 | 113 | Add `swipe_refresh` to your `pubspec.yaml` file: 114 | 115 | ```yaml 116 | dependencies: 117 | swipe_refresh: $currentVersion$ 118 | ``` 119 | 120 |

At this moment, the current version of swipe_refresh is swipe_refresh version.

121 | 122 | ## Changelog 123 | 124 | All notable changes to this project will be documented in [this file](./CHANGELOG.md). 125 | 126 | ## Issues 127 | 128 | To report your issues, submit them directly in the [Issues](https://github.com/surfstudio/flutter-swipe-refresh/issues) section. 129 | 130 | ## Contribute 131 | 132 | If you would like to contribute to the package (e.g. by improving the documentation, fixing a bug or adding a cool new feature), please read our [contribution guide](./CONTRIBUTING.md) first and send us your pull request. 133 | 134 | Your PRs are always welcome. 135 | 136 | ## How to reach us 137 | 138 | Please feel free to ask any questions about this package. Join our community chat on Telegram. We speak English and Russian. 139 | 140 | [![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg)](https://t.me/SurfGear) 141 | 142 | ## License 143 | 144 | [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) 145 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:surf_lint_rules/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /dart_dependency_validator.yaml: -------------------------------------------------------------------------------- 1 | exclude: 2 | - "example/**" 3 | 4 | ignore: 5 | - analyzer 6 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .classpath 21 | .project 22 | .settings/ 23 | .vscode/ 24 | 25 | # Flutter/Dart/Pub related 26 | **/doc/api/ 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | build/ 34 | .fvm/flutter_sdk 35 | 36 | # Android related 37 | **/android/**/gradle-wrapper.jar 38 | **/android/.gradle 39 | **/android/captures/ 40 | **/android/gradlew 41 | **/android/gradlew.bat 42 | **/android/local.properties 43 | **/android/**/GeneratedPluginRegistrant.java 44 | 45 | # iOS/XCode related 46 | **/ios/**/*.mode1v3 47 | **/ios/**/*.mode2v3 48 | **/ios/**/*.moved-aside 49 | **/ios/**/*.pbxuser 50 | **/ios/**/*.perspectivev3 51 | **/ios/**/*sync/ 52 | **/ios/**/.sconsign.dblite 53 | **/ios/**/.tags* 54 | **/ios/**/.vagrant/ 55 | **/ios/**/DerivedData/ 56 | **/ios/**/Icon? 57 | **/ios/**/Pods/ 58 | **/ios/**/.symlinks/ 59 | **/ios/**/profile 60 | **/ios/**/xcuserdata 61 | **/ios/.generated/ 62 | **/ios/Flutter/App.framework 63 | **/ios/Flutter/Flutter.framework 64 | **/ios/Flutter/Generated.xcconfig 65 | **/ios/Flutter/flutter_export_environment.sh 66 | **/ios/Flutter/app.flx 67 | **/ios/Flutter/app.zip 68 | **/ios/Flutter/flutter_assets/ 69 | **/ios/ServiceDefinitions.json 70 | **/ios/Runner/GeneratedPluginRegistrant.* 71 | 72 | # Coverage 73 | coverage/ 74 | 75 | # Exceptions to above rules. 76 | !**/ios/**/default.mode1v3 77 | !**/ios/**/default.mode2v3 78 | !**/ios/**/default.pbxuser 79 | !**/ios/**/default.perspectivev3 80 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: unknown 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:surf_lint_rules/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 31 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.example" 38 | minSdkVersion 16 39 | targetSdkVersion 30 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 43 | } 44 | 45 | buildTypes { 46 | release { 47 | // TODO: Add your own signing config for the release build. 48 | // Signing with the debug keys for now, so `flutter run --release` works. 49 | signingConfig signingConfigs.debug 50 | } 51 | } 52 | } 53 | 54 | flutter { 55 | source '../..' 56 | } 57 | 58 | dependencies { 59 | testImplementation 'junit:junit:4.12' 60 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 61 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 62 | } 63 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 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 | 10 | } 11 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.2.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 13 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 14 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 15 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 16 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 17 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 39 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 40 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 41 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 42 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 9740EEB11CF90186004384FC /* Flutter */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 65 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 66 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 67 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 68 | ); 69 | name = Flutter; 70 | sourceTree = ""; 71 | }; 72 | 97C146E51CF9000F007C117D = { 73 | isa = PBXGroup; 74 | children = ( 75 | 9740EEB11CF90186004384FC /* Flutter */, 76 | 97C146F01CF9000F007C117D /* Runner */, 77 | 97C146EF1CF9000F007C117D /* Products */, 78 | CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, 79 | ); 80 | sourceTree = ""; 81 | }; 82 | 97C146EF1CF9000F007C117D /* Products */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 97C146EE1CF9000F007C117D /* Runner.app */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | 97C146F01CF9000F007C117D /* Runner */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 94 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 95 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 96 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 98 | 97C147021CF9000F007C117D /* Info.plist */, 99 | 97C146F11CF9000F007C117D /* Supporting Files */, 100 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 101 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 102 | ); 103 | path = Runner; 104 | sourceTree = ""; 105 | }; 106 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 97C146F21CF9000F007C117D /* main.m */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | 97C146ED1CF9000F007C117D /* Runner */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 120 | buildPhases = ( 121 | 9740EEB61CF901F6004384FC /* Run Script */, 122 | 97C146EA1CF9000F007C117D /* Sources */, 123 | 97C146EB1CF9000F007C117D /* Frameworks */, 124 | 97C146EC1CF9000F007C117D /* Resources */, 125 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 126 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 127 | ); 128 | buildRules = ( 129 | ); 130 | dependencies = ( 131 | ); 132 | name = Runner; 133 | productName = Runner; 134 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 97C146E61CF9000F007C117D /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastUpgradeCheck = 1510; 144 | ORGANIZATIONNAME = "The Chromium Authors"; 145 | TargetAttributes = { 146 | 97C146ED1CF9000F007C117D = { 147 | CreatedOnToolsVersion = 7.3.1; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = en; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 97C146E51CF9000F007C117D; 160 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 97C146ED1CF9000F007C117D /* Runner */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 97C146EC1CF9000F007C117D /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 175 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 176 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 177 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 178 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXResourcesBuildPhase section */ 183 | 184 | /* Begin PBXShellScriptBuildPhase section */ 185 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 186 | isa = PBXShellScriptBuildPhase; 187 | alwaysOutOfDate = 1; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 193 | ); 194 | name = "Thin Binary"; 195 | outputPaths = ( 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | shellPath = /bin/sh; 199 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 200 | }; 201 | 9740EEB61CF901F6004384FC /* Run Script */ = { 202 | isa = PBXShellScriptBuildPhase; 203 | alwaysOutOfDate = 1; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | ); 207 | inputPaths = ( 208 | ); 209 | name = "Run Script"; 210 | outputPaths = ( 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | shellPath = /bin/sh; 214 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 215 | }; 216 | /* End PBXShellScriptBuildPhase section */ 217 | 218 | /* Begin PBXSourcesBuildPhase section */ 219 | 97C146EA1CF9000F007C117D /* Sources */ = { 220 | isa = PBXSourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 224 | 97C146F31CF9000F007C117D /* main.m in Sources */, 225 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | /* End PBXSourcesBuildPhase section */ 230 | 231 | /* Begin PBXVariantGroup section */ 232 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | 97C146FB1CF9000F007C117D /* Base */, 236 | ); 237 | name = Main.storyboard; 238 | sourceTree = ""; 239 | }; 240 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 241 | isa = PBXVariantGroup; 242 | children = ( 243 | 97C147001CF9000F007C117D /* Base */, 244 | ); 245 | name = LaunchScreen.storyboard; 246 | sourceTree = ""; 247 | }; 248 | /* End PBXVariantGroup section */ 249 | 250 | /* Begin XCBuildConfiguration section */ 251 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | ALWAYS_SEARCH_USER_PATHS = NO; 255 | CLANG_ANALYZER_NONNULL = YES; 256 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 257 | CLANG_CXX_LIBRARY = "libc++"; 258 | CLANG_ENABLE_MODULES = YES; 259 | CLANG_ENABLE_OBJC_ARC = YES; 260 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 261 | CLANG_WARN_BOOL_CONVERSION = YES; 262 | CLANG_WARN_COMMA = YES; 263 | CLANG_WARN_CONSTANT_CONVERSION = YES; 264 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 265 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 266 | CLANG_WARN_EMPTY_BODY = YES; 267 | CLANG_WARN_ENUM_CONVERSION = YES; 268 | CLANG_WARN_INFINITE_RECURSION = YES; 269 | CLANG_WARN_INT_CONVERSION = YES; 270 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 272 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 273 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 274 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 275 | CLANG_WARN_STRICT_PROTOTYPES = YES; 276 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 280 | COPY_PHASE_STRIP = NO; 281 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 282 | ENABLE_NS_ASSERTIONS = NO; 283 | ENABLE_STRICT_OBJC_MSGSEND = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 293 | MTL_ENABLE_DEBUG_INFO = NO; 294 | SDKROOT = iphoneos; 295 | TARGETED_DEVICE_FAMILY = "1,2"; 296 | VALIDATE_PRODUCT = YES; 297 | }; 298 | name = Profile; 299 | }; 300 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 301 | isa = XCBuildConfiguration; 302 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 303 | buildSettings = { 304 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 305 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 306 | DEVELOPMENT_TEAM = S8QB4VV633; 307 | ENABLE_BITCODE = NO; 308 | FRAMEWORK_SEARCH_PATHS = ( 309 | "$(inherited)", 310 | "$(PROJECT_DIR)/Flutter", 311 | ); 312 | INFOPLIST_FILE = Runner/Info.plist; 313 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 314 | LIBRARY_SEARCH_PATHS = ( 315 | "$(inherited)", 316 | "$(PROJECT_DIR)/Flutter", 317 | ); 318 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 319 | PRODUCT_NAME = "$(TARGET_NAME)"; 320 | VERSIONING_SYSTEM = "apple-generic"; 321 | }; 322 | name = Profile; 323 | }; 324 | 97C147031CF9000F007C117D /* Debug */ = { 325 | isa = XCBuildConfiguration; 326 | buildSettings = { 327 | ALWAYS_SEARCH_USER_PATHS = NO; 328 | CLANG_ANALYZER_NONNULL = YES; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 334 | CLANG_WARN_BOOL_CONVERSION = YES; 335 | CLANG_WARN_COMMA = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 338 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 339 | CLANG_WARN_EMPTY_BODY = YES; 340 | CLANG_WARN_ENUM_CONVERSION = YES; 341 | CLANG_WARN_INFINITE_RECURSION = YES; 342 | CLANG_WARN_INT_CONVERSION = YES; 343 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 344 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 345 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 347 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 348 | CLANG_WARN_STRICT_PROTOTYPES = YES; 349 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 350 | CLANG_WARN_UNREACHABLE_CODE = YES; 351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 353 | COPY_PHASE_STRIP = NO; 354 | DEBUG_INFORMATION_FORMAT = dwarf; 355 | ENABLE_STRICT_OBJC_MSGSEND = YES; 356 | ENABLE_TESTABILITY = YES; 357 | GCC_C_LANGUAGE_STANDARD = gnu99; 358 | GCC_DYNAMIC_NO_PIC = NO; 359 | GCC_NO_COMMON_BLOCKS = YES; 360 | GCC_OPTIMIZATION_LEVEL = 0; 361 | GCC_PREPROCESSOR_DEFINITIONS = ( 362 | "DEBUG=1", 363 | "$(inherited)", 364 | ); 365 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 366 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 367 | GCC_WARN_UNDECLARED_SELECTOR = YES; 368 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 369 | GCC_WARN_UNUSED_FUNCTION = YES; 370 | GCC_WARN_UNUSED_VARIABLE = YES; 371 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 372 | MTL_ENABLE_DEBUG_INFO = YES; 373 | ONLY_ACTIVE_ARCH = YES; 374 | SDKROOT = iphoneos; 375 | TARGETED_DEVICE_FAMILY = "1,2"; 376 | }; 377 | name = Debug; 378 | }; 379 | 97C147041CF9000F007C117D /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ALWAYS_SEARCH_USER_PATHS = NO; 383 | CLANG_ANALYZER_NONNULL = YES; 384 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 385 | CLANG_CXX_LIBRARY = "libc++"; 386 | CLANG_ENABLE_MODULES = YES; 387 | CLANG_ENABLE_OBJC_ARC = YES; 388 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 389 | CLANG_WARN_BOOL_CONVERSION = YES; 390 | CLANG_WARN_COMMA = YES; 391 | CLANG_WARN_CONSTANT_CONVERSION = YES; 392 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 393 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 394 | CLANG_WARN_EMPTY_BODY = YES; 395 | CLANG_WARN_ENUM_CONVERSION = YES; 396 | CLANG_WARN_INFINITE_RECURSION = YES; 397 | CLANG_WARN_INT_CONVERSION = YES; 398 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 399 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 400 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 401 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 402 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 403 | CLANG_WARN_STRICT_PROTOTYPES = YES; 404 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 405 | CLANG_WARN_UNREACHABLE_CODE = YES; 406 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 407 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 408 | COPY_PHASE_STRIP = NO; 409 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 410 | ENABLE_NS_ASSERTIONS = NO; 411 | ENABLE_STRICT_OBJC_MSGSEND = YES; 412 | GCC_C_LANGUAGE_STANDARD = gnu99; 413 | GCC_NO_COMMON_BLOCKS = YES; 414 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 415 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 416 | GCC_WARN_UNDECLARED_SELECTOR = YES; 417 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 418 | GCC_WARN_UNUSED_FUNCTION = YES; 419 | GCC_WARN_UNUSED_VARIABLE = YES; 420 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 421 | MTL_ENABLE_DEBUG_INFO = NO; 422 | SDKROOT = iphoneos; 423 | TARGETED_DEVICE_FAMILY = "1,2"; 424 | VALIDATE_PRODUCT = YES; 425 | }; 426 | name = Release; 427 | }; 428 | 97C147061CF9000F007C117D /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 431 | buildSettings = { 432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | FRAMEWORK_SEARCH_PATHS = ( 436 | "$(inherited)", 437 | "$(PROJECT_DIR)/Flutter", 438 | ); 439 | INFOPLIST_FILE = Runner/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | LIBRARY_SEARCH_PATHS = ( 442 | "$(inherited)", 443 | "$(PROJECT_DIR)/Flutter", 444 | ); 445 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | VERSIONING_SYSTEM = "apple-generic"; 448 | }; 449 | name = Debug; 450 | }; 451 | 97C147071CF9000F007C117D /* Release */ = { 452 | isa = XCBuildConfiguration; 453 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 454 | buildSettings = { 455 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 456 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 457 | ENABLE_BITCODE = NO; 458 | FRAMEWORK_SEARCH_PATHS = ( 459 | "$(inherited)", 460 | "$(PROJECT_DIR)/Flutter", 461 | ); 462 | INFOPLIST_FILE = Runner/Info.plist; 463 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 464 | LIBRARY_SEARCH_PATHS = ( 465 | "$(inherited)", 466 | "$(PROJECT_DIR)/Flutter", 467 | ); 468 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 469 | PRODUCT_NAME = "$(TARGET_NAME)"; 470 | VERSIONING_SYSTEM = "apple-generic"; 471 | }; 472 | name = Release; 473 | }; 474 | /* End XCBuildConfiguration section */ 475 | 476 | /* Begin XCConfigurationList section */ 477 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 478 | isa = XCConfigurationList; 479 | buildConfigurations = ( 480 | 97C147031CF9000F007C117D /* Debug */, 481 | 97C147041CF9000F007C117D /* Release */, 482 | 249021D3217E4FDB00AE95B9 /* Profile */, 483 | ); 484 | defaultConfigurationIsVisible = 0; 485 | defaultConfigurationName = Release; 486 | }; 487 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 488 | isa = XCConfigurationList; 489 | buildConfigurations = ( 490 | 97C147061CF9000F007C117D /* Debug */, 491 | 97C147071CF9000F007C117D /* Release */, 492 | 249021D4217E4FDB00AE95B9 /* Profile */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | /* End XCConfigurationList section */ 498 | }; 499 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 500 | } 501 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "size": "20x20", 5 | "idiom": "iphone", 6 | "filename": "Icon-App-20x20@2x.png", 7 | "scale": "2x" 8 | }, 9 | { 10 | "size": "20x20", 11 | "idiom": "iphone", 12 | "filename": "Icon-App-20x20@3x.png", 13 | "scale": "3x" 14 | }, 15 | { 16 | "size": "29x29", 17 | "idiom": "iphone", 18 | "filename": "Icon-App-29x29@1x.png", 19 | "scale": "1x" 20 | }, 21 | { 22 | "size": "29x29", 23 | "idiom": "iphone", 24 | "filename": "Icon-App-29x29@2x.png", 25 | "scale": "2x" 26 | }, 27 | { 28 | "size": "29x29", 29 | "idiom": "iphone", 30 | "filename": "Icon-App-29x29@3x.png", 31 | "scale": "3x" 32 | }, 33 | { 34 | "size": "40x40", 35 | "idiom": "iphone", 36 | "filename": "Icon-App-40x40@2x.png", 37 | "scale": "2x" 38 | }, 39 | { 40 | "size": "40x40", 41 | "idiom": "iphone", 42 | "filename": "Icon-App-40x40@3x.png", 43 | "scale": "3x" 44 | }, 45 | { 46 | "size": "60x60", 47 | "idiom": "iphone", 48 | "filename": "Icon-App-60x60@2x.png", 49 | "scale": "2x" 50 | }, 51 | { 52 | "size": "60x60", 53 | "idiom": "iphone", 54 | "filename": "Icon-App-60x60@3x.png", 55 | "scale": "3x" 56 | }, 57 | { 58 | "size": "20x20", 59 | "idiom": "ipad", 60 | "filename": "Icon-App-20x20@1x.png", 61 | "scale": "1x" 62 | }, 63 | { 64 | "size": "20x20", 65 | "idiom": "ipad", 66 | "filename": "Icon-App-20x20@2x.png", 67 | "scale": "2x" 68 | }, 69 | { 70 | "size": "29x29", 71 | "idiom": "ipad", 72 | "filename": "Icon-App-29x29@1x.png", 73 | "scale": "1x" 74 | }, 75 | { 76 | "size": "29x29", 77 | "idiom": "ipad", 78 | "filename": "Icon-App-29x29@2x.png", 79 | "scale": "2x" 80 | }, 81 | { 82 | "size": "40x40", 83 | "idiom": "ipad", 84 | "filename": "Icon-App-40x40@1x.png", 85 | "scale": "1x" 86 | }, 87 | { 88 | "size": "40x40", 89 | "idiom": "ipad", 90 | "filename": "Icon-App-40x40@2x.png", 91 | "scale": "2x" 92 | }, 93 | { 94 | "size": "76x76", 95 | "idiom": "ipad", 96 | "filename": "Icon-App-76x76@1x.png", 97 | "scale": "1x" 98 | }, 99 | { 100 | "size": "76x76", 101 | "idiom": "ipad", 102 | "filename": "Icon-App-76x76@2x.png", 103 | "scale": "2x" 104 | }, 105 | { 106 | "size": "83.5x83.5", 107 | "idiom": "ipad", 108 | "filename": "Icon-App-83.5x83.5@2x.png", 109 | "scale": "2x" 110 | }, 111 | { 112 | "size": "1024x1024", 113 | "idiom": "ios-marketing", 114 | "filename": "Icon-App-1024x1024@1x.png", 115 | "scale": "1x" 116 | } 117 | ], 118 | "info": { 119 | "version": 1, 120 | "author": "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "LaunchImage.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "filename": "LaunchImage@2x.png", 11 | "scale": "2x" 12 | }, 13 | { 14 | "idiom": "universal", 15 | "filename": "LaunchImage@3x.png", 16 | "scale": "3x" 17 | } 18 | ], 19 | "info": { 20 | "version": 1, 21 | "author": "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | 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 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // ignore_for_file: library_private_types_in_public_api 16 | 17 | import 'package:example/screens/my_app.dart'; 18 | import 'package:flutter/material.dart'; 19 | 20 | void main() => runApp(const MyApp()); 21 | -------------------------------------------------------------------------------- /example/lib/screens/main_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:swipe_refresh/swipe_refresh.dart'; 5 | 6 | class MainPage extends StatefulWidget { 7 | const MainPage({Key? key}) : super(key: key); 8 | 9 | @override 10 | State createState() => _MainPageState(); 11 | } 12 | 13 | class _MainPageState extends State { 14 | final _controller = StreamController.broadcast(); 15 | 16 | Stream get _stream => _controller.stream; 17 | 18 | Future _refresh() async { 19 | await Future.delayed(const Duration(seconds: 3)); 20 | 21 | /// When all needed is done change state. 22 | _controller.sink.add(SwipeRefreshState.hidden); 23 | } 24 | 25 | @override 26 | void dispose() { 27 | _controller.close(); 28 | 29 | super.dispose(); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return DefaultTabController( 35 | length: 3, 36 | child: Scaffold( 37 | body: Padding( 38 | padding: const EdgeInsets.only(top: 25), 39 | child: Column( 40 | children: [ 41 | const TabBar( 42 | tabs: [ 43 | _TabWidget(style: SwipeRefreshStyle.material), 44 | _TabWidget(style: SwipeRefreshStyle.cupertino), 45 | _TabWidget(style: SwipeRefreshStyle.builder), 46 | ], 47 | ), 48 | Expanded( 49 | child: TabBarView( 50 | children: [ 51 | SwipeRefresh.material( 52 | stateStream: _stream, 53 | onRefresh: () { 54 | _refresh().ignore(); 55 | }, 56 | padding: const EdgeInsets.symmetric(vertical: 10), 57 | children: const [ 58 | _ExampleBodyWidget(style: SwipeRefreshStyle.material), 59 | ], 60 | ), 61 | SwipeRefresh.cupertino( 62 | stateStream: _stream, 63 | onRefresh: () { 64 | _refresh().ignore(); 65 | }, 66 | padding: const EdgeInsets.symmetric(vertical: 10), 67 | children: const [ 68 | _ExampleBodyWidget(style: SwipeRefreshStyle.cupertino), 69 | ], 70 | ), 71 | SwipeRefresh.builder( 72 | stateStream: _stream, 73 | onRefresh: () { 74 | _refresh().ignore(); 75 | }, 76 | padding: const EdgeInsets.symmetric(vertical: 10), 77 | itemCount: Colors.primaries.length, 78 | itemBuilder: (context, index) { 79 | return Container( 80 | color: Colors.primaries[index], 81 | height: 100, 82 | child: const Center( 83 | child: Text( 84 | 'Builder example', 85 | style: TextStyle(color: white), 86 | ), 87 | ), 88 | ); 89 | }, 90 | ), 91 | ], 92 | ), 93 | ), 94 | ], 95 | ), 96 | ), 97 | ), 98 | ); 99 | } 100 | } 101 | 102 | class _TabWidget extends StatelessWidget { 103 | const _TabWidget({ 104 | required this.style, 105 | Key? key, 106 | }) : super(key: key); 107 | 108 | final SwipeRefreshStyle style; 109 | 110 | @override 111 | Widget build(BuildContext context) { 112 | return InkWell( 113 | child: SizedBox( 114 | height: 100, 115 | child: Center( 116 | child: Text( 117 | _getText(style), 118 | style: TextStyle(color: _getColor(style).withOpacity(0.5)), 119 | ), 120 | ), 121 | ), 122 | ); 123 | } 124 | } 125 | 126 | class _ExampleBodyWidget extends StatelessWidget { 127 | const _ExampleBodyWidget({ 128 | required this.style, 129 | Key? key, 130 | }) : super(key: key); 131 | 132 | final SwipeRefreshStyle style; 133 | 134 | @override 135 | Widget build(BuildContext context) { 136 | return Container( 137 | color: _getColor(style), 138 | height: 100, 139 | child: Center( 140 | child: Text( 141 | style == SwipeRefreshStyle.material 142 | ? 'Material example' 143 | : 'Cupertino example', 144 | style: const TextStyle(color: white), 145 | ), 146 | ), 147 | ); 148 | } 149 | } 150 | 151 | Color _getColor(SwipeRefreshStyle style) { 152 | switch (style) { 153 | case SwipeRefreshStyle.material: 154 | return red; 155 | case SwipeRefreshStyle.cupertino: 156 | return blue; 157 | case SwipeRefreshStyle.builder: 158 | return green; 159 | default: 160 | return black; 161 | } 162 | } 163 | 164 | String _getText(SwipeRefreshStyle style) { 165 | switch (style) { 166 | case SwipeRefreshStyle.material: 167 | return 'Material'; 168 | case SwipeRefreshStyle.cupertino: 169 | return 'Cupertino'; 170 | case SwipeRefreshStyle.builder: 171 | return 'Builder'; 172 | default: 173 | return 'SwipeRefresh'; 174 | } 175 | } 176 | 177 | const white = Color(0xFFFFFFFF); 178 | const black = Color(0xFF000000); 179 | const red = Color(0xFFFF0000); 180 | const green = Color(0xFF00FF00); 181 | const blue = Color(0xFF0000FF); 182 | -------------------------------------------------------------------------------- /example/lib/screens/my_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:example/screens/main_page.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class MyApp extends StatelessWidget { 5 | const MyApp({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Refresher Example', 11 | theme: ThemeData( 12 | primarySwatch: Colors.blue, 13 | ), 14 | home: const MainPage(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "61.0.0" 12 | analyzer: 13 | dependency: transitive 14 | description: 15 | name: analyzer 16 | sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "5.13.0" 20 | analyzer_plugin: 21 | dependency: transitive 22 | description: 23 | name: analyzer_plugin 24 | sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "0.11.2" 28 | ansicolor: 29 | dependency: transitive 30 | description: 31 | name: ansicolor 32 | sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.0.1" 36 | args: 37 | dependency: transitive 38 | description: 39 | name: args 40 | sha256: "4276641ebd31b2fd6dbd922c665a4877482179fee8034cf7bdfb8bc70b7b67c8" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "2.1.1" 44 | async: 45 | dependency: transitive 46 | description: 47 | name: async 48 | sha256: "5386f08a54d1b58d17e4bc6dee9b6b24a256b1fc7e2addba11945eec144edad8" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "2.7.0" 52 | characters: 53 | dependency: transitive 54 | description: 55 | name: characters 56 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.0" 60 | charcode: 61 | dependency: transitive 62 | description: 63 | name: charcode 64 | sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.3.1" 68 | collection: 69 | dependency: transitive 70 | description: 71 | name: collection 72 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "1.18.0" 76 | convert: 77 | dependency: transitive 78 | description: 79 | name: convert 80 | sha256: f08428ad63615f96a27e34221c65e1a451439b5f26030f78d790f461c686d65d 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "3.0.1" 84 | crypto: 85 | dependency: transitive 86 | description: 87 | name: crypto 88 | sha256: cf75650c66c0316274e21d7c43d3dea246273af5955bd94e8184837cd577575c 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "3.0.1" 92 | csslib: 93 | dependency: transitive 94 | description: 95 | name: csslib 96 | sha256: f857285c8dc0b4f2f77b49a1c083ff8c75223a7549de20f3e607df58cf497a43 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "0.17.0" 100 | dart_code_metrics: 101 | dependency: transitive 102 | description: 103 | name: dart_code_metrics 104 | sha256: "3dede3f7abc077a4181ec7445448a289a9ce08e2981e6a4d49a3fb5099d47e1f" 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "5.7.6" 108 | dart_code_metrics_presets: 109 | dependency: transitive 110 | description: 111 | name: dart_code_metrics_presets 112 | sha256: b71eadf02a3787ebd5c887623f83f6fdc204d45c75a081bd636c4104b3fd8b73 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "1.8.0" 116 | dart_style: 117 | dependency: transitive 118 | description: 119 | name: dart_style 120 | sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "2.3.2" 124 | file: 125 | dependency: transitive 126 | description: 127 | name: file 128 | sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "6.1.2" 132 | flutter: 133 | dependency: "direct main" 134 | description: flutter 135 | source: sdk 136 | version: "0.0.0" 137 | flutter_lints: 138 | dependency: transitive 139 | description: 140 | name: flutter_lints 141 | sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 142 | url: "https://pub.dev" 143 | source: hosted 144 | version: "2.0.3" 145 | glob: 146 | dependency: transitive 147 | description: 148 | name: glob 149 | sha256: dda85ce2aefce16f7e75586acbcb1e8320bf176f69fd94082e31945d6de67f3e 150 | url: "https://pub.dev" 151 | source: hosted 152 | version: "2.0.1" 153 | html: 154 | dependency: transitive 155 | description: 156 | name: html 157 | sha256: bfef906cbd4e78ef49ae511d9074aebd1d2251482ef601a280973e8b58b51bbf 158 | url: "https://pub.dev" 159 | source: hosted 160 | version: "0.15.0" 161 | http: 162 | dependency: transitive 163 | description: 164 | name: http 165 | sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" 166 | url: "https://pub.dev" 167 | source: hosted 168 | version: "0.13.6" 169 | http_parser: 170 | dependency: transitive 171 | description: 172 | name: http_parser 173 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 174 | url: "https://pub.dev" 175 | source: hosted 176 | version: "4.0.2" 177 | json_annotation: 178 | dependency: transitive 179 | description: 180 | name: json_annotation 181 | sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 182 | url: "https://pub.dev" 183 | source: hosted 184 | version: "4.8.1" 185 | lints: 186 | dependency: transitive 187 | description: 188 | name: lints 189 | sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" 190 | url: "https://pub.dev" 191 | source: hosted 192 | version: "2.1.1" 193 | material_color_utilities: 194 | dependency: transitive 195 | description: 196 | name: material_color_utilities 197 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 198 | url: "https://pub.dev" 199 | source: hosted 200 | version: "0.8.0" 201 | meta: 202 | dependency: transitive 203 | description: 204 | name: meta 205 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 206 | url: "https://pub.dev" 207 | source: hosted 208 | version: "1.11.0" 209 | package_config: 210 | dependency: transitive 211 | description: 212 | name: package_config 213 | sha256: "20e7154d701fedaeb219dad732815ecb66677667871127998a9a6581c2aba4ba" 214 | url: "https://pub.dev" 215 | source: hosted 216 | version: "2.0.0" 217 | path: 218 | dependency: transitive 219 | description: 220 | name: path 221 | sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb" 222 | url: "https://pub.dev" 223 | source: hosted 224 | version: "1.8.0" 225 | pedantic: 226 | dependency: transitive 227 | description: 228 | name: pedantic 229 | sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" 230 | url: "https://pub.dev" 231 | source: hosted 232 | version: "1.11.1" 233 | petitparser: 234 | dependency: transitive 235 | description: 236 | name: petitparser 237 | sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 238 | url: "https://pub.dev" 239 | source: hosted 240 | version: "6.0.2" 241 | platform: 242 | dependency: transitive 243 | description: 244 | name: platform 245 | sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" 246 | url: "https://pub.dev" 247 | source: hosted 248 | version: "3.1.4" 249 | process: 250 | dependency: transitive 251 | description: 252 | name: process 253 | sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" 254 | url: "https://pub.dev" 255 | source: hosted 256 | version: "4.2.4" 257 | pub_semver: 258 | dependency: transitive 259 | description: 260 | name: pub_semver 261 | sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" 262 | url: "https://pub.dev" 263 | source: hosted 264 | version: "2.1.4" 265 | pub_updater: 266 | dependency: transitive 267 | description: 268 | name: pub_updater 269 | sha256: "05ae70703e06f7fdeb05f7f02dd680b8aad810e87c756a618f33e1794635115c" 270 | url: "https://pub.dev" 271 | source: hosted 272 | version: "0.3.0" 273 | sky_engine: 274 | dependency: transitive 275 | description: flutter 276 | source: sdk 277 | version: "0.0.99" 278 | source_span: 279 | dependency: transitive 280 | description: 281 | name: source_span 282 | sha256: d5f89a9e52b36240a80282b3dc0667dd36e53459717bb17b8fb102d30496606a 283 | url: "https://pub.dev" 284 | source: hosted 285 | version: "1.8.1" 286 | string_scanner: 287 | dependency: transitive 288 | description: 289 | name: string_scanner 290 | sha256: dd11571b8a03f7cadcf91ec26a77e02bfbd6bbba2a512924d3116646b4198fc4 291 | url: "https://pub.dev" 292 | source: hosted 293 | version: "1.1.0" 294 | surf_lint_rules: 295 | dependency: "direct dev" 296 | description: 297 | name: surf_lint_rules 298 | sha256: "0465c70586a137db13a1e6afb1bd10b48a95c90fe29fdcee15a96c9f70fe2b19" 299 | url: "https://pub.dev" 300 | source: hosted 301 | version: "2.1.0" 302 | swipe_refresh: 303 | dependency: "direct main" 304 | description: 305 | path: ".." 306 | relative: true 307 | source: path 308 | version: "1.1.0" 309 | term_glyph: 310 | dependency: transitive 311 | description: 312 | name: term_glyph 313 | sha256: a88162591b02c1f3a3db3af8ce1ea2b374bd75a7bb8d5e353bcfbdc79d719830 314 | url: "https://pub.dev" 315 | source: hosted 316 | version: "1.2.0" 317 | typed_data: 318 | dependency: transitive 319 | description: 320 | name: typed_data 321 | sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" 322 | url: "https://pub.dev" 323 | source: hosted 324 | version: "1.3.0" 325 | uuid: 326 | dependency: transitive 327 | description: 328 | name: uuid 329 | sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" 330 | url: "https://pub.dev" 331 | source: hosted 332 | version: "3.0.7" 333 | vector_math: 334 | dependency: transitive 335 | description: 336 | name: vector_math 337 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 338 | url: "https://pub.dev" 339 | source: hosted 340 | version: "2.1.4" 341 | watcher: 342 | dependency: transitive 343 | description: 344 | name: watcher 345 | sha256: "68173f2fa67d241323a4123be7ed4e43424c54befa5505d71c8ad4b7baf8f71d" 346 | url: "https://pub.dev" 347 | source: hosted 348 | version: "1.0.0" 349 | xml: 350 | dependency: transitive 351 | description: 352 | name: xml 353 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 354 | url: "https://pub.dev" 355 | source: hosted 356 | version: "6.5.0" 357 | yaml: 358 | dependency: transitive 359 | description: 360 | name: yaml 361 | sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" 362 | url: "https://pub.dev" 363 | source: hosted 364 | version: "3.1.0" 365 | sdks: 366 | dart: ">=3.2.0 <4.0.0" 367 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: Example of using swipe refresh. 3 | version: 1.0.0+1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.0.0 <4.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | swipe_refresh: 14 | path: ../ 15 | 16 | dev_dependencies: 17 | surf_lint_rules: ^2.0.0 18 | 19 | flutter: 20 | uses-material-design: true 21 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surfstudio/flutter-swipe-refresh/9a680f7aaf036211b8556214769155cb98df9cf0/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/cupertino_swipe_refresh.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/cupertino.dart'; 18 | import 'package:swipe_refresh/src/swipe_refresh_base.dart'; 19 | import 'package:swipe_refresh/src/swipe_refresh_state.dart'; 20 | 21 | /// Refresh indicator widget with Cupertino style. 22 | /// [stateStream] - indicator state([SwipeRefreshState.loading] or 23 | /// [SwipeRefreshState.hidden]). 24 | /// [onRefresh] - callback invoked when pulled by [refreshTriggerPullDistance]. 25 | /// [children] - list of any widgets. 26 | /// [childrenDelegate] - pass the inheritor to SliverChildDelegate to avoid 27 | /// creating more children than are visible through the [Viewport]. 28 | /// [initState] - initialization state([SwipeRefreshState.loading] or 29 | /// [SwipeRefreshState.hidden]). 30 | /// [padding] - passed to add [SliverPadding]. 31 | /// [scrollController] - ScrollController for [CustomScrollView]. 32 | /// [shrinkWrap] - Whether the extent of the scroll view should be determined 33 | /// by the contents being viewed(default - false). 34 | /// [refreshTriggerPullDistance] - The amount of overscroll the scrollable 35 | /// must be dragged to trigger a reload(default - [defaultRefreshTriggerPullDistance]). 36 | /// [refreshIndicatorExtent] - amount of space the refresh indicator 37 | /// sliver will keep holding while [onRefresh] is still running. 38 | /// [indicatorBuilder] - builder that's called as this sliver's size changes, 39 | /// and as the state changes(default - [CupertinoSliverRefreshControl.buildRefreshIndicator]). 40 | /// [keyboardDismissBehavior] - [ScrollViewKeyboardDismissBehavior] 41 | /// the defines how this [ScrollView] will dismiss the keyboard automatically. 42 | /// (if == null it will be [ScrollViewKeyboardDismissBehavior.onDrag]). 43 | /// [physics] - defines the physics of the scroll(if == null it will be 44 | /// [AlwaysScrollableScrollPhysics]). 45 | class CupertinoSwipeRefresh extends SwipeRefreshBase { 46 | const CupertinoSwipeRefresh({ 47 | required Stream stateStream, 48 | required VoidCallback onRefresh, 49 | this.refreshTriggerPullDistance = defaultRefreshTriggerPullDistance, 50 | this.refreshIndicatorExtent = defaultRefreshIndicatorExtent, 51 | this.indicatorBuilder = CupertinoSliverRefreshControl.buildRefreshIndicator, 52 | List? children, 53 | SliverChildDelegate? childrenDelegate, 54 | SwipeRefreshState? initState, 55 | EdgeInsets? padding, 56 | ScrollController? scrollController, 57 | bool shrinkWrap = false, 58 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 59 | ScrollPhysics? physics, 60 | Key? key, 61 | this.cacheExtent, 62 | }) : super( 63 | key: key, 64 | children: children, 65 | childrenDelegate: childrenDelegate, 66 | stateStream: stateStream, 67 | initState: initState, 68 | onRefresh: onRefresh, 69 | scrollController: scrollController, 70 | padding: padding, 71 | shrinkWrap: shrinkWrap, 72 | keyboardDismissBehavior: keyboardDismissBehavior, 73 | physics: physics, 74 | ); 75 | 76 | static const double defaultRefreshTriggerPullDistance = 100.0; 77 | static const double defaultRefreshIndicatorExtent = 60.0; 78 | 79 | final double refreshTriggerPullDistance; 80 | final double refreshIndicatorExtent; 81 | final RefreshControlIndicatorBuilder indicatorBuilder; 82 | final double? cacheExtent; 83 | 84 | @override 85 | SwipeRefreshBaseState createState() => _CupertinoSwipeRefreshState(); 86 | } 87 | 88 | class _CupertinoSwipeRefreshState 89 | extends SwipeRefreshBaseState { 90 | late final ScrollController _scrollController; 91 | 92 | @override 93 | void initState() { 94 | super.initState(); 95 | _scrollController = widget.scrollController ?? ScrollController(); 96 | } 97 | 98 | @override 99 | Widget buildRefresher( 100 | Key key, 101 | List children, 102 | Future Function() onRefresh, 103 | ) { 104 | return CustomScrollView( 105 | shrinkWrap: widget.shrinkWrap, 106 | controller: _scrollController, 107 | scrollBehavior: scrollBehavior, 108 | keyboardDismissBehavior: widget.keyboardDismissBehavior ?? 109 | ScrollViewKeyboardDismissBehavior.onDrag, 110 | cacheExtent: widget.cacheExtent, 111 | physics: widget.physics == null 112 | ? const BouncingScrollPhysics( 113 | parent: AlwaysScrollableScrollPhysics(), 114 | ) 115 | : AlwaysScrollableScrollPhysics(parent: widget.physics), 116 | slivers: [ 117 | CupertinoSliverRefreshControl( 118 | key: key, 119 | onRefresh: onRefresh, 120 | refreshTriggerPullDistance: widget.refreshTriggerPullDistance, 121 | refreshIndicatorExtent: widget.refreshIndicatorExtent, 122 | builder: widget.indicatorBuilder, 123 | ), 124 | SliverSafeArea( 125 | bottom: widget.padding == null, 126 | left: widget.padding == null, 127 | right: widget.padding == null, 128 | top: widget.padding == null, 129 | sliver: _ListChildrenWidget( 130 | children: children, 131 | padding: widget.padding, 132 | childrenDelegate: widget.childrenDelegate, 133 | ), 134 | ), 135 | ], 136 | ); 137 | } 138 | 139 | @override 140 | void onUpdateState(SwipeRefreshState state) { 141 | if (state == SwipeRefreshState.hidden) { 142 | if (completer != null) { 143 | completer!.complete(); 144 | completer = null; 145 | } 146 | } 147 | } 148 | } 149 | 150 | class _ListChildrenWidget extends StatelessWidget { 151 | const _ListChildrenWidget({ 152 | required this.children, 153 | Key? key, 154 | this.padding, 155 | this.childrenDelegate, 156 | }) : super(key: key); 157 | 158 | final List children; 159 | final EdgeInsets? padding; 160 | final SliverChildDelegate? childrenDelegate; 161 | 162 | @override 163 | Widget build(BuildContext context) { 164 | if (padding != null) { 165 | return SliverPadding( 166 | padding: padding!, 167 | sliver: SliverList( 168 | delegate: childrenDelegate ?? 169 | SliverChildListDelegate( 170 | children, 171 | ), 172 | ), 173 | ); 174 | } 175 | return SliverList( 176 | delegate: childrenDelegate ?? 177 | SliverChildListDelegate( 178 | children, 179 | ), 180 | ); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /lib/src/material_swipe_refresh.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // ignore_for_file: library_private_types_in_public_api 16 | 17 | import 'dart:async'; 18 | 19 | import 'package:flutter/material.dart'; 20 | import 'package:swipe_refresh/src/swipe_refresh_base.dart'; 21 | import 'package:swipe_refresh/src/swipe_refresh_state.dart'; 22 | import 'package:swipe_refresh/src/widgets/conditional_wrapper.dart'; 23 | 24 | /// Refresh indicator widget with Material Design style. 25 | /// [stateStream] - indicator state([SwipeRefreshState.loading] or 26 | /// [SwipeRefreshState.hidden]). 27 | /// [onRefresh] - function that's called when the user has dragged the 28 | /// refresh indicator far enough to demonstrate that they want the app to refresh. 29 | /// [indicatorColor] - progress indicator's foreground color 30 | /// (default - [ColorScheme.primary]). 31 | /// [children] - list of any widgets. 32 | /// [childrenDelegate] - pass the inheritor to SliverChildDelegate 33 | /// to avoid creating more children than are visible through the [Viewport]. 34 | /// [initState] - initialization state([SwipeRefreshState.loading] or 35 | /// [SwipeRefreshState.hidden]). 36 | /// [backgroundColor] - progress indicator's background color 37 | /// (default - Color(0xFFFFFFFF)). 38 | /// [scrollController] - [ScrollController] for [ListView]. 39 | /// [padding] - corresponds to having a [SliverPadding] in the 40 | /// [CustomScrollView.slivers] property instead of the list itself, 41 | /// and having the [SliverList] instead be a child of the [SliverPadding]. 42 | /// [shrinkWrap] - Whether the extent of the scroll view should be determined 43 | /// by the contents being viewed(default - false). 44 | /// [keyboardDismissBehavior] - [ScrollViewKeyboardDismissBehavior] 45 | /// the defines how this [ScrollView] will dismiss the keyboard automatically. 46 | /// (if == null it will be [ScrollViewKeyboardDismissBehavior.manual]). 47 | /// [physics] - defines the physics of the scroll(if == null it will be 48 | /// [AlwaysScrollableScrollPhysics]). 49 | class MaterialSwipeRefresh extends SwipeRefreshBase { 50 | const MaterialSwipeRefresh({ 51 | required Stream stateStream, 52 | required VoidCallback onRefresh, 53 | this.indicatorColor, 54 | List? children, 55 | SliverChildDelegate? childrenDelegate, 56 | SwipeRefreshState? initState, 57 | Color? backgroundColor, 58 | EdgeInsets? padding, 59 | ScrollController? scrollController, 60 | bool shrinkWrap = false, 61 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 62 | ScrollPhysics? physics, 63 | Key? key, 64 | this.cacheExtent, 65 | }) : backgroundColor = backgroundColor ?? Colors.white, 66 | super( 67 | key: key, 68 | children: children, 69 | childrenDelegate: childrenDelegate, 70 | stateStream: stateStream, 71 | initState: initState, 72 | onRefresh: onRefresh, 73 | scrollController: scrollController, 74 | padding: padding, 75 | shrinkWrap: shrinkWrap, 76 | keyboardDismissBehavior: keyboardDismissBehavior, 77 | physics: physics, 78 | ); 79 | 80 | final Color? indicatorColor; 81 | final Color backgroundColor; 82 | final double? cacheExtent; 83 | 84 | @override 85 | SwipeRefreshBaseState createState() => _MaterialSwipeRefreshState(); 86 | } 87 | 88 | class _MaterialSwipeRefreshState 89 | extends SwipeRefreshBaseState { 90 | late final ScrollController _scrollController; 91 | 92 | @override 93 | void initState() { 94 | super.initState(); 95 | _scrollController = widget.scrollController ?? ScrollController(); 96 | } 97 | 98 | @override 99 | Widget buildRefresher( 100 | Key key, 101 | List children, 102 | Future Function() onRefresh, 103 | ) { 104 | return RefreshIndicator( 105 | key: key, 106 | onRefresh: onRefresh, 107 | color: widget.indicatorColor, 108 | backgroundColor: widget.backgroundColor, 109 | child: ConditionalWrapper( 110 | condition: scrollBehavior != null, 111 | wrapper: (child) => ScrollConfiguration( 112 | behavior: scrollBehavior ?? const MaterialScrollBehavior(), 113 | child: child, 114 | ), 115 | child: widget.childrenDelegate == null 116 | ? ListView( 117 | shrinkWrap: widget.shrinkWrap, 118 | padding: widget.padding, 119 | cacheExtent: widget.cacheExtent, 120 | controller: _scrollController, 121 | physics: AlwaysScrollableScrollPhysics(parent: widget.physics), 122 | keyboardDismissBehavior: widget.keyboardDismissBehavior ?? 123 | ScrollViewKeyboardDismissBehavior.manual, 124 | children: children, 125 | ) 126 | : ListView.custom( 127 | shrinkWrap: widget.shrinkWrap, 128 | padding: widget.padding, 129 | cacheExtent: widget.cacheExtent, 130 | childrenDelegate: widget.childrenDelegate!, 131 | controller: _scrollController, 132 | keyboardDismissBehavior: widget.keyboardDismissBehavior ?? 133 | ScrollViewKeyboardDismissBehavior.manual, 134 | physics: AlwaysScrollableScrollPhysics(parent: widget.physics), 135 | ), 136 | ), 137 | ); 138 | } 139 | 140 | @override 141 | void onUpdateState(SwipeRefreshState state) { 142 | if (state == SwipeRefreshState.hidden) { 143 | if (completer != null) { 144 | completer!.complete(); 145 | completer = null; 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /lib/src/swipe_refresh.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:flutter/cupertino.dart'; 16 | import 'package:swipe_refresh/src/cupertino_swipe_refresh.dart'; 17 | import 'package:swipe_refresh/src/material_swipe_refresh.dart'; 18 | import 'package:swipe_refresh/src/swipe_refresh_state.dart'; 19 | import 'package:swipe_refresh/src/swipe_refresh_style.dart'; 20 | import 'package:swipe_refresh/utills/platform_wrapper.dart'; 21 | 22 | /// Refresh indicator widget. 23 | /// 24 | /// Params for Material Design style: 25 | /// [indicatorColor], [backgroundColor](more details [MaterialSwipeRefresh]). 26 | /// 27 | /// Params for Cupertino style: 28 | /// [refreshTriggerPullDistance], [refreshIndicatorExtent], [indicatorBuilder] 29 | /// (more details [CupertinoSwipeRefresh]). 30 | class SwipeRefresh extends StatelessWidget { 31 | const SwipeRefresh( 32 | this.style, { 33 | required this.stateStream, 34 | required this.onRefresh, 35 | Key? key, 36 | this.children, 37 | this.initState, 38 | this.scrollController, 39 | this.childrenDelegate, 40 | this.padding, 41 | this.indicatorColor, 42 | this.shrinkWrap = false, 43 | this.keyboardDismissBehavior, 44 | this.physics, 45 | Color? backgroundColor, 46 | double? refreshTriggerPullDistance, 47 | double? refreshIndicatorExtent, 48 | RefreshControlIndicatorBuilder? indicatorBuilder, 49 | PlatformWrapper? platform, 50 | this.cacheExtent, 51 | }) : backgroundColor = backgroundColor ?? const Color(0xFFFFFFFF), 52 | refreshTriggerPullDistance = refreshTriggerPullDistance ?? 53 | CupertinoSwipeRefresh.defaultRefreshTriggerPullDistance, 54 | refreshIndicatorExtent = refreshIndicatorExtent ?? 55 | CupertinoSwipeRefresh.defaultRefreshIndicatorExtent, 56 | indicatorBuilder = indicatorBuilder ?? 57 | CupertinoSliverRefreshControl.buildRefreshIndicator, 58 | _platform = platform ?? const PlatformWrapper(), 59 | super(key: key); 60 | 61 | /// Create refresh indicator adaptive to platform. 62 | const SwipeRefresh.adaptive({ 63 | required Stream stateStream, 64 | required VoidCallback onRefresh, 65 | List? children, 66 | SliverChildDelegate? childrenDelegate, 67 | Key? key, 68 | SwipeRefreshState? initState, 69 | Color? indicatorColor, 70 | Color? backgroundColor, 71 | double? refreshTriggerPullDistance, 72 | double? refreshIndicatorExtent, 73 | RefreshControlIndicatorBuilder? indicatorBuilder, 74 | ScrollController? scrollController, 75 | EdgeInsets? padding, 76 | bool shrinkWrap = false, 77 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 78 | ScrollPhysics? physics, 79 | PlatformWrapper? platform, 80 | double? cacheExtent, 81 | }) : this( 82 | SwipeRefreshStyle.adaptive, 83 | key: key, 84 | children: children, 85 | childrenDelegate: childrenDelegate, 86 | stateStream: stateStream, 87 | initState: initState, 88 | onRefresh: onRefresh, 89 | indicatorColor: indicatorColor, 90 | backgroundColor: backgroundColor, 91 | refreshTriggerPullDistance: refreshTriggerPullDistance, 92 | refreshIndicatorExtent: refreshIndicatorExtent, 93 | indicatorBuilder: indicatorBuilder, 94 | scrollController: scrollController, 95 | padding: padding, 96 | shrinkWrap: shrinkWrap, 97 | keyboardDismissBehavior: keyboardDismissBehavior, 98 | physics: physics, 99 | platform: platform, 100 | cacheExtent: cacheExtent, 101 | ); 102 | 103 | /// Create refresh indicator with Material Design style. 104 | const SwipeRefresh.material({ 105 | required Stream stateStream, 106 | required VoidCallback onRefresh, 107 | List? children, 108 | SliverChildDelegate? childrenDelegate, 109 | Key? key, 110 | SwipeRefreshState? initState, 111 | Color? indicatorColor, 112 | Color? backgroundColor, 113 | ScrollController? scrollController, 114 | EdgeInsets? padding, 115 | bool shrinkWrap = false, 116 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 117 | ScrollPhysics? physics, 118 | double? cacheExtent, 119 | }) : this( 120 | SwipeRefreshStyle.material, 121 | key: key, 122 | children: children, 123 | childrenDelegate: childrenDelegate, 124 | stateStream: stateStream, 125 | initState: initState, 126 | onRefresh: onRefresh, 127 | indicatorColor: indicatorColor, 128 | backgroundColor: backgroundColor, 129 | scrollController: scrollController, 130 | padding: padding, 131 | shrinkWrap: shrinkWrap, 132 | keyboardDismissBehavior: keyboardDismissBehavior, 133 | physics: physics, 134 | cacheExtent: cacheExtent, 135 | ); 136 | 137 | /// Create refresh indicator with Cupertino style. 138 | const SwipeRefresh.cupertino({ 139 | required Stream stateStream, 140 | required VoidCallback onRefresh, 141 | List? children, 142 | SliverChildDelegate? childrenDelegate, 143 | Key? key, 144 | SwipeRefreshState? initState, 145 | double? refreshTriggerPullDistance, 146 | double? refreshIndicatorExtent, 147 | RefreshControlIndicatorBuilder? indicatorBuilder, 148 | ScrollController? scrollController, 149 | EdgeInsets? padding, 150 | bool shrinkWrap = false, 151 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 152 | ScrollPhysics? physics, 153 | double? cacheExtent, 154 | }) : this( 155 | SwipeRefreshStyle.cupertino, 156 | key: key, 157 | children: children, 158 | childrenDelegate: childrenDelegate, 159 | stateStream: stateStream, 160 | initState: initState, 161 | onRefresh: onRefresh, 162 | refreshTriggerPullDistance: refreshTriggerPullDistance, 163 | refreshIndicatorExtent: refreshIndicatorExtent, 164 | indicatorBuilder: indicatorBuilder, 165 | scrollController: scrollController, 166 | padding: padding, 167 | shrinkWrap: shrinkWrap, 168 | keyboardDismissBehavior: keyboardDismissBehavior, 169 | physics: physics, 170 | cacheExtent: cacheExtent, 171 | ); 172 | 173 | /// Create refresh indicator with adaptive to platform style. 174 | /// Uses SliverChildBuilderDelegate in childrenDelegate to avoid 175 | /// creating more children than are visible through the [Viewport]. 176 | factory SwipeRefresh.builder({ 177 | required IndexedWidgetBuilder itemBuilder, 178 | required int itemCount, 179 | required Stream stateStream, 180 | required VoidCallback onRefresh, 181 | Key? key, 182 | SwipeRefreshState? initState, 183 | Color? indicatorColor, 184 | Color? backgroundColor, 185 | double? refreshTriggerPullDistance, 186 | double? refreshIndicatorExtent, 187 | RefreshControlIndicatorBuilder? indicatorBuilder, 188 | ScrollController? scrollController, 189 | EdgeInsets? padding, 190 | bool shrinkWrap = false, 191 | ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior, 192 | ScrollPhysics? physics, 193 | PlatformWrapper? platform, 194 | double? cacheExtent, 195 | }) { 196 | return SwipeRefresh( 197 | SwipeRefreshStyle.adaptive, 198 | key: key, 199 | stateStream: stateStream, 200 | initState: initState, 201 | onRefresh: onRefresh, 202 | indicatorColor: indicatorColor, 203 | backgroundColor: backgroundColor, 204 | refreshTriggerPullDistance: refreshTriggerPullDistance, 205 | refreshIndicatorExtent: refreshIndicatorExtent, 206 | indicatorBuilder: indicatorBuilder, 207 | scrollController: scrollController, 208 | padding: padding, 209 | shrinkWrap: shrinkWrap, 210 | keyboardDismissBehavior: keyboardDismissBehavior, 211 | physics: physics, 212 | childrenDelegate: SliverChildBuilderDelegate( 213 | itemBuilder, 214 | childCount: itemCount, 215 | ), 216 | platform: platform, 217 | cacheExtent: cacheExtent, 218 | ); 219 | } 220 | 221 | final List? children; 222 | final VoidCallback onRefresh; 223 | final SwipeRefreshState? initState; 224 | final Stream stateStream; 225 | final Color? indicatorColor; 226 | final Color backgroundColor; 227 | final double refreshTriggerPullDistance; 228 | final double refreshIndicatorExtent; 229 | final RefreshControlIndicatorBuilder indicatorBuilder; 230 | final SwipeRefreshStyle style; 231 | final ScrollController? scrollController; 232 | final SliverChildDelegate? childrenDelegate; 233 | final EdgeInsets? padding; 234 | final bool shrinkWrap; 235 | final ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior; 236 | final ScrollPhysics? physics; 237 | final PlatformWrapper _platform; 238 | final double? cacheExtent; 239 | 240 | @override 241 | Widget build(BuildContext context) { 242 | switch (style) { 243 | case SwipeRefreshStyle.material: 244 | return MaterialSwipeRefresh( 245 | key: key, 246 | childrenDelegate: childrenDelegate, 247 | stateStream: stateStream, 248 | initState: initState, 249 | onRefresh: onRefresh, 250 | scrollController: scrollController, 251 | backgroundColor: backgroundColor, 252 | indicatorColor: indicatorColor, 253 | shrinkWrap: shrinkWrap, 254 | padding: padding, 255 | keyboardDismissBehavior: keyboardDismissBehavior, 256 | physics: physics, 257 | children: children, 258 | ); 259 | case SwipeRefreshStyle.cupertino: 260 | return CupertinoSwipeRefresh( 261 | key: key, 262 | childrenDelegate: childrenDelegate, 263 | stateStream: stateStream, 264 | initState: initState, 265 | onRefresh: onRefresh, 266 | scrollController: scrollController, 267 | refreshIndicatorExtent: refreshIndicatorExtent, 268 | refreshTriggerPullDistance: refreshTriggerPullDistance, 269 | indicatorBuilder: indicatorBuilder, 270 | shrinkWrap: shrinkWrap, 271 | padding: padding, 272 | physics: physics, 273 | children: children, 274 | ); 275 | case SwipeRefreshStyle.builder: 276 | case SwipeRefreshStyle.adaptive: 277 | if (_platform.isCupertino) { 278 | return CupertinoSwipeRefresh( 279 | key: key, 280 | childrenDelegate: childrenDelegate, 281 | stateStream: stateStream, 282 | initState: initState, 283 | onRefresh: onRefresh, 284 | scrollController: scrollController, 285 | refreshIndicatorExtent: refreshIndicatorExtent, 286 | refreshTriggerPullDistance: refreshTriggerPullDistance, 287 | indicatorBuilder: indicatorBuilder, 288 | shrinkWrap: shrinkWrap, 289 | padding: padding, 290 | physics: physics, 291 | children: children, 292 | cacheExtent: cacheExtent, 293 | ); 294 | } else { 295 | return MaterialSwipeRefresh( 296 | key: key, 297 | childrenDelegate: childrenDelegate, 298 | stateStream: stateStream, 299 | initState: initState, 300 | onRefresh: onRefresh, 301 | scrollController: scrollController, 302 | backgroundColor: backgroundColor, 303 | indicatorColor: indicatorColor, 304 | shrinkWrap: shrinkWrap, 305 | padding: padding, 306 | keyboardDismissBehavior: keyboardDismissBehavior, 307 | physics: physics, 308 | children: children, 309 | cacheExtent: cacheExtent, 310 | ); 311 | } 312 | } 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /lib/src/swipe_refresh_base.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/foundation.dart'; 18 | import 'package:flutter/material.dart'; 19 | import 'package:swipe_refresh/src/swipe_refresh_state.dart'; 20 | import 'package:swipe_refresh/src/widgets/scroll_behavior_in_web.dart'; 21 | 22 | /// Base refresh indicator widget. 23 | abstract class SwipeRefreshBase extends StatefulWidget { 24 | const SwipeRefreshBase({ 25 | required this.stateStream, 26 | required this.onRefresh, 27 | Key? key, 28 | this.initState, 29 | this.scrollController, 30 | this.childrenDelegate, 31 | this.children, 32 | this.padding, 33 | this.shrinkWrap = false, 34 | this.keyboardDismissBehavior, 35 | this.physics, 36 | }) : assert((children == null || childrenDelegate == null) && 37 | (children != null || childrenDelegate != null)), 38 | super(key: key); 39 | 40 | final List? children; 41 | final VoidCallback onRefresh; 42 | final SwipeRefreshState? initState; 43 | final Stream stateStream; 44 | final ScrollController? scrollController; 45 | final SliverChildDelegate? childrenDelegate; 46 | final EdgeInsets? padding; 47 | final bool shrinkWrap; 48 | final ScrollViewKeyboardDismissBehavior? keyboardDismissBehavior; 49 | final ScrollPhysics? physics; 50 | 51 | @override 52 | @protected 53 | // ignore: no_logic_in_create_state 54 | SwipeRefreshBaseState createState(); 55 | } 56 | 57 | abstract class SwipeRefreshBaseState 58 | extends State { 59 | @protected 60 | final GlobalKey refreshKey = GlobalKey(); 61 | 62 | @protected 63 | late final MaterialScrollBehavior? scrollBehavior; 64 | 65 | @protected 66 | Completer? completer; 67 | 68 | @visibleForTesting 69 | @protected 70 | SwipeRefreshState currentState = SwipeRefreshState.hidden; 71 | 72 | StreamSubscription? _stateSubscription; 73 | 74 | @override 75 | void initState() { 76 | super.initState(); 77 | 78 | if (widget.initState != null) { 79 | currentState = widget.initState!; 80 | } 81 | 82 | _stateSubscription = widget.stateStream.listen(_updateState); 83 | scrollBehavior = _getScrollBehavior(); 84 | } 85 | 86 | void _updateState(SwipeRefreshState newState) { 87 | if (currentState != newState) { 88 | setState( 89 | () { 90 | currentState = newState; 91 | 92 | onUpdateState(currentState); 93 | }, 94 | ); 95 | } 96 | } 97 | 98 | @protected 99 | Future _onRefresh() { 100 | _updateState(SwipeRefreshState.loading); 101 | widget.onRefresh(); 102 | completer = Completer(); 103 | return completer!.future; 104 | } 105 | 106 | MaterialScrollBehavior? _getScrollBehavior() { 107 | final behaviorInWeb = ScrollBehaviorInWeb(); 108 | 109 | switch (defaultTargetPlatform) { 110 | case TargetPlatform.android: 111 | case TargetPlatform.iOS: 112 | return null; 113 | case TargetPlatform.fuchsia: 114 | case TargetPlatform.linux: 115 | case TargetPlatform.macOS: 116 | case TargetPlatform.windows: 117 | return behaviorInWeb; 118 | } 119 | } 120 | 121 | @override 122 | void dispose() { 123 | _stateSubscription?.cancel(); 124 | super.dispose(); 125 | } 126 | 127 | @override 128 | Widget build(BuildContext context) { 129 | // ignore: avoid-returning-widgets 130 | return buildRefresher(refreshKey, widget.children ?? [], _onRefresh); 131 | } 132 | 133 | @protected 134 | Widget buildRefresher( 135 | Key key, 136 | List children, 137 | Future Function() onRefresh, 138 | ); 139 | 140 | @protected 141 | void onUpdateState(SwipeRefreshState state); 142 | } 143 | -------------------------------------------------------------------------------- /lib/src/swipe_refresh_state.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// Refresh indicator states. 16 | enum SwipeRefreshState { 17 | /// Indicator hidden. 18 | hidden, 19 | 20 | /// Indicator shown. 21 | loading, 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/swipe_refresh_style.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// Indicator style. 16 | enum SwipeRefreshStyle { 17 | /// Material Design. 18 | material, 19 | 20 | /// Cupertino. 21 | cupertino, 22 | 23 | /// Adaptive. 24 | adaptive, 25 | 26 | /// Builder. 27 | builder, 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/widgets/conditional_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Wrap the child with a wrapper if the condition is true. 4 | class ConditionalWrapper extends StatelessWidget { 5 | /// Create an instance [ConditionalWrapper]. 6 | const ConditionalWrapper({ 7 | required this.condition, 8 | required this.wrapper, 9 | required this.child, 10 | super.key, 11 | }); 12 | 13 | /// Condition to wrap the child. 14 | final bool condition; 15 | 16 | /// Wrapper for the child. 17 | final Widget Function(Widget child) wrapper; 18 | 19 | /// Child to be wrapped. 20 | final Widget child; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return condition ? wrapper(child) : child; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/widgets/scroll_behavior_in_web.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/gestures.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// For websites to work on the web and desktop. 5 | class ScrollBehaviorInWeb extends MaterialScrollBehavior { 6 | @override 7 | Set get dragDevices => { 8 | PointerDeviceKind.touch, 9 | PointerDeviceKind.mouse, 10 | PointerDeviceKind.trackpad, 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /lib/swipe_refresh.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | export 'package:swipe_refresh/src/cupertino_swipe_refresh.dart'; 16 | export 'package:swipe_refresh/src/material_swipe_refresh.dart'; 17 | export 'package:swipe_refresh/src/swipe_refresh.dart'; 18 | export 'package:swipe_refresh/src/swipe_refresh_state.dart'; 19 | export 'package:swipe_refresh/src/swipe_refresh_style.dart'; 20 | -------------------------------------------------------------------------------- /lib/utills/platform_wrapper.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:flutter/foundation.dart'; 16 | 17 | /// Wrapper for Platform io. 18 | class PlatformWrapper { 19 | bool get isCupertino => _cupertino.contains(defaultTargetPlatform); 20 | 21 | bool get isMaterial => _material.contains(defaultTargetPlatform); 22 | 23 | const PlatformWrapper(); 24 | } 25 | 26 | const _cupertino = [ 27 | TargetPlatform.iOS, 28 | TargetPlatform.macOS, 29 | ]; 30 | 31 | const _material = [ 32 | TargetPlatform.android, 33 | TargetPlatform.fuchsia, 34 | TargetPlatform.linux, 35 | TargetPlatform.windows, 36 | ]; 37 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "61.0.0" 12 | analyzer: 13 | dependency: transitive 14 | description: 15 | name: analyzer 16 | sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "5.13.0" 20 | analyzer_plugin: 21 | dependency: transitive 22 | description: 23 | name: analyzer_plugin 24 | sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "0.11.2" 28 | ansicolor: 29 | dependency: transitive 30 | description: 31 | name: ansicolor 32 | sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.0.1" 36 | args: 37 | dependency: transitive 38 | description: 39 | name: args 40 | sha256: "4276641ebd31b2fd6dbd922c665a4877482179fee8034cf7bdfb8bc70b7b67c8" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "2.1.1" 44 | async: 45 | dependency: transitive 46 | description: 47 | name: async 48 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "2.11.0" 52 | boolean_selector: 53 | dependency: transitive 54 | description: 55 | name: boolean_selector 56 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "2.1.1" 60 | characters: 61 | dependency: transitive 62 | description: 63 | name: characters 64 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.3.0" 68 | clock: 69 | dependency: transitive 70 | description: 71 | name: clock 72 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "1.1.1" 76 | collection: 77 | dependency: transitive 78 | description: 79 | name: collection 80 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.18.0" 84 | convert: 85 | dependency: transitive 86 | description: 87 | name: convert 88 | sha256: f08428ad63615f96a27e34221c65e1a451439b5f26030f78d790f461c686d65d 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "3.0.1" 92 | coverage: 93 | dependency: transitive 94 | description: 95 | name: coverage 96 | sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.7.2" 100 | crypto: 101 | dependency: transitive 102 | description: 103 | name: crypto 104 | sha256: cf75650c66c0316274e21d7c43d3dea246273af5955bd94e8184837cd577575c 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "3.0.1" 108 | csslib: 109 | dependency: transitive 110 | description: 111 | name: csslib 112 | sha256: f857285c8dc0b4f2f77b49a1c083ff8c75223a7549de20f3e607df58cf497a43 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "0.17.0" 116 | dart_code_metrics: 117 | dependency: transitive 118 | description: 119 | name: dart_code_metrics 120 | sha256: "3dede3f7abc077a4181ec7445448a289a9ce08e2981e6a4d49a3fb5099d47e1f" 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "5.7.6" 124 | dart_code_metrics_presets: 125 | dependency: transitive 126 | description: 127 | name: dart_code_metrics_presets 128 | sha256: b71eadf02a3787ebd5c887623f83f6fdc204d45c75a081bd636c4104b3fd8b73 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "1.8.0" 132 | dart_style: 133 | dependency: transitive 134 | description: 135 | name: dart_style 136 | sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" 137 | url: "https://pub.dev" 138 | source: hosted 139 | version: "2.3.2" 140 | fake_async: 141 | dependency: transitive 142 | description: 143 | name: fake_async 144 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 145 | url: "https://pub.dev" 146 | source: hosted 147 | version: "1.3.1" 148 | file: 149 | dependency: transitive 150 | description: 151 | name: file 152 | sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad 153 | url: "https://pub.dev" 154 | source: hosted 155 | version: "6.1.2" 156 | flutter: 157 | dependency: "direct main" 158 | description: flutter 159 | source: sdk 160 | version: "0.0.0" 161 | flutter_lints: 162 | dependency: transitive 163 | description: 164 | name: flutter_lints 165 | sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 166 | url: "https://pub.dev" 167 | source: hosted 168 | version: "2.0.3" 169 | flutter_test: 170 | dependency: "direct dev" 171 | description: flutter 172 | source: sdk 173 | version: "0.0.0" 174 | frontend_server_client: 175 | dependency: transitive 176 | description: 177 | name: frontend_server_client 178 | sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" 179 | url: "https://pub.dev" 180 | source: hosted 181 | version: "3.2.0" 182 | glob: 183 | dependency: transitive 184 | description: 185 | name: glob 186 | sha256: dda85ce2aefce16f7e75586acbcb1e8320bf176f69fd94082e31945d6de67f3e 187 | url: "https://pub.dev" 188 | source: hosted 189 | version: "2.0.1" 190 | html: 191 | dependency: transitive 192 | description: 193 | name: html 194 | sha256: bfef906cbd4e78ef49ae511d9074aebd1d2251482ef601a280973e8b58b51bbf 195 | url: "https://pub.dev" 196 | source: hosted 197 | version: "0.15.0" 198 | http: 199 | dependency: transitive 200 | description: 201 | name: http 202 | sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" 203 | url: "https://pub.dev" 204 | source: hosted 205 | version: "0.13.6" 206 | http_multi_server: 207 | dependency: transitive 208 | description: 209 | name: http_multi_server 210 | sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" 211 | url: "https://pub.dev" 212 | source: hosted 213 | version: "3.2.1" 214 | http_parser: 215 | dependency: transitive 216 | description: 217 | name: http_parser 218 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 219 | url: "https://pub.dev" 220 | source: hosted 221 | version: "4.0.2" 222 | io: 223 | dependency: transitive 224 | description: 225 | name: io 226 | sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" 227 | url: "https://pub.dev" 228 | source: hosted 229 | version: "1.0.4" 230 | js: 231 | dependency: transitive 232 | description: 233 | name: js 234 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 235 | url: "https://pub.dev" 236 | source: hosted 237 | version: "0.6.7" 238 | json_annotation: 239 | dependency: transitive 240 | description: 241 | name: json_annotation 242 | sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 243 | url: "https://pub.dev" 244 | source: hosted 245 | version: "4.8.1" 246 | leak_tracker: 247 | dependency: transitive 248 | description: 249 | name: leak_tracker 250 | sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" 251 | url: "https://pub.dev" 252 | source: hosted 253 | version: "10.0.0" 254 | leak_tracker_flutter_testing: 255 | dependency: transitive 256 | description: 257 | name: leak_tracker_flutter_testing 258 | sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 259 | url: "https://pub.dev" 260 | source: hosted 261 | version: "2.0.1" 262 | leak_tracker_testing: 263 | dependency: transitive 264 | description: 265 | name: leak_tracker_testing 266 | sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 267 | url: "https://pub.dev" 268 | source: hosted 269 | version: "2.0.1" 270 | lints: 271 | dependency: transitive 272 | description: 273 | name: lints 274 | sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" 275 | url: "https://pub.dev" 276 | source: hosted 277 | version: "2.1.1" 278 | logging: 279 | dependency: transitive 280 | description: 281 | name: logging 282 | sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" 283 | url: "https://pub.dev" 284 | source: hosted 285 | version: "1.2.0" 286 | matcher: 287 | dependency: transitive 288 | description: 289 | name: matcher 290 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 291 | url: "https://pub.dev" 292 | source: hosted 293 | version: "0.12.16+1" 294 | material_color_utilities: 295 | dependency: transitive 296 | description: 297 | name: material_color_utilities 298 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 299 | url: "https://pub.dev" 300 | source: hosted 301 | version: "0.8.0" 302 | meta: 303 | dependency: transitive 304 | description: 305 | name: meta 306 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 307 | url: "https://pub.dev" 308 | source: hosted 309 | version: "1.11.0" 310 | mime: 311 | dependency: transitive 312 | description: 313 | name: mime 314 | sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" 315 | url: "https://pub.dev" 316 | source: hosted 317 | version: "1.0.5" 318 | mocktail: 319 | dependency: "direct dev" 320 | description: 321 | name: mocktail 322 | sha256: dd85ca5229cf677079fd9ac740aebfc34d9287cdf294e6b2ba9fae25c39e4dc2 323 | url: "https://pub.dev" 324 | source: hosted 325 | version: "0.2.0" 326 | node_preamble: 327 | dependency: transitive 328 | description: 329 | name: node_preamble 330 | sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" 331 | url: "https://pub.dev" 332 | source: hosted 333 | version: "2.0.2" 334 | package_config: 335 | dependency: transitive 336 | description: 337 | name: package_config 338 | sha256: "20e7154d701fedaeb219dad732815ecb66677667871127998a9a6581c2aba4ba" 339 | url: "https://pub.dev" 340 | source: hosted 341 | version: "2.0.0" 342 | path: 343 | dependency: transitive 344 | description: 345 | name: path 346 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 347 | url: "https://pub.dev" 348 | source: hosted 349 | version: "1.9.0" 350 | pedantic: 351 | dependency: transitive 352 | description: 353 | name: pedantic 354 | sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" 355 | url: "https://pub.dev" 356 | source: hosted 357 | version: "1.11.1" 358 | petitparser: 359 | dependency: transitive 360 | description: 361 | name: petitparser 362 | sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 363 | url: "https://pub.dev" 364 | source: hosted 365 | version: "6.0.2" 366 | platform: 367 | dependency: transitive 368 | description: 369 | name: platform 370 | sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" 371 | url: "https://pub.dev" 372 | source: hosted 373 | version: "3.1.4" 374 | pool: 375 | dependency: transitive 376 | description: 377 | name: pool 378 | sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" 379 | url: "https://pub.dev" 380 | source: hosted 381 | version: "1.5.1" 382 | process: 383 | dependency: transitive 384 | description: 385 | name: process 386 | sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" 387 | url: "https://pub.dev" 388 | source: hosted 389 | version: "4.2.4" 390 | pub_semver: 391 | dependency: transitive 392 | description: 393 | name: pub_semver 394 | sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" 395 | url: "https://pub.dev" 396 | source: hosted 397 | version: "2.1.4" 398 | pub_updater: 399 | dependency: transitive 400 | description: 401 | name: pub_updater 402 | sha256: "05ae70703e06f7fdeb05f7f02dd680b8aad810e87c756a618f33e1794635115c" 403 | url: "https://pub.dev" 404 | source: hosted 405 | version: "0.3.0" 406 | shelf: 407 | dependency: transitive 408 | description: 409 | name: shelf 410 | sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 411 | url: "https://pub.dev" 412 | source: hosted 413 | version: "1.4.1" 414 | shelf_packages_handler: 415 | dependency: transitive 416 | description: 417 | name: shelf_packages_handler 418 | sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" 419 | url: "https://pub.dev" 420 | source: hosted 421 | version: "3.0.2" 422 | shelf_static: 423 | dependency: transitive 424 | description: 425 | name: shelf_static 426 | sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e 427 | url: "https://pub.dev" 428 | source: hosted 429 | version: "1.1.2" 430 | shelf_web_socket: 431 | dependency: transitive 432 | description: 433 | name: shelf_web_socket 434 | sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" 435 | url: "https://pub.dev" 436 | source: hosted 437 | version: "1.0.4" 438 | sky_engine: 439 | dependency: transitive 440 | description: flutter 441 | source: sdk 442 | version: "0.0.99" 443 | source_map_stack_trace: 444 | dependency: transitive 445 | description: 446 | name: source_map_stack_trace 447 | sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" 448 | url: "https://pub.dev" 449 | source: hosted 450 | version: "2.1.1" 451 | source_maps: 452 | dependency: transitive 453 | description: 454 | name: source_maps 455 | sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" 456 | url: "https://pub.dev" 457 | source: hosted 458 | version: "0.10.12" 459 | source_span: 460 | dependency: transitive 461 | description: 462 | name: source_span 463 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 464 | url: "https://pub.dev" 465 | source: hosted 466 | version: "1.10.0" 467 | stack_trace: 468 | dependency: transitive 469 | description: 470 | name: stack_trace 471 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 472 | url: "https://pub.dev" 473 | source: hosted 474 | version: "1.11.1" 475 | stream_channel: 476 | dependency: transitive 477 | description: 478 | name: stream_channel 479 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 480 | url: "https://pub.dev" 481 | source: hosted 482 | version: "2.1.2" 483 | string_scanner: 484 | dependency: transitive 485 | description: 486 | name: string_scanner 487 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 488 | url: "https://pub.dev" 489 | source: hosted 490 | version: "1.2.0" 491 | surf_lint_rules: 492 | dependency: "direct dev" 493 | description: 494 | name: surf_lint_rules 495 | sha256: "0465c70586a137db13a1e6afb1bd10b48a95c90fe29fdcee15a96c9f70fe2b19" 496 | url: "https://pub.dev" 497 | source: hosted 498 | version: "2.1.0" 499 | term_glyph: 500 | dependency: transitive 501 | description: 502 | name: term_glyph 503 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 504 | url: "https://pub.dev" 505 | source: hosted 506 | version: "1.2.1" 507 | test: 508 | dependency: transitive 509 | description: 510 | name: test 511 | sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f 512 | url: "https://pub.dev" 513 | source: hosted 514 | version: "1.24.9" 515 | test_api: 516 | dependency: transitive 517 | description: 518 | name: test_api 519 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 520 | url: "https://pub.dev" 521 | source: hosted 522 | version: "0.6.1" 523 | test_core: 524 | dependency: transitive 525 | description: 526 | name: test_core 527 | sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a 528 | url: "https://pub.dev" 529 | source: hosted 530 | version: "0.5.9" 531 | typed_data: 532 | dependency: transitive 533 | description: 534 | name: typed_data 535 | sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee" 536 | url: "https://pub.dev" 537 | source: hosted 538 | version: "1.3.0" 539 | uuid: 540 | dependency: transitive 541 | description: 542 | name: uuid 543 | sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" 544 | url: "https://pub.dev" 545 | source: hosted 546 | version: "3.0.7" 547 | vector_math: 548 | dependency: transitive 549 | description: 550 | name: vector_math 551 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 552 | url: "https://pub.dev" 553 | source: hosted 554 | version: "2.1.4" 555 | vm_service: 556 | dependency: transitive 557 | description: 558 | name: vm_service 559 | sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 560 | url: "https://pub.dev" 561 | source: hosted 562 | version: "13.0.0" 563 | watcher: 564 | dependency: transitive 565 | description: 566 | name: watcher 567 | sha256: "68173f2fa67d241323a4123be7ed4e43424c54befa5505d71c8ad4b7baf8f71d" 568 | url: "https://pub.dev" 569 | source: hosted 570 | version: "1.0.0" 571 | web: 572 | dependency: transitive 573 | description: 574 | name: web 575 | sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" 576 | url: "https://pub.dev" 577 | source: hosted 578 | version: "0.5.1" 579 | web_socket_channel: 580 | dependency: transitive 581 | description: 582 | name: web_socket_channel 583 | sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" 584 | url: "https://pub.dev" 585 | source: hosted 586 | version: "2.4.4" 587 | webkit_inspection_protocol: 588 | dependency: transitive 589 | description: 590 | name: webkit_inspection_protocol 591 | sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" 592 | url: "https://pub.dev" 593 | source: hosted 594 | version: "1.2.1" 595 | xml: 596 | dependency: transitive 597 | description: 598 | name: xml 599 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 600 | url: "https://pub.dev" 601 | source: hosted 602 | version: "6.5.0" 603 | yaml: 604 | dependency: transitive 605 | description: 606 | name: yaml 607 | sha256: "3cee79b1715110341012d27756d9bae38e650588acd38d3f3c610822e1337ace" 608 | url: "https://pub.dev" 609 | source: hosted 610 | version: "3.1.0" 611 | sdks: 612 | dart: ">=3.3.0 <4.0.0" 613 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: swipe_refresh 2 | version: 1.1.2 3 | description: Set of widgets provides make refresh by using pull down gesture. 4 | repository: "https://github.com/surfstudio/flutter-swipe-refresh" 5 | issue_tracker: "https://github.com/surfstudio/flutter-swipe-refresh/issues" 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | 11 | dev_dependencies: 12 | flutter_test: 13 | sdk: flutter 14 | mocktail: ^0.2.0 15 | surf_lint_rules: ^2.0.0 16 | 17 | environment: 18 | sdk: ">=3.0.0 <4.0.0" 19 | 20 | flutter: 21 | uses-material-design: true 22 | -------------------------------------------------------------------------------- /test/platform_wrapper_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:flutter_test/flutter_test.dart'; 16 | import 'package:swipe_refresh/utills/platform_wrapper.dart'; 17 | 18 | void main() { 19 | late PlatformWrapper platformWrapper; 20 | 21 | setUp(() { 22 | platformWrapper = const PlatformWrapper(); 23 | }); 24 | 25 | test( 26 | 'Method isAndroid should return true', 27 | () { 28 | final isAndroid = platformWrapper.isMaterial; 29 | 30 | /// Because the target flutter checks the test environment and by default outputs 31 | /// the platform android. 32 | /* 33 | assert(() { 34 | if (Platform.environment.containsKey('FLUTTER_TEST')) 35 | result = platform.TargetPlatform.android; 36 | return true; 37 | }()); 38 | */ 39 | expect(isAndroid, true); 40 | }, 41 | ); 42 | 43 | test( 44 | 'Method isIOS should return false', 45 | () { 46 | final isIOS = platformWrapper.isCupertino; 47 | 48 | expect(isIOS, false); 49 | }, 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /test/swipe_refresh_adaptive_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/material.dart'; 18 | import 'package:flutter_test/flutter_test.dart'; 19 | import 'package:mocktail/mocktail.dart'; 20 | import 'package:swipe_refresh/swipe_refresh.dart'; 21 | import 'package:swipe_refresh/utills/platform_wrapper.dart'; 22 | 23 | import 'test_utils.dart'; 24 | 25 | void main() { 26 | late StreamController controller; 27 | late Stream stream; 28 | late MockPlatformWrapper platformWrapper; 29 | final children = _listColors 30 | .map((e) => Container( 31 | color: e, 32 | height: 100, 33 | )) 34 | .toList(); 35 | 36 | setUp(() { 37 | controller = StreamController.broadcast(); 38 | stream = controller.stream; 39 | 40 | platformWrapper = MockPlatformWrapper(); 41 | }); 42 | 43 | tearDown(() async { 44 | await controller.close(); 45 | }); 46 | 47 | Future onRefresh() async { 48 | await Future.delayed(const Duration(seconds: 3)); 49 | 50 | controller.sink.add(SwipeRefreshState.hidden); 51 | } 52 | 53 | testWidgets( 54 | 'When call SwipeRefresh.adaptive on Android platform should build MaterialSwipeRefresh', 55 | (tester) async { 56 | when(() => platformWrapper.isMaterial).thenReturn(true); 57 | when(() => platformWrapper.isCupertino).thenReturn(false); 58 | 59 | final adaptiveSwipeRefresh = makeTestableWidget( 60 | SwipeRefresh.adaptive( 61 | stateStream: stream, 62 | onRefresh: () { 63 | onRefresh().ignore(); 64 | }, 65 | children: children, 66 | platform: platformWrapper, 67 | ), 68 | ); 69 | 70 | await tester.pumpWidget(adaptiveSwipeRefresh); 71 | 72 | expect(() => adaptiveSwipeRefresh, returnsNormally); 73 | expect(find.byType(MaterialSwipeRefresh), findsOneWidget); 74 | }, 75 | ); 76 | 77 | testWidgets( 78 | 'When call SwipeRefresh.adaptive on iOS platform should build CupertinoSwipeRefresh', 79 | (tester) async { 80 | when(() => platformWrapper.isMaterial).thenReturn(false); 81 | when(() => platformWrapper.isCupertino).thenReturn(true); 82 | 83 | final adaptiveSwipeRefresh = makeTestableWidget( 84 | SwipeRefresh.adaptive( 85 | stateStream: stream, 86 | onRefresh: () { 87 | onRefresh().ignore(); 88 | }, 89 | children: children, 90 | platform: platformWrapper, 91 | ), 92 | ); 93 | 94 | await tester.pumpWidget(adaptiveSwipeRefresh); 95 | 96 | expect(() => adaptiveSwipeRefresh, returnsNormally); 97 | expect(find.byType(CupertinoSwipeRefresh), findsOneWidget); 98 | }, 99 | ); 100 | } 101 | 102 | class MockPlatformWrapper extends Mock implements PlatformWrapper {} 103 | 104 | const _listColors = [ 105 | Colors.blue, 106 | Colors.green, 107 | Colors.red, 108 | Colors.amber, 109 | ]; 110 | -------------------------------------------------------------------------------- /test/swipe_refresh_builder_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/material.dart'; 18 | import 'package:flutter_test/flutter_test.dart'; 19 | import 'package:mocktail/mocktail.dart'; 20 | import 'package:swipe_refresh/swipe_refresh.dart'; 21 | import 'package:swipe_refresh/utills/platform_wrapper.dart'; 22 | 23 | import 'test_utils.dart'; 24 | 25 | void main() { 26 | late StreamController controller; 27 | late Stream stream; 28 | 29 | late MockPlatformWrapper platformWrapper; 30 | 31 | setUp(() { 32 | controller = StreamController.broadcast(); 33 | stream = controller.stream; 34 | 35 | platformWrapper = MockPlatformWrapper(); 36 | }); 37 | 38 | tearDown(() async { 39 | await controller.close(); 40 | }); 41 | 42 | Future onRefresh() async { 43 | await Future.delayed(const Duration(seconds: 3)); 44 | 45 | controller.sink.add(SwipeRefreshState.hidden); 46 | } 47 | 48 | final listColors = [ 49 | Colors.blue, 50 | Colors.green, 51 | Colors.red, 52 | Colors.amber, 53 | ]; 54 | 55 | testWidgets( 56 | 'SwipeRefresh.builder with itemBuilder as argument builds normally(iOS platform as example)', 57 | (tester) async { 58 | when(() => platformWrapper.isMaterial).thenReturn(false); 59 | when(() => platformWrapper.isCupertino).thenReturn(true); 60 | 61 | final testWidget = makeTestableWidget( 62 | SwipeRefresh.builder( 63 | stateStream: stream, 64 | onRefresh: () { 65 | onRefresh().ignore(); 66 | }, 67 | itemCount: listColors.length, 68 | itemBuilder: (_, index) => Container( 69 | color: listColors[index], 70 | height: 100, 71 | ), 72 | platform: platformWrapper, 73 | ), 74 | ); 75 | 76 | await tester.pumpWidget(testWidget); 77 | 78 | expect(() => testWidget, returnsNormally); 79 | expect(find.byType(Container), findsNWidgets(4)); 80 | }, 81 | ); 82 | } 83 | 84 | class MockPlatformWrapper extends Mock implements PlatformWrapper {} 85 | -------------------------------------------------------------------------------- /test/swipe_refresh_cupertino_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/material.dart'; 18 | import 'package:flutter_test/flutter_test.dart'; 19 | import 'package:mocktail/mocktail.dart'; 20 | import 'package:swipe_refresh/src/swipe_refresh_base.dart'; 21 | import 'package:swipe_refresh/swipe_refresh.dart'; 22 | 23 | import 'test_utils.dart'; 24 | 25 | void main() { 26 | late StreamController streamController; 27 | late Stream stream; 28 | late MockOnRefreshFunction onRefreshFunction; 29 | late ScrollPhysics scrollPhysics; 30 | final children = _listColors 31 | .map((e) => Container( 32 | color: e, 33 | height: 100, 34 | )) 35 | .toList(); 36 | 37 | setUp(() { 38 | streamController = StreamController.broadcast(); 39 | stream = streamController.stream; 40 | 41 | onRefreshFunction = MockOnRefreshFunction(); 42 | when(() => onRefreshFunction.call()).thenAnswer( 43 | (invocation) { 44 | return streamController.sink.add(SwipeRefreshState.hidden); 45 | }, 46 | ); 47 | 48 | scrollPhysics = const ScrollPhysics(); 49 | }); 50 | 51 | tearDown( 52 | () async { 53 | await streamController.close(); 54 | }, 55 | ); 56 | 57 | testWidgets( 58 | 'When trying to return a CupertinoSwipeRefresh with no children or ' 59 | 'childrenDelegate passed, must be an assertion error', 60 | (tester) async { 61 | expect( 62 | () { 63 | return makeTestableWidget( 64 | CupertinoSwipeRefresh( 65 | stateStream: stream, 66 | onRefresh: onRefreshFunction, 67 | ), 68 | ); 69 | }, 70 | throwsAssertionError, 71 | ); 72 | }, 73 | ); 74 | 75 | testWidgets( 76 | 'SwipeRefresh.cupertino widget with children as argument does not break', 77 | (tester) async { 78 | final cupertinoSwipeRefresh = makeTestableWidget( 79 | SwipeRefresh.cupertino( 80 | stateStream: stream, 81 | onRefresh: onRefreshFunction, 82 | children: children, 83 | ), 84 | ); 85 | 86 | await tester.pumpWidget(cupertinoSwipeRefresh); 87 | 88 | expect(() => cupertinoSwipeRefresh, returnsNormally); 89 | expect(find.byType(CupertinoSwipeRefresh), findsOneWidget); 90 | expect(find.byType(Container), findsNWidgets(4)); 91 | }, 92 | ); 93 | 94 | testWidgets( 95 | 'When drag down enough, the refresh should start and should called ' 96 | 'onRefreshFunction', 97 | (tester) async { 98 | final cupertinoSwipeRefresh = makeTestableWidget( 99 | SwipeRefresh.cupertino( 100 | stateStream: stream, 101 | onRefresh: onRefreshFunction, 102 | children: children, 103 | ), 104 | ); 105 | 106 | await tester.pumpWidget(cupertinoSwipeRefresh); 107 | await tester.drag( 108 | find.byType(SwipeRefresh), 109 | const Offset(0, 300), 110 | touchSlopY: 0, 111 | ); 112 | await tester.pump(); 113 | 114 | verify(() => onRefreshFunction()).called(1); 115 | }, 116 | ); 117 | 118 | testWidgets( 119 | 'When drag down enough, the refresh should start and end after 3 seconds', 120 | (tester) async { 121 | const key = Key('Test key'); 122 | final findKey = find.byKey(key); 123 | 124 | final cupertinoSwipeRefresh = makeTestableWidget( 125 | SwipeRefresh.cupertino( 126 | stateStream: stream, 127 | onRefresh: onRefreshFunction, 128 | indicatorBuilder: ( 129 | context, 130 | refreshState, 131 | pulledExtent, 132 | refreshTriggerPullDistance, 133 | refreshIndicatorExtent, 134 | ) { 135 | return Container( 136 | key: key, 137 | ); 138 | }, 139 | children: children, 140 | ), 141 | ); 142 | 143 | await tester.pumpWidget(cupertinoSwipeRefresh); 144 | 145 | await tester.drag( 146 | find.byType(SwipeRefresh), 147 | const Offset(0, 300), 148 | touchSlopY: 0, 149 | ); 150 | 151 | await tester.pump(); 152 | 153 | expect(findKey, findsOneWidget); 154 | 155 | await tester.pump(const Duration(seconds: 3)); 156 | await tester.pump(); 157 | 158 | expect(findKey, findsNothing); 159 | }, 160 | ); 161 | 162 | testWidgets( 163 | 'When drag down is not enough to trigger an update the update should not be', 164 | (tester) async { 165 | final events = []; 166 | 167 | stream.listen(events.add); 168 | 169 | final cupertinoSwipeRefresh = makeTestableWidget( 170 | SwipeRefresh.cupertino( 171 | stateStream: stream, 172 | onRefresh: onRefreshFunction, 173 | children: children, 174 | ), 175 | ); 176 | 177 | await tester.pumpWidget(cupertinoSwipeRefresh); 178 | await tester.drag(find.byType(SwipeRefresh), const Offset(0.0, 50.0)); 179 | await tester.pump(); 180 | 181 | verifyNever(() => onRefreshFunction()); 182 | }, 183 | ); 184 | 185 | testWidgets( 186 | 'If initState: SwipeRefreshState.loading passed to the SwipeRefresh.cupertino, ' 187 | 'the currentState of the SwipeRefreshBase should be SwipeRefreshState.loading', 188 | (tester) async { 189 | final cupertinoWidget = SwipeRefresh.cupertino( 190 | stateStream: stream, 191 | onRefresh: onRefreshFunction, 192 | children: children, 193 | initState: SwipeRefreshState.loading, 194 | ); 195 | 196 | final cupertinoSwipeRefresh = makeTestableWidget(cupertinoWidget); 197 | 198 | await tester.pumpWidget(cupertinoSwipeRefresh); 199 | 200 | final SwipeRefreshBaseState state = tester.state( 201 | find.byType(CupertinoSwipeRefresh), 202 | ) as SwipeRefreshBaseState; 203 | 204 | expect(state.currentState, cupertinoWidget.initState); 205 | }, 206 | ); 207 | 208 | testWidgets( 209 | 'if pass the physics to the SwipeRefresh.cupertino, then SwipeRefreshBase ' 210 | 'physics should be the same', 211 | (tester) async { 212 | final events = []; 213 | 214 | stream.listen(events.add); 215 | 216 | final cupertinoWidget = SwipeRefresh.cupertino( 217 | stateStream: stream, 218 | onRefresh: onRefreshFunction, 219 | children: children, 220 | initState: SwipeRefreshState.loading, 221 | physics: scrollPhysics, 222 | ); 223 | 224 | final cupertinoSwipeRefresh = makeTestableWidget(cupertinoWidget); 225 | 226 | await tester.pumpWidget(cupertinoSwipeRefresh); 227 | 228 | final baseWidget = tester.widget( 229 | find.byType(SwipeRefresh), 230 | ) as SwipeRefresh; 231 | 232 | expect(baseWidget.physics, scrollPhysics); 233 | }, 234 | ); 235 | 236 | testWidgets( 237 | 'If padding passed to the SwipeRefresh.cupertino, ' 238 | 'SliverList should be wrapped in SliverPadding', 239 | (tester) async { 240 | final events = []; 241 | 242 | stream.listen(events.add); 243 | 244 | final cupertinoWidgetWithoutPadding = makeTestableWidget( 245 | SwipeRefresh.cupertino( 246 | stateStream: stream, 247 | onRefresh: onRefreshFunction, 248 | children: children, 249 | ), 250 | ); 251 | 252 | final cupertinoWidgetWithPadding = makeTestableWidget( 253 | SwipeRefresh.cupertino( 254 | stateStream: stream, 255 | onRefresh: onRefreshFunction, 256 | children: children, 257 | padding: const EdgeInsets.only(top: 16.0), 258 | ), 259 | ); 260 | 261 | final findSliverList = find.byType(SliverList); 262 | final findSliverPadding = find.byType(SliverPadding); 263 | 264 | await tester.pumpWidget(cupertinoWidgetWithoutPadding); 265 | 266 | expect(findSliverList, findsOneWidget); 267 | // Must find one widget create by SliverSafeArea. 268 | expect(findSliverPadding, findsOneWidget); 269 | 270 | await tester.pumpWidget(cupertinoWidgetWithPadding); 271 | 272 | expect(findSliverList, findsOneWidget); 273 | // Must find two widgets(create by SliverSafeArea and create by SwipeRefresh.cupertino). 274 | expect(findSliverPadding, findsNWidgets(2)); 275 | }, 276 | ); 277 | } 278 | 279 | class MockOnRefreshFunction extends Mock { 280 | void call(); 281 | } 282 | 283 | const _listColors = [ 284 | Colors.blue, 285 | Colors.green, 286 | Colors.red, 287 | Colors.amber, 288 | ]; 289 | -------------------------------------------------------------------------------- /test/swipe_refresh_material_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'dart:async'; 16 | 17 | import 'package:flutter/material.dart'; 18 | import 'package:flutter_test/flutter_test.dart'; 19 | import 'package:mocktail/mocktail.dart'; 20 | import 'package:swipe_refresh/src/swipe_refresh_base.dart'; 21 | import 'package:swipe_refresh/swipe_refresh.dart'; 22 | 23 | import 'test_utils.dart'; 24 | 25 | void main() { 26 | late StreamController controller; 27 | late Stream stream; 28 | late MockOnRefreshFunction onRefreshFunction; 29 | late TestSliverChildListDelegate sliverChildDelegate; 30 | final children = _listColors 31 | .map((e) => Container( 32 | color: e, 33 | height: 100, 34 | )) 35 | .toList(); 36 | 37 | setUp(() { 38 | controller = StreamController.broadcast(); 39 | stream = controller.stream; 40 | sliverChildDelegate = TestSliverChildListDelegate([const Text('Test')]); 41 | 42 | onRefreshFunction = MockOnRefreshFunction(); 43 | when(() => onRefreshFunction.call()).thenAnswer( 44 | (invocation) { 45 | return controller.sink.add(SwipeRefreshState.hidden); 46 | }, 47 | ); 48 | }); 49 | 50 | tearDown(() async { 51 | await controller.close(); 52 | }); 53 | 54 | testWidgets( 55 | 'When trying create MaterialSwipeRefresh without children or ' 56 | 'childrenDelegate should be assertion error', 57 | (tester) async { 58 | expect( 59 | () { 60 | return makeTestableWidget( 61 | MaterialSwipeRefresh( 62 | stateStream: stream, 63 | onRefresh: onRefreshFunction, 64 | ), 65 | ); 66 | }, 67 | throwsAssertionError, 68 | ); 69 | }, 70 | ); 71 | 72 | testWidgets( 73 | 'SwipeRefresh.material widget with children as argument does not break', 74 | (tester) async { 75 | final materialSwipeRefresh = makeTestableWidget( 76 | SwipeRefresh.material( 77 | stateStream: stream, 78 | onRefresh: onRefreshFunction, 79 | children: children, 80 | ), 81 | ); 82 | 83 | await tester.pumpWidget(materialSwipeRefresh); 84 | 85 | expect(() => materialSwipeRefresh, returnsNormally); 86 | 87 | expect(find.byType(Container), findsNWidgets(4)); 88 | 89 | expect(find.byType(MaterialSwipeRefresh), findsOneWidget); 90 | }, 91 | ); 92 | 93 | testWidgets( 94 | 'When drag down enough, the refresh should start and should called ' 95 | 'onRefreshFunction', 96 | (tester) async { 97 | final materialSwipeRefresh = makeTestableWidget( 98 | SwipeRefresh.material( 99 | stateStream: stream, 100 | onRefresh: onRefreshFunction, 101 | children: children, 102 | ), 103 | ); 104 | 105 | await tester.pumpWidget(materialSwipeRefresh); 106 | await tester.drag( 107 | find.byType(SwipeRefresh), 108 | const Offset(0, 300), 109 | touchSlopY: 0, 110 | ); 111 | await tester.pump(); 112 | await tester.pump(const Duration(seconds: 3)); 113 | 114 | verify(() => onRefreshFunction()).called(1); 115 | }, 116 | ); 117 | 118 | testWidgets( 119 | 'When drag down enough, the refresh should start and end after 3 seconds', 120 | (tester) async { 121 | final materialSwipeRefresh = makeTestableWidget( 122 | SwipeRefresh.material( 123 | stateStream: stream, 124 | onRefresh: onRefreshFunction, 125 | children: children, 126 | ), 127 | ); 128 | 129 | final findSwipeRefresh = find.byType(SwipeRefresh); 130 | final findRefreshProgressIndicator = 131 | find.byType(RefreshProgressIndicator); 132 | 133 | await tester.pumpWidget(materialSwipeRefresh); 134 | await tester.drag( 135 | findSwipeRefresh, 136 | const Offset(0, 300), 137 | touchSlopY: 0, 138 | ); 139 | await tester.pump(); 140 | 141 | expect(findRefreshProgressIndicator, findsOneWidget); 142 | 143 | await tester.pump(); 144 | await tester.pump(const Duration(seconds: 1)); 145 | await tester.pump(const Duration(seconds: 2)); 146 | 147 | expect(findRefreshProgressIndicator, findsNothing); 148 | }, 149 | ); 150 | 151 | testWidgets( 152 | 'When drag down is not enough to trigger an update the update should not be', 153 | (tester) async { 154 | final materialSwipeRefresh = makeTestableWidget( 155 | SwipeRefresh.material( 156 | stateStream: stream, 157 | onRefresh: onRefreshFunction, 158 | children: children, 159 | ), 160 | ); 161 | await tester.pumpWidget(materialSwipeRefresh); 162 | await tester.drag( 163 | find.byType(SwipeRefresh), 164 | const Offset(0, 50), 165 | touchSlopY: 0, 166 | ); 167 | await tester.pump(); 168 | 169 | verifyNever(() => onRefreshFunction()); 170 | }, 171 | ); 172 | 173 | testWidgets( 174 | 'If initState: SwipeRefreshState.loading passed to the SwipeRefresh.material, ' 175 | 'currentState should be SwipeRefreshState.loading', 176 | (tester) async { 177 | final materialWidget = SwipeRefresh.material( 178 | stateStream: stream, 179 | onRefresh: onRefreshFunction, 180 | children: children, 181 | initState: SwipeRefreshState.loading, 182 | ); 183 | final materialSwipeRefresh = makeTestableWidget(materialWidget); 184 | await tester.pumpWidget(materialSwipeRefresh); 185 | final SwipeRefreshBaseState state = tester.state( 186 | find.byType(MaterialSwipeRefresh), 187 | ) as SwipeRefreshBaseState; 188 | 189 | expect(state.currentState, materialWidget.initState); 190 | }, 191 | ); 192 | 193 | testWidgets( 194 | 'SwipeRefresh.material widget with childrenDelegate as argument does not break', 195 | (tester) async { 196 | final scrollController = ScrollController(); 197 | 198 | final materialWidget = MaterialSwipeRefresh( 199 | stateStream: stream, 200 | onRefresh: onRefreshFunction, 201 | childrenDelegate: sliverChildDelegate, 202 | scrollController: scrollController, 203 | ); 204 | 205 | final materialSwipeRefresh = makeTestableWidget(materialWidget); 206 | await tester.pumpWidget(materialSwipeRefresh); 207 | 208 | expect( 209 | find.text('Test'), 210 | findsOneWidget, 211 | ); 212 | }, 213 | ); 214 | } 215 | 216 | class MockOnRefreshFunction extends Mock { 217 | void call(); 218 | } 219 | 220 | class TestSliverChildListDelegate extends SliverChildListDelegate { 221 | TestSliverChildListDelegate(List children) : super(children); 222 | } 223 | 224 | const _listColors = [ 225 | Colors.blue, 226 | Colors.green, 227 | Colors.red, 228 | Colors.amber, 229 | ]; 230 | -------------------------------------------------------------------------------- /test/test_utils.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019-present, SurfStudio LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import 'package:flutter/material.dart'; 16 | 17 | // ignore: avoid-returning-widgets 18 | Widget makeTestableWidget(Widget widget) => MaterialApp(home: widget); 19 | --------------------------------------------------------------------------------