├── .gitignore ├── .metadata ├── CODE_OF_CONDUCT.md ├── README.md ├── SECURITY.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── io │ │ │ │ └── flutter │ │ │ │ └── app │ │ │ │ └── FlutterMultiDexApplication.java │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── rightdevs │ │ │ │ └── status_saver │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── 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 ├── l10n.yaml ├── lib ├── main.dart └── src │ ├── common │ ├── constants │ │ └── directory_paths.dart │ ├── extensions │ │ ├── async_value.dart │ │ └── permission_handler.dart │ ├── helpers │ │ ├── android_api_level_helper.dart │ │ ├── get_video_thumbnail.dart │ │ ├── show_toast.dart │ │ ├── statuses_helper.dart │ │ └── storage_helper.dart │ └── views │ │ ├── circular_loader.dart │ │ └── common_error_screen.dart │ ├── debug │ ├── console_log.dart │ └── red_container.dart │ ├── home │ ├── models │ │ ├── android_info.dart │ │ ├── tab_type.dart │ │ └── whatsapp_type_enum.dart │ ├── notifiers │ │ └── selected_tab_index_notifier.dart │ ├── services │ │ ├── android_info_notifier.dart │ │ └── whatsapp_type_notifier.dart │ └── views │ │ ├── home_screen.dart │ │ └── my_drawer.dart │ ├── localization │ ├── enums │ │ └── language_code.dart │ ├── extensions │ │ ├── on_build_context.dart │ │ └── on_string.dart │ ├── l10n │ │ ├── app_af.arb │ │ ├── app_ar.arb │ │ ├── app_az.arb │ │ ├── app_bn.arb │ │ ├── app_en.arb │ │ ├── app_es.arb │ │ ├── app_gu.arb │ │ ├── app_hi.arb │ │ ├── app_ja.arb │ │ ├── app_kn.arb │ │ ├── app_ko.arb │ │ ├── app_mr.arb │ │ ├── app_pa.arb │ │ ├── app_ta.arb │ │ ├── app_te.arb │ │ ├── app_ur.arb │ │ └── l10n.dart │ └── notifiers │ │ └── locale_notifier.dart │ ├── statuses │ ├── notifiers │ │ └── statuses_notifier.dart │ └── views │ │ ├── image_tile.dart │ │ ├── image_view.dart │ │ ├── status_actions.dart │ │ ├── statuses_grid_widget.dart │ │ ├── statuses_screen.dart │ │ ├── video_tile.dart │ │ └── video_view.dart │ ├── storage_permission │ ├── notifiers │ │ └── storage_permission_notifier.dart │ └── views │ │ └── give_permissions_screen.dart │ └── theme │ ├── app_theme.dart │ ├── colors.dart │ └── notifiers │ └── theme_mode_notifier.dart ├── pubspec.lock ├── pubspec.yaml └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | -------------------------------------------------------------------------------- /.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: "ba393198430278b6595976de84fe170f553cc728" 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: ba393198430278b6595976de84fe170f553cc728 17 | base_revision: ba393198430278b6595976de84fe170f553cc728 18 | - platform: android 19 | create_revision: ba393198430278b6595976de84fe170f553cc728 20 | base_revision: ba393198430278b6595976de84fe170f553cc728 21 | - platform: ios 22 | create_revision: ba393198430278b6595976de84fe170f553cc728 23 | base_revision: ba393198430278b6595976de84fe170f553cc728 24 | - platform: linux 25 | create_revision: ba393198430278b6595976de84fe170f553cc728 26 | base_revision: ba393198430278b6595976de84fe170f553cc728 27 | - platform: macos 28 | create_revision: ba393198430278b6595976de84fe170f553cc728 29 | base_revision: ba393198430278b6595976de84fe170f553cc728 30 | - platform: web 31 | create_revision: ba393198430278b6595976de84fe170f553cc728 32 | base_revision: ba393198430278b6595976de84fe170f553cc728 33 | - platform: windows 34 | create_revision: ba393198430278b6595976de84fe170f553cc728 35 | base_revision: ba393198430278b6595976de84fe170f553cc728 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | We, as contributors and maintainers of the Status Saver project, pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 4 | 5 | ## Our Standards 6 | 7 | Examples of behavior that contributes to creating a positive environment include: 8 | 9 | - **Being respectful**: Disagreements happen all the time. You should focus on the issue, not the person. 10 | - **Being inclusive**: Everyone is welcome, regardless of their background. 11 | - **Being understanding**: Not everyone will agree with your decisions, but try to understand different perspectives. 12 | - **Being patient**: Processes may take time. Be patient and give people the time to voice their opinions. 13 | 14 | Examples of unacceptable behavior by participants include: 15 | 16 | - **The use of sexualized language or imagery** 17 | - **Personal attacks** 18 | - **Trolling or insulting/derogatory comments** 19 | - **Public or private harassment** 20 | - **Publishing others' private information, such as physical or electronic addresses, without explicit permission** 21 | - **Other unethical or unprofessional conduct** 22 | 23 | ## Responsibilities 24 | 25 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 26 | 27 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 28 | 29 | ## Scope 30 | 31 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 32 | 33 | ## Enforcement 34 | 35 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [geekforgeeks222@gmail.com](mailto:geekforgeeks222@gmail.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 36 | 37 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership. 38 | 39 | ## Attribution 40 | 41 | This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at [https://www.contributor-covenant.org/version/1/4](https://www.contributor-covenant.org/version/1/4/) 42 | 43 | For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WhatsApp Status Saver 2 | 3 | A WhatsApp status saver Flutter project. 4 | 5 | ## Features 6 | * View Recent statuses from WhatsApp & WhatsApp Business. 7 | * Share statuses without saving. 8 | * Save statuses to Gallary 9 | * Material3 UI 10 | 11 | ## Contributing 12 | 13 | Contributions are welcome! 14 | 15 | Here is a curated list of how you can help: 16 | 17 | - Report bugs and scenarios that are difficult to implement 18 | - Fix typos/grammar mistakes 19 | - Implement new features by making a pull-request 20 | 21 | If you find this project useful, please consider giving it a ⭐. Your support is much appreciated! 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Security Issue 4 | 5 | If you discover a security issue in Status Saver, please report it by sending an email to [geekforgeeks222@gmail.com](mailto:geekforgeeks222@gmail.com). We will promptly address the issue and keep you informed of our progress. 6 | 7 | Please do not disclose security-related issues publicly until we have had a chance to address them. 8 | 9 | ## Supported Versions 10 | 11 | These versions of Status Saver are currently being supported with security updates: 12 | 13 | - Version 1.0.0 and above 14 | 15 | ## Vulnerability Disclosure Policy 16 | 17 | We encourage responsible disclosure of security vulnerabilities. If you have discovered a vulnerability, we kindly request that you: 18 | 19 | - Email your findings to [geekforgeeks222@gmail.com](mailto:geekforgeeks222@example.com) 20 | - Do not publicize the issue until we have addressed it 21 | - Provide sufficient information to help us understand and reproduce the problem 22 | 23 | ## Guidelines for Reporting a Security Issue 24 | 25 | When reporting a security issue, please provide the following details: 26 | 27 | - Your name and affiliation (if applicable) 28 | - A description of the security issue 29 | - Steps to reproduce the issue 30 | - Any proof-of-concept or exploit code (if possible) 31 | - Your contact information, so we can reach out for further discussion 32 | 33 | ## Security Response Process 34 | 35 | Once we receive your report, we will acknowledge the receipt of the report and begin investigating the issue. We will keep you updated on our progress and let you know when the issue has been resolved. 36 | 37 | ## Responsible Disclosure 38 | 39 | We ask that you do not attempt to compromise the security of our services or systems. Please act in good faith towards our users' privacy and data during your research. 40 | 41 | Thank you for helping to improve the security of Status Saver! 42 | 43 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | 30 | analyzer: 31 | plugins: 32 | - custom_lint -------------------------------------------------------------------------------- /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 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.rightdevs.status_saver" 27 | compileSdk flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.rightdevs.status_saver" 46 | // You can update the following values to match your application needs. 47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 48 | minSdkVersion flutter.minSdkVersion 49 | targetSdkVersion flutter.targetSdkVersion 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | } 53 | 54 | buildTypes { 55 | release { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies { 68 | implementation 'com.android.support:multidex:1.0.3' 69 | implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")) 70 | } 71 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 20 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/app/FlutterMultiDexApplication.java: -------------------------------------------------------------------------------- 1 | // Generated file. 2 | // 3 | // If you wish to remove Flutter's multidex support, delete this entire file. 4 | // 5 | // Modifications to this file should be done in a copy under a different name 6 | // as this file may be regenerated. 7 | 8 | package io.flutter.app; 9 | 10 | import android.app.Application; 11 | import android.content.Context; 12 | import androidx.annotation.CallSuper; 13 | import androidx.multidex.MultiDex; 14 | 15 | /** 16 | * Extension of {@link android.app.Application}, adding multidex support. 17 | */ 18 | public class FlutterMultiDexApplication extends Application { 19 | @Override 20 | @CallSuper 21 | protected void attachBaseContext(Context base) { 22 | super.attachBaseContext(base); 23 | MultiDex.install(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/rightdevs/status_saver/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.rightdevs.status_saver 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /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-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | } 19 | 20 | plugins { 21 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 22 | id "com.android.application" version "7.3.0" apply false 23 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 24 | } 25 | 26 | include ":app" 27 | -------------------------------------------------------------------------------- /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.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 25 | remoteInfo = Runner; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 2147483647; 33 | dstPath = ""; 34 | dstSubfolderSpec = 10; 35 | files = ( 36 | ); 37 | name = "Embed Frameworks"; 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXCopyFilesBuildPhase section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 44 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 45 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 46 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 48 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 49 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 50 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 51 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 52 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 75 | ); 76 | path = RunnerTests; 77 | sourceTree = ""; 78 | }; 79 | 9740EEB11CF90186004384FC /* Flutter */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 83 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 84 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 85 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 86 | ); 87 | name = Flutter; 88 | sourceTree = ""; 89 | }; 90 | 97C146E51CF9000F007C117D = { 91 | isa = PBXGroup; 92 | children = ( 93 | 9740EEB11CF90186004384FC /* Flutter */, 94 | 97C146F01CF9000F007C117D /* Runner */, 95 | 97C146EF1CF9000F007C117D /* Products */, 96 | 331C8082294A63A400263BE5 /* RunnerTests */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 97C146EF1CF9000F007C117D /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 97C146EE1CF9000F007C117D /* Runner.app */, 104 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | 97C146F01CF9000F007C117D /* Runner */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 113 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 114 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 115 | 97C147021CF9000F007C117D /* Info.plist */, 116 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 117 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 118 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 119 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 120 | ); 121 | path = Runner; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 130 | buildPhases = ( 131 | 331C807D294A63A400263BE5 /* Sources */, 132 | 331C807F294A63A400263BE5 /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 138 | ); 139 | name = RunnerTests; 140 | productName = RunnerTests; 141 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 142 | productType = "com.apple.product-type.bundle.unit-test"; 143 | }; 144 | 97C146ED1CF9000F007C117D /* Runner */ = { 145 | isa = PBXNativeTarget; 146 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 147 | buildPhases = ( 148 | 9740EEB61CF901F6004384FC /* Run Script */, 149 | 97C146EA1CF9000F007C117D /* Sources */, 150 | 97C146EB1CF9000F007C117D /* Frameworks */, 151 | 97C146EC1CF9000F007C117D /* Resources */, 152 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 153 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = Runner; 160 | productName = Runner; 161 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | 97C146E61CF9000F007C117D /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | BuildIndependentTargetsInParallel = YES; 171 | LastUpgradeCheck = 1510; 172 | ORGANIZATIONNAME = ""; 173 | TargetAttributes = { 174 | 331C8080294A63A400263BE5 = { 175 | CreatedOnToolsVersion = 14.0; 176 | TestTargetID = 97C146ED1CF9000F007C117D; 177 | }; 178 | 97C146ED1CF9000F007C117D = { 179 | CreatedOnToolsVersion = 7.3.1; 180 | LastSwiftMigration = 1100; 181 | }; 182 | }; 183 | }; 184 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 185 | compatibilityVersion = "Xcode 9.3"; 186 | developmentRegion = en; 187 | hasScannedForEncodings = 0; 188 | knownRegions = ( 189 | en, 190 | Base, 191 | ); 192 | mainGroup = 97C146E51CF9000F007C117D; 193 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 97C146ED1CF9000F007C117D /* Runner */, 198 | 331C8080294A63A400263BE5 /* RunnerTests */, 199 | ); 200 | }; 201 | /* End PBXProject section */ 202 | 203 | /* Begin PBXResourcesBuildPhase section */ 204 | 331C807F294A63A400263BE5 /* Resources */ = { 205 | isa = PBXResourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | 97C146EC1CF9000F007C117D /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 216 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 217 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 218 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | }; 222 | /* End PBXResourcesBuildPhase section */ 223 | 224 | /* Begin PBXShellScriptBuildPhase section */ 225 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 226 | isa = PBXShellScriptBuildPhase; 227 | alwaysOutOfDate = 1; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | ); 231 | inputPaths = ( 232 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 233 | ); 234 | name = "Thin Binary"; 235 | outputPaths = ( 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | shellPath = /bin/sh; 239 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 240 | }; 241 | 9740EEB61CF901F6004384FC /* Run Script */ = { 242 | isa = PBXShellScriptBuildPhase; 243 | alwaysOutOfDate = 1; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | ); 247 | inputPaths = ( 248 | ); 249 | name = "Run Script"; 250 | outputPaths = ( 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | shellPath = /bin/sh; 254 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 255 | }; 256 | /* End PBXShellScriptBuildPhase section */ 257 | 258 | /* Begin PBXSourcesBuildPhase section */ 259 | 331C807D294A63A400263BE5 /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | }; 267 | 97C146EA1CF9000F007C117D /* Sources */ = { 268 | isa = PBXSourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 272 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | /* End PBXSourcesBuildPhase section */ 277 | 278 | /* Begin PBXTargetDependency section */ 279 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 280 | isa = PBXTargetDependency; 281 | target = 97C146ED1CF9000F007C117D /* Runner */; 282 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 283 | }; 284 | /* End PBXTargetDependency section */ 285 | 286 | /* Begin PBXVariantGroup section */ 287 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 288 | isa = PBXVariantGroup; 289 | children = ( 290 | 97C146FB1CF9000F007C117D /* Base */, 291 | ); 292 | name = Main.storyboard; 293 | sourceTree = ""; 294 | }; 295 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | 97C147001CF9000F007C117D /* Base */, 299 | ); 300 | name = LaunchScreen.storyboard; 301 | sourceTree = ""; 302 | }; 303 | /* End PBXVariantGroup section */ 304 | 305 | /* Begin XCBuildConfiguration section */ 306 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 311 | CLANG_ANALYZER_NONNULL = YES; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_COMMA = YES; 319 | CLANG_WARN_CONSTANT_CONVERSION = YES; 320 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 331 | CLANG_WARN_STRICT_PROTOTYPES = YES; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 341 | GCC_C_LANGUAGE_STANDARD = gnu99; 342 | GCC_NO_COMMON_BLOCKS = YES; 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 350 | MTL_ENABLE_DEBUG_INFO = NO; 351 | SDKROOT = iphoneos; 352 | SUPPORTED_PLATFORMS = iphoneos; 353 | TARGETED_DEVICE_FAMILY = "1,2"; 354 | VALIDATE_PRODUCT = YES; 355 | }; 356 | name = Profile; 357 | }; 358 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 359 | isa = XCBuildConfiguration; 360 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | CLANG_ENABLE_MODULES = YES; 364 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 365 | DEVELOPMENT_TEAM = 54K3FT3CBT; 366 | ENABLE_BITCODE = NO; 367 | INFOPLIST_FILE = Runner/Info.plist; 368 | LD_RUNPATH_SEARCH_PATHS = ( 369 | "$(inherited)", 370 | "@executable_path/Frameworks", 371 | ); 372 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver; 373 | PRODUCT_NAME = "$(TARGET_NAME)"; 374 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 375 | SWIFT_VERSION = 5.0; 376 | VERSIONING_SYSTEM = "apple-generic"; 377 | }; 378 | name = Profile; 379 | }; 380 | 331C8088294A63A400263BE5 /* Debug */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | BUNDLE_LOADER = "$(TEST_HOST)"; 384 | CODE_SIGN_STYLE = Automatic; 385 | CURRENT_PROJECT_VERSION = 1; 386 | GENERATE_INFOPLIST_FILE = YES; 387 | MARKETING_VERSION = 1.0; 388 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver.RunnerTests; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 391 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 392 | SWIFT_VERSION = 5.0; 393 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 394 | }; 395 | name = Debug; 396 | }; 397 | 331C8089294A63A400263BE5 /* Release */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | BUNDLE_LOADER = "$(TEST_HOST)"; 401 | CODE_SIGN_STYLE = Automatic; 402 | CURRENT_PROJECT_VERSION = 1; 403 | GENERATE_INFOPLIST_FILE = YES; 404 | MARKETING_VERSION = 1.0; 405 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver.RunnerTests; 406 | PRODUCT_NAME = "$(TARGET_NAME)"; 407 | SWIFT_VERSION = 5.0; 408 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 409 | }; 410 | name = Release; 411 | }; 412 | 331C808A294A63A400263BE5 /* Profile */ = { 413 | isa = XCBuildConfiguration; 414 | buildSettings = { 415 | BUNDLE_LOADER = "$(TEST_HOST)"; 416 | CODE_SIGN_STYLE = Automatic; 417 | CURRENT_PROJECT_VERSION = 1; 418 | GENERATE_INFOPLIST_FILE = YES; 419 | MARKETING_VERSION = 1.0; 420 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver.RunnerTests; 421 | PRODUCT_NAME = "$(TARGET_NAME)"; 422 | SWIFT_VERSION = 5.0; 423 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 424 | }; 425 | name = Profile; 426 | }; 427 | 97C147031CF9000F007C117D /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 432 | CLANG_ANALYZER_NONNULL = YES; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_COMMA = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 443 | CLANG_WARN_EMPTY_BODY = YES; 444 | CLANG_WARN_ENUM_CONVERSION = YES; 445 | CLANG_WARN_INFINITE_RECURSION = YES; 446 | CLANG_WARN_INT_CONVERSION = YES; 447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 448 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 449 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 451 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 452 | CLANG_WARN_STRICT_PROTOTYPES = YES; 453 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 454 | CLANG_WARN_UNREACHABLE_CODE = YES; 455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 457 | COPY_PHASE_STRIP = NO; 458 | DEBUG_INFORMATION_FORMAT = dwarf; 459 | ENABLE_STRICT_OBJC_MSGSEND = YES; 460 | ENABLE_TESTABILITY = YES; 461 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 462 | GCC_C_LANGUAGE_STANDARD = gnu99; 463 | GCC_DYNAMIC_NO_PIC = NO; 464 | GCC_NO_COMMON_BLOCKS = YES; 465 | GCC_OPTIMIZATION_LEVEL = 0; 466 | GCC_PREPROCESSOR_DEFINITIONS = ( 467 | "DEBUG=1", 468 | "$(inherited)", 469 | ); 470 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 471 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 472 | GCC_WARN_UNDECLARED_SELECTOR = YES; 473 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 474 | GCC_WARN_UNUSED_FUNCTION = YES; 475 | GCC_WARN_UNUSED_VARIABLE = YES; 476 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 477 | MTL_ENABLE_DEBUG_INFO = YES; 478 | ONLY_ACTIVE_ARCH = YES; 479 | SDKROOT = iphoneos; 480 | TARGETED_DEVICE_FAMILY = "1,2"; 481 | }; 482 | name = Debug; 483 | }; 484 | 97C147041CF9000F007C117D /* Release */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ALWAYS_SEARCH_USER_PATHS = NO; 488 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 489 | CLANG_ANALYZER_NONNULL = YES; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 495 | CLANG_WARN_BOOL_CONVERSION = YES; 496 | CLANG_WARN_COMMA = YES; 497 | CLANG_WARN_CONSTANT_CONVERSION = YES; 498 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 499 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 500 | CLANG_WARN_EMPTY_BODY = YES; 501 | CLANG_WARN_ENUM_CONVERSION = YES; 502 | CLANG_WARN_INFINITE_RECURSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 505 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 506 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 508 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 509 | CLANG_WARN_STRICT_PROTOTYPES = YES; 510 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 511 | CLANG_WARN_UNREACHABLE_CODE = YES; 512 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 513 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 514 | COPY_PHASE_STRIP = NO; 515 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 516 | ENABLE_NS_ASSERTIONS = NO; 517 | ENABLE_STRICT_OBJC_MSGSEND = YES; 518 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 519 | GCC_C_LANGUAGE_STANDARD = gnu99; 520 | GCC_NO_COMMON_BLOCKS = YES; 521 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 522 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 523 | GCC_WARN_UNDECLARED_SELECTOR = YES; 524 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 525 | GCC_WARN_UNUSED_FUNCTION = YES; 526 | GCC_WARN_UNUSED_VARIABLE = YES; 527 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 528 | MTL_ENABLE_DEBUG_INFO = NO; 529 | SDKROOT = iphoneos; 530 | SUPPORTED_PLATFORMS = iphoneos; 531 | SWIFT_COMPILATION_MODE = wholemodule; 532 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 533 | TARGETED_DEVICE_FAMILY = "1,2"; 534 | VALIDATE_PRODUCT = YES; 535 | }; 536 | name = Release; 537 | }; 538 | 97C147061CF9000F007C117D /* Debug */ = { 539 | isa = XCBuildConfiguration; 540 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 541 | buildSettings = { 542 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 543 | CLANG_ENABLE_MODULES = YES; 544 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 545 | DEVELOPMENT_TEAM = 54K3FT3CBT; 546 | ENABLE_BITCODE = NO; 547 | INFOPLIST_FILE = Runner/Info.plist; 548 | LD_RUNPATH_SEARCH_PATHS = ( 549 | "$(inherited)", 550 | "@executable_path/Frameworks", 551 | ); 552 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 555 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 556 | SWIFT_VERSION = 5.0; 557 | VERSIONING_SYSTEM = "apple-generic"; 558 | }; 559 | name = Debug; 560 | }; 561 | 97C147071CF9000F007C117D /* Release */ = { 562 | isa = XCBuildConfiguration; 563 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 564 | buildSettings = { 565 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 566 | CLANG_ENABLE_MODULES = YES; 567 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 568 | DEVELOPMENT_TEAM = 54K3FT3CBT; 569 | ENABLE_BITCODE = NO; 570 | INFOPLIST_FILE = Runner/Info.plist; 571 | LD_RUNPATH_SEARCH_PATHS = ( 572 | "$(inherited)", 573 | "@executable_path/Frameworks", 574 | ); 575 | PRODUCT_BUNDLE_IDENTIFIER = com.rightdevs.statusSaver; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 578 | SWIFT_VERSION = 5.0; 579 | VERSIONING_SYSTEM = "apple-generic"; 580 | }; 581 | name = Release; 582 | }; 583 | /* End XCBuildConfiguration section */ 584 | 585 | /* Begin XCConfigurationList section */ 586 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 331C8088294A63A400263BE5 /* Debug */, 590 | 331C8089294A63A400263BE5 /* Release */, 591 | 331C808A294A63A400263BE5 /* Profile */, 592 | ); 593 | defaultConfigurationIsVisible = 0; 594 | defaultConfigurationName = Release; 595 | }; 596 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 97C147031CF9000F007C117D /* Debug */, 600 | 97C147041CF9000F007C117D /* Release */, 601 | 249021D3217E4FDB00AE95B9 /* Profile */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | 97C147061CF9000F007C117D /* Debug */, 610 | 97C147071CF9000F007C117D /* Release */, 611 | 249021D4217E4FDB00AE95B9 /* Profile */, 612 | ); 613 | defaultConfigurationIsVisible = 0; 614 | defaultConfigurationName = Release; 615 | }; 616 | /* End XCConfigurationList section */ 617 | }; 618 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 619 | } 620 | -------------------------------------------------------------------------------- /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.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krupal4/StatusSaver/f94ee8dfb52ac444758e2b03dd0e7aab513f63cb/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 | Status Saver 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | status_saver 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 | -------------------------------------------------------------------------------- /l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/src/localization/l10n 2 | template-arb-file: app_en.arb 3 | output-localization-file: app_localizations.dart -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:dynamic_color/dynamic_color.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_localizations/flutter_localizations.dart'; 4 | import 'package:flutter_native_splash/flutter_native_splash.dart'; 5 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 6 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 7 | import 'package:material_color_utilities/palettes/core_palette.dart'; 8 | import 'package:status_saver/src/home/views/home_screen.dart'; 9 | import 'package:status_saver/src/localization/notifiers/locale_notifier.dart'; 10 | import 'package:status_saver/src/theme/app_theme.dart'; 11 | import 'package:status_saver/src/theme/notifiers/theme_mode_notifier.dart'; 12 | 13 | void main() async { 14 | WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); 15 | FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); 16 | CorePalette? corePalette = await DynamicColorPlugin.getCorePalette(); 17 | FlutterNativeSplash.remove(); 18 | runApp(ProviderScope(child: MyApp(corePalette: corePalette))); 19 | } 20 | 21 | class MyApp extends ConsumerWidget { 22 | final CorePalette? corePalette; 23 | const MyApp({super.key, this.corePalette}); 24 | 25 | @override 26 | Widget build(BuildContext context, WidgetRef ref) { 27 | return MaterialApp( 28 | restorationScopeId: 'app', 29 | title: 'Whatsapp Status Saver', 30 | localizationsDelegates: const [ 31 | GlobalMaterialLocalizations.delegate, 32 | GlobalWidgetsLocalizations.delegate, 33 | GlobalCupertinoLocalizations.delegate, 34 | AppLocalizations.delegate 35 | ], 36 | locale: ref.watch(localeProvider), // TODO: revisit implementation 37 | supportedLocales: AppLocalizations.supportedLocales, 38 | themeMode: ref.watch(themeModeProvider), 39 | theme: AppTheme.themeData(corePalette, Brightness.light), 40 | darkTheme: AppTheme.themeData(corePalette, Brightness.dark), 41 | home: const HomeScreen(), 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/src/common/constants/directory_paths.dart: -------------------------------------------------------------------------------- 1 | const String savedStatusesDirectory = 2 | "/storage/emulated/0/Download/Saved Statuses"; 3 | -------------------------------------------------------------------------------- /lib/src/common/extensions/async_value.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:status_saver/src/common/views/circular_loader.dart'; 4 | import 'package:status_saver/src/common/views/common_error_screen.dart'; 5 | 6 | extension WhenAsyncValue on AsyncValue { 7 | Widget whenWidget(Widget Function(T) data) => when( 8 | data: data, 9 | error: commonErrorScreen, 10 | loading: CircularLoader.new, 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/common/extensions/permission_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:permission_handler/permission_handler.dart'; 2 | import 'package:status_saver/src/debug/console_log.dart'; 3 | 4 | extension CustomPermissionHandler on Permission { 5 | Future requestAndHandle() async { 6 | PermissionStatus status = await request(); 7 | 8 | if (status.isPermanentlyDenied) { 9 | // The user opted to never again see the permission request dialog for this 10 | // app. The only way to change the permission's status now is to let the 11 | // user manually enables it in the system settings. 12 | openAppSettings(); 13 | } 14 | return status.isGranted; 15 | } 16 | } 17 | 18 | extension CustomPermissionListHandler on List { 19 | Future requestAndHandle() async { 20 | Iterable statuses = (await request()).values; 21 | consoleLog(statuses, "statueses resp"); 22 | 23 | if (statuses 24 | .any((status) => status == PermissionStatus.permanentlyDenied)) { 25 | // The user opted to never again see the permission request dialog for this 26 | // app. The only way to change the permission's status now is to let the 27 | // user manually enables it in the system settings. 28 | openAppSettings(); 29 | } 30 | return statuses.every((status) => status.isGranted); 31 | } 32 | 33 | Future get isGranted async { 34 | return (await Future.wait( 35 | map((permission) => permission.status), 36 | )) 37 | .every((status) => status.isGranted); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/common/helpers/android_api_level_helper.dart: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/src/common/helpers/get_video_thumbnail.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:video_thumbnail/video_thumbnail.dart'; 3 | 4 | Future getVideoThumbnailData(String videoPath) async { 5 | return await VideoThumbnail.thumbnailData( 6 | video: videoPath, 7 | imageFormat: ImageFormat.JPEG, 8 | quality: 50, 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/common/helpers/show_toast.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:fluttertoast/fluttertoast.dart'; 3 | 4 | void showToast( 5 | {String Function()? getMessage, 6 | String? message, 7 | Toast toastLength = Toast.LENGTH_SHORT}) { 8 | if (message == null && getMessage == null) { 9 | throw ArgumentError('Either message or getMessage is required.'); 10 | } 11 | Fluttertoast.showToast( 12 | msg: message ?? (getMessage != null ? getMessage() : ""), 13 | toastLength: toastLength, 14 | gravity: ToastGravity.BOTTOM, 15 | timeInSecForIosWeb: 1, 16 | backgroundColor: Colors.greenAccent.shade200, 17 | textColor: Colors.black, 18 | fontSize: 16.0); 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/common/helpers/statuses_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:status_saver/src/common/constants/directory_paths.dart'; 2 | 3 | // List getDirectoryPaths(TabType tabType) { 4 | // return tabType == TabType.recent 5 | // ? recentDirectoryPaths 6 | // : const [savedStatusesDirectory]; 7 | // } 8 | 9 | String getSavedStatusPath(String statusPath) => 10 | "$savedStatusesDirectory/${statusPath.split('/').last}"; 11 | 12 | bool isItSavedStatus(statusPath) => 13 | getSavedStatusPath(statusPath).compareTo(statusPath) == 0; 14 | 15 | // String getThumbnailPath(String videoPath) { 16 | // return "$thumbnailsDirectoryPath/${videoPath.split("/").last.replaceAll(mp4, png)}"; 17 | // } -------------------------------------------------------------------------------- /lib/src/common/helpers/storage_helper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:status_saver/src/home/models/whatsapp_type_enum.dart'; 4 | 5 | String getStatusesPath(WhatsAppType whatsAppType, bool isAndroid11OrLater) { 6 | if (whatsAppType == WhatsAppType.whatsApp) { 7 | return isAndroid11OrLater 8 | ? "Android/media/com.whatsapp/WhatsApp/Media/.Statuses" 9 | : ""; 10 | } else if (whatsAppType == WhatsAppType.w4b) { 11 | return isAndroid11OrLater 12 | ? "Android/media/com.whatsapp.w4b/WhatsApp Business/Media/.Statuses" 13 | : ""; 14 | } else { 15 | throw Exception( 16 | "Please provide statuses dir path for whatsapp type: '$whatsAppType'"); 17 | } 18 | } 19 | 20 | bool isItStatusFile(String filePath) { 21 | return filePath.endsWith(".mp4") || filePath.endsWith(".jpg"); 22 | } 23 | 24 | List getDirectoryFilePaths( 25 | String dirPath, { 26 | bool Function(String)? whereCallback, 27 | }) { 28 | whereCallback ??= (_) => true; 29 | 30 | try { 31 | Directory dir = Directory(dirPath); 32 | if (!dir.existsSync()) { 33 | return []; 34 | } 35 | 36 | return dir 37 | .listSync() 38 | .map((fileSystemEntity) => fileSystemEntity.path) 39 | .where(whereCallback) 40 | .toList(); 41 | } catch (e) { 42 | return List.empty(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/src/common/views/circular_loader.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircularLoader extends StatelessWidget { 4 | const CircularLoader({super.key}); 5 | 6 | @override 7 | Widget build(BuildContext context) { 8 | return const Center( 9 | child: CircularProgressIndicator(), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/common/views/common_error_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Widget commonErrorScreen( 4 | final Object error, 5 | final StackTrace stackTrace, 6 | ) => 7 | Column( 8 | children: [ 9 | const Text( 10 | "something went wrong, please restart app", 11 | style: TextStyle( 12 | fontSize: 18, 13 | ), 14 | ), 15 | Text( 16 | error.toString(), 17 | style: const TextStyle(fontSize: 22), 18 | ) 19 | ], 20 | ); 21 | -------------------------------------------------------------------------------- /lib/src/debug/console_log.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | void consoleLog(Object? obj, [String? message]) { 4 | debugPrint(''' 5 | ---------------------------- 6 | ${message == null ? obj : "$message : $obj"} 7 | ---------------------------- 8 | '''); 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/debug/red_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class RedContainer extends StatelessWidget { 4 | const RedContainer({super.key, required this.child}); 5 | final Widget child; 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return Container( 10 | decoration: BoxDecoration( 11 | border: Border.all( 12 | color: Colors.red, 13 | ), 14 | ), 15 | child: child, 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/home/models/android_info.dart: -------------------------------------------------------------------------------- 1 | class AndroidInfo { 2 | final int androidSdkApiLevel; 3 | final bool isAndroid11OrLater; 4 | final bool isAndroid13OrLater; 5 | 6 | const AndroidInfo({ 7 | required this.androidSdkApiLevel, 8 | required this.isAndroid11OrLater, 9 | required this.isAndroid13OrLater, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/home/models/tab_type.dart: -------------------------------------------------------------------------------- 1 | enum StatusTabType { 2 | recent, 3 | saved, 4 | } 5 | -------------------------------------------------------------------------------- /lib/src/home/models/whatsapp_type_enum.dart: -------------------------------------------------------------------------------- 1 | enum WhatsAppType { 2 | whatsApp, 3 | w4b, 4 | } 5 | -------------------------------------------------------------------------------- /lib/src/home/notifiers/selected_tab_index_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 2 | 3 | const recentTabIndex = 0; 4 | const savedTabIndex = 1; 5 | 6 | class SelectedTabNotifier extends Notifier { 7 | @override 8 | int build() { 9 | return recentTabIndex; 10 | } 11 | 12 | void set(int selectedIndex) { 13 | state = selectedIndex; 14 | } 15 | } 16 | 17 | final selectedTabIndexProvider = 18 | NotifierProvider(SelectedTabNotifier.new); 19 | -------------------------------------------------------------------------------- /lib/src/home/services/android_info_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:device_info_plus/device_info_plus.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:status_saver/src/home/models/android_info.dart'; 4 | 5 | final androidInfoProvider = FutureProvider((ref) async { 6 | DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); 7 | AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; 8 | final int androidSdkApiLevel = androidInfo.version.sdkInt; 9 | 10 | final bool isAndroid11OrLater = androidSdkApiLevel >= 30; 11 | final bool isAndroid13OrLater = androidSdkApiLevel >= 33; 12 | return AndroidInfo( 13 | androidSdkApiLevel: androidSdkApiLevel, 14 | isAndroid11OrLater: isAndroid11OrLater, 15 | isAndroid13OrLater: isAndroid13OrLater, 16 | ); 17 | }); 18 | -------------------------------------------------------------------------------- /lib/src/home/services/whatsapp_type_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:appcheck/appcheck.dart'; 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:flutter/services.dart'; 7 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 8 | import 'package:status_saver/src/home/models/whatsapp_type_enum.dart'; 9 | 10 | class WhatsAppTypeNotifier extends AsyncNotifier { 11 | @override 12 | FutureOr build() async { 13 | final Map packagesMap = { 14 | WhatsAppType.whatsApp: "com.whatsapp", 15 | WhatsAppType.w4b: "com.whatsapp.w4b" 16 | }; 17 | for (MapEntry packageMap in packagesMap.entries) { 18 | if (Platform.isAndroid) { 19 | final app = await _checkAppAvailability(packageMap.value); 20 | if (app != null) { 21 | return packageMap.key; 22 | } 23 | } 24 | } 25 | return null; 26 | } 27 | 28 | Future _checkAppAvailability(String package) async { 29 | try { 30 | final app = await AppCheck.checkAvailability(package); 31 | return app; 32 | } on PlatformException catch (e) { 33 | if (e.code == '400' && e.message?.contains('App not found') == true) { 34 | debugPrint('App not found for package $package'); 35 | // Handle the app not being found (e.g., show a user message or handle gracefully) 36 | } else { 37 | debugPrint('PlatformException: ${e.message}'); 38 | // Handle other platform exceptions 39 | } 40 | } catch (error) { 41 | debugPrint( 42 | 'General error checking availability for package $package: $error'); 43 | // Handle other general exceptions 44 | } 45 | return null; 46 | } 47 | } 48 | 49 | final whatsAppTypeProvider = 50 | AsyncNotifierProvider( 51 | WhatsAppTypeNotifier.new); 52 | -------------------------------------------------------------------------------- /lib/src/home/views/home_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:status_saver/src/common/extensions/async_value.dart'; 4 | import 'package:status_saver/src/debug/console_log.dart'; 5 | import 'package:status_saver/src/home/models/tab_type.dart'; 6 | import 'package:status_saver/src/home/notifiers/selected_tab_index_notifier.dart'; 7 | import 'package:status_saver/src/home/services/whatsapp_type_notifier.dart'; 8 | import 'package:status_saver/src/home/views/my_drawer.dart'; 9 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 10 | import 'package:status_saver/src/statuses/views/statuses_screen.dart'; 11 | import 'package:status_saver/src/storage_permission/notifiers/storage_permission_notifier.dart'; 12 | import 'package:status_saver/src/storage_permission/views/give_permissions_screen.dart'; 13 | 14 | class HomeScreen extends ConsumerWidget { 15 | const HomeScreen({super.key}); 16 | 17 | @override 18 | Widget build(BuildContext context, WidgetRef ref) { 19 | return Scaffold( 20 | appBar: AppBar( 21 | elevation: 5, 22 | title: Text(context.l10n.appTitle), 23 | ), 24 | bottomNavigationBar: _navigationBar(context, ref), 25 | body: [ 26 | () => _recentStatusesScreen(ref), 27 | () => _savedStatusesScreen(ref), 28 | ][ref.watch(selectedTabIndexProvider)](), 29 | drawer: const MyDrawer(), 30 | ); 31 | } 32 | 33 | Widget _recentStatusesScreen(WidgetRef ref) => 34 | ref.watch(whatsAppTypeProvider).whenWidget( 35 | (whatsAppType) { 36 | if (whatsAppType == null) { 37 | return const Center( 38 | child: Text("No WhatsApp found on this mobile.")); 39 | } 40 | final AsyncValue storagePermissionAsync = 41 | ref.watch(recentStoragePermissionProvider); 42 | return storagePermissionAsync.whenWidget( 43 | (isStoragePermitted) { 44 | return isStoragePermitted 45 | ? const StatusesScreen(tabType: StatusTabType.recent) 46 | : GivePermissionsScreen( 47 | onRequestPermission: ref 48 | .read(recentStoragePermissionProvider.notifier) 49 | .request, 50 | ); 51 | }, 52 | ); 53 | }, 54 | ); 55 | 56 | Widget _savedStatusesScreen(WidgetRef ref) => 57 | ref.watch(savedStoragePermissionProvider).whenWidget( 58 | (isStoragePermitted) { 59 | consoleLog(isStoragePermitted, "saves storage permitted?"); 60 | return isStoragePermitted 61 | ? const StatusesScreen( 62 | tabType: StatusTabType.saved, 63 | ) 64 | : GivePermissionsScreen( 65 | onRequestPermission: 66 | ref.read(savedStoragePermissionProvider.notifier).request, 67 | ); 68 | }, 69 | ); 70 | 71 | NavigationBar _navigationBar(BuildContext context, WidgetRef ref) { 72 | final int selectedTabIndex = ref.watch(selectedTabIndexProvider); 73 | return NavigationBar( 74 | selectedIndex: selectedTabIndex, 75 | onDestinationSelected: (value) => 76 | ref.read(selectedTabIndexProvider.notifier).set(value), 77 | destinations: [ 78 | NavigationDestination( 79 | selectedIcon: const Icon(Icons.auto_stories_rounded), 80 | icon: const Icon(Icons.auto_stories_outlined), 81 | label: context.l10n.recentStatuses, 82 | ), 83 | NavigationDestination( 84 | selectedIcon: const Icon(Icons.save_rounded), 85 | icon: const Icon(Icons.save_outlined), 86 | label: context.l10n.savedStatuses, 87 | ), 88 | ], 89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/home/views/my_drawer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; 4 | import 'package:status_saver/src/localization/enums/language_code.dart'; 5 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 6 | import 'package:status_saver/src/localization/extensions/on_string.dart'; 7 | import 'package:status_saver/src/localization/l10n/l10n.dart'; 8 | import 'package:status_saver/src/localization/notifiers/locale_notifier.dart'; 9 | import 'package:status_saver/src/theme/notifiers/theme_mode_notifier.dart'; 10 | 11 | // TODO: re visit this 12 | const String applicationVersion = "1.0.0"; 13 | String applicationName(BuildContext context) => context.l10n.appTitle; 14 | 15 | Icon applicationIcon = 16 | const Icon(FontAwesomeIcons.squareVirus); // TODO: provide application icon 17 | 18 | class MyDrawer extends ConsumerWidget { 19 | const MyDrawer({super.key}); 20 | 21 | @override 22 | Widget build(BuildContext context, WidgetRef ref) { 23 | return Drawer( 24 | elevation: 2.5, 25 | child: ListView( 26 | children: [ 27 | ListTile( 28 | title: Text(context.l10n.appLanguageLabel), 29 | leading: const Icon(Icons.translate), 30 | onTap: () { 31 | Navigator.of(context).pop(); 32 | _showLanguageChooser(context, ref); 33 | }, 34 | ), 35 | ListTile( 36 | title: Text(context.l10n.appThemeModeLabel), 37 | leading: const Icon(Icons.dark_mode_outlined), 38 | onTap: () { 39 | Navigator.of(context).pop(); 40 | _showThemeModeSelector(context, ref); 41 | }, 42 | ), 43 | ListTile( 44 | title: Text(context.l10n.aboutButtonLabel), 45 | leading: const Icon(Icons.info), 46 | onTap: () { 47 | Navigator.of(context).pop(); 48 | showAboutDialog( 49 | context: context, 50 | applicationIcon: applicationIcon, 51 | applicationVersion: applicationVersion, 52 | applicationName: applicationName(context), 53 | children: [ 54 | Text( 55 | context.l10n.howDoesItWorkTitle, 56 | style: const TextStyle(fontSize: 22), 57 | ), 58 | Text( 59 | context.l10n.howDoesItWorkDescription, 60 | style: const TextStyle(fontSize: 18), 61 | ) 62 | ]); 63 | }, 64 | ), 65 | ], 66 | ), 67 | ); 68 | } 69 | 70 | Future _showThemeModeSelector(BuildContext context, WidgetRef ref) { 71 | return showDialog( 72 | context: context, 73 | builder: (context) { 74 | final themeModeNotifier = ref.watch(themeModeProvider.notifier); 75 | return AlertDialog( 76 | content: SizedBox( 77 | height: MediaQuery.of(context).size.height * 78 | 0.22, // FIXME: give auto height 79 | width: MediaQuery.of(context).size.width * 0.7, 80 | child: Scrollbar( 81 | child: Padding( 82 | padding: const EdgeInsets.only( 83 | right: 12, 84 | ), 85 | child: ListView.builder( 86 | itemCount: MyThemes.themeModeTypes(context).length, 87 | itemBuilder: (context, index) { 88 | return ListTile( 89 | title: Text(MyThemes.themeModeTypes(context)[index]), 90 | leading: MyThemes.themeModeIcons[index], 91 | trailing: themeModeNotifier.themeMode == 92 | MyThemes.themeModes[index] 93 | ? const Icon(Icons.check) 94 | : null, 95 | onTap: () { 96 | themeModeNotifier.setThemeMode( 97 | MyThemes.themeModes[index], context); 98 | }, 99 | ); 100 | }, 101 | ), 102 | ), 103 | ), 104 | ), 105 | actions: [ 106 | TextButton( 107 | onPressed: () { 108 | Navigator.of(context).pop(); 109 | }, 110 | child: Text(context.l10n.closeButtonLabel)) 111 | ], 112 | ); 113 | }); 114 | } 115 | 116 | void _showLanguageChooser(BuildContext context, WidgetRef ref) { 117 | final localeProviderNotifier = ref.watch(localeProvider.notifier); 118 | LanguageCode tempSelectedLanguageCode = 119 | localeProviderNotifier.locale?.languageCode.toLanguageCode() ?? 120 | systemLanguageCode; 121 | showDialog( 122 | context: context, 123 | builder: (context) { 124 | return StatefulBuilder(builder: (context, setState) { 125 | return AlertDialog( 126 | contentPadding: const EdgeInsets.only(top: 4), 127 | title: Text(context.l10n.appLanguageLabel, 128 | style: const TextStyle(fontSize: 18)), 129 | content: SizedBox( 130 | height: double.maxFinite, // FIXME: give auto height 131 | width: MediaQuery.of(context).size.width * 0.85, 132 | child: Scrollbar( 133 | child: Padding( 134 | padding: const EdgeInsets.only( 135 | right: 12, 136 | ), 137 | child: ListView.builder( 138 | itemCount: LanguageCode.values.length, 139 | itemBuilder: (context, index) { 140 | final LanguageCode languageCode = 141 | LanguageCode.values[index]; 142 | return RadioListTile( 143 | value: LanguageCode.values[index], 144 | groupValue: tempSelectedLanguageCode, 145 | onChanged: (value) { 146 | setState(() { 147 | tempSelectedLanguageCode = value!; 148 | }); 149 | }, 150 | title: Text( 151 | '${L10n.getLanguageName(languageCode, context)} ${languageCode != systemLanguageCode ? "[${languageCode.name}]" : ""}')); 152 | }, 153 | ), 154 | ), 155 | ), 156 | ), 157 | actions: [ 158 | TextButton( 159 | onPressed: () => Navigator.of(context).pop(), 160 | child: Text(context.l10n.cancelButtonLabel), 161 | ), 162 | TextButton( 163 | onPressed: () { 164 | Navigator.of(context).pop(); 165 | localeProviderNotifier.setLocale( 166 | tempSelectedLanguageCode, context); 167 | }, 168 | child: Text(context.l10n.okButtonLabel), 169 | ), 170 | ], 171 | ); 172 | }); 173 | }); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /lib/src/localization/enums/language_code.dart: -------------------------------------------------------------------------------- 1 | enum LanguageCode { 2 | system, 3 | en, 4 | af, 5 | ar, 6 | az, 7 | bn, 8 | es, 9 | gu, 10 | hi, 11 | ja, 12 | kn, 13 | ko, 14 | mr, 15 | pa, 16 | ta, 17 | te, 18 | ur 19 | } -------------------------------------------------------------------------------- /lib/src/localization/extensions/on_build_context.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 3 | export 'package:flutter_gen/gen_l10n/app_localizations.dart'; 4 | 5 | extension LocalizationsContext on BuildContext { 6 | AppLocalizations get l10n => AppLocalizations.of(this)!; 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/localization/extensions/on_string.dart: -------------------------------------------------------------------------------- 1 | import 'package:status_saver/src/localization/enums/language_code.dart'; 2 | 3 | extension LanguageCodeExtension on String { 4 | LanguageCode toLanguageCode() { 5 | return LanguageCode.values.firstWhere((element) => element.name == this); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_af.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "Hallo Wêreld!", 3 | "appTitle": "Statusbewaarder", 4 | "recentStatuses": "Onlangs", 5 | "savedStatuses": "Bewaar", 6 | "statusSavedMessage": "Status bewaar", 7 | "noSavedStatusesMessage": "Geen bewaarde statuses", 8 | "noWhatsappFoundMessage": "Whatsapp bestaan nie op jou selfoon nie", 9 | "appLanguageLabel": "App Taal", 10 | "saveButtonLabel": "Bewaar", 11 | "shareButtonLabel": "Deel", 12 | "okButtonLabel": "OK", 13 | "cancelButtonLabel": "KANSELLEER", 14 | "closeButtonLabel": "SLUIT", 15 | "howDoesItWorkTitle": "Hoe werk dit?", 16 | "howDoesItWorkDescription": "Ons is nie geaffilieer of amptelik verbind met WhatsApp Inc op enige manier nie. En ons het geen toegang tot jou WhatsApp-boodskappe nie.\n\nHierdie toepassing is bedoel om jou 'n geriefliker manier te bied om deur, te bewaar en te deel die statusafbeeldings en -video's wat in jou toestel se opbergruimte gekasheer is.", 17 | "aboutButtonLabel": "Oor die App", 18 | "appThemeModeLabel": "App Tema-modus", 19 | "systemDefaultLabel": "Standaard Sisteem", 20 | "couldNotSaveYourLanguagePreference": "Kon jou taalvoorkeur nie stoor nie", 21 | "couldNotSaveYourThemePreference": "Kon jou temavoorkeur nie stoor nie", 22 | "giveStoragePermission": "Gee stoorregte", 23 | "needToGiveStoragePermission": "Jy moet stoorregte vir hierdie toepassing gee.", 24 | "couldNotOpenAppSettings": "Kon nie toepassingsinstellings vir stoorregte oopmaak nie.", 25 | "allowStoragePermission": "Staan stoorregte toe vir Statusbewaarder", 26 | "openWhatsAppLabel": "Maak WhatsApp oop", 27 | "openW4BLabel": "Maak WhatsApp Business oop", 28 | "doNotHaveSeenStatusesMessage": "Jy het nog geen statuses gesien nie, gaan kyk na sommige statuses", 29 | "systemThemeLabel": "Sisteemtema", 30 | "lightThemeLabel": "Ligte Tema", 31 | "darkThemeLabel": "Donker Tema", 32 | "exitButtonLabel": "SLUIT", 33 | "exitWarningTitle": "Verlaat Statusbewaarder", 34 | "exitWarningMessage": "Is jy seker dat jy wil afsluit?", 35 | "deleteButtonLabel": "VERWYDER", 36 | "deleteStatusWarningTitle": "Verwyder Status", 37 | "deleteStatusWarningMessage": "Wil jy hierdie status permanent verwyder?", 38 | "deletedStatusMessage": "Status Verwyder" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_ar.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "مرحبًا بالعالم!", 3 | "appTitle": "حفّاظ الحالة", 4 | "recentStatuses": "الأحداث الأخيرة", 5 | "savedStatuses": "الحالات المحفوظة", 6 | "statusSavedMessage": "تم حفظ الحالة", 7 | "noSavedStatusesMessage": "لا توجد حالات محفوظة", 8 | "noWhatsappFoundMessage": "لا يوجد تطبيق واتساب على جوالك", 9 | "appLanguageLabel": "لغة التطبيق", 10 | "saveButtonLabel": "حفظ", 11 | "shareButtonLabel": "مشاركة", 12 | "okButtonLabel": "موافق", 13 | "cancelButtonLabel": "إلغاء", 14 | "closeButtonLabel": "إغلاق", 15 | "howDoesItWorkTitle": "كيف يعمل؟", 16 | "howDoesItWorkDescription": "نحن لسنا مرتبطين أو متصلين رسميًا بشركة واتساب بأي شكل من الأشكال. وليس لدينا أي وصول إلى رسائل واتساب الخاصة بك.\n\nتهدف هذه التطبيق لتوفير وسيلة أكثر ملاءمة لاستكشاف وحفظ ومشاركة الصور ومقاطع الفيديو للحالات المخزنة في ذاكرة جهازك.", 17 | "aboutButtonLabel": "حول التطبيق", 18 | "appThemeModeLabel": "وضعية تصميم التطبيق", 19 | "systemDefaultLabel": "الوضعية الافتراضية للنظام", 20 | "couldNotSaveYourLanguagePreference": "تعذر حفظ تفضيلات اللغة الخاصة بك", 21 | "couldNotSaveYourThemePreference": "تعذر حفظ تفضيلات التصميم الخاصة بك", 22 | "giveStoragePermission": "منح إذن التخزين", 23 | "needToGiveStoragePermission": "يجب عليك منح إذن التخزين لهذا التطبيق.", 24 | "couldNotOpenAppSettings": "تعذر فتح إعدادات التطبيق لإذن التخزين.", 25 | "allowStoragePermission": "السماح بإذن التخزين لحفّاظ الحالة", 26 | "openWhatsAppLabel": "فتح واتساب", 27 | "openW4BLabel": "فتح واتساب بزنس", 28 | "doNotHaveSeenStatusesMessage": "لم تشاهد أي حالات حتى الآن، اذهب وشاهد بعض الحالات", 29 | "systemThemeLabel": "وضعية التصميم النظام", 30 | "lightThemeLabel": "الوضع الفاتح", 31 | "darkThemeLabel": "الوضع الداكن", 32 | "exitButtonLabel": "خروج", 33 | "exitWarningTitle": "خروج من التطبيق", 34 | "exitWarningMessage": "هل أنت متأكد من أنك تريد الخروج؟", 35 | "deleteButtonLabel": "حذف", 36 | "deleteStatusWarningTitle": "حذف الحالة", 37 | "deleteStatusWarningMessage": "هل تريد حذف هذه الحالة نهائياً؟", 38 | "deletedStatusMessage": "تم حذف الحالة" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_az.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "Salam Dünya!", 3 | "appTitle": "Status Saxlayıcı", 4 | "recentStatuses": "Sonuncular", 5 | "savedStatuses": "Saxlanılanlar", 6 | "statusSavedMessage": "Status saxlanıldı", 7 | "noSavedStatusesMessage": "Saxlanılan status yoxdur", 8 | "noWhatsappFoundMessage": "Mobilinizdə WhatsApp yoxdur", 9 | "appLanguageLabel": "Proqram Dil", 10 | "saveButtonLabel": "Saxla", 11 | "shareButtonLabel": "Paylaş", 12 | "okButtonLabel": "OK", 13 | "cancelButtonLabel": "İmtina et", 14 | "closeButtonLabel": "Bağla", 15 | "howDoesItWorkTitle": "Bu necə işləyir?", 16 | "howDoesItWorkDescription": "Biz WhatsApp Inc. ilə heç bir əlaqəsi olmayan və rəsmi şəkildə əlaqələndirilməmişik. Həmçinin, WhatsApp mesajlarınıza heç bir girişimiz yoxdur.\n\nBu tətbiq, cihazınızın saxlamağa qənaətli bir yolu təmin etmək, saxlanılan status şəkillərini və videolarını kəşf etmək və paylaşmaq üçün nəzərdə tutulmuşdur.", 17 | "aboutButtonLabel": "Proqram haqqında", 18 | "appThemeModeLabel":"Proqram Masa Üstü Üzərindəki Modu", 19 | "systemDefaultLabel": "Sistem Standartı", 20 | "couldNotSaveYourLanguagePreference": "Dil tercihinizi saxlaya bilmədik", 21 | "couldNotSaveYourThemePreference": "Tema tercihinizi saxlaya bilmədik", 22 | "giveStoragePermission": "Yaddaş icazəsi verin", 23 | "needToGiveStoragePermission": "Bu tətbiq üçün yaddaş icazəsinə ehtiyacınız var.", 24 | "couldNotOpenAppSettings": "Yaddaş icazəsi üçün tətbiq ayarlarını açmaq mümkün olmadı.", 25 | "allowStoragePermission": "Status Saxlayıcıya yaddaş icazəsi verin", 26 | "openWhatsAppLabel": "WhatsApp'ı aç", 27 | "openW4BLabel": "WhatsApp Business'ı aç", 28 | "doNotHaveSeenStatusesMessage": "Hələ heç bir status görməmisiniz, get və bir neçə status izləyin", 29 | "systemThemeLabel": "Sistem Teması", 30 | "lightThemeLabel": "Açıq Tema", 31 | "darkThemeLabel": "Tünd Tema", 32 | "exitButtonLabel": "ÇIXIŞ", 33 | "exitWarningTitle": "StatusSaver'dan Çıxmaq", 34 | "exitWarningMessage": "Çıxmağa əminsinizmi?", 35 | "deleteButtonLabel": "SİL", 36 | "deleteStatusWarningTitle": "Statusu Sil", 37 | "deleteStatusWarningMessage": "Bu statusu daimi olaraq silmək istəyirsiniz?", 38 | "deletedStatusMessage": "Status Silindi" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_bn.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "ওহে বিশ্ব!", 3 | "appTitle": "স্ট্যাটাস সেভার", 4 | "recentStatuses": "সাম্প্রতিক", 5 | "savedStatuses": "সেভ করা স্ট্যাটাস", 6 | "statusSavedMessage": "স্ট্যাটাস সেভ করা হয়েছে", 7 | "noSavedStatusesMessage": "কোন সেভ করা স্ট্যাটাস নেই", 8 | "noWhatsappFoundMessage": "আপনার মোবাইলে উইটসঅ্যাপ পাওয়া যায়নি", 9 | "appLanguageLabel": "অ্যাপ ভাষা", 10 | "saveButtonLabel": "সেভ করুন", 11 | "shareButtonLabel": "শেয়ার করুন", 12 | "okButtonLabel": "ঠিক আছে", 13 | "cancelButtonLabel": "বাতিল করুন", 14 | "closeButtonLabel": "বন্ধ করুন", 15 | "howDoesItWorkTitle": "এটি কিভাবে কাজ করে?", 16 | "howDoesItWorkDescription": "আমরা কোনও ভাবিত নথি নই বা কোনও প্রকারে ওয়াটসঅ্যাপ ইনক সংযুক্ত নই। আর আপনার ওয়াটসঅ্যাপ বার্তাগুলির কোনও অ্যাক্সেস নেই।\n\nএই অ্যাপ্লিকেশনটি আপনাকে আপনার ডিভাইসের স্টোরেজে সংরক্ষিত স্থিতির চিত্র এবং ভিডিও বেচে চলার ও শেয়ার করার একটি সুবিধায় প্রদান করার উদ্দেশ্যে তৈরি করা হয়েছে", 17 | "aboutButtonLabel": "অ্যাপ সম্পর্কে", 18 | "appThemeModeLabel": "অ্যাপ থিম মোড", 19 | "systemDefaultLabel": "সিস্টেম ডিফল্ট", 20 | "couldNotSaveYourLanguagePreference": "আপনার ভাষা পছন্দটি সংরক্ষণ করতে পারেনি", 21 | "couldNotSaveYourThemePreference": "আপনার থিম পছন্দটি সংরক্ষণ করতে পারেনি", 22 | "giveStoragePermission": "স্টোরেজ অনুমতি দিন", 23 | "needToGiveStoragePermission": "আপনাকে এই অ্যাপ্লিকেশনের জন্য স্টোরেজ অনুমতি দিতে হবে।", 24 | "couldNotOpenAppSettings": "স্টোরেজ অনুমতির জন্য অ্যাপ সেটিংস খুলতে পারা যায়নি।", 25 | "allowStoragePermission": "স্টোরেজ অনুমতি দিন স্ট্যাটাস সেভার এর জন্য", 26 | "openWhatsAppLabel": "ওয়াটসঅ্যাপ খুলুন", 27 | "openW4BLabel": "ওয়াটসঅ্যাপ ব্যবসা খুলুন", 28 | "doNotHaveSeenStatusesMessage": "আপনি এখনও কোনও স্থিতি দেখা করেননি, যান এবং কিছু স্থিতি দেখুন", 29 | "systemThemeLabel": "সিস্টেম থিম", 30 | "lightThemeLabel": "হালকা থিম", 31 | "darkThemeLabel": "ডার্ক থিম", 32 | "exitButtonLabel": "বাহির", 33 | "exitWarningTitle": "স্থিতি সংরক্ষণকারী থেকে বেরিয়ে যেতে চান", 34 | "exitWarningMessage": "আপনি কি নিশ্চিত যে আপনি বের হতে চান?", 35 | "deleteButtonLabel": "মুছে ফেলুন", 36 | "deleteStatusWarningTitle": "স্থিতি মুছুন", 37 | "deleteStatusWarningMessage": "আপনি কি এই স্থিতি স্থায়ীভাবে মুছে ফেলতে চান?", 38 | "deletedStatusMessage": "স্থিতি মুছে ফেলা হয়েছে" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_en.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "Hello World!", 3 | "appTitle": "Status Saver", 4 | "recentStatuses": "Recent", 5 | "savedStatuses": "Saved", 6 | "statusSavedMessage": "Status saved", 7 | "noSavedStatusesMessage": "No saved statuses", 8 | "noWhatsappFoundMessage": "Whatsapp does not exists on your mobile", 9 | "appLanguageLabel": "App Language", 10 | "saveButtonLabel": "Save", 11 | "shareButtonLabel": "Share", 12 | "okButtonLabel": "OK", 13 | "cancelButtonLabel": "CANCEL", 14 | "closeButtonLabel": "CLOSE", 15 | "howDoesItWorkTitle": "How does it work?", 16 | "howDoesItWorkDescription": "We are not affiliated or officially connected with WhatsApp Inc in any way. And, we do not have any access to your WhatsApp messages.\n\nThis application is intended to provide you with a more convenient way to explore, save and share the status images and videos cached in your device storage", 17 | "aboutButtonLabel": "About App", 18 | "appThemeModeLabel":"App Theme Mode", 19 | "systemDefaultLabel": "System Default", 20 | "couldNotSaveYourLanguagePreference": "Could not save your language preference", 21 | "couldNotSaveYourThemePreference": "Could not save your theme preference", 22 | "giveStoragePermission": "Give storage permission", 23 | "needToGiveStoragePermission": "You need to give storage permissions for this application.", 24 | "couldNotOpenAppSettings": "Could not open app settings for storage permission.", 25 | "allowStoragePermission": "Allow storage permission for Status Saver", 26 | "openWhatsAppLabel": "Open WhatsApp", 27 | "openW4BLabel": "Open WhatsApp Business", 28 | "doNotHaveSeenStatusesMessage": "You do not have seen any statuses yet, go and watch some statuses", 29 | "systemThemeLabel": "System Theme", 30 | "lightThemeLabel": "Light Theme", 31 | "darkThemeLabel": "Dark Theme", 32 | "exitButtonLabel": "EXIT", 33 | "exitWarningTitle": "Exit StatusSaver", 34 | "exitWarningMessage": "Are you sure you want to exit ?", 35 | "deleteButtonLabel": "DELETE", 36 | "deleteStatusWarningTitle": "Delete Status", 37 | "deleteStatusWarningMessage": "Do you want to permanently delete this status ?", 38 | "deletedStatusMessage": "Status Deleted" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_es.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "¡Hola Mundo!", 3 | "appTitle": "Ahorrador de Estados", 4 | "recentStatuses": "Recientes", 5 | "savedStatuses": "Guardados", 6 | "statusSavedMessage": "Estado guardado", 7 | "noSavedStatusesMessage": "No hay estados guardados", 8 | "noWhatsappFoundMessage": "WhatsApp no existe en tu móvil", 9 | "appLanguageLabel": "Idioma de la aplicación", 10 | "saveButtonLabel": "Guardar", 11 | "shareButtonLabel": "Compartir", 12 | "okButtonLabel": "Aceptar", 13 | "cancelButtonLabel": "Cancelar", 14 | "closeButtonLabel": "Cerrar", 15 | "howDoesItWorkTitle": "¿Cómo funciona?", 16 | "howDoesItWorkDescription": "No estamos afiliados ni conectados oficialmente de ninguna manera con WhatsApp Inc. Y no tenemos acceso a tus mensajes de WhatsApp.\n\nEsta aplicación está destinada a proporcionarte una forma más conveniente de explorar, guardar y compartir las imágenes y videos de estados almacenados en tu dispositivo.", 17 | "aboutButtonLabel": "Acerca de la aplicación", 18 | "appThemeModeLabel": "Modo de tema de la aplicación", 19 | "systemDefaultLabel": "Predeterminado del sistema", 20 | "couldNotSaveYourLanguagePreference": "No se pudo guardar tu preferencia de idioma", 21 | "couldNotSaveYourThemePreference": "No se pudo guardar tu preferencia de tema", 22 | "giveStoragePermission": "Dar permiso de almacenamiento", 23 | "needToGiveStoragePermission": "Necesitas otorgar permisos de almacenamiento para esta aplicación.", 24 | "couldNotOpenAppSettings": "No se pudo abrir la configuración de la aplicación para el permiso de almacenamiento.", 25 | "allowStoragePermission": "Permitir permiso de almacenamiento para Ahorrador de Estados", 26 | "openWhatsAppLabel": "Abrir WhatsApp", 27 | "openW4BLabel": "Abrir WhatsApp Business", 28 | "doNotHaveSeenStatusesMessage": "Aún no has visto ningún estado, ve y mira algunos estados", 29 | "systemThemeLabel": "Tema del sistema", 30 | "lightThemeLabel": "Tema claro", 31 | "darkThemeLabel": "Tema oscuro", 32 | "exitButtonLabel": "SALIR", 33 | "exitWarningTitle": "Salir de StatusSaver", 34 | "exitWarningMessage": "¿Estás seguro de que quieres salir?", 35 | "deleteButtonLabel": "ELIMINAR", 36 | "deleteStatusWarningTitle": "Eliminar Estado", 37 | "deleteStatusWarningMessage": "¿Deseas eliminar permanentemente este estado?", 38 | "deletedStatusMessage": "Estado Eliminado" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_gu.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "હેલો વર્લ્ડ!", 3 | "appTitle": "સ્ટેટસ સેવર", 4 | "recentStatuses": "તાજેતરની", 5 | "savedStatuses": "સંગ્રહિત", 6 | "statusSavedMessage": "સ્ટેટસ સંગ્રહિત થઇ ગઈ", 7 | "noSavedStatusesMessage": "કોઈ સંગ્રહિત સ્ટેટસઓ નથી", 8 | "noWhatsappFoundMessage": "તમારી મોબાઇલમાં વોટ્સએપ અસ્તિત્વમાં નથી", 9 | "appLanguageLabel": "ઍપ ભાષા", 10 | "saveButtonLabel": "સંગ્રહ કરો", 11 | "shareButtonLabel": "શેર કરો", 12 | "okButtonLabel": "ઠીક છે", 13 | "cancelButtonLabel": "રદ કરો", 14 | "closeButtonLabel": "બંધ કરો", 15 | "howDoesItWorkTitle": "તે કેમ કામ કરે છે?", 16 | "howDoesItWorkDescription": "અમે કોઈપણ રીતે વોટ્સએપ Inc સાથે સંબંધિત અથવા આધિકારિકપણે જોડાયેલ નથી. અને અમારી કોઈપણ વોટ્સએપ સંદેશો પર કોઈપણ ઍક્સેસ નથી.\n\nઆ એપ્લિકેશન તમને આપના ડિવાઇસ સ્ટોરેજમાં સંગ્રહિત સ્ટેટસ છબીઓ અને વિડિઓઝ ને અવગણવા, સંગ્રહિત કરવા અને શેર કરવાની વધારાની સાધની પૂરી કરવાની માટે છે.", 17 | "aboutButtonLabel": "ઍપ વિશે", 18 | "appThemeModeLabel":"ઍપ થીમ મોડ", 19 | "systemDefaultLabel": "સિસ્ટમ ડિફોલ્ટ", 20 | "couldNotSaveYourLanguagePreference": "તમારી ભાષાની પસંદગી સંગ્રહિત કરી શકી નથી", 21 | "couldNotSaveYourThemePreference": "તમારી થીમ પસંદગી સંગ્રહિત કરી શકી નથી", 22 | "giveStoragePermission": "સંગ્રહણ માટે પરવાનગી આપો", 23 | "needToGiveStoragePermission": "આ ઍપ્લિકેશન માટે તમને સંગ્રહણ પરવાનગી આપવી આવશ્યક છે.", 24 | "couldNotOpenAppSettings": "સંગ્રહણ પરવાનગી માટે ઍપ સેટિંગ્સ ખોલી શકાતી નથી.", 25 | "allowStoragePermission": "સ્ટેટસ સંગ્રહક માટે સંગ્રહણ પરવાનગી આપો", 26 | "openWhatsAppLabel": "વોટ્સએપ ખોલો", 27 | "openW4BLabel": "વોટ્સએપ બિઝનેસ ખોલો", 28 | "doNotHaveSeenStatusesMessage": "તમે હજી સુધી કોઈ સ્થિતિઓ જોવા નથી, થોડી સ્થિતિઓ જોવા જાઓ", 29 | "systemThemeLabel": "સિસ્ટમ થીમ", 30 | "lightThemeLabel": "લાઇટ થીમ", 31 | "darkThemeLabel": "ડાર્ક થીમ", 32 | "exitButtonLabel": "બહાર નીકળો", 33 | "exitWarningTitle": "સ્થિતિસંગ્રાહકને બંધ કરો", 34 | "exitWarningMessage": "શું તમે ખરેખર બહાર નીકળવા માંગો છો?", 35 | "deleteButtonLabel": "કાઢી નાખો", 36 | "deleteStatusWarningTitle": "સ્થિતિ કાઢી નાખો", 37 | "deleteStatusWarningMessage": "શું તમે આ સ્થિતિને કાયમરી રૂપે કાઢી નાખવા માંગો છો?", 38 | "deletedStatusMessage": "સ્થિતિ કાઢી નાખી દેવાયેલ" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_hi.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "नमस्ते दुनिया!", 3 | "appTitle": "स्टेटस सेवर", 4 | "recentStatuses": "हाल के स्टेटस", 5 | "savedStatuses": "सेव की गई स्टेटस", 6 | "statusSavedMessage": "स्टेटस सेव हो गई है", 7 | "noSavedStatusesMessage": "कोई सेव की गई स्टेटस नहीं", 8 | "noWhatsappFoundMessage": "आपके मोबाइल में व्हाट्सएप मौजूद नहीं है", 9 | "appLanguageLabel": "ऐप भाषा", 10 | "saveButtonLabel": "सेव करें", 11 | "shareButtonLabel": "शेयर करें", 12 | "okButtonLabel": "ठीक है", 13 | "cancelButtonLabel": "रद्द करें", 14 | "closeButtonLabel": "बंद करें", 15 | "howDoesItWorkTitle": "यह कैसे काम करता है?", 16 | "howDoesItWorkDescription": "हम व्हाट्सएप Inc से किसी भी तरीके से संबंधित या आधिकारिक रूप से जुड़े नहीं हैं। और, हमें आपके व्हाट्सएप संदेशों का कोई पहुंच नहीं है।\n\nयह एप्लिकेशन आपको उन स्टेटस छवियों और वीडियोज़ को खोजने, संग्रहीत करने और शेयर करने के लिए एक आसान तरीके से प्रदान करने के उद्देश्य से बनाई गई है, जो आपके डिवाइस स्टोरेज में कैश किए गए हैं।", 17 | "aboutButtonLabel": "ऐप के बारे में", 18 | "appThemeModeLabel":"ऐप थीम मोड", 19 | "systemDefaultLabel": "सिस्टम डिफ़ॉल्ट", 20 | "couldNotSaveYourLanguagePreference": "आपकी भाषा प्राथमिकता सहेजने में असमर्थ", 21 | "couldNotSaveYourThemePreference": "आपकी थीम प्राथमिकता सहेजने में असमर्थ", 22 | "giveStoragePermission": "संग्रहण अनुमति दें", 23 | "needToGiveStoragePermission": "आपको इस ऐप्लिकेशन के लिए संग्रहण अनुमतियों की आवश्यकता है।", 24 | "couldNotOpenAppSettings": "संग्रहण अनुमति के लिए ऐप सेटिंग्स नहीं खोल सका।", 25 | "allowStoragePermission": "स्टेटस सेवर के लिए संग्रहण अनुमति दें", 26 | "openWhatsAppLabel": "व्हाट्सएप खोलें", 27 | "openW4BLabel": "व्हाट्सएप बिजनेस खोलें", 28 | "doNotHaveSeenStatusesMessage": "आपने अबतक कोई स्थिति नहीं देखी है, कुछ स्थितियाँ देखें", 29 | "systemThemeLabel": "सिस्टम थीम", 30 | "lightThemeLabel": "लाइट थीम", 31 | "darkThemeLabel": "डार्क थीम", 32 | "exitButtonLabel": "बाहर निकलें", 33 | "exitWarningTitle": "स्थिति संग्रहक से बाहर निकलें", 34 | "exitWarningMessage": "क्या आप निश्चित रूप से बाहर निकलना चाहते हैं?", 35 | "deleteButtonLabel": "हटाएं", 36 | "deleteStatusWarningTitle": "स्थिति हटाएं", 37 | "deleteStatusWarningMessage": "क्या आप इस स्थिति को स्थायी रूप से हटाना चाहते हैं?", 38 | "deletedStatusMessage": "स्थिति हटा दी गई" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_ja.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "こんにちは、世界!", 3 | "appTitle": "ステータスセーバー", 4 | "recentStatuses": "最近のステータス", 5 | "savedStatuses": "保存されたステータス", 6 | "statusSavedMessage": "ステータスが保存されました", 7 | "noSavedStatusesMessage": "保存されたステータスはありません", 8 | "noWhatsappFoundMessage": "お使いのモバイルにWhatsAppが存在しません", 9 | "appLanguageLabel": "アプリの言語", 10 | "saveButtonLabel": "保存", 11 | "shareButtonLabel": "共有", 12 | "okButtonLabel": "OK", 13 | "cancelButtonLabel": "キャンセル", 14 | "closeButtonLabel": "閉じる", 15 | "howDoesItWorkTitle": "どのように機能しますか?", 16 | "howDoesItWorkDescription": "当アプリはWhatsApp Incとは関連付けられておらず、公式に接続されていません。また、WhatsAppのメッセージにアクセスする権限もありません。\n\nこのアプリは、デバイスストレージにキャッシュされたステータスの画像や動画を簡単に探索、保存、共有するための便利な方法を提供することを目的としています。", 17 | "aboutButtonLabel": "アプリについて", 18 | "appThemeModeLabel": "アプリのテーマモード", 19 | "systemDefaultLabel": "システムデフォルト", 20 | "couldNotSaveYourLanguagePreference": "言語設定を保存できませんでした", 21 | "couldNotSaveYourThemePreference": "テーマ設定を保存できませんでした", 22 | "giveStoragePermission": "ストレージの許可を与える", 23 | "needToGiveStoragePermission": "このアプリケーションにはストレージの許可が必要です。", 24 | "couldNotOpenAppSettings": "ストレージの許可のためのアプリの設定を開くことができませんでした。", 25 | "allowStoragePermission": "ステータスセーバーにストレージの許可を与える", 26 | "openWhatsAppLabel": "WhatsAppを開く", 27 | "openW4BLabel": "WhatsApp Businessを開く", 28 | "doNotHaveSeenStatusesMessage": "まだステータスを閲覧していません。いくつかのステータスを見てください", 29 | "systemThemeLabel": "システムテーマ", 30 | "lightThemeLabel": "ライトテーマ", 31 | "darkThemeLabel": "ダークテーマ", 32 | "exitButtonLabel": "終了", 33 | "exitWarningTitle": "StatusSaverを終了する", 34 | "exitWarningMessage": "本当に終了しますか?", 35 | "deleteButtonLabel": "削除", 36 | "deleteStatusWarningTitle": "ステータスの削除", 37 | "deleteStatusWarningMessage": "このステータスを永久に削除しますか?", 38 | "deletedStatusMessage": "ステータスが削除されました" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_kn.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "ಹಲೋ ವರ್ಲ್ಡ್!", 3 | "appTitle": "ಸ್ಥಿತಿ ಉಳಿಸುವಿಕೆಗಾಗಿ", 4 | "recentStatuses": "ಇತ್ತೀಚಿನ", 5 | "savedStatuses": "ಉಳಿಸಿದ ಸ್ಥಿತಿಗಳು", 6 | "statusSavedMessage": "ಸ್ಥಿತಿ ಉಳಿಸಲಾಗಿದೆ", 7 | "noSavedStatusesMessage": "ಯಾವುದೇ ಉಳಿಸಲಾಗಿದ್ದ ಸ್ಥಿತಿಗಳಿಲ್ಲ", 8 | "noWhatsappFoundMessage": "ನಿಮ್ಮ ಮೊಬೈಲ್‌ನಲ್ಲಿ WhatsApp ಕಂಡುಬರಲಿಲ್ಲ", 9 | "appLanguageLabel": "ಆ್ಯಪ್ ಭಾಷೆ", 10 | "saveButtonLabel": "ಉಳಿಸಿ", 11 | "shareButtonLabel": "ಹಂಚಿಕೆ ಮಾಡಿ", 12 | "okButtonLabel": "ಸರಿ", 13 | "cancelButtonLabel": "ರದ್ದುಮಾಡಿ", 14 | "closeButtonLabel": "ಮುಚ್ಚಿಕೊಳ್ಳುವುದು", 15 | "howDoesItWorkTitle": "ಇದು ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ?", 16 | "howDoesItWorkDescription": "ನೀವು ನಿಮ್ಮ ಸಾಧನದ ನಂತರದ ಸ್ಥಿತಿ ಚಿತ್ರಗಳನ್ನು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಅನ್ವೇಷಿಸಲು, ಉಳಿಸಲು ಮತ್ತು ಹಂಚಿಕೆಯಾಗಲು ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮಗೆ ಇತರ ವ್ಯಾಪ್ತಿಗಳ ಜೊತೆಗೆ ಸಂಬಂಧಿಸಿದ ಸೌಲಭ್ಯವನ್ನು ನೀಡುತ್ತದೆ", 17 | "aboutButtonLabel": "ಆ್ಯಪ್ ಬಗ್ಗೆ", 18 | "appThemeModeLabel": "ಆ್ಯಪ್ ಥೀಮ್ ಮೋಡ್", 19 | "systemDefaultLabel": "ವ್ಯವಸ್ಥೆಯ ಪೂರ್ವನಿಯಮಿತ", 20 | "couldNotSaveYourLanguagePreference": "ನಿಮ್ಮ ಭಾಷಾ ಆದಾಯವನ್ನು ಉಳಿಸಲಾಗಲಿಲ್ಲ", 21 | "couldNotSaveYourThemePreference": "ನಿಮ್ಮ ಥೀಮ್ ಆದಾಯವನ್ನು ಉಳಿಸಲಾಗಲಿಲ್ಲ", 22 | "giveStoragePermission": "ಸಂಗ್ರಹ ಅನುಮತಿಯನ್ನು ನೀಡಿ", 23 | "needToGiveStoragePermission": "ಈ ಅಪ್ಲಿಕೇಶನ್ ಗೆ ನೀವು ಸಂಗ್ರಹ ಅನುಮತಿ ನೀಡಬೇಕಾಗಿದೆ.", 24 | "couldNotOpenAppSettings": "ಸಂಗ್ರಹ ಅನುಮತಿಗಾಗಿ ಆ್ಯಪ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರವಲೇರುವುದಿಲ್ಲ", 25 | "allowStoragePermission": "ಸಂಗ್ರಹ ಅನುಮತಿಯನ್ನು ನೀಡಿ Status Saver ಗೆ", 26 | "openWhatsAppLabel": "WhatsApp ತೆರವಿಗೆ", 27 | "openW4BLabel": "WhatsApp Business ತೆರವಿಗೆ", 28 | "doNotHaveSeenStatusesMessage": "ನೀವು ಯಾವುದೇ ಸ್ಥಿತಿಗಳನ್ನು ನೋಡಿಲ್ಲ, ಕೆಲವು ಸ್ಥಿತಿಗಳನ್ನು ನೋಡಲು ಹೋಗಿ", 29 | "systemThemeLabel": "ವ್ಯವಸ್ಥೆಯ ಥೀಮ್", 30 | "lightThemeLabel": "ಹೆಣ್ಣು ಥೀಮ್", 31 | "darkThemeLabel": "ಕತ್ತಲ ಥೀಮ್", 32 | "exitButtonLabel": "ನಿರ್ಗಮಿಸು", 33 | "exitWarningTitle": "ಸ್ಥಿತಿಸಂಗ್ರಹಕವನ್ನು ನಿರ್ಗಮಿಸಿ", 34 | "exitWarningMessage": "ನೀವು ನಿಶ್ಚಯವಾಗಿ ನಿರ್ಗಮಿಸಲು ಬಯಸುವಿರಾ?", 35 | "deleteButtonLabel": "ಅಳಿಸಿ", 36 | "deleteStatusWarningTitle": "ಸ್ಥಿತಿಯನ್ನು ಅಳಿಸಿ", 37 | "deleteStatusWarningMessage": "ನೀವು ಈ ಸ್ಥಿತಿಯನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಬೇಕೆ?", 38 | "deletedStatusMessage": "ಸ್ಥಿತಿ ಅಳಿಸಲಾಗಿದೆ" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_ko.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "안녕, 세상아!", 3 | "appTitle": "상태 저장기", 4 | "recentStatuses": "최근", 5 | "savedStatuses": "저장됨", 6 | "statusSavedMessage": "상태 저장됨", 7 | "noSavedStatusesMessage": "저장된 상태가 없습니다", 8 | "noWhatsappFoundMessage": "당신의 모바일에 WhatsApp이 존재하지 않습니다", 9 | "appLanguageLabel": "앱 언어", 10 | "saveButtonLabel": "저장", 11 | "shareButtonLabel": "공유", 12 | "okButtonLabel": "확인", 13 | "cancelButtonLabel": "취소", 14 | "closeButtonLabel": "닫기", 15 | "howDoesItWorkTitle": "어떻게 작동하나요?", 16 | "howDoesItWorkDescription": "저희는 WhatsApp Inc와 어떠한 제휴 관계도 없으며 공식적으로 연결되어 있지 않습니다. 또한, WhatsApp 메시지에 대한 접근 권한이 없습니다.\n\n이 애플리케이션은 당신의 기기 저장 공간에 캐시된 상태 이미지와 동영상을 더 편리하게 찾아보고 저장하고 공유할 수 있는 방법을 제공하기 위해 만들어졌습니다.", 17 | "aboutButtonLabel": "앱 정보", 18 | "appThemeModeLabel": "앱 테마 모드", 19 | "systemDefaultLabel": "시스템 기본값", 20 | "couldNotSaveYourLanguagePreference": "언어 설정을 저장할 수 없습니다", 21 | "couldNotSaveYourThemePreference": "테마 설정을 저장할 수 없습니다", 22 | "giveStoragePermission": "저장소 권한 부여", 23 | "needToGiveStoragePermission": "이 애플리케이션에 대한 저장소 권한을 부여해야 합니다", 24 | "couldNotOpenAppSettings": "저장소 권한을 위한 앱 설정을 열 수 없습니다", 25 | "allowStoragePermission": "상태 저장기를 위해 저장소 권한 허용", 26 | "openWhatsAppLabel": "WhatsApp 열기", 27 | "openW4BLabel": "WhatsApp Business 열기", 28 | "doNotHaveSeenStatusesMessage": "아직 상태를 보지 않았습니다. 상태를 확인해보세요", 29 | "systemThemeLabel": "시스템 테마", 30 | "lightThemeLabel": "라이트 테마", 31 | "darkThemeLabel": "다크 테마", 32 | "exitButtonLabel": "종료", 33 | "exitWarningTitle": "StatusSaver 종료", 34 | "exitWarningMessage": "정말로 종료하시겠습니까?", 35 | "deleteButtonLabel": "삭제", 36 | "deleteStatusWarningTitle": "상태 삭제", 37 | "deleteStatusWarningMessage": "이 상태를 영구적으로 삭제하시겠습니까?", 38 | "deletedStatusMessage": "상태가 삭제되었습니다" 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_mr.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "हॅलो वर्ल्ड!", 3 | "appTitle": "स्थिती सेव्हर", 4 | "recentStatuses": "नवीन", 5 | "savedStatuses": "सेव्ह केलेले स्थिती", 6 | "statusSavedMessage": "स्थिती सेव्ह केली", 7 | "noSavedStatusesMessage": "कोणतीही सेव्ह केलेली स्थिती नाहीत", 8 | "noWhatsappFoundMessage": "आपल्या मोबाइलवर व्हॉट्सऐप उपलब्ध नाही", 9 | "appLanguageLabel": "अ‍ॅप भाषा", 10 | "saveButtonLabel": "सेव्ह करा", 11 | "shareButtonLabel": "सामायिक करा", 12 | "okButtonLabel": "ठीक आहे", 13 | "cancelButtonLabel": "रद्द करा", 14 | "closeButtonLabel": "बंद करा", 15 | "howDoesItWorkTitle": "हे कसे कार्य करते?", 16 | "howDoesItWorkDescription": "आम्ही कोणत्याही प्रकारच्या व्हॉट्सऐप इंकचे अधिकारीक आणि संबद्ध नाही. आणि, आमच्याकडे आपल्या व्हॉट्सऐप संदेशांसाठी कोणतेही प्रवेश नाही.\n\nया अॅपलिकेशनमध्ये आपल्याला आपल्या डिव्हाइसवर संग्रहित केलेल्या स्थितीचे चित्र आणि व्हिडिओ अन्वेषण, सेव्ह आणि सामायिक करण्यासाठी एक सोपे मार्ग पुरविते", 17 | "aboutButtonLabel": "अॅपबद्दल", 18 | "appThemeModeLabel": "अॅप थीम मोड", 19 | "systemDefaultLabel": "सिस्टम डिफॉल्ट", 20 | "couldNotSaveYourLanguagePreference": "आपली भाषा प्राधान्य वाचवता येऊ शकली नाही", 21 | "couldNotSaveYourThemePreference": "आपली थीम प्राधान्य वाचवता येऊ शकली नाही", 22 | "giveStoragePermission": "संग्रह अनुमती द्या", 23 | "needToGiveStoragePermission": "या अ‍ॅपच्या साठी आपल्याला संग्रह अनुमती द्यावी लागेल.", 24 | "couldNotOpenAppSettings": "संग्रह अनुमतीसाठी अ‍ॅप सेटिंग्ज उघडू शकत नाहीत.", 25 | "allowStoragePermission": "स्थिती सेव्हरसाठी संग्रह अनुमती द्या", 26 | "openWhatsAppLabel": "व्हॉट्सऐप उघडा", 27 | "openW4BLabel": "व्हॉट्सऐप व्यवसाय उघडा", 28 | "doNotHaveSeenStatusesMessage": "आपण अद्याप पाहिलेल्या कोणत्याही स्थितींना नाहीत, जा आणि काही स्थिती पाहा", 29 | "systemThemeLabel": "सिस्टम थीम", 30 | "lightThemeLabel": "प्रकाश थीम", 31 | "darkThemeLabel": "डार्क थीम", 32 | "exitButtonLabel": "बंद करा", 33 | "exitWarningTitle": "बाहेर पडणे स्थितीसेव्हर", 34 | "exitWarningMessage": "तुम्ही खरंतर बाहेर पडायला आवडता आहात का?", 35 | "deleteButtonLabel": "काढून टाका", 36 | "deleteStatusWarningTitle": "स्थिती काढून टाका", 37 | "deleteStatusWarningMessage": "तुम्हाला हे स्थिती कायमच्या निर्मितीचे काढून टाकायला आवडते का?", 38 | "deletedStatusMessage": "स्थिती काढून टाकली आहे" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_pa.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "ਸਤ ਸ੍ਰੀ ਅਕਾਲ ਦੁਨਿਆ!", 3 | "appTitle": "ਸਥਿਤੀ ਸੇਵਰ", 4 | "recentStatuses": "ਤਾਜ਼ਾ", 5 | "savedStatuses": "ਸੰਭਾਲੇ ਹੋਏ ਸਥਿਤੀਆਂ", 6 | "statusSavedMessage": "ਸਥਿਤੀ ਸੰਭਾਲੀ ਗਈ", 7 | "noSavedStatusesMessage": "ਕੋਈ ਸੰਭਾਲੀ ਗਈ ਸਥਿਤੀਆਂ ਨਹੀਂ", 8 | "noWhatsappFoundMessage": "ਤੁਹਾਡੇ ਮੋਬਾਈਲ ਵਿੱਚ ਵਾਟਸਐਪ ਮੌਜੂਦ ਨਹੀਂ ਹੈ", 9 | "appLanguageLabel": "ਐਪ ਭਾਸ਼ਾ", 10 | "saveButtonLabel": "ਸੰਭਾਲੋ", 11 | "shareButtonLabel": "ਸਾਂਝਾ ਕਰੋ", 12 | "okButtonLabel": "ਠੀਕ ਹੈ", 13 | "cancelButtonLabel": "ਰੱਦ ਕਰੋ", 14 | "closeButtonLabel": "ਬੰਦ ਕਰੋ", 15 | "howDoesItWorkTitle": "ਇਹ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ?", 16 | "howDoesItWorkDescription": "ਅਸੀਂ ਕਿਸੇ ਵੀ ਢੰਗ ਨਾਲ ਵਾਟਸਐਪ ਇੰਕ ਨਾਲ ਜੁੜੇ ਨਹੀਂ ਹਾਂ. ਅਤੇ ਸਾਨੂੰ ਤੁਹਾਡੇ ਵਾਟਸਐਪ ਸੁਨੇਹਾਂ ਤੱਕ ਕੋਈ ਪਹੁੰਚ ਨਹੀਂ ਹੈ।\n\nਇਹ ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਸਟੋਰੇਜ਼ ਵਿੱਚ ਕੈਸ਼ ਕੀਤੀ ਗਈ ਸਥਿਤੀ ਚਿੱਤਰ ਅਤੇ ਵੀਡੀਓ ਦੇ ਖੋਜ, ਸੰਭਾਲ ਅਤੇ ਸਾਂਝਾ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਇਕ ਵਧੀਆ ਤਰੀਕਾ ਪ੍ਰਦਾਨ ਕਰਨ ਦਾ ਉਦੇਸ਼ ਰੱਖਦਾ ਹੈ।", 17 | "aboutButtonLabel": "ਐਪ ਬਾਰੇ", 18 | "appThemeModeLabel":"ਐਪ ਥੀਮ ਮੋਡ", 19 | "systemDefaultLabel": "ਸਿਸਟਮ ਡਿਫਾਲਟ", 20 | "couldNotSaveYourLanguagePreference": "ਤੁਹਾਡੀ ਭਾਸ਼ਾ ਪਸੰਦ ਸੰਭਾਲਣ ਵਿੱਚ ਅਸਮਰੱਥ ਰਹੀ", 21 | "couldNotSaveYourThemePreference": "ਤੁਹਾਡੀ ਥੀਮ ਪਸੰਦ ਸੰਭਾਲਣ ਵਿੱਚ ਅਸਮਰੱਥ ਰਹੀ", 22 | "giveStoragePermission": "ਸਟੋਰੇਜ਼ ਅਨੁਮਤੀ ਦਿਓ", 23 | "needToGiveStoragePermission": "ਇਸ ਐਪਲੀਕੇਸ਼ਨ ਲਈ ਤੁਹਾਨੂੰ ਸਟੋਰੇਜ਼ ਅਨੁਮਤੀ ਦੇਣੀ ਲੋੜ ਹੈ।", 24 | "couldNotOpenAppSettings": "ਸਟੋਰੇਜ਼ ਅਨੁਮਤੀ ਲਈ ਐਪ ਸੈਟਿੰਗਾਂ ਨੂੰ ਖੋਲਣਾ ਸਮੰਭਵ ਨਹੀਂ ਹੋਇਆ।", 25 | "allowStoragePermission": "ਸਥਿਤੀ ਸੇਵਰ ਲਈ ਸਟੋਰੇਜ਼ ਅਨੁਮਤੀ ਦਿਓ", 26 | "openWhatsAppLabel": "ਵਾਟਸਐਪ ਖੋਲੋ", 27 | "openW4BLabel": "ਵਾਟਸਐਪ ਵਾਪਾਰ ਖੋਲੋ", 28 | "doNotHaveSeenStatusesMessage": "ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਥਿਤੀਆਂ ਦੇਖੀਆਂ ਨਹੀਂ ਗਈਆਂ ਹਨ, ਜਾਓ ਅਤੇ ਕੁਝ ਸਥਿਤੀਆਂ ਵੇਖੋ", 29 | "systemThemeLabel": "ਸਿਸਟਮ ਥੀਮ", 30 | "lightThemeLabel": "ਹਲਕੀ ਥੀਮ", 31 | "darkThemeLabel": "ਅੰਧਕਾਰ ਥੀਮ", 32 | "exitButtonLabel": "ਬਾਹਰ ਜਾਓ", 33 | "exitWarningTitle": "ਸਥਿਤੀ ਸੇਵਰ ਤੋਂ ਬਾਹਰ ਜਾਓ", 34 | "exitWarningMessage": "ਕੀ ਤੁਸੀਂ ਪੁਸ਼ਟੀ ਕਰਦੇ ਹੋ ਕਿ ਤੁਸੀਂ ਬਾਹਰ ਜਾਣਾ ਚਾਹੁੰਦੇ ਹੋ?", 35 | "deleteButtonLabel": "ਹਟਾਓ", 36 | "deleteStatusWarningTitle": "ਸਥਿਤੀ ਹਟਾਓ", 37 | "deleteStatusWarningMessage": "ਕੀ ਤੁਸੀਂ ਇਹ ਸਥਿਤੀ ਪੱਕੇ ਤੌਰ 'ਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", 38 | "deletedStatusMessage": "ਸਥਿਤੀ ਹਟਾਈ ਗਈ ਹੈ" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_ta.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "ஹலோ உலகம்!", 3 | "appTitle": "ஸ்டேட்டஸ் சேவர்", 4 | "recentStatuses": "சமீபத்தியமான", 5 | "savedStatuses": "சேமித்த ஸ்டேட்டஸ்கள்", 6 | "statusSavedMessage": "ஸ்டேட்டஸ் சேமிக்கப்பட்டது", 7 | "noSavedStatusesMessage": "சேமித்த ஸ்டேட்டஸ்கள் இல்லை", 8 | "noWhatsappFoundMessage": "உங்கள் மொபைலில் WhatsApp இல்லை", 9 | "appLanguageLabel": "பயன்பாட்டின் மொழி", 10 | "saveButtonLabel": "சேமி", 11 | "shareButtonLabel": "பகிர்", 12 | "okButtonLabel": "சரி", 13 | "cancelButtonLabel": "ரத்துசெய்", 14 | "closeButtonLabel": "மூடு", 15 | "howDoesItWorkTitle": "இது எப்படி வேலை செய்கிறது?", 16 | "howDoesItWorkDescription": "மாற்றம் முடிவடைந்த நிலைப்பாடுகளைக் காண, சேமி மற்றும் பகிர்ந்துகொள்ள உங்கள் சாதாரண நிலை மொபைலின் சேமிப்புக்களில் இருக்கும் படங்களும் காட்சிகளை பாதுகாக்கும்படி இந்த பயன்பாட்டை வழங்க எங்கள் எந்தக் கைமுறையும் கையாளப்படவில்லை என்பது என்னவெனில். மேலும், உங்கள் WhatsApp செயல்பாட்டுகளுக்கு எங்கள் எந்தக் கையாளும் இல்லை.\n\nஇந்த பயன்பாட்டின் மூலம், நீங்கள் மொபைலின் சேமிப்புகளில் பதிவு செய்த ஸ்டேட்டஸ் படங்கள் மற்றும் காட்சிகளை வேர்வையிட மேலும் செமானான வழியை வழங்க மேலும் செமானான வழியை வழங்க முயற்சிக்கின்றது", 17 | "aboutButtonLabel": "பயன்பாட்டு பற்றி", 18 | "appThemeModeLabel": "பயன்பாட்டின் தீம் முறை", 19 | "systemDefaultLabel": "முக்கிய அமைப்பு", 20 | "couldNotSaveYourLanguagePreference": "உங்கள் மொழி விருப்பத்தை சேமிக்க முடியவில்லை", 21 | "couldNotSaveYourThemePreference": "உங்கள் தீம் விருப்பத்தை சேமிக்க முடியவில்லை", 22 | "giveStoragePermission": "சேமிப்பு அனுமதியைப் பயன்படுத்துக", 23 | "needToGiveStoragePermission": "இந்த பயன்பாட்டுக்கு நீங்கள் சேமிப்பு அனுமதியை அளிக்க வேண்டும்.", 24 | "couldNotOpenAppSettings": "சேமிப்பு அனுமதி மறுக்க பயன்பாட்டு அமை ப்புகளை திறக்க முடியவில்லை.", 25 | "allowStoragePermission": "ஸ்டேட்டஸ் சேவர் சேமிப்பு அனுமதியை அனுமதிக்க", 26 | "openWhatsAppLabel": "WhatsApp ஐ திறக்கவும்", 27 | "openW4BLabel": "வாட்ஸ்அப் பிரின்ஸை திறக்கவும்", 28 | "doNotHaveSeenStatusesMessage": "நீங்கள் எந்த ஸ்டேட்டஸ்களையும் பார்க்கவில்லை, சில ஸ்டேட்டஸ்களை பார்க்கவும்", 29 | "systemThemeLabel": "முக்கிய தீம்", 30 | "lightThemeLabel": "ஒளியான தீம்", 31 | "darkThemeLabel": "இருண்ட தீம்", 32 | "exitButtonLabel": "வெளியேறு", 33 | "exitWarningTitle": "நிறுவுவதை வெளியேறு", 34 | "exitWarningMessage": "நீங்கள் உறுதியாக வெளியேற விரும்புகிறீர்களா?", 35 | "deleteButtonLabel": "நீக்கு", 36 | "deleteStatusWarningTitle": "நிலையை நீக்கு", 37 | "deleteStatusWarningMessage": "இந்த நிலையை நிரந்தரமாக நீக்க விரும்புகிறீர்களா?", 38 | "deletedStatusMessage": "நிலை நீக்கப்பட்டது" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_te.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "హలో ప్రపంచం!", 3 | "appTitle": "స్థితి సేవరకు", 4 | "recentStatuses": "ఇటీవలి", 5 | "savedStatuses": "సేవ్ చేసిన స్థితులు", 6 | "statusSavedMessage": "స్థితి సేవ్ చేయబడింది", 7 | "noSavedStatusesMessage": "సేవ్ చేయబడని స్థితులు లేవు", 8 | "noWhatsappFoundMessage": "మీ మొబైల్‌లో WhatsApp లేదు", 9 | "appLanguageLabel": "యాప్ భాష", 10 | "saveButtonLabel": "సేవ్ చేయండి", 11 | "shareButtonLabel": "షేర్ చేయండి", 12 | "okButtonLabel": "సరే", 13 | "cancelButtonLabel": "రద్దు చేయండి", 14 | "closeButtonLabel": "మూసివేయి", 15 | "howDoesItWorkTitle": "ఇది ఎలా పని చేస్తుంది?", 16 | "howDoesItWorkDescription": "మీ పరికరంలో ఉన్న క్యాష్ చేసిన స్థితి చిత్రాలు మరియు వీడియోలను అన్వేషించడం, సేవ్ చేయడం మరియు షేర్ చేయడం కోసం మీకు ఇతర యాప్‌నుతో సంబంధించినందున ఏంపికలను అందిస్తుంది", 17 | "aboutButtonLabel": "యాప్ గురించి", 18 | "appThemeModeLabel": "యాప్ థీమ్ మోడ్", 19 | "systemDefaultLabel": "సిస్టమ్ డిఫాల్ట్", 20 | "couldNotSaveYourLanguagePreference": "మీ భాష ప్రాధాన్యతను సేవ్ చేయలేరు", 21 | "couldNotSaveYourThemePreference": "మీ థీమ్ ప్రాధాన్యతను సేవ్ చేయలేరు", 22 | "giveStoragePermission": "స్థిరానికి అనుమతించండి", 23 | "needToGiveStoragePermission": "ఈ అప్లికేషన్ కోసం మీకు స్థిరాన్ని అనుమతించాలి.", 24 | "couldNotOpenAppSettings": "స్థిరా అనుమతి కోసం అప్లికేషన్ సెట్టింగ్లను తెరవలేరు.", 25 | "allowStoragePermission": "స్థిరా అనుమతించండి స్థితి సేవకు", 26 | "openWhatsAppLabel": "WhatsApp తెరవండి", 27 | "openW4BLabel": "WhatsApp వ్యాపారాన్ని తెరవండి", 28 | "doNotHaveSeenStatusesMessage": "మీరు ఏమి స్థితులను చూడలేదు, కొనసాగిపోవడానికి స్థితులను చూడండి", 29 | "systemThemeLabel": "సిస్టమ్ థీమ్", 30 | "lightThemeLabel": "లైట్ థీమ్", 31 | "darkThemeLabel": "డార్క్ థీమ్", 32 | "exitButtonLabel": "నిష్క్రమించు", 33 | "exitWarningTitle": "పరిస్థితి సేవకి నిష్క్రమించండి", 34 | "exitWarningMessage": "నిజంగా నిష్క్రమించాలని మీరు ఖచ్చితంగా ఉంచారా?", 35 | "deleteButtonLabel": "తొలగించు", 36 | "deleteStatusWarningTitle": "స్థితిని తొలగించండి", 37 | "deleteStatusWarningMessage": "మీరు ఈ స్థితిని శాశ్వతంగా తొలగించాలని మీరు కోరుకుంటున్నారా?", 38 | "deletedStatusMessage": "స్థితి తొలగబడింది" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/app_ur.arb: -------------------------------------------------------------------------------- 1 | { 2 | "helloWorld": "ہیلو ورلڈ!", 3 | "appTitle": "سٹیٹس سیو کرنے والا", 4 | "recentStatuses": "حالیہ", 5 | "savedStatuses": "محفوظ شدہ", 6 | "statusSavedMessage": "حالت محفوظ کر دی گئی", 7 | "noSavedStatusesMessage": "کوئی محفوظ شدہ حالتیں نہیں", 8 | "noWhatsappFoundMessage": "آپ کے موبائل پر واٹس ایپ موجود نہیں ہے", 9 | "appLanguageLabel": "اپلیکیشن کی زبان", 10 | "saveButtonLabel": "محفوظ کریں", 11 | "shareButtonLabel": "شئیر کریں", 12 | "okButtonLabel": "ٹھیک ہے", 13 | "cancelButtonLabel": "منسوخ کریں", 14 | "closeButtonLabel": "بند کریں", 15 | "howDoesItWorkTitle": "یہ کام کیسے کرتا ہے؟", 16 | "howDoesItWorkDescription": "ہم WhatsApp انک سے کسی بھی طرح تعلق نہیں رکھتے ہیں۔ اور ہمیں آپ کے واٹس ایپ پیغاموں تک رسائی کا کوئی راستہ نہیں ہے۔\n\nیہ ایپلیکیشن آپ کو آپ کی ڈیوائس میں ذخیرہ ہونے والی حالتوں کی تصاویر اور ویڈیوز کو کھولنے، محفوظ کرنے اور شئیر کرنے کا آسان ترین طریقہ فراہم کرنے کے لئے تشکیل دی گئی ہے", 17 | "aboutButtonLabel": "اے پی پر معلومات", 18 | "appThemeModeLabel": "اے پی کا تھیم موڈ", 19 | "systemDefaultLabel": "سسٹم ڈیفالٹ", 20 | "couldNotSaveYourLanguagePreference": "آپ کی زبان کی ترجیح محفوظ نہیں کی جا سکی", 21 | "couldNotSaveYourThemePreference": "آپ کی تھیم کی ترجیح محفوظ نہیں کی جا سکی", 22 | "giveStoragePermission": "ذخیرہ کی اجازت دیں", 23 | "needToGiveStoragePermission": "اس ایپلیکیشن کے لئے آپ کو ذخیرہ کی اجازت دینے کی ضرورت ہے۔", 24 | "couldNotOpenAppSettings": "ذخیرہ کی اجازت کے لئے ایپ کی ترتیبات کھولنے میں ناکامی", 25 | "allowStoragePermission": "سٹیٹس سیو کرنے والے کو ذخیرہ کی اجازت دیں", 26 | "openWhatsAppLabel": "واٹس ایپ کھولیں", 27 | "openW4BLabel": "واٹس ایپ بزنس کھولیں", 28 | "doNotHaveSeenStatusesMessage": "آپ نے ابھی تک کوئی حالت دیکھی نہیں ہے، جائیں اور کچھ حالتوں کو دیکھیں", 29 | "systemThemeLabel": "سسٹم تھیم", 30 | "lightThemeLabel": "روشنی کا تھیم", 31 | "darkThemeLabel": "تاریک تھیم", 32 | "exitButtonLabel": "بند کریں", 33 | "exitWarningTitle": "اسٹیٹس سیو کرنے والے سے باہر نکلیں", 34 | "exitWarningMessage": "کیا آپ واقعی بند کرنا چاہتے ہیں؟", 35 | "deleteButtonLabel": "حذف کریں", 36 | "deleteStatusWarningTitle": "حالت کو حذف کریں", 37 | "deleteStatusWarningMessage": "کیا آپ اس حالت کو مستقل طور پر حذف کرنا چاہتے ہیں؟", 38 | "deletedStatusMessage": "حالت حذف کردی گئی ہے" 39 | } -------------------------------------------------------------------------------- /lib/src/localization/l10n/l10n.dart: -------------------------------------------------------------------------------- 1 | 2 | import "package:flutter/material.dart"; 3 | import "package:status_saver/src/localization/enums/language_code.dart"; 4 | import "package:status_saver/src/localization/extensions/on_build_context.dart"; 5 | 6 | class L10n { 7 | static final allSupportedLocales = LanguageCode.values 8 | .map((languageCode) => Locale(languageCode.name)) 9 | .toList(); 10 | 11 | static String? getLanguageName( 12 | LanguageCode languageCode, BuildContext context) { 13 | switch (languageCode) { 14 | case LanguageCode.system: 15 | return context.l10n.systemDefaultLabel; 16 | case LanguageCode.en: 17 | return "English"; 18 | case LanguageCode.hi: 19 | return "हिंदी"; 20 | case LanguageCode.gu: 21 | return "ગુજરાતી"; 22 | case LanguageCode.ko: 23 | return "한국어"; 24 | case LanguageCode.mr: 25 | return "मराठी"; 26 | case LanguageCode.pa: 27 | return "ਪੰਜਾਬੀ"; 28 | case LanguageCode.ta: 29 | return "தமிழ்"; 30 | case LanguageCode.te: 31 | return "తెలుగు"; 32 | case LanguageCode.ja: 33 | return "日本語 (にほんご"; 34 | case LanguageCode.af: 35 | return "Afrikaans"; 36 | case LanguageCode.az: 37 | return "Azərbaycan dili"; 38 | case LanguageCode.bn: 39 | return "বাংলা"; 40 | case LanguageCode.kn: 41 | return "ಕನ್ನಡ"; 42 | case LanguageCode.ur: 43 | return "اردو"; 44 | case LanguageCode.es: 45 | return "Español"; 46 | case LanguageCode.ar: 47 | return "العربية"; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /lib/src/localization/notifiers/locale_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | import 'package:status_saver/src/localization/enums/language_code.dart'; 5 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 6 | import 'package:status_saver/src/localization/extensions/on_string.dart'; 7 | import 'package:status_saver/src/common/helpers/show_toast.dart'; 8 | 9 | const languageCodeKey = "languageCode"; 10 | const defaultLanguageCode = "en"; 11 | const systemLanguageCode = LanguageCode.system; 12 | 13 | // TODO: visit 14 | // https://github.com/bizz84/localization_riverpod_flutter/blob/main/lib/src/localization/app_localizations_provider.dart 15 | class LocaleNotifier extends StateNotifier { 16 | LocaleNotifier() : super(null); 17 | 18 | void initialize() async { 19 | final sharedPreferences = await SharedPreferences.getInstance(); 20 | final String? languageCode = sharedPreferences.getString(languageCodeKey); 21 | if (languageCode != null && 22 | languageCode.toLanguageCode() != systemLanguageCode) { 23 | state = Locale(languageCode); 24 | } 25 | } 26 | 27 | Locale? get locale => state; 28 | 29 | void setLocale(LanguageCode languageCode, BuildContext context) { 30 | if (!LanguageCode.values.contains(languageCode)) return; 31 | 32 | state = 33 | languageCode == systemLanguageCode ? null : Locale(languageCode.name); 34 | SharedPreferences.getInstance().then((sharedPreferences) { 35 | sharedPreferences 36 | .setString(languageCodeKey, languageCode.name) 37 | .then((value) { 38 | if (!value) { 39 | showToast(message: context.l10n.couldNotSaveYourLanguagePreference); 40 | } 41 | }); 42 | }); 43 | } 44 | } 45 | 46 | final localeProvider = StateNotifierProvider( 47 | (ref) => LocaleNotifier()..initialize()); 48 | -------------------------------------------------------------------------------- /lib/src/statuses/notifiers/statuses_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 6 | import 'package:permission_handler/permission_handler.dart'; 7 | import 'package:saf/saf.dart'; 8 | import 'package:status_saver/src/common/helpers/statuses_helper.dart'; 9 | import 'package:status_saver/src/common/helpers/storage_helper.dart'; 10 | import 'package:status_saver/src/debug/console_log.dart'; 11 | import 'package:status_saver/src/home/models/tab_type.dart'; 12 | import 'package:status_saver/src/home/services/android_info_notifier.dart'; 13 | import 'package:status_saver/src/storage_permission/notifiers/storage_permission_notifier.dart'; 14 | 15 | class StatusesNotifier 16 | extends FamilyAsyncNotifier, StatusTabType> { 17 | @override 18 | FutureOr> build(StatusTabType arg) async { 19 | state = const AsyncValue.loading(); 20 | return await getStatuses(); 21 | } 22 | 23 | Future> getStatuses() async { 24 | if (arg == StatusTabType.recent) { 25 | final androidInfo = await ref.watch(androidInfoProvider.future); 26 | List statusesDirAllFiles; 27 | final recentStatusesNotifier = 28 | ref.read(recentStoragePermissionProvider.notifier); 29 | if (androidInfo.isAndroid11OrLater) { 30 | statusesDirAllFiles = 31 | await getStatusesDirFilesFromSaf(recentStatusesNotifier.saf()!); 32 | } else { 33 | statusesDirAllFiles = getDirectoryFilePaths( 34 | recentStatusesNotifier.statusesPath()!, 35 | whereCallback: isItStatusFile, 36 | ); 37 | } 38 | return statusesDirAllFiles.where(isItStatusFile).toList(); 39 | } else if (arg == StatusTabType.saved) { 40 | final savedStatusesNotifier = 41 | ref.read(savedStoragePermissionProvider.notifier); 42 | return getDirectoryFilePaths( 43 | savedStatusesNotifier.statusesPath()!, 44 | whereCallback: isItStatusFile, 45 | ); 46 | } else { 47 | return List.empty(); 48 | } 49 | } 50 | 51 | Future> getStatusesDirFilesFromSaf(Saf saf) async { 52 | try { 53 | await saf.sync(); 54 | List statuses = 55 | await saf.getCachedFilesPath() ?? List.empty(); 56 | return statuses; 57 | } catch (e) { 58 | await saf.releasePersistedPermission(); 59 | ref.read(recentStoragePermissionProvider.notifier).releasePermissions(); 60 | return List.empty(); 61 | } 62 | } 63 | 64 | Future saveStatus(String statusPath) async { 65 | try { 66 | state = const AsyncLoading(); 67 | final String savedStatusPath = getSavedStatusPath(statusPath); 68 | await File(savedStatusPath).create(recursive: true); 69 | await File(statusPath).copy(savedStatusPath); 70 | state = AsyncValue.data(await getStatuses()); 71 | return true; 72 | } catch (_) { 73 | return false; 74 | } 75 | } 76 | 77 | Future deleteStatus(String statusPath) async { 78 | final previousState = state; 79 | try { 80 | final File status = File(statusPath); 81 | state = const AsyncLoading(); 82 | 83 | bool statusFileExists = await status.exists(); 84 | if (!statusFileExists) { 85 | consoleLog("File does not exist at path: $statusPath"); 86 | return true; 87 | } 88 | 89 | debugPrint("file exists: $statusFileExists"); 90 | debugPrint(" file exists on '$statusPath'"); 91 | debugPrint("stat: ${await status.stat()}"); 92 | if (await Permission.storage.request().isGranted) { 93 | await status.delete(recursive: true); 94 | } 95 | consoleLog("Deleted file at path: $statusPath"); 96 | 97 | state = AsyncValue.data(await getStatuses()); 98 | return true; 99 | } catch (e) { 100 | consoleLog(e, "Error deleting file at path: $statusPath"); 101 | state = previousState; 102 | return false; 103 | } 104 | } 105 | } 106 | 107 | final statusesProvider = 108 | AsyncNotifierProvider.family, StatusTabType>( 109 | () => StatusesNotifier()); 110 | 111 | final recentStatusesProvider = statusesProvider(StatusTabType.recent); 112 | final savedStatusesProvider = statusesProvider(StatusTabType.saved); 113 | -------------------------------------------------------------------------------- /lib/src/statuses/views/image_tile.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:status_saver/src/statuses/views/image_view.dart'; 5 | 6 | class ImageTile extends StatelessWidget { 7 | const ImageTile({ 8 | super.key, 9 | required this.imagePath, 10 | }); 11 | 12 | final String imagePath; 13 | @override 14 | Widget build(BuildContext context) { 15 | File imageFile = File(imagePath); 16 | return Card( 17 | elevation: 5, 18 | clipBehavior: Clip.hardEdge, 19 | child: InkWell( 20 | onTap: () { 21 | Navigator.of(context).push( 22 | MaterialPageRoute( 23 | builder: (context) { 24 | // return Text(imagePath); 25 | return ImageView( 26 | imagePath: imagePath, 27 | ); 28 | }, 29 | ), 30 | ); 31 | }, 32 | child: Hero( 33 | tag: imagePath, 34 | child: Image.file( 35 | imageFile, 36 | fit: BoxFit.cover, 37 | ), 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/src/statuses/views/image_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:photo_view/photo_view.dart'; 5 | import 'package:status_saver/src/common/helpers/statuses_helper.dart'; 6 | import 'package:status_saver/src/statuses/views/status_actions.dart'; 7 | 8 | class ImageView extends StatelessWidget { 9 | final String imagePath; 10 | const ImageView({super.key, required this.imagePath}); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Scaffold( 15 | appBar: AppBar( 16 | backgroundColor: Colors.black, 17 | actions: [ 18 | if (isItSavedStatus(imagePath)) 19 | DeleteSavedStatusAction( 20 | statusPath: imagePath, 21 | ) 22 | ], 23 | ), 24 | body: Stack( 25 | clipBehavior: Clip.none, 26 | children: [ 27 | Hero( 28 | tag: imagePath, 29 | child: PhotoView( 30 | minScale: PhotoViewComputedScale.contained * 0.6, 31 | maxScale: PhotoViewComputedScale.contained * 2.5, 32 | imageProvider: FileImage(File(imagePath)), 33 | ), 34 | ), 35 | Positioned( 36 | bottom: 20, 37 | right: 10, 38 | height: MediaQuery.of(context).size.height * 0.2, 39 | child: StatusActions( 40 | statusPath: imagePath, 41 | ), 42 | ), 43 | ], 44 | ), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/statuses/views/status_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:share_plus/share_plus.dart'; 4 | import 'package:status_saver/src/common/helpers/show_toast.dart'; 5 | import 'package:status_saver/src/common/helpers/statuses_helper.dart'; 6 | import 'package:status_saver/src/debug/console_log.dart'; 7 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 8 | import 'package:status_saver/src/statuses/notifiers/statuses_notifier.dart'; 9 | 10 | class StatusActions extends ConsumerWidget { 11 | final String statusPath; 12 | final Future Function()? pauseVideoStatus; 13 | const StatusActions({ 14 | super.key, 15 | required this.statusPath, 16 | this.pauseVideoStatus, 17 | }); 18 | 19 | @override 20 | Widget build(BuildContext context, WidgetRef ref) { 21 | List actions = []; 22 | 23 | // Insert Save status action 24 | final String saveStatusPath = getSavedStatusPath(statusPath); 25 | if (saveStatusPath.compareTo(statusPath) != 0) { 26 | actions.add(FloatingActionButton.extended( 27 | heroTag: null, 28 | onPressed: () async { 29 | ref.read(savedStatusesProvider.notifier).saveStatus(statusPath); 30 | showToast(getMessage: () => context.l10n.statusSavedMessage); 31 | }, 32 | icon: const Icon(Icons.file_download_rounded), 33 | label: Text(context.l10n.saveButtonLabel), 34 | )); 35 | } 36 | 37 | actions.addAll([ 38 | // Insert Share status action 39 | FloatingActionButton.extended( 40 | heroTag: null, 41 | onPressed: () async { 42 | if (statusPath.endsWith(".mp4") && pauseVideoStatus != null) { 43 | await pauseVideoStatus!(); 44 | } 45 | final res = await Share.shareXFiles( 46 | [XFile(statusPath)], 47 | subject: 'Whatsapp Status', 48 | ); 49 | consoleLog(res, "result"); 50 | }, 51 | icon: const Icon(Icons.share_rounded), 52 | label: Text(context.l10n.shareButtonLabel), 53 | ) 54 | ]); 55 | 56 | return Column( 57 | mainAxisAlignment: MainAxisAlignment.spaceAround, 58 | children: actions, 59 | ); 60 | } 61 | } 62 | 63 | class DeleteSavedStatusAction extends ConsumerWidget { 64 | const DeleteSavedStatusAction( 65 | {super.key, required this.statusPath, this.onPressed}); 66 | final String statusPath; 67 | final void Function(Future Function() deleteStatus)? onPressed; 68 | 69 | @override 70 | Widget build(BuildContext context, WidgetRef ref) { 71 | return IconButton( 72 | onPressed: onPressed != null 73 | ? () => onPressed!(() => deleteStatus(context, ref)) 74 | : () => deleteStatus(context, ref), 75 | icon: const Icon( 76 | Icons.delete_forever, 77 | color: Colors.white, 78 | ), 79 | ); 80 | } 81 | 82 | Future deleteStatus(BuildContext context, WidgetRef ref) => 83 | showDialog( 84 | context: context, 85 | barrierDismissible: false, 86 | builder: (context) => AlertDialog( 87 | title: Text(context.l10n.deleteStatusWarningTitle), 88 | content: Text( 89 | context.l10n.deleteStatusWarningMessage, 90 | style: const TextStyle(fontSize: 18), 91 | ), 92 | actions: [ 93 | TextButton( 94 | onPressed: () => Navigator.pop(context), 95 | child: Text(context.l10n.cancelButtonLabel), 96 | ), 97 | TextButton( 98 | onPressed: () { 99 | ref 100 | .read(savedStatusesProvider.notifier) 101 | .deleteStatus(statusPath) 102 | .then((isDeleted) { 103 | Navigator.pop(context); 104 | if (isDeleted) { 105 | Navigator.pop(context); 106 | showToast( 107 | message: context.l10n.deletedStatusMessage, 108 | ); 109 | } else { 110 | showToast( 111 | message: "was not able to delete", 112 | ); 113 | } 114 | }); 115 | }, 116 | child: Text(context.l10n.deleteButtonLabel), 117 | ), 118 | ], 119 | ), 120 | ); 121 | } 122 | -------------------------------------------------------------------------------- /lib/src/statuses/views/statuses_grid_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; 3 | import 'package:status_saver/src/statuses/views/image_tile.dart'; 4 | import 'package:status_saver/src/statuses/views/video_tile.dart'; 5 | 6 | class StatusesGridWidget extends StatelessWidget { 7 | const StatusesGridWidget({ 8 | super.key, 9 | required this.scrollController, 10 | required this.statuses, 11 | required this.noStatusesFoundMessage, 12 | }); 13 | final List statuses; 14 | final ScrollController scrollController; 15 | final String noStatusesFoundMessage; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return statuses.isEmpty 20 | ? Center( 21 | child: Text( 22 | noStatusesFoundMessage, 23 | style: const TextStyle( 24 | fontSize: 18, 25 | ), 26 | ), 27 | ) 28 | : MasonryGridView.count( 29 | controller: scrollController, 30 | cacheExtent: 9999, 31 | padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), 32 | crossAxisCount: 2, 33 | mainAxisSpacing: 1, 34 | crossAxisSpacing: 5, 35 | itemCount: statuses.length, 36 | itemBuilder: (context, index) { 37 | final String statusPath = statuses[index]; 38 | if (statusPath.endsWith(".jpg")) { 39 | return ImageTile(imagePath: statusPath); 40 | } else { 41 | return VideoTile(videoPath: statusPath); 42 | } 43 | }, 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/statuses/views/statuses_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:status_saver/src/common/extensions/async_value.dart'; 4 | import 'package:status_saver/src/home/models/tab_type.dart'; 5 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 6 | import 'package:status_saver/src/statuses/notifiers/statuses_notifier.dart'; 7 | import 'package:status_saver/src/statuses/views/statuses_grid_widget.dart'; 8 | 9 | class StatusesScreen extends ConsumerWidget { 10 | const StatusesScreen({super.key, required this.tabType}); 11 | final StatusTabType tabType; 12 | 13 | @override 14 | Widget build(BuildContext context, WidgetRef ref) { 15 | final statusesProvider = tabType == StatusTabType.recent 16 | ? recentStatusesProvider 17 | : savedStatusesProvider; 18 | 19 | final noStatusesFoundMessage = tabType == StatusTabType.recent 20 | ? context.l10n.doNotHaveSeenStatusesMessage 21 | : context.l10n.noSavedStatusesMessage; 22 | 23 | ScrollController scrollController = ScrollController(); 24 | return ref.watch(statusesProvider).whenWidget( 25 | (statuses) { 26 | return Scrollbar( 27 | controller: scrollController, 28 | interactive: true, 29 | child: RefreshIndicator( 30 | onRefresh: () async => await ref.refresh(statusesProvider), 31 | child: StatusesGridWidget( 32 | scrollController: scrollController, 33 | statuses: statuses, 34 | noStatusesFoundMessage: noStatusesFoundMessage, 35 | ), 36 | ), 37 | ); 38 | }, 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/statuses/views/video_tile.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:status_saver/src/common/helpers/get_video_thumbnail.dart'; 5 | import 'package:status_saver/src/statuses/views/video_view.dart'; 6 | 7 | class VideoTile extends StatelessWidget { 8 | final String videoPath; 9 | const VideoTile({super.key, required this.videoPath}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return FutureBuilder( 14 | future: getVideoThumbnailData(videoPath), 15 | builder: ((_, snapshot) { 16 | if (snapshot.connectionState == ConnectionState.done && 17 | snapshot.data != null) { 18 | return Card( 19 | elevation: 5, 20 | clipBehavior: Clip.hardEdge, 21 | child: InkWell( 22 | onTap: () => Navigator.of(context).push( 23 | MaterialPageRoute( 24 | builder: (_) => VideoView( 25 | videoPath: videoPath, 26 | // height: snapshot.data!.videoHeight, 27 | // width: snapshot.data!.videoWidth, 28 | ), 29 | ), 30 | ), 31 | child: Stack( 32 | children: [ 33 | Hero( 34 | tag: videoPath, 35 | child: Image.memory( 36 | fit: BoxFit.cover, 37 | snapshot.data!, 38 | ), 39 | ), 40 | Positioned.fill( 41 | child: Container( 42 | color: Colors.black54, 43 | ), 44 | ), 45 | const Positioned.fill( 46 | child: Center( 47 | child: Icon( 48 | Icons.play_circle_fill_rounded, 49 | size: 55, 50 | color: Colors.grey, 51 | ))) 52 | ], 53 | ), 54 | ), 55 | ); 56 | } else { 57 | return const Center( 58 | child: CircularProgressIndicator(), 59 | ); 60 | } 61 | }), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/statuses/views/video_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:chewie/chewie.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:status_saver/src/common/helpers/statuses_helper.dart'; 6 | import 'package:status_saver/src/statuses/views/status_actions.dart'; 7 | import 'package:video_player/video_player.dart'; 8 | 9 | class VideoView extends StatefulWidget { 10 | final String videoPath; 11 | const VideoView({ 12 | super.key, 13 | required this.videoPath, 14 | }); 15 | 16 | @override 17 | State createState() => _VideoViewState(); 18 | } 19 | 20 | class _VideoViewState extends State { 21 | late final ChewieController? _chewieController; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _chewieController = ChewieController( 27 | videoPlayerController: 28 | VideoPlayerController.file(File(widget.videoPath)), 29 | autoInitialize: true, 30 | autoPlay: true, 31 | showOptions: false, 32 | errorBuilder: (_, errorMessage) { 33 | return Text(errorMessage); 34 | }); 35 | } 36 | 37 | @override 38 | void dispose() { 39 | _chewieController!.pause(); 40 | _chewieController.dispose(); 41 | super.dispose(); 42 | } 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | return Scaffold( 47 | appBar: AppBar( 48 | backgroundColor: Colors.black, 49 | actions: [ 50 | if (isItSavedStatus(widget.videoPath)) 51 | DeleteSavedStatusAction( 52 | statusPath: widget.videoPath, 53 | onPressed: (deleteStatus) async { 54 | bool wasVideoPlaying = _chewieController?.isPlaying ?? false; 55 | if (wasVideoPlaying) { 56 | _chewieController?.pause(); 57 | } 58 | await deleteStatus(); 59 | if (wasVideoPlaying) { 60 | _chewieController?.play(); 61 | } 62 | }, 63 | ), 64 | ], 65 | ), 66 | body: Stack( 67 | clipBehavior: Clip.none, 68 | children: [ 69 | Hero( 70 | tag: widget.videoPath, 71 | child: Chewie( 72 | controller: _chewieController!, 73 | ), 74 | ), 75 | Positioned( 76 | bottom: 33, 77 | right: 10, 78 | height: MediaQuery.of(context).size.height * 0.2, 79 | child: StatusActions( 80 | statusPath: widget.videoPath, 81 | pauseVideoStatus: () async { 82 | await _chewieController.pause(); 83 | }, 84 | ), 85 | ), 86 | ], 87 | ), 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/src/storage_permission/notifiers/storage_permission_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | import 'package:permission_handler/permission_handler.dart'; 5 | import 'package:saf/saf.dart'; 6 | import 'package:status_saver/src/common/constants/directory_paths.dart'; 7 | import 'package:status_saver/src/common/helpers/storage_helper.dart'; 8 | import 'package:status_saver/src/debug/console_log.dart'; 9 | import 'package:status_saver/src/home/models/tab_type.dart'; 10 | import 'package:status_saver/src/home/services/android_info_notifier.dart'; 11 | import 'package:status_saver/src/home/services/whatsapp_type_notifier.dart'; 12 | import 'package:status_saver/src/common/extensions/permission_handler.dart'; 13 | 14 | class StoragePermissionNotifier 15 | extends FamilyAsyncNotifier { 16 | Saf? _saf; 17 | late final String? _statusesPath; 18 | 19 | @override 20 | FutureOr build(StatusTabType arg) async { 21 | state = const AsyncValue.loading(); 22 | _statusesPath = await _getStatusesDirPath(); 23 | await _initPlatformSpecificMembers(); 24 | return await isStoragePermitted(); 25 | } 26 | 27 | Saf? saf() => _saf; 28 | String? statusesPath() => _statusesPath; 29 | 30 | Future request() async { 31 | state = const AsyncValue.loading(); 32 | final bool isPermitted = await _requestStoragePermission(_saf); 33 | state = AsyncData(isPermitted); 34 | } 35 | 36 | Future isStoragePermitted() async { 37 | try { 38 | if (arg == StatusTabType.recent) { 39 | if (_saf != null) { 40 | return await _saf!.getDirectoryPermission(isDynamic: true) ?? false; 41 | } else { 42 | return await Permission.storage.isGranted; 43 | } 44 | } else if (arg == StatusTabType.saved) { 45 | final androidInfoNotifier = await ref.read(androidInfoProvider.future); 46 | return androidInfoNotifier.isAndroid13OrLater 47 | ? await [ 48 | Permission.photos, 49 | Permission.videos, 50 | ].isGranted 51 | : await Permission.storage.isGranted; 52 | } else { 53 | return false; 54 | } 55 | } catch (e) { 56 | return false; 57 | } 58 | } 59 | 60 | Future _requestStoragePermission(Saf? saf) async { 61 | if (arg == StatusTabType.recent) { 62 | try { 63 | if (saf != null) { 64 | return await saf.getDirectoryPermission(isDynamic: true) ?? false; 65 | } else { 66 | return await Permission.storage.request().isGranted; 67 | } 68 | } catch (e) { 69 | consoleLog("error in storage_helper/requestStoragePermission: $e"); 70 | return false; 71 | } 72 | } else if (arg == StatusTabType.saved) { 73 | consoleLog("in saved request ok"); 74 | 75 | final androidInfoNotifier = await ref.read(androidInfoProvider.future); 76 | return androidInfoNotifier.isAndroid13OrLater 77 | ? await [ 78 | Permission.photos, 79 | Permission.videos, 80 | ].requestAndHandle() 81 | : await Permission.storage.requestAndHandle(); 82 | } else { 83 | return false; 84 | } 85 | } 86 | 87 | Future _initPlatformSpecificMembers() async { 88 | final androidInfo = await ref.watch(androidInfoProvider.future); 89 | 90 | if (arg == StatusTabType.recent && androidInfo.isAndroid11OrLater) { 91 | final whatsAppType = await ref.watch(whatsAppTypeProvider.future); 92 | 93 | if (whatsAppType == null) { 94 | state = AsyncError("Whats app not found", StackTrace.current); 95 | return; 96 | } 97 | _saf = Saf(_statusesPath!); 98 | } 99 | } 100 | 101 | void releasePermissions() { 102 | state = const AsyncValue.data(false); 103 | } 104 | 105 | Future _getStatusesDirPath() async { 106 | if (arg == StatusTabType.recent) { 107 | return getStatusesPath( 108 | (await ref.read(whatsAppTypeProvider.future))!, 109 | (await ref.read(androidInfoProvider.future)).isAndroid11OrLater, 110 | ); 111 | } else if (arg == StatusTabType.saved) { 112 | return savedStatusesDirectory; 113 | } else { 114 | return ""; 115 | } 116 | } 117 | } 118 | 119 | final storagePermissionProvider = AsyncNotifierProvider.family< 120 | StoragePermissionNotifier, 121 | bool, 122 | StatusTabType>(StoragePermissionNotifier.new); 123 | 124 | final recentStoragePermissionProvider = 125 | storagePermissionProvider(StatusTabType.recent); 126 | 127 | final savedStoragePermissionProvider = 128 | storagePermissionProvider(StatusTabType.saved); 129 | -------------------------------------------------------------------------------- /lib/src/storage_permission/views/give_permissions_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 3 | 4 | class GivePermissionsScreen extends StatelessWidget { 5 | const GivePermissionsScreen({ 6 | super.key, 7 | required this.onRequestPermission, 8 | }); 9 | final void Function() onRequestPermission; 10 | @override 11 | Widget build(BuildContext context) { 12 | return Column( 13 | crossAxisAlignment: CrossAxisAlignment.center, 14 | mainAxisAlignment: MainAxisAlignment.center, 15 | children: [ 16 | Padding( 17 | padding: const EdgeInsets.all(8.0), 18 | child: Text( 19 | context.l10n 20 | .needToGiveStoragePermission, // FIXME: give better message using GPT 21 | textAlign: TextAlign.center, 22 | style: const TextStyle( 23 | fontSize: 18, 24 | ), 25 | ), 26 | ), 27 | ElevatedButton( 28 | onPressed: onRequestPermission, 29 | child: Text(context.l10n.giveStoragePermission), 30 | ), 31 | ], 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/theme/app_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:dynamic_color/dynamic_color.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:material_color_utilities/palettes/core_palette.dart'; 4 | 5 | class AppTheme { 6 | static ThemeData themeData(CorePalette? corePalette, Brightness brightness) { 7 | ColorScheme scheme = corePalette?.toColorScheme(brightness: brightness) ?? defaultColorScheme(brightness); 8 | return ThemeData( 9 | useMaterial3: true, 10 | colorScheme: scheme, 11 | ); 12 | } 13 | 14 | static ColorScheme defaultColorScheme(Brightness brightness) { 15 | return ColorScheme.fromSeed( 16 | seedColor: const Color(0xFF00FF00), brightness: brightness); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/theme/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const MaterialColor videoPlayIconColor = Colors.grey; 4 | final Color statusBorderColor = Colors.green.shade400; -------------------------------------------------------------------------------- /lib/src/theme/notifiers/theme_mode_notifier.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | import 'package:status_saver/src/localization/extensions/on_build_context.dart'; 5 | import 'package:status_saver/src/common/helpers/show_toast.dart'; 6 | 7 | const themeModeTypeKey = "themeData"; 8 | 9 | class ThemeModeNotifier extends StateNotifier { 10 | ThemeModeNotifier() : super(null); 11 | 12 | void initialize() async { 13 | final sharedPreferences = await SharedPreferences.getInstance(); 14 | String? themeModeType = sharedPreferences.getString(themeModeTypeKey); 15 | state = _getThemeMode(themeModeType); 16 | } 17 | 18 | void setThemeMode(ThemeMode? themeMode, BuildContext context) { 19 | SharedPreferences.getInstance().then((sharedPreferences) { 20 | final themeModeType = _getThemeModeType(themeMode); 21 | sharedPreferences 22 | .setString(themeModeTypeKey, themeModeType) 23 | .then((value) { 24 | if (!value) { 25 | showToast(message: context.l10n.couldNotSaveYourThemePreference); 26 | } 27 | }); 28 | }); 29 | state = themeMode; 30 | } 31 | 32 | static ThemeMode _getThemeMode(String? themeModeType) { 33 | switch (themeModeType) { 34 | case 'light': 35 | return ThemeMode.light; 36 | case 'dark': 37 | return ThemeMode.dark; 38 | } 39 | return ThemeMode.system; 40 | } 41 | 42 | static String _getThemeModeType(ThemeMode? themeMode) { 43 | switch (themeMode) { 44 | case ThemeMode.light: 45 | return "light"; 46 | case ThemeMode.dark: 47 | return "dark"; 48 | case ThemeMode.system: 49 | default: 50 | return "system"; 51 | } 52 | } 53 | 54 | ThemeMode? get themeMode => state; 55 | } 56 | 57 | class MyThemes { 58 | static List themeModes = [ 59 | ThemeMode.system, 60 | ThemeMode.light, 61 | ThemeMode.dark, 62 | ]; 63 | 64 | static List themeModeTypes(BuildContext context) => [ 65 | context.l10n.systemThemeLabel, 66 | context.l10n.lightThemeLabel, 67 | context.l10n.darkThemeLabel 68 | ]; 69 | 70 | static List themeModeIcons = const [ 71 | Icon(Icons.hotel_class), 72 | Icon(Icons.light_mode), 73 | Icon(Icons.dark_mode), 74 | ]; 75 | } 76 | 77 | final themeModeProvider = StateNotifierProvider( 78 | (ref) => ThemeModeNotifier()..initialize()); 79 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "67.0.0" 12 | analyzer: 13 | dependency: transitive 14 | description: 15 | name: analyzer 16 | sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "6.4.1" 20 | analyzer_plugin: 21 | dependency: transitive 22 | description: 23 | name: analyzer_plugin 24 | sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "0.11.3" 28 | ansicolor: 29 | dependency: transitive 30 | description: 31 | name: ansicolor 32 | sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.0.2" 36 | appcheck: 37 | dependency: "direct main" 38 | description: 39 | name: appcheck 40 | sha256: "2682c9c270c28d83f8d87d68bb607a83882778b14c6a8da19df423be1b386520" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.1.0" 44 | archive: 45 | dependency: transitive 46 | description: 47 | name: archive 48 | sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "3.5.1" 52 | args: 53 | dependency: transitive 54 | description: 55 | name: args 56 | sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "2.5.0" 60 | async: 61 | dependency: transitive 62 | description: 63 | name: async 64 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "2.11.0" 68 | boolean_selector: 69 | dependency: transitive 70 | description: 71 | name: boolean_selector 72 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "2.1.1" 76 | characters: 77 | dependency: transitive 78 | description: 79 | name: characters 80 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.3.0" 84 | checked_yaml: 85 | dependency: transitive 86 | description: 87 | name: checked_yaml 88 | sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "2.0.3" 92 | chewie: 93 | dependency: "direct main" 94 | description: 95 | name: chewie 96 | sha256: e53da939709efb9aad0f3d72a69a8d05f889168b7a138af60ce78bab5c94b135 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.8.1" 100 | ci: 101 | dependency: transitive 102 | description: 103 | name: ci 104 | sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "0.1.0" 108 | cli_util: 109 | dependency: transitive 110 | description: 111 | name: cli_util 112 | sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "0.4.1" 116 | clock: 117 | dependency: transitive 118 | description: 119 | name: clock 120 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "1.1.1" 124 | collection: 125 | dependency: transitive 126 | description: 127 | name: collection 128 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "1.18.0" 132 | convert: 133 | dependency: transitive 134 | description: 135 | name: convert 136 | sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" 137 | url: "https://pub.dev" 138 | source: hosted 139 | version: "3.1.1" 140 | cross_file: 141 | dependency: transitive 142 | description: 143 | name: cross_file 144 | sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" 145 | url: "https://pub.dev" 146 | source: hosted 147 | version: "0.3.4+1" 148 | crypto: 149 | dependency: transitive 150 | description: 151 | name: crypto 152 | sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab 153 | url: "https://pub.dev" 154 | source: hosted 155 | version: "3.0.3" 156 | csslib: 157 | dependency: transitive 158 | description: 159 | name: csslib 160 | sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" 161 | url: "https://pub.dev" 162 | source: hosted 163 | version: "1.0.0" 164 | cupertino_icons: 165 | dependency: "direct main" 166 | description: 167 | name: cupertino_icons 168 | sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 169 | url: "https://pub.dev" 170 | source: hosted 171 | version: "1.0.8" 172 | custom_lint: 173 | dependency: "direct dev" 174 | description: 175 | name: custom_lint 176 | sha256: "7c0aec12df22f9082146c354692056677f1e70bc43471644d1fdb36c6fdda799" 177 | url: "https://pub.dev" 178 | source: hosted 179 | version: "0.6.4" 180 | custom_lint_builder: 181 | dependency: transitive 182 | description: 183 | name: custom_lint_builder 184 | sha256: d7dc41e709dde223806660268678be7993559e523eb3164e2a1425fd6f7615a9 185 | url: "https://pub.dev" 186 | source: hosted 187 | version: "0.6.4" 188 | custom_lint_core: 189 | dependency: transitive 190 | description: 191 | name: custom_lint_core 192 | sha256: a85e8f78f4c52f6c63cdaf8c872eb573db0231dcdf3c3a5906d493c1f8bc20e6 193 | url: "https://pub.dev" 194 | source: hosted 195 | version: "0.6.3" 196 | dart_style: 197 | dependency: transitive 198 | description: 199 | name: dart_style 200 | sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" 201 | url: "https://pub.dev" 202 | source: hosted 203 | version: "2.3.6" 204 | dbus: 205 | dependency: transitive 206 | description: 207 | name: dbus 208 | sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" 209 | url: "https://pub.dev" 210 | source: hosted 211 | version: "0.7.10" 212 | device_info_plus: 213 | dependency: "direct main" 214 | description: 215 | name: device_info_plus 216 | sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 217 | url: "https://pub.dev" 218 | source: hosted 219 | version: "10.1.0" 220 | device_info_plus_platform_interface: 221 | dependency: transitive 222 | description: 223 | name: device_info_plus_platform_interface 224 | sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 225 | url: "https://pub.dev" 226 | source: hosted 227 | version: "7.0.0" 228 | dynamic_color: 229 | dependency: "direct main" 230 | description: 231 | name: dynamic_color 232 | sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d 233 | url: "https://pub.dev" 234 | source: hosted 235 | version: "1.7.0" 236 | fake_async: 237 | dependency: transitive 238 | description: 239 | name: fake_async 240 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 241 | url: "https://pub.dev" 242 | source: hosted 243 | version: "1.3.1" 244 | ffi: 245 | dependency: transitive 246 | description: 247 | name: ffi 248 | sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" 249 | url: "https://pub.dev" 250 | source: hosted 251 | version: "2.1.2" 252 | file: 253 | dependency: transitive 254 | description: 255 | name: file 256 | sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" 257 | url: "https://pub.dev" 258 | source: hosted 259 | version: "7.0.0" 260 | fixnum: 261 | dependency: transitive 262 | description: 263 | name: fixnum 264 | sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" 265 | url: "https://pub.dev" 266 | source: hosted 267 | version: "1.1.0" 268 | flutter: 269 | dependency: "direct main" 270 | description: flutter 271 | source: sdk 272 | version: "0.0.0" 273 | flutter_lints: 274 | dependency: "direct dev" 275 | description: 276 | name: flutter_lints 277 | sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" 278 | url: "https://pub.dev" 279 | source: hosted 280 | version: "3.0.2" 281 | flutter_localizations: 282 | dependency: "direct main" 283 | description: flutter 284 | source: sdk 285 | version: "0.0.0" 286 | flutter_native_splash: 287 | dependency: "direct main" 288 | description: 289 | name: flutter_native_splash 290 | sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0 291 | url: "https://pub.dev" 292 | source: hosted 293 | version: "2.4.0" 294 | flutter_riverpod: 295 | dependency: "direct main" 296 | description: 297 | name: flutter_riverpod 298 | sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" 299 | url: "https://pub.dev" 300 | source: hosted 301 | version: "2.5.1" 302 | flutter_staggered_grid_view: 303 | dependency: "direct main" 304 | description: 305 | name: flutter_staggered_grid_view 306 | sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" 307 | url: "https://pub.dev" 308 | source: hosted 309 | version: "0.7.0" 310 | flutter_test: 311 | dependency: "direct dev" 312 | description: flutter 313 | source: sdk 314 | version: "0.0.0" 315 | flutter_web_plugins: 316 | dependency: transitive 317 | description: flutter 318 | source: sdk 319 | version: "0.0.0" 320 | fluttertoast: 321 | dependency: "direct main" 322 | description: 323 | name: fluttertoast 324 | sha256: "81b68579e23fcbcada2db3d50302813d2371664afe6165bc78148050ab94bf66" 325 | url: "https://pub.dev" 326 | source: hosted 327 | version: "8.2.5" 328 | font_awesome_flutter: 329 | dependency: "direct main" 330 | description: 331 | name: font_awesome_flutter 332 | sha256: "275ff26905134bcb59417cf60ad979136f1f8257f2f449914b2c3e05bbb4cd6f" 333 | url: "https://pub.dev" 334 | source: hosted 335 | version: "10.7.0" 336 | freezed_annotation: 337 | dependency: transitive 338 | description: 339 | name: freezed_annotation 340 | sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d 341 | url: "https://pub.dev" 342 | source: hosted 343 | version: "2.4.1" 344 | glob: 345 | dependency: transitive 346 | description: 347 | name: glob 348 | sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" 349 | url: "https://pub.dev" 350 | source: hosted 351 | version: "2.1.2" 352 | hotreloader: 353 | dependency: transitive 354 | description: 355 | name: hotreloader 356 | sha256: ed56fdc1f3a8ac924e717257621d09e9ec20e308ab6352a73a50a1d7a4d9158e 357 | url: "https://pub.dev" 358 | source: hosted 359 | version: "4.2.0" 360 | html: 361 | dependency: transitive 362 | description: 363 | name: html 364 | sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" 365 | url: "https://pub.dev" 366 | source: hosted 367 | version: "0.15.4" 368 | http: 369 | dependency: transitive 370 | description: 371 | name: http 372 | sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" 373 | url: "https://pub.dev" 374 | source: hosted 375 | version: "1.2.1" 376 | http_parser: 377 | dependency: transitive 378 | description: 379 | name: http_parser 380 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 381 | url: "https://pub.dev" 382 | source: hosted 383 | version: "4.0.2" 384 | image: 385 | dependency: transitive 386 | description: 387 | name: image 388 | sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" 389 | url: "https://pub.dev" 390 | source: hosted 391 | version: "4.1.7" 392 | intl: 393 | dependency: "direct main" 394 | description: 395 | name: intl 396 | sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" 397 | url: "https://pub.dev" 398 | source: hosted 399 | version: "0.18.1" 400 | json_annotation: 401 | dependency: transitive 402 | description: 403 | name: json_annotation 404 | sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" 405 | url: "https://pub.dev" 406 | source: hosted 407 | version: "4.9.0" 408 | leak_tracker: 409 | dependency: transitive 410 | description: 411 | name: leak_tracker 412 | sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" 413 | url: "https://pub.dev" 414 | source: hosted 415 | version: "10.0.0" 416 | leak_tracker_flutter_testing: 417 | dependency: transitive 418 | description: 419 | name: leak_tracker_flutter_testing 420 | sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 421 | url: "https://pub.dev" 422 | source: hosted 423 | version: "2.0.1" 424 | leak_tracker_testing: 425 | dependency: transitive 426 | description: 427 | name: leak_tracker_testing 428 | sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 429 | url: "https://pub.dev" 430 | source: hosted 431 | version: "2.0.1" 432 | lints: 433 | dependency: transitive 434 | description: 435 | name: lints 436 | sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 437 | url: "https://pub.dev" 438 | source: hosted 439 | version: "3.0.0" 440 | logging: 441 | dependency: transitive 442 | description: 443 | name: logging 444 | sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" 445 | url: "https://pub.dev" 446 | source: hosted 447 | version: "1.2.0" 448 | matcher: 449 | dependency: transitive 450 | description: 451 | name: matcher 452 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 453 | url: "https://pub.dev" 454 | source: hosted 455 | version: "0.12.16+1" 456 | material_color_utilities: 457 | dependency: "direct main" 458 | description: 459 | name: material_color_utilities 460 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 461 | url: "https://pub.dev" 462 | source: hosted 463 | version: "0.8.0" 464 | meta: 465 | dependency: transitive 466 | description: 467 | name: meta 468 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 469 | url: "https://pub.dev" 470 | source: hosted 471 | version: "1.11.0" 472 | mime: 473 | dependency: transitive 474 | description: 475 | name: mime 476 | sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" 477 | url: "https://pub.dev" 478 | source: hosted 479 | version: "1.0.5" 480 | nested: 481 | dependency: transitive 482 | description: 483 | name: nested 484 | sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" 485 | url: "https://pub.dev" 486 | source: hosted 487 | version: "1.0.0" 488 | package_config: 489 | dependency: transitive 490 | description: 491 | name: package_config 492 | sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" 493 | url: "https://pub.dev" 494 | source: hosted 495 | version: "2.1.0" 496 | package_info_plus: 497 | dependency: transitive 498 | description: 499 | name: package_info_plus 500 | sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 501 | url: "https://pub.dev" 502 | source: hosted 503 | version: "8.0.0" 504 | package_info_plus_platform_interface: 505 | dependency: transitive 506 | description: 507 | name: package_info_plus_platform_interface 508 | sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e 509 | url: "https://pub.dev" 510 | source: hosted 511 | version: "3.0.0" 512 | path: 513 | dependency: transitive 514 | description: 515 | name: path 516 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 517 | url: "https://pub.dev" 518 | source: hosted 519 | version: "1.9.0" 520 | path_provider: 521 | dependency: transitive 522 | description: 523 | name: path_provider 524 | sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 525 | url: "https://pub.dev" 526 | source: hosted 527 | version: "2.1.3" 528 | path_provider_android: 529 | dependency: transitive 530 | description: 531 | name: path_provider_android 532 | sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d 533 | url: "https://pub.dev" 534 | source: hosted 535 | version: "2.2.4" 536 | path_provider_foundation: 537 | dependency: transitive 538 | description: 539 | name: path_provider_foundation 540 | sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 541 | url: "https://pub.dev" 542 | source: hosted 543 | version: "2.4.0" 544 | path_provider_linux: 545 | dependency: transitive 546 | description: 547 | name: path_provider_linux 548 | sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 549 | url: "https://pub.dev" 550 | source: hosted 551 | version: "2.2.1" 552 | path_provider_platform_interface: 553 | dependency: transitive 554 | description: 555 | name: path_provider_platform_interface 556 | sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" 557 | url: "https://pub.dev" 558 | source: hosted 559 | version: "2.1.2" 560 | path_provider_windows: 561 | dependency: transitive 562 | description: 563 | name: path_provider_windows 564 | sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" 565 | url: "https://pub.dev" 566 | source: hosted 567 | version: "2.2.1" 568 | permission_handler: 569 | dependency: "direct main" 570 | description: 571 | name: permission_handler 572 | sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 573 | url: "https://pub.dev" 574 | source: hosted 575 | version: "10.4.5" 576 | permission_handler_android: 577 | dependency: transitive 578 | description: 579 | name: permission_handler_android 580 | sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" 581 | url: "https://pub.dev" 582 | source: hosted 583 | version: "10.3.6" 584 | permission_handler_apple: 585 | dependency: transitive 586 | description: 587 | name: permission_handler_apple 588 | sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" 589 | url: "https://pub.dev" 590 | source: hosted 591 | version: "9.1.4" 592 | permission_handler_platform_interface: 593 | dependency: transitive 594 | description: 595 | name: permission_handler_platform_interface 596 | sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" 597 | url: "https://pub.dev" 598 | source: hosted 599 | version: "3.12.0" 600 | permission_handler_windows: 601 | dependency: transitive 602 | description: 603 | name: permission_handler_windows 604 | sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 605 | url: "https://pub.dev" 606 | source: hosted 607 | version: "0.1.3" 608 | petitparser: 609 | dependency: transitive 610 | description: 611 | name: petitparser 612 | sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 613 | url: "https://pub.dev" 614 | source: hosted 615 | version: "6.0.2" 616 | photo_view: 617 | dependency: "direct main" 618 | description: 619 | name: photo_view 620 | sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" 621 | url: "https://pub.dev" 622 | source: hosted 623 | version: "0.15.0" 624 | platform: 625 | dependency: transitive 626 | description: 627 | name: platform 628 | sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" 629 | url: "https://pub.dev" 630 | source: hosted 631 | version: "3.1.4" 632 | plugin_platform_interface: 633 | dependency: transitive 634 | description: 635 | name: plugin_platform_interface 636 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 637 | url: "https://pub.dev" 638 | source: hosted 639 | version: "2.1.8" 640 | provider: 641 | dependency: transitive 642 | description: 643 | name: provider 644 | sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c 645 | url: "https://pub.dev" 646 | source: hosted 647 | version: "6.1.2" 648 | pub_semver: 649 | dependency: transitive 650 | description: 651 | name: pub_semver 652 | sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" 653 | url: "https://pub.dev" 654 | source: hosted 655 | version: "2.1.4" 656 | pubspec_parse: 657 | dependency: transitive 658 | description: 659 | name: pubspec_parse 660 | sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 661 | url: "https://pub.dev" 662 | source: hosted 663 | version: "1.2.3" 664 | riverpod: 665 | dependency: transitive 666 | description: 667 | name: riverpod 668 | sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d 669 | url: "https://pub.dev" 670 | source: hosted 671 | version: "2.5.1" 672 | riverpod_analyzer_utils: 673 | dependency: transitive 674 | description: 675 | name: riverpod_analyzer_utils 676 | sha256: "8b71f03fc47ae27d13769496a1746332df4cec43918aeba9aff1e232783a780f" 677 | url: "https://pub.dev" 678 | source: hosted 679 | version: "0.5.1" 680 | riverpod_lint: 681 | dependency: "direct dev" 682 | description: 683 | name: riverpod_lint 684 | sha256: "3c67c14ccd16f0c9d53e35ef70d06cd9d072e2fb14557326886bbde903b230a5" 685 | url: "https://pub.dev" 686 | source: hosted 687 | version: "2.3.10" 688 | rxdart: 689 | dependency: transitive 690 | description: 691 | name: rxdart 692 | sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" 693 | url: "https://pub.dev" 694 | source: hosted 695 | version: "0.27.7" 696 | saf: 697 | dependency: "direct main" 698 | description: 699 | name: saf 700 | sha256: "3b7565638bc155801dc2b1b948ee0545f8cf9310da6e0f4ded45f62ee83f1321" 701 | url: "https://pub.dev" 702 | source: hosted 703 | version: "1.0.3+4" 704 | share_plus: 705 | dependency: "direct main" 706 | description: 707 | name: share_plus 708 | sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544 709 | url: "https://pub.dev" 710 | source: hosted 711 | version: "9.0.0" 712 | share_plus_platform_interface: 713 | dependency: transitive 714 | description: 715 | name: share_plus_platform_interface 716 | sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4" 717 | url: "https://pub.dev" 718 | source: hosted 719 | version: "4.0.0" 720 | shared_preferences: 721 | dependency: "direct main" 722 | description: 723 | name: shared_preferences 724 | sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 725 | url: "https://pub.dev" 726 | source: hosted 727 | version: "2.2.3" 728 | shared_preferences_android: 729 | dependency: transitive 730 | description: 731 | name: shared_preferences_android 732 | sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" 733 | url: "https://pub.dev" 734 | source: hosted 735 | version: "2.2.2" 736 | shared_preferences_foundation: 737 | dependency: transitive 738 | description: 739 | name: shared_preferences_foundation 740 | sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" 741 | url: "https://pub.dev" 742 | source: hosted 743 | version: "2.3.5" 744 | shared_preferences_linux: 745 | dependency: transitive 746 | description: 747 | name: shared_preferences_linux 748 | sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" 749 | url: "https://pub.dev" 750 | source: hosted 751 | version: "2.3.2" 752 | shared_preferences_platform_interface: 753 | dependency: transitive 754 | description: 755 | name: shared_preferences_platform_interface 756 | sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" 757 | url: "https://pub.dev" 758 | source: hosted 759 | version: "2.3.2" 760 | shared_preferences_web: 761 | dependency: transitive 762 | description: 763 | name: shared_preferences_web 764 | sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" 765 | url: "https://pub.dev" 766 | source: hosted 767 | version: "2.3.0" 768 | shared_preferences_windows: 769 | dependency: transitive 770 | description: 771 | name: shared_preferences_windows 772 | sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" 773 | url: "https://pub.dev" 774 | source: hosted 775 | version: "2.3.2" 776 | sky_engine: 777 | dependency: transitive 778 | description: flutter 779 | source: sdk 780 | version: "0.0.99" 781 | source_span: 782 | dependency: transitive 783 | description: 784 | name: source_span 785 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 786 | url: "https://pub.dev" 787 | source: hosted 788 | version: "1.10.0" 789 | sprintf: 790 | dependency: transitive 791 | description: 792 | name: sprintf 793 | sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" 794 | url: "https://pub.dev" 795 | source: hosted 796 | version: "7.0.0" 797 | stack_trace: 798 | dependency: transitive 799 | description: 800 | name: stack_trace 801 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 802 | url: "https://pub.dev" 803 | source: hosted 804 | version: "1.11.1" 805 | state_notifier: 806 | dependency: transitive 807 | description: 808 | name: state_notifier 809 | sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb 810 | url: "https://pub.dev" 811 | source: hosted 812 | version: "1.0.0" 813 | stream_channel: 814 | dependency: transitive 815 | description: 816 | name: stream_channel 817 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 818 | url: "https://pub.dev" 819 | source: hosted 820 | version: "2.1.2" 821 | stream_transform: 822 | dependency: transitive 823 | description: 824 | name: stream_transform 825 | sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" 826 | url: "https://pub.dev" 827 | source: hosted 828 | version: "2.1.0" 829 | string_scanner: 830 | dependency: transitive 831 | description: 832 | name: string_scanner 833 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 834 | url: "https://pub.dev" 835 | source: hosted 836 | version: "1.2.0" 837 | term_glyph: 838 | dependency: transitive 839 | description: 840 | name: term_glyph 841 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 842 | url: "https://pub.dev" 843 | source: hosted 844 | version: "1.2.1" 845 | test_api: 846 | dependency: transitive 847 | description: 848 | name: test_api 849 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 850 | url: "https://pub.dev" 851 | source: hosted 852 | version: "0.6.1" 853 | typed_data: 854 | dependency: transitive 855 | description: 856 | name: typed_data 857 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 858 | url: "https://pub.dev" 859 | source: hosted 860 | version: "1.3.2" 861 | universal_io: 862 | dependency: transitive 863 | description: 864 | name: universal_io 865 | sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" 866 | url: "https://pub.dev" 867 | source: hosted 868 | version: "2.2.2" 869 | url_launcher_linux: 870 | dependency: transitive 871 | description: 872 | name: url_launcher_linux 873 | sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 874 | url: "https://pub.dev" 875 | source: hosted 876 | version: "3.1.1" 877 | url_launcher_platform_interface: 878 | dependency: transitive 879 | description: 880 | name: url_launcher_platform_interface 881 | sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" 882 | url: "https://pub.dev" 883 | source: hosted 884 | version: "2.3.2" 885 | url_launcher_web: 886 | dependency: transitive 887 | description: 888 | name: url_launcher_web 889 | sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" 890 | url: "https://pub.dev" 891 | source: hosted 892 | version: "2.3.1" 893 | url_launcher_windows: 894 | dependency: transitive 895 | description: 896 | name: url_launcher_windows 897 | sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 898 | url: "https://pub.dev" 899 | source: hosted 900 | version: "3.1.1" 901 | uuid: 902 | dependency: transitive 903 | description: 904 | name: uuid 905 | sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" 906 | url: "https://pub.dev" 907 | source: hosted 908 | version: "4.4.0" 909 | vector_math: 910 | dependency: transitive 911 | description: 912 | name: vector_math 913 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 914 | url: "https://pub.dev" 915 | source: hosted 916 | version: "2.1.4" 917 | video_player: 918 | dependency: "direct main" 919 | description: 920 | name: video_player 921 | sha256: aced48e701e24c02b0b7f881a8819e4937794e46b5a5821005e2bf3b40a324cc 922 | url: "https://pub.dev" 923 | source: hosted 924 | version: "2.8.7" 925 | video_player_android: 926 | dependency: transitive 927 | description: 928 | name: video_player_android 929 | sha256: "134e1ad410d67e18a19486ed9512c72dfc6d8ffb284d0e8f2e99e903d1ba8fa3" 930 | url: "https://pub.dev" 931 | source: hosted 932 | version: "2.4.14" 933 | video_player_avfoundation: 934 | dependency: transitive 935 | description: 936 | name: video_player_avfoundation 937 | sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c 938 | url: "https://pub.dev" 939 | source: hosted 940 | version: "2.6.1" 941 | video_player_platform_interface: 942 | dependency: transitive 943 | description: 944 | name: video_player_platform_interface 945 | sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6" 946 | url: "https://pub.dev" 947 | source: hosted 948 | version: "6.2.2" 949 | video_player_web: 950 | dependency: transitive 951 | description: 952 | name: video_player_web 953 | sha256: ff4d69a6614b03f055397c27a71c9d3ddea2b2a23d71b2ba0164f59ca32b8fe2 954 | url: "https://pub.dev" 955 | source: hosted 956 | version: "2.3.1" 957 | video_thumbnail: 958 | dependency: "direct main" 959 | description: 960 | name: video_thumbnail 961 | sha256: "3455c189d3f0bb4e3fc2236475aa84fe598b9b2d0e08f43b9761f5bc44210016" 962 | url: "https://pub.dev" 963 | source: hosted 964 | version: "0.5.3" 965 | vm_service: 966 | dependency: transitive 967 | description: 968 | name: vm_service 969 | sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 970 | url: "https://pub.dev" 971 | source: hosted 972 | version: "13.0.0" 973 | wakelock_plus: 974 | dependency: transitive 975 | description: 976 | name: wakelock_plus 977 | sha256: "14758533319a462ffb5aa3b7ddb198e59b29ac3b02da14173a1715d65d4e6e68" 978 | url: "https://pub.dev" 979 | source: hosted 980 | version: "1.2.5" 981 | wakelock_plus_platform_interface: 982 | dependency: transitive 983 | description: 984 | name: wakelock_plus_platform_interface 985 | sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16" 986 | url: "https://pub.dev" 987 | source: hosted 988 | version: "1.2.1" 989 | watcher: 990 | dependency: transitive 991 | description: 992 | name: watcher 993 | sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" 994 | url: "https://pub.dev" 995 | source: hosted 996 | version: "1.1.0" 997 | web: 998 | dependency: transitive 999 | description: 1000 | name: web 1001 | sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" 1002 | url: "https://pub.dev" 1003 | source: hosted 1004 | version: "0.5.1" 1005 | win32: 1006 | dependency: transitive 1007 | description: 1008 | name: win32 1009 | sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" 1010 | url: "https://pub.dev" 1011 | source: hosted 1012 | version: "5.5.0" 1013 | win32_registry: 1014 | dependency: transitive 1015 | description: 1016 | name: win32_registry 1017 | sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" 1018 | url: "https://pub.dev" 1019 | source: hosted 1020 | version: "1.1.3" 1021 | xdg_directories: 1022 | dependency: transitive 1023 | description: 1024 | name: xdg_directories 1025 | sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d 1026 | url: "https://pub.dev" 1027 | source: hosted 1028 | version: "1.0.4" 1029 | xml: 1030 | dependency: transitive 1031 | description: 1032 | name: xml 1033 | sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 1034 | url: "https://pub.dev" 1035 | source: hosted 1036 | version: "6.5.0" 1037 | yaml: 1038 | dependency: transitive 1039 | description: 1040 | name: yaml 1041 | sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" 1042 | url: "https://pub.dev" 1043 | source: hosted 1044 | version: "3.1.2" 1045 | sdks: 1046 | dart: ">=3.3.1 <4.0.0" 1047 | flutter: ">=3.19.0" 1048 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: status_saver 2 | description: "Open Source Status Saver application" 3 | 4 | publish_to: "none" 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=3.3.1 <4.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | flutter_localizations: 15 | sdk: flutter 16 | intl: any 17 | 18 | cupertino_icons: ^1.0.6 19 | flutter_native_splash: ^2.4.0 20 | flutter_riverpod: ^2.5.1 21 | dynamic_color: ^1.7.0 22 | material_color_utilities: ^0.8.0 23 | shared_preferences: ^2.2.3 24 | fluttertoast: ^8.2.5 25 | permission_handler: ^10.2.0 26 | font_awesome_flutter: ^10.7.0 27 | device_info_plus: ^10.1.0 28 | saf: ^1.0.3+4 29 | flutter_staggered_grid_view: ^0.7.0 30 | appcheck: ^1.1.0 31 | chewie: ^1.8.1 32 | photo_view: ^0.15.0 33 | video_thumbnail: ^0.5.3 34 | video_player: ^2.8.7 35 | share_plus: ^9.0.0 36 | 37 | dev_dependencies: 38 | flutter_test: 39 | sdk: flutter 40 | 41 | flutter_lints: ^3.0.0 42 | custom_lint: ^0.6.4 43 | riverpod_lint: ^2.3.10 44 | 45 | flutter: 46 | uses-material-design: true 47 | generate: true -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:status_saver/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------