├── .github ├── FUNDING.yml └── workflows │ ├── configs │ └── configuration.json │ └── main.yaml ├── .gitignore ├── .metadata ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── flutter_sharez │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ └── splash.png │ │ │ ├── drawable-mdpi │ │ │ └── splash.png │ │ │ ├── drawable-v21 │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── drawable-xhdpi │ │ │ └── splash.png │ │ │ ├── drawable-xxhdpi │ │ │ └── splash.png │ │ │ ├── drawable-xxxhdpi │ │ │ └── splash.png │ │ │ ├── drawable │ │ │ ├── background.png │ │ │ └── launch_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_rounded.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_background.png │ │ │ ├── ic_launcher_foreground.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-night-v31 │ │ │ └── styles.xml │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ ├── values-v31 │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── anim │ ├── files.json │ ├── scanning.json │ └── starting_rocket.json └── images │ └── logo │ ├── es.json │ ├── ic_launcher.png │ ├── ic_launcher_adaptive_back.png │ ├── ic_launcher_adaptive_fore.png │ ├── icon.svg │ ├── logo_white_bg.png │ ├── logo_white_fg.png │ └── or.json ├── build.yaml ├── coverage └── lcov.info ├── devtools_options.yaml ├── flutter_native_splash.yaml ├── icons_launcher.yaml ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h └── RunnerTests │ └── RunnerTests.swift ├── lib ├── app │ ├── app.dart │ └── view │ │ └── app.dart ├── bootstrap.dart ├── const │ ├── app_urls.dart │ └── resource.dart ├── core │ ├── local_storage │ │ ├── app_storage.dart │ │ └── app_storage_pod.dart │ ├── router │ │ ├── auto_route_observer.dart │ │ ├── router.dart │ │ ├── router.gr.dart │ │ └── router_pod.dart │ └── theme │ │ ├── app_theme.dart │ │ └── theme_controller.dart ├── data │ ├── model │ │ ├── check_server_model.dart │ │ ├── file_model.dart │ │ ├── file_paths_model.dart │ │ ├── file_select_model.dart │ │ ├── range_header.dart │ │ ├── receiver_model.dart │ │ ├── receiver_model.mapper.dart │ │ ├── sender_model.dart │ │ ├── server_info.dart │ │ └── update_model.dart │ └── service │ │ ├── receiver │ │ ├── receiver_service.dart │ │ └── receiver_service_pod.dart │ │ └── sender │ │ ├── sender_service.dart │ │ └── sender_service_pod.dart ├── features │ ├── confirm_connection │ │ └── view │ │ │ └── confirm_connection_page.dart │ ├── counter │ │ ├── controller │ │ │ ├── counter_state_pod.dart │ │ │ └── notifier │ │ │ │ └── counter_notifier.dart │ │ ├── counter.dart │ │ └── view │ │ │ └── counter_page.dart │ ├── device_share │ │ ├── controller │ │ │ └── files_list_pods.dart │ │ └── view │ │ │ ├── device_share_page.dart │ │ │ └── tabs │ │ │ ├── device_info_tab_page.dart │ │ │ └── sender_files_tab_page.dart │ ├── downloads │ │ └── view │ │ │ └── downloads_page.dart │ ├── file_download_btn │ │ ├── controller │ │ │ ├── file_download_pod.dart │ │ │ └── notifier │ │ │ │ └── file_download_notifier.dart │ │ ├── state │ │ │ ├── file_download_state.dart │ │ │ └── file_download_state.mapper.dart │ │ └── view │ │ │ └── file_download_btn.dart │ ├── file_selector │ │ ├── controller │ │ │ ├── notifier │ │ │ │ └── selected_files_notifier.dart │ │ │ └── selected_files_list_pod.dart │ │ ├── state │ │ │ └── select_file_state.dart │ │ └── view │ │ │ ├── file_list_view.dart │ │ │ └── file_selector_page.dart │ ├── help_dialog │ │ └── view │ │ │ └── help_dialog_page.dart │ ├── home │ │ └── view │ │ │ └── home_page.dart │ ├── manual_connect │ │ └── view │ │ │ └── manual_connect_page.dart │ ├── qr_scan │ │ └── qr_scan_page.dart │ ├── receive │ │ ├── controller │ │ │ ├── connect_pod.dart │ │ │ ├── notifier │ │ │ │ └── connect_btn_notifier.dart │ │ │ └── receive_pods.dart │ │ ├── state │ │ │ ├── connect_btn_state_pod.dart │ │ │ └── receive_scan_start.dart │ │ └── view │ │ │ ├── receive_page.dart │ │ │ ├── receive_state_page.dart │ │ │ └── widget │ │ │ └── connect_btn.dart │ ├── send │ │ ├── controller │ │ │ ├── notifier │ │ │ │ └── send_state_notifier.dart │ │ │ └── send_notifier_pod.dart │ │ ├── state │ │ │ └── send_state.dart │ │ └── view │ │ │ ├── send_page.dart │ │ │ ├── send_state_page.dart │ │ │ ├── ui_state │ │ │ ├── started_server_view.dart │ │ │ └── starting_server_view.dart │ │ │ └── widgets │ │ │ ├── action_dialog_page.dart │ │ │ ├── files_bottomsheet.dart │ │ │ ├── send_actions.dart │ │ │ ├── server_info_box.dart │ │ │ └── share_on_web.dart │ ├── settings │ │ ├── controller │ │ │ └── current_version_pod.dart │ │ └── view │ │ │ ├── settings_page.dart │ │ │ └── widget │ │ │ └── about_app_tile.dart │ ├── splash │ │ ├── controller │ │ │ ├── box_encryption_key_pod.dart │ │ │ └── future_initializer.dart │ │ └── view │ │ │ └── splash_view.dart │ ├── theme_segmented_btn │ │ ├── controller │ │ │ └── selection_theme_pod.dart │ │ └── view │ │ │ └── theme_segmented_btn.dart │ └── update_app_version │ │ ├── controller │ │ ├── check_update_available.dart │ │ ├── check_update_version.dart │ │ └── get_changelog_pod.dart │ │ └── view │ │ ├── changelog_page.dart │ │ ├── update_app_version_icon.dart │ │ └── widgets │ │ └── animated_sync.dart ├── i18n │ ├── en.i18n.json │ ├── es.i18n.json │ ├── or.i18n.json │ ├── strings.g.dart │ ├── strings_en.g.dart │ ├── strings_es.g.dart │ └── strings_or.g.dart ├── init.dart ├── main.dart ├── main_development.dart ├── main_production.dart ├── main_staging.dart ├── shared │ ├── api_client │ │ └── dio │ │ │ ├── bad_certificate_fixer.dart │ │ │ ├── default_api_error_handler.dart │ │ │ ├── default_api_interceptor.dart │ │ │ ├── default_time_response_interceptor.dart │ │ │ ├── dio_client_provider.dart │ │ │ └── form_data_interceptor.dart │ ├── exception │ │ └── base_exception.dart │ ├── extension │ │ └── response_success_error_handler.dart │ ├── helper │ │ ├── file_list_html_render.dart │ │ ├── global_helper.dart │ │ ├── network_helper.dart │ │ ├── range_downloader.dart │ │ └── version.dart │ ├── pods │ │ ├── internet_checker_pod.dart │ │ └── locale_pod.dart │ ├── riverpod_ext │ │ ├── asynvalue_easy_when.dart │ │ ├── cache_extensions.dart │ │ ├── cancel_extensions.dart │ │ ├── riverpod_extensions.dart │ │ └── riverpod_observer.dart │ └── widget │ │ ├── app_locale_popup.dart │ │ ├── app_logo.dart │ │ ├── custom_app_bar.dart │ │ ├── no_internet_widget.dart │ │ ├── os_logo.dart │ │ └── responsive_wrapper.dart ├── splasher.dart ├── translation_override_map.dart └── translation_pod.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements └── RunnerTests │ └── RunnerTests.swift ├── pubspec.lock ├── pubspec.yaml ├── riverpod_simple_architecture.md ├── screenshot ├── 1.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── test ├── app │ └── view │ │ └── app_test.dart ├── core │ ├── storage │ │ └── app_storage_test.dart │ └── theme │ │ └── theme_controller_pod_test.dart ├── features │ ├── counter │ │ ├── pod │ │ │ └── counter_pod_test.dart │ │ └── view │ │ │ └── counter_page_test.dart │ └── theme_segment_btn │ │ └── view │ │ └── theme_segment_btn_test.dart ├── helpers │ ├── helpers.dart │ └── pump_app.dart ├── init_test.dart ├── shared │ ├── api_client │ │ └── dio │ │ │ └── dio_client_provider_test.dart │ ├── exception │ │ └── exception_test.dart │ ├── pods │ │ ├── internet_checker_pod_test.dart │ │ └── locale_pod_test.dart │ ├── riverpod_ext │ │ ├── asynvalue_easywhen_test.dart │ │ └── cache_extension_test.dart │ └── widgets │ │ ├── app_locale_popup_test.dart │ │ └── no_interenet_widget_test.dart └── widget_test.dart └── web ├── favicon.png ├── icons ├── Icon-192.png ├── Icon-512.png ├── Icon-maskable-192.png └── Icon-maskable-512.png ├── index.html ├── manifest.json └── splash └── img ├── dark-1x.png ├── dark-2x.png ├── dark-3x.png ├── dark-4x.png ├── light-1x.png ├── light-2x.png ├── light-3x.png ├── light-4x.png └── light-background.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: Shreemanarjun 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /.github/workflows/configs/configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "title": "## 🚀 Features", 5 | "labels": ["feat"] 6 | }, 7 | { 8 | "title": "## 🐛 Fixes", 9 | "labels": ["fix"] 10 | }, 11 | { 12 | "title": "## 🧪 Tests", 13 | "labels": ["test"] 14 | }, 15 | { 16 | "title": "## 🧪 Tests and some 🪄 Magic", 17 | "labels": ["test", "magic"], 18 | "exclude_labels": ["no-magic"], 19 | "exhaustive": true, 20 | "empty_content": "- no matching PRs" 21 | }, 22 | { 23 | "title": "## 📦 Uncategorized", 24 | "labels": [] 25 | } 26 | ], 27 | "ignore_labels": [ 28 | "ignore" 29 | ], 30 | "sort": { 31 | "order": "ASC", 32 | "on_property": "mergedAt" 33 | }, 34 | "template": "${{CHANGELOG}}\n\n
\nUncategorized\n\n${{UNCATEGORIZED}}\n
", 35 | "pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}", 36 | "empty_template": "- no changes", 37 | "label_extractor": [ 38 | { 39 | "pattern": "(.) (.+)", 40 | "target": "$1", 41 | "flags": "gu" 42 | }, 43 | { 44 | "pattern": "\\[Issue\\]", 45 | "on_property": "title", 46 | "method": "match" 47 | } 48 | ], 49 | "duplicate_filter": { 50 | "pattern": "\\[ABC-....\\]", 51 | "on_property": "title", 52 | "method": "match" 53 | }, 54 | "transformers": [ 55 | { 56 | "pattern": "[\\-\\*] (\\[(...|TEST|CI|SKIP)\\])( )?(.+?)\n(.+?[\\-\\*] )(.+)", 57 | "target": "- $4\n - $6" 58 | } 59 | ], 60 | "max_tags_to_fetch": 200, 61 | "max_pull_requests": 200, 62 | "max_back_track_time_days": 365, 63 | "exclude_merge_branches": [ 64 | "Owner/qa" 65 | ], 66 | "tag_resolver": { 67 | "method": "semver", 68 | "filter": { 69 | "pattern": "api-(.+)", 70 | "flags": "gu" 71 | } 72 | }, 73 | "base_branches": [ 74 | "main" 75 | ] 76 | } -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: Flutter Workflow 2 | 3 | on: 4 | #push: 5 | pull_request: 6 | # Sequence of patterns matched against refs/heads 7 | branches: 8 | - main 9 | - master 10 | permissions: read-all 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v3 19 | - uses: actions/setup-java@v3 20 | with: 21 | distribution: 'zulu' # See 'Supported distributions' for available options 22 | java-version: '11' 23 | - name: Install Flutter 24 | uses: subosito/flutter-action@v2 25 | with: 26 | channel: 'stable' 27 | cache: true 28 | # - name: Install dependencies 29 | # run: flutter pub get 30 | - run: flutter --version 31 | 32 | 33 | - name: Run unit tests 34 | run: flutter test --coverage 35 | 36 | # - name: Run integration tests 37 | # uses: reactivecircus/android-emulator-runner@v1 38 | # with: 39 | # api-level: 29 40 | # script: flutter drive --driver=test_driver/main_test.dart --target integration_test/app_test.dart 41 | - name: create Fat APK 42 | run: flutter build apk --release 43 | 44 | - name: create Split APK 45 | run: flutter build apk --split-per-abi 46 | 47 | - name: Upload Fat APK 48 | uses: actions/upload-artifact@v3 49 | with: 50 | name: release-fat-apk 51 | path: build/app/outputs/apk/release/app-release.apk 52 | 53 | - name: Upload Split APK 54 | uses: actions/upload-artifact@v3 55 | with: 56 | name: release-split-apk 57 | path: build/app/outputs/flutter-apk/*.apk 58 | 59 | - id: read-version 60 | uses: NiklasLehnfeld/flutter-version-number-action@main 61 | with: 62 | file-path: pubspec.yaml 63 | - name: Push to Releases 64 | uses: ncipollo/release-action@v1 65 | with: 66 | artifacts: "build/app/outputs/apk/release/*.apk, build/app/outputs/flutter-apk/*.apk" 67 | tag: v${{ steps.read-version.outputs.version-number }} 68 | token: ${{ secrets.TOKEN }} 69 | generateReleaseNotes: true 70 | - name: Checkout 71 | uses: actions/checkout@v2 72 | with: 73 | fetch-depth: 0 74 | - name: "Build Changelog" 75 | uses: mikepenz/release-changelog-builder-action@v3 76 | with: 77 | configuration: ".github/workflows/configs/configuration.json" 78 | ignorePreReleases: "false" 79 | commitMode: "true" 80 | env: 81 | GITHUB_TOKEN: ${{ secrets.TOKEN }} 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | **/ios/Flutter/.last_build_id 29 | .dart_tool/ 30 | .flutter-plugins 31 | .flutter-plugins-dependencies 32 | .packages 33 | .pub-cache/ 34 | .pub/ 35 | /build/ 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.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: "ead455963c12b453cdb2358cad34969c76daf180" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 17 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 18 | - platform: android 19 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 20 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 21 | - platform: ios 22 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 23 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 24 | - platform: linux 25 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 26 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 27 | - platform: macos 28 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 29 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 30 | - platform: web 31 | create_revision: ead455963c12b453cdb2358cad34969c76daf180 32 | base_revision: ead455963c12b453cdb2358cad34969c76daf180 33 | 34 | # User provided section 35 | 36 | # List of Local paths (relative to this file) that should be 37 | # ignored by the migrate tool. 38 | # 39 | # Files that are not part of the templates will be ignored by default. 40 | unmanaged_files: 41 | - 'lib/main.dart' 42 | - 'ios/Runner.xcodeproj/project.pbxproj' 43 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dart-code.dart-code", 6 | "dart-code.flutter", 7 | "aaron-bond.better-comments", 8 | "alexisvt.flutter-snippets", 9 | "BendixMa.dart-data-class-generator", 10 | "flutterando.flutter-coverage", 11 | "jeroen-meijer.pubspec-assist", 12 | "Nash.awesome-flutter-snippets", 13 | "pflannery.vscode-versionlens", 14 | "PratheeshRussell.flutter-commands", 15 | "robert-brunhage.flutter-riverpod-snippets", 16 | "ricardo-emerson.create-flutter-widgets-and-classes", 17 | "ryanluker.vscode-coverage-gutters" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch development", 9 | "request": "launch", 10 | "type": "dart", 11 | "program": "lib/main_development.dart", 12 | "args": [ 13 | "--flavor", 14 | "development", 15 | "--target", 16 | "lib/main_development.dart" 17 | ] 18 | }, 19 | { 20 | "name": "Launch staging", 21 | "request": "launch", 22 | "type": "dart", 23 | "program": "lib/main_staging.dart", 24 | "args": ["--flavor", "staging", "--target", "lib/main_staging.dart"] 25 | }, 26 | { 27 | "name": "Launch production", 28 | "request": "launch", 29 | "type": "dart", 30 | "program": "lib/main_production.dart", 31 | "args": ["--flavor", "production", "--target", "lib/main_production.dart"] 32 | }, 33 | { 34 | "name": "Launch normal", 35 | "request": "launch", 36 | "type": "dart", 37 | "program": "lib/main.dart", 38 | 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dart.flutterSdkPath": "/Users/shreemanarjunsahu/.puro/envs/stable/flutter", 3 | "dart.sdkPath": "/Users/shreemanarjunsahu/.puro/envs/stable/flutter/bin/cache/dart-sdk" 4 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.9+1 2 | - 🌐 Update app name 3 | - Update some theme on report issue dialog 4 | 5 | # 1.0.8+1 6 | - Upgraded dependencies 7 | 8 | # 1.0.7+1 9 | - Fix ios 17 build 10 | 11 | # 1.0.6+1 12 | - Upgrade responsive framework 13 | - Upgrade dependencies 14 | 15 | # 1.0.5+1 16 | - Upgrade responsive framework 17 | - Upgrade dependencies 18 | 19 | # 1.0.4+1 20 | - fixed translations 21 | 22 | # 1.0.3+1 23 | - fixed updates 24 | 25 | # 1.0.2+5 26 | - update docs and update to add codepush docs in to-do 27 | 28 | # 1.0.2+4 29 | - Update logic enhanced 30 | 31 | # 1.0.2+3 32 | - Auto update app version support 33 | - Update settings for changelog view 34 | 35 | # 1.0.2+2 36 | - Upda7te setting pages to add app info, bug report feature 37 | - Added Localization 38 | 39 | # 1.0.2+1 40 | - Added Localization Support: Now available in English, Spanish, and Odia, enhancing accessibility for a broader audience. 41 | - Added Workflow 42 | 43 | # 1.0.1+1 44 | - Resumable Downloads: Introduce the ability to resume interrupted or paused downloads, ensuring a seamless download experience even in case of network disruptions (hyper_thread_downloader) 45 | - fix receive list auto refresh 46 | - UI improvements 47 | - docs updated 48 | 49 | 50 | # 1.0.0+1 51 | - Initial release -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing to flutter_sharez 3 | 4 | Thank you for considering contributing to flutter_sharez! We appreciate your interest in helping us improve our project. Please follow these guidelines to make the contribution process smooth and effective. 5 | 6 | ## Getting Started 7 | 8 | 1. Fork the repository to your GitHub account. 9 | 2. Clone the forked repository to your local machine: 10 | 11 | ``` 12 | git clone https://github.com/Shreemanarjun/flutter_sharez 13 | ``` 14 | 15 | 3. Create a new branch for your changes: 16 | 17 | ``` 18 | git checkout -b feature-name 19 | ``` 20 | 21 | 4. Make your changes and commit them with a descriptive commit message: 22 | 23 | ``` 24 | git commit -m "Description of the changes" 25 | ``` 26 | 27 | 5. Push your changes to your forked repository: 28 | 29 | ``` 30 | git push origin feature-name 31 | ``` 32 | 33 | 6. Open a pull request on the `main` branch of this repository. Provide a clear and descriptive title for your pull request, explaining your changes. 34 | 35 | ## Contribution Guidelines 36 | 37 | - Please make sure your code adheres to the existing coding standards and style in the project. 38 | - If your contribution changes existing functionality, make sure to update the documentation accordingly. 39 | - Test your changes thoroughly before opening a pull request. 40 | - Be respectful and considerate in your comments and discussions on issues and pull requests. 41 | 42 | ## Code of Conduct 43 | 44 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project, you agree to abide by its terms. You can read the full code of conduct [here](CODE_OF_CONDUCT.md). 45 | 46 | ## Need Help? 47 | 48 | If you have any questions or need further assistance, feel free to open an issue or join our community discussions. 49 | 50 | Thank you for contributing to flutter_sharez! We appreciate your help in making this project better. 51 | 52 | Happy Coding! 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2023] [Shreeman Arjun Sahu] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | # analyzer: 3 | # plugins: 4 | # - custom_lint 5 | linter: 6 | rules: 7 | public_member_api_docs: false 8 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /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 | namespace "com.example.flutter_sharez" 30 | compileSdkVersion 34 31 | ndkVersion flutter.ndkVersion 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | kotlinOptions { 39 | jvmTarget = '1.8' 40 | } 41 | 42 | sourceSets { 43 | main.java.srcDirs += 'src/main/kotlin' 44 | } 45 | 46 | defaultConfig { 47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 48 | applicationId "com.example.flutter_sharez" 49 | // You can update the following values to match your application needs. 50 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 51 | minSdkVersion 24 52 | targetSdkVersion flutter.targetSdkVersion 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | // Signing with the debug keys for now, so `flutter run --release` works. 61 | signingConfig signingConfigs.debug 62 | } 63 | } 64 | } 65 | 66 | flutter { 67 | source '../..' 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 16 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /android/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/flutter_sharez/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flutter_sharez 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-v21/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/drawable/background.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_rounded.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 19 | 22 | 23 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.8.20' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:8.5.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 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 | tasks.register("clean", Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.defaults.buildfeatures.buildconfig=true 5 | android.nonTransitiveRClass=false 6 | android.nonFinalResIds=false 7 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /assets/images/logo/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/assets/images/logo/ic_launcher.png -------------------------------------------------------------------------------- /assets/images/logo/ic_launcher_adaptive_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/assets/images/logo/ic_launcher_adaptive_back.png -------------------------------------------------------------------------------- /assets/images/logo/ic_launcher_adaptive_fore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/assets/images/logo/ic_launcher_adaptive_fore.png -------------------------------------------------------------------------------- /assets/images/logo/logo_white_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/assets/images/logo/logo_white_bg.png -------------------------------------------------------------------------------- /assets/images/logo/logo_white_fg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/assets/images/logo/logo_white_fg.png -------------------------------------------------------------------------------- /build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | auto_route_generator:auto_route_generator: # this for @RoutePage 5 | options: 6 | enable_cached_builds: true 7 | generate_for: 8 | - lib/features/**_page.dart 9 | auto_route_generator:auto_router_generator: # this for @AutoRouterConfig 10 | options: 11 | enable_cached_builds: true 12 | generate_for: 13 | - lib/core/router/router.dart 14 | -------------------------------------------------------------------------------- /devtools_options.yaml: -------------------------------------------------------------------------------- 1 | description: This file stores settings for Dart & Flutter DevTools. 2 | documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states 3 | extensions: 4 | -------------------------------------------------------------------------------- /icons_launcher.yaml: -------------------------------------------------------------------------------- 1 | icons_launcher: 2 | image_path: "assets/images/logo/ic_launcher_adaptive_fore.png" 3 | platforms: 4 | android: 5 | enable: true 6 | # adaptive_background_color: '#ffffff' 7 | adaptive_background_image: "assets/images/logo/ic_launcher_adaptive_back.png" 8 | adaptive_foreground_image: "assets/images/logo/ic_launcher_adaptive_fore.png" 9 | adaptive_round_image: "assets/images/logo/logo_white_fg.png" 10 | ios: 11 | enable: true 12 | image_path: "assets/images/logo/logo_white_fg.png" 13 | web: 14 | enable: true 15 | image_path: "assets/images/logo/ic_launcher.png" 16 | favicon_path: "assets/images/logo/logo_white_fg.png" 17 | macos: 18 | enable: true 19 | image_path: "assets/images/logo/ic_launcher.png" 20 | # windows: 21 | # enable: true 22 | # image_path: "assets/images/logo/ic_launcher.png" 23 | # linux: 24 | # enable: true 25 | # image_path: "assets/images/logo/ic_launcher.png" -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter Sharez 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | flutter_sharez 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/app/app.dart: -------------------------------------------------------------------------------- 1 | export 'view/app.dart'; 2 | -------------------------------------------------------------------------------- /lib/bootstrap.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: deprecated_member_use 2 | 3 | import 'dart:async'; 4 | import 'dart:developer'; 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:flutter/widgets.dart'; 7 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 8 | import 'package:platform_info/platform_info.dart'; 9 | import 'package:talker_flutter/talker_flutter.dart'; 10 | 11 | // coverage:ignore-file 12 | 13 | /// This `talker` global variable used for logging and accessible 14 | /// to other classed or function 15 | // coverage:ignore-file 16 | 17 | final talker = TalkerFlutter.init( 18 | settings: TalkerSettings( 19 | // maxHistoryItems: null, 20 | useConsoleLogs: !kReleaseMode, 21 | enabled: !kReleaseMode, 22 | ), 23 | logger: TalkerLogger( 24 | // output: debugPrint, 25 | settings: TalkerLoggerSettings( 26 | enableColors: !Platform.I.iOS, 27 | ), 28 | ), 29 | ); 30 | 31 | ///This bootstrap function builds widget asynchronusly 32 | ///where builder function used for building your start widget. 33 | ///You can override riverpod providers ,also setup observers 34 | ///or you can put a provider container in parent 35 | Future bootstrap( 36 | FutureOr Function() builder, { 37 | required ProviderContainer parent, 38 | }) async { 39 | FlutterError.onError = (details) { 40 | log(details.exceptionAsString(), stackTrace: details.stack); 41 | }; 42 | 43 | runApp( 44 | UncontrolledProviderScope( 45 | container: parent, 46 | child: await builder(), 47 | ), 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /lib/const/app_urls.dart: -------------------------------------------------------------------------------- 1 | /// This class helping putting all 2 | /// the urls needed in apps 3 | class AppUrls { 4 | AppUrls._(); 5 | } 6 | -------------------------------------------------------------------------------- /lib/const/resource.dart: -------------------------------------------------------------------------------- 1 | /// Generate by [resource_generator](https://github.com/CaiJingLong/flutter_resource_generator) library. 2 | /// PLEASE DO NOT EDIT MANUALLY. 3 | // ignore_for_file: constant_identifier_names 4 | class R { 5 | const R._(); 6 | 7 | /// ![preview](file://C:\Users\shree\Documents\GitHub\flutter_sharez\assets\anim\nointernet.riv) 8 | static const String ASSETS_ANIM_NOINTERNET_RIV = 'assets/anim/nointernet.riv'; 9 | } 10 | -------------------------------------------------------------------------------- /lib/core/local_storage/app_storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:hive_ce_flutter/hive_flutter.dart'; 3 | 4 | /// This class used for storing data in nosql hive boxes 5 | /// ,reading data and deleting data . 6 | class AppStorage { 7 | Box? appBox; 8 | 9 | AppStorage(this.appBox); 10 | 11 | Future init({isTest = false}) async { 12 | appBox = appBox ?? 13 | await Hive.openBox( 14 | 'appBox', 15 | bytes: isTest ? Uint8List(0) : null, 16 | ); 17 | } 18 | 19 | /// for getting value as String for a 20 | /// given key from the box 21 | String? get({required String key}) { 22 | return appBox?.get(key) as String?; 23 | } 24 | 25 | /// for storing value on defined key 26 | /// on the box 27 | Future put({ 28 | required String key, 29 | required String value, 30 | }) async { 31 | await appBox?.put(key, value); 32 | } 33 | 34 | /// for clearing all data in box 35 | Future clearAllData() async { 36 | await appBox?.clear(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/core/local_storage/app_storage_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:hive_ce_flutter/hive_flutter.dart'; 3 | import 'package:flutter_sharez/core/local_storage/app_storage.dart'; 4 | 5 | /// This provider used for App Storage Service class which 6 | /// depends on appBoxProvider for getting intial Hive Box 7 | final appStorageProvider = Provider.autoDispose( 8 | (ref) => AppStorage(ref.watch(appBoxProvider)), 9 | name: 'appStorageProvider', 10 | ); 11 | 12 | /// This provider used for Storing Hive Box which you can override on 13 | /// bootstrap function on start of the app 14 | final appBoxProvider = Provider.autoDispose( 15 | (ref) => throw UnimplementedError("appBoxProvider is not overriden"), 16 | name: 'appBoxProvider', 17 | ); 18 | -------------------------------------------------------------------------------- /lib/core/router/auto_route_observer.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: strict_raw_type 2 | 3 | import 'package:auto_route/auto_route.dart'; 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter_sharez/bootstrap.dart'; 7 | 8 | /// This class observers all events happening in routing/navigation 9 | class RouterObserver extends AutoRouterObserver { 10 | @override 11 | void didPush(Route route, Route? previousRoute) { 12 | talker.debug( 13 | 'New route pushed: ${route.settings.name} Previous route is: ${previousRoute?.settings.name}'); 14 | } 15 | 16 | @override 17 | void didPop(Route route, Route? previousRoute) { 18 | talker.debug( 19 | 'Previous route poped: ${route.settings.name} Active route is: ${previousRoute?.settings.name}'); 20 | } 21 | 22 | @override 23 | void didReplace({Route? newRoute, Route? oldRoute}) { 24 | talker.debug( 25 | 'Route ${newRoute?.settings.name} is replaced with ${oldRoute?.settings.name}'); 26 | } 27 | 28 | @override 29 | void didRemove(Route route, Route? previousRoute) { 30 | talker.debug( 31 | 'Route ${route.settings.name} is removed. Previous route is: ${previousRoute?.settings.name}'); 32 | } 33 | 34 | // only override to observer tab routes 35 | @override 36 | void didInitTabRoute(TabPageRoute route, TabPageRoute? previousRoute) { 37 | talker.debug( 38 | 'Tab route visited: ${route.name} Previous route is: ${previousRoute?.name}'); 39 | } 40 | 41 | @override 42 | void didChangeTabRoute(TabPageRoute route, TabPageRoute previousRoute) { 43 | talker.debug( 44 | 'Tab route re-visited: ${route.name} Previous route is: ${previousRoute.name}'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/core/router/router_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/router/router.dart'; 4 | 5 | /// This global variable used for global working on ui elements where 6 | /// may be context is not present 7 | final navigatorKey = GlobalKey(); 8 | 9 | /// This provider used for storing router 10 | /// and can be acessed by reading it using ProviderRef/WidgetRef 11 | final autorouterProvider = Provider.autoDispose( 12 | (ref) => AppRouter(), 13 | name: 'autorouterProvider', 14 | ); 15 | -------------------------------------------------------------------------------- /lib/core/theme/theme_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/local_storage/app_storage_pod.dart'; 4 | 5 | ///This provider stores the ThemeModeController 6 | final themecontrollerProvider = 7 | NotifierProvider.autoDispose( 8 | ThemeModeController.new, 9 | name: 'themecontrollerProvider', 10 | ); 11 | 12 | ///This controller class used change theme and 13 | ///get the intial theme from storage if its available 14 | class ThemeModeController extends AutoDisposeNotifier { 15 | final _themeKey = "theme"; 16 | 17 | @override 18 | ThemeMode build() { 19 | final theme = ref.watch(appStorageProvider).get(key: _themeKey); 20 | if (theme != null) { 21 | if (theme == ThemeMode.light.name) { 22 | return ThemeMode.light; 23 | } else if (theme == ThemeMode.dark.name) { 24 | return ThemeMode.dark; 25 | } 26 | return ThemeMode.system; 27 | } 28 | return ThemeMode.system; 29 | } 30 | 31 | Future changeTheme(ThemeMode theme) async { 32 | state = theme; 33 | await ref.read(appStorageProvider).put(key: _themeKey, value: theme.name); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/data/model/check_server_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class CheckServerModel { 4 | final String message; 5 | final String? token; 6 | CheckServerModel({ 7 | required this.message, 8 | this.token, 9 | }); 10 | 11 | CheckServerModel copyWith({ 12 | String? message, 13 | String? token, 14 | }) { 15 | return CheckServerModel( 16 | message: message ?? this.message, 17 | token: token ?? this.token, 18 | ); 19 | } 20 | 21 | Map toMap() { 22 | return { 23 | 'message': message, 24 | 'token': token, 25 | }; 26 | } 27 | 28 | factory CheckServerModel.fromMap(Map map) { 29 | return CheckServerModel( 30 | message: map['message'] ?? '', 31 | token: map['token'], 32 | ); 33 | } 34 | 35 | String toJson() => json.encode(toMap()); 36 | 37 | factory CheckServerModel.fromJson(String source) => 38 | CheckServerModel.fromMap(json.decode(source)); 39 | 40 | @override 41 | String toString() => 'CheckServerModel(message: $message, token: $token)'; 42 | 43 | @override 44 | bool operator ==(Object other) { 45 | if (identical(this, other)) return true; 46 | 47 | return other is CheckServerModel && 48 | other.message == message && 49 | other.token == token; 50 | } 51 | 52 | @override 53 | int get hashCode => message.hashCode ^ token.hashCode; 54 | } 55 | -------------------------------------------------------------------------------- /lib/data/model/file_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class FileModel { 4 | final String name; 5 | final int size; 6 | 7 | final String fileExt; 8 | FileModel({ 9 | required this.name, 10 | required this.size, 11 | required this.fileExt, 12 | }); 13 | 14 | FileModel copyWith({ 15 | String? name, 16 | int? size, 17 | String? fileExt, 18 | }) { 19 | return FileModel( 20 | name: name ?? this.name, 21 | size: size ?? this.size, 22 | fileExt: fileExt ?? this.fileExt, 23 | ); 24 | } 25 | 26 | Map toMap() { 27 | return { 28 | 'name': name, 29 | 'size': size, 30 | 'fileExt': fileExt, 31 | }; 32 | } 33 | 34 | factory FileModel.fromMap(Map map) { 35 | return FileModel( 36 | name: map['name'] ?? '', 37 | size: map['size']?.toInt() ?? 0, 38 | fileExt: map['fileExt'] ?? '', 39 | ); 40 | } 41 | 42 | String toJson() => json.encode(toMap()); 43 | 44 | factory FileModel.fromJson(String source) => 45 | FileModel.fromMap(json.decode(source)); 46 | 47 | @override 48 | String toString() => 'FileModel(name: $name, size: $size, fileExt: $fileExt)'; 49 | 50 | @override 51 | bool operator ==(Object other) { 52 | if (identical(this, other)) return true; 53 | 54 | return other is FileModel && 55 | other.name == name && 56 | other.size == size && 57 | other.fileExt == fileExt; 58 | } 59 | 60 | @override 61 | int get hashCode => name.hashCode ^ size.hashCode ^ fileExt.hashCode; 62 | } 63 | -------------------------------------------------------------------------------- /lib/data/model/file_select_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:file_picker/file_picker.dart'; 2 | 3 | class FileSelectModel { 4 | final bool isSelected; 5 | final PlatformFile file; 6 | FileSelectModel({ 7 | required this.isSelected, 8 | required this.file, 9 | }); 10 | 11 | FileSelectModel copyWith({ 12 | bool? isSelected, 13 | PlatformFile? file, 14 | }) { 15 | return FileSelectModel( 16 | isSelected: isSelected ?? this.isSelected, 17 | file: file ?? this.file, 18 | ); 19 | } 20 | 21 | @override 22 | bool operator ==(Object other) { 23 | if (identical(this, other)) return true; 24 | 25 | return other is FileSelectModel && 26 | other.isSelected == isSelected && 27 | other.file == file; 28 | } 29 | 30 | @override 31 | int get hashCode => isSelected.hashCode ^ file.hashCode; 32 | 33 | @override 34 | String toString() => 'FileSelectModel(isSelected: $isSelected, file: $file)'; 35 | } 36 | -------------------------------------------------------------------------------- /lib/data/model/range_header.dart: -------------------------------------------------------------------------------- 1 | class RangeHeader { 2 | final int start; 3 | final int? end; 4 | 5 | RangeHeader(this.start, this.end); 6 | 7 | @override 8 | String toString() { 9 | if (end != null) { 10 | return 'bytes $start-$end'; 11 | } else { 12 | return 'bytes $start-'; 13 | } 14 | } 15 | } 16 | 17 | RangeHeader parseRangeHeader(String? rangeHeaderValue, int fileSize) { 18 | if (rangeHeaderValue == null) { 19 | return RangeHeader(0, null); 20 | } 21 | 22 | final matches = RegExp(r'bytes=(\d*)-(\d*)').firstMatch(rangeHeaderValue); 23 | if (matches != null) { 24 | final start = matches.group(1); 25 | final end = matches.group(2); 26 | if (start!.isNotEmpty) { 27 | final startByte = int.parse(start); 28 | if (end!.isNotEmpty) { 29 | final endByte = int.parse(end); 30 | if (endByte >= startByte && endByte < fileSize) { 31 | return RangeHeader(startByte, endByte); 32 | } 33 | } else { 34 | if (startByte < fileSize) { 35 | return RangeHeader(startByte, null); 36 | } 37 | } 38 | } else if (end!.isNotEmpty) { 39 | final endByte = int.parse(end); 40 | if (fileSize - endByte >= 0) { 41 | return RangeHeader(fileSize - endByte, fileSize - 1); 42 | } 43 | } 44 | } 45 | return RangeHeader(0, null); 46 | } 47 | -------------------------------------------------------------------------------- /lib/data/model/receiver_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_mappable/dart_mappable.dart'; 2 | part 'receiver_model.mapper.dart'; 3 | 4 | @MappableClass() 5 | class ReceiverModel with ReceiverModelMappable { 6 | final String ip; 7 | final int port; 8 | final String host; 9 | final String os; 10 | final String version; 11 | ReceiverModel({ 12 | required this.ip, 13 | required this.port, 14 | required this.host, 15 | required this.os, 16 | required this.version, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /lib/data/model/sender_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class SenderModel { 4 | final String? ip; 5 | final int? port; 6 | final int? filesCount; 7 | final String? host; 8 | final String? os; 9 | final String? version; 10 | SenderModel({ 11 | this.ip, 12 | this.port, 13 | this.filesCount, 14 | this.host, 15 | this.os, 16 | this.version, 17 | }); 18 | 19 | SenderModel copyWith({ 20 | String? ip, 21 | int? port, 22 | int? filesCount, 23 | String? host, 24 | String? os, 25 | String? version, 26 | }) { 27 | return SenderModel( 28 | ip: ip ?? this.ip, 29 | port: port ?? this.port, 30 | filesCount: filesCount ?? this.filesCount, 31 | host: host ?? this.host, 32 | os: os ?? this.os, 33 | version: version ?? this.version, 34 | ); 35 | } 36 | 37 | Map toMap() { 38 | return { 39 | 'ip': ip, 40 | 'port': port, 41 | 'filesCount': filesCount, 42 | 'host': host, 43 | 'os': os, 44 | 'version': version, 45 | }; 46 | } 47 | 48 | factory SenderModel.fromMap(Map map) { 49 | return SenderModel( 50 | ip: map['ip'], 51 | port: map['port']?.toInt(), 52 | filesCount: map['filesCount']?.toInt(), 53 | host: map['host'], 54 | os: map['os'], 55 | version: map['version'], 56 | ); 57 | } 58 | 59 | String toJson() => json.encode(toMap()); 60 | 61 | factory SenderModel.fromJson(String source) => 62 | SenderModel.fromMap(json.decode(source)); 63 | 64 | @override 65 | String toString() { 66 | return 'SenderModel(ip: $ip, port: $port, filesCount: $filesCount, host: $host, os: $os, version: $version)'; 67 | } 68 | 69 | @override 70 | bool operator ==(Object other) { 71 | if (identical(this, other)) return true; 72 | 73 | return other is SenderModel && 74 | other.ip == ip && 75 | other.port == port && 76 | other.filesCount == filesCount && 77 | other.host == host && 78 | other.os == os && 79 | other.version == version; 80 | } 81 | 82 | @override 83 | int get hashCode { 84 | return ip.hashCode ^ 85 | port.hashCode ^ 86 | filesCount.hashCode ^ 87 | host.hashCode ^ 88 | os.hashCode ^ 89 | version.hashCode; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/data/model/server_info.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class ServerInfo { 4 | final String ip; 5 | final int port; 6 | final String host; 7 | final String os; 8 | final String version; 9 | ServerInfo({ 10 | required this.ip, 11 | required this.port, 12 | required this.host, 13 | required this.os, 14 | required this.version, 15 | }); 16 | 17 | ServerInfo copyWith({ 18 | String? ip, 19 | int? port, 20 | String? host, 21 | String? os, 22 | String? version, 23 | }) { 24 | return ServerInfo( 25 | ip: ip ?? this.ip, 26 | port: port ?? this.port, 27 | host: host ?? this.host, 28 | os: os ?? this.os, 29 | version: version ?? this.version, 30 | ); 31 | } 32 | 33 | Map toMap() { 34 | return { 35 | 'ip': ip, 36 | 'port': port, 37 | 'host': host, 38 | 'os': os, 39 | 'version': version, 40 | }; 41 | } 42 | 43 | factory ServerInfo.fromMap(Map map) { 44 | return ServerInfo( 45 | ip: map['ip'] ?? '', 46 | port: map['port']?.toInt() ?? 0, 47 | host: map['host'] ?? '', 48 | os: map['os'] ?? '', 49 | version: map['version'] ?? '', 50 | ); 51 | } 52 | 53 | String toJson() => json.encode(toMap()); 54 | 55 | factory ServerInfo.fromJson(String source) => 56 | ServerInfo.fromMap(json.decode(source)); 57 | 58 | @override 59 | String toString() { 60 | return 'ServerInfo(ip: $ip, port: $port, host: $host, os: $os, version: $version)'; 61 | } 62 | 63 | @override 64 | bool operator ==(Object other) { 65 | if (identical(this, other)) return true; 66 | 67 | return other is ServerInfo && 68 | other.ip == ip && 69 | other.port == port && 70 | other.host == host && 71 | other.os == os && 72 | other.version == version; 73 | } 74 | 75 | @override 76 | int get hashCode { 77 | return ip.hashCode ^ 78 | port.hashCode ^ 79 | host.hashCode ^ 80 | os.hashCode ^ 81 | version.hashCode; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/data/service/receiver/receiver_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dio/dio.dart'; 4 | import 'package:flutter_sharez/data/model/check_server_model.dart'; 5 | import 'package:flutter_sharez/data/model/file_paths_model.dart'; 6 | import 'package:flutter_sharez/data/model/receiver_model.dart'; 7 | import 'package:flutter_sharez/shared/exception/base_exception.dart'; 8 | import 'package:multiple_result/multiple_result.dart'; 9 | 10 | class ReceiverService { 11 | final Dio dio; 12 | 13 | ReceiverService({required this.dio}); 14 | 15 | Future> connectToDevice({ 16 | required String ip, 17 | required String port, 18 | required currentIP, 19 | required CancelToken cancelToken, 20 | }) async { 21 | final response = await dio.post( 22 | '/checkServer', 23 | data: ReceiverModel( 24 | ip: currentIP, 25 | port: 8080, 26 | host: Platform.localHostname, 27 | os: Platform.operatingSystem, 28 | version: Platform.operatingSystemVersion, 29 | ).toMap(), 30 | cancelToken: cancelToken, 31 | ); 32 | 33 | if (response.statusCode == 200) { 34 | final checkServermodel = CheckServerModel.fromMap(response.data); 35 | if (checkServermodel.message.contains('Accepted')) { 36 | return const Success(true); 37 | } else { 38 | return const Success(false); 39 | } 40 | } else { 41 | try { 42 | final checkServermodel = CheckServerModel.fromMap(response.data); 43 | return Error(BaseException(message: checkServermodel.message)); 44 | } catch (e) { 45 | return Error(BaseException(message: e.toString())); 46 | } 47 | } 48 | } 49 | 50 | Future> getFilePaths({ 51 | required CancelToken cancelToken, 52 | }) async { 53 | final response = await dio.get( 54 | '/filepath', 55 | cancelToken: cancelToken, 56 | ); 57 | 58 | if (response.statusCode == 200) { 59 | return Success( 60 | FilePathsModel.fromMap(response.data), 61 | ); 62 | } else { 63 | return Error( 64 | BaseException(message: "Failed to get files"), 65 | ); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/data/service/receiver/receiver_service_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/data/model/sender_model.dart'; 3 | import 'package:flutter_sharez/data/service/receiver/receiver_service.dart'; 4 | import 'package:flutter_sharez/shared/api_client/dio/dio_client_provider.dart'; 5 | 6 | final receiverServicePod = 7 | Provider.autoDispose.family( 8 | (ref, sendermodel) { 9 | return ReceiverService( 10 | dio: ref.watch( 11 | dioProvider('http://${sendermodel.ip}:${sendermodel.port}'), 12 | ), 13 | ); 14 | }, 15 | name: 'receiverServicePod', 16 | ); 17 | -------------------------------------------------------------------------------- /lib/data/service/sender/sender_service_pod.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:alfred/alfred.dart'; 4 | import 'package:file_picker/file_picker.dart'; 5 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 6 | import 'package:flutter_sharez/data/service/sender/sender_service.dart'; 7 | import 'package:flutter_sharez/features/file_selector/controller/selected_files_list_pod.dart'; 8 | 9 | final senderServicePod = Provider.autoDispose((ref) { 10 | return SenderService( 11 | app: ref.watch(alfredPod), 12 | port: ref.watch(defaultPortProvider), 13 | ref: ref, 14 | ); 15 | }, name: 'senderServicePod'); 16 | 17 | final alfredPod = Provider.autoDispose((ref) { 18 | FutureOr missingHandler(HttpRequest req, HttpResponse res) { 19 | res.statusCode = 404; 20 | return {'message': '${req.uri.toString()} not found'}; 21 | } 22 | 23 | FutureOr onInternalError(HttpRequest req, HttpResponse res) { 24 | res.statusCode = 500; 25 | return {'message': 'Error in ${req..uri.toString()},'}; 26 | } 27 | 28 | return Alfred( 29 | onNotFound: missingHandler, 30 | onInternalError: onInternalError, 31 | ); 32 | }, name: 'alfredPod'); 33 | 34 | final defaultPortProvider = 35 | StateProvider.autoDispose((ref) => 8080, name: 'defaultPortProvider'); 36 | 37 | final paltformFilesPod = Provider.autoDispose>( 38 | (ref) { 39 | return ref.watch( 40 | selectedFilesPod.select( 41 | (value) => value.map((e) => e.file).toList(), 42 | ), 43 | ); 44 | }, 45 | name: 'paltformFilesPod', 46 | ); 47 | -------------------------------------------------------------------------------- /lib/features/counter/controller/counter_state_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/features/counter/counter.dart'; 3 | 4 | /// This provider holds CounternNotifier 5 | final counterPod = NotifierProvider( 6 | CounterNotifier.new, 7 | name: 'counterPod', 8 | ); 9 | 10 | ///This provider used to seup the intial value 11 | ///which can be overriden for test 12 | final intialCounterValuePod = Provider((ref) => 0); 13 | -------------------------------------------------------------------------------- /lib/features/counter/controller/notifier/counter_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/features/counter/counter.dart'; 3 | 4 | /// This notifier class used to build intial value 5 | /// from intial counter value which can be overriden. 6 | 7 | class CounterNotifier extends Notifier { 8 | @override 9 | int build() { 10 | return ref.read(intialCounterValuePod); 11 | } 12 | 13 | ///This function updates current state increase by 1 14 | void increment() => state = state + 1; 15 | 16 | ///This function updates current state decrease by 1 17 | void decrement() => state = state - 1; 18 | } 19 | -------------------------------------------------------------------------------- /lib/features/counter/counter.dart: -------------------------------------------------------------------------------- 1 | export 'controller/counter_state_pod.dart'; 2 | export 'controller/notifier/counter_notifier.dart'; 3 | export 'view/counter_page.dart'; 4 | -------------------------------------------------------------------------------- /lib/features/device_share/controller/files_list_pods.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/data/model/file_paths_model.dart'; 3 | import 'package:flutter_sharez/data/model/sender_model.dart'; 4 | import 'package:flutter_sharez/data/service/receiver/receiver_service_pod.dart'; 5 | import 'package:flutter_sharez/shared/riverpod_ext/cancel_extensions.dart'; 6 | 7 | final senderfileListPod = FutureProvider.autoDispose 8 | .family((ref, sendermodel) async { 9 | final result = await ref 10 | .watch(receiverServicePod(sendermodel)) 11 | .getFilePaths(cancelToken: ref.cancelToken()); 12 | return result.when( 13 | (filepathsmodel) { 14 | return filepathsmodel; 15 | }, 16 | (error) => throw error.message, 17 | ); 18 | }); 19 | -------------------------------------------------------------------------------- /lib/features/device_share/view/device_share_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sharez/core/router/router.gr.dart'; 4 | 5 | import 'package:flutter_sharez/data/model/sender_model.dart'; 6 | import 'package:velocity_x/velocity_x.dart'; 7 | 8 | @RoutePage( 9 | deferredLoading: true, 10 | ) 11 | class DeviceSharePage extends StatelessWidget { 12 | final SenderModel senderModel; 13 | const DeviceSharePage({super.key, required this.senderModel}); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return DeviceShareView( 18 | senderModel: senderModel, 19 | ); 20 | } 21 | } 22 | 23 | class DeviceShareView extends StatelessWidget { 24 | final SenderModel senderModel; 25 | const DeviceShareView({super.key, required this.senderModel}); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return AutoTabsRouter.tabBar( 30 | routes: [ 31 | DeviceInfoTabRoute(senderModel: senderModel), 32 | SenderFilesTabRoute(senderModel: senderModel) 33 | ], 34 | builder: (context, child, tabsRouter) { 35 | return Scaffold( 36 | body: [ 37 | ColoredBox( 38 | color: context.theme.dialogBackgroundColor, 39 | child: TabBar( 40 | controller: tabsRouter, 41 | tabs: const [ 42 | Tab( 43 | text: 'Device Info', 44 | icon: Icon(Icons.info_outline_rounded)), 45 | Tab(text: 'Files', icon: Icon(Icons.folder_open_outlined)), 46 | ], 47 | ), 48 | ).flexible(), 49 | child.expand() 50 | ].vStack(), 51 | ); 52 | }, 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/features/device_share/view/tabs/device_info_tab_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sharez/data/model/sender_model.dart'; 4 | import 'package:flutter_sharez/shared/widget/os_logo.dart'; 5 | import 'package:velocity_x/velocity_x.dart'; 6 | 7 | @RoutePage( 8 | deferredLoading: true, 9 | ) 10 | class DeviceInfoTabPage extends StatelessWidget { 11 | final SenderModel senderModel; 12 | const DeviceInfoTabPage({super.key, required this.senderModel}); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return ListView( 17 | children: [ 18 | ListTile( 19 | title: "Host: ${senderModel.host}".text.make(), 20 | ), 21 | ListTile( 22 | title: "IP: ${senderModel.ip}".text.make(), 23 | ), 24 | ListTile( 25 | title: "Port: ${senderModel.port}".text.make(), 26 | ), 27 | ListTile( 28 | title: "OS: ${senderModel.os}".text.make(), 29 | trailing: OSLogo(os: senderModel.os), 30 | ), 31 | ListTile( 32 | title: "Version: ${senderModel.version}".text.make(), 33 | ) 34 | ], 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/features/downloads/view/downloads_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:auto_route/auto_route.dart'; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'package:flutter_sharez/translation_pod.dart'; 7 | import 'package:velocity_x/velocity_x.dart'; 8 | 9 | @RoutePage( 10 | deferredLoading: true, 11 | ) 12 | class DownloadsPage extends ConsumerWidget { 13 | const DownloadsPage({super.key}); 14 | 15 | @override 16 | Widget build(BuildContext context, WidgetRef ref) { 17 | final t = ref.watch(translationsPod); 18 | return Scaffold( 19 | appBar: AppBar( 20 | title: t.downloads.text.make(), 21 | ), 22 | body: ListView( 23 | physics: const ClampingScrollPhysics(), 24 | padding: const EdgeInsets.all(8), 25 | children: [ 26 | ListTile( 27 | title: "Change".text.make(), 28 | onTap: () async { 29 | // Translations t2 = await AppLocaleUtils.v( 30 | // locale: AppLocaleUtils.parse("or"), 31 | // isFlatMap: false, 32 | // map: { 33 | // t.action_downloads: "action download", 34 | // t.downloads: 'updated transladsdtdsad', 35 | // }, 36 | // ); 37 | // ref.read(translationsPod.notifier).update( 38 | // (state) => t2, 39 | // ); 40 | }, 41 | ) 42 | ], 43 | ), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/features/file_download_btn/controller/file_download_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/data/model/file_paths_model.dart'; 3 | import 'package:flutter_sharez/features/file_download_btn/controller/notifier/file_download_notifier.dart'; 4 | import 'package:flutter_sharez/features/file_download_btn/state/file_download_state.dart'; 5 | 6 | final fileDownloaderPod = AsyncNotifierProvider.autoDispose 7 | .family( 8 | FileDownloaderNotifier.new); 9 | -------------------------------------------------------------------------------- /lib/features/file_download_btn/state/file_download_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_mappable/dart_mappable.dart'; 2 | part 'file_download_state.mapper.dart'; 3 | 4 | @MappableClass() 5 | sealed class DownloadState with DownloadStateMappable { 6 | const DownloadState(); // Factory constructor for initial state 7 | factory DownloadState.initial() => const InitialDownloadState(); 8 | 9 | // Factory constructor for downloading state 10 | factory DownloadState.downloading({ 11 | required Progress progress, 12 | required bool isPaused, 13 | }) => 14 | DownloadingState( 15 | progress: progress, 16 | isPaused: isPaused, 17 | ); 18 | 19 | // Factory constructor for completed state 20 | factory DownloadState.completed() => const CompletedDownloadState(); 21 | 22 | // Factory constructor for error state 23 | factory DownloadState.error() => const ErrorDownloadState(); 24 | 25 | // Factory constructor for merge done state 26 | factory DownloadState.mergeDone({required bool isCompleted}) => 27 | MergeDoneState(isCompleted); 28 | } 29 | 30 | @MappableClass() 31 | class InitialDownloadState extends DownloadState 32 | with InitialDownloadStateMappable { 33 | const InitialDownloadState(); 34 | } 35 | 36 | @MappableClass() 37 | class DownloadingState extends DownloadState with DownloadingStateMappable { 38 | final Progress progress; 39 | final bool isPaused; 40 | 41 | const DownloadingState({required this.progress, required this.isPaused}); 42 | } 43 | 44 | @MappableClass() 45 | class CompletedDownloadState extends DownloadState 46 | with CompletedDownloadStateMappable { 47 | const CompletedDownloadState(); 48 | } 49 | 50 | @MappableClass() 51 | class ErrorDownloadState extends DownloadState with ErrorDownloadStateMappable { 52 | const ErrorDownloadState(); 53 | } 54 | 55 | @MappableClass() 56 | class MergeDoneState extends DownloadState with MergeDoneStateMappable { 57 | final bool isCompleted; 58 | const MergeDoneState(this.isCompleted); 59 | } 60 | 61 | @MappableClass() 62 | class Progress with ProgressMappable { 63 | double currentProgress; 64 | double speed; 65 | double remainTime; 66 | 67 | Progress({ 68 | required this.currentProgress, 69 | required this.speed, 70 | required this.remainTime, 71 | }); 72 | } 73 | -------------------------------------------------------------------------------- /lib/features/file_selector/controller/selected_files_list_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/data/model/file_select_model.dart'; 3 | import 'package:flutter_sharez/features/file_selector/controller/notifier/selected_files_notifier.dart'; 4 | 5 | final selectedFilesPod = 6 | NotifierProvider.autoDispose>( 7 | FilesListNotifier.new, 8 | name: 'selectedFilesPod', 9 | ); 10 | -------------------------------------------------------------------------------- /lib/features/file_selector/state/select_file_state.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | sealed class SelectFileState { 4 | const SelectFileState(); 5 | } 6 | 7 | class Initial implements SelectFileState { 8 | const Initial(); 9 | } 10 | 11 | class PermissionDenied implements SelectFileState { 12 | const PermissionDenied(); 13 | } 14 | 15 | class SelectFiles implements SelectFileState { 16 | const SelectFiles(); 17 | } 18 | 19 | class SelectFileStateError implements SelectFileState { 20 | final String message; 21 | final String? details; 22 | SelectFileStateError({ 23 | required this.message, 24 | this.details, 25 | }); 26 | 27 | SelectFileStateError copyWith({ 28 | String? message, 29 | String? details, 30 | }) { 31 | return SelectFileStateError( 32 | message: message ?? this.message, 33 | details: details ?? this.details, 34 | ); 35 | } 36 | 37 | Map toMap() { 38 | return { 39 | 'message': message, 40 | 'details': details, 41 | }; 42 | } 43 | 44 | factory SelectFileStateError.fromMap(Map map) { 45 | return SelectFileStateError( 46 | message: map['message'] ?? '', 47 | details: map['details'], 48 | ); 49 | } 50 | 51 | String toJson() => json.encode(toMap()); 52 | 53 | factory SelectFileStateError.fromJson(String source) => 54 | SelectFileStateError.fromMap(json.decode(source)); 55 | 56 | @override 57 | String toString() => 58 | 'SelectFileStateError(message: $message, details: $details)'; 59 | 60 | @override 61 | bool operator ==(Object other) { 62 | if (identical(this, other)) return true; 63 | 64 | return other is SelectFileStateError && 65 | other.message == message && 66 | other.details == details; 67 | } 68 | 69 | @override 70 | int get hashCode => message.hashCode ^ details.hashCode; 71 | } 72 | -------------------------------------------------------------------------------- /lib/features/file_selector/view/file_list_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:file_sizes/file_sizes.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:flutter_sharez/data/model/file_select_model.dart'; 5 | import 'package:flutter_sharez/features/file_selector/controller/selected_files_list_pod.dart'; 6 | import 'package:velocity_x/velocity_x.dart'; 7 | 8 | class FileListView extends StatelessWidget { 9 | final List files; 10 | const FileListView({super.key, required this.files}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return ListView.separated( 15 | itemCount: files.length, 16 | padding: const EdgeInsets.only( 17 | bottom: 80, 18 | top: 16, 19 | ), 20 | separatorBuilder: (context, index) => const Divider(), 21 | itemBuilder: (context, index) { 22 | final file = files[index]; 23 | return ListTile( 24 | minVerticalPadding: 0, 25 | leading: index 26 | .toString() 27 | .text 28 | .color(context.colors.onSurface) 29 | .bold 30 | .makeCentered() 31 | .circle( 32 | radius: 24, 33 | backgroundColor: context.colors.surface, 34 | ), 35 | title: file.file.name.text.make(), 36 | subtitle: "size: ${FileSize.getSize(file.file.size)}" 37 | .toString() 38 | .text 39 | .make(), 40 | trailing: Consumer( 41 | builder: (context, ref, child) { 42 | return IconButton( 43 | onPressed: () { 44 | ref.read(selectedFilesPod.notifier).deleteItem(index); 45 | }, 46 | icon: const Icon( 47 | Icons.delete, 48 | color: Vx.red400, 49 | )); 50 | }, 51 | ), 52 | ); 53 | }, 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/features/help_dialog/view/help_dialog_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:auto_route/auto_route.dart'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_sharez/translation_pod.dart'; 6 | 7 | import 'package:url_launcher/url_launcher.dart'; 8 | import 'package:velocity_x/velocity_x.dart'; 9 | 10 | @RoutePage( 11 | deferredLoading: true, 12 | ) 13 | class HelpDialogPage extends ConsumerWidget { 14 | const HelpDialogPage({super.key}); 15 | 16 | void launchGithubissue() async { 17 | final uri = 18 | Uri.parse('https://github.com/Shreemanarjun/flutter_sharez/issues'); 19 | if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) { 20 | throw Exception('Could not launch $uri'); 21 | } 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context, WidgetRef ref) { 26 | final t = ref.watch(translationsPod); 27 | return AlertDialog( 28 | title: t.reportABug.text.xl.isIntrinsic.makeCentered(), 29 | content: t.reportDescription.text.bold.lg.center.isIntrinsic.make(), 30 | actionsAlignment: MainAxisAlignment.spaceAround, 31 | actions: [ 32 | TextButton( 33 | style: ElevatedButton.styleFrom( 34 | backgroundColor: context.colors.tertiary, 35 | foregroundColor: context.colors.surface, 36 | ), 37 | onPressed: () { 38 | context.back(); 39 | }, 40 | child: t.cancel.text.isIntrinsic.make(), 41 | ), 42 | TextButton( 43 | style: ElevatedButton.styleFrom( 44 | backgroundColor: context.colors.primary, 45 | foregroundColor: context.colors.surface, 46 | ), 47 | onPressed: launchGithubissue, 48 | child: t.report.text.isIntrinsic.make(), 49 | ), 50 | ], 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/features/home/view/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:flutter_sharez/core/router/router.gr.dart'; 6 | import 'package:flutter_sharez/core/router/router_pod.dart'; 7 | import 'package:flutter_sharez/features/update_app_version/controller/check_update_available.dart'; 8 | import 'package:flutter_sharez/translation_pod.dart'; 9 | 10 | @RoutePage( 11 | deferredLoading: true, 12 | ) 13 | class HomePage extends ConsumerWidget { 14 | const HomePage({super.key}); 15 | 16 | @override 17 | Widget build(BuildContext context, WidgetRef ref) { 18 | final t = ref.watch(translationsPod); 19 | ref.listen( 20 | checkUpdateAvailablePod, 21 | (previous, next) { 22 | if (next is AsyncData && next.value != null) { 23 | ref 24 | .read(autorouterProvider) 25 | .navigate(ChangelogRoute(updateModel: next.value)); 26 | } 27 | }, 28 | ); 29 | return AutoTabsScaffold( 30 | routes: const [ 31 | SendRoute(), 32 | ReceiveRoute(), 33 | ], 34 | bottomNavigationBuilder: (context, tabsRouter) { 35 | return NavigationBar( 36 | selectedIndex: tabsRouter.activeIndex, 37 | onDestinationSelected: tabsRouter.setActiveIndex, 38 | destinations: [ 39 | NavigationDestination( 40 | icon: const Icon(Icons.arrow_upward_outlined), 41 | label: t.sendLbl, 42 | ), 43 | NavigationDestination( 44 | icon: const Icon(Icons.arrow_downward_outlined), 45 | label: t.receiveLbl, 46 | ), 47 | ], 48 | ); 49 | }, 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/features/manual_connect/view/manual_connect_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:auto_route/auto_route.dart'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_form_builder/flutter_form_builder.dart'; 6 | import 'package:flutter_sharez/translation_pod.dart'; 7 | 8 | import 'package:velocity_x/velocity_x.dart'; 9 | 10 | @RoutePage( 11 | deferredLoading: true, 12 | ) 13 | class ManualConnectPage extends ConsumerStatefulWidget { 14 | const ManualConnectPage({super.key}); 15 | 16 | @override 17 | ConsumerState createState() => _ManualConnectPageState(); 18 | } 19 | 20 | class _ManualConnectPageState extends ConsumerState { 21 | final _formKey = GlobalKey(); 22 | @override 23 | void dispose() { 24 | _formKey.currentState?.dispose(); 25 | super.dispose(); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | final t = ref.watch(translationsPod); 31 | return AlertDialog( 32 | alignment: Alignment.center, 33 | content: FormBuilder( 34 | key: _formKey, 35 | child: [ 36 | FormBuilderTextField( 37 | name: 'ip', 38 | decoration: InputDecoration( 39 | labelText: t.enterIp, 40 | ), 41 | ).p4(), 42 | FormBuilderTextField( 43 | name: 'port', 44 | decoration: InputDecoration( 45 | labelText: t.enterPort, 46 | ), 47 | ).p4(), 48 | ].vStack( 49 | crossAlignment: CrossAxisAlignment.start, 50 | alignment: MainAxisAlignment.spaceAround, 51 | axisSize: MainAxisSize.min, 52 | ), 53 | ), 54 | actions: [ 55 | ElevatedButton( 56 | onPressed: () {}, 57 | child: t.connect.text.isIntrinsic.make(), 58 | ) 59 | ], 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/features/qr_scan/qr_scan_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:ai_barcode_scanner/ai_barcode_scanner.dart'; 3 | import 'package:auto_route/auto_route.dart'; 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter_sharez/bootstrap.dart'; 7 | import 'package:flutter_sharez/translation_pod.dart'; 8 | 9 | import 'package:platform_info/platform_info.dart'; 10 | import 'package:velocity_x/velocity_x.dart'; 11 | 12 | @RoutePage( 13 | deferredLoading: true, 14 | ) 15 | class QrScanPage extends ConsumerStatefulWidget { 16 | const QrScanPage({super.key}); 17 | 18 | @override 19 | ConsumerState createState() => _QrScanPageState(); 20 | } 21 | 22 | class _QrScanPageState extends ConsumerState { 23 | final scannerController = MobileScannerController( 24 | detectionSpeed: DetectionSpeed.noDuplicates, 25 | ); 26 | 27 | @override 28 | void dispose() { 29 | scannerController.dispose(); 30 | super.dispose(); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | final t = ref.watch(translationsPod); 36 | return AlertDialog( 37 | content: Platform.I.desktop 38 | ? [ 39 | t.qrscannotSupported.text.isIntrinsic.make(), 40 | FilledButton( 41 | onPressed: () { 42 | Navigator.pop(context); 43 | }, 44 | child: t.ok.text.isIntrinsic.make(), 45 | ).p8() 46 | ].vStack( 47 | axisSize: MainAxisSize.min, 48 | ) 49 | : AiBarcodeScanner( 50 | onDetect: (value) { 51 | talker.debug(value); 52 | scannerController.stop(); 53 | Navigator.of(context).pop(); 54 | }, 55 | controller: scannerController, 56 | ).hHalf(context), 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/features/receive/controller/connect_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/data/model/sender_model.dart'; 3 | import 'package:flutter_sharez/features/receive/controller/notifier/connect_btn_notifier.dart'; 4 | import 'package:flutter_sharez/features/receive/state/connect_btn_state_pod.dart'; 5 | 6 | final connectBtnPod = AsyncNotifierProvider.autoDispose 7 | .family( 8 | ConnectBtnNotifier.new); 9 | -------------------------------------------------------------------------------- /lib/features/receive/controller/notifier/connect_btn_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:flutter_sharez/data/model/sender_model.dart'; 5 | import 'package:flutter_sharez/data/service/receiver/receiver_service_pod.dart'; 6 | import 'package:flutter_sharez/features/receive/state/connect_btn_state_pod.dart'; 7 | import 'package:flutter_sharez/shared/riverpod_ext/cancel_extensions.dart'; 8 | 9 | 10 | class ConnectBtnNotifier 11 | extends AutoDisposeFamilyAsyncNotifier { 12 | @override 13 | FutureOr build(SenderModel arg) { 14 | return UnconnectedState(); 15 | } 16 | 17 | Future connectToDevice() async { 18 | state = AsyncData(ConnectingState()); 19 | state = await AsyncValue.guard(() async { 20 | final receiverService = ref.watch(receiverServicePod(arg)); 21 | // final currentIP = await NetworkDiscovery.discoverDeviceIpAddress(); 22 | final result = await receiverService.connectToDevice( 23 | ip: arg.ip.toString(), 24 | port: arg.port.toString(), 25 | currentIP: "currentIP", 26 | cancelToken: ref.cancelToken(), 27 | ); 28 | return result.when((isAccepted) { 29 | ref.keepAlive(); 30 | return ConenctionAcceptanceState(isAccepted: isAccepted); 31 | }, (error) { 32 | return ConnectionFailedState(message: error.message); 33 | }); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/features/receive/state/connect_btn_state_pod.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | sealed class ConnectBtnState { 4 | const ConnectBtnState(); 5 | } 6 | 7 | class UnconnectedState implements ConnectBtnState {} 8 | 9 | class ConnectingState implements ConnectBtnState {} 10 | 11 | class ConenctionAcceptanceState implements ConnectBtnState { 12 | final bool isAccepted; 13 | ConenctionAcceptanceState({ 14 | required this.isAccepted, 15 | }); 16 | 17 | ConenctionAcceptanceState copyWith({ 18 | bool? isAccepted, 19 | }) { 20 | return ConenctionAcceptanceState( 21 | isAccepted: isAccepted ?? this.isAccepted, 22 | ); 23 | } 24 | 25 | Map toMap() { 26 | return { 27 | 'isAccepted': isAccepted, 28 | }; 29 | } 30 | 31 | factory ConenctionAcceptanceState.fromMap(Map map) { 32 | return ConenctionAcceptanceState( 33 | isAccepted: map['isAccepted'] ?? false, 34 | ); 35 | } 36 | 37 | String toJson() => json.encode(toMap()); 38 | 39 | factory ConenctionAcceptanceState.fromJson(String source) => 40 | ConenctionAcceptanceState.fromMap(json.decode(source)); 41 | 42 | @override 43 | String toString() => 'ConenctionAcceptanceState(isAccepted: $isAccepted)'; 44 | 45 | @override 46 | bool operator ==(Object other) { 47 | if (identical(this, other)) return true; 48 | 49 | return other is ConenctionAcceptanceState && other.isAccepted == isAccepted; 50 | } 51 | 52 | @override 53 | int get hashCode => isAccepted.hashCode; 54 | } 55 | 56 | class ConnectionFailedState implements ConnectBtnState { 57 | final String message; 58 | ConnectionFailedState({ 59 | required this.message, 60 | }); 61 | 62 | ConnectionFailedState copyWith({ 63 | String? message, 64 | }) { 65 | return ConnectionFailedState( 66 | message: message ?? this.message, 67 | ); 68 | } 69 | 70 | Map toMap() { 71 | return { 72 | 'message': message, 73 | }; 74 | } 75 | 76 | factory ConnectionFailedState.fromMap(Map map) { 77 | return ConnectionFailedState( 78 | message: map['message'] ?? '', 79 | ); 80 | } 81 | 82 | String toJson() => json.encode(toMap()); 83 | 84 | factory ConnectionFailedState.fromJson(String source) => 85 | ConnectionFailedState.fromMap(json.decode(source)); 86 | 87 | @override 88 | String toString() => 'ConnectionFailedState(message: $message)'; 89 | 90 | @override 91 | bool operator ==(Object other) { 92 | if (identical(this, other)) return true; 93 | 94 | return other is ConnectionFailedState && other.message == message; 95 | } 96 | 97 | @override 98 | int get hashCode => message.hashCode; 99 | } 100 | -------------------------------------------------------------------------------- /lib/features/receive/state/receive_scan_start.dart: -------------------------------------------------------------------------------- 1 | sealed class ReceieveScan { 2 | const ReceieveScan(); 3 | } 4 | 5 | class InitialReceiveScan implements ReceieveScan { 6 | const InitialReceiveScan(); 7 | } 8 | 9 | class Scanning implements ReceieveScan { 10 | const Scanning(); 11 | } 12 | 13 | class ScanError implements ReceieveScan { 14 | final String error; 15 | ScanError({ 16 | required this.error, 17 | }); 18 | 19 | @override 20 | bool operator ==(Object other) { 21 | if (identical(this, other)) return true; 22 | 23 | return other is ScanError && other.error == error; 24 | } 25 | 26 | @override 27 | int get hashCode => error.hashCode; 28 | } 29 | -------------------------------------------------------------------------------- /lib/features/receive/view/receive_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sharez/core/router/router.gr.dart'; 4 | import 'package:flutter_sharez/shared/widget/custom_app_bar.dart'; 5 | 6 | @RoutePage( 7 | deferredLoading: true, 8 | ) 9 | class ReceivePage extends StatelessWidget { 10 | const ReceivePage({super.key}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Scaffold( 15 | appBar: CustomAppBar( 16 | appActions: [ 17 | IconButton( 18 | onPressed: () { 19 | context.navigateTo(const DownloadsRoute()); 20 | }, 21 | icon: const Icon( 22 | Icons.download_outlined, 23 | ), 24 | tooltip: 'Downloads', 25 | ), 26 | IconButton( 27 | onPressed: () { 28 | context.navigateTo(const SettingsRoute()); 29 | }, 30 | icon: const Icon(Icons.settings_outlined), 31 | tooltip: 'App Settings', 32 | ), 33 | ], 34 | ), 35 | body: const AutoRouter(), 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/features/send/controller/notifier/send_state_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:flutter_sharez/core/router/router.gr.dart'; 5 | import 'package:flutter_sharez/core/router/router_pod.dart'; 6 | import 'package:flutter_sharez/data/service/sender/sender_service_pod.dart'; 7 | import 'package:flutter_sharez/features/file_selector/controller/selected_files_list_pod.dart'; 8 | import 'package:flutter_sharez/features/send/state/send_state.dart'; 9 | 10 | class SendStateNotifier extends AutoDisposeAsyncNotifier { 11 | @override 12 | FutureOr build() async { 13 | return await startServer(); 14 | } 15 | 16 | Future startServer() async { 17 | SendState mystate = const StartingServer(); 18 | 19 | final files = ref.read(selectedFilesPod); 20 | final sendService = ref.watch(senderServicePod); 21 | if (files.isNotEmpty) { 22 | final result = await sendService.startServer( 23 | onCheckServerCalled: (receivermodel) async { 24 | final Completer sendConfirmCompleter = Completer(); 25 | if (sendConfirmCompleter.isCompleted) { 26 | return false; 27 | } else { 28 | final value = await ref 29 | .read(autorouterProvider) 30 | .navigate(ConfirmConnectionDialogRoute( 31 | receiverModel: receivermodel, 32 | onCofirmation: (v) { 33 | if (!sendConfirmCompleter.isCompleted) { 34 | sendConfirmCompleter.complete(v); 35 | } 36 | }, 37 | )); 38 | if (value is bool) { 39 | return value; 40 | } 41 | return await sendConfirmCompleter.future; 42 | } 43 | }, 44 | ); 45 | result.when((success) { 46 | mystate = StartedServer(serverInfo: sendService.getServerInfo()); 47 | }, (error) { 48 | mystate = ServerError( 49 | error: 50 | "Server cannot be started due to ${error.message}. Please make sure you have connected to wifi", 51 | ); 52 | }); 53 | } else { 54 | ref.read(selectedFilesPod.notifier).resetState(); 55 | mystate = ServerError(error: 'No files Selected Yet'); 56 | } 57 | return mystate; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/features/send/controller/send_notifier_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/features/send/controller/notifier/send_state_notifier.dart'; 3 | import 'package:flutter_sharez/features/send/state/send_state.dart'; 4 | 5 | final sendStateNotifierPod = 6 | AsyncNotifierProvider.autoDispose( 7 | SendStateNotifier.new, 8 | name: 'sendStateNotifierPod', 9 | ); 10 | -------------------------------------------------------------------------------- /lib/features/send/state/send_state.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter_sharez/data/model/server_info.dart'; 4 | 5 | sealed class SendState { 6 | const SendState(); 7 | } 8 | 9 | class StartingServer implements SendState { 10 | const StartingServer(); 11 | } 12 | 13 | class StartedServer implements SendState { 14 | final ServerInfo serverInfo; 15 | const StartedServer({ 16 | required this.serverInfo, 17 | }); 18 | 19 | StartedServer copyWith({ 20 | ServerInfo? serverInfo, 21 | }) { 22 | return StartedServer( 23 | serverInfo: serverInfo ?? this.serverInfo, 24 | ); 25 | } 26 | 27 | Map toMap() { 28 | return { 29 | 'serverInfo': serverInfo.toMap(), 30 | }; 31 | } 32 | 33 | factory StartedServer.fromMap(Map map) { 34 | return StartedServer( 35 | serverInfo: ServerInfo.fromMap(map['serverInfo']), 36 | ); 37 | } 38 | 39 | String toJson() => json.encode(toMap()); 40 | 41 | factory StartedServer.fromJson(String source) => 42 | StartedServer.fromMap(json.decode(source)); 43 | 44 | @override 45 | String toString() => 'StartedServer(serverInfo: $serverInfo)'; 46 | 47 | @override 48 | bool operator ==(Object other) { 49 | if (identical(this, other)) return true; 50 | 51 | return other is StartedServer && other.serverInfo == serverInfo; 52 | } 53 | 54 | @override 55 | int get hashCode => serverInfo.hashCode; 56 | } 57 | 58 | class StoppedServer implements SendState { 59 | const StoppedServer(); 60 | } 61 | 62 | class ServerError implements SendState { 63 | final String error; 64 | ServerError({ 65 | required this.error, 66 | }); 67 | 68 | ServerError copyWith({ 69 | String? error, 70 | }) { 71 | return ServerError( 72 | error: error ?? this.error, 73 | ); 74 | } 75 | 76 | Map toMap() { 77 | return { 78 | 'error': error, 79 | }; 80 | } 81 | 82 | factory ServerError.fromMap(Map map) { 83 | return ServerError( 84 | error: map['error'] ?? '', 85 | ); 86 | } 87 | 88 | String toJson() => json.encode(toMap()); 89 | 90 | factory ServerError.fromJson(String source) => 91 | ServerError.fromMap(json.decode(source)); 92 | 93 | @override 94 | String toString() => 'ServerError(error: $error)'; 95 | 96 | @override 97 | bool operator ==(Object other) { 98 | if (identical(this, other)) return true; 99 | 100 | return other is ServerError && other.error == error; 101 | } 102 | 103 | @override 104 | int get hashCode => error.hashCode; 105 | } 106 | -------------------------------------------------------------------------------- /lib/features/send/view/send_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:auto_route/auto_route.dart'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_sharez/core/router/router.gr.dart'; 6 | 7 | import 'package:flutter_sharez/shared/widget/custom_app_bar.dart'; 8 | import 'package:flutter_sharez/translation_pod.dart'; 9 | 10 | @RoutePage( 11 | deferredLoading: true, 12 | ) 13 | class SendPage extends ConsumerWidget { 14 | const SendPage({super.key}); 15 | 16 | @override 17 | Widget build(BuildContext context, WidgetRef ref) { 18 | final t = ref.watch(translationsPod); 19 | return Scaffold( 20 | appBar: CustomAppBar( 21 | appActions: [ 22 | IconButton( 23 | onPressed: () { 24 | context.navigateTo(const DownloadsRoute()); 25 | }, 26 | icon: const Icon( 27 | Icons.download_outlined, 28 | ), 29 | tooltip: t.actionDownloads, 30 | ), 31 | IconButton( 32 | onPressed: () { 33 | context.navigateTo(const SettingsRoute()); 34 | }, 35 | icon: const Icon(Icons.settings_outlined), 36 | tooltip: t.actionSettings, 37 | ), 38 | ], 39 | ), 40 | body: const AutoRouter(), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/features/send/view/send_state_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:flutter_sharez/features/send/controller/send_notifier_pod.dart'; 6 | import 'package:flutter_sharez/features/send/state/send_state.dart'; 7 | import 'package:flutter_sharez/features/send/view/ui_state/started_server_view.dart'; 8 | import 'package:flutter_sharez/features/send/view/ui_state/starting_server_view.dart'; 9 | 10 | import 'package:flutter_sharez/shared/riverpod_ext/asynvalue_easy_when.dart'; 11 | import 'package:flutter_sharez/translation_pod.dart'; 12 | import 'package:velocity_x/velocity_x.dart'; 13 | 14 | @RoutePage( 15 | deferredLoading: true, 16 | ) 17 | class SendStatePage extends ConsumerStatefulWidget { 18 | const SendStatePage({ 19 | super.key, 20 | }); 21 | 22 | @override 23 | ConsumerState createState() => _SendStatePageState(); 24 | } 25 | 26 | class _SendStatePageState extends ConsumerState { 27 | @override 28 | Widget build(BuildContext context) { 29 | final t = ref.watch(translationsPod); 30 | final sendStateAsync = ref.watch(sendStateNotifierPod); 31 | return sendStateAsync.easyWhen( 32 | data: (sendstate) { 33 | return switch (sendstate) { 34 | StartingServer() => const StartingServerView(), 35 | StartedServer(:final serverInfo) => StartedServerView( 36 | serverInfo: serverInfo, 37 | ), 38 | StoppedServer() => t.sendStateServerStopped.text.makeCentered(), 39 | ServerError(:final error) => error.text.makeCentered().p8(), 40 | }; 41 | }, 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/features/send/view/ui_state/starting_server_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sharez/translation_pod.dart'; 4 | 5 | import 'package:velocity_x/velocity_x.dart'; 6 | 7 | class StartingServerView extends ConsumerWidget { 8 | const StartingServerView({super.key}); 9 | 10 | @override 11 | Widget build(BuildContext context, WidgetRef ref) { 12 | final t = ref.watch(translationsPod); 13 | return [ 14 | const CircularProgressIndicator.adaptive().p8(), 15 | t.settingUpServer.text.make().objectCenter(), 16 | ] 17 | .vStack( 18 | alignment: MainAxisAlignment.center, 19 | ) 20 | .safeArea(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/features/send/view/widgets/action_dialog_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:flutter_sharez/data/service/sender/sender_service_pod.dart'; 5 | 6 | import 'package:flutter_sharez/shared/helper/global_helper.dart'; 7 | import 'package:flutter_sharez/translation_pod.dart'; 8 | import 'package:velocity_x/velocity_x.dart'; 9 | 10 | @RoutePage() 11 | class StopServerActionDialogPage extends ConsumerStatefulWidget { 12 | final VoidCallback onYesClicked; 13 | const StopServerActionDialogPage({ 14 | super.key, 15 | required this.onYesClicked, 16 | }); 17 | 18 | @override 19 | ConsumerState createState() => 20 | _StopServerActionDialogState(); 21 | } 22 | 23 | class _StopServerActionDialogState 24 | extends ConsumerState with GlobalHelper { 25 | @override 26 | Widget build(BuildContext context) { 27 | final t = ref.watch(translationsPod); 28 | return AlertDialog( 29 | actionsAlignment: MainAxisAlignment.spaceAround, 30 | actions: [ 31 | ElevatedButton( 32 | onPressed: () async { 33 | await ref.read(senderServicePod).stopServer(); 34 | if (context.mounted) { 35 | Navigator.of(context).pop(); 36 | } 37 | widget.onYesClicked(); 38 | }, 39 | child: t.dialogActionYes.text.isIntrinsic.green500.bold.make(), 40 | ).p4(), 41 | ElevatedButton( 42 | onPressed: () { 43 | Navigator.of(context).pop(); 44 | completer.complete(false); 45 | }, 46 | child: t.dialogActionNo.text.isIntrinsic.red500.bold.make(), 47 | ).p4(), 48 | ], 49 | title: t.stopSharingTitle.text.center.isIntrinsic.make(), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/features/send/view/widgets/send_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/router/router.gr.dart'; 4 | import 'package:flutter_sharez/core/router/router_pod.dart'; 5 | 6 | import 'package:flutter_sharez/data/model/server_info.dart'; 7 | 8 | import 'package:flutter_sharez/shared/helper/global_helper.dart'; 9 | import 'package:flutter_sharez/translation_pod.dart'; 10 | 11 | import 'package:velocity_x/velocity_x.dart'; 12 | 13 | class SendActions extends ConsumerStatefulWidget { 14 | final ServerInfo serverInfo; 15 | const SendActions({ 16 | super.key, 17 | required this.serverInfo, 18 | }); 19 | 20 | @override 21 | ConsumerState createState() => _SendActionsState(); 22 | } 23 | 24 | class _SendActionsState extends ConsumerState with GlobalHelper { 25 | @override 26 | Widget build(BuildContext context) { 27 | final t = ref.watch(translationsPod); 28 | return Wrap( 29 | children: [ 30 | Tooltip( 31 | message: t.copyAddressTooltip, 32 | child: ElevatedButton.icon( 33 | onPressed: () async => await copyToClipBoard( 34 | text: '${widget.serverInfo.ip}:${widget.serverInfo.port}', 35 | message: t.addressCopiedMsg, 36 | ), 37 | icon: const Icon(Icons.content_copy_outlined), 38 | label: t.copyAddressTooltip.text.make(), 39 | ), 40 | ).p8(), 41 | Consumer( 42 | builder: (context, ref, child) { 43 | return ElevatedButton.icon( 44 | onPressed: () async { 45 | await ref.read(autorouterProvider).navigate( 46 | StopServerActionDialogRoute( 47 | onYesClicked: () { 48 | Navigator.pop(context); 49 | }, 50 | ), 51 | ); 52 | }, 53 | label: t.stopSharing.text.red500.bold.make(), 54 | icon: const Icon(Icons.cancel_outlined), 55 | ).p8(); 56 | }, 57 | ), 58 | ], 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/features/send/view/widgets/share_on_web.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/data/model/server_info.dart'; 4 | 5 | import 'package:flutter_sharez/shared/helper/global_helper.dart'; 6 | import 'package:flutter_sharez/translation_pod.dart'; 7 | import 'package:qr_flutter/qr_flutter.dart'; 8 | import 'package:velocity_x/velocity_x.dart'; 9 | 10 | class ShareOnWebSheet extends ConsumerStatefulWidget { 11 | final ServerInfo serverInfo; 12 | const ShareOnWebSheet({super.key, required this.serverInfo}); 13 | 14 | @override 15 | ConsumerState createState() => _ShareOnWebSheetState(); 16 | } 17 | 18 | class _ShareOnWebSheetState extends ConsumerState 19 | with GlobalHelper { 20 | @override 21 | Widget build(BuildContext context) { 22 | final t = ref.watch(translationsPod); 23 | return [ 24 | QrImageView( 25 | data: '${widget.serverInfo.ip}:${widget.serverInfo.port}/filepath/web', 26 | version: QrVersions.auto, 27 | size: context.safePercentHeight * 18, 28 | gapless: true, 29 | embeddedImageStyle: const QrEmbeddedImageStyle(size: Size(120, 120)), 30 | embeddedImage: const AssetImage( 31 | 'assets/images/logo/ic_launcher_adaptive_fore.png', 32 | ), 33 | constrainErrorBounds: true, 34 | dataModuleStyle: QrDataModuleStyle( 35 | color: context.colors.primary, 36 | ), 37 | eyeStyle: QrEyeStyle( 38 | color: context.colors.primary, 39 | ), 40 | ).p8().flexible(), 41 | t.shareWebMsg.text.xl.bold.center.make().px4(), 42 | '${widget.serverInfo.ip}:${widget.serverInfo.port}/web ' 43 | .text 44 | .extraBold 45 | .green500 46 | .lg 47 | .makeCentered() 48 | .py8(), 49 | Tooltip( 50 | message: t.copyAddressTooltip, 51 | child: ElevatedButton.icon( 52 | onPressed: () async => await copyToClipBoard( 53 | text: '${widget.serverInfo.ip}:${widget.serverInfo.port}/web ', 54 | message: t.addressCopiedMsg, 55 | ), 56 | icon: const Icon(Icons.content_copy_outlined), 57 | label: t.copyAddressTooltip.text.make(), 58 | ), 59 | ).p8(), 60 | ].vStack().whFull(context); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/features/settings/controller/current_version_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/bootstrap.dart'; 3 | import 'package:package_info_plus/package_info_plus.dart'; 4 | 5 | final currentVersionPod = FutureProvider.autoDispose((ref) async { 6 | PackageInfo packageInfo = await PackageInfo.fromPlatform(); 7 | 8 | talker.log(packageInfo.toString()); 9 | ref.keepAlive(); 10 | return "v${packageInfo.version}+${packageInfo.buildNumber}"; 11 | }); 12 | -------------------------------------------------------------------------------- /lib/features/settings/view/settings_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:auto_route/annotations.dart'; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'package:flutter_sharez/shared/widget/app_locale_popup.dart'; 7 | import 'package:flutter_sharez/translation_pod.dart'; 8 | import 'package:velocity_x/velocity_x.dart'; 9 | import 'package:flutter_sharez/features/settings/view/widget/about_app_tile.dart'; 10 | import 'package:flutter_sharez/features/theme_segmented_btn/view/theme_segmented_btn.dart'; 11 | 12 | @RoutePage( 13 | deferredLoading: true, 14 | ) 15 | class SettingsPage extends ConsumerWidget { 16 | const SettingsPage({super.key}); 17 | 18 | @override 19 | Widget build(BuildContext context, WidgetRef ref) { 20 | final t = ref.watch(translationsPod); 21 | return Scaffold( 22 | appBar: AppBar( 23 | title: t.settingsPage.text.make(), 24 | ), 25 | bottomNavigationBar: BottomSheet( 26 | onClosing: () {}, 27 | builder: (context) => const AboutAppTile(), 28 | enableDrag: false, 29 | showDragHandle: false, 30 | ).safeArea(), 31 | body: ListView( 32 | physics: const ClampingScrollPhysics(), 33 | padding: const EdgeInsets.all(8), 34 | children: [ 35 | ListTile( 36 | title: t.changeLanguage.text.bold.make(), 37 | trailing: const AppLocalePopUp(), 38 | ), 39 | ListTile( 40 | title: t.switchTheme.text.bold.make(), 41 | trailing: const ThemeSegmentedBtn(), 42 | ), 43 | ], 44 | ), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/features/splash/controller/box_encryption_key_pod.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:flutter_secure_storage_x/flutter_secure_storage_x.dart'; 6 | 7 | import 'package:hive_ce_flutter/hive_flutter.dart'; 8 | 9 | final boxEncryptionKeyPod = FutureProvider.autoDispose((ref) async { 10 | const secureStorage = FlutterSecureStorage( 11 | aOptions: AndroidOptions(), 12 | iOptions: IOSOptions( 13 | accessibility: KeychainAccessibility.first_unlock, 14 | )); 15 | 16 | const secureStorageKey = "FlutterSharez"; 17 | // if key not exists return null 18 | final encryptionKeyString = await secureStorage.read(key: secureStorageKey); 19 | 20 | if (encryptionKeyString == null) { 21 | final key = Hive.generateSecureKey(); 22 | await secureStorage.write( 23 | key: secureStorageKey, 24 | value: base64UrlEncode(key), 25 | ); 26 | } 27 | final key = await secureStorage.read(key: secureStorageKey); 28 | final encryptionKeyUint8List = base64Url.decode(key!); 29 | return encryptionKeyUint8List; 30 | }); 31 | -------------------------------------------------------------------------------- /lib/features/splash/controller/future_initializer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/i18n/strings.g.dart'; 3 | 4 | import 'package:flutter_sharez/translation_pod.dart'; 5 | 6 | import 'package:hive_ce_flutter/hive_flutter.dart'; 7 | import 'package:platform_info/platform_info.dart'; 8 | import 'package:flutter_sharez/bootstrap.dart'; 9 | import 'package:flutter_sharez/core/local_storage/app_storage_pod.dart'; 10 | import 'package:flutter_sharez/features/splash/controller/box_encryption_key_pod.dart'; 11 | import 'package:flutter_sharez/init.dart'; 12 | 13 | import 'package:talker_riverpod_logger/talker_riverpod_logger.dart'; 14 | 15 | final futureInitializerPod = 16 | FutureProvider.autoDispose((ref) async { 17 | ///Additional intial delay duration for app 18 | // await Future.delayed(const Duration(seconds: 1)); 19 | await (init()); 20 | await Hive.initFlutter(); 21 | 22 | AppLocale deviceLocale = AppLocaleUtils.findDeviceLocale(); 23 | final translations = await deviceLocale.build(); 24 | 25 | ///Replace `appBox` namw with any key you want 26 | 27 | final encryptionCipher = await Platform.I.when( 28 | mobile: () async { 29 | final encryptionKey = await ref.watch(boxEncryptionKeyPod.future); 30 | return HiveAesCipher(encryptionKey); 31 | }, 32 | ); 33 | 34 | final appBox = await Hive.openBox( 35 | 'FlutterSharezBox', 36 | encryptionCipher: encryptionCipher, 37 | ); 38 | return ProviderContainer( 39 | overrides: [ 40 | appBoxProvider.overrideWithValue(appBox), 41 | translationsPod.overrideWith( 42 | (ref) => translations, 43 | ) 44 | ], 45 | observers: [ 46 | ///Added new talker riverpod observer 47 | /// 48 | /// If you want old behaviour 49 | /// Replace with 50 | /// 51 | /// MyObserverLogger( talker: talker,) 52 | /// 53 | /// 54 | /// 55 | /// 56 | TalkerRiverpodObserver( 57 | talker: talker, 58 | settings: const TalkerRiverpodLoggerSettings( 59 | printProviderDisposed: true, 60 | ), 61 | ), 62 | ], 63 | ); 64 | }); 65 | -------------------------------------------------------------------------------- /lib/features/theme_segmented_btn/controller/selection_theme_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/theme/theme_controller.dart'; 4 | 5 | ///This provider gives initial value to theme segment button 6 | final themeSelectionPod = Provider.autoDispose>( 7 | (ref) => {ref.watch(themecontrollerProvider)}, 8 | name: "themeSelectionPod", 9 | ); 10 | -------------------------------------------------------------------------------- /lib/features/theme_segmented_btn/view/theme_segmented_btn.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/theme/theme_controller.dart'; 4 | import 'package:flutter_sharez/features/theme_segmented_btn/controller/selection_theme_pod.dart'; 5 | 6 | ///This class provider segmented button which can be used 7 | ///for getting current theme and switching theme 8 | class ThemeSegmentedBtn extends ConsumerStatefulWidget { 9 | const ThemeSegmentedBtn({super.key}); 10 | 11 | @override 12 | ConsumerState createState() => _ThemeSegmentedBtnState(); 13 | } 14 | 15 | class _ThemeSegmentedBtnState extends ConsumerState { 16 | @override 17 | Widget build(BuildContext context) { 18 | return SegmentedButton( 19 | segments: const >[ 20 | ButtonSegment( 21 | value: ThemeMode.light, 22 | icon: Icon(Icons.light_mode), 23 | ), 24 | ButtonSegment( 25 | value: ThemeMode.dark, 26 | icon: Icon(Icons.dark_mode), 27 | ), 28 | ButtonSegment( 29 | value: ThemeMode.system, 30 | icon: Icon(Icons.brightness_auto), 31 | ), 32 | ], 33 | selected: ref.watch(themeSelectionPod), 34 | onSelectionChanged: (thememodes) { 35 | ref 36 | .read(themecontrollerProvider.notifier) 37 | .changeTheme(thememodes.first); 38 | }, 39 | style: const ButtonStyle( 40 | maximumSize: WidgetStatePropertyAll(Size.fromWidth(12))), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/features/update_app_version/controller/check_update_available.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/bootstrap.dart'; 3 | import 'package:flutter_sharez/data/model/update_model.dart'; 4 | import 'package:flutter_sharez/features/settings/controller/current_version_pod.dart'; 5 | import 'package:flutter_sharez/features/update_app_version/controller/check_update_version.dart'; 6 | import 'package:flutter_sharez/shared/helper/version.dart'; 7 | 8 | final checkUpdateAvailablePod = FutureProvider.autoDispose( 9 | (ref) async { 10 | final updateModel = await ref.watch(getUpdateModelPod.future); 11 | if (updateModel == null) { 12 | return null; 13 | } 14 | final currentAppVersion = 15 | (await ref.watch(currentVersionPod.future))!.replaceFirst('v', ''); 16 | final tagname = updateModel.name.replaceFirst('v', ''); 17 | Version currentVersion = Version.parse(currentAppVersion); 18 | 19 | Version latestVersion = Version.parse(tagname); 20 | talker.debug("$currentVersion $latestVersion"); 21 | 22 | /// updatemodel when update available 23 | 24 | if (currentVersion < latestVersion) { 25 | return updateModel; 26 | } else { 27 | return null; 28 | } 29 | }, 30 | name: 'checkUpdateAvailablePod', 31 | ); 32 | -------------------------------------------------------------------------------- /lib/features/update_app_version/controller/check_update_version.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/data/model/update_model.dart'; 4 | import 'package:flutter_sharez/shared/api_client/dio/dio_client_provider.dart'; 5 | import 'package:flutter_sharez/shared/riverpod_ext/cancel_extensions.dart'; 6 | 7 | final getUpdateModelPod = FutureProvider.autoDispose( 8 | (ref) async { 9 | if (kDebugMode) { 10 | return null; 11 | } 12 | final dio = ref.watch(dioProvider( 13 | "https://api.github.com/repos/Shreemanarjun/flutter_sharez")); 14 | final result = await dio.get( 15 | '/releases/latest', 16 | cancelToken: ref.cancelToken(), 17 | ); 18 | return UpdateModel.fromMap(result.data); 19 | }, 20 | name: 'getUpdateModelPod', 21 | ); 22 | -------------------------------------------------------------------------------- /lib/features/update_app_version/controller/get_changelog_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/shared/api_client/dio/dio_client_provider.dart'; 3 | import 'package:flutter_sharez/shared/riverpod_ext/cancel_extensions.dart'; 4 | 5 | final getChangeLogPod = FutureProvider.autoDispose( 6 | (ref) async { 7 | final dio = ref.watch(dioProvider( 8 | "https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/main")); 9 | final result = await dio.get( 10 | '/CHANGELOG.md', 11 | cancelToken: ref.cancelToken(), 12 | ); 13 | if (result.statusCode == 200) { 14 | return result.data.toString(); 15 | } else { 16 | throw "Error getting changelog"; 17 | } 18 | }, 19 | name: 'getChangeLogPod', 20 | ); 21 | -------------------------------------------------------------------------------- /lib/features/update_app_version/view/update_app_version_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:flutter_sharez/core/router/router.gr.dart'; 4 | import 'package:flutter_sharez/core/router/router_pod.dart'; 5 | import 'package:flutter_sharez/features/update_app_version/controller/check_update_available.dart'; 6 | import 'package:flutter_sharez/features/update_app_version/controller/check_update_version.dart'; 7 | import 'package:flutter_sharez/features/update_app_version/view/widgets/animated_sync.dart'; 8 | import 'package:flutter_sharez/shared/riverpod_ext/asynvalue_easy_when.dart'; 9 | 10 | class UpdateAppVersionIcon extends ConsumerWidget { 11 | const UpdateAppVersionIcon({super.key}); 12 | 13 | @override 14 | Widget build(BuildContext context, WidgetRef ref) { 15 | final updateCheckAsync = ref.watch(checkUpdateAvailablePod); 16 | return updateCheckAsync.easyWhen( 17 | data: (updatemodel) { 18 | return IconButton( 19 | onPressed: () async { 20 | ref.invalidate(getUpdateModelPod); 21 | final data = await ref.read(checkUpdateAvailablePod.future); 22 | ref 23 | .read(autorouterProvider) 24 | .navigate(ChangelogRoute(updateModel: data)); 25 | }, 26 | icon: Icon( 27 | Icons.sync, 28 | color: updatemodel != null ? Colors.green : null, 29 | ), 30 | ); 31 | }, 32 | errorWidget: (error, stackTrace) => IconButton( 33 | onPressed: () async { 34 | ref.invalidate(getUpdateModelPod); 35 | final data = await ref.read(checkUpdateAvailablePod.future); 36 | ref 37 | .read(autorouterProvider) 38 | .navigate(ChangelogRoute(updateModel: data)); 39 | }, 40 | icon: const Icon( 41 | Icons.sync, 42 | color: Colors.red, 43 | )), 44 | loadingWidget: () => const SpinningIconButton( 45 | iconData: Icons.sync, 46 | ), 47 | skipLoadingOnRefresh: false, 48 | skipLoadingOnReload: false); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/features/update_app_version/view/widgets/animated_sync.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SpinningIconButton extends StatefulWidget { 4 | final IconData iconData; 5 | 6 | const SpinningIconButton({ 7 | super.key, 8 | required this.iconData, 9 | }); 10 | 11 | @override 12 | State createState() => _SpinningIconButtonState(); 13 | } 14 | 15 | class _SpinningIconButtonState extends State 16 | with SingleTickerProviderStateMixin { 17 | late final AnimationController controller; 18 | late final Animation _animation; 19 | @override 20 | void initState() { 21 | controller = 22 | AnimationController(vsync: this, duration: const Duration(seconds: 10)); 23 | _animation = CurvedAnimation( 24 | parent: controller, 25 | // Use whatever curve you would like, for more details refer to the Curves class 26 | curve: Curves.linearToEaseOut, 27 | ); 28 | controller.forward(); 29 | 30 | super.initState(); 31 | } 32 | 33 | @override 34 | void dispose() { 35 | controller.stop(); 36 | controller.dispose(); 37 | super.dispose(); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return RotationTransition( 43 | turns: _animation, 44 | child: IconButton( 45 | icon: Icon(widget.iconData), 46 | onPressed: null, 47 | )); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/init.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_displaymode/flutter_displaymode.dart'; 3 | import 'package:platform_info/platform_info.dart'; 4 | 5 | ///This function is used for setting up default orientation, 6 | ///display refresh rate, hide keyboard etc system services. 7 | Future init() async { 8 | await SystemChrome.setPreferredOrientations([ 9 | DeviceOrientation.portraitUp, 10 | DeviceOrientation.portraitDown, 11 | ]); 12 | SystemChrome.setEnabledSystemUIMode( 13 | SystemUiMode.edgeToEdge, 14 | overlays: [ 15 | SystemUiOverlay.top, 16 | ], 17 | ); 18 | await platform.when( 19 | android: FlutterDisplayMode.setHighRefreshRate, 20 | ); 21 | await SystemChannels.textInput.invokeMethod('TextInput.hide'); 22 | } 23 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | 4 | import 'package:flutter_sharez/splasher.dart'; 5 | 6 | /// This entry point should be used for production only 7 | void main() async { 8 | WidgetsFlutterBinding.ensureInitialized(); 9 | 10 | runApp( 11 | ProviderScope( 12 | child: Splasher(), 13 | ), 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /lib/main_development.dart: -------------------------------------------------------------------------------- 1 | 2 | /// This entry point should be used for development only 3 | void main() { 4 | ///You can override your environment variable in bootstrap method here for providers 5 | // bootstrap(() => const App()); 6 | } 7 | -------------------------------------------------------------------------------- /lib/main_production.dart: -------------------------------------------------------------------------------- 1 | 2 | /// This entry point should be used for production only 3 | void main() { 4 | // ///You can override your environment variable in bootstrap method here for providers 5 | // bootstrap(() => const App()); 6 | } 7 | -------------------------------------------------------------------------------- /lib/main_staging.dart: -------------------------------------------------------------------------------- 1 | 2 | /// This entry point should be used for staging only 3 | void main() { 4 | ///You can override your environment variable in bootstrap method here for providers 5 | // bootstrap(() => const App()); 6 | } 7 | -------------------------------------------------------------------------------- /lib/shared/api_client/dio/bad_certificate_fixer.dart: -------------------------------------------------------------------------------- 1 | // coverage:ignore-file 2 | 3 | import 'dart:io'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:dio/io.dart'; 6 | import 'package:flutter/foundation.dart'; 7 | 8 | ///This function used for those devices which doesnot support 9 | /// newer ssl certificate and disabled in web 10 | void fixBadCertificate({required Dio dio}) { 11 | if (!kIsWeb) { 12 | dio.httpClientAdapter = IOHttpClientAdapter( 13 | createHttpClient: () { 14 | // Don't trust any certificate just because their root cert is trusted. 15 | final HttpClient client = 16 | HttpClient(context: SecurityContext(withTrustedRoots: false)); 17 | // You can test the intermediate / root cert here. We just ignore it. 18 | client.badCertificateCallback = (cert, host, port) => true; 19 | return client; 20 | }, 21 | validateCertificate: (cert, host, port) => true, 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/shared/api_client/dio/default_api_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter_sharez/shared/api_client/dio/default_api_error_handler.dart'; 3 | 4 | // coverage:ignore-file 5 | 6 | ///This one is default interceptor which includes default api 7 | ///error handler 8 | class DefaultAPIInterceptor extends Interceptor { 9 | DefaultAPIInterceptor({ 10 | required this.dio, 11 | }); 12 | final Dio dio; 13 | @override 14 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) { 15 | print(options.uri); 16 | super.onRequest(options, handler); 17 | } 18 | 19 | @override 20 | void onError(DioException err, ErrorInterceptorHandler handler) { 21 | defaultAPIErrorHandler(err, handler, dio); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/shared/api_client/dio/default_time_response_interceptor.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: strict_raw_type 2 | // coverage:ignore-file 3 | import 'package:dio/dio.dart'; 4 | import 'package:duration/duration.dart'; 5 | import 'package:flutter_sharez/bootstrap.dart'; 6 | 7 | ///This Interceptor is used check the response time from the server for each request 8 | class TimeResponseInterceptor extends Interceptor { 9 | late Stopwatch stopwatch; 10 | 11 | @override 12 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) { 13 | stopwatch = Stopwatch()..start(); 14 | 15 | super.onRequest(options, handler); 16 | } 17 | 18 | @override 19 | void onResponse(Response response, ResponseInterceptorHandler handler) { 20 | final duration = prettyDuration( 21 | stopwatch.elapsed, 22 | tersity: DurationTersity.millisecond, 23 | ); 24 | talker.log('\x1B[34mResponse time 😇 : $duration\x1B[0m'); 25 | 26 | super.onResponse(response, handler); 27 | } 28 | 29 | @override 30 | void onError(DioException err, ErrorInterceptorHandler handler) { 31 | final duration = prettyDuration( 32 | stopwatch.elapsed, 33 | tersity: DurationTersity.millisecond, 34 | ); 35 | talker.log('\x1B[34mError Response time 😇 : $duration\x1B[0m'); 36 | 37 | super.onError(err, handler); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/shared/api_client/dio/dio_client_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:flutter_sharez/bootstrap.dart'; 6 | import 'package:flutter_sharez/shared/api_client/dio/bad_certificate_fixer.dart'; 7 | import 'package:flutter_sharez/shared/api_client/dio/default_api_interceptor.dart'; 8 | import 'package:flutter_sharez/shared/api_client/dio/default_time_response_interceptor.dart'; 9 | import 'package:flutter_sharez/shared/api_client/dio/form_data_interceptor.dart'; 10 | import 'package:talker_dio_logger/talker_dio_logger.dart'; 11 | 12 | typedef DeviceAddress = String; 13 | 14 | ///This provider dioClient with interceptors(TimeResponseInterceptor,FormDataInterceptor,TalkerDioLogger,DefaultAPIInterceptor) 15 | ///with fixing bad certificate. 16 | final dioProvider = Provider.autoDispose.family( 17 | (ref, deviceAddress) { 18 | final dio = Dio(); 19 | // ..options.receiveTimeout = 1.minutes 20 | // ..options.connectTimeout = 1.minutes; 21 | dio.options.baseUrl = deviceAddress; 22 | if (kDebugMode) { 23 | dio.interceptors.add(TimeResponseInterceptor()); 24 | dio.interceptors.add(FormDataInterceptor()); 25 | dio.interceptors.add( 26 | TalkerDioLogger( 27 | talker: talker, 28 | settings: const TalkerDioLoggerSettings( 29 | printRequestHeaders: true, 30 | printResponseHeaders: true, 31 | ), 32 | ), 33 | ); 34 | } 35 | 36 | dio.interceptors.addAll([ 37 | DefaultAPIInterceptor(dio: dio), 38 | // RetryInterceptor( 39 | // dio: dio, 40 | // logPrint: talker.log, // specify log function (optional) 41 | // // retry count (optional) 42 | // retries: 2, 43 | // retryDelays: [ 44 | // const Duration(seconds: 2), 45 | // const Duration(seconds: 4), 46 | // const Duration(seconds: 6), 47 | // ], 48 | // retryEvaluator: (error, i) { 49 | // // only retry on DioError 50 | // if (error.error is SocketException) { 51 | // // only retry on timeout error 52 | // return true; 53 | // } else { 54 | // // coverage:ignore-line 55 | // return false; 56 | // } 57 | // }, 58 | // ), 59 | ]); 60 | fixBadCertificate(dio: dio); 61 | return dio; 62 | }, 63 | name: 'dioProvider', 64 | ); 65 | -------------------------------------------------------------------------------- /lib/shared/api_client/dio/form_data_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter_sharez/bootstrap.dart'; 3 | 4 | // coverage:ignore-file 5 | 6 | ///This interceptor to print form data content of the request body 7 | class FormDataInterceptor extends Interceptor { 8 | @override 9 | void onRequest(RequestOptions options, RequestInterceptorHandler handler) { 10 | final data = options.data; 11 | 12 | if (data is FormData) { 13 | ///print form data 14 | for (final item in data.fields) { 15 | talker.log('${item.key} : ${item.value}'); 16 | } 17 | } 18 | super.onRequest(options, handler); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/shared/exception/base_exception.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_dynamic_calls 2 | 3 | import 'dart:convert'; 4 | 5 | ///This is the base class exception which can be 6 | ///used to throw with a message 7 | class BaseException implements Exception { 8 | BaseException({this.message = 'Unknown Error'}); 9 | final String message; 10 | } 11 | 12 | ///This class used to throw error from API Providers 13 | class APIException implements BaseException { 14 | final int? statusCode; 15 | final String? statusMessage; 16 | final String errorMessage; 17 | APIException({ 18 | this.statusCode, 19 | this.statusMessage, 20 | required this.errorMessage, 21 | }); 22 | 23 | APIException copyWith({ 24 | int? statusCode, 25 | String? statusMessage, 26 | String? errorMessage, 27 | }) { 28 | return APIException( 29 | statusCode: statusCode ?? this.statusCode, 30 | statusMessage: statusMessage ?? this.statusMessage, 31 | errorMessage: errorMessage ?? this.errorMessage, 32 | ); 33 | } 34 | 35 | Map toMap() { 36 | return { 37 | 'statusCode': statusCode, 38 | 'statusMessage': statusMessage, 39 | 'errorMessage': errorMessage, 40 | }; 41 | } 42 | 43 | factory APIException.fromMap(Map map) { 44 | return APIException( 45 | statusCode: map['statusCode']?.toInt(), 46 | statusMessage: map['statusMessage'], 47 | errorMessage: map['errorMessage'] ?? '', 48 | ); 49 | } 50 | 51 | String toJson() => json.encode(toMap()); 52 | 53 | factory APIException.fromJson(String source) => 54 | APIException.fromMap(json.decode(source)); 55 | 56 | @override 57 | String toString() => 58 | 'APIException(statusCode: $statusCode, statusMessage: $statusMessage, errorMessage: $errorMessage)'; 59 | 60 | @override 61 | bool operator ==(Object other) { 62 | if (identical(this, other)) return true; 63 | 64 | return other is APIException && 65 | other.statusCode == statusCode && 66 | other.statusMessage == statusMessage && 67 | other.errorMessage == errorMessage; 68 | } 69 | 70 | @override 71 | int get hashCode => 72 | statusCode.hashCode ^ statusMessage.hashCode ^ errorMessage.hashCode; 73 | 74 | @override 75 | String get message => errorMessage; 76 | } 77 | -------------------------------------------------------------------------------- /lib/shared/extension/response_success_error_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:flutter_sharez/shared/exception/base_exception.dart'; 4 | import 'package:multiple_result/multiple_result.dart'; 5 | 6 | typedef Mapper = T Function(dynamic data); 7 | 8 | extension ResponseHandler on Response { 9 | Result successErrorHandler({ 10 | required Mapper successMapper, 11 | Mapper? errorMapper, 12 | List defaultSuccessCode = const [200], 13 | }) { 14 | if (defaultSuccessCode.contains(statusCode)) { 15 | if (kDebugMode) { 16 | T successData = successMapper(data); 17 | return Result.success(successData); 18 | } else { 19 | try { 20 | T successData = successMapper(data); 21 | return Result.success(successData); 22 | } catch (e) { 23 | APIException errorData = errorMapper?.call(data) ?? 24 | APIException( 25 | statusCode: statusCode, 26 | errorMessage: 'Error parsing response data $e', 27 | ); 28 | return Result.error(errorData); 29 | } 30 | } 31 | } else { 32 | late APIException errorData; 33 | if (errorMapper != null) { 34 | errorData = errorMapper(data); 35 | } else { 36 | try { 37 | errorData = APIException.fromMap(data); 38 | } catch (e) { 39 | errorData = APIException( 40 | statusCode: statusCode, 41 | statusMessage: statusMessage, 42 | errorMessage: "Failed to get data $data", 43 | ); 44 | } 45 | } 46 | 47 | return Result.error(errorData); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/shared/helper/network_helper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter_sharez/bootstrap.dart'; 4 | import 'package:flutter_sharez/shared/exception/base_exception.dart'; 5 | import 'package:multiple_result/multiple_result.dart'; 6 | 7 | Future> getDefaultAddress() async { 8 | final ipresult = await getAllIPs(); 9 | return ipresult.when( 10 | (iplist) { 11 | if (iplist.isEmpty) { 12 | return Error(BaseException(message: "No IPs found")); 13 | } else { 14 | return Success(iplist.first); 15 | } 16 | }, 17 | (error) { 18 | return Error(error); 19 | }, 20 | ); 21 | } 22 | 23 | Future, BaseException>> getAllIPs() async { 24 | final iplist = []; 25 | try { 26 | final networkinterfaces = await NetworkInterface.list( 27 | type: InternetAddressType.IPv4, 28 | ); 29 | 30 | for (var newti in networkinterfaces) { 31 | for (var ip in newti.addresses) { 32 | talker.log(ip.address); 33 | if (ip.address.startsWith("192.168") || ip.address.startsWith("10.0")) { 34 | iplist.add(ip.address); 35 | } 36 | } 37 | } 38 | return Success(iplist); 39 | } catch (e) { 40 | return Error(BaseException(message: e.toString())); 41 | } 42 | } 43 | 44 | List getNetAddress(List ipList) { 45 | List netAdd = []; 46 | for (String ip in ipList) { 47 | var ipToList = ip.split('.'); 48 | ipToList.removeLast(); 49 | netAdd.add(ipToList.join('.')); 50 | } 51 | return netAdd; 52 | } 53 | -------------------------------------------------------------------------------- /lib/shared/helper/range_downloader.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:dio/dio.dart'; 3 | 4 | typedef ProgressCallback = void Function(double progress); 5 | typedef CompleteCallback = void Function(); 6 | 7 | Future downloadFileWithResumeAndProgress({ 8 | required Dio dio, 9 | required String url, 10 | required String savePath, 11 | required CancelToken cancelToken, 12 | required ProgressCallback onProgress, 13 | required CompleteCallback onComplete, 14 | }) async { 15 | final file = File(savePath); 16 | 17 | double receivedBytes = 0; 18 | if (await file.exists()) { 19 | receivedBytes = (await file.length()).toDouble(); 20 | } 21 | 22 | final response = await dio.head(url); 23 | final totalBytes = 24 | double.parse(response.headers.value('content-length') ?? "-1"); 25 | 26 | if (receivedBytes < totalBytes) { 27 | final options = Options( 28 | headers: {'range': 'bytes=$receivedBytes-$totalBytes'}, 29 | ); 30 | 31 | await dio.download( 32 | url, 33 | savePath, 34 | options: options, 35 | cancelToken: cancelToken, 36 | onReceiveProgress: (received, total) { 37 | if (total != -1) { 38 | double progress = received / total; 39 | if (progress <= 1) { 40 | onProgress(progress); 41 | } 42 | } 43 | }, 44 | deleteOnError: true, 45 | ); 46 | 47 | onComplete(); 48 | } else { 49 | onComplete(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/shared/pods/internet_checker_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart'; 3 | 4 | ///This stream provider class holds stream notifier 5 | final internetCheckerNotifierPod = 6 | StreamNotifierProvider.autoDispose( 7 | InternetStatusNotifier.new); 8 | 9 | /// This provider used to when to enable internet checker which 10 | /// can be overriden for default value. 11 | final enableInternetCheckerPod = Provider.autoDispose((ref) { 12 | return true; 13 | }); 14 | 15 | /// This provider used to give a instance Internet Connection Checker 16 | final internetConnectionCheckerInstancePod = 17 | Provider.autoDispose((ref) { 18 | final internetchecker = InternetConnection.createInstance( 19 | checkInterval: const Duration(seconds: 5), 20 | ); 21 | return internetchecker; 22 | }); 23 | 24 | ///This stream notifier class handles internet connection status, and changes status if needed 25 | class InternetStatusNotifier extends AutoDisposeStreamNotifier { 26 | @override 27 | Stream build() { 28 | final enabled = ref.watch(enableInternetCheckerPod); 29 | if (enabled) { 30 | final statuschange = 31 | ref.watch(internetConnectionCheckerInstancePod).onStatusChange; 32 | 33 | return statuschange.distinct(); 34 | } else { 35 | return Stream.value(InternetStatus.connected); 36 | } 37 | } 38 | 39 | void change({required InternetStatus status}) { 40 | state = AsyncValue.data(status); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/shared/pods/locale_pod.dart: -------------------------------------------------------------------------------- 1 | /* import 'package:flutter/material.dart'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | 5 | import 'package:flutter_sharez/core/local_storage/app_storage_pod.dart'; 6 | 7 | import 'package:flutter_sharez/shared/exception/base_exception.dart'; 8 | 9 | ///This Notifier class used to get current locale and change local in DB 10 | class LocaleNotifier extends AutoDisposeNotifier { 11 | final _localeBoxKey = 'locale'; 12 | 13 | @override 14 | Locale build() { 15 | final locale = ref.watch(appStorageProvider).get(key: _localeBoxKey); 16 | 17 | if (locale != null) { 18 | return AppLocalizations.supportedLocales 19 | .where((element) => element.languageCode == locale) 20 | .map((e) => Locale(e.languageCode)) 21 | .first; 22 | } else { 23 | return AppLocalizations.supportedLocales.first; 24 | } 25 | } 26 | 27 | Future changeLocale({required Locale locale}) async { 28 | final isSupported = AppLocalizations.supportedLocales.contains(locale); 29 | if (isSupported) { 30 | state = locale; 31 | await ref.read(appStorageProvider).put( 32 | key: _localeBoxKey, 33 | value: locale.languageCode, 34 | ); 35 | } else { 36 | throw BaseException(message: 'Language not supported'); 37 | } 38 | } 39 | } 40 | 41 | final localePod = NotifierProvider.autoDispose( 42 | LocaleNotifier.new, 43 | name: 'localePod', 44 | ); 45 | */ 46 | -------------------------------------------------------------------------------- /lib/shared/riverpod_ext/cache_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | 5 | ///This 6 | extension CacheExtension on Ref { 7 | KeepAliveLink cacheFor([Duration duration = const Duration(seconds: 3)]) { 8 | Timer? timer; 9 | // prevents being disposed 10 | final link = keepAlive(); 11 | 12 | // when the provider is no longer used (removed all listeners) 13 | // the timer will be started with the given cache duration 14 | // when the time expires, the link will be closed, 15 | // and the provider will dispose itself 16 | onCancel(() { 17 | timer?.cancel(); 18 | link.close(); 19 | }); 20 | 21 | /// uncomment for better caching leaking fix 22 | /// // when we recall the provider again 23 | // the timer will be canceled and the link will no longer close. 24 | // onResume(() { 25 | // timer?.cancel(); 26 | // timer = Timer(duration, link.close); 27 | // }); 28 | 29 | timer = Timer(duration, link.close); 30 | 31 | return link; 32 | } 33 | 34 | /// Refreshes the provider's value automatically at a specified interval. 35 | /// 36 | /// This method is best suited for scenarios where real-time data updates are required. 37 | void autoRefresh({required Duration duration}) { 38 | final timer = Timer.periodic(duration, (_) => invalidateSelf()); 39 | onDispose(timer.cancel); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/shared/riverpod_ext/cancel_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | 4 | extension CancelTokenExtension on Ref { 5 | /// creates a token to cancel API requests 6 | CancelToken cancelToken() { 7 | final token = CancelToken(); 8 | onCancel(token.cancel); 9 | return token; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/shared/riverpod_ext/riverpod_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | 5 | extension DebounceExtension on Ref { 6 | /// delays the execution of the code for the given duration, 7 | /// if any dependency changes during the period, 8 | /// the timer will reset and restart 9 | /// if nothing changes, the rest of the code will be executed. 10 | Future debounce([ 11 | Duration duration = const Duration(milliseconds: 350), 12 | ]) { 13 | final completer = Completer(); 14 | 15 | /// creates a timer with the given duration 16 | /// when the time expires, and the completer hasn't completed yet, complete it. 17 | /// and the debounce function lets the rest of the code executed 18 | final timer = Timer(duration, () { 19 | if (!completer.isCompleted) completer.complete(); 20 | }); 21 | 22 | /// if provider disposed and the completer hasn't completed yet 23 | /// cancel the timer and throw canceled error 24 | onDispose(() { 25 | timer.cancel(); 26 | if (!completer.isCompleted) { 27 | completer.complete(); 28 | // completer.completeError(StateError('Canceled')); 29 | } 30 | }); 31 | 32 | return completer.future; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/shared/riverpod_ext/riverpod_observer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:talker_flutter/talker_flutter.dart'; 3 | 4 | // coverage:ignore-file 5 | class MyObserverLogger extends ProviderObserver { 6 | MyObserverLogger({required this.talker}) : super(); 7 | final Talker talker; 8 | 9 | @override 10 | void didUpdateProvider( 11 | ProviderBase provider, 12 | Object? previousValue, 13 | Object? newValue, 14 | ProviderContainer container, 15 | ) { 16 | final name = provider.name != null 17 | ? '${provider.name} of Type `${provider.runtimeType}`' 18 | : {provider.runtimeType}; 19 | if (newValue is StateController) { 20 | final newv = newValue.state; 21 | final perviousv = (previousValue as StateController?)?.state; 22 | talker.log('Provider is: ' 23 | '$name \n' 24 | 'previous value: $perviousv \n' 25 | 'new value: $newv'); 26 | } else if ((newValue is AsyncValue?) && (previousValue is AsyncValue?)) { 27 | final previousAsyncValue = previousValue; 28 | if (previousAsyncValue != null) { 29 | final newv = newValue?.valueOrNull; 30 | final previousv = previousAsyncValue.valueOrNull; 31 | talker.log('Provider is: ' 32 | '$name \n' 33 | 'previous value: $previousv \n' 34 | 'new value: $newv'); 35 | } else { 36 | talker.log('Provider is: ' 37 | '$name \n' 38 | 'previous value: null \n' 39 | 'new value: ${newValue?.valueOrNull}'); 40 | } 41 | } else { 42 | talker.log('Provider is: ' 43 | '$name \n' 44 | 'previous value: $previousValue\n' 45 | 'new value: $newValue'); 46 | } 47 | super.didUpdateProvider(provider, previousValue, newValue, container); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/shared/widget/app_logo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AppLogo extends StatelessWidget { 4 | final double? height; 5 | final double? width; 6 | const AppLogo({ 7 | super.key, 8 | this.height, 9 | this.width, 10 | }); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Image.asset( 15 | 'assets/images/logo/logo_white_fg.png', 16 | height: height ?? 48, 17 | width: width ?? 48, 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/shared/widget/custom_app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:auto_route/auto_route.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sharez/shared/widget/app_logo.dart'; 4 | import 'package:velocity_x/velocity_x.dart'; 5 | 6 | class CustomAppBar extends AppBar { 7 | final Widget? appTitle; 8 | final List? appActions; 9 | CustomAppBar({super.key, this.appTitle, this.appActions}) 10 | : super( 11 | elevation: 0, 12 | leading: const AutoLeadingButton( 13 | ignorePagelessRoutes: true, 14 | showIfParentCanPop: false, 15 | ), 16 | centerTitle: true, 17 | title: [ 18 | const AppLogo().py8(), 19 | if (appTitle != null) appTitle 20 | ].aStack(), 21 | actions: [if (appActions != null) ...appActions]); 22 | } 23 | -------------------------------------------------------------------------------- /lib/shared/widget/os_logo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class OSLogo extends StatelessWidget { 4 | final String? os; 5 | const OSLogo({ 6 | super.key, 7 | required this.os, 8 | }); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | if (os == "windows") { 13 | return const ImageIcon( 14 | NetworkImage("https://img.icons8.com/fluency/48/000000/windows-10.png"), 15 | color: Colors.blue, 16 | ); 17 | } else if (os == "macos") { 18 | return const ImageIcon( 19 | NetworkImage( 20 | "https://img.icons8.com/tiny-color/64/null/mac-client--v2.png"), 21 | ); 22 | } else if (os == "linux") { 23 | return const ImageIcon( 24 | NetworkImage("https://img.icons8.com/color/48/000000/linux--v1.png"), 25 | color: Colors.yellow, 26 | ); 27 | } else if (os == "android") { 28 | return const ImageIcon( 29 | NetworkImage("https://img.icons8.com/fluency/96/000000/android-os.png"), 30 | color: Colors.green, 31 | ); 32 | } else if (os == "ios") { 33 | return const ImageIcon( 34 | NetworkImage( 35 | "https://img.icons8.com/ios-filled/50/000000/ios-logo.png"), 36 | color: Colors.black, 37 | ); 38 | } else { 39 | return const Icon(Icons.laptop); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/shared/widget/responsive_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:responsive_framework/responsive_framework.dart'; 3 | 4 | class ResponsiveBreakPointWrapper extends StatelessWidget { 5 | final Widget child; 6 | 7 | ///the initial frame 0 width and height issue is still present in the Flutter framework 8 | final Widget firstFrameWidget; 9 | 10 | const ResponsiveBreakPointWrapper({ 11 | super.key, 12 | required this.child, 13 | required this.firstFrameWidget, 14 | }); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return ResponsiveBreakpoints.builder( 19 | child: ResponsiveViewWrapper( 20 | firstFrameWidget: firstFrameWidget, 21 | child: child, 22 | ), 23 | breakpoints: [ 24 | const Breakpoint(start: 0.0, end: 480.0, name: MOBILE), 25 | const Breakpoint(start: 480.0, end: 1200.0, name: TABLET), 26 | const Breakpoint(start: 900.0, end: 1920.0, name: DESKTOP), 27 | const Breakpoint(start: 1921.0, end: double.infinity, name: '4K'), 28 | ], 29 | ); 30 | } 31 | } 32 | 33 | class ResponsiveViewWrapper extends StatefulWidget { 34 | final Widget child; 35 | 36 | ///the initial frame 0 width and height issue is still present in the Flutter framework 37 | final Widget firstFrameWidget; 38 | 39 | const ResponsiveViewWrapper({ 40 | super.key, 41 | required this.child, 42 | required this.firstFrameWidget, 43 | }); 44 | 45 | @override 46 | State createState() => _ResponsiveViewWrapperState(); 47 | } 48 | 49 | class _ResponsiveViewWrapperState extends State { 50 | late ResponsiveBreakpointsData breakpointsData; 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | breakpointsData = ResponsiveBreakpoints.of(context); 55 | if (breakpointsData.breakpoints.isEmpty) { 56 | return widget.firstFrameWidget; 57 | } else { 58 | return MaxWidthBox( 59 | maxWidth: 3840, 60 | child: ResponsiveScaledBox( 61 | width: ResponsiveValue( 62 | context, 63 | conditionalValues: [ 64 | const Condition.equals(name: MOBILE, value: 400.0), 65 | const Condition.equals(name: TABLET, value: 800.0), 66 | const Condition.equals(name: DESKTOP, value: 1800.0), 67 | const Condition.equals(name: '4K', value: 3840.0), 68 | ], 69 | ).value, 70 | child: BouncingScrollWrapper.builder( 71 | context, 72 | widget.child, 73 | dragWithMouse: true, 74 | ), 75 | ), 76 | ); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/splasher.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_sharez/app/view/app.dart'; 3 | import 'package:flutter_sharez/bootstrap.dart'; 4 | import 'package:flutter_sharez/features/splash/view/splash_view.dart'; 5 | 6 | class Splasher extends StatelessWidget { 7 | const Splasher({super.key}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return MaterialApp( 12 | debugShowCheckedModeBanner: false, 13 | theme: ThemeData(primaryColor: Colors.blue), 14 | home: SplashView( 15 | removeSpalshLoader: true, 16 | onInitialized: (container) { 17 | bootstrap( 18 | () => const App(), 19 | parent: container, 20 | ); 21 | }, 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/translation_override_map.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter_sharez/i18n/translations.g.dart'; 2 | 3 | // void overrideTrans() async { 4 | // await LocaleSettings.overrideTranslationsFromMap( 5 | // locale: AppLocale.en, 6 | // isFlatMap: false, 7 | // map: { 8 | // "actionDownloads": "Hello", 9 | // }); 10 | // print(t.action_downloads); 11 | // } 12 | -------------------------------------------------------------------------------- /lib/translation_pod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | import 'package:flutter_sharez/i18n/strings.g.dart'; 3 | 4 | final translationsPod = StateProvider( 5 | (ref) => throw UnimplementedError( 6 | "translations not overriden yet", 7 | ), 8 | name: 'translationsProvider', 9 | ); 10 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import connectivity_plus 9 | import file_selector_macos 10 | import flutter_secure_storage_x_macos 11 | import mobile_scanner 12 | import package_info_plus 13 | import path_provider_foundation 14 | import share_plus 15 | import shared_preferences_foundation 16 | import url_launcher_macos 17 | 18 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 19 | ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) 20 | FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) 21 | FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) 22 | MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin")) 23 | FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) 24 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 25 | SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) 26 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) 27 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 28 | } 29 | -------------------------------------------------------------------------------- /macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.15' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_macos_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "app_icon_16.png", 5 | "idiom": "mac", 6 | "scale": "1x", 7 | "size": "16x16" 8 | }, 9 | { 10 | "filename": "app_icon_32.png", 11 | "idiom": "mac", 12 | "scale": "2x", 13 | "size": "16x16" 14 | }, 15 | { 16 | "filename": "app_icon_32.png", 17 | "idiom": "mac", 18 | "scale": "1x", 19 | "size": "32x32" 20 | }, 21 | { 22 | "filename": "app_icon_64.png", 23 | "idiom": "mac", 24 | "scale": "2x", 25 | "size": "32x32" 26 | }, 27 | { 28 | "filename": "app_icon_128.png", 29 | "idiom": "mac", 30 | "scale": "1x", 31 | "size": "128x128" 32 | }, 33 | { 34 | "filename": "app_icon_256.png", 35 | "idiom": "mac", 36 | "scale": "2x", 37 | "size": "128x128" 38 | }, 39 | { 40 | "filename": "app_icon_256.png", 41 | "idiom": "mac", 42 | "scale": "1x", 43 | "size": "256x256" 44 | }, 45 | { 46 | "filename": "app_icon_512.png", 47 | "idiom": "mac", 48 | "scale": "2x", 49 | "size": "256x256" 50 | }, 51 | { 52 | "filename": "app_icon_512.png", 53 | "idiom": "mac", 54 | "scale": "1x", 55 | "size": "512x512" 56 | }, 57 | { 58 | "filename": "app_icon_1024.png", 59 | "idiom": "mac", 60 | "scale": "2x", 61 | "size": "512x512" 62 | } 63 | ], 64 | "info": { 65 | "author": "icons_launcher", 66 | "version": 1 67 | } 68 | } -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = flutter_sharez 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.flutterSharez 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | com.apple.security.network.client 9 | 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import FlutterMacOS 2 | import Cocoa 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_sharez 2 | description: "" 3 | version: 2.0.0+1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.0.0 <4.0.0" 8 | 9 | dependencies: 10 | ai_barcode_scanner: ^6.0.1 11 | alfred: ^1.1.1 12 | auto_route: ^9.2.2 13 | dart_jwt_token: ^0.0.3 14 | dart_mappable: ^4.3.0 15 | device_preview: ^1.2.0 16 | device_preview_screenshot: ^1.0.0 17 | dio: ^5.7.0 18 | dio_smart_retry: ^7.0.1 19 | duration: ^4.0.3 20 | file_picker: ^8.1.7 21 | file_sizes: ^1.0.6 22 | flash: ^3.1.1 23 | flex_color_scheme: ^8.0.2 24 | flutter: 25 | sdk: flutter 26 | flutter_displaymode: ^0.6.0 27 | flutter_form_builder: ^9.6.0 28 | flutter_localizations: 29 | sdk: flutter 30 | flutter_markdown: ^0.7.4+3 31 | flutter_native_splash: ^2.4.4 32 | flutter_riverpod: ^2.6.1 33 | flutter_secure_storage_x: ^10.2.2 34 | flutter_speed_dial: ^7.0.0 35 | hive_ce_flutter: ^2.2.0 36 | hive_flutter: ^1.1.0 37 | hyper_thread_downloader: ^1.0.5 38 | internet_connection_checker_plus: ^2.6.0 39 | intl: ^0.19.0 40 | lottie: ^3.3.0 41 | multiple_result: ^5.1.0 42 | network_discovery: ^1.0.0 43 | open_filex: ^4.6.0 44 | package_info_plus: ^8.1.2 45 | path: ^1.8.3 46 | path_provider: ^2.1.5 47 | permission_handler: ^11.3.1 48 | platform_info: ^5.0.0 49 | qr_flutter: ^4.1.0 50 | responsive_framework: 51 | git: https://github.com/Shreemanarjun/ResponsiveFramework.git 52 | slang: ^4.4.0 53 | slang_flutter: ^4.4.0 54 | talker_dio_logger: ^4.5.5 55 | talker_flutter: ^4.5.5 56 | talker_riverpod_logger: ^4.5.5 57 | url_launcher: ^6.3.1 58 | velocity_x: 59 | git: https://github.com/Shreemanarjun/VelocityX.git 60 | 61 | 62 | dev_dependencies: 63 | auto_route_generator: ^9.0.0 64 | build_runner: ^2.4.14 65 | custom_lint: ^0.7.0 66 | dart_mappable_builder: ^4.3.0 67 | flutter_lints: ^5.0.0 68 | flutter_test: 69 | sdk: flutter 70 | icons_launcher: ^3.0.0 71 | mocktail: ^1.0.4 72 | riverpod_lint: ^2.6.3 73 | riverpod_test: ^0.1.6 74 | slang_build_runner: ^4.4.0 75 | spot: ^0.16.0 76 | very_good_analysis: ^7.0.0 77 | 78 | 79 | 80 | 81 | 82 | 83 | flutter: 84 | uses-material-design: true 85 | assets: 86 | - assets/images/logo/ 87 | - assets/anim/ 88 | 89 | 90 | -------------------------------------------------------------------------------- /riverpod_simple_architecture.md: -------------------------------------------------------------------------------- 1 | Hello flutter_sharez! 2 | Made using riverpod_simple_architecture. -------------------------------------------------------------------------------- /screenshot/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/1.png -------------------------------------------------------------------------------- /screenshot/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/10.png -------------------------------------------------------------------------------- /screenshot/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/11.png -------------------------------------------------------------------------------- /screenshot/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/12.png -------------------------------------------------------------------------------- /screenshot/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/13.png -------------------------------------------------------------------------------- /screenshot/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/14.png -------------------------------------------------------------------------------- /screenshot/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/15.png -------------------------------------------------------------------------------- /screenshot/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/16.png -------------------------------------------------------------------------------- /screenshot/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/17.png -------------------------------------------------------------------------------- /screenshot/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/2.png -------------------------------------------------------------------------------- /screenshot/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/3.png -------------------------------------------------------------------------------- /screenshot/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/4.png -------------------------------------------------------------------------------- /screenshot/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/5.png -------------------------------------------------------------------------------- /screenshot/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/6.png -------------------------------------------------------------------------------- /screenshot/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/7.png -------------------------------------------------------------------------------- /screenshot/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/8.png -------------------------------------------------------------------------------- /screenshot/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/screenshot/9.png -------------------------------------------------------------------------------- /test/app/view/app_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:hive_ce_flutter/hive_flutter.dart'; 7 | import 'package:flutter_sharez/core/local_storage/app_storage_pod.dart'; 8 | import 'package:flutter_sharez/features/counter/counter.dart'; 9 | import 'package:flutter_sharez/shared/pods/internet_checker_pod.dart'; 10 | 11 | import '../../helpers/pump_app.dart'; 12 | 13 | Future main() async { 14 | TestWidgetsFlutterBinding.ensureInitialized(); 15 | late Box appBox; 16 | setUp(() async { 17 | appBox = await Hive.openBox('appBox', bytes: Uint8List(0)); 18 | }); 19 | tearDown(() { 20 | appBox.clear(); 21 | }); 22 | group('App', () { 23 | testWidgets('renders CounterPage', (tester) async { 24 | await tester.pumpApp( 25 | ProviderScope( 26 | overrides: [ 27 | enableInternetCheckerPod.overrideWith( 28 | (ref) => false, 29 | ), 30 | appBoxProvider.overrideWithValue(appBox), 31 | ], 32 | child: const CounterPage(), 33 | ), 34 | ); 35 | expect(find.byType(CounterPage), findsOneWidget); 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /test/features/counter/pod/counter_pod_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:flutter_sharez/features/counter/counter.dart'; 3 | import 'package:riverpod_test/riverpod_test.dart'; 4 | 5 | abstract class MyAbstract {} 6 | 7 | class AbstractwithconstConstructor implements MyAbstract { 8 | const AbstractwithconstConstructor(); 9 | } 10 | 11 | class NOConstAbstract implements MyAbstract {} 12 | 13 | void main() { 14 | group('CounterNotifier', () { 15 | testNotifier( 16 | 'initial state is 0', 17 | provider: counterPod, 18 | expect: () => [0], 19 | emitBuildStates: true, 20 | ); 21 | testNotifier( 22 | 'initial state is 1', 23 | overrides: [intialCounterValuePod.overrideWithValue(1)], 24 | provider: counterPod, 25 | expect: () => [1], 26 | emitBuildStates: true, 27 | ); 28 | testNotifier( 29 | 'emits [0] on start then [1] when increment is called', 30 | provider: counterPod, 31 | expect: () => [0, 1], 32 | emitBuildStates: true, 33 | act: (notifier) => notifier.increment(), 34 | ); 35 | testNotifier( 36 | 'emits [1] when increment is called', 37 | provider: counterPod, 38 | expect: () => [1], 39 | act: (notifier) => notifier.increment(), 40 | ); 41 | testNotifier( 42 | 'emits [0] on start then [-1] when increment is called', 43 | provider: counterPod, 44 | expect: () => [0, -1], 45 | emitBuildStates: true, 46 | act: (notifier) => notifier.decrement(), 47 | ); 48 | testNotifier( 49 | 'emits [-1] when decrement is called', 50 | provider: counterPod, 51 | expect: () => [-1], 52 | act: (notifier) => notifier.decrement(), 53 | ); 54 | testNotifier( 55 | 'expect [2] when increment is called twice', 56 | provider: counterPod, 57 | act: (notifier) => notifier 58 | ..increment() 59 | ..increment(), 60 | skip: 1, 61 | expect: () => [2], 62 | ); 63 | 64 | test('with const', () { 65 | expect( 66 | const AbstractwithconstConstructor(), 67 | const AbstractwithconstConstructor(), 68 | ); 69 | }); 70 | test('without const', () { 71 | expect( 72 | NOConstAbstract(), 73 | isNot(equals(NOConstAbstract())), 74 | ); 75 | }); 76 | }); 77 | } 78 | -------------------------------------------------------------------------------- /test/helpers/helpers.dart: -------------------------------------------------------------------------------- 1 | export 'pump_app.dart'; 2 | -------------------------------------------------------------------------------- /test/helpers/pump_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | extension PumpApp on WidgetTester { 5 | Future pumpApp(Widget widget) { 6 | return pumpWidget( 7 | MaterialApp( 8 | debugShowCheckedModeBanner: false, 9 | //localizationsDelegates: AppLocalizations.localizationsDelegates, 10 | // supportedLocales: AppLocalizations.supportedLocales, 11 | home: widget, 12 | ), 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/init_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | import 'package:flutter_sharez/init.dart'; 5 | 6 | Future main() async { 7 | group( 8 | 'check init is working ', 9 | () { 10 | testWidgets('It should be in the landscape view', (tester) async { 11 | final widget = OrientationBuilder( 12 | builder: (context, orientation) { 13 | return Text(orientation.name); 14 | }, 15 | ); 16 | 17 | final logs = []; 18 | 19 | tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( 20 | SystemChannels.platform, (methodCall) async { 21 | if (methodCall.method == 'SystemChrome.setPreferredOrientations') { 22 | logs.add((methodCall.arguments as List)[0]); 23 | } 24 | return null; 25 | }); 26 | 27 | expect(logs.length, 0); 28 | 29 | await tester.pumpWidget( 30 | MaterialApp( 31 | home: widget, 32 | ), 33 | ); 34 | await init(); 35 | 36 | expect(logs.length, 1, 37 | reason: 'It should have pushed a log after the initState'); 38 | expect(logs.first, 'DeviceOrientation.portraitUp', 39 | reason: 'It should be in the landscape view after the initState'); 40 | }); 41 | }, 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /test/shared/api_client/dio/dio_client_provider_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/io.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:flutter_sharez/shared/api_client/dio/default_api_interceptor.dart'; 4 | import 'package:flutter_sharez/shared/api_client/dio/default_time_response_interceptor.dart'; 5 | import 'package:flutter_sharez/shared/api_client/dio/dio_client_provider.dart'; 6 | import 'package:flutter_sharez/shared/api_client/dio/form_data_interceptor.dart'; 7 | import 'package:riverpod_test/riverpod_test.dart'; 8 | import 'package:talker_dio_logger/talker_dio_logger.dart'; 9 | 10 | void main() { 11 | testProvider( 12 | 'expect dio.baseUrl should be "https://randomuser.me/api/"', 13 | provider: dioProvider("https://randomuser.me/api/"), 14 | expect: () => [ 15 | isA() 16 | .having( 17 | (d) => d.options.baseUrl, 18 | 'default interceptor should be 2', 19 | equals("https://randomuser.me/api/"), 20 | ) 21 | .having( 22 | (d) => d.interceptors.length, 23 | "Interceptors should be 5", 24 | equals(5), 25 | ) 26 | .having( 27 | (d) => d.interceptors, 28 | "Contains a time response interceptor", 29 | containsAll( 30 | [ 31 | isA(), 32 | isA(), 33 | isA(), 34 | isA(), 35 | ], 36 | )), 37 | ], 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /test/shared/pods/locale_pod_test.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:ui'; 2 | 3 | // import 'package:flutter_test/flutter_test.dart'; 4 | // import 'package:flutter_sharez/core/local_storage/app_storage.dart'; 5 | // import 'package:flutter_sharez/core/local_storage/app_storage_pod.dart'; 6 | // import 'package:flutter_sharez/shared/exception/base_exception.dart'; 7 | // import 'package:flutter_sharez/shared/pods/locale_pod.dart'; 8 | // import 'package:riverpod_test/riverpod_test.dart'; 9 | 10 | // void main() { 11 | // group( 12 | // 'Locale Pod Test', 13 | // () { 14 | // AppStorage appStorage = AppStorage(null); 15 | // setUp(() async { 16 | // await appStorage.init(isTest: true); 17 | // }); 18 | // tearDown(() async { 19 | // await appStorage.clearAllData(); 20 | // }); 21 | 22 | // testNotifier( 23 | // "check default locale should be English", 24 | // provider: localePod, 25 | // overrides: [ 26 | // appStorageProvider.overrideWithValue(appStorage), 27 | // ], 28 | // emitBuildStates: true, 29 | // expect: () => [ 30 | // const Locale.fromSubtags(languageCode: 'en'), 31 | // ], 32 | // ); 33 | // testNotifier( 34 | // "check default locale should be English and after change it should be Arabic", 35 | // provider: localePod, 36 | // overrides: [ 37 | // appStorageProvider.overrideWithValue(appStorage), 38 | // ], 39 | // emitBuildStates: true, 40 | // act: (notifier) async => await notifier.changeLocale( 41 | // locale: const Locale.fromSubtags(languageCode: 'es')), 42 | // expect: () => [ 43 | // const Locale.fromSubtags(languageCode: 'en'), 44 | // const Locale.fromSubtags(languageCode: 'es'), 45 | // ], 46 | // ); 47 | // testNotifier( 48 | // "check default locale should be English and after change it to Spanish,it should throw as it not supported", 49 | // provider: localePod, 50 | // overrides: [ 51 | // appStorageProvider.overrideWithValue(appStorage), 52 | // ], 53 | // emitBuildStates: true, 54 | // act: (notifier) async => await notifier.changeLocale( 55 | // locale: const Locale.fromSubtags(languageCode: 'ar')), 56 | // errors: () => [ 57 | // isA().having( 58 | // (s) => s.message, 59 | // 'error message', 60 | // contains('Language not supported'), 61 | // ), 62 | // ], 63 | // ); 64 | // }, 65 | // ); 66 | // } 67 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | void main() {} 2 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_sharez", 3 | "short_name": "flutter_sharez", 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 | -------------------------------------------------------------------------------- /web/splash/img/dark-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/dark-1x.png -------------------------------------------------------------------------------- /web/splash/img/dark-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/dark-2x.png -------------------------------------------------------------------------------- /web/splash/img/dark-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/dark-3x.png -------------------------------------------------------------------------------- /web/splash/img/dark-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/dark-4x.png -------------------------------------------------------------------------------- /web/splash/img/light-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/light-1x.png -------------------------------------------------------------------------------- /web/splash/img/light-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/light-2x.png -------------------------------------------------------------------------------- /web/splash/img/light-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/light-3x.png -------------------------------------------------------------------------------- /web/splash/img/light-4x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/light-4x.png -------------------------------------------------------------------------------- /web/splash/img/light-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shreemanarjun/flutter_sharez/a82c03912fdd7c55ef66d284b149c8cfa336c525/web/splash/img/light-background.png --------------------------------------------------------------------------------