commit 583df76d902753bff4ee4fb3bf3cb7aeca8eb38b Author: mohsen zamani Date: Tue May 16 16:36:54 2023 +0330 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24476c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..f991a3a --- /dev/null +++ b/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: android + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + - platform: ios + create_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + base_revision: 84a1e904f44f9b0e9c4510138010edcc653163f8 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..f52fe51 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# sonnat + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..80982ef --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,20 @@ +include: package:flutter_lints/flutter.yaml + +linter: + # In addition to the flutter_lints + rules: + - always_declare_return_types + - avoid_types_on_closure_parameters + - avoid_void_async + - cancel_subscriptions + - close_sinks + - directives_ordering + - flutter_style_todos + - package_api_docs + - prefer_single_quotes + - test_types_in_equals + - throw_in_finally + - unawaited_futures + - unnecessary_statements + - unsafe_html + - use_super_parameters \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..9b62aec --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,72 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + namespace "com.example.sonnat" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.sonnat" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b82084a --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/sonnat/MainActivity.kt b/android/app/src/main/kotlin/com/example/sonnat/MainActivity.kt new file mode 100644 index 0000000..41b5f27 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/sonnat/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.sonnat + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..f7eb7f6 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/fonts/arabi/Cairo-Black.ttf b/assets/fonts/arabi/Cairo-Black.ttf new file mode 100644 index 0000000..a2e4fc2 Binary files /dev/null and b/assets/fonts/arabi/Cairo-Black.ttf differ diff --git a/assets/fonts/arabi/Cairo-Bold.ttf b/assets/fonts/arabi/Cairo-Bold.ttf new file mode 100644 index 0000000..74ce7b1 Binary files /dev/null and b/assets/fonts/arabi/Cairo-Bold.ttf differ diff --git a/assets/fonts/arabi/Cairo-ExtraBold.ttf b/assets/fonts/arabi/Cairo-ExtraBold.ttf new file mode 100644 index 0000000..4d7f7d4 Binary files /dev/null and b/assets/fonts/arabi/Cairo-ExtraBold.ttf differ diff --git a/assets/fonts/arabi/Cairo-ExtraLight.ttf b/assets/fonts/arabi/Cairo-ExtraLight.ttf new file mode 100644 index 0000000..1f6f156 Binary files /dev/null and b/assets/fonts/arabi/Cairo-ExtraLight.ttf differ diff --git a/assets/fonts/arabi/Cairo-Light.ttf b/assets/fonts/arabi/Cairo-Light.ttf new file mode 100644 index 0000000..8263721 Binary files /dev/null and b/assets/fonts/arabi/Cairo-Light.ttf differ diff --git a/assets/fonts/arabi/Cairo-Medium.ttf b/assets/fonts/arabi/Cairo-Medium.ttf new file mode 100644 index 0000000..28be823 Binary files /dev/null and b/assets/fonts/arabi/Cairo-Medium.ttf differ diff --git a/assets/fonts/arabi/Cairo-Regular.ttf b/assets/fonts/arabi/Cairo-Regular.ttf new file mode 100644 index 0000000..e2ae267 Binary files /dev/null and b/assets/fonts/arabi/Cairo-Regular.ttf differ diff --git a/assets/fonts/arabi/Cairo-SemiBold.ttf b/assets/fonts/arabi/Cairo-SemiBold.ttf new file mode 100644 index 0000000..448367b Binary files /dev/null and b/assets/fonts/arabi/Cairo-SemiBold.ttf differ diff --git a/assets/fonts/farsi/Vazir-Black-FD.ttf b/assets/fonts/farsi/Vazir-Black-FD.ttf new file mode 100644 index 0000000..abae638 Binary files /dev/null and b/assets/fonts/farsi/Vazir-Black-FD.ttf differ diff --git a/assets/fonts/farsi/Vazir-Bold-FD.ttf b/assets/fonts/farsi/Vazir-Bold-FD.ttf new file mode 100644 index 0000000..53c0477 Binary files /dev/null and b/assets/fonts/farsi/Vazir-Bold-FD.ttf differ diff --git a/assets/fonts/farsi/Vazir-Light-FD.ttf b/assets/fonts/farsi/Vazir-Light-FD.ttf new file mode 100644 index 0000000..be25d9b Binary files /dev/null and b/assets/fonts/farsi/Vazir-Light-FD.ttf differ diff --git a/assets/fonts/farsi/Vazir-Medium-FD.ttf b/assets/fonts/farsi/Vazir-Medium-FD.ttf new file mode 100644 index 0000000..feba954 Binary files /dev/null and b/assets/fonts/farsi/Vazir-Medium-FD.ttf differ diff --git a/assets/fonts/farsi/Vazir-Regular-FD.ttf b/assets/fonts/farsi/Vazir-Regular-FD.ttf new file mode 100644 index 0000000..b4117c1 Binary files /dev/null and b/assets/fonts/farsi/Vazir-Regular-FD.ttf differ diff --git a/assets/fonts/farsi/Vazir-Thin-FD.ttf b/assets/fonts/farsi/Vazir-Thin-FD.ttf new file mode 100644 index 0000000..be7a74a Binary files /dev/null and b/assets/fonts/farsi/Vazir-Thin-FD.ttf differ diff --git a/assets/images/png/ic_main_header.png b/assets/images/png/ic_main_header.png new file mode 100644 index 0000000..f68549e Binary files /dev/null and b/assets/images/png/ic_main_header.png differ diff --git a/assets/images/svg/ic_akhbar.svg b/assets/images/svg/ic_akhbar.svg new file mode 100644 index 0000000..0867343 --- /dev/null +++ b/assets/images/svg/ic_akhbar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_aqayed.svg b/assets/images/svg/ic_aqayed.svg new file mode 100644 index 0000000..db8e082 --- /dev/null +++ b/assets/images/svg/ic_aqayed.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_back.svg b/assets/images/svg/ic_back.svg new file mode 100644 index 0000000..de10ae9 --- /dev/null +++ b/assets/images/svg/ic_back.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_instagram.svg b/assets/images/svg/ic_instagram.svg new file mode 100644 index 0000000..30a98bb --- /dev/null +++ b/assets/images/svg/ic_instagram.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/svg/ic_line.svg b/assets/images/svg/ic_line.svg new file mode 100644 index 0000000..3254434 --- /dev/null +++ b/assets/images/svg/ic_line.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/svg/ic_mataen.svg b/assets/images/svg/ic_mataen.svg new file mode 100644 index 0000000..c668b69 --- /dev/null +++ b/assets/images/svg/ic_mataen.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_more.svg b/assets/images/svg/ic_more.svg new file mode 100644 index 0000000..d139396 --- /dev/null +++ b/assets/images/svg/ic_more.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/svg/ic_phone.svg b/assets/images/svg/ic_phone.svg new file mode 100644 index 0000000..3c4fbcf --- /dev/null +++ b/assets/images/svg/ic_phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/svg/ic_rounded_search.svg b/assets/images/svg/ic_rounded_search.svg new file mode 100644 index 0000000..150e089 --- /dev/null +++ b/assets/images/svg/ic_rounded_search.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/svg/ic_search.svg b/assets/images/svg/ic_search.svg new file mode 100644 index 0000000..4b101fd --- /dev/null +++ b/assets/images/svg/ic_search.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_shobahat.svg b/assets/images/svg/ic_shobahat.svg new file mode 100644 index 0000000..57905bf --- /dev/null +++ b/assets/images/svg/ic_shobahat.svg @@ -0,0 +1,6 @@ + + + + ? + + diff --git a/assets/images/svg/ic_video.svg b/assets/images/svg/ic_video.svg new file mode 100644 index 0000000..2bafbe8 --- /dev/null +++ b/assets/images/svg/ic_video.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/svg/ic_vijeha.svg b/assets/images/svg/ic_vijeha.svg new file mode 100644 index 0000000..0cad48c --- /dev/null +++ b/assets/images/svg/ic_vijeha.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/languages/ar.json b/assets/languages/ar.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/assets/languages/ar.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/assets/languages/en.json b/assets/languages/en.json new file mode 100644 index 0000000..0d6631c --- /dev/null +++ b/assets/languages/en.json @@ -0,0 +1,17 @@ +{ + "criticism_of_ideas": "Criticism of ideas", + "doubts": "Doubts", + "forbidden": "Forbidden", + "video": "Video", + "news": "News", + "specials": "Specials", + "search_term": "Search term", + "main_header_text": "Saint comprehensive portal", + "second_header_text": "A description of the unanalyzed history of Islam", + "more_about_us": "Get to know us more", + "main_target": "Our main goal", + "contact_to_us": "Contact us", + "send_message_to_us": "Send us a message", + "send_message": "Write your message", + "send": "Send" +} \ No newline at end of file diff --git a/assets/languages/fa.json b/assets/languages/fa.json new file mode 100644 index 0000000..abd172b --- /dev/null +++ b/assets/languages/fa.json @@ -0,0 +1,17 @@ +{ + "criticism_of_ideas": "نقد عقاید", + "doubts": "شبهات", + "forbidden": "مطاعن", + "video": "ویدئو", + "news": "اخبار", + "specials": "ویژه\u200Cها", + "search_term": "...جستجوی عبارت", + "main_header_text": "پرتال جامع سنت", + "second_header_text": " شرحی بر تاریـــخ تحلیل نشــده اســــلام", + "more_about_us": "با ما بیشتر آشنا شوید", + "main_target": "هدف اصلی ما", + "contact_to_us": "ارتباط با ما", + "send_message_to_us": "ارسال پیام به ما", + "send_message": "پیام خود را بنویسید", + "send": "ارسال" +} \ No newline at end of file diff --git a/assets/meta/about_us.txt b/assets/meta/about_us.txt new file mode 100644 index 0000000..76c639d --- /dev/null +++ b/assets/meta/about_us.txt @@ -0,0 +1,2 @@ + نقل است که هنگام بیعت با ابوبکر در سقیفه نزدیک بود سعدبن‌عباده کشته ‌شود و به نقل بخاری به سوی سعد هجوم‌ برده‌ می‌شود.در این هنگام یکی از یاران سعد می‌گوید: «مراقب سعد باشید که لهش نکنید!(به نقل بخاری: سعد را کشتید!)»و عمر می‌گوید: «او را بکشید، خدا او را بکشد!» به نقل طبری عمر بالای سر سعد می‌ایستد و می‌گوید: «سعی‌داشتم آن‌گونه تو را له‌کنم که اعضایت از هم بپاشد!» و سعد ریش عمر را می‌گیرد و می‌گوید:« اگر فقط یک مو از ریشم بکَنی، برنمی‌گردی مگراین‌که دندان سالم در دهانت نیست!» و بعدمی‌گوید: «(اگر می‌توانستم) تو را به همان قومی که درمیان‌شان بودی و تبعیّت‌می‌کردی امّا موردتبعیّت نبودی، ملحق‌می‌کردم.» پس از آن حباب‌بن‌منذر روبه انصار می‌گوید: «اگر بخواهیم این‌ها را از مدینه بیرون‌ می‌کنیم.» عمر پاسخ‌می‌دهد: «در آن صورت خدا تو را بکشد.» +و حباب‌بن‌منذر هم در جواب او می‌گوید: «بلکه خودت کشته‌شوی!» \ No newline at end of file diff --git a/data/data_core/local_db/local_db_core/.gitignore b/data/data_core/local_db/local_db_core/.gitignore new file mode 100644 index 0000000..a8e938c --- /dev/null +++ b/data/data_core/local_db/local_db_core/.gitignore @@ -0,0 +1,47 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/data/data_core/local_db/local_db_core/.metadata b/data/data_core/local_db/local_db_core/.metadata new file mode 100644 index 0000000..39f2501 --- /dev/null +++ b/data/data_core/local_db/local_db_core/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: android + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: ios + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: linux + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: macos + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: web + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: windows + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/data/data_core/local_db/local_db_core/README.md b/data/data_core/local_db/local_db_core/README.md new file mode 100644 index 0000000..e56ed17 --- /dev/null +++ b/data/data_core/local_db/local_db_core/README.md @@ -0,0 +1,16 @@ +# local_db_core + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/data/data_core/local_db/local_db_core/analysis_options.yaml b/data/data_core/local_db/local_db_core/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/data/data_core/local_db/local_db_core/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/app_setting_box.dart b/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/app_setting_box.dart new file mode 100644 index 0000000..0df1521 --- /dev/null +++ b/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/app_setting_box.dart @@ -0,0 +1,66 @@ +import 'package:hive/hive.dart'; +import 'package:local_db_core/lib/boxes/box_list/setting_box/box_keys.dart'; +import 'package:local_db_core/lib/boxes/interfaces/config_box_interface.dart'; +import 'package:repositories/app_setting_box_domain/model/user_data_model.dart'; + +class AppSettingBox implements ConfigBoxInterface { + Box? _box; + + AppSettingBox.privateConstructor(); + + static final AppSettingBox instance = AppSettingBox.privateConstructor(); + + factory AppSettingBox() { + return instance; + } + + @override + String getBoxName() { + return "appSetting"; + } + + @override + String getKeyName(BoxKeys key) { + return key.value; + } + + @override + Future openBox() async { + _box = await Hive.openBox(getBoxName()); + initialFirstData(); + } + + @override + void initialFirstData() {} + + void setAppDirection(String value) { + _box?.put(getKeyName(BoxKeys.appDirection), value); + } + + String? getAppDirection() { + return _box?.get(getKeyName(BoxKeys.appDirection)); + } + + String? getCurrentLanguage() { + return _box?.get(getKeyName(BoxKeys.currentLanguage)); + } + + Future setCurrentLanguage(String language) async { + await _box?.put(getKeyName(BoxKeys.currentLanguage), language); + } + + Future getUserData() async { + if(!Hive.isBoxOpen(getBoxName())) { + await Hive.openBox(getBoxName()); + } + Map? data = await _box!.get(getKeyName(BoxKeys.userData)); + if (data == null) { + return null; + } + return UserDataModel.fromJson(data); + } + + Future setUserData(Map data) async { + await _box!.put(getKeyName(BoxKeys.userData), data); + } +} diff --git a/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/box_keys.dart b/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/box_keys.dart new file mode 100644 index 0000000..2be7d14 --- /dev/null +++ b/data/data_core/local_db/local_db_core/lib/lib/boxes/box_list/setting_box/box_keys.dart @@ -0,0 +1,9 @@ +enum BoxKeys { + currentLanguage("current-language"), + userData('user-data'), + appDirection("app-direction"); + + final String value; + + const BoxKeys(this.value); +} diff --git a/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/base_box_interface.dart b/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/base_box_interface.dart new file mode 100644 index 0000000..48e33f4 --- /dev/null +++ b/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/base_box_interface.dart @@ -0,0 +1,7 @@ +abstract class BaseBoxInterface { + String getBoxName(); + + String getKeyName(T key); + + Future openBox(); +} diff --git a/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/config_box_interface.dart b/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/config_box_interface.dart new file mode 100644 index 0000000..789624b --- /dev/null +++ b/data/data_core/local_db/local_db_core/lib/lib/boxes/interfaces/config_box_interface.dart @@ -0,0 +1,5 @@ +import 'package:local_db_core/lib/boxes/interfaces/base_box_interface.dart'; + +abstract class ConfigBoxInterface implements BaseBoxInterface { + void initialFirstData(); +} diff --git a/data/data_core/local_db/local_db_core/pubspec.lock b/data/data_core/local_db/local_db_core/pubspec.lock new file mode 100644 index 0000000..5b89e0c --- /dev/null +++ b/data/data_core/local_db/local_db_core/pubspec.lock @@ -0,0 +1,340 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + hive: + dependency: "direct main" + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "050e8e85e4b7fecdf2bb3682c1c64c4887a183720c802d323de8a5fd76d372dd" + url: "https://pub.dev" + source: hosted + version: "2.0.11" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "1dab723dd8feeb80afb39c7be894f09df1457243d930010f6f328fb8c660c5e1" + url: "https://pub.dev" + source: hosted + version: "2.0.21" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + sha256: "03d639406f5343478352433f00d3c4394d52dac8df3d847869c5e2333e0bbce8" + url: "https://pub.dev" + source: hosted + version: "2.0.11" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" + source: hosted + version: "2.1.7" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + sha256: "2a97e7fbb7ae9dcd0dfc1220a78e9ec3e71da691912e617e8715ff2a13086ae8" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" + source: hosted + version: "2.1.3" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" + source: hosted + version: "2.1.3" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + repositories: + dependency: "direct main" + description: + path: "../../../../domain/repositories" + relative: true + source: path + version: "0.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + win32: + dependency: transitive + description: + name: win32 + sha256: d13ac5deea7327f027b3b97ee19ee210f68256ecf3f1a304bcfb992ee947637c + url: "https://pub.dev" + source: hosted + version: "3.1.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "11541eedefbcaec9de35aa82650b695297ce668662bbd6e3911a7fabdbde589f" + url: "https://pub.dev" + source: hosted + version: "0.2.0+2" +sdks: + dart: ">=3.0.0-0 <4.0.0" + flutter: ">=3.0.0" diff --git a/data/data_core/local_db/local_db_core/pubspec.yaml b/data/data_core/local_db/local_db_core/pubspec.yaml new file mode 100644 index 0000000..8778e3c --- /dev/null +++ b/data/data_core/local_db/local_db_core/pubspec.yaml @@ -0,0 +1,23 @@ +name: local_db_core +description: A new Flutter project. +version: 1.0.0+1 +publish_to: 'none' + +environment: + sdk: ">=2.17.6 <3.0.0" +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^1.0.2 + hive: ^2.0.5 + hive_flutter: ^1.1.0 + path_provider: ^2.0.11 + repositories: + path: ../../../../domain/repositories + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 +flutter: + uses-material-design: true \ No newline at end of file diff --git a/data/data_core/local_db/local_db_core/test/widget_test.dart b/data/data_core/local_db/local_db_core/test/widget_test.dart new file mode 100644 index 0000000..9a3bf78 --- /dev/null +++ b/data/data_core/local_db/local_db_core/test/widget_test.dart @@ -0,0 +1,10 @@ +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('adds one to input values', () { + // final calculator = Calculator(); + // expect(calculator.addOne(2), 3); + // expect(calculator.addOne(-7), -6); + // expect(calculator.addOne(0), 1); + }); +} diff --git a/data/data_core/network/network_core/.gitignore b/data/data_core/network/network_core/.gitignore new file mode 100644 index 0000000..96486fd --- /dev/null +++ b/data/data_core/network/network_core/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/data/data_core/network/network_core/.metadata b/data/data_core/network/network_core/.metadata new file mode 100644 index 0000000..e7011f6 --- /dev/null +++ b/data/data_core/network/network_core/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + channel: stable + +project_type: package diff --git a/data/data_core/network/network_core/CHANGELOG.md b/data/data_core/network/network_core/CHANGELOG.md new file mode 100644 index 0000000..41cc7d8 --- /dev/null +++ b/data/data_core/network/network_core/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/data/data_core/network/network_core/README.md b/data/data_core/network/network_core/README.md new file mode 100644 index 0000000..8b55e73 --- /dev/null +++ b/data/data_core/network/network_core/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/data/data_core/network/network_core/lib/initializer/base_initializer.dart b/data/data_core/network/network_core/lib/initializer/base_initializer.dart new file mode 100644 index 0000000..7970f51 --- /dev/null +++ b/data/data_core/network/network_core/lib/initializer/base_initializer.dart @@ -0,0 +1,37 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/interface/network_initializer_interface.dart'; +import 'package:network_core/network/networking/api_endpoint.dart'; +import 'package:network_core/network/networking/api_service.dart'; +import 'package:network_core/network/networking/dio_service.dart'; +import 'package:network_core/network/networking/interceptors/api_interceptor.dart'; + +class BaseInitializer implements NetworkInitializerInterface { + factory BaseInitializer() { + return instance; + } + + BaseInitializer.privateConstructor(); + + static final BaseInitializer instance = BaseInitializer.privateConstructor(); + + @override + DioService getDioService() { + return DioService( + dioClient: getDioClient(), + interceptors: [ + ApiInterceptor(), + ], + ); + } + + @override + Dio getDioClient() { + final baseOptions = BaseOptions(baseUrl: ApiEndpoint.baseUrl); + return Dio(baseOptions); + } + + @override + ApiService getApiService() { + return ApiService(getDioService()); + } +} diff --git a/data/data_core/network/network_core/lib/initializer/gamification_initializer.dart b/data/data_core/network/network_core/lib/initializer/gamification_initializer.dart new file mode 100644 index 0000000..18515b2 --- /dev/null +++ b/data/data_core/network/network_core/lib/initializer/gamification_initializer.dart @@ -0,0 +1,34 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/interface/network_initializer_interface.dart'; +import 'package:network_core/network/networking/api_endpoint.dart'; +import 'package:network_core/network/networking/api_service.dart'; +import 'package:network_core/network/networking/dio_service.dart'; + +class GamificationInitializer implements NetworkInitializerInterface { + factory GamificationInitializer() { + return instance; + } + + GamificationInitializer.privateConstructor(); + + static final GamificationInitializer instance = GamificationInitializer.privateConstructor(); + + @override + DioService getDioService() { + return DioService( + dioClient: getDioClient(), + interceptors: [], + ); + } + + @override + Dio getDioClient() { + final baseOptions = BaseOptions(baseUrl: ApiEndpoint.gamificationBaseUrl); + return Dio(baseOptions); + } + + @override + ApiService getApiService() { + return ApiService(getDioService()); + } +} diff --git a/data/data_core/network/network_core/lib/initializer/hamrah_cloud_initializer.dart b/data/data_core/network/network_core/lib/initializer/hamrah_cloud_initializer.dart new file mode 100644 index 0000000..8ff1035 --- /dev/null +++ b/data/data_core/network/network_core/lib/initializer/hamrah_cloud_initializer.dart @@ -0,0 +1,37 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/interface/network_initializer_interface.dart'; +import 'package:network_core/network/networking/api_endpoint.dart'; +import 'package:network_core/network/networking/api_service.dart'; +import 'package:network_core/network/networking/dio_service.dart'; +import 'package:network_core/network/networking/interceptors/api_interceptor.dart'; + +class HamrahCloudInitializer implements NetworkInitializerInterface { + factory HamrahCloudInitializer() { + return instance; + } + + HamrahCloudInitializer.privateConstructor(); + + static final HamrahCloudInitializer instance = HamrahCloudInitializer.privateConstructor(); + + @override + DioService getDioService() { + return DioService( + dioClient: getDioClient(), + interceptors: [ + ApiInterceptor(useToken: false, addAllowMethod: false), + ], + ); + } + + @override + Dio getDioClient() { + final baseOptions = BaseOptions(baseUrl: ApiEndpoint.hamrahCloudBaseUrl); + return Dio(baseOptions); + } + + @override + ApiService getApiService() { + return ApiService(getDioService()); + } +} diff --git a/data/data_core/network/network_core/lib/initializer/logger_initializer.dart b/data/data_core/network/network_core/lib/initializer/logger_initializer.dart new file mode 100644 index 0000000..6aecdc6 --- /dev/null +++ b/data/data_core/network/network_core/lib/initializer/logger_initializer.dart @@ -0,0 +1,39 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/interface/network_initializer_interface.dart'; +import 'package:network_core/network/networking/api_endpoint.dart'; +import 'package:network_core/network/networking/api_service.dart'; +import 'package:network_core/network/networking/dio_service.dart'; +import 'package:network_core/network/networking/interceptors/api_interceptor.dart'; + +class LoggerInitializer implements NetworkInitializerInterface { + factory LoggerInitializer() { + return instance; + } + + LoggerInitializer.privateConstructor(); + + static final LoggerInitializer instance = LoggerInitializer.privateConstructor(); + + @override + DioService getDioService() { + return DioService( + dioClient: getDioClient(), + interceptors: [ + ApiInterceptor(), + ], + ); + } + + @override + Dio getDioClient() { + final baseOptions = BaseOptions( + baseUrl: ApiEndpoint.loggerBaseUrl, + ); + return Dio(baseOptions); + } + + @override + ApiService getApiService() { + return ApiService(getDioService()); + } +} diff --git a/data/data_core/network/network_core/lib/network/helper/config.dart b/data/data_core/network/network_core/lib/network/helper/config.dart new file mode 100644 index 0000000..86bcd11 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/helper/config.dart @@ -0,0 +1,20 @@ +import 'package:flutter/foundation.dart'; + +@immutable +class Config { + const Config._(); + + static const baseUrl = String.fromEnvironment('BASE_URL', defaultValue: 'https://api-game.zarebin.ir/api'); + + static const loggerBaseUrl = String.fromEnvironment( + 'BASE_URL', + defaultValue: 'https://supervisor.pr.mci.dev/api/v1/', + ); + + static const hamrahCloudBaseUrl = String.fromEnvironment( + 'BASE_URL', + defaultValue: 'https://hamrahi.cloud/live/api/v1', + ); + + static const gamificationBaseUrl = String.fromEnvironment('BASE_URL', defaultValue: 'https://eagle-eyes.st.mci.dev'); +} diff --git a/data/data_core/network/network_core/lib/network/helper/path_provider_service.dart b/data/data_core/network/network_core/lib/network/helper/path_provider_service.dart new file mode 100644 index 0000000..b60938e --- /dev/null +++ b/data/data_core/network/network_core/lib/network/helper/path_provider_service.dart @@ -0,0 +1,21 @@ +import 'package:path_provider/path_provider.dart' as pp; + +class PathProviderService { + PathProviderService._(); + + static String? _path; + + static String get path { + if (_path != null) { + return _path!; + } else { + throw Exception('Path not initialized'); + } + } + + static Future init() async { + final dir = await pp.getApplicationDocumentsDirectory(); + _path = dir.path; + return _path!; + } +} diff --git a/data/data_core/network/network_core/lib/network/helper/util.dart b/data/data_core/network/network_core/lib/network/helper/util.dart new file mode 100644 index 0000000..1361329 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/helper/util.dart @@ -0,0 +1,8 @@ +import 'package:flutter/foundation.dart'; + +@immutable +class Util { + const Util._(); + + static bool boolFromInt(int i) => i == 1; +} diff --git a/data/data_core/network/network_core/lib/network/interface/network_initializer_interface.dart b/data/data_core/network/network_core/lib/network/interface/network_initializer_interface.dart new file mode 100644 index 0000000..3a4b433 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/interface/network_initializer_interface.dart @@ -0,0 +1,11 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/networking/api_service.dart'; +import 'package:network_core/network/networking/dio_service.dart'; + +abstract class NetworkInitializerInterface { + DioService getDioService(); + + Dio getDioClient(); + + ApiService getApiService(); +} diff --git a/data/data_core/network/network_core/lib/network/networking/api_endpoint.dart b/data/data_core/network/network_core/lib/network/networking/api_endpoint.dart new file mode 100644 index 0000000..2d8d68c --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/api_endpoint.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:network_core/network/helper/config.dart'; + +@immutable +class ApiEndpoint { + const ApiEndpoint._(); + + static const baseUrl = Config.baseUrl; + static const loggerBaseUrl = Config.loggerBaseUrl; + static const hamrahCloudBaseUrl = Config.hamrahCloudBaseUrl; + static const gamificationBaseUrl = Config.gamificationBaseUrl; + + static String account(AccountEndpoint endpoint) { + return '/account/${endpoint.value}'; + } + + static String game(GameEndpoint endpoint) { + return '/game/${endpoint.value}'; + } + + static String general(GeneralEndPoint endPoint) { + return '/general/${endPoint.value}'; + } + + static String leaderboard(LeaderboardEndpoint endpoint) { + return '/leaderboard/${endpoint.value}'; + } + + static String gamePlayer(GamePlayerEndpoint endpoint) { + return '/game-player/${endpoint.value}'; + } + + static String getFriendReq(FriendRequestEndPoint endPoint) { + return '/player/friendRequest/${endPoint.value}'; + } + + static String logger(LogEndPoint endPoint) { + return endPoint.value; + } + + static String hamrahCloud(HamrahCloudEndpoint endPoint) { + return endPoint.value; + } + + static String campaigns(CampaignsEndPoint endPoint) { + return '/api/v1/campaigns/${endPoint.value}/'; + } +} + +enum AccountEndpoint { + profile('profile'); + + final String value; + + const AccountEndpoint(this.value); +} + +enum GamePlayerEndpoint { + playerInfo('gamePlayerInfo'), + myRank('best'); + + final String value; + + const GamePlayerEndpoint(this.value); +} + +enum GameEndpoint { + banners('banners'), + categories('categories'), + favoriteGames('favorite-games'), + gameProfile('game-profile'), + games('games'), + recentPlayedGames('recent-played-games'), + search('search'), + searchHistory('search-history'), + suggestedGames('suggested-games'), + topGames('top-games'); + + final String value; + + const GameEndpoint(this.value); +} + +enum GeneralEndPoint { + streams('streams'), + whiteList('channels/whitelist'), + deepLink('deeplink'), + lv('lv'), + rootItems('root_items'); + + final String value; + + const GeneralEndPoint(this.value); +} + +enum LeaderboardEndpoint { + campaignLeaderboard('campaign-leaderboard'), + games('games'), + leaderboards('leaderboards'); + + final String value; + + const LeaderboardEndpoint(this.value); +} + +enum FriendRequestEndPoint { + createFriendReq(''), + answerFriendReq('answer'), + getWaitingAddFriendReq('waiting'); + + final String value; + + const FriendRequestEndPoint(this.value); +} + +enum LogEndPoint { + multiEvent('events'), + singleEvent('event'); + + final String value; + + const LogEndPoint(this.value); +} + +enum HamrahCloudEndpoint { + list('/vod/viewers/list-vod/'), + search('/live/search/pinobject/387/?'); + + final String value; + + const HamrahCloudEndpoint(this.value); +} + +enum CampaignsEndPoint { + events('events'); + + final String value; + + const CampaignsEndPoint(this.value); +} \ No newline at end of file diff --git a/data/data_core/network/network_core/lib/network/networking/api_interface.dart b/data/data_core/network/network_core/lib/network/networking/api_interface.dart new file mode 100644 index 0000000..8fc9cf9 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/api_interface.dart @@ -0,0 +1,41 @@ +import 'package:dio/dio.dart'; +import 'package:network_core/network/networking/response_model.dart'; +import 'package:repositories/typedefs.dart'; + +abstract class ApiInterface { + const ApiInterface(); + + Future getCollectionData({ + required String endpoint, + JSON? queryParams, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required T Function(Response responseBody) converter, + }); + + Future getDocumentData({ + required String endpoint, + JSON? queryParams, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required T Function(JSON responseBody) converter, + }); + + Future setData({ + required String endpoint, + required JSON data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required T Function(Response response) converter, + }); + + Future deleteData({ + required String endpoint, + JSON? data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required T Function(ResponseModel response) converter, + }); + + void cancelRequests({CancelToken? cancelToken}); +} diff --git a/data/data_core/network/network_core/lib/network/networking/api_service.dart b/data/data_core/network/network_core/lib/network/networking/api_service.dart new file mode 100644 index 0000000..f374684 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/api_service.dart @@ -0,0 +1,210 @@ +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:network_core/network/networking/api_interface.dart'; +import 'package:network_core/network/networking/custom_exception.dart'; +import 'package:network_core/network/networking/dio_service.dart'; +import 'package:network_core/network/networking/response_model.dart'; +import 'package:repositories/typedefs.dart'; + +class ApiService implements ApiInterface { + ApiService(DioService dioService) : _dioService = dioService; + late final DioService _dioService; + + @override + Future getCollectionData({ + required String endpoint, + JSON? queryParams, + CancelToken? cancelToken, + CachePolicy? cachePolicy, + int? cacheAgeDays, + bool requiresAuthToken = true, + required T Function(Response responseBody) converter, + }) async { + Response data; + try { + data = await _dioService.getData( + endpoint: endpoint, + options: Options( + extra: { + 'requiresAuthToken': requiresAuthToken, + }, + ), + queryParams: queryParams, + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(data); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + @override + Future getDocumentData({ + required String endpoint, + JSON? queryParams, + CancelToken? cancelToken, + CachePolicy? cachePolicy, + int? cacheAgeDays, + bool requiresAuthToken = true, + required T Function(JSON response) converter, + }) async { + Response response; + try { + response = await _dioService.get( + endpoint: endpoint, + queryParams: queryParams, + cacheOptions: _dioService.globalCacheOptions?.copyWith( + policy: cachePolicy, + maxStale: cacheAgeDays != null ? Nullable(Duration(days: cacheAgeDays)) : null, + ), + options: requiresAuthToken + ? Options( + extra: {'requiresAuthToken': requiresAuthToken}, + ) + : null, + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(response.data); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + @override + Future setData({ + required String endpoint, + JSON? data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + ProgressCallback? onReceiveProgress, + JSON? queryParams, + required T Function(Response response) converter, + }) async { + Response response; + try { + response = await _dioService.post( + endpoint: endpoint, + data: data, + queryParams: queryParams, + onReceiveProgress: onReceiveProgress, + options: Options( + extra: { + 'requiresAuthToken': requiresAuthToken, + }, + ), + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(response); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + Future setDataWithListResponse({ + required String endpoint, + JSON? data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + ProgressCallback? onReceiveProgress, + JSON? queryParams, + required T Function(Response response) converter, + }) async { + Response response; + try { + response = await _dioService.post>( + endpoint: endpoint, + data: data, + queryParams: queryParams, + onReceiveProgress: onReceiveProgress, + options: Options( + extra: { + 'requiresAuthToken': requiresAuthToken, + }, + ), + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(response); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + Future updateData({ + required String endpoint, + required JSON data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required Function() converter, + }) async { + try { + await _dioService.patchData( + endpoint: endpoint, + data: data, + options: Options( + extra: { + 'requiresAuthToken': requiresAuthToken, + }, + ), + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + @override + Future deleteData({ + required String endpoint, + JSON? data, + CancelToken? cancelToken, + bool requiresAuthToken = true, + required T Function(ResponseModel response) converter, + }) async { + ResponseModel response; + try { + response = await _dioService.delete( + endpoint: endpoint, + data: data, + options: Options( + extra: { + 'requiresAuthToken': requiresAuthToken, + }, + ), + cancelToken: cancelToken, + ); + } on Exception catch (ex) { + throw CustomException.fromDioException(ex); + } + try { + return converter(response); + } on Exception catch (ex) { + throw CustomException.fromParsingException(ex); + } + } + + @override + void cancelRequests({CancelToken? cancelToken}) { + _dioService.cancelRequests(cancelToken: cancelToken); + } +} diff --git a/data/data_core/network/network_core/lib/network/networking/custom_exception.dart b/data/data_core/network/network_core/lib/network/networking/custom_exception.dart new file mode 100644 index 0000000..0d291c9 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/custom_exception.dart @@ -0,0 +1,111 @@ +import 'package:dio/dio.dart'; + +enum ExceptionType { + tokenExpiredException, + cancelException, + connectTimeoutException, + sendTimeoutException, + receiveTimeoutException, + socketException, + fetchDataException, + formatException, + unrecognizedException, + apiException, + serializationException, +} + +class CustomException implements Exception { + CustomException({ + this.code, + int? statusCode, + required this.message, + this.exceptionType = ExceptionType.apiException, + String? apiPath, + }) : statusCode = statusCode ?? 500, + apiPath = apiPath ?? '', + name = exceptionType.name; + + factory CustomException.fromDioException(Exception error) { + try { + if (error is DioError) { + switch (error.type) { + case DioErrorType.cancel: + return CustomException( + exceptionType: ExceptionType.cancelException, + statusCode: error.response?.statusCode, + message: 'Request cancelled prematurely', + ); + case DioErrorType.connectTimeout: + return CustomException( + exceptionType: ExceptionType.connectTimeoutException, + statusCode: error.response?.statusCode, + message: 'Connection not established', + ); + case DioErrorType.sendTimeout: + return CustomException( + exceptionType: ExceptionType.sendTimeoutException, + statusCode: error.response?.statusCode, + message: 'Failed to send', + ); + case DioErrorType.receiveTimeout: + return CustomException( + exceptionType: ExceptionType.receiveTimeoutException, + statusCode: error.response?.statusCode, + message: 'Failed to receive', + ); + case DioErrorType.response: + case DioErrorType.other: + if (error.response != null) { + if (error.response?.data != null) { + return CustomException( + exceptionType: ExceptionType.apiException, + statusCode: error.response?.statusCode, + message: error.response?.data.toString() ?? '', + apiPath: error.requestOptions.baseUrl + error.requestOptions.path, + ); + } + return CustomException( + exceptionType: ExceptionType.apiException, + statusCode: error.response?.statusCode, + message: '', + ); + } + return CustomException( + exceptionType: ExceptionType.apiException, + statusCode: error.response?.statusCode, + message: '', + ); + } + } else { + return CustomException( + exceptionType: ExceptionType.unrecognizedException, + message: 'Error unrecognized', + ); + } + } on FormatException catch (e) { + return CustomException( + exceptionType: ExceptionType.formatException, + message: e.message, + ); + } on Exception catch (_) { + return CustomException( + exceptionType: ExceptionType.unrecognizedException, + message: 'Error unrecognized', + ); + } + } + + factory CustomException.fromParsingException(Exception error) { + return CustomException( + exceptionType: ExceptionType.serializationException, + message: 'Failed to parse network response to model or vice versa', + ); + } + + final String name; + String message; + final String? code; + final int? statusCode; + final ExceptionType exceptionType; + String? apiPath; +} diff --git a/data/data_core/network/network_core/lib/network/networking/dio_service.dart b/data/data_core/network/network_core/lib/network/networking/dio_service.dart new file mode 100644 index 0000000..b8050ec --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/dio_service.dart @@ -0,0 +1,203 @@ +import 'dart:async'; + +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:network_core/network/networking/response_model.dart'; +import 'package:repositories/typedefs.dart'; + +class DioService { + DioService({ + required Dio dioClient, + this.globalCacheOptions, + Iterable? interceptors, + HttpClientAdapter? httpClientAdapter, + }) : _dio = dioClient, + _cancelToken = CancelToken() { + if (interceptors != null) { + _dio.interceptors.addAll(interceptors); + } + if (httpClientAdapter != null) { + _dio.httpClientAdapter = httpClientAdapter; + } + } + + final Dio _dio; + final CacheOptions? globalCacheOptions; + final CancelToken _cancelToken; + + void cancelRequests({CancelToken? cancelToken}) { + if (cancelToken == null) { + _cancelToken.cancel('Cancelled'); + } else { + cancelToken.cancel(); + } + } + + Future get({ + required String endpoint, + JSON? queryParams, + Options? options, + CacheOptions? cacheOptions, + CancelToken? cancelToken, + }) async { + final response = await _dio.get( + endpoint, + queryParameters: queryParams, + options: _mergeDioAndCacheOptions( + dioOptions: options, + cacheOptions: cacheOptions, + ), + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future getData({ + required String endpoint, + Options? options, + CancelToken? cancelToken, + JSON? queryParams, + }) async { + final response = await _dio.get( + endpoint, + queryParameters: queryParams, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future post({ + required String endpoint, + JSON? data, + Options? options, + JSON? queryParams, + CancelToken? cancelToken, + ProgressCallback? onReceiveProgress, + }) async { + final response = await _dio.post( + endpoint, + data: data, + options: options, + queryParameters: queryParams, + cancelToken: cancelToken ?? _cancelToken, + onReceiveProgress: onReceiveProgress, + ); + return response; + } + + Future upload({ + required String endpoint, + required FormData data, + Options? options, + JSON? queryParams, + CancelToken? cancelToken, + }) async { + final response = await _dio.post( + endpoint, + queryParameters: queryParams, + data: data, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future postData({ + required String endpoint, + JSON? data, + Options? options, + CancelToken? cancelToken, + JSON? queryParams, + }) async { + final response = await _dio.post( + endpoint, + data: data, + queryParameters: queryParams, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future postDataWithParams({ + required String endpoint, + JSON? data, + JSON? queryParams, + Options? options, + CancelToken? cancelToken, + }) async { + final response = await _dio.post( + endpoint, + data: data, + queryParameters: queryParams, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future patchData({ + required String endpoint, + JSON? data, + Options? options, + CancelToken? cancelToken, + }) async { + final response = await _dio.patch( + endpoint, + data: data, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return response; + } + + Future> patch({ + required String endpoint, + JSON? data, + Options? options, + CancelToken? cancelToken, + }) async { + final response = await _dio.patch( + endpoint, + data: data, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return ResponseModel.fromJson(response.data!); + } + + Future> delete({ + required String endpoint, + JSON? data, + Options? options, + CancelToken? cancelToken, + }) async { + final response = await _dio.delete( + endpoint, + data: data, + options: options, + cancelToken: cancelToken ?? _cancelToken, + ); + return ResponseModel.fromJson(response.data!); + } + + Options? _mergeDioAndCacheOptions({ + Options? dioOptions, + CacheOptions? cacheOptions, + }) { + if (dioOptions == null && cacheOptions == null) { + return null; + } else if (dioOptions == null && cacheOptions != null) { + return cacheOptions.toOptions(); + } else if (dioOptions != null && cacheOptions == null) { + return dioOptions; + } + + final cacheOptionsMap = cacheOptions!.toExtra(); + final options = dioOptions!.copyWith( + extra: {...dioOptions.extra!, ...cacheOptionsMap}, + ); + return options; + } +} diff --git a/data/data_core/network/network_core/lib/network/networking/interceptors/api_interceptor.dart b/data/data_core/network/network_core/lib/network/networking/interceptors/api_interceptor.dart new file mode 100644 index 0000000..f869e15 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/interceptors/api_interceptor.dart @@ -0,0 +1,53 @@ +import 'package:data/app_setting_data/repository/app_setting_box_repository_impl.dart'; +import 'package:dio/dio.dart'; +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:repositories/app_setting_box_domain/model/user_data_model.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; + +class ApiInterceptor extends Interceptor { + final bool useToken; + final bool addAllowMethod; + AppSettingBoxRepository _repository = AppSettingBoxRepositoryImpl(appSettingBox: AppSettingBox()); + + ApiInterceptor({this.useToken = true, this.addAllowMethod = true}); + + @override + Future onRequest(RequestOptions options, RequestInterceptorHandler handler) async { + if (options.extra['requiresAuthToken'] == true) { + options.headers.addAll({ + 'Content-Type': 'application/json', + 'Accept': '*/*', + }); + if (addAllowMethod) { + options.headers.addAll({ + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE, HEAD', + 'Access-Control-Allow-Origin': '*', + }); + } + UserDataModel? userData = await _repository.getUserData(); + if (useToken) { + if (userData != null) { + options.headers.addAll({ + 'Authorization': 'Bearer ${userData.token}', + }); + } + } + } + options.extra.remove('requiresAuthToken'); + return handler.next(options); + } + + @override + void onResponse(Response response, ResponseInterceptorHandler handler) { + final success = [200, 201, 202, 203, 204].contains(response.statusCode); + if (success) { + return handler.next(response); + } + return handler.reject( + DioError( + requestOptions: response.requestOptions, + response: response, + ), + ); + } +} diff --git a/data/data_core/network/network_core/lib/network/networking/response_model.dart b/data/data_core/network/network_core/lib/network/networking/response_model.dart new file mode 100644 index 0000000..c5687f9 --- /dev/null +++ b/data/data_core/network/network_core/lib/network/networking/response_model.dart @@ -0,0 +1,48 @@ +import 'package:repositories/typedefs.dart'; + +class ResponseModel { + final T data; + String? message; + final ResponseStatus code; + + ResponseModel({ + required this.data, + required this.code, + this.message, + }); + + factory ResponseModel.fromJson(JSON json) { + return ResponseModel( + data: json['data'], + code: json['status'] == 'success' ? ResponseStatus.success : ResponseStatus.failure, + ); + } +} + +enum ResponseStatus { + success('success'), + failure('failure'); + + final String value; + + const ResponseStatus(this.value); +} + +class ResponseListModel { + final List data; + String? message; + final ResponseStatus code; + + ResponseListModel({ + required this.data, + required this.code, + this.message, + }); + + factory ResponseListModel.fromJson(JSON json) { + return ResponseListModel( + data: json['data'], + code: json['status'] == 'success' ? ResponseStatus.success : ResponseStatus.failure, + ); + } +} diff --git a/data/data_core/network/network_core/pubspec.yaml b/data/data_core/network/network_core/pubspec.yaml new file mode 100644 index 0000000..e58850b --- /dev/null +++ b/data/data_core/network/network_core/pubspec.yaml @@ -0,0 +1,26 @@ +name: network_core +description: A new Flutter project. +version: 0.0.1 +publish_to: 'none' + + +environment: + sdk: ">=2.17.6 <3.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + dio: ^4.0.6 + dio_cache_interceptor: ^3.3.1 + repositories: + path: ../../../../domain/repositories + local_db_core: + path: ../../../../data/data_core/local_db/local_db_core + data: + path: ../../../../data/data_types/data + +dev_dependencies: + flutter_test: + sdk: flutter +flutter: diff --git a/data/data_types/data/.gitignore b/data/data_types/data/.gitignore new file mode 100644 index 0000000..96486fd --- /dev/null +++ b/data/data_types/data/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/data/data_types/data/.metadata b/data/data_types/data/.metadata new file mode 100644 index 0000000..fbfa6df --- /dev/null +++ b/data/data_types/data/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + channel: stable + +project_type: package diff --git a/data/data_types/data/CHANGELOG.md b/data/data_types/data/CHANGELOG.md new file mode 100644 index 0000000..41cc7d8 --- /dev/null +++ b/data/data_types/data/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/data/data_types/data/README.md b/data/data_types/data/README.md new file mode 100644 index 0000000..02fe8ec --- /dev/null +++ b/data/data_types/data/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/data/data_types/data/lib/app_setting_data/repository/app_setting_box_repository_impl.dart b/data/data_types/data/lib/app_setting_data/repository/app_setting_box_repository_impl.dart new file mode 100644 index 0000000..40735b8 --- /dev/null +++ b/data/data_types/data/lib/app_setting_data/repository/app_setting_box_repository_impl.dart @@ -0,0 +1,102 @@ +import 'dart:convert'; + +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:repositories/app_setting_box_domain/model/user_data_model.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; + +class AppSettingBoxRepositoryImpl extends AppSettingBoxRepository { + final AppSettingBox _appSettingBox; + + AppSettingBoxRepositoryImpl({required AppSettingBox appSettingBox}) : _appSettingBox = appSettingBox; + + @override + String? getAppDirection() { + return _appSettingBox.getAppDirection(); + } + + @override + String? getCurrentLanguage() { + return _appSettingBox.getCurrentLanguage(); + } + + @override + Future setCurrentLanguage(String language) async { + await _appSettingBox.setCurrentLanguage(language); + return; + } + + @override + Future openBox() async { + await _appSettingBox.openBox(); + } + + @override + void setAppDirection(String value) { + _appSettingBox.setAppDirection(value); + } + + @override + Future getUserData() async { + return await _appSettingBox.getUserData(); + } + + @override + Future setUserData(Map data) async { + return await _appSettingBox.setUserData(data); + } + + @override + Future isUserLogin() async { + return await _appSettingBox.getUserData() != null; + } + + @override + Future getUserId() async { + bool isLogin = await isUserLogin(); + if (!isLogin) { + return null; + } + UserDataModel? data = await _appSettingBox.getUserData(); + if (data == null) { + return null; + } + Map tokenData = parseJwt(data.token); + if (tokenData.containsKey('muid')) { + return tokenData['muid']; + } + if (tokenData.containsKey('data')) { + return tokenData['data']; + } + return null; + } + + Map parseJwt(String token) { + final parts = token.split('.'); + if (parts.length != 3) { + throw Exception('invalid token'); + } + final payload = decodeBase64(parts[1]); + final payloadMap = json.decode(payload); + if (payloadMap is! Map) { + throw Exception('invalid payload'); + } + return payloadMap; + } + + String decodeBase64(String str) { + String output = str.replaceAll('-', '+').replaceAll('_', '/'); + switch (output.length % 4) { + case 0: + break; + case 2: + output += '=='; + break; + case 3: + output += '='; + break; + default: + throw Exception('Illegal base64url string!"'); + } + return utf8.decode(base64Url.decode(output)); + } +} diff --git a/data/data_types/data/pubspec.yaml b/data/data_types/data/pubspec.yaml new file mode 100644 index 0000000..6ab0788 --- /dev/null +++ b/data/data_types/data/pubspec.yaml @@ -0,0 +1,22 @@ +name: data +description: A new Flutter package project. +version: 0.0.1 +publish_to: 'none' + +environment: + sdk: '>=2.18.5 <3.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + repositories: + path: ../../../domain/repositories + local_db_core: + path: ../../data_core/local_db/local_db_core + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 +flutter: diff --git a/domain/repositories/.gitignore b/domain/repositories/.gitignore new file mode 100644 index 0000000..96486fd --- /dev/null +++ b/domain/repositories/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/domain/repositories/analysis_options.yaml b/domain/repositories/analysis_options.yaml new file mode 100644 index 0000000..a5744c1 --- /dev/null +++ b/domain/repositories/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/domain/repositories/lib/app_setting_box_domain/model/user_data_model.dart b/domain/repositories/lib/app_setting_box_domain/model/user_data_model.dart new file mode 100644 index 0000000..4641ab6 --- /dev/null +++ b/domain/repositories/lib/app_setting_box_domain/model/user_data_model.dart @@ -0,0 +1,13 @@ +class UserDataModel { + final String token; + + UserDataModel({required this.token}); + + Map toJson() { + return {"token": token}; + } + + factory UserDataModel.fromJson(Map json) { + return UserDataModel(token: json['token']); + } +} diff --git a/domain/repositories/lib/app_setting_box_domain/repository/app_setting_box_repository.dart b/domain/repositories/lib/app_setting_box_domain/repository/app_setting_box_repository.dart new file mode 100644 index 0000000..029e43e --- /dev/null +++ b/domain/repositories/lib/app_setting_box_domain/repository/app_setting_box_repository.dart @@ -0,0 +1,21 @@ +import 'package:repositories/app_setting_box_domain/model/user_data_model.dart'; + +abstract class AppSettingBoxRepository { + Future openBox(); + + String? getAppDirection(); + + void setAppDirection(String value); + + String? getCurrentLanguage(); + + Future setCurrentLanguage(String language); + + Future getUserData(); + + Future setUserData(Map data); + + Future isUserLogin(); + + Future getUserId(); +} diff --git a/domain/repositories/lib/typedefs.dart b/domain/repositories/lib/typedefs.dart new file mode 100644 index 0000000..61d928b --- /dev/null +++ b/domain/repositories/lib/typedefs.dart @@ -0,0 +1,6 @@ +import 'package:flutter/material.dart'; + +typedef JSON = Map; +typedef QueryParams = Map; +typedef RouteBuilder = Widget Function(BuildContext); +typedef ItemBuilder = Widget Function(BuildContext, T); diff --git a/domain/repositories/pubspec.yaml b/domain/repositories/pubspec.yaml new file mode 100644 index 0000000..4937cde --- /dev/null +++ b/domain/repositories/pubspec.yaml @@ -0,0 +1,17 @@ +name: repositories +description: A new Flutter project. +version: 0.0.1 + +environment: + sdk: ">=2.17.6 <3.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 +flutter: diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..78e0143 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,613 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.sonnat; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..e42adcb --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..cca0f55 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Sonnat + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + sonnat + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/core/extensions/context_extension.dart b/lib/core/extensions/context_extension.dart new file mode 100644 index 0000000..605bd2d --- /dev/null +++ b/lib/core/extensions/context_extension.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/theme/cubit/theme_cubit.dart'; + +extension ContextExtentions on BuildContext { + double get height { + return MediaQuery.of(this).size.height; + } + + double get width { + return MediaQuery.of(this).size.width; + } + + Container get horizontalDivider { + return Container( + height: 2, + margin: const EdgeInsets.symmetric(horizontal: 16), + width: width, + color: theme.colors.primary80.withOpacity(0.05), + ); + } + + Container get verticalDivider { + return Container( + height: 12, + width: 1, + color: theme.colors.primary80.withOpacity(0.05), + ); + } + + ThemeCubit get theme { + return read(); + } + + Future push(Widget page) async { + await Navigator.push(this, MaterialPageRoute(builder: (_) => page)); + } + + Future pushNamed(String name) async { + await Navigator.pushNamed(this, name); + } + + Future pushReplacement(Widget page) async { + await Navigator.pushReplacement(this, MaterialPageRoute(builder: (_) => page)); + } + + Future pop(Widget page, [result]) async { + Navigator.pop(this, result); + } +} diff --git a/lib/core/extensions/string_extension.dart b/lib/core/extensions/string_extension.dart new file mode 100644 index 0000000..09082f4 --- /dev/null +++ b/lib/core/extensions/string_extension.dart @@ -0,0 +1,21 @@ +extension StringExtentions on String { + String get svgPath { + return 'assets/images/svg/$this.svg'; + } + + String get pngPath { + return 'assets/images/png/$this.png'; + } + + String get jpgPath { + return 'assets/images/jpg/$this.jpg'; + } + + String get avatarPath { + return 'assets/images/avatar/$this.jpg'; + } + + String get lottiePath { + return 'assets/lottie_files/$this.json'; + } +} diff --git a/lib/core/extensions/text_style_extension.dart b/lib/core/extensions/text_style_extension.dart new file mode 100644 index 0000000..30f08fe --- /dev/null +++ b/lib/core/extensions/text_style_extension.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; + +extension MainTextStyle on TextStyle { + TextStyle get main { + return const TextStyle( + fontSize: 16, + color: Colors.white, + fontWeight: FontWeight.w700, + ); + } +} diff --git a/lib/core/language/language_cubit.dart b/lib/core/language/language_cubit.dart new file mode 100644 index 0000000..078c3e8 --- /dev/null +++ b/lib/core/language/language_cubit.dart @@ -0,0 +1,76 @@ +import 'package:data/app_setting_data/repository/app_setting_box_repository_impl.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; +import 'package:sonnat/core/language/translator.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; + +enum LanguageState { + loading, + loaded, +} + +enum CurrentLanguage { + en, + fa, + ar, +} + +enum Languages { + fa('fa'), + en('en'), + ar('ar'); + + const Languages(this.value); + + final String value; +} + +class LanguageCubit extends Cubit> { + final AppSettingBoxRepository _repository = AppSettingBoxRepositoryImpl(appSettingBox: AppSettingBox()); + + LanguageCubit() : super(BaseCubitType(eventName: LanguageState.loading)) { + _initial(); + } + + Future _initial() async { + String? language = _repository.getCurrentLanguage(); + if (language == null || language == '') { + await Translator.setNewLanguage(Languages.fa); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.fa)); + return; + } + switch (language) { + case 'fa': + await Translator.setNewLanguage(Languages.fa); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.fa)); + return; + case 'en': + await Translator.setNewLanguage(Languages.en); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.en)); + return; + case 'ar': + await Translator.setNewLanguage(Languages.ar); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.ar)); + return; + } + } + + String getCurrentLanguage() { + String? language = _repository.getCurrentLanguage(); + if (language == null || language == '') { + return 'fa'; + } + return language; + } + + Future changeLanguage() async { + if (getCurrentLanguage() == 'fa') { + await Translator.setNewLanguage(Languages.en); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.en)); + } else { + await Translator.setNewLanguage(Languages.fa); + emit(BaseCubitType(eventName: LanguageState.loaded, data: CurrentLanguage.fa)); + } + } +} diff --git a/lib/core/language/translator.dart b/lib/core/language/translator.dart new file mode 100644 index 0000000..e367518 --- /dev/null +++ b/lib/core/language/translator.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:data/app_setting_data/repository/app_setting_box_repository_impl.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart' show rootBundle; +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; +import 'package:sonnat/core/language/language_cubit.dart'; + +final List supportedLanguages = [ + 'en', + 'fa', + 'ar', +]; + +class Translator { + static Map? _localizedValues; + + static Iterable supportedLocales() => supportedLanguages.map((lang) => Locale(lang, '')); + + static String translate(String key) { + if (_localizedValues == null || _localizedValues![key] == null) { + return '$key not found'; + } + return _localizedValues![key]; + } + + static Future setNewLanguage(Languages newLanguage) async { + AppSettingBoxRepository repository = AppSettingBoxRepositoryImpl(appSettingBox: AppSettingBox()); + Locale locale = Locale(newLanguage.value, ''); + String jsonContent = await rootBundle.loadString('assets/languages/${locale.languageCode}.json'); + _localizedValues = json.decode(jsonContent); + await repository.setCurrentLanguage(locale.languageCode); + return; + } + + Translator._internal(); +} diff --git a/lib/core/theme/cubit/theme_cubit.dart b/lib/core/theme/cubit/theme_cubit.dart new file mode 100644 index 0000000..d67b538 --- /dev/null +++ b/lib/core/theme/cubit/theme_cubit.dart @@ -0,0 +1,27 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/theme/panel_colors.dart'; +import 'package:sonnat/core/theme/panel_theme.dart'; +import 'package:sonnat/core/theme/panel_typography.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; + +class ThemeCubit extends Cubit> { + PanelTheme _currentTheme = LightTheme(); + + ThemeCubit() : super(BaseCubitType(eventName: ThemeState.empty)); + + void empty() => emit(BaseCubitType(eventName: ThemeState.empty)); + + void setTheme(PanelTheme theme) { + _currentTheme = theme; + } + + PanelTheme get currentTheme => _currentTheme; + + PanelColors get colors => _currentTheme.colors; + + PanelTypography get typo => _currentTheme.typography; +} + +enum ThemeState { + empty, +} diff --git a/lib/core/theme/panel_colors.dart b/lib/core/theme/panel_colors.dart new file mode 100644 index 0000000..067978d --- /dev/null +++ b/lib/core/theme/panel_colors.dart @@ -0,0 +1,296 @@ +import 'dart:ui'; + +abstract class PanelColors { + final Color primary; + final Color primary80; + final Color onPrimary; + final Color primaryContainer; + final Color onPrimaryContainer; + final Color secondary; + final Color onSecondary; + final Color secondaryContainer; + final Color onSecondaryContainer; + final Color tertiary; + final Color onTertiary; + final Color tertiaryContainer; + final Color onTertiaryContainer; + final Color error; + final Color onError; + final Color errorContainer; + final Color onErrorContainer; + final Color background; + final Color onBackground; + final Color onBackground2; + final Color onSurface; + final Color surfaceNeutral; + final Color tuneNeutral; + + final Color onSurfaceHighEmpathy; + final Color onSurfaceHighEmpathyReverse; + final Color onSurfaceMediumEmpathy; + final Color onSurfaceLowEmpathy; + final Color onSurfaceDisableEmpathy; + final Color onSurfaceOverlayLightHigh; + + final Color onPrimaryHighEmpathy; + final Color onPrimaryMediumEmpathy; + final Color onPrimaryLowEmpathy; + final Color outline; + final Color onSport; + final Color sport; + final Color sportContainer; + final Color onSportContainer; + final Color game; + final Color onGame; + final Color gameContainer; + final Color onGameContainer; + final Color ava; + final Color onAva; + final Color avaContainer; + final Color onAvaContainer; + final Color success; + final Color warning; + final Color info; + final Color link; + final Color linkClicked; + final Color focus; + final Color pressed; + final Color dargged; + final Color selected; + final Color hover; + + final Color surface; + final Color surface1; + final Color surface2; + final Color surface3; + final Color surface4; + final Color surface5; + final Color surface6; + + final Color background2; + final Color profileItemColor; + + final Color lightWarning; + final Color additionalGreen; + final Color additionalLightGreen; + final Color lightError; + + PanelColors({ + required this.onBackground2, + required this.additionalLightGreen, + required this.additionalGreen, + required this.surface6, + required this.lightError, + required this.lightWarning, + required this.primary, + required this.tuneNeutral, + required this.primary80, + required this.profileItemColor, + required this.onPrimary, + required this.primaryContainer, + required this.onPrimaryContainer, + required this.secondary, + required this.onSecondary, + required this.secondaryContainer, + required this.onSecondaryContainer, + required this.tertiary, + required this.onTertiary, + required this.tertiaryContainer, + required this.onTertiaryContainer, + required this.background, + required this.onBackground, + required this.surfaceNeutral, + required this.onSurface, + required this.onPrimaryHighEmpathy, + required this.onPrimaryMediumEmpathy, + required this.onPrimaryLowEmpathy, + required this.outline, + required this.onSport, + required this.sport, + required this.sportContainer, + required this.onSportContainer, + required this.game, + required this.onGame, + required this.gameContainer, + required this.pressed, + required this.dargged, + required this.onGameContainer, + required this.ava, + required this.onAva, + required this.avaContainer, + required this.onAvaContainer, + required this.success, + required this.warning, + required this.info, + required this.link, + required this.linkClicked, + required this.focus, + required this.selected, + required this.hover, + required this.error, + required this.onError, + required this.errorContainer, + required this.onErrorContainer, + required this.onSurfaceDisableEmpathy, + required this.onSurfaceHighEmpathy, + required this.onSurfaceHighEmpathyReverse, + required this.onSurfaceLowEmpathy, + required this.onSurfaceMediumEmpathy, + required this.surface, + required this.surface1, + required this.surface2, + required this.surface3, + required this.surface4, + required this.surface5, + required this.background2, + required this.onSurfaceOverlayLightHigh, + }); +} + +class LightThemeColors extends PanelColors { + LightThemeColors() + : super( + onBackground2: const Color(0xff1B1B1F), + additionalLightGreen: const Color(0xffF6FFF1), + additionalGreen: const Color(0xff16A765), + surface6: const Color(0xff7C4DFF).withOpacity(0.05), + lightError: const Color(0xffBA1A1A), + lightWarning: const Color(0xffFFB300), + primary: const Color(0xFF7C4DFF), + tuneNeutral: const Color(0xFFE3E2E6), + primary80: const Color(0xFF303034), + profileItemColor: const Color(0xFFFDA126), + onPrimary: const Color(0xFFFFFFFF), + primaryContainer: const Color(0xFFE8DEFF), + onPrimaryContainer: const Color(0xFF370096), + secondary: const Color(0xFF8E4E00), + onSecondary: const Color(0xFFFFFFFF), + secondaryContainer: const Color(0xFFFFDCC1), + onSecondaryContainer: const Color(0xFF2E1500), + tertiary: const Color(0xFFCEBDFF), + onTertiary: const Color(0xFF390590), + tertiaryContainer: const Color(0xFF502BA7), + onTertiaryContainer: const Color(0xFFE8DDFF), + error: const Color(0xFFBA1A1A), + onError: const Color(0xFFFFFFFF), + onErrorContainer: const Color(0xFF410002), + errorContainer: const Color(0xFFFFDAD6), + background: const Color(0xFFFEFBFF), + onBackground: const Color(0xFF303034), + onSurface: const Color(0xFF303034), + onSurfaceDisableEmpathy: const Color(0xFFC7C6CA), + onSurfaceMediumEmpathy: const Color(0xFF5E5E62), + onSurfaceLowEmpathy: const Color(0xFF5E5E62), + onSurfaceHighEmpathy: const Color(0xFF303034), + onSurfaceHighEmpathyReverse: const Color(0xFFE3E2E6), + outline: const Color(0xFF1C1B1E).withOpacity(.05), + sport: const Color(0xFF7EDB89), + onSport: const Color(0xFF003912), + sportContainer: const Color(0xFF00531E), + onSportContainer: const Color(0xFF9AF8A2), + game: const Color(0xFFF8ACFF), + onGame: const Color(0xFF570067), + gameContainer: const Color(0xFF7B0091), + onGameContainer: const Color(0xFFFFD6FF), + ava: const Color(0xFFFFB4A8), + onAva: const Color(0xFF690000), + avaContainer: const Color(0xFF930000), + onAvaContainer: const Color(0xFFFFDAD4), + success: const Color(0xFF70CD9B), + warning: const Color(0xFFFFD64F), + info: const Color(0xFF81D5FC), + link: const Color(0xFF8AB4F8), + linkClicked: const Color(0xFFB99BFE), + focus: const Color(0xFFFFFFFF).withOpacity(.12), + pressed: const Color(0xFFFFFFFF).withOpacity(.1), + dargged: const Color(0xFFFFFFFF).withOpacity(.08), + selected: const Color(0xFFFFFFFF).withOpacity(.08), + hover: const Color(0xFFFFFFFF).withOpacity(.04), + onPrimaryHighEmpathy: const Color(0xFFFFFFFF), + onPrimaryLowEmpathy: const Color(0xFF919094), + onPrimaryMediumEmpathy: const Color(0xFFABABAF), + surface: const Color(0xFFFFFDFF), + surface1: const Color(0xFFFEFBFF), + surface2: const Color(0xFFFFFBFE), + surface3: const Color(0xFFFFFBFE), + surface4: const Color(0xFFFFFBFE), + surface5: const Color(0xFFFFFBFE), + background2: const Color(0xFFf2f0f4), + surfaceNeutral: const Color(0xFFFFFDFF), + onSurfaceOverlayLightHigh: const Color(0xFF000000).withOpacity(0.9), + ); +} + +class DarkThemeColors extends PanelColors { + DarkThemeColors() + : super( + onBackground2: const Color(0xffE3E2E6), + additionalLightGreen: const Color(0xff002D0D), + additionalGreen: const Color(0xff70CD9B), + surface6: const Color(0xffCDBDFF).withOpacity(0.05), + lightError: const Color(0xffBA1A1A), + lightWarning: const Color(0xffFFB300), + primary: const Color(0xFFBB86FC), + tuneNeutral: const Color(0xFFE3E2E6), + primary80: const Color(0xFFCDBDFF), + profileItemColor: const Color(0xFFFD9B19), + onPrimary: const Color(0xFF2A0053), + primaryContainer: const Color(0xFF7743B5), + onPrimaryContainer: const Color(0xFFEEDBFF), + secondary: const Color(0xFF4C2700), + onSecondary: const Color(0xFF4C2700), + secondaryContainer: const Color(0xFF6C3A00), + onSecondaryContainer: const Color(0xFF2E1500), + tertiary: const Color(0xFFCEBDFF), + onTertiary: const Color(0xFF390590), + tertiaryContainer: const Color(0xFF502BA7), + onTertiaryContainer: const Color(0xFFE8DDFF), + error: const Color(0xFFFF5449), + onError: const Color(0xFF690005), + onErrorContainer: const Color(0xFFFFDAD6), + errorContainer: const Color(0xFFFFDAD6), + background: const Color(0xFF1B1B1F), + onBackground: const Color(0xFFE3E2E6), + surfaceNeutral: const Color(0xFF1C1B1E), + onSurface: const Color(0xFFE3E2E6), + onSurfaceDisableEmpathy: const Color(0xFFC7C6CA), + onSurfaceMediumEmpathy: const Color(0xFFABABAF), + onSurfaceLowEmpathy: const Color(0xFF919094), + onSurfaceHighEmpathy: const Color(0xFFE3E2E6), + onSurfaceHighEmpathyReverse: const Color(0xFF303034), + outline: const Color(0xFFFFFDFF).withOpacity(.05), + sport: const Color(0xFF7EDB89), + onSport: const Color(0xFF003912), + sportContainer: const Color(0xFF00531E), + onSportContainer: const Color(0xFF9AF8A2), + game: const Color(0xFFF8ACFF), + onGame: const Color(0xFF570067), + gameContainer: const Color(0xFF7B0091), + onGameContainer: const Color(0xFFFFD6FF), + ava: const Color(0xFFFFB4A8), + onAva: const Color(0xFF690000), + avaContainer: const Color(0xFF930000), + onAvaContainer: const Color(0xFFFFDAD4), + success: const Color(0xFF70CD9B), + warning: const Color(0xFFFFD64F), + info: const Color(0xFF81D5FC), + link: const Color(0xFF8AB4F8), + linkClicked: const Color(0xFFB99BFE), + focus: const Color(0xFFFFFFFF).withOpacity(.12), + pressed: const Color(0xFFFFFFFF).withOpacity(.1), + dargged: const Color(0xFFFFFFFF).withOpacity(.08), + selected: const Color(0xFFFFFFFF).withOpacity(.08), + hover: const Color(0xFFFFFFFF).withOpacity(.04), + onPrimaryHighEmpathy: const Color(0xFF2A0053), + onPrimaryLowEmpathy: const Color(0xFF915DD0), + onPrimaryMediumEmpathy: const Color(0xFF5E289B), + surface: const Color(0xFF1C1B1E), + surface1: const Color(0xFF1C1B1E), + surface2: const Color(0xFF1C1B1E), + surface3: const Color(0xFF1C1B1F), + surface4: const Color(0xFF1C1B1E), + surface5: const Color(0xFF1C1B1E), + background2: const Color(0xFF46464a), + onSurfaceOverlayLightHigh: const Color(0xFFE3E2E6), + ); +} diff --git a/lib/core/theme/panel_theme.dart b/lib/core/theme/panel_theme.dart new file mode 100644 index 0000000..ad26e73 --- /dev/null +++ b/lib/core/theme/panel_theme.dart @@ -0,0 +1,17 @@ +import 'package:sonnat/core/theme/panel_colors.dart'; +import 'package:sonnat/core/theme/panel_typography.dart'; + +abstract class PanelTheme { + PanelTheme({required this.colors, required this.typography}); + + final PanelColors colors; + final PanelTypography typography; +} + +class LightTheme extends PanelTheme { + LightTheme() : super(colors: LightThemeColors(), typography: PersianTypo()); +} + +class DarkTheme extends PanelTheme { + DarkTheme() : super(colors: DarkThemeColors(), typography: PersianTypo()); +} diff --git a/lib/core/theme/panel_typography.dart b/lib/core/theme/panel_typography.dart new file mode 100644 index 0000000..33d58d8 --- /dev/null +++ b/lib/core/theme/panel_typography.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; + +abstract class PanelTypography { + PanelTypography({ + required this.heroText1Light, + required this.heroText1Medium, + required this.heroText1DemiBold, + required this.heroText2Light, + required this.heroText2Medium, + required this.heroText2DemiBold, + required this.heroText3Light, + required this.heroText3Medium, + required this.heroText3DemiBold, + required this.titleText1, + required this.titleText2, + required this.titleText3, + required this.titleText4, + required this.titleText5, + required this.bodyText1Light, + required this.bodyText1Regular, + required this.bodyText2Medium, + required this.bodyText2Regular, + required this.bodyText3Medium, + required this.bodyText3Regular, + required this.bodyCaption1Medium, + required this.bodyCaption1Regular, + required this.bodyCaption2Medium, + required this.bodyCaption2Regular, + required this.bodyCaption3, + required this.bottomTextSmall, + required this.bottomTextMedium, + required this.bottomTextLarge, + required this.sourceLink, + required this.sourceLinkSmall, + }); + + final TextStyle heroText1Light; + + final TextStyle heroText1Medium; + + final TextStyle heroText1DemiBold; + final TextStyle heroText2Light; + final TextStyle heroText2Medium; + final TextStyle heroText2DemiBold; + final TextStyle heroText3Light; + final TextStyle heroText3Medium; + final TextStyle heroText3DemiBold; + final TextStyle titleText1; + final TextStyle titleText2; + final TextStyle titleText3; + final TextStyle titleText4; + final TextStyle titleText5; + final TextStyle bodyText1Light; + final TextStyle bodyText1Regular; + final TextStyle bodyText2Regular; + final TextStyle bodyText2Medium; + final TextStyle bodyText3Regular; + final TextStyle bodyText3Medium; + final TextStyle bodyCaption1Regular; + final TextStyle bodyCaption1Medium; + final TextStyle bodyCaption2Regular; + final TextStyle bodyCaption2Medium; + + final TextStyle bodyCaption3; + final TextStyle bottomTextSmall; + final TextStyle bottomTextMedium; + final TextStyle bottomTextLarge; + final TextStyle sourceLink; + final TextStyle sourceLinkSmall; +} + +class PersianTypo extends PanelTypography { + PersianTypo() + : super( + heroText1Light: const TextStyle( + fontSize: 48, + fontWeight: FontWeight.w300, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText1Medium: const TextStyle( + fontSize: 48, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText1DemiBold: const TextStyle( + fontSize: 48, + fontWeight: FontWeight.w600, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText2Light: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.w300, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText2Medium: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText2DemiBold: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.w600, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText3Light: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.w300, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText3Medium: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + heroText3DemiBold: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.w600, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + titleText1: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + titleText2: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + titleText3: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + titleText4: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + titleText5: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText1Light: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w300, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText1Regular: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText2Regular: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText2Medium: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText3Regular: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyText3Medium: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyCaption1Regular: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyCaption1Medium: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyCaption2Regular: const TextStyle( + fontSize: 10, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyCaption2Medium: const TextStyle( + fontSize: 10, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bodyCaption3: const TextStyle( + fontSize: 8, + fontWeight: FontWeight.w500, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bottomTextSmall: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bottomTextMedium: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + bottomTextLarge: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + sourceLink: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + sourceLinkSmall: const TextStyle( + fontSize: 10, + fontWeight: FontWeight.w400, + letterSpacing: 0, + fontFamily: FontFamily.iranSans, + ), + ); +} + +class FontFamily { + static const String iranSans = 'Vazir'; +} diff --git a/lib/core/utils/app_constants.dart b/lib/core/utils/app_constants.dart new file mode 100644 index 0000000..a9256ef --- /dev/null +++ b/lib/core/utils/app_constants.dart @@ -0,0 +1,13 @@ +class AppConstants { + AppConstants.privateConstructor(); + + static final AppConstants instance = AppConstants.privateConstructor(); + + factory AppConstants() { + return instance; + } + + final int pageSize = 20; + final int appHeight = 808; + final int appWidth = 375; +} \ No newline at end of file diff --git a/lib/core/utils/app_utils.dart b/lib/core/utils/app_utils.dart new file mode 100644 index 0000000..7c29437 --- /dev/null +++ b/lib/core/utils/app_utils.dart @@ -0,0 +1,85 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:shamsi_date/shamsi_date.dart'; +import 'package:sonnat/core/language/language_cubit.dart'; +import 'package:sonnat/core/utils/toast.dart'; + +class DisableScrollEffect extends ScrollBehavior { + @override + Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) { + return child; + } +} + +class Utils { + Utils.privateConstructor(); + + static final Utils instance = Utils.privateConstructor(); + + factory Utils() { + return instance; + } + + void showToast(BuildContext? context, String? txt, {bool isError = true, ToastGravity gravity = ToastGravity.top}) { + try { + if (context == null) return; + if (txt == null || txt.isEmpty) { + if (isError == false) { + return; + } + txt = 'خطا در برقراری ارتباط'; + } + FToast fToast = FToast(); + fToast.init(context); + Widget toast = Container( + padding: const EdgeInsetsDirectional.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: isError ? Colors.red : Colors.lightBlue, + ), + child: Text( + txt, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ); + fToast.showToast(child: toast, gravity: gravity, toastDuration: const Duration(milliseconds: 1500)); + } catch (e) { + assert(() { + if (kDebugMode) { + print(e); + } + return true; + }()); + } + } + + String showTimeInJalali(DateTime dateTime) { + Jalali jalali = Jalali.fromDateTime(dateTime); + return '${jalali.year}/${jalali.month}/${jalali.day}'; + } + + ThemeData getAppTheme(BuildContext context, CurrentLanguage language) { + switch (language) { + case CurrentLanguage.en: + return ThemeData( + scaffoldBackgroundColor: const Color(0xffE7E7F5), + useMaterial3: true, + ); + case CurrentLanguage.fa: + return ThemeData( + fontFamily: 'Vazir', + scaffoldBackgroundColor: const Color(0xffE7E7F5), + useMaterial3: true, + ); + case CurrentLanguage.ar: + return ThemeData( + fontFamily: 'Cairo', + useMaterial3: true, + scaffoldBackgroundColor: const Color(0xffE7E7F5), + ); + } + } +} diff --git a/lib/core/utils/base_cubit_type.dart b/lib/core/utils/base_cubit_type.dart new file mode 100644 index 0000000..9872a5f --- /dev/null +++ b/lib/core/utils/base_cubit_type.dart @@ -0,0 +1,6 @@ +class BaseCubitType { + T? eventName; + dynamic data; + + BaseCubitType({this.eventName, this.data}); +} diff --git a/lib/core/utils/debounce.dart b/lib/core/utils/debounce.dart new file mode 100644 index 0000000..0670dff --- /dev/null +++ b/lib/core/utils/debounce.dart @@ -0,0 +1,25 @@ +import 'dart:async'; + +class Debounce { + static final Map _timers = {}; + + static void debounce(String tag, Duration duration, Function onExecute) { + if (duration == Duration.zero) { + _timers[tag]?.cancel(); + _timers.remove(tag); + onExecute(); + } else { + _timers[tag]?.cancel(); + _timers[tag] = Timer(duration, () { + _timers[tag]?.cancel(); + _timers.remove(tag); + onExecute(); + }); + } + } + + static void cancel(String tag) { + _timers[tag]?.cancel(); + _timers.remove(tag); + } +} diff --git a/lib/core/utils/initializer.dart b/lib/core/utils/initializer.dart new file mode 100644 index 0000000..8c3ad64 --- /dev/null +++ b/lib/core/utils/initializer.dart @@ -0,0 +1,38 @@ +import 'dart:ui'; + +import 'package:data/app_setting_data/repository/app_setting_box_repository_impl.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:local_db_core/lib/boxes/box_list/setting_box/app_setting_box.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:repositories/app_setting_box_domain/repository/app_setting_box_repository.dart'; + +class Initializer { + Initializer.privateConstructor(); + + final AppSettingBoxRepository _repository = AppSettingBoxRepositoryImpl(appSettingBox: AppSettingBox()); + static final Initializer instance = Initializer.privateConstructor(); + + factory Initializer() { + return instance; + } + + Future initialHive() async { + final dir = await getApplicationDocumentsDirectory(); + Hive.init(dir.path); + await _repository.openBox(); + } + + TextDirection getTextDirection() { + String? appDirection = _repository.getAppDirection(); + if (appDirection == null || appDirection == 'rtl') return TextDirection.rtl; + return TextDirection.ltr; + } + + String? getAppDirection() { + return _repository.getAppDirection(); + } + + void setAppDirection(String value) { + _repository.setAppDirection(value); + } +} diff --git a/lib/core/utils/metrics.dart b/lib/core/utils/metrics.dart new file mode 100644 index 0000000..0ddd591 --- /dev/null +++ b/lib/core/utils/metrics.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart' show MediaQuery, BuildContext; + +class Metric { + Metric._(); + + static double width(BuildContext context) => MediaQuery.of(context).size.width; + static double height(BuildContext context) => MediaQuery.of(context).size.height; + + static DeviceWidth getScreenWidth(BuildContext context) { + if (width(context) >= 1440) { + return DeviceWidth.lg; + } else if (width(context) >= 976) { + return DeviceWidth.md; + } else if (width(context) >= 576) { + return DeviceWidth.sm; + } else { + return DeviceWidth.xs; + } + } + + static bool isDesktop(BuildContext context) => getScreenWidth(context) == DeviceWidth.lg; + static bool isTablet(BuildContext context) => getScreenWidth(context) == DeviceWidth.md; + static bool isCompact(BuildContext context) => getScreenWidth(context) == DeviceWidth.sm; + static bool isMobile(BuildContext context) => getScreenWidth(context) == DeviceWidth.xs; +} + +enum DeviceWidth { xs, sm, md, lg } diff --git a/lib/core/utils/no_transition_on_web.dart b/lib/core/utils/no_transition_on_web.dart new file mode 100644 index 0000000..a631dd8 --- /dev/null +++ b/lib/core/utils/no_transition_on_web.dart @@ -0,0 +1,18 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class NoTransitionsOnWeb extends PageTransitionsTheme { + @override + Widget buildTransitions(route, context, animation, secondaryAnimation, child) { + if (kIsWeb) { + return child; + } + return super.buildTransitions( + route, + context, + animation, + secondaryAnimation, + child, + ); + } +} diff --git a/lib/core/utils/path_utils.dart b/lib/core/utils/path_utils.dart new file mode 100644 index 0000000..70ee7e8 --- /dev/null +++ b/lib/core/utils/path_utils.dart @@ -0,0 +1,9 @@ +class PathUtils { + PathUtils.privateConstructor(); + + static final PathUtils instance = PathUtils.privateConstructor(); + + factory PathUtils() { + return instance; + } +} diff --git a/lib/core/utils/replace_number_input_formatter.dart b/lib/core/utils/replace_number_input_formatter.dart new file mode 100644 index 0000000..422c506 --- /dev/null +++ b/lib/core/utils/replace_number_input_formatter.dart @@ -0,0 +1,20 @@ +import 'package:flutter/services.dart'; +import 'package:sonnat/core/utils/string_utils.dart'; + +class ReplaceNumberInputFormatter extends TextInputFormatter { + @override + TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { + var text = newValue.text; + String buffer = ''; + if (newValue.selection.baseOffset == 0) { + return newValue; + } + for (int i = 0; i < text.length; i++) { + buffer += StringUtils.uniqueNumbers(text[i]); + } + return newValue.copyWith( + text: buffer, + selection: TextSelection.collapsed(offset: newValue.selection.baseOffset), + ); + } +} diff --git a/lib/core/utils/string_utils.dart b/lib/core/utils/string_utils.dart new file mode 100644 index 0000000..d5e34f6 --- /dev/null +++ b/lib/core/utils/string_utils.dart @@ -0,0 +1,58 @@ +class StringUtils { + static String uniqueNumbers(String str) { + return str + .replaceAll('۰', '0') + .replaceAll('۱', '1') + .replaceAll('۲', '2') + .replaceAll('۳', '3') + .replaceAll('۴', '4') + .replaceAll('۵', '5') + .replaceAll('۶', '6') + .replaceAll('۷', '7') + .replaceAll('۸', '8') + .replaceAll('۹', '9') + .replaceAll('٠', '0') + .replaceAll('١', '1') + .replaceAll('٢', '2') + .replaceAll('٣', '3') + .replaceAll('٤', '4') + .replaceAll('٥', '5') + .replaceAll('٦', '6') + .replaceAll('٧', '7') + .replaceAll('٨', '8') + .replaceAll('٩', '9'); + } + + static String uniqueLetters(String str) { + return str + .replaceAll('ﮎ', 'ک') + .replaceAll('ﮏ', 'ک') + .replaceAll('ﮐ', 'ک') + .replaceAll('ﮑ', 'ک') + .replaceAll('ك', 'ک') + .replaceAll('ي', 'ی') + // .replaceAll("ئ", "ی") + .replaceAll('یٰ', 'ی') + .replaceAll(' ّ', ' ') + .replaceAll(' ٌ', '') + .replaceAll(' ٍ', '') + .replaceAll(' ً', '') + .replaceAll(' ُ', '') + .replaceAll(' ِ', '') + .replaceAll(' ', ' ') + .replaceAll('ـ', '_') + .replaceAll('ؤ', 'و') + .replaceAll('إ', 'ا') + .replaceAll('ٱ', 'ا') + .replaceAll('أ', 'ا') + .replaceAll('ھ', 'ه') + .replaceAll('ۀ', 'ه') + .replaceAll('هٔ', 'ه') + .replaceAll('ه‍', 'ه') + .replaceAll('ة', 'ه'); + } + + static String uniqueString(String str) { + return StringUtils.uniqueNumbers(StringUtils.uniqueLetters(str)); + } +} diff --git a/lib/core/utils/toast.dart b/lib/core/utils/toast.dart new file mode 100644 index 0000000..04d913a --- /dev/null +++ b/lib/core/utils/toast.dart @@ -0,0 +1,196 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +enum Toast { + short, + long, +} + +enum ToastGravity { + top, + bottom, + center, + topLeft, + topRight, + bottomLeft, + bottomRight, + centerLEft, + centerRight, + snackBar, +} + +typedef PositionedToastBuilder = Widget Function(BuildContext context, Widget child); + +class FToast { + late BuildContext context; + + static final FToast _instance = FToast._internal(); + + factory FToast() { + return _instance; + } + + FToast init(BuildContext context) { + _instance.context = context; + return _instance; + } + + FToast._internal(); + + OverlayEntry? _entry; + final List<_ToastEntry> _overlayQueue = []; + Timer? _timer; + + void _showOverlay() { + if (_overlayQueue.isEmpty) { + _entry = null; + return; + } + _ToastEntry toastEntry = _overlayQueue.removeAt(0); + _entry = toastEntry.entry; + Overlay.of(context).insert(_entry!); + + _timer = Timer(toastEntry.duration, () { + Future.delayed(const Duration(milliseconds: 360), () { + removeCustomToast(); + }); + }); + } + + void removeCustomToast() { + _timer!.cancel(); + _timer = null; + if (_entry != null) _entry!.remove(); + _entry = null; + _showOverlay(); + } + + void removeQueuedCustomToasts() { + _timer?.cancel(); + _timer = null; + _overlayQueue.clear(); + if (_entry != null) _entry!.remove(); + _entry = null; + } + + void showToast({ + required Widget child, + PositionedToastBuilder? positionedToastBuilder, + required Duration? toastDuration, + required ToastGravity gravity, + int fadeDuration = 350, + }) { + Widget newChild = _ToastStateFul(child, toastDuration ?? const Duration(seconds: 2), fadeDuration: fadeDuration); + if (gravity == ToastGravity.bottom) { + if (MediaQuery.of(context).viewInsets.bottom != 0) { + gravity = ToastGravity.center; + } + } + OverlayEntry newEntry = OverlayEntry(builder: (context) { + if (positionedToastBuilder != null) return positionedToastBuilder(context, newChild); + return _getPositionWidgetBasedOnGravity(newChild, gravity); + }); + + _overlayQueue.add(_ToastEntry(entry: newEntry, duration: toastDuration ?? const Duration(seconds: 2))); + if (_timer == null) _showOverlay(); + } + + Positioned _getPositionWidgetBasedOnGravity(Widget child, ToastGravity gravity) { + switch (gravity) { + case ToastGravity.top: + return Positioned(top: 100.0, left: 24.0, right: 24.0, child: child); + case ToastGravity.topLeft: + return Positioned(top: 100.0, left: 24.0, child: child); + case ToastGravity.topRight: + return Positioned(top: 100.0, right: 24.0, child: child); + case ToastGravity.center: + return Positioned(top: 50.0, bottom: 50.0, left: 24.0, right: 24.0, child: child); + case ToastGravity.centerLEft: + return Positioned(top: 50.0, bottom: 50.0, left: 24.0, child: child); + case ToastGravity.centerRight: + return Positioned(top: 50.0, bottom: 50.0, right: 24.0, child: child); + case ToastGravity.bottomLeft: + return Positioned(bottom: 50.0, left: 24.0, child: child); + case ToastGravity.bottomRight: + return Positioned(bottom: 50.0, right: 24.0, child: child); + case ToastGravity.snackBar: + return Positioned(bottom: MediaQuery.of(context).viewInsets.bottom, left: 0, right: 0, child: child); + case ToastGravity.bottom: + default: + return Positioned(bottom: 50.0, left: 24.0, right: 24.0, child: child); + } + } +} + +class _ToastEntry { + final OverlayEntry entry; + final Duration duration; + + _ToastEntry({required this.entry, required this.duration}); +} + +class _ToastStateFul extends StatefulWidget { + const _ToastStateFul(this.child, this.duration, {this.fadeDuration = 350}); + + final Widget child; + final Duration duration; + final int fadeDuration; + + @override + ToastStateFulState createState() => ToastStateFulState(); +} + +class ToastStateFulState extends State<_ToastStateFul> with SingleTickerProviderStateMixin { + void showIt() { + _animationController.forward(); + } + + void hideIt() { + _animationController.reverse(); + _timer.cancel(); + } + + late AnimationController _animationController; + late Animation _fadeAnimation; + late Timer _timer; + + @override + void initState() { + _animationController = AnimationController( + vsync: this, + duration: Duration(milliseconds: widget.fadeDuration), + ); + _fadeAnimation = CurvedAnimation(parent: _animationController, curve: Curves.easeIn); + super.initState(); + showIt(); + _timer = Timer(widget.duration, hideIt); + } + + @override + void deactivate() { + _timer.cancel(); + _animationController.stop(); + super.deactivate(); + } + + @override + void dispose() { + _timer.cancel(); + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return FadeTransition( + opacity: _fadeAnimation as Animation, + child: Center( + child: Material( + color: Colors.transparent, + child: widget.child, + ), + ), + ); + } +} diff --git a/lib/features/aabout_us/about_us_screen.dart b/lib/features/aabout_us/about_us_screen.dart new file mode 100644 index 0000000..3cb5961 --- /dev/null +++ b/lib/features/aabout_us/about_us_screen.dart @@ -0,0 +1,185 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.dart'; +import 'package:sonnat/core/language/translator.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class AboutUsScreen extends StatefulWidget { + const AboutUsScreen({super.key}); + + @override + State createState() => _AboutUsScreenState(); +} + +class _AboutUsScreenState extends State { + final TextEditingController _controller = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: EdgeInsets.symmetric(horizontal: context.width * 25 / AppConstants.instance.appWidth), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: context.height * 33 / AppConstants.instance.appHeight), + Row( + children: [ + const Spacer(), + Text( + Translator.translate('more_about_us'), + style: const TextStyle( + color: Color(0xff222D4E), + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + 'ic_back'.svgPath, + ), + ), + ], + ), + SizedBox(height: context.height * 54 / AppConstants.instance.appHeight), + Text( + Translator.translate('main_target'), + style: const TextStyle(color: Color(0xff178756), fontSize: 16), + ), + SizedBox(height: context.height * 11 / AppConstants.instance.appHeight), + SingleChildScrollView( + child: FutureBuilder( + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text( + snapshot.data as String, + textDirection: TextDirection.rtl, + style: const TextStyle( + color: Color(0xff636E88), + fontSize: 13, + ), + textAlign: TextAlign.justify, + ); + } + return const CircularProgressIndicator(); + }, + future: rootBundle.loadString('assets/meta/about_us.txt'), + ), + ), + SizedBox(height: context.height * 20 / AppConstants.instance.appHeight), + Text( + Translator.translate('contact_to_us'), + style: const TextStyle(color: Color(0xff178756), fontSize: 16), + ), + SizedBox(height: context.height * 24 / AppConstants.instance.appHeight), + Row( + children: [ + GestureDetector( + onTap: _openInstagram, + child: Row( + children: [ + const Text( + 'Sonnat_islam', + style: TextStyle(color: Color(0xff404966), fontSize: 13), + ), + SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), + SvgPicture.asset('ic_instagram'.svgPath), + ], + ), + ), + const Spacer(), + GestureDetector( + onTap: _openPhone, + child: Row( + children: [ + const Text( + '+98 92300264', + textDirection: TextDirection.ltr, + style: TextStyle(color: Color(0xff404966), fontSize: 13), + ), + SizedBox(width: context.width * 15 / AppConstants.instance.appWidth), + SvgPicture.asset('ic_phone'.svgPath), + ], + ), + ), + ], + ), + SizedBox(height: context.height * 29 / AppConstants.instance.appHeight), + Text( + Translator.translate('send_message_to_us'), + style: const TextStyle(color: Color(0xff404966), fontSize: 12), + ), + SizedBox(height: context.height * 12 / AppConstants.instance.appHeight), + TextFormField( + autofocus: true, + maxLength: 300, + controller: _controller, + maxLines: 10, + minLines: 4, + style: const TextStyle( + color: Color(0xff8D95AB), + fontSize: 10, + ), + decoration: InputDecoration( + fillColor: Colors.transparent, + hintText: Translator.translate('send_message'), + filled: true, + counterText: '', + hintStyle: const TextStyle( + color: Color(0xff8D95AB), + fontSize: 10, + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide(color: Color(0xff636E88)), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Color(0xff636E88), + ), + ), + ), + ), + SizedBox(height: context.height * 9 / AppConstants.instance.appHeight), + Container( + decoration: BoxDecoration( + color: const Color(0xff178756), + borderRadius: BorderRadius.circular(12), + ), + padding: EdgeInsets.symmetric( + horizontal: context.width * 20 / AppConstants.instance.appWidth, + vertical: context.height * 10 / AppConstants.instance.appHeight, + ), + child: Text( + Translator.translate('send'), + style: const TextStyle(color: Color(0xffffffff), fontSize: 12), + ), + ), + ], + ), + ), + ); + } + + Future _openInstagram() async { + var url = 'https://www.instagram.com//'; + if (await canLaunchUrl(Uri.parse(url))) { + await launchUrl(Uri.parse(url)); + } else { + throw 'There was a problem to open the url: $url'; + } + } + + // ignore: avoid_void_async + void _openPhone() async { + await launchUrl(Uri.parse('tel://+98 92300264')); + } +} diff --git a/lib/features/main/main_screen.dart b/lib/features/main/main_screen.dart new file mode 100644 index 0000000..5a69f7f --- /dev/null +++ b/lib/features/main/main_screen.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.dart'; +import 'package:sonnat/core/language/translator.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; +import 'package:sonnat/features/aabout_us/about_us_screen.dart'; +import 'package:sonnat/features/main/widget/main_item_widget.dart'; +import 'package:sonnat/features/posts/screen/posts_screen.dart'; + +class MainScreen extends StatefulWidget { + const MainScreen({super.key}); + + @override + State createState() => _MainScreenState(); +} + +class _MainScreenState extends State { + final List _icons = [ + 'ic_mataen', + 'ic_shobahat', + 'ic_aqayed', + 'ic_vijeha', + 'ic_akhbar', + 'ic_video', + ]; + final List _names = [ + Translator.translate('forbidden'), + Translator.translate('doubts'), + Translator.translate('criticism_of_ideas'), + Translator.translate('specials'), + Translator.translate('news'), + Translator.translate('video'), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xff26237A), + body: Column( + children: [ + Container( + margin: EdgeInsets.only( + top: context.height * 27 / AppConstants.instance.appHeight, + left: context.width * 86 / AppConstants.instance.appWidth, + right: context.width * 86 / AppConstants.instance.appWidth, + ), + child: Image.asset('ic_main_header'.pngPath), + ), + Text( + Translator.translate('main_header_text'), + style: const TextStyle( + color: Color(0xffFFD800), + fontSize: 28, + ), + ), + SizedBox(height: context.height * 5 / AppConstants.instance.appHeight), + Text( + Translator.translate('second_header_text'), + style: const TextStyle( + color: Color(0xffDEDEDE), + fontSize: 16, + ), + ), + Container( + decoration: BoxDecoration( + color: const Color(0xffF4F4F8), + borderRadius: BorderRadius.circular(22), + ), + margin: EdgeInsets.only( + left: context.width * 35 / AppConstants.instance.appWidth, + right: context.width * 35 / AppConstants.instance.appWidth, + top: context.height * 40 / AppConstants.instance.appHeight, + bottom: context.height * 90 / AppConstants.instance.appHeight, + ), + padding: EdgeInsets.symmetric( + vertical: context.height * 13 / AppConstants.instance.appHeight, + horizontal: context.width * 8 / AppConstants.instance.appWidth, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + Translator.translate('search_term'), + style: const TextStyle( + color: Color(0xffBCC1CD), + fontSize: 16, + ), + ), + SizedBox(width: context.width * 14 / AppConstants.instance.appWidth), + SvgPicture.asset('ic_search'.svgPath), + ], + ), + ), + SvgPicture.asset('ic_line'.svgPath), + SizedBox(height: context.height * 70 / AppConstants.instance.appHeight), + Padding( + padding: EdgeInsets.symmetric(horizontal: context.width * 35 / AppConstants.instance.appWidth), + child: Row( + children: [ + GestureDetector( + child: MainItemWidget(icon: _icons[2], name: _names[2]), + onTap: () => _openItem(index: 2), + ), + SizedBox(width: context.width * 13 / AppConstants.instance.appWidth), + GestureDetector( + child: MainItemWidget(icon: _icons[1], name: _names[1]), + onTap: () => _openItem(index: 1), + ), + SizedBox(width: context.width * 13 / AppConstants.instance.appWidth), + GestureDetector( + child: MainItemWidget(icon: _icons[0], name: _names[0]), + onTap: () => _openItem(index: 0), + ), + ], + ), + ), + SizedBox(height: context.height * 15 / AppConstants.instance.appHeight), + Padding( + padding: EdgeInsets.symmetric(horizontal: context.width * 35 / AppConstants.instance.appWidth), + child: Row( + children: [ + GestureDetector( + child: MainItemWidget(icon: _icons[5], name: _names[5]), + onTap: () => _openItem(index: 5), + ), + SizedBox(width: context.width * 13 / AppConstants.instance.appWidth), + GestureDetector( + child: MainItemWidget(icon: _icons[4], name: _names[4]), + onTap: () => _openItem(index: 4), + ), + SizedBox(width: context.width * 13 / AppConstants.instance.appWidth), + GestureDetector( + child: MainItemWidget(icon: _icons[3], name: _names[3]), + onTap: () => _openItem(index: 3), + ), + ], + ), + ), + SizedBox(height: context.height * 40 / AppConstants.instance.appHeight), + ], + ), + ); + } + + void _openItem({required int index}) { + switch (index) { + case 0: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return PostsScreen(title: _names[index]); + }, + )); + break; + case 1: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return PostsScreen(title: _names[index]); + }, + )); + break; + case 2: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return PostsScreen(title: _names[index]); + }, + )); + break; + case 3: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return PostsScreen(title: _names[index]); + }, + )); + break; + case 4: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return PostsScreen(title: _names[index]); + }, + )); + break; + case 5: + Navigator.push(context, MaterialPageRoute( + builder: (context) { + return const AboutUsScreen(); + }, + )); + break; + } + } +} diff --git a/lib/features/main/widget/main_item_widget.dart b/lib/features/main/widget/main_item_widget.dart new file mode 100644 index 0000000..0b0e907 --- /dev/null +++ b/lib/features/main/widget/main_item_widget.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; + +class MainItemWidget extends StatelessWidget { + final String icon; + final String name; + + const MainItemWidget({super.key, required this.icon, required this.name}); + + @override + Widget build(BuildContext context) { + return Container( + width: context.width * 93 / AppConstants.instance.appWidth, + height: context.height * 95 / AppConstants.instance.appHeight, + decoration: BoxDecoration( + color: const Color(0xff3733A1), + borderRadius: BorderRadius.circular(22), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(icon.svgPath), + SizedBox(height: context.height * 8 / AppConstants.instance.appHeight), + Text( + name, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/posts/screen/posts_screen.dart b/lib/features/posts/screen/posts_screen.dart new file mode 100644 index 0000000..802c243 --- /dev/null +++ b/lib/features/posts/screen/posts_screen.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/extensions/string_extension.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; +import 'package:sonnat/features/posts/widgets/filter_item_widget.dart'; +import 'package:sonnat/features/posts/widgets/post_item_widget.dart'; + +class PostsScreen extends StatefulWidget { + final String title; + + const PostsScreen({super.key, required this.title}); + + @override + State createState() => _PostsScreenState(); +} + +class _PostsScreenState extends State { + final List _filterList = [ + const FilterItem(selected: false, title: 'پر تکرارترین‌ها'), + const FilterItem(selected: true, title: 'مشابه‌ها'), + const FilterItem(selected: false, title: 'محبوبترین‌ها'), + const FilterItem(selected: false, title: 'برای‌ شما'), + const FilterItem(selected: false, title: 'محبوبترین‌ها'), + const FilterItem(selected: false, title: 'پر تکرارترین‌ها'), + const FilterItem(selected: true, title: 'مشابه‌ها'), + const FilterItem(selected: false, title: 'محبوبترین‌ها'), + const FilterItem(selected: false, title: 'برای‌ شما'), + const FilterItem(selected: false, title: 'محبوبترین‌ها'), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + SizedBox(height: context.height * 26 / AppConstants.instance.appHeight), + Padding( + padding: EdgeInsets.symmetric(horizontal: context.width * 26 / AppConstants.instance.appWidth), + child: Row( + children: [ + GestureDetector( + onTap: () {}, + child: SvgPicture.asset( + 'ic_more'.svgPath, + ), + ), + SizedBox(width: context.width * 8 / AppConstants.instance.appWidth), + GestureDetector( + onTap: () {}, + child: SvgPicture.asset( + 'ic_rounded_search'.svgPath, + ), + ), + const Spacer(), + Text( + widget.title, + style: const TextStyle( + color: Color(0xff404966), + fontSize: 22, + ), + ), + const Spacer(), + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: SvgPicture.asset( + 'ic_back'.svgPath, + ), + ), + ], + ), + ), + SizedBox(height: context.height * 35 / AppConstants.instance.appHeight), + SizedBox( + height: context.height * 31 / AppConstants.instance.appHeight, + child: ListView.builder( + padding: EdgeInsetsDirectional.only(start: context.width * 26 / AppConstants.instance.appWidth), + itemBuilder: (context, index) { + return FilterItemWidget(title: _filterList[index].title, selected: _filterList[index].selected); + }, + itemCount: _filterList.length, + scrollDirection: Axis.horizontal, + ), + ), + SizedBox(height: context.height * 26 / AppConstants.instance.appHeight), + Expanded( + child: ListView.builder( + itemBuilder: (context, index) { + return const PostItemWidget(); + }, + itemCount: 10, + ), + ) + ], + ), + ); + } +} + +class FilterItem { + final bool selected; + final String title; + + const FilterItem({required this.selected, required this.title}); +} diff --git a/lib/features/posts/widgets/filter_item_widget.dart b/lib/features/posts/widgets/filter_item_widget.dart new file mode 100644 index 0000000..922c53c --- /dev/null +++ b/lib/features/posts/widgets/filter_item_widget.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; + +class FilterItemWidget extends StatelessWidget { + final bool selected; + final String title; + + const FilterItemWidget({ + super.key, + this.selected = false, + required this.title, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + left: context.width * 9 / AppConstants.instance.appWidth, + right: context.width * 9 / AppConstants.instance.appWidth, + top: context.height * 5 / AppConstants.instance.appHeight, + bottom: context.height * 10 / AppConstants.instance.appHeight, + ), + margin: EdgeInsetsDirectional.only(end: context.width * 4 / AppConstants.instance.appWidth), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(22), + color: selected ? const Color(0xff26237A) : const Color(0xffffffff), + ), + child: Text( + title, + style: TextStyle( + color: selected ? const Color(0xffffffff) : const Color(0xff636E88), + fontSize: 12, + ), + ), + ); + } +} diff --git a/lib/features/posts/widgets/post_item_widget.dart b/lib/features/posts/widgets/post_item_widget.dart new file mode 100644 index 0000000..a7a0692 --- /dev/null +++ b/lib/features/posts/widgets/post_item_widget.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:sonnat/core/extensions/context_extension.dart'; +import 'package:sonnat/core/utils/app_constants.dart'; + +class PostItemWidget extends StatelessWidget { + const PostItemWidget({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + horizontal: context.width * 11 / AppConstants.instance.appWidth, + vertical: context.width * 11 / AppConstants.instance.appWidth, + ), + decoration: BoxDecoration( + color: const Color(0xffffffff), + borderRadius: BorderRadius.circular(16), + ), + margin: EdgeInsets.only( + left: context.width * 26 / AppConstants.instance.appWidth, + right: context.width * 26 / AppConstants.instance.appWidth, + bottom: context.height * 21 / AppConstants.instance.appHeight, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: context.height * 174 / AppConstants.instance.appHeight, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + color: Colors.red, + ), + ), + SizedBox(height: context.height * 14 / AppConstants.instance.appHeight), + const Text( + 'عدم بیعت صحابه با ابوبکر+سند', + style: TextStyle( + color: Color(0xff222D4E), + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: context.height * 8 / AppConstants.instance.appHeight), + const Text( + 'سعد بن عباده انصار که از صحابه به شمار می آید هرگز با ابوبکر بیعت نکرد ، یعنی او را به خلافت قبول نداشت (1) چرا کسانی را که خلافت ابوبکر را قبول ندارند و پیرو سعد بن عباده می باشند ، هدایت یافته نمی دانید ', + style: TextStyle( + color: Color(0xff8990A1), + fontSize: 13, + ), + textAlign: TextAlign.justify, + ), + SizedBox(height: context.height * 30 / AppConstants.instance.appHeight), + const Align( + alignment: AlignmentDirectional.centerEnd, + child: Text( + '1404/12/25', + style: TextStyle( + color: Color(0xff8D95AB), + fontSize: 11, + fontWeight: FontWeight.bold, + ), + ), + ), + SizedBox(height: context.height * 7 / AppConstants.instance.appHeight), + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..efe0e54 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,121 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:sonnat/core/language/language_cubit.dart'; +import 'package:sonnat/core/language/translator.dart'; +import 'package:sonnat/core/theme/cubit/theme_cubit.dart'; +import 'package:sonnat/core/utils/app_utils.dart'; +import 'package:sonnat/core/utils/base_cubit_type.dart'; +import 'package:sonnat/core/utils/initializer.dart'; +import 'package:sonnat/features/main/main_screen.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Initializer.instance.initialHive(); + if (!kDebugMode) { + await runZonedGuarded>(() async { + runApp(const MyApp()); + }, (error, stackTrace) async {}); + } else { + runApp(const MyApp()); + } +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); + return MultiBlocProvider( + providers: [ + BlocProvider(create: (context) => LanguageCubit()), + BlocProvider(create: (context) => ThemeCubit()), + ], + child: const MyHomePage(), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + @override + Widget build(BuildContext context) { + return BlocBuilder>( + builder: (context, state) { + if (state.eventName == LanguageState.loaded) { + Initializer.instance.setAppDirection( + state.data == CurrentLanguage.fa || state.data == CurrentLanguage.ar ? 'rtl' : 'ltr', + ); + return MaterialApp( + builder: (context, child) { + Widget error = const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'خطا در نمابش اطلاعات', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w700, + fontSize: 18, + ), + textAlign: TextAlign.center, + ), + ], + ), + ); + if (child is Scaffold || child is Navigator) { + error = Scaffold( + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + error, + const Icon( + Icons.error_outline_rounded, + size: 130, + color: Colors.red, + ), + ], + ), + ), + ); + } + ErrorWidget.builder = (errorDetails) => error; + return ScrollConfiguration( + behavior: DisableScrollEffect().copyWith(scrollbars: false), + child: Directionality( + textDirection: Initializer.instance.getTextDirection(), + child: child!, + ), + ); + }, + theme: Utils.instance.getAppTheme(context, state.data), + debugShowCheckedModeBanner: false, + supportedLocales: Translator.supportedLocales(), + initialRoute: '/', + routes: { + '/': (context) => const MainScreen(), + }, + ); + } + return MaterialApp( + debugShowCheckedModeBanner: false, + builder: (context, child) { + return Container(color: Colors.white); + }, + ); + }, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..9a076c2 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,591 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" + args: + dependency: transitive + description: + name: args + sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + url: "https://pub.dev" + source: hosted + version: "2.4.1" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + bloc: + dependency: transitive + description: + name: bloc + sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80" + url: "https://pub.dev" + source: hosted + version: "8.1.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" + source: hosted + version: "0.3.5" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + data: + dependency: "direct main" + description: + path: "data/data_types/data" + relative: true + source: path + version: "0.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775" + url: "https://pub.dev" + source: hosted + version: "8.1.2" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: a9de6706cd844668beac27c0aed5910fa0534832b3c2cad61a5fd977fce82a5d + url: "https://pub.dev" + source: hosted + version: "0.10.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f + url: "https://pub.dev" + source: hosted + version: "2.0.5" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: transitive + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" + image: + dependency: transitive + description: + name: image + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" + source: hosted + version: "3.3.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + lints: + dependency: transitive + description: + name: lints + sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + local_db_core: + dependency: "direct main" + description: + path: "data/data_core/local_db/local_db_core" + relative: true + source: path + version: "1.0.0+1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + url: "https://pub.dev" + source: hosted + version: "2.0.27" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + url: "https://pub.dev" + source: hosted + version: "2.1.10" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + provider: + dependency: transitive + description: + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" + source: hosted + version: "6.0.5" + repositories: + dependency: "direct main" + description: + path: "domain/repositories" + relative: true + source: path + version: "0.0.1" + shamsi_date: + dependency: "direct main" + description: + name: shamsi_date + sha256: "938bd68e6f99fab7f93c04a0fc4248a09355f67eca90510f0ee7579f6014b56c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + url: "https://pub.dev" + source: hosted + version: "6.1.11" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "7aac14be5f4731b923cc697ae2d42043945076cd0dbb8806baecc92c1dc88891" + url: "https://pub.dev" + source: hosted + version: "6.0.33" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + url: "https://pub.dev" + source: hosted + version: "2.0.16" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "59a230f8bf37dd8b077335d1d64d895bccef0fb14f50730e3d79e8990bf3ed2b" + url: "https://pub.dev" + source: hosted + version: "1.1.5+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "40781fe91c6d10a617c0289f7ec16cdb2d85a7f3654af2778c6d0adbf3bf45a3" + url: "https://pub.dev" + source: hosted + version: "1.1.5+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "6ca1298b70edcc3486fdb14032f1a186a593f1b5f6b5e82fb10febddcb1c61bb" + url: "https://pub.dev" + source: hosted + version: "1.1.5+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + win32: + dependency: transitive + description: + name: win32 + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + url: "https://pub.dev" + source: hosted + version: "4.1.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.0-417 <4.0.0" + flutter: ">=3.7.0-0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..ce0bf5e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,57 @@ +name: sonnat +description: A new Flutter project. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev +version: 1.0.0+1 + +environment: + sdk: '>=2.19.6 <3.0.0' +dependencies: + flutter: + sdk: flutter + flutter_svg: ^2.0.5 + path_provider: ^2.0.11 + cupertino_icons: ^1.0.2 + flutter_bloc: ^8.1.1 + shamsi_date: ^1.0.1 + url_launcher: ^6.1.11 + local_db_core: + path: data/data_core/local_db/local_db_core + repositories: + path: domain/repositories + data: + path: data/data_types/data + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + flutter_launcher_icons: ^0.10.0 +flutter: + uses-material-design: true + assets: + - assets/images/ + - assets/languages/ + - assets/images/png/ + - assets/images/svg/ + - assets/meta/ + - assets/fonts/arabi/ + - assets/fonts/farsi/ + fonts: + - family: Vazir + fonts: + - asset: assets/fonts/farsi/Vazir-Black-FD.ttf + - asset: assets/fonts/farsi/Vazir-Bold-FD.ttf + - asset: assets/fonts/farsi/Vazir-Light-FD.ttf + - asset: assets/fonts/farsi/Vazir-Medium-FD.ttf + - asset: assets/fonts/farsi/Vazir-Regular-FD.ttf + - asset: assets/fonts/farsi/Vazir-Thin-FD.ttf + - family: Cairo + fonts: + - asset: assets/fonts/arabi/Cairo-Black.ttf + - asset: assets/fonts/arabi/Cairo-Bold.ttf + - asset: assets/fonts/arabi/Cairo-ExtraBold.ttf + - asset: assets/fonts/arabi/Cairo-ExtraLight.ttf + - asset: assets/fonts/arabi/Cairo-Light.ttf + - asset: assets/fonts/arabi/Cairo-Medium.ttf + - asset: assets/fonts/arabi/Cairo-Regular.ttf + - asset: assets/fonts/arabi/Cairo-SemiBold.ttf \ No newline at end of file