diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 34e5ed5..08c9397 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,7 @@
-cache:
- paths:
+cache:
+ paths:
- build/web
+
stages:
- build
- push
@@ -11,9 +12,10 @@ build:
image: cirrusci/flutter:latest
script:
- flutter clean
- - flutter build web --web-renderer canvaskit
+ - flutter build web --web-renderer html
only:
- test
+ - dev
push:
stage: push
@@ -26,8 +28,9 @@ push:
- docker push registry.gitlab.com/didvan/didvan-app/api:latest
only:
- test
+ - dev
-deploy:
+deploy-test:
stage: deploy
image: python:3.10.2
variables:
@@ -35,6 +38,18 @@ deploy:
script:
- pip install fandogh_cli --upgrade
- fandogh login --username=$FAN_USR --password=$FAN_PASS
- - fandogh service apply -f ./deployment/config.yaml -p SEC_NAME
+ - fandogh service apply -f ./deployment/test.yaml -p SEC_NAME
only:
- test
+
+deploy-dev:
+ stage: deploy
+ image: python:3.10.2
+ variables:
+ COLLECT_ERROR: 1
+ script:
+ - pip install fandogh_cli --upgrade
+ - fandogh login --username=$FAN_USR --password=$FAN_PASS
+ - fandogh service apply -f ./deployment/dev.yaml -p SEC_NAME
+ only:
+ - dev
\ No newline at end of file
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 21ce8ff..293ad3a 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -22,7 +22,6 @@ if (flutterVersionName == null) {
}
apply plugin: 'com.android.application'
-apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@@ -66,7 +65,5 @@ flutter {
}
dependencies {
- implementation platform('com.google.firebase:firebase-bom:29.0.4')
- implementation 'com.google.firebase:firebase-analytics'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
diff --git a/android/app/google-services.json b/android/app/google-services.json
deleted file mode 100644
index 5cb370e..0000000
--- a/android/app/google-services.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "project_info": {
- "project_number": "935017686266",
- "project_id": "didvan-9b7da",
- "storage_bucket": "didvan-9b7da.appspot.com"
- },
- "client": [
- {
- "client_info": {
- "mobilesdk_app_id": "1:935017686266:android:f9cbc9aba8e3d65ed2d543",
- "android_client_info": {
- "package_name": "com.didvan.didvanapp"
- }
- },
- "oauth_client": [
- {
- "client_id": "935017686266-lebnol7rb05oi9h0mripb41c892d2gij.apps.googleusercontent.com",
- "client_type": 3
- }
- ],
- "api_key": [
- {
- "current_key": "AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw"
- }
- ],
- "services": {
- "appinvite_service": {
- "other_platform_oauth_client": [
- {
- "client_id": "935017686266-lebnol7rb05oi9h0mripb41c892d2gij.apps.googleusercontent.com",
- "client_type": 3
- }
- ]
- }
- }
- }
- ],
- "configuration_version": "1"
-}
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index aadf776..34d2e7f 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -5,8 +5,10 @@
+ android:icon="@mipmap/ic_launcher"
+ android:usesCleartextTraffic="true">
+
+
-
diff --git a/android/build.gradle b/android/build.gradle
index 1607692..09fbd64 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,12 +1,11 @@
buildscript {
- ext.kotlin_version = '1.3.50'
+ ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
- classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58a..cc5527d 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/deployment/dev.yaml b/deployment/dev.yaml
new file mode 100644
index 0000000..6738cdd
--- /dev/null
+++ b/deployment/dev.yaml
@@ -0,0 +1,14 @@
+kind: ExternalService
+name: app-dev
+spec:
+ allow_http: false
+ disable_default_domains: true
+ image: registry.gitlab.com/didvan/didvan-app/api:latest
+ image_pull_policy: Always
+ image_pull_secret: $SEC_NAME
+ path: /
+ replicas: 1
+ resources:
+ memory: 100Mi
+ domains:
+ - name: dev.didvan.app
\ No newline at end of file
diff --git a/deployment/config.yaml b/deployment/test.yaml
similarity index 100%
rename from deployment/config.yaml
rename to deployment/test.yaml
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
index 592ceee..ec97fc6 100644
--- a/ios/Flutter/Debug.xcconfig
+++ b/ios/Flutter/Debug.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
index 592ceee..c4855bf 100644
--- a/ios/Flutter/Release.xcconfig
+++ b/ios/Flutter/Release.xcconfig
@@ -1 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..252d9ec
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,41 @@
+# Uncomment this line to define a global platform for your project
+platform :ios, '9.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ end
+end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
new file mode 100644
index 0000000..402e2e1
--- /dev/null
+++ b/ios/Podfile.lock
@@ -0,0 +1,89 @@
+PODS:
+ - audio_session (0.0.1):
+ - Flutter
+ - Flutter (1.0.0)
+ - flutter_secure_storage (3.3.1):
+ - Flutter
+ - flutter_vibrate (0.0.1):
+ - Flutter
+ - FMDB (2.7.5):
+ - FMDB/standard (= 2.7.5)
+ - FMDB/standard (2.7.5)
+ - image_cropper (0.0.4):
+ - Flutter
+ - TOCropViewController (~> 2.6.1)
+ - image_picker (0.0.1):
+ - Flutter
+ - just_audio (0.0.1):
+ - Flutter
+ - path_provider_ios (0.0.1):
+ - Flutter
+ - record (0.0.1):
+ - Flutter
+ - sqflite (0.0.2):
+ - Flutter
+ - FMDB (>= 2.7.5)
+ - TOCropViewController (2.6.1)
+ - url_launcher_ios (0.0.1):
+ - Flutter
+
+DEPENDENCIES:
+ - audio_session (from `.symlinks/plugins/audio_session/ios`)
+ - Flutter (from `Flutter`)
+ - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
+ - image_cropper (from `.symlinks/plugins/image_cropper/ios`)
+ - image_picker (from `.symlinks/plugins/image_picker/ios`)
+ - just_audio (from `.symlinks/plugins/just_audio/ios`)
+ - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
+ - record (from `.symlinks/plugins/record/ios`)
+ - sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+
+SPEC REPOS:
+ trunk:
+ - FMDB
+ - TOCropViewController
+
+EXTERNAL SOURCES:
+ audio_session:
+ :path: ".symlinks/plugins/audio_session/ios"
+ Flutter:
+ :path: Flutter
+ flutter_secure_storage:
+ :path: ".symlinks/plugins/flutter_secure_storage/ios"
+ flutter_vibrate:
+ :path: ".symlinks/plugins/flutter_vibrate/ios"
+ image_cropper:
+ :path: ".symlinks/plugins/image_cropper/ios"
+ image_picker:
+ :path: ".symlinks/plugins/image_picker/ios"
+ just_audio:
+ :path: ".symlinks/plugins/just_audio/ios"
+ path_provider_ios:
+ :path: ".symlinks/plugins/path_provider_ios/ios"
+ record:
+ :path: ".symlinks/plugins/record/ios"
+ sqflite:
+ :path: ".symlinks/plugins/sqflite/ios"
+ url_launcher_ios:
+ :path: ".symlinks/plugins/url_launcher_ios/ios"
+
+SPEC CHECKSUMS:
+ audio_session: 4f3e461722055d21515cf3261b64c973c062f345
+ Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
+ flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801
+ FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
+ image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
+ image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6
+ just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
+ path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
+ record: 7ee2393532f8553bbb09fa19e95478323b7c0a99
+ sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
+ TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
+ url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af
+
+PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
+
+COCOAPODS: 1.11.2
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index ab390f9..afb27d5 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@@ -13,6 +13,7 @@
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 */; };
+ E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75DBECA488F412614712FB74 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -31,9 +32,11 @@
/* 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 = ""; };
+ 1CDA6531AC975E620DBA1134 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; 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 = ""; };
+ 75DBECA488F412614712FB74 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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 = ""; };
@@ -42,6 +45,8 @@
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 = ""; };
+ 98ACB01D5FA5A78DB2686183 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ C97DED20C4A171F16FB949CD /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -49,12 +54,31 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 650C3E9A238A953E4E8E6AED /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 75DBECA488F412614712FB74 /* Pods_Runner.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 8170350417391B7E9B77985B /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ C97DED20C4A171F16FB949CD /* Pods-Runner.debug.xcconfig */,
+ 98ACB01D5FA5A78DB2686183 /* Pods-Runner.release.xcconfig */,
+ 1CDA6531AC975E620DBA1134 /* Pods-Runner.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@@ -72,6 +96,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
+ 8170350417391B7E9B77985B /* Pods */,
+ 650C3E9A238A953E4E8E6AED /* Frameworks */,
);
sourceTree = "";
};
@@ -105,12 +131,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
+ 9F9C99F59A6A1134B656560D /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ AE20B55CEF8506DDEEBE3543 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -127,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -197,6 +225,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
+ 9F9C99F59A6A1134B656560D /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ AE20B55CEF8506DDEEBE3543 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -287,12 +354,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@@ -411,12 +485,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -430,12 +511,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..3db53b6 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+
+
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png
new file mode 100644
index 0000000..c89e7ed
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png
new file mode 100644
index 0000000..55e86ba
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png
new file mode 100644
index 0000000..0a984f2
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png
new file mode 100644
index 0000000..54ff853
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png
new file mode 100644
index 0000000..d525986
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png
new file mode 100644
index 0000000..f00cef9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png
new file mode 100644
index 0000000..1cebf8d
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png
new file mode 100644
index 0000000..eb8dc68
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png
new file mode 100644
index 0000000..2692e97
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png
new file mode 100644
index 0000000..8836e48
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png
new file mode 100644
index 0000000..0d0a595
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png
new file mode 100644
index 0000000..f7aee80
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png
new file mode 100644
index 0000000..05a2b2c
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png
new file mode 100644
index 0000000..e60aeea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png
new file mode 100644
index 0000000..090d005
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png
new file mode 100644
index 0000000..489b5c8
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png
new file mode 100644
index 0000000..c9bf87c
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png
new file mode 100644
index 0000000..05c32e8
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png
new file mode 100644
index 0000000..a246eff
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png
new file mode 100644
index 0000000..d30c1cc
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png
new file mode 100644
index 0000000..77f48a9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png
new file mode 100644
index 0000000..d38ad5d
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png
new file mode 100644
index 0000000..9e534dc
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png
new file mode 100644
index 0000000..e1fc0c9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png
new file mode 100644
index 0000000..615b8f4
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png
new file mode 100644
index 0000000..82cbc07
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png
new file mode 100644
index 0000000..7ff37bc
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png
new file mode 100644
index 0000000..f7388be
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png
new file mode 100644
index 0000000..6702119
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png
new file mode 100644
index 0000000..b1011a6
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png
new file mode 100644
index 0000000..6d433e1
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
index d36b1fa..e138c0b 100644
--- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,122 +1 @@
-{
- "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"
- }
-}
+{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]}
\ No newline at end of file
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
deleted file mode 100644
index dc9ada4..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null 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
deleted file mode 100644
index 28c6bf0..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null 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
deleted file mode 100644
index 2ccbfd9..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null 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
deleted file mode 100644
index f091b6b..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null 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
deleted file mode 100644
index 4cde121..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null 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
deleted file mode 100644
index d0ef06e..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null 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
deleted file mode 100644
index dcdc230..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null 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
deleted file mode 100644
index 2ccbfd9..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null 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
deleted file mode 100644
index c8f9ed8..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null 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
deleted file mode 100644
index a6d6b86..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null 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
deleted file mode 100644
index a6d6b86..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null 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
deleted file mode 100644
index 75b2d16..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null 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
deleted file mode 100644
index c4df70d..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null 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
deleted file mode 100644
index 6a84f41..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null 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
deleted file mode 100644
index d0e1f58..0000000
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 8a877dd..4d67f3b 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -26,6 +26,12 @@
LaunchScreen
UIMainStoryboardFile
Main
+ NSMicrophoneUsageDescription
+We need to access to the microphone to record audio file
+NSPhotoLibraryUsageDescription
+We need to access to the user gallery to add user profile photo
+NSCameraUsageDescription
+We need to access to the user gallery to add user profile photo
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
diff --git a/lib/assets/animations/loading.gif b/lib/assets/animations/loading.gif
new file mode 100644
index 0000000..cf967e1
Binary files /dev/null and b/lib/assets/animations/loading.gif differ
diff --git a/lib/assets/images/logos/studio-dark.svg b/lib/assets/images/logos/studio-dark.svg
new file mode 100644
index 0000000..3d0e67d
--- /dev/null
+++ b/lib/assets/images/logos/studio-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/lib/assets/images/logos/studio-light.svg b/lib/assets/images/logos/studio-light.svg
new file mode 100644
index 0000000..73d14b1
--- /dev/null
+++ b/lib/assets/images/logos/studio-light.svg
@@ -0,0 +1,25 @@
+
diff --git a/lib/config/theme_data.dart b/lib/config/theme_data.dart
index d605c2a..c2c4516 100644
--- a/lib/config/theme_data.dart
+++ b/lib/config/theme_data.dart
@@ -36,9 +36,9 @@ class LightThemeConfig {
static const ColorScheme _colorScheme = ColorScheme(
primary: _primary,
- primaryVariant: _white,
+ primaryContainer: _white,
secondary: Color(0xFFD61515),
- secondaryVariant: _white,
+ secondaryContainer: _white,
surface: _white,
background: _background,
error: Color(0xFFF00505),
@@ -116,9 +116,9 @@ class DarkThemeConfig {
static const ColorScheme _colorScheme = ColorScheme(
primary: _primary,
- primaryVariant: _white,
+ primaryContainer: _white,
secondary: Color(0xFFE53939),
- secondaryVariant: _white,
+ secondaryContainer: _white,
surface: Color(0xFF181B1F),
background: _background,
error: Color(0xFFF53B3B),
diff --git a/lib/constants/assets.dart b/lib/constants/assets.dart
index a331516..e19e386 100644
--- a/lib/constants/assets.dart
+++ b/lib/constants/assets.dart
@@ -8,11 +8,13 @@ class Assets {
static const String _baseEmptyStatesPath = _basePath + '/images/empty_states';
static const String _baseAnimationsPath = _basePath + '/animations';
static const String _baseRecordsPath = _basePath + '/images/records';
+ static const String _baseLogosPath = _basePath + '/images/logos';
static String get verticalLogoWithText =>
- _baseImagesPath + '/logos/logo-vertical-$_themeSuffix.svg';
+ _baseLogosPath + '/logo-vertical-$_themeSuffix.svg';
static String get horizontalLogoWithText =>
- _baseImagesPath + '/logos/logo-horizontal-$_themeSuffix.svg';
+ _baseLogosPath + '/logo-horizontal-$_themeSuffix.svg';
+ static String get studioLogo => _baseLogosPath + '/studio-$_themeSuffix.svg';
static String get logoLoadingAnimation =>
_baseAnimationsPath + '/indicator-$_themeSuffix.riv';
diff --git a/lib/main.dart b/lib/main.dart
index 9c23e4d..01dbfff 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,6 +1,5 @@
import 'package:bot_toast/bot_toast.dart';
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/providers/server_data_provider.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/route_generator.dart';
@@ -24,9 +23,6 @@ class Didvan extends StatelessWidget {
ChangeNotifierProvider(
create: (context) => UserProvider(),
),
- ChangeNotifierProvider(
- create: (context) => ServerDataProvider(),
- ),
ChangeNotifierProvider(
create: (context) => ThemeProvider(),
),
diff --git a/lib/models/category.dart b/lib/models/category.dart
index 6968552..3faf75a 100644
--- a/lib/models/category.dart
+++ b/lib/models/category.dart
@@ -1,10 +1,10 @@
-class Category {
+class CategoryData {
final int id;
final String label;
- const Category({required this.id, required this.label});
+ const CategoryData({required this.id, required this.label});
- factory Category.fromJson(Map json) => Category(
+ factory CategoryData.fromJson(Map json) => CategoryData(
id: json['id'],
label: json['label'],
);
diff --git a/lib/models/chat_room/chat_room.dart b/lib/models/chat_room/chat_room.dart
index a741cc7..99457eb 100644
--- a/lib/models/chat_room/chat_room.dart
+++ b/lib/models/chat_room/chat_room.dart
@@ -4,10 +4,10 @@ class ChatRoom {
final int id;
final String type;
final String updatedAt;
- final int unread;
+ int unread;
final LastMessage lastMessage;
- const ChatRoom({
+ ChatRoom({
required this.id,
required this.type,
required this.updatedAt,
diff --git a/lib/models/item_overview.dart b/lib/models/item_overview.dart
deleted file mode 100644
index 921d7db..0000000
--- a/lib/models/item_overview.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-class OverviewData {
- final int id;
- final String title;
- final String image;
- final String description;
- final String createdAt;
- final String? type;
-
- const OverviewData({
- required this.id,
- required this.title,
- required this.image,
- required this.description,
- required this.createdAt,
- required this.type,
- });
-
- factory OverviewData.fromJson(Map json) => OverviewData(
- id: json['id'],
- title: json['title'],
- image: json['image'],
- description: json['description'],
- createdAt: json['createdAt'],
- type: json['type'],
- );
-}
diff --git a/lib/models/message_data/message_data.dart b/lib/models/message_data/message_data.dart
index 8cb4b45..1778abc 100644
--- a/lib/models/message_data/message_data.dart
+++ b/lib/models/message_data/message_data.dart
@@ -1,3 +1,6 @@
+import 'dart:convert';
+import 'dart:io';
+
import 'radar_attachment.dart';
class MessageData {
@@ -8,15 +11,19 @@ class MessageData {
final bool readed;
final String createdAt;
final RadarAttachment? radar;
+ final File? audioFile;
+ final int? audioDuration;
const MessageData({
required this.id,
required this.writedByAdmin,
required this.readed,
required this.createdAt,
- required this.text,
- required this.audio,
- required this.radar,
+ this.text,
+ this.audio,
+ this.radar,
+ this.audioFile,
+ this.audioDuration,
});
factory MessageData.fromJson(Map json) => MessageData(
@@ -26,9 +33,12 @@ class MessageData {
writedByAdmin: json['writedByAdmin'],
readed: json['readed'],
createdAt: json['createdAt'],
+ audioDuration: json['waveform'] == null
+ ? null
+ : jsonDecode(json['waveform'])['duration'] ?? 0,
radar: json['radar'] == null
? null
- : RadarAttachment.fromJson(json['radar'] as Map),
+ : RadarAttachment.fromJson(json['radar']),
);
Map toJson() => {
diff --git a/lib/models/message_data/radar_attachment.dart b/lib/models/message_data/radar_attachment.dart
index 13dbe76..6e55f2d 100644
--- a/lib/models/message_data/radar_attachment.dart
+++ b/lib/models/message_data/radar_attachment.dart
@@ -1,3 +1,5 @@
+import 'package:didvan/models/category.dart';
+
class RadarAttachment {
final int id;
final String title;
@@ -5,6 +7,8 @@ class RadarAttachment {
final int timeToRead;
final String image;
final bool forManagers;
+ final String createdAt;
+ final List categories;
const RadarAttachment({
required this.id,
@@ -13,6 +17,8 @@ class RadarAttachment {
required this.timeToRead,
required this.image,
required this.forManagers,
+ required this.categories,
+ required this.createdAt,
});
factory RadarAttachment.fromJson(Map json) =>
@@ -22,7 +28,13 @@ class RadarAttachment {
description: json['description'],
timeToRead: json['timeToRead'],
image: json['image'],
+ createdAt: json['createdAt'],
forManagers: json['forManagers'],
+ categories: List.from(
+ json['categories'].map(
+ (cat) => CategoryData.fromJson(cat),
+ ),
+ ),
);
Map toJson() => {
diff --git a/lib/models/news_details_data.dart b/lib/models/news_details_data.dart
index 1b603bd..0a1a68b 100644
--- a/lib/models/news_details_data.dart
+++ b/lib/models/news_details_data.dart
@@ -1,4 +1,5 @@
import 'package:didvan/models/content.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/tag.dart';
class NewsDetailsData {
@@ -12,6 +13,7 @@ class NewsDetailsData {
final int order;
final List tags;
final List contents;
+ final List relatedContents = [];
NewsDetailsData({
required this.id,
diff --git a/lib/models/news_overview.dart b/lib/models/news_overview.dart
deleted file mode 100644
index 35d2161..0000000
--- a/lib/models/news_overview.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-import 'package:didvan/models/item_overview.dart';
-
-class NewsOverviewData extends OverviewData {
- final String reference;
- bool marked;
-
- NewsOverviewData({
- required this.reference,
- required this.marked,
- required id,
- required createdAt,
- required description,
- required title,
- required image,
- }) : super(
- createdAt: createdAt,
- description: description,
- id: id,
- image: image,
- title: title,
- type: 'news',
- );
-
- factory NewsOverviewData.fromJson(Map json) =>
- NewsOverviewData(
- id: json['id'],
- title: json['title'],
- reference: json['reference'],
- description: json['description'],
- image: json['image'],
- createdAt: json['createdAt'],
- marked: json['marked'] ?? true,
- );
-}
diff --git a/lib/models/overview_data.dart b/lib/models/overview_data.dart
new file mode 100644
index 0000000..4d16449
--- /dev/null
+++ b/lib/models/overview_data.dart
@@ -0,0 +1,61 @@
+import 'package:didvan/models/category.dart';
+
+class OverviewData {
+ final int id;
+ final String title;
+ final String image;
+ final String description;
+ final int? timeToRead;
+ final String? reference;
+ final bool forManagers;
+ final String createdAt;
+ final String type;
+ int comments;
+ bool marked;
+ final List? categories;
+
+ OverviewData({
+ required this.id,
+ required this.title,
+ required this.image,
+ required this.description,
+ required this.createdAt,
+ required this.type,
+ required this.marked,
+ required this.comments,
+ required this.forManagers,
+ this.timeToRead,
+ this.reference,
+ this.categories,
+ });
+
+ factory OverviewData.fromJson(Map json) => OverviewData(
+ id: json['id'],
+ title: json['title'],
+ image: json['image'],
+ description: json['description'],
+ timeToRead: json['timeToRead'],
+ reference: json['reference'],
+ forManagers: json['forManagers'] ?? false,
+ comments: json['comments'] ?? 0,
+ createdAt: json['createdAt'],
+ type: json['type'] ?? '',
+ marked: json['marked'] ?? false,
+ categories: (json['categories'] as List?)
+ ?.map((e) => CategoryData.fromJson(e as Map))
+ .toList(),
+ );
+
+ Map toJson() => {
+ 'id': id,
+ 'title': title,
+ 'image': image,
+ 'description': description,
+ 'timeToRead': timeToRead,
+ 'reference': reference,
+ 'forManagers': forManagers,
+ 'createdAt': createdAt,
+ 'type': type,
+ 'categories': categories?.map((e) => e.toJson()).toList(),
+ };
+}
diff --git a/lib/models/radar_details_data.dart b/lib/models/radar_details_data.dart
index fb493e3..a41bb1e 100644
--- a/lib/models/radar_details_data.dart
+++ b/lib/models/radar_details_data.dart
@@ -1,4 +1,5 @@
import 'package:didvan/models/category.dart';
+import 'package:didvan/models/overview_data.dart';
import 'content.dart';
import 'tag.dart';
@@ -15,8 +16,9 @@ class RadarDetailsData {
int comments;
final List tags;
final List contents;
- final List categories;
+ final List categories;
final int order;
+ final List relatedContents = [];
RadarDetailsData({
required this.id,
@@ -52,9 +54,9 @@ class RadarDetailsData {
(content) => Content.fromJson(content),
),
),
- categories: List.from(
+ categories: List.from(
json['categories'].map(
- (cat) => Category.fromJson(cat),
+ (cat) => CategoryData.fromJson(cat),
),
),
);
diff --git a/lib/models/radar_overview.dart b/lib/models/radar_overview.dart
deleted file mode 100644
index ba3469e..0000000
--- a/lib/models/radar_overview.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-import 'package:didvan/models/item_overview.dart';
-
-import 'category.dart';
-
-class RadarOverviewData extends OverviewData {
- final bool forManagers;
- final List categories;
- final int timeToRead;
- int comments;
- bool marked;
-
- RadarOverviewData({
- required this.forManagers,
- required this.categories,
- required this.comments,
- required this.timeToRead,
- required this.marked,
- required createdAt,
- required description,
- required id,
- required image,
- required title,
- }) : super(
- createdAt: createdAt,
- description: description,
- id: id,
- image: image,
- title: title,
- type: 'radar',
- );
-
- factory RadarOverviewData.fromJson(Map json) =>
- RadarOverviewData(
- id: json['id'],
- image: json['image'],
- title: json['title'],
- description: json['description'],
- timeToRead: json['timeToRead'],
- createdAt: json['createdAt'],
- forManagers: json['forManagers'],
- marked: json['marked'],
- comments: json['comments'],
- categories: List.from(
- json['categories'].map(
- (category) => Category.fromJson(category),
- ),
- ),
- );
-}
diff --git a/lib/models/user.dart b/lib/models/user.dart
index 01feaf8..92011db 100644
--- a/lib/models/user.dart
+++ b/lib/models/user.dart
@@ -43,11 +43,11 @@ class User {
}) {
return User(
id: id ?? this.id,
- username: username ?? this.username,
+ username: this.username,
phoneNumber: phoneNumber ?? this.phoneNumber,
- photo: photo ?? this.photo,
+ photo: photo,
fullName: fullName ?? this.fullName,
- email: email ?? this.email,
+ email: email,
);
}
}
diff --git a/lib/models/view/action_sheet_data.dart b/lib/models/view/action_sheet_data.dart
index a95a4a2..6166bb6 100644
--- a/lib/models/view/action_sheet_data.dart
+++ b/lib/models/view/action_sheet_data.dart
@@ -10,6 +10,7 @@ class ActionSheetData {
final IconData? titleIcon;
final Color? titleColor;
final bool hasDismissButton;
+ final bool hasConfirmButton;
final bool withoutButtonMode;
final bool smallDismissButton;
@@ -20,6 +21,7 @@ class ActionSheetData {
this.onConfirmed,
this.titleColor,
this.hasDismissButton = true,
+ this.hasConfirmButton = true,
this.titleIcon,
this.dismissTitle,
this.onDismissed,
diff --git a/lib/pages/home/direct/direct.dart b/lib/pages/home/direct/direct.dart
deleted file mode 100644
index 095f8d7..0000000
--- a/lib/pages/home/direct/direct.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-import 'package:didvan/pages/home/direct/direct_state.dart';
-import 'package:didvan/pages/home/direct/widgets/message_box.dart';
-import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class Direct extends StatefulWidget {
- final int id;
- const Direct({Key? key, required this.id}) : super(key: key);
-
- @override
- State createState() => _DirectState();
-}
-
-class _DirectState extends State {
- @override
- void initState() {
- Future.delayed(Duration.zero, () {
- context.read().getMessages(widget.id);
- });
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- return Material(
- child: Stack(
- children: [
- Positioned(
- top: 0,
- bottom: 56,
- left: 0,
- right: 0,
- child: DidvanScaffold(
- appBarData: AppBarData(
- hasBack: true,
- subtitle: 'ارتباط با سردبیر',
- title: 'رادار اقتصادی',
- ),
- slivers: const [],
- ),
- ),
- Positioned(
- bottom: MediaQuery.of(context).viewInsets.bottom,
- right: 0,
- left: 0,
- child: const MessageBox(),
- ),
- ],
- ),
- );
- }
-}
diff --git a/lib/pages/home/direct/direct_state.dart b/lib/pages/home/direct/direct_state.dart
deleted file mode 100644
index 18b9b86..0000000
--- a/lib/pages/home/direct/direct_state.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import 'dart:io';
-
-import 'package:didvan/providers/core_provider.dart';
-import 'package:didvan/services/network/request.dart';
-import 'package:didvan/services/network/request_helper.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter_vibrate/flutter_vibrate.dart';
-import 'package:record/record.dart';
-
-class DirectState extends CoreProvier {
- final _recorder = Record();
-
- File? recordedFile;
-
- bool isRecording = false;
-
- Future getMessages(int id) async {
- final RequestService service = RequestService(RequestHelper.direct(id));
- await service.httpGet();
- if (service.isSuccess) {}
- }
-
- void deleteRecordedFile() {
- recordedFile!.delete();
- recordedFile = null;
- notifyListeners();
- }
-
- Future startRecording() async {
- await _recorder.hasPermission();
- if (!kIsWeb) {
- Vibrate.feedback(FeedbackType.medium);
- }
- isRecording = true;
- _recorder.start();
- notifyListeners();
- }
-
- Future stopRecording(bool sendImidiately) async {
- final path = await _recorder.stop();
- isRecording = false;
- if (path == null) {
- notifyListeners();
- return;
- }
- if (kIsWeb) {
- final uri = Uri.file(path);
- recordedFile = File.fromUri(uri);
- } else {
- recordedFile = File(path);
- }
- if (sendImidiately) {
- await sendMessage();
- } else {
- notifyListeners();
- }
- }
-
- Future sendMessage() async {}
-}
diff --git a/lib/pages/home/direct/widgets/message_box.dart b/lib/pages/home/direct/widgets/message_box.dart
deleted file mode 100644
index 3f2ccf4..0000000
--- a/lib/pages/home/direct/widgets/message_box.dart
+++ /dev/null
@@ -1,131 +0,0 @@
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/pages/home/direct/direct_state.dart';
-import 'package:didvan/pages/home/widgets/audio_visualizer.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-class MessageBox extends StatelessWidget {
- const MessageBox({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- height: 56,
- decoration: BoxDecoration(
- border: Border(
- top: BorderSide(
- color: Theme.of(context).colorScheme.cardBorder,
- ),
- ),
- color: Theme.of(context).colorScheme.surface,
- ),
- child: Consumer(
- builder: (context, state, child) {
- if (state.isRecording) {
- return const _Recording();
- } else if (!state.isRecording && state.recordedFile != null) {
- return const _RecordChecking();
- }
- return const _Typing();
- },
- ),
- );
- }
-}
-
-class _Typing extends StatelessWidget {
- const _Typing({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- final state = context.read();
- return Row(
- children: [
- DidvanIconButton(
- icon: DidvanIcons.mic_solid,
- onPressed: state.startRecording,
- size: 32,
- color: Theme.of(context).colorScheme.focusedBorder,
- ),
- Expanded(
- child: TextField(
- textInputAction: TextInputAction.send,
- decoration: InputDecoration(
- border: InputBorder.none,
- hintText: 'بنویسید یا پیام صوتی بگذارید...',
- hintStyle: Theme.of(context)
- .textTheme
- .caption!
- .copyWith(color: Theme.of(context).colorScheme.disabledText),
- ),
- onChanged: (value) {},
- ),
- ),
- ],
- );
- }
-}
-
-class _Recording extends StatelessWidget {
- const _Recording({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- final state = context.read();
- return Row(
- children: [
- DidvanIconButton(
- icon: DidvanIcons.send_solid,
- onPressed: () => state.stopRecording(true),
- gestureSize: 52,
- ),
- Expanded(
- child: DidvanText(
- 'در حال ضبط صدا ...',
- style: Theme.of(context).textTheme.caption,
- ),
- ),
- DidvanIconButton(
- icon: DidvanIcons.stop_circle_solid,
- color: Theme.of(context).colorScheme.secondary,
- onPressed: () => state.stopRecording(false),
- size: 32,
- ),
- ],
- );
- }
-}
-
-class _RecordChecking extends StatelessWidget {
- const _RecordChecking({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- final state = context.read();
- return Row(
- children: [
- DidvanIconButton(
- icon: DidvanIcons.send_solid,
- onPressed: () => state.stopRecording(true),
- color: Theme.of(context).colorScheme.focusedBorder,
- ),
- Expanded(
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 8),
- child: AudioVisualizer(
- audioFile: state.recordedFile!,
- ),
- ),
- ),
- DidvanIconButton(
- icon: DidvanIcons.trash_solid,
- color: Theme.of(context).colorScheme.secondary,
- onPressed: state.deleteRecordedFile,
- ),
- ],
- );
- }
-}
diff --git a/lib/pages/home/studio/studio.dart b/lib/pages/home/studio/studio.dart
deleted file mode 100644
index dd7eed3..0000000
--- a/lib/pages/home/studio/studio.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/assets.dart';
-import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
-import 'package:flutter/material.dart';
-
-class Studio extends StatelessWidget {
- const Studio({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Column(
- children: [
- const LogoAppBar(),
- Expanded(
- child: EmptyState(
- asset: Assets.emptyStudio,
- title: 'استودیو آینده',
- subtitle: 'به زودی...',
- titleColor: Theme.of(context).colorScheme.title,
- ),
- ),
- ],
- );
- }
-}
diff --git a/lib/pages/home/widgets/audio_visualizer.dart b/lib/pages/home/widgets/audio_visualizer.dart
deleted file mode 100644
index 94fc277..0000000
--- a/lib/pages/home/widgets/audio_visualizer.dart
+++ /dev/null
@@ -1,314 +0,0 @@
-import 'dart:io';
-import 'dart:math';
-
-import 'package:didvan/config/design_config.dart';
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/constants/assets.dart';
-import 'package:didvan/services/storage/storage.dart';
-import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/flutter_svg.dart';
-import 'package:just_audio/just_audio.dart';
-import 'package:just_waveform/just_waveform.dart';
-
-class AudioVisualizer extends StatefulWidget {
- final File audioFile;
-
- const AudioVisualizer({
- Key? key,
- required this.audioFile,
- }) : super(key: key);
-
- @override
- State createState() => _AudioVisualizerState();
-}
-
-class _AudioVisualizerState extends State {
- final AudioPlayer _audioPlayer = AudioPlayer();
-
- Stream? waveDataStream;
-
- @override
- void initState() {
- if (!kIsWeb) {
- waveDataStream = JustWaveform.extract(
- audioInFile: widget.audioFile,
- waveOutFile: File(StorageService.appTempsDir + '/rec-wave.wave'),
- zoom: const WaveformZoom.pixelsPerSecond(100),
- );
- }
- _setupAudioPlayer();
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- return Container(
- decoration: BoxDecoration(
- color: DesignConfig.isDark
- ? Theme.of(context).colorScheme.black
- : Theme.of(context).colorScheme.background,
- borderRadius: DesignConfig.mediumBorderRadius,
- ),
- child: Row(
- children: [
- const SizedBox(width: 12),
- StreamBuilder(
- stream: _audioPlayer.positionStream,
- builder: (context, snapshot) {
- String text = '';
- if (_audioPlayer.duration == null) {
- Future.delayed(Duration.zero, () {
- setState(() {});
- });
- }
- if (snapshot.data == null || snapshot.data == Duration.zero) {
- text = DateTimeUtils.normalizeTimeDuration(
- _audioPlayer.duration ?? Duration.zero);
- } else {
- text = DateTimeUtils.normalizeTimeDuration(snapshot.data!);
- }
- return DidvanText(
- text,
- color: Theme.of(context).colorScheme.focusedBorder,
- isEnglishFont: true,
- );
- },
- ),
- const SizedBox(width: 12),
- Expanded(
- child: Builder(
- builder: (context) {
- if (kIsWeb) {
- return SvgPicture.asset(Assets.record);
- }
- return StreamBuilder(
- stream: waveDataStream,
- builder: (context, snapshot) {
- if (snapshot.data == null) {
- return const SizedBox();
- }
- if (snapshot.data!.waveform == null) {
- return const SizedBox();
- }
- final waveform = snapshot.data!.waveform!;
- return GestureDetector(
- onHorizontalDragUpdate: _changePosition,
- onTapDown: _changePosition,
- child: SizedBox(
- height: double.infinity,
- width: double.infinity,
- child: _AudioWaveformWidget(
- waveform: waveform,
- audioPlayer: _audioPlayer,
- start: Duration.zero,
- scale: 2,
- strokeWidth: 3,
- duration: waveform.duration,
- waveColor:
- Theme.of(context).colorScheme.focusedBorder,
- ),
- ),
- );
- },
- );
- },
- ),
- ),
- StreamBuilder(
- stream: _audioPlayer.playingStream,
- builder: (context, snapshot) {
- return DidvanIconButton(
- icon: snapshot.data == true
- ? DidvanIcons.pause_circle_solid
- : DidvanIcons.play_circle_solid,
- color: Theme.of(context).colorScheme.focusedBorder,
- onPressed: _playAndPouse,
- );
- },
- ),
- ],
- ),
- );
- }
-
- void _changePosition(details) {
- double posper =
- details.localPosition.dx / (MediaQuery.of(context).size.width - 200);
- if (posper >= 1 || posper < 0) return;
- final position = _audioPlayer.duration!.inMilliseconds;
- _audioPlayer.seek(
- Duration(milliseconds: (posper * position).toInt()),
- );
- setState(() {});
- }
-
- Future _setupAudioPlayer() async {
- if (kIsWeb) {
- await _audioPlayer.setUrl(
- widget.audioFile.uri.path.replaceAll('%3A', ':'),
- );
- } else {
- await _audioPlayer.setFilePath(widget.audioFile.path);
- }
- }
-
- Future _playAndPouse() async {
- if (_audioPlayer.playing) {
- _audioPlayer.pause();
- return;
- }
- await _audioPlayer.play();
- }
-
- @override
- void dispose() {
- _audioPlayer.dispose();
- super.dispose();
- }
-}
-
-class _AudioWaveformWidget extends StatefulWidget {
- final Color waveColor;
- final double scale;
- final double strokeWidth;
- final double pixelsPerStep;
- final Waveform waveform;
- final Duration start;
- final Duration duration;
- final AudioPlayer audioPlayer;
-
- const _AudioWaveformWidget({
- Key? key,
- required this.waveform,
- required this.start,
- required this.duration,
- required this.audioPlayer,
- this.waveColor = Colors.blue,
- this.scale = 1.0,
- this.strokeWidth = 5.0,
- this.pixelsPerStep = 8.0,
- }) : super(key: key);
-
- @override
- __AudioWaveformWidgetState createState() => __AudioWaveformWidgetState();
-}
-
-class __AudioWaveformWidgetState extends State<_AudioWaveformWidget>
- with SingleTickerProviderStateMixin {
- double progress = 0;
-
- @override
- void initState() {
- widget.audioPlayer.positionStream.listen((event) {
- if (widget.audioPlayer.duration == null) return;
- setState(() {
- progress = event.inMilliseconds /
- widget.audioPlayer.duration!.inMilliseconds *
- 100;
- if (progress >= 100) {
- progress = 0;
- widget.audioPlayer.stop();
- widget.audioPlayer.seek(Duration.zero);
- }
- });
- });
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- return ClipRect(
- child: CustomPaint(
- painter: _AudioWaveformPainter(
- waveColor: widget.waveColor,
- waveform: widget.waveform,
- start: widget.start,
- duration: widget.duration,
- scale: widget.scale,
- strokeWidth: widget.strokeWidth,
- pixelsPerStep: widget.pixelsPerStep,
- progressPercentage: progress,
- progressColor: Theme.of(context).colorScheme.focusedBorder,
- color: Theme.of(context).colorScheme.border,
- ),
- ),
- );
- }
-}
-
-class _AudioWaveformPainter extends CustomPainter {
- final double scale;
- final double strokeWidth;
- final double pixelsPerStep;
- final Waveform waveform;
- final Duration start;
- final Duration duration;
- final double progressPercentage;
- final Color progressColor;
- final Color color;
-
- _AudioWaveformPainter({
- required this.waveform,
- required this.start,
- required this.duration,
- required this.progressPercentage,
- required this.color,
- required this.progressColor,
- Color waveColor = Colors.blue,
- this.scale = 1.0,
- this.strokeWidth = 5.0,
- this.pixelsPerStep = 8.0,
- });
-
- @override
- void paint(Canvas canvas, Size size) {
- if (duration == Duration.zero) return;
- double width = size.width;
- double height = size.height;
-
- final waveformPixelsPerWindow = waveform.positionToPixel(duration).toInt();
- final waveformPixelsPerDevicePixel = waveformPixelsPerWindow / width;
- final waveformPixelsPerStep = waveformPixelsPerDevicePixel * pixelsPerStep;
- final sampleOffset = waveform.positionToPixel(start);
- final sampleStart = -sampleOffset % waveformPixelsPerStep;
- final totalLength = waveformPixelsPerWindow;
- final wavePaintB = Paint()
- ..style = PaintingStyle.stroke
- ..strokeWidth = strokeWidth
- ..strokeCap = StrokeCap.round
- ..color = progressColor;
- final wavePaintA = Paint()
- ..style = PaintingStyle.stroke
- ..strokeWidth = strokeWidth
- ..strokeCap = StrokeCap.round
- ..color = color;
- for (var i = sampleStart.toDouble();
- i <= waveformPixelsPerWindow + 1.0;
- i += waveformPixelsPerStep) {
- final sampleIdx = (sampleOffset + i).toInt();
- final x = i / waveformPixelsPerDevicePixel;
- final minY = normalise(waveform.getPixelMin(sampleIdx), height);
- final maxY = normalise(waveform.getPixelMax(sampleIdx), height);
- canvas.drawLine(
- Offset(x + strokeWidth / 2, max(strokeWidth * 0.75, minY)),
- Offset(x + strokeWidth / 2, min(height - strokeWidth * 0.75, maxY)),
- i / totalLength < progressPercentage / 100 ? wavePaintB : wavePaintA,
- );
- }
- }
-
- @override
- bool shouldRepaint(covariant _AudioWaveformPainter oldDelegate) {
- return oldDelegate.progressPercentage != progressPercentage;
- }
-
- double normalise(int s, double height) {
- final y = 32768 + (scale * s).clamp(-32768.0, 32767.0).toDouble();
- return height - 1 - y * height / 65536;
- }
-}
diff --git a/lib/pages/home/widgets/tag_item.dart b/lib/pages/home/widgets/tag_item.dart
deleted file mode 100644
index 24d9fa3..0000000
--- a/lib/pages/home/widgets/tag_item.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-import 'package:didvan/config/design_config.dart';
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:flutter/material.dart';
-
-class TagItem extends StatelessWidget {
- final String label;
-
- const TagItem({
- Key? key,
- required this.label,
- }) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- padding: const EdgeInsets.symmetric(
- vertical: 4,
- horizontal: 8,
- ),
- decoration: BoxDecoration(
- borderRadius: DesignConfig.lowBorderRadius,
- border: Border.all(
- color: Theme.of(context).colorScheme.focusedBorder,
- ),
- ),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- Icon(
- DidvanIcons.hashtag_regular,
- color: Theme.of(context).colorScheme.focusedBorder,
- ),
- DidvanText(
- label,
- color: Theme.of(context).colorScheme.focusedBorder,
- style: Theme.of(context).textTheme.bodyText1,
- ),
- ],
- ),
- );
- }
-}
diff --git a/lib/providers/server_data_provider.dart b/lib/providers/server_data_provider.dart
index 53eb006..e9b02a5 100644
--- a/lib/providers/server_data_provider.dart
+++ b/lib/providers/server_data_provider.dart
@@ -1,15 +1,18 @@
-import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
-class ServerDataProvider extends CoreProvier {
- final List directTypes = [];
+class ServerDataProvider {
+ static final List directTypes = [];
- Future getData() async {
+ static Future getData() async {
await _getDirectTypes();
}
- Future _getDirectTypes() async {
+ static int labelToTypeId(String? label) => label == null
+ ? 7
+ : directTypes.firstWhere((element) => element.value.contains(label)).key;
+
+ static Future _getDirectTypes() async {
final service = RequestService(RequestHelper.directTypes);
await service.httpGet();
if (service.isSuccess) {
@@ -17,6 +20,8 @@ class ServerDataProvider extends CoreProvier {
for (var i = 0; i < types.length; i++) {
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
}
+ } else {
+ throw 'Fetchin direct types failed!';
}
}
}
diff --git a/lib/providers/user_provider.dart b/lib/providers/user_provider.dart
index 3be9ea5..219acd1 100644
--- a/lib/providers/user_provider.dart
+++ b/lib/providers/user_provider.dart
@@ -20,6 +20,7 @@ class UserProvider extends CoreProvier {
return token;
}
await StorageService.setValue(key: 'token', value: newToken);
+ return null;
}
Future getUserInfo() async {
@@ -35,8 +36,15 @@ class UserProvider extends CoreProvier {
Future setProfilePhoto(dynamic file) async {
appState = AppState.isolatedBusy;
final RequestService service =
- RequestService(RequestHelper.updateUserProfile);
- await service.multipart(file);
+ RequestService(RequestHelper.updateProfilePhoto);
+ await service.multipart(
+ file: file,
+ method: 'PUT',
+ fileName: 'user-profile',
+ fieldName: 'photo',
+ mediaExtension: 'jpg',
+ mediaFormat: 'image',
+ );
if (service.isSuccess) {
user = user.copyWith(photo: service.result['photo']);
appState = AppState.idle;
@@ -46,6 +54,20 @@ class UserProvider extends CoreProvier {
return false;
}
+ Future deleteProfilePhoto() async {
+ appState = AppState.isolatedBusy;
+ final RequestService service =
+ RequestService(RequestHelper.updateProfilePhoto);
+ await service.delete();
+ if (service.isSuccess) {
+ user = user.copyWith(photo: null);
+ appState = AppState.idle;
+ return true;
+ }
+ appState = AppState.idle;
+ return false;
+ }
+
Future checkUsername(String username) async {
if (user.username == username) return true;
final RequestService service = RequestService(
diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart
index 15452b7..9bf6300 100644
--- a/lib/routes/route_generator.dart
+++ b/lib/routes/route_generator.dart
@@ -1,30 +1,32 @@
-import 'package:didvan/pages/authentication/authentication.dart';
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/pages/home/comments/comments.dart';
-import 'package:didvan/pages/home/comments/comments_state.dart';
-import 'package:didvan/pages/home/direct/direct.dart';
-import 'package:didvan/pages/home/direct/direct_state.dart';
-import 'package:didvan/pages/home/home.dart';
-import 'package:didvan/pages/home/home_state.dart';
-import 'package:didvan/pages/home/news/news_details/news_details.dart';
-import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
-import 'package:didvan/pages/home/news/news_state.dart';
-import 'package:didvan/pages/home/radar/radar_details/radar_details.dart';
-import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart';
-import 'package:didvan/pages/home/radar/radar_state.dart';
-import 'package:didvan/pages/home/settings/about_us/about_us.dart';
-import 'package:didvan/pages/home/settings/bookmarks/bookmarks.dart';
-import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
-import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
-import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
-import 'package:didvan/pages/home/settings/direct_list/direct_list.dart';
-import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
-import 'package:didvan/pages/home/settings/general_settings/settings.dart';
-import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
-import 'package:didvan/pages/home/settings/profile/profile.dart';
-import 'package:didvan/pages/splash/splash.dart';
+import 'package:didvan/models/tag.dart';
+import 'package:didvan/views/authentication/authentication.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/home/comments/comments.dart';
+import 'package:didvan/views/home/comments/comments_state.dart';
+import 'package:didvan/views/home/direct/direct.dart';
+import 'package:didvan/views/home/direct/direct_state.dart';
+import 'package:didvan/views/home/hashtag/hashtag.dart';
+import 'package:didvan/views/home/hashtag/hashtag_state.dart';
+import 'package:didvan/views/home/home.dart';
+import 'package:didvan/views/home/home_state.dart';
+import 'package:didvan/views/home/news/news_details/news_details.dart';
+import 'package:didvan/views/home/news/news_details/news_details_state.dart';
+import 'package:didvan/views/home/news/news_state.dart';
+import 'package:didvan/views/home/radar/radar_details/radar_details.dart';
+import 'package:didvan/views/home/radar/radar_details/radar_details_state.dart';
+import 'package:didvan/views/home/radar/radar_state.dart';
+import 'package:didvan/views/home/settings/about_us/about_us.dart';
+import 'package:didvan/views/home/settings/bookmarks/bookmarks.dart';
+import 'package:didvan/views/home/settings/bookmarks/bookmark_state.dart';
+import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
+import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
+import 'package:didvan/views/home/settings/direct_list/direct_list.dart';
+import 'package:didvan/views/home/settings/direct_list/direct_list_state.dart';
+import 'package:didvan/views/home/settings/general_settings/settings.dart';
+import 'package:didvan/views/home/settings/general_settings/settings_state.dart';
+import 'package:didvan/views/home/settings/profile/profile.dart';
+import 'package:didvan/views/splash/splash.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/image_cropper.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -67,12 +69,6 @@ class RouteGenerator {
return _createRoute(
const AboutUs(),
);
- case Routes.imageCropper:
- return _createRoute(
- ImageCropper(
- data: settings.arguments as Map,
- ),
- );
case Routes.generalSettings:
return _createRoute(
ChangeNotifierProvider(
@@ -109,7 +105,7 @@ class RouteGenerator {
return _createRoute(
ChangeNotifierProvider(
create: (context) => DirectState(),
- child: Direct(id: settings.arguments as int),
+ child: Direct(pageData: settings.arguments as Map),
),
);
case Routes.comments:
@@ -128,6 +124,14 @@ class RouteGenerator {
child: const Bookmarks(),
),
);
+ case Routes.hashtag:
+ return _createRoute(
+ ChangeNotifierProvider(
+ create: (context) => HashtagState(),
+ child: Hashtag(tag: settings.arguments as Tag),
+ ),
+ );
+
case Routes.filteredBookmarks:
return _createRoute(
ChangeNotifierProvider(
@@ -157,7 +161,13 @@ class RouteGenerator {
static Route _createRoute(page) {
return MaterialPageRoute(
- builder: (context) => page,
+ builder: (context) => Container(
+ color: Theme.of(context).colorScheme.surface,
+ child: SafeArea(
+ child: page,
+ top: false,
+ ),
+ ),
);
}
}
diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart
index 5bc9c90..7cbab35 100644
--- a/lib/routes/routes.dart
+++ b/lib/routes/routes.dart
@@ -14,4 +14,5 @@ class Routes {
static const String bookmarks = '/bookmarks';
static const String filteredBookmarks = '/filtered-bookmarks';
static const String imageCropper = '/image-cropper';
+ static const String hashtag = '/hashtag';
}
diff --git a/lib/services/app_initalizer.dart b/lib/services/app_initalizer.dart
index 2e9b1aa..236fc19 100644
--- a/lib/services/app_initalizer.dart
+++ b/lib/services/app_initalizer.dart
@@ -1,6 +1,5 @@
+import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/storage/storage.dart';
-import 'package:firebase_core/firebase_core.dart';
-import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
@@ -11,8 +10,8 @@ class AppInitializer {
StorageService.appDocsDir =
(await getApplicationDocumentsDirectory()).path;
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
+ MediaService.init();
}
- await _initializeFirebase();
}
static Future initilizeSettings() async {
@@ -43,29 +42,4 @@ class AppInitializer {
return ThemeMode.light;
}
}
-
- static Future _initializeFirebase() async {
- try {
- await Firebase.initializeApp(
- options: const FirebaseOptions(
- apiKey: 'AIzaSyBp-UHjWeM0H0UHtX5yguFKG-riMzvvCzw',
- appId: '1:935017686266:android:f9cbc9aba8e3d65ed2d543',
- messagingSenderId: '935017686266',
- projectId: 'didvan-9b7da',
- ),
- );
- } catch (e) {
- Firebase.app();
- }
- final FirebaseMessaging fcm = FirebaseMessaging.instance;
- await fcm.requestPermission(
- alert: true,
- announcement: false,
- badge: true,
- carPlay: false,
- criticalAlert: false,
- provisional: false,
- sound: true,
- );
- }
}
diff --git a/lib/services/media/media.dart b/lib/services/media/media.dart
index de0dba3..7e173cf 100644
--- a/lib/services/media/media.dart
+++ b/lib/services/media/media.dart
@@ -1,6 +1,59 @@
+import 'package:didvan/services/network/request.dart';
+import 'package:didvan/services/network/request_helper.dart';
+import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
+import 'package:just_audio/just_audio.dart';
class MediaService {
+ static final AudioPlayer audioPlayer = AudioPlayer();
+ static String? audioPlayerTag;
+
+ static void init() {
+ audioPlayer.positionStream.listen((event) {
+ if (audioPlayer.duration != null && audioPlayer.duration! < event) {
+ audioPlayer.stop();
+ audioPlayer.seek(const Duration(seconds: 0));
+ }
+ });
+ }
+
+ static Future handleAudioPlayback({
+ required dynamic audioSource,
+ }) async {
+ bool isNetworkAudio = audioSource.runtimeType == String;
+ String tag;
+ if (isNetworkAudio) {
+ tag = audioSource;
+ } else {
+ tag = audioSource.path;
+ }
+ if (audioPlayerTag == tag) {
+ if (audioPlayer.playing) {
+ await audioPlayer.pause();
+ } else {
+ await audioPlayer.play();
+ }
+ } else {
+ await audioPlayer.stop();
+ audioPlayerTag = tag;
+ if (isNetworkAudio) {
+ await audioPlayer.setUrl(
+ RequestHelper.baseUrl +
+ audioSource +
+ '?accessToken=${RequestService.token}',
+ );
+ } else {
+ if (kIsWeb) {
+ await audioPlayer
+ .setUrl(audioSource!.uri.path.replaceAll('%3A', ':'));
+ } else {
+ await audioPlayer.setFilePath(audioSource.path);
+ }
+ }
+ audioPlayer.play();
+ }
+ }
+
static Future pickImage({required ImageSource source}) async {
final imagePicker = ImagePicker();
final XFile? pickedFile = await imagePicker.pickImage(source: source);
diff --git a/lib/services/network/request.dart b/lib/services/network/request.dart
index 1b11098..1614cbc 100644
--- a/lib/services/network/request.dart
+++ b/lib/services/network/request.dart
@@ -2,7 +2,6 @@ import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart' as parser;
-import 'package:image_picker/image_picker.dart';
class RequestService {
static late String token;
@@ -100,19 +99,31 @@ class RequestService {
}
}
- Future multipart(XFile file) async {
+ Future multipart({
+ required dynamic file,
+ required String method,
+ required String fileName,
+ required String fieldName,
+ required String mediaFormat,
+ required String mediaExtension,
+ }) async {
try {
- final request = http.MultipartRequest('PUT', Uri.parse(url));
+ final request = http.MultipartRequest(method, Uri.parse(url));
_headers.update('Content-Type', (_) => 'multipart/form-data');
request.headers.addAll(_headers);
final length = await file.length();
+ if (_requestBody != null) {
+ _requestBody!.forEach((key, value) {
+ request.fields.addAll({key.toString(): value.toString()});
+ });
+ }
request.files.add(
http.MultipartFile(
- 'photo',
+ fieldName,
file.readAsBytes().asStream(),
length,
- filename: 'profile-photo',
- contentType: parser.MediaType('image', 'jpg'),
+ filename: fileName + '.' + mediaExtension,
+ contentType: parser.MediaType(mediaFormat, mediaExtension),
),
);
final streamedResponse = await request
diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart
index b9f2876..1eb9a6f 100644
--- a/lib/services/network/request_helper.dart
+++ b/lib/services/network/request_helper.dart
@@ -6,19 +6,37 @@ class RequestHelper {
static const String _baseUserUrl = baseUrl + '/user';
static const String _baseRadarUrl = baseUrl + '/radar';
static const String _baseNewsUrl = baseUrl + '/news';
+ static const String _baseDirectUrl = _baseUserUrl + '/direct';
static const String confirmUsername = _baseUserUrl + '/confirmUsername';
static const String login = _baseUserUrl + '/login';
static const String directs = _baseUserUrl + '/direct';
static const String userInfo = _baseUserUrl + '/info';
- static const String updateUserProfile = _baseUserUrl + '/profile/photo';
+ static const String updateProfilePhoto = _baseUserUrl + '/profile/photo';
static const String checkUsername = _baseUserUrl + '/CheckUsername';
static const String updateProfile = _baseUserUrl + '/profile/edit';
static String bookmarks({String? type}) =>
_baseUserUrl + '/marked/${type ?? ''}';
static const String directTypes = baseUrl + '/direct/types';
- static String direct(int id) => _baseUserUrl + '/direct/$id';
+ static String direct(int id) => _baseDirectUrl + '/$id';
+ static String sendDirectMessage(int id) =>
+ _baseDirectUrl + '/$id/sendMessage';
+ static String tag({
+ required List ids,
+ String? type,
+ int? itemId,
+ int? page,
+ int? limit,
+ }) =>
+ baseUrl +
+ '/tag' +
+ _urlConcatGenerator([
+ MapEntry('limit', limit?.toString() ?? '3'),
+ MapEntry('type', type),
+ MapEntry('id', itemId.toString()),
+ MapEntry('tags', _urlListConcatGenerator(ids))
+ ]);
static String markRadar(int id) => _baseRadarUrl + '/$id/mark';
static String radarComments(int id) => _baseRadarUrl + '/$id/comments';
@@ -96,5 +114,6 @@ class RequestHelper {
}
return result;
}
+ return null;
}
}
diff --git a/lib/utils/action_sheet.dart b/lib/utils/action_sheet.dart
index f121af0..0bdb571 100644
--- a/lib/utils/action_sheet.dart
+++ b/lib/utils/action_sheet.dart
@@ -7,8 +7,8 @@ import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
@@ -83,9 +83,7 @@ class ActionSheetUtils {
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(
- top: Radius.circular(
- 10,
- ),
+ top: Radius.circular(10),
),
),
child: SingleChildScrollView(
@@ -136,17 +134,18 @@ class ActionSheetUtils {
),
),
if (data.hasDismissButton) const SizedBox(width: 20),
- Expanded(
- flex: data.smallDismissButton ? 2 : 1,
- child: DidvanButton(
- style: ButtonStyleMode.primary,
- onPressed: () {
- Navigator.of(context).pop();
- data.onConfirmed?.call();
- },
- title: data.confrimTitle ?? 'تایید',
+ if (data.hasConfirmButton)
+ Expanded(
+ flex: data.smallDismissButton ? 2 : 1,
+ child: DidvanButton(
+ style: ButtonStyleMode.primary,
+ onPressed: () {
+ Navigator.of(context).pop();
+ data.onConfirmed?.call();
+ },
+ title: data.confrimTitle ?? 'تایید',
+ ),
),
- ),
],
),
],
@@ -160,6 +159,7 @@ class ActionSheetUtils {
await showDialog(
context: context,
builder: (context) => Dialog(
+ backgroundColor: Theme.of(context).colorScheme.surface,
shape: const RoundedRectangleBorder(
borderRadius: DesignConfig.mediumBorderRadius,
),
diff --git a/lib/utils/date_time.dart b/lib/utils/date_time.dart
index e2332a4..202a9ec 100644
--- a/lib/utils/date_time.dart
+++ b/lib/utils/date_time.dart
@@ -52,6 +52,31 @@ class DateTimeUtils {
return result?.toDateTime().toString();
}
+ static String timeWithAmPm(String input) {
+ final dateTime = utcToLocalTime(input);
+ bool isAm = true;
+ int hour = 0;
+ int minute = 0;
+ if (dateTime.hour > 12) {
+ isAm = false;
+ hour = dateTime.hour - 12;
+ } else {
+ hour = dateTime.hour;
+ }
+ minute = dateTime.minute;
+ return '$hour:${_timeNormalizer(minute)} ${isAm ? 'ق.ظ' : 'ب.ظ'}';
+ }
+
+ static DateTime utcToLocalTime(String input) {
+ final dateTime = DateTime.parse(input);
+ return dateTime.add(const Duration(hours: 3, minutes: 30));
+ }
+
+ static String _timeNormalizer(int input) {
+ if (input < 10) return '0$input';
+ return input.toString();
+ }
+
static String momentGenerator(String input) {
final date = DateTime.parse(input);
final int seconds = (DateTime.now().difference(date).inSeconds).floor();
@@ -67,6 +92,7 @@ class DateTimeUtils {
}
interval = seconds / 86400;
if (interval > 1) {
+ if (interval.floor() == 1) return 'دیروز';
return interval.floor().toString() + " روز پیش";
}
interval = seconds / 3600;
diff --git a/lib/pages/authentication/authentication.dart b/lib/views/authentication/authentication.dart
similarity index 81%
rename from lib/pages/authentication/authentication.dart
rename to lib/views/authentication/authentication.dart
index cd06164..9119411 100644
--- a/lib/pages/authentication/authentication.dart
+++ b/lib/views/authentication/authentication.dart
@@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/pages/authentication/screens/password.dart';
-import 'package:didvan/pages/authentication/screens/username.dart';
-import 'package:didvan/pages/authentication/screens/reset_password.dart';
-import 'package:didvan/pages/authentication/screens/verification.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/authentication/screens/password.dart';
+import 'package:didvan/views/authentication/screens/reset_password.dart';
+import 'package:didvan/views/authentication/screens/username.dart';
+import 'package:didvan/views/authentication/screens/verification.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/authentication/authentication_state.dart b/lib/views/authentication/authentication_state.dart
similarity index 99%
rename from lib/pages/authentication/authentication_state.dart
rename to lib/views/authentication/authentication_state.dart
index 7894f4e..7efa3ba 100644
--- a/lib/pages/authentication/authentication_state.dart
+++ b/lib/views/authentication/authentication_state.dart
@@ -55,5 +55,6 @@ class AuthenticationState extends CoreProvier {
appState = AppState.failed;
ActionSheetUtils.showAlert(AlertData(message: service.errorMessage));
}
+ return null;
}
}
diff --git a/lib/pages/authentication/screens/password.dart b/lib/views/authentication/screens/password.dart
similarity index 83%
rename from lib/pages/authentication/screens/password.dart
rename to lib/views/authentication/screens/password.dart
index daada7e..391556b 100644
--- a/lib/pages/authentication/screens/password.dart
+++ b/lib/views/authentication/screens/password.dart
@@ -1,10 +1,13 @@
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
+import 'dart:developer';
+
+import 'package:didvan/providers/server_data_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/didvan/text_field.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -70,6 +73,8 @@ class _PasswordInputState extends State {
final userProvider = context.read();
final token = await state.login(userProvider);
if (token != null) {
+ log(token);
+ await ServerDataProvider.getData();
Navigator.of(context).pushReplacementNamed(Routes.home);
}
}
diff --git a/lib/pages/authentication/screens/reset_password.dart b/lib/views/authentication/screens/reset_password.dart
similarity index 83%
rename from lib/pages/authentication/screens/reset_password.dart
rename to lib/views/authentication/screens/reset_password.dart
index 328265b..212dd2d 100644
--- a/lib/pages/authentication/screens/reset_password.dart
+++ b/lib/views/authentication/screens/reset_password.dart
@@ -1,6 +1,6 @@
-import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text_field.dart';
+import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
class ResetPassword extends StatelessWidget {
diff --git a/lib/pages/authentication/screens/username.dart b/lib/views/authentication/screens/username.dart
similarity index 92%
rename from lib/pages/authentication/screens/username.dart
rename to lib/views/authentication/screens/username.dart
index 395db9d..fcec2fd 100644
--- a/lib/pages/authentication/screens/username.dart
+++ b/lib/views/authentication/screens/username.dart
@@ -1,7 +1,7 @@
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text_field.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text_field.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/authentication/screens/verification.dart b/lib/views/authentication/screens/verification.dart
similarity index 90%
rename from lib/pages/authentication/screens/verification.dart
rename to lib/views/authentication/screens/verification.dart
index e6f5d4f..80bfeef 100644
--- a/lib/pages/authentication/screens/verification.dart
+++ b/lib/views/authentication/screens/verification.dart
@@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/authentication/widgets/authentication_app_bar.dart b/lib/views/authentication/widgets/authentication_app_bar.dart
similarity index 85%
rename from lib/pages/authentication/widgets/authentication_app_bar.dart
rename to lib/views/authentication/widgets/authentication_app_bar.dart
index e9cb490..81e86f3 100644
--- a/lib/pages/authentication/widgets/authentication_app_bar.dart
+++ b/lib/views/authentication/widgets/authentication_app_bar.dart
@@ -1,8 +1,8 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/pages/authentication/authentication_state.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/authentication/authentication_state.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/authentication/widgets/authentication_layout.dart b/lib/views/authentication/widgets/authentication_layout.dart
similarity index 92%
rename from lib/pages/authentication/widgets/authentication_layout.dart
rename to lib/views/authentication/widgets/authentication_layout.dart
index 4d063d4..e3fceca 100644
--- a/lib/pages/authentication/widgets/authentication_layout.dart
+++ b/lib/views/authentication/widgets/authentication_layout.dart
@@ -1,5 +1,5 @@
-import 'package:didvan/pages/authentication/widgets/authentication_app_bar.dart';
-import 'package:didvan/widgets/logos/didvan_horizontal_logo.dart';
+import 'package:didvan/views/authentication/widgets/authentication_app_bar.dart';
+import 'package:didvan/views/widgets/logos/didvan_horizontal_logo.dart';
import 'package:flutter/material.dart';
class AuthenticationLayout extends StatelessWidget {
diff --git a/lib/pages/home/comments/comments.dart b/lib/views/home/comments/comments.dart
similarity index 93%
rename from lib/pages/home/comments/comments.dart
rename to lib/views/home/comments/comments.dart
index ce45163..0bf0c72 100644
--- a/lib/pages/home/comments/comments.dart
+++ b/lib/views/home/comments/comments.dart
@@ -2,14 +2,14 @@ import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/comments/comments_state.dart';
-import 'package:didvan/pages/home/comments/widgets/comment_item.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/comments/comments_state.dart';
+import 'package:didvan/views/home/comments/widgets/comment_item.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/comments/comments_state.dart b/lib/views/home/comments/comments_state.dart
similarity index 100%
rename from lib/pages/home/comments/comments_state.dart
rename to lib/views/home/comments/comments_state.dart
diff --git a/lib/pages/home/comments/widgets/comment_item.dart b/lib/views/home/comments/widgets/comment_item.dart
similarity index 96%
rename from lib/pages/home/comments/widgets/comment_item.dart
rename to lib/views/home/comments/widgets/comment_item.dart
index 1230d14..62fc0a2 100644
--- a/lib/pages/home/comments/widgets/comment_item.dart
+++ b/lib/views/home/comments/widgets/comment_item.dart
@@ -2,13 +2,13 @@ import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/comment/comment.dart';
-import 'package:didvan/pages/home/comments/comments_state.dart';
import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/ink_wrapper.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
+import 'package:didvan/views/home/comments/comments_state.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/ink_wrapper.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/views/home/direct/direct.dart b/lib/views/home/direct/direct.dart
new file mode 100644
index 0000000..e3cf43e
--- /dev/null
+++ b/lib/views/home/direct/direct.dart
@@ -0,0 +1,94 @@
+import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/view/app_bar_data.dart';
+import 'package:didvan/providers/server_data_provider.dart';
+import 'package:didvan/views/home/direct/direct_state.dart';
+import 'package:didvan/views/home/direct/widgets/message.dart';
+import 'package:didvan/views/home/direct/widgets/message_box.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_spinkit/flutter_spinkit.dart';
+import 'package:provider/provider.dart';
+
+class Direct extends StatefulWidget {
+ final Map pageData;
+ const Direct({Key? key, required this.pageData}) : super(key: key);
+
+ @override
+ State createState() => _DirectState();
+}
+
+class _DirectState extends State {
+ @override
+ void initState() {
+ final state = context.read();
+ state.replyRadar = widget.pageData['radarAttachment'];
+ final typeId = ServerDataProvider.labelToTypeId(widget.pageData['type']);
+ state.typeId = typeId;
+ Future.delayed(Duration.zero, () {
+ state.getMessages();
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final state = context.watch();
+ final d = MediaQuery.of(context);
+ return Material(
+ child: Stack(
+ children: [
+ Positioned(
+ top: 0,
+ bottom: 56,
+ left: 0,
+ right: 0,
+ child: DidvanScaffold(
+ reverse: true,
+ backgroundColor: Theme.of(context).colorScheme.surface,
+ appBarData: AppBarData(
+ hasBack: true,
+ subtitle: 'ارتباط با سردبیر',
+ title: widget.pageData['type'] ?? 'پشتیبانی اپلیکیشن',
+ ),
+ slivers: [
+ if (state.appState != AppState.busy)
+ SliverPadding(
+ padding: state.replyRadar == null
+ ? EdgeInsets.zero
+ : const EdgeInsets.only(bottom: 68),
+ sliver: SliverStateHandler(
+ itemPadding: const EdgeInsets.only(bottom: 12),
+ state: state,
+ builder: (context, state, index) => Message(
+ message: state.messages[index],
+ ),
+ childCount: state.messages.length,
+ onRetry: state.getMessages,
+ ),
+ ),
+ ],
+ children: [
+ if (state.appState == AppState.busy)
+ SizedBox(
+ height: d.size.height - kToolbarHeight - d.padding.top,
+ child: Center(
+ child: SpinKitSpinningLines(
+ color: Theme.of(context).colorScheme.primary,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ Positioned(
+ bottom: d.viewInsets.bottom,
+ right: 0,
+ left: 0,
+ child: const MessageBox(),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/views/home/direct/direct_state.dart b/lib/views/home/direct/direct_state.dart
new file mode 100644
index 0000000..86cf3a9
--- /dev/null
+++ b/lib/views/home/direct/direct_state.dart
@@ -0,0 +1,134 @@
+import 'dart:io';
+
+import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/message_data/message_data.dart';
+import 'package:didvan/models/message_data/radar_attachment.dart';
+import 'package:didvan/providers/core_provider.dart';
+import 'package:didvan/services/network/request.dart';
+import 'package:didvan/services/network/request_helper.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter_vibrate/flutter_vibrate.dart';
+import 'package:record/record.dart';
+
+class DirectState extends CoreProvier {
+ final _recorder = Record();
+ final List messages = [];
+ late final int typeId;
+ final Map> dailyMessages = {};
+
+ String? text;
+ RadarAttachment? replyRadar;
+ File? recordedFile;
+ int? audioDuration;
+
+ bool isRecording = false;
+
+ Future getMessages() async {
+ appState = AppState.busy;
+ final RequestService service = RequestService(RequestHelper.direct(typeId));
+ await service.httpGet();
+ if (service.isSuccess) {
+ final messageDatas = service.result['messages'];
+ for (var i = 0; i < messageDatas.length; i++) {
+ messages.add(MessageData.fromJson(messageDatas[i]));
+ _addToDailyGrouped();
+ }
+ appState = AppState.idle;
+ return;
+ }
+ appState = AppState.failed;
+ }
+
+ void deleteRecordedFile() {
+ recordedFile!.delete();
+ recordedFile = null;
+ notifyListeners();
+ }
+
+ Future startRecording() async {
+ await _recorder.hasPermission();
+ if (!kIsWeb) {
+ Vibrate.feedback(FeedbackType.medium);
+ }
+ isRecording = true;
+ _recorder.start();
+ notifyListeners();
+ }
+
+ Future stopRecording({required bool sendImidiately}) async {
+ final path = await _recorder.stop();
+ isRecording = false;
+ if (path == null) {
+ notifyListeners();
+ return;
+ }
+ if (kIsWeb) {
+ final uri = Uri.file(path);
+ recordedFile = File.fromUri(uri);
+ } else {
+ recordedFile = File(path);
+ }
+ if (sendImidiately) {
+ await sendMessage();
+ } else {
+ notifyListeners();
+ }
+ }
+
+ void _addToDailyGrouped() {
+ final createdAt = messages.last.createdAt.split('T').first;
+ if (!dailyMessages.containsKey(createdAt)) {
+ dailyMessages.addAll({
+ createdAt: [messages.last.id]
+ });
+ } else {
+ dailyMessages[createdAt]!.add(messages.last.id);
+ }
+ }
+
+ Future sendMessage() async {
+ if ((text == null || text!.isEmpty) && recordedFile == null) return;
+ replyRadar = null;
+ messages.insert(
+ 0,
+ MessageData(
+ id: 0,
+ writedByAdmin: false,
+ readed: false,
+ createdAt:
+ DateTime.now().subtract(const Duration(minutes: 210)).toString(),
+ text: text,
+ audio: null,
+ audioFile: recordedFile,
+ radar: replyRadar,
+ audioDuration: audioDuration,
+ ),
+ );
+ _addToDailyGrouped();
+ final body = {};
+ if (text != null) {
+ body.addAll({'text': text});
+ }
+ if (replyRadar != null) {
+ body.addAll({'radarId': replyRadar!.id});
+ }
+ final uploadFile = recordedFile;
+ text = null;
+ recordedFile = null;
+ notifyListeners();
+ final service =
+ RequestService(RequestHelper.sendDirectMessage(typeId), body: body);
+ if (uploadFile == null) {
+ service.post();
+ } else {
+ service.multipart(
+ file: uploadFile,
+ method: 'POST',
+ fieldName: 'audio',
+ fileName: 'voice-message',
+ mediaExtension: 'm4a',
+ mediaFormat: 'audio',
+ );
+ }
+ }
+}
diff --git a/lib/views/home/direct/widgets/audio_widget.dart b/lib/views/home/direct/widgets/audio_widget.dart
new file mode 100644
index 0000000..5bb7ba7
--- /dev/null
+++ b/lib/views/home/direct/widgets/audio_widget.dart
@@ -0,0 +1,35 @@
+import 'dart:io';
+
+import 'package:didvan/services/media/media.dart';
+import 'package:didvan/views/home/widgets/audio_slider.dart';
+import 'package:didvan/views/home/widgets/player_controller_button.dart';
+import 'package:flutter/material.dart';
+
+class AudioWidget extends StatelessWidget {
+ final String? audioUrl;
+ final File? audioFile;
+ const AudioWidget({Key? key, this.audioUrl, this.audioFile})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return StreamBuilder(
+ stream: MediaService.audioPlayer.playingStream,
+ builder: (context, snapshot) {
+ return Row(
+ children: [
+ Expanded(
+ child: AudioSlider(
+ tag: audioUrl ?? audioFile!.path,
+ ),
+ ),
+ AudioControllerButton(
+ audioFile: audioFile,
+ audioUrl: audioUrl,
+ ),
+ ],
+ );
+ },
+ );
+ }
+}
diff --git a/lib/views/home/direct/widgets/message.dart b/lib/views/home/direct/widgets/message.dart
new file mode 100644
index 0000000..818b2ff
--- /dev/null
+++ b/lib/views/home/direct/widgets/message.dart
@@ -0,0 +1,187 @@
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/models/message_data/message_data.dart';
+import 'package:didvan/utils/date_time.dart';
+import 'package:didvan/views/home/direct/direct_state.dart';
+import 'package:didvan/views/home/direct/widgets/audio_widget.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:persian_number_utility/persian_number_utility.dart';
+
+class Message extends StatelessWidget {
+ final MessageData message;
+ const Message({Key? key, required this.message}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final firstMessageOfGroupId = context
+ .read()
+ .dailyMessages[message.createdAt.replaceAll('T', ' ').split(' ').first]!
+ .last;
+ return Column(
+ crossAxisAlignment: message.writedByAdmin
+ ? CrossAxisAlignment.end
+ : CrossAxisAlignment.start,
+ children: [
+ if (message.id == firstMessageOfGroupId)
+ Center(
+ child: Container(
+ margin: const EdgeInsets.only(bottom: 12),
+ padding: const EdgeInsets.all(4),
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.splash,
+ borderRadius: DesignConfig.lowBorderRadius,
+ ),
+ child: DidvanText(
+ DateTime.parse(message.createdAt).toPersianDateStr(),
+ style: Theme.of(context).textTheme.overline,
+ color: DesignConfig.isDark
+ ? Theme.of(context).colorScheme.white
+ : Theme.of(context).colorScheme.black,
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsets.only(
+ right: message.writedByAdmin ? 20 : 0,
+ left: !message.writedByAdmin ? 20 : 0,
+ ),
+ child: Column(
+ crossAxisAlignment: message.writedByAdmin
+ ? CrossAxisAlignment.start
+ : CrossAxisAlignment.end,
+ children: [
+ _MessageContainer(
+ writedByAdmin: message.writedByAdmin,
+ child: Column(
+ children: [
+ if (message.text != null) DidvanText(message.text!),
+ if (message.audio != null || message.audioFile != null)
+ AudioWidget(
+ audioFile: message.audioFile,
+ audioUrl: message.audio,
+ ),
+ if (message.radar != null) const DidvanDivider(),
+ if (message.radar != null) const SizedBox(height: 4),
+ if (message.radar != null)
+ _ReplyRadarOverview(message: message),
+ if (message.radar != null) const SizedBox(height: 4),
+ ],
+ ),
+ ),
+ const SizedBox(height: 4),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ DidvanText(
+ DateTimeUtils.timeWithAmPm(message.createdAt),
+ style: Theme.of(context).textTheme.overline,
+ color: Theme.of(context).colorScheme.caption,
+ ),
+ if (!message.writedByAdmin)
+ Icon(
+ message.readed
+ ? DidvanIcons.check_double_light
+ : DidvanIcons.check_light,
+ size: 16,
+ )
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _ReplyRadarOverview extends StatelessWidget {
+ final MessageData message;
+ const _ReplyRadarOverview({Key? key, required this.message})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SkeletonImage(
+ imageUrl: message.radar!.image,
+ height: 52,
+ width: 52,
+ ),
+ const SizedBox(width: 8),
+ Expanded(
+ child: SizedBox(
+ height: 52,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ DidvanText(
+ message.radar!.title,
+ style: Theme.of(context).textTheme.bodyText1,
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ Row(
+ children: [
+ DidvanText(
+ 'رادار ' + message.radar!.categories.first.label,
+ style: Theme.of(context).textTheme.overline,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ const Spacer(),
+ DidvanText(
+ DateTimeUtils.momentGenerator(message.radar!.createdAt) +
+ ' | خواندن در ' +
+ message.radar!.timeToRead.toString() +
+ ' دقیقه',
+ color: Theme.of(context).colorScheme.focusedBorder,
+ style: Theme.of(context).textTheme.overline,
+ ),
+ // DidvanText('text'),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _MessageContainer extends StatelessWidget {
+ final bool writedByAdmin;
+ final Widget child;
+ const _MessageContainer({
+ Key? key,
+ required this.writedByAdmin,
+ required this.child,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
+ decoration: BoxDecoration(
+ borderRadius: DesignConfig.mediumBorderRadius.copyWith(
+ bottomLeft: writedByAdmin ? Radius.zero : null,
+ bottomRight: !writedByAdmin ? Radius.zero : null,
+ ),
+ color: writedByAdmin ? null : Theme.of(context).colorScheme.focused,
+ border: Border.all(
+ color: Theme.of(context).colorScheme.border,
+ width: 0.5,
+ ),
+ ),
+ child: child,
+ );
+ }
+}
diff --git a/lib/views/home/direct/widgets/message_box.dart b/lib/views/home/direct/widgets/message_box.dart
new file mode 100644
index 0000000..090f409
--- /dev/null
+++ b/lib/views/home/direct/widgets/message_box.dart
@@ -0,0 +1,220 @@
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/views/home/direct/direct_state.dart';
+import 'package:didvan/views/home/direct/widgets/audio_widget.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class MessageBox extends StatelessWidget {
+ const MessageBox({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ Consumer(
+ builder: (context, state, child) => state.replyRadar != null
+ ? _MessageBoxContainer(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Row(
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const DidvanText(
+ 'لینک به مطلب:',
+ ),
+ DidvanText(
+ state.replyRadar!.title,
+ overflow: TextOverflow.ellipsis,
+ maxLines: 1,
+ color: Theme.of(context).colorScheme.primary,
+ ),
+ ],
+ ),
+ ),
+ DidvanIconButton(
+ icon: DidvanIcons.close_regular,
+ gestureSize: 24,
+ onPressed: () {
+ state.replyRadar = null;
+ state.update();
+ },
+ ),
+ ],
+ ),
+ ),
+ )
+ : const SizedBox(),
+ ),
+ _MessageBoxContainer(
+ child: Consumer(
+ builder: (context, state, child) {
+ if (state.isRecording) {
+ return const _Recording();
+ } else if (!state.isRecording && state.recordedFile != null) {
+ return const _RecordChecking();
+ }
+ return const _Typing();
+ },
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _MessageBoxContainer extends StatelessWidget {
+ final Widget child;
+ const _MessageBoxContainer({Key? key, required this.child}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: 68,
+ decoration: BoxDecoration(
+ border: Border(
+ top: BorderSide(
+ color: Theme.of(context).colorScheme.cardBorder,
+ ),
+ ),
+ color: Theme.of(context).colorScheme.surface,
+ ),
+ child: child,
+ );
+ }
+}
+
+class _Typing extends StatefulWidget {
+ const _Typing({Key? key}) : super(key: key);
+
+ @override
+ State<_Typing> createState() => _TypingState();
+}
+
+class _TypingState extends State<_Typing> {
+ final _formKey = GlobalKey();
+
+ @override
+ Widget build(BuildContext context) {
+ final state = context.read();
+ return Row(
+ children: [
+ Expanded(
+ flex: 2,
+ child: AnimatedSwitcher(
+ duration: DesignConfig.lowAnimationDuration,
+ transitionBuilder: (child, animation) => ScaleTransition(
+ scale: animation,
+ child: child,
+ ),
+ child: state.text != null && state.text!.isNotEmpty
+ ? DidvanIconButton(
+ key: const ValueKey(1),
+ icon: DidvanIcons.send_solid,
+ onPressed: () {
+ _formKey.currentState!.reset();
+ state.sendMessage();
+ },
+ size: 32,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ )
+ : DidvanIconButton(
+ key: const ValueKey(2),
+ icon: DidvanIcons.mic_solid,
+ onPressed: state.startRecording,
+ size: 32,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ ),
+ ),
+ Expanded(
+ flex: 15,
+ child: Form(
+ key: _formKey,
+ child: TextFormField(
+ textInputAction: TextInputAction.send,
+ style: Theme.of(context).textTheme.bodyText2,
+ decoration: InputDecoration(
+ border: InputBorder.none,
+ hintText: 'بنویسید یا پیام صوتی بگذارید...',
+ hintStyle: Theme.of(context).textTheme.caption!.copyWith(
+ color: Theme.of(context).colorScheme.disabledText),
+ ),
+ onChanged: (value) {
+ if (value.length <= 1) {
+ setState(() {});
+ }
+ state.text = value;
+ },
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class _Recording extends StatelessWidget {
+ const _Recording({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final state = context.read();
+ return Row(
+ children: [
+ DidvanIconButton(
+ icon: DidvanIcons.send_solid,
+ onPressed: () => state.stopRecording(sendImidiately: true),
+ gestureSize: 52,
+ ),
+ Expanded(
+ child: DidvanText(
+ 'در حال ضبط صدا ...',
+ style: Theme.of(context).textTheme.caption,
+ ),
+ ),
+ DidvanIconButton(
+ icon: DidvanIcons.stop_circle_solid,
+ color: Theme.of(context).colorScheme.secondary,
+ onPressed: () => state.stopRecording(sendImidiately: false),
+ size: 32,
+ ),
+ ],
+ );
+ }
+}
+
+class _RecordChecking extends StatelessWidget {
+ const _RecordChecking({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final state = context.read();
+ return Row(
+ children: [
+ DidvanIconButton(
+ icon: DidvanIcons.send_solid,
+ onPressed: state.sendMessage,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ Expanded(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: AudioWidget(audioFile: state.recordedFile!),
+ ),
+ ),
+ DidvanIconButton(
+ icon: DidvanIcons.trash_solid,
+ color: Theme.of(context).colorScheme.secondary,
+ onPressed: state.deleteRecordedFile,
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/views/home/hashtag/hashtag.dart b/lib/views/home/hashtag/hashtag.dart
new file mode 100644
index 0000000..eb95e99
--- /dev/null
+++ b/lib/views/home/hashtag/hashtag.dart
@@ -0,0 +1,60 @@
+import 'package:didvan/models/tag.dart';
+import 'package:didvan/models/view/app_bar_data.dart';
+import 'package:didvan/views/home/hashtag/hashtag_state.dart';
+import 'package:didvan/views/home/widgets/news_overview.dart';
+import 'package:didvan/views/home/widgets/radar_overview.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class Hashtag extends StatefulWidget {
+ final Tag tag;
+ const Hashtag({Key? key, required this.tag}) : super(key: key);
+
+ @override
+ _HashtagState createState() => _HashtagState();
+}
+
+class _HashtagState extends State {
+ @override
+ void initState() {
+ final state = context.read();
+ state.id = widget.tag.id;
+ Future.delayed(Duration.zero, () => state.getTagItems(page: 1));
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return DidvanScaffold(
+ appBarData: AppBarData(title: widget.tag.label, hasBack: true),
+ slivers: [
+ Consumer(
+ builder: (context, state, child) => SliverStateHandler(
+ state: state,
+ builder: (context, state, index) {
+ final item = state.items[index];
+ final type = item.type;
+ if (type == 'radar') {
+ return RadarOverview(
+ radar: item,
+ onCommentsChanged: (id, count) => item.comments = count,
+ onMarkChanged: (id, value) => item.marked = value,
+ );
+ } else if (type == 'news') {
+ return NewsOverview(
+ news: item,
+ onMarkChanged: (id, value) => item.marked = value,
+ );
+ }
+ return Container();
+ },
+ childCount: state.items.length,
+ onRetry: () {},
+ ),
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/views/home/hashtag/hashtag_state.dart b/lib/views/home/hashtag/hashtag_state.dart
new file mode 100644
index 0000000..3dcb2f3
--- /dev/null
+++ b/lib/views/home/hashtag/hashtag_state.dart
@@ -0,0 +1,34 @@
+import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/overview_data.dart';
+import 'package:didvan/providers/core_provider.dart';
+import 'package:didvan/services/network/request.dart';
+import 'package:didvan/services/network/request_helper.dart';
+
+class HashtagState extends CoreProvier {
+ final List items = [];
+
+ late final int id;
+ int page = 1;
+
+ Future getTagItems({required int page}) async {
+ this.page = page;
+ if (this.page == 1) {
+ appState = AppState.busy;
+ }
+ final service = RequestService(RequestHelper.tag(
+ ids: [id],
+ limit: 15,
+ page: page,
+ ));
+ await service.httpGet();
+ if (service.isSuccess) {
+ final contents = service.result['contents'];
+ for (var i = 0; i < contents.length; i++) {
+ items.add(OverviewData.fromJson(contents[i]));
+ }
+ appState = AppState.idle;
+ return;
+ }
+ appState = AppState.failed;
+ }
+}
diff --git a/lib/pages/home/home.dart b/lib/views/home/home.dart
similarity index 78%
rename from lib/pages/home/home.dart
rename to lib/views/home/home.dart
index 880e84a..0e1d5a8 100644
--- a/lib/pages/home/home.dart
+++ b/lib/views/home/home.dart
@@ -1,11 +1,11 @@
import 'package:didvan/config/design_config.dart';
-import 'package:didvan/pages/home/home_state.dart';
-import 'package:didvan/pages/home/news/news.dart';
-import 'package:didvan/pages/home/radar/radar.dart';
-import 'package:didvan/pages/home/settings/settings.dart';
-import 'package:didvan/pages/home/statistics/statistics.dart';
-import 'package:didvan/pages/home/studio/studio.dart';
-import 'package:didvan/pages/home/widgets/bnb.dart';
+import 'package:didvan/views/home/home_state.dart';
+import 'package:didvan/views/home/news/news.dart';
+import 'package:didvan/views/home/radar/radar.dart';
+import 'package:didvan/views/home/settings/settings.dart';
+import 'package:didvan/views/home/statistics/statistics.dart';
+import 'package:didvan/views/home/studio/studio.dart';
+import 'package:didvan/views/home/widgets/bnb.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/home_state.dart b/lib/views/home/home_state.dart
similarity index 100%
rename from lib/pages/home/home_state.dart
rename to lib/views/home/home_state.dart
diff --git a/lib/pages/home/news/news.dart b/lib/views/home/news/news.dart
similarity index 82%
rename from lib/pages/home/news/news.dart
rename to lib/views/home/news/news.dart
index 2adeb13..df3950e 100644
--- a/lib/pages/home/news/news.dart
+++ b/lib/views/home/news/news.dart
@@ -4,15 +4,15 @@ import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
-import 'package:didvan/pages/home/news/news_state.dart';
-import 'package:didvan/pages/home/widgets/news_overview.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/pages/home/widgets/date_picker_button.dart';
-import 'package:didvan/widgets/item_title.dart';
-import 'package:didvan/pages/home/widgets/search_field.dart';
-import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
-import 'package:didvan/widgets/state_handlers/empty_result.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/news/news_state.dart';
+import 'package:didvan/views/home/widgets/date_picker_button.dart';
+import 'package:didvan/views/home/widgets/logo_app_bar.dart';
+import 'package:didvan/views/home/widgets/news_overview.dart';
+import 'package:didvan/views/home/widgets/search_field.dart';
+import 'package:didvan/views/widgets/item_title.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_result.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -55,6 +55,14 @@ class _NewsState extends State {
onRetry: () => state.getNews(page: state.page),
state: state,
builder: (context, state, index) {
+ index += 2;
+ if (index % 15 == 0 && index / 15 >= state.page) {
+ state.getNews(page: index ~/ 15 + 1);
+ }
+ index -= 2;
+ if (index >= state.news.length) {
+ return NewsOverview.placeholder;
+ }
final news = state.news[index];
return NewsOverview(
news: news,
@@ -71,7 +79,8 @@ class _NewsState extends State {
emptyState: EmptyResult(
onNewSearch: () => _focusNode.requestFocus(),
),
- childCount: state.news.length,
+ childCount:
+ state.news.length + (state.lastPage == state.page ? 0 : 3),
itemPadding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
placeholder: NewsOverview.placeholder,
),
diff --git a/lib/pages/home/news/news_details/news_details.dart b/lib/views/home/news/news_details/news_details.dart
similarity index 67%
rename from lib/pages/home/news/news_details/news_details.dart
rename to lib/views/home/news/news_details/news_details.dart
index 9b55a2d..55d09d4 100644
--- a/lib/pages/home/news/news_details/news_details.dart
+++ b/lib/views/home/news/news_details/news_details.dart
@@ -1,8 +1,8 @@
import 'package:didvan/models/requests/news.dart';
-import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
-import 'package:didvan/widgets/didvan/page_view.dart';
-import 'package:didvan/pages/home/widgets/floating_navigation_bar.dart';
-import 'package:didvan/widgets/state_handlers/state_handler.dart';
+import 'package:didvan/views/home/news/news_details/news_details_state.dart';
+import 'package:didvan/views/home/widgets/floating_navigation_bar.dart';
+import 'package:didvan/views/widgets/didvan/page_view.dart';
+import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -20,6 +20,13 @@ class _NewsDetailsState extends State {
@override
void initState() {
final state = context.read();
+ _scrollController.addListener(() {
+ if (_scrollController.position.pixels >
+ _scrollController.position.maxScrollExtent - 200 &&
+ !state.relatedQueue.contains(state.currentNews.id)) {
+ state.getRelatedContents();
+ }
+ });
state.args = widget.pageData['args'] ?? const NewsRequestArgs(page: 0);
Future.delayed(Duration.zero, () {
state.getNewsDetails(widget.pageData['id']);
@@ -37,13 +44,16 @@ class _NewsDetailsState extends State {
builder: (context, state) => Stack(
children: [
if (state.news.isNotEmpty)
- DidvanPageView(
- isRadar: false,
- initialIndex: state.initialIndex,
- onPageChanged: _onPageChnaged,
- scrollController: _scrollController,
- items: state.news,
- currentIndex: state.currentIndex,
+ IgnorePointer(
+ ignoring: state.isFetchingNewItem,
+ child: DidvanPageView(
+ isRadar: false,
+ initialIndex: state.initialIndex,
+ onPageChanged: _onPageChnaged,
+ scrollController: _scrollController,
+ items: state.news,
+ currentIndex: state.currentIndex,
+ ),
),
if (state.news.isNotEmpty)
Positioned(
@@ -54,10 +64,7 @@ class _NewsDetailsState extends State {
hasUnmarkConfirmation:
widget.pageData['hasUnmarkConfirmation'],
scrollController: _scrollController,
- comments: state.currentNews.comments,
- id: state.currentNews.id,
- marked: state.currentNews.marked,
- title: state.currentNews.title,
+ item: state.currentNews,
onCommentsChanged: state.onCommentsChanged,
onMarkChanged: (value) => widget.pageData['onMarkChanged'](
state.currentNews.id,
diff --git a/lib/pages/home/news/news_details/news_details_state.dart b/lib/views/home/news/news_details/news_details_state.dart
similarity index 75%
rename from lib/pages/home/news/news_details/news_details_state.dart
rename to lib/views/home/news/news_details/news_details_state.dart
index ba97db3..879a178 100644
--- a/lib/pages/home/news/news_details/news_details_state.dart
+++ b/lib/views/home/news/news_details/news_details_state.dart
@@ -3,6 +3,7 @@ import 'dart:math';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/news_details_data.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/network/request.dart';
@@ -14,6 +15,8 @@ class NewsDetailsState extends CoreProvier {
late final NewsRequestArgs args;
late Timer _trackingTimer;
int _trackingTimerCounter = 0;
+ bool isFetchingNewItem = false;
+ final List relatedQueue = [];
int _currentIndex = 0;
int get currentIndex => _currentIndex;
@@ -23,6 +26,9 @@ class NewsDetailsState extends CoreProvier {
Future getNewsDetails(int id, {bool? isForward}) async {
if (isForward == null) {
appState = AppState.busy;
+ } else {
+ isFetchingNewItem = true;
+ notifyListeners();
}
final service = RequestService(RequestHelper.newsDetails(id, args));
await service.httpGet();
@@ -65,6 +71,7 @@ class NewsDetailsState extends CoreProvier {
}
_currentIndex--;
}
+ isFetchingNewItem = false;
appState = AppState.idle;
return;
}
@@ -92,6 +99,28 @@ class NewsDetailsState extends CoreProvier {
_trackingTimerCounter = 0;
}
+ Future getRelatedContents() async {
+ if (currentNews.relatedContents.isNotEmpty) return;
+ relatedQueue.add(currentNews.id);
+ final service = RequestService(RequestHelper.tag(
+ ids: currentNews.tags.map((tag) => tag.id).toList(),
+ itemId: currentNews.id,
+ type: 'news',
+ ));
+ await service.httpGet();
+ if (service.isSuccess) {
+ final relateds = service.result['contents'];
+ for (var i = 0; i < relateds.length; i++) {
+ news
+ .where((element) => element != null)
+ .firstWhere((element) => element!.id == currentNews.id)!
+ .relatedContents
+ .add(OverviewData.fromJson(relateds[i]));
+ }
+ notifyListeners();
+ }
+ }
+
@override
void dispose() {
_trackingTimer.cancel();
diff --git a/lib/pages/home/news/news_state.dart b/lib/views/home/news/news_state.dart
similarity index 84%
rename from lib/pages/home/news/news_state.dart
rename to lib/views/home/news/news_state.dart
index 2c54cef..47f3366 100644
--- a/lib/pages/home/news/news_state.dart
+++ b/lib/views/home/news/news_state.dart
@@ -1,5 +1,5 @@
import 'package:didvan/models/enums.dart';
-import 'package:didvan/models/news_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/providers/user_provider.dart';
@@ -12,8 +12,9 @@ class NewsState extends CoreProvier {
String? startDate;
String? endDate;
int page = 1;
+ int lastPage = 0;
- final List news = [];
+ final List news = [];
void init() {
search = '';
@@ -34,19 +35,21 @@ class NewsState extends CoreProvier {
Future getNews({
required int page,
}) async {
- if (this.page == page) {
+ this.page = page;
+ if (this.page == 1) {
news.clear();
}
- this.page = page;
if (search != '') {
lastSearch = search;
}
lastSearch = search;
- appState = AppState.busy;
+ if (page == 1) {
+ appState = AppState.busy;
+ }
final service = RequestService(
RequestHelper.newsOverviews(
args: NewsRequestArgs(
- page: 1,
+ page: page,
startDate: startDate?.split(' ').first,
endDate: endDate?.split(' ').first,
search: search == '' ? null : search,
@@ -55,9 +58,10 @@ class NewsState extends CoreProvier {
);
await service.httpGet();
if (service.isSuccess) {
+ lastPage = service.result['lastPage'];
final newsList = service.result['news'];
for (var i = 0; i < newsList.length; i++) {
- news.add(NewsOverviewData.fromJson(newsList[i]));
+ news.add(OverviewData.fromJson(newsList[i]));
}
appState = AppState.idle;
return;
diff --git a/lib/pages/home/radar/radar.dart b/lib/views/home/radar/radar.dart
similarity index 85%
rename from lib/pages/home/radar/radar.dart
rename to lib/views/home/radar/radar.dart
index a6bbf3b..0c97ddb 100644
--- a/lib/pages/home/radar/radar.dart
+++ b/lib/views/home/radar/radar.dart
@@ -9,20 +9,20 @@ import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
-import 'package:didvan/pages/home/radar/radar_state.dart';
-import 'package:didvan/pages/home/radar/widgets/categories_gird.dart';
-import 'package:didvan/pages/home/radar/widgets/categories_list.dart';
-import 'package:didvan/pages/home/widgets/radar_overview.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/pages/home/widgets/search_field.dart';
-import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
+import 'package:didvan/views/home/radar/radar_state.dart';
+import 'package:didvan/views/home/radar/widgets/categories_gird.dart';
+import 'package:didvan/views/home/radar/widgets/categories_list.dart';
+import 'package:didvan/views/home/widgets/date_picker_button.dart';
+import 'package:didvan/views/home/widgets/logo_app_bar.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/pages/home/widgets/date_picker_button.dart';
-import 'package:didvan/widgets/didvan/checkbox.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/item_title.dart';
-import 'package:didvan/widgets/state_handlers/empty_result.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/widgets/radar_overview.dart';
+import 'package:didvan/views/home/widgets/search_field.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/checkbox.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/item_title.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_result.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -113,7 +113,7 @@ class _RadarState extends State {
),
),
SliverStateHandler(
- onRetry: () => state.getRadarOverviewDatas(page: state.page),
+ onRetry: () => state.getRadars(page: state.page),
state: state,
itemPadding: const EdgeInsets.only(
bottom: 20,
@@ -128,6 +128,14 @@ class _RadarState extends State {
),
placeholder: RadarOverview.placeholder,
builder: (context, state, index) {
+ index += 2;
+ if (index % 15 == 0 && index / 15 >= state.page) {
+ state.getRadars(page: index ~/ 15 + 1);
+ }
+ index -= 2;
+ if (index >= state.radars.length) {
+ return RadarOverview.placeholder;
+ }
final radar = state.radars[index];
return RadarOverview(
radar: radar,
@@ -145,7 +153,8 @@ class _RadarState extends State {
),
);
},
- childCount: state.radars.length,
+ childCount: state.radars.length +
+ (state.lastPage == state.page ? 0 : 3),
),
if (state.radars.length == 1)
const SliverToBoxAdapter(
@@ -155,7 +164,9 @@ class _RadarState extends State {
),
if (state.appState != AppState.failed) CategoriesRow1(),
if (state.appState != AppState.failed) CategoriesRow2(),
- if (state.appState != AppState.failed && !state.searching)
+ if (state.appState != AppState.failed &&
+ !state.searching &&
+ !state.filtering)
CategoriesList(),
],
),
@@ -170,7 +181,7 @@ class _RadarState extends State {
_timer?.cancel();
_timer = Timer(const Duration(seconds: 1), () {
state.search = value;
- state.getRadarOverviewDatas(page: 1);
+ state.getRadars(page: 1);
});
}
@@ -215,7 +226,7 @@ class _RadarState extends State {
dismissTitle: 'حذف فیلتر',
confrimTitle: 'نمایش نتایج',
onDismissed: () => state.resetFilters(false),
- onConfirmed: () => state.getRadarOverviewDatas(page: 1),
+ onConfirmed: () => state.getRadars(page: 1),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
diff --git a/lib/pages/home/radar/radar_details/radar_details.dart b/lib/views/home/radar/radar_details/radar_details.dart
similarity index 70%
rename from lib/pages/home/radar/radar_details/radar_details.dart
rename to lib/views/home/radar/radar_details/radar_details.dart
index 6b27000..1c9eb11 100644
--- a/lib/pages/home/radar/radar_details/radar_details.dart
+++ b/lib/views/home/radar/radar_details/radar_details.dart
@@ -1,8 +1,8 @@
import 'package:didvan/models/requests/radar.dart';
-import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart';
-import 'package:didvan/widgets/didvan/page_view.dart';
-import 'package:didvan/pages/home/widgets/floating_navigation_bar.dart';
-import 'package:didvan/widgets/state_handlers/state_handler.dart';
+import 'package:didvan/views/home/radar/radar_details/radar_details_state.dart';
+import 'package:didvan/views/home/widgets/floating_navigation_bar.dart';
+import 'package:didvan/views/widgets/didvan/page_view.dart';
+import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -20,6 +20,13 @@ class _RadarDetailsState extends State {
@override
void initState() {
final state = context.read();
+ _scrollController.addListener(() {
+ if (_scrollController.position.pixels >
+ _scrollController.position.maxScrollExtent - 200 &&
+ !state.relatedQueue.contains(state.currentRadar.id)) {
+ state.getRelatedContents();
+ }
+ });
state.args = widget.pageData['args'] ?? const RadarRequestArgs(page: 0);
Future.delayed(Duration.zero, () {
state.getRadarDetails(widget.pageData['id']);
@@ -37,13 +44,16 @@ class _RadarDetailsState extends State {
builder: (context, state) => Stack(
children: [
if (state.radars.isNotEmpty)
- DidvanPageView(
- isRadar: true,
- initialIndex: state.initialIndex,
- onPageChanged: _onPageChanged,
- scrollController: _scrollController,
- items: state.radars,
- currentIndex: state.currentIndex,
+ IgnorePointer(
+ ignoring: state.isFetchingNewItem,
+ child: DidvanPageView(
+ isRadar: true,
+ initialIndex: state.initialIndex,
+ onPageChanged: _onPageChanged,
+ scrollController: _scrollController,
+ items: state.radars,
+ currentIndex: state.currentIndex,
+ ),
),
if (state.radars.isNotEmpty)
Positioned(
@@ -53,18 +63,14 @@ class _RadarDetailsState extends State {
child: FloatingNavigationBar(
hasUnmarkConfirmation:
widget.pageData['hasUnmarkConfirmation'],
- comments: state.currentRadar.comments,
- id: state.currentRadar.id,
isRadar: true,
- marked: state.currentRadar.marked,
- title: state.currentRadar.title,
+ scrollController: _scrollController,
onMarkChanged: (value) =>
widget.pageData['onMarkChanged']?.call(
state.currentRadar.id,
value,
),
- categories: state.currentRadar.categories,
- scrollController: _scrollController,
+ item: state.currentRadar,
onCommentsChanged: (count) {
state.onCommentsChanged(count);
widget.pageData['onCommentsChanged']?.call(
diff --git a/lib/pages/home/radar/radar_details/radar_details_state.dart b/lib/views/home/radar/radar_details/radar_details_state.dart
similarity index 76%
rename from lib/pages/home/radar/radar_details/radar_details_state.dart
rename to lib/views/home/radar/radar_details/radar_details_state.dart
index 61f9ccf..1e6c4e8 100644
--- a/lib/pages/home/radar/radar_details/radar_details_state.dart
+++ b/lib/views/home/radar/radar_details/radar_details_state.dart
@@ -2,11 +2,13 @@ import 'dart:async';
import 'dart:math';
import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/radar_details_data.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
+import 'package:flutter/material.dart';
class RadarDetailsState extends CoreProvier {
final List radars = [];
@@ -14,6 +16,8 @@ class RadarDetailsState extends CoreProvier {
int _trackingTimerCounter = 0;
late final int initialIndex;
late final RadarRequestArgs args;
+ bool isFetchingNewItem = false;
+ final List relatedQueue = [];
int _currentIndex = 0;
int get currentIndex => _currentIndex;
@@ -29,6 +33,9 @@ class RadarDetailsState extends CoreProvier {
Future getRadarDetails(int id, {bool? isForward}) async {
if (isForward == null) {
appState = AppState.busy;
+ } else {
+ isFetchingNewItem = true;
+ notifyListeners();
}
final service = RequestService(RequestHelper.radarDetails(id, args));
await service.httpGet();
@@ -74,6 +81,7 @@ class RadarDetailsState extends CoreProvier {
}
_currentIndex--;
}
+ isFetchingNewItem = false;
appState = AppState.idle;
return;
}
@@ -83,6 +91,28 @@ class RadarDetailsState extends CoreProvier {
}
}
+ Future getRelatedContents() async {
+ if (currentRadar.relatedContents.isNotEmpty) return;
+ relatedQueue.add(currentRadar.id);
+ final service = RequestService(RequestHelper.tag(
+ ids: currentRadar.tags.map((tag) => tag.id).toList(),
+ itemId: currentRadar.id,
+ type: 'radar',
+ ));
+ await service.httpGet();
+ if (service.isSuccess) {
+ final relateds = service.result['contents'];
+ for (var i = 0; i < relateds.length; i++) {
+ radars
+ .where((element) => element != null)
+ .firstWhere((element) => element!.id == currentRadar.id)!
+ .relatedContents
+ .add(OverviewData.fromJson(relateds[i]));
+ }
+ notifyListeners();
+ }
+ }
+
bool exists(RadarDetailsData? radar) =>
radars.any((r) => radar != null && r != null && r.id == radar.id);
diff --git a/lib/pages/home/radar/radar_state.dart b/lib/views/home/radar/radar_state.dart
similarity index 87%
rename from lib/pages/home/radar/radar_state.dart
rename to lib/views/home/radar/radar_state.dart
index dd3fe11..75318ee 100644
--- a/lib/pages/home/radar/radar_state.dart
+++ b/lib/views/home/radar/radar_state.dart
@@ -1,8 +1,8 @@
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/view/radar_category.dart';
-import 'package:didvan/models/radar_overview.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/services/network/request.dart';
@@ -14,11 +14,12 @@ class RadarState extends CoreProvier {
String? startDate;
String? endDate;
int page = 1;
+ int lastPage = 1;
bool isScrolled = false;
bool shouldColapse = false;
final List selectedCats = [];
List categories = [];
- final List radars = [];
+ final List radars = [];
bool get filtering =>
selectedCats.length > 1 || startDate != null || endDate != null;
@@ -38,19 +39,21 @@ class RadarState extends CoreProvier {
lastSearch = '';
isScrolled = false;
if (!isInit) {
- notifyListeners();
+ getRadars(page: 1);
}
}
- Future getRadarOverviewDatas({
+ Future getRadars({
required int page,
}) async {
+ this.page = page;
if (this.page == page) {
radars.clear();
}
- this.page = page;
lastSearch = search;
- appState = AppState.busy;
+ if (page == 1) {
+ appState = AppState.busy;
+ }
final RequestService service = RequestService(
RequestHelper.radarOverviews(
args: RadarRequestArgs(
@@ -64,8 +67,10 @@ class RadarState extends CoreProvier {
);
await service.httpGet();
if (service.isSuccess) {
- for (var i = 0; i < service.result['radars'].length; i++) {
- radars.add(RadarOverviewData.fromJson(service.result['radars'][i]));
+ lastPage = service.result['lastPage'];
+ final radarsList = service.result['radars'];
+ for (var i = 0; i < radarsList.length; i++) {
+ radars.add(OverviewData.fromJson(radarsList[i]));
}
if (searching || filtering || isColapsed || isCategorySelected) {
shouldColapse = true;
@@ -91,7 +96,7 @@ class RadarState extends CoreProvier {
void init() {
resetFilters(true);
Future.delayed(Duration.zero, () {
- getRadarOverviewDatas(page: 1);
+ getRadars(page: 1);
});
categories = [
RadarCategory(
diff --git a/lib/pages/home/radar/widgets/categories_gird.dart b/lib/views/home/radar/widgets/categories_gird.dart
similarity index 94%
rename from lib/pages/home/radar/widgets/categories_gird.dart
rename to lib/views/home/radar/widgets/categories_gird.dart
index 9818b02..abcc0e2 100644
--- a/lib/pages/home/radar/widgets/categories_gird.dart
+++ b/lib/views/home/radar/widgets/categories_gird.dart
@@ -1,6 +1,6 @@
import 'package:didvan/config/design_config.dart';
-import 'package:didvan/pages/home/radar/radar_state.dart';
-import 'package:didvan/pages/home/radar/widgets/category_item.dart';
+import 'package:didvan/views/home/radar/radar_state.dart';
+import 'package:didvan/views/home/radar/widgets/category_item.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/radar/widgets/categories_list.dart b/lib/views/home/radar/widgets/categories_list.dart
similarity index 95%
rename from lib/pages/home/radar/widgets/categories_list.dart
rename to lib/views/home/radar/widgets/categories_list.dart
index 6546c61..bca0187 100644
--- a/lib/pages/home/radar/widgets/categories_list.dart
+++ b/lib/views/home/radar/widgets/categories_list.dart
@@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/view/radar_category.dart';
-import 'package:didvan/pages/home/radar/radar_state.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/home/radar/radar_state.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -98,7 +98,7 @@ class _CategoriesListState extends State {
duration: DesignConfig.lowAnimationDuration,
curve: Curves.easeIn,
);
- state.getRadarOverviewDatas(page: 1);
+ state.getRadars(page: 1);
},
child: Container(
margin: const EdgeInsets.only(left: 12),
diff --git a/lib/pages/home/radar/widgets/category_item.dart b/lib/views/home/radar/widgets/category_item.dart
similarity index 91%
rename from lib/pages/home/radar/widgets/category_item.dart
rename to lib/views/home/radar/widgets/category_item.dart
index f545396..f8176a5 100644
--- a/lib/pages/home/radar/widgets/category_item.dart
+++ b/lib/views/home/radar/widgets/category_item.dart
@@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/view/radar_category.dart';
-import 'package:didvan/pages/home/radar/radar_state.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/home/radar/radar_state.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
@@ -29,7 +29,7 @@ class CategoryItem extends StatelessWidget {
if (category.id != 0) {
state.selectedCats.add(category);
}
- state.getRadarOverviewDatas(page: 1);
+ state.getRadars(page: 1);
},
child: AnimatedContainer(
duration: DesignConfig.mediumAnimationDuration,
diff --git a/lib/pages/home/settings/about_us/about_us.dart b/lib/views/home/settings/about_us/about_us.dart
similarity index 95%
rename from lib/pages/home/settings/about_us/about_us.dart
rename to lib/views/home/settings/about_us/about_us.dart
index 037057d..6cc17f9 100644
--- a/lib/pages/home/settings/about_us/about_us.dart
+++ b/lib/views/home/settings/about_us/about_us.dart
@@ -1,6 +1,6 @@
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class AboutUs extends StatelessWidget {
diff --git a/lib/pages/home/settings/bookmarks/bookmark_state.dart b/lib/views/home/settings/bookmarks/bookmark_state.dart
similarity index 95%
rename from lib/pages/home/settings/bookmarks/bookmark_state.dart
rename to lib/views/home/settings/bookmarks/bookmark_state.dart
index 5786b50..1807179 100644
--- a/lib/pages/home/settings/bookmarks/bookmark_state.dart
+++ b/lib/views/home/settings/bookmarks/bookmark_state.dart
@@ -1,5 +1,5 @@
import 'package:didvan/models/enums.dart';
-import 'package:didvan/models/item_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/services/network/request.dart';
@@ -36,7 +36,7 @@ class BookmarksState extends CoreProvier {
if (value) return;
final type = bookmarks.firstWhere((element) => element.id == id).type;
switch (type) {
- case 'radars':
+ case 'radar':
UserProvider.changeRadarMark(id, value);
break;
case 'news':
diff --git a/lib/pages/home/settings/bookmarks/bookmarks.dart b/lib/views/home/settings/bookmarks/bookmarks.dart
similarity index 82%
rename from lib/pages/home/settings/bookmarks/bookmarks.dart
rename to lib/views/home/settings/bookmarks/bookmarks.dart
index 6d1474a..1cb736a 100644
--- a/lib/pages/home/settings/bookmarks/bookmarks.dart
+++ b/lib/views/home/settings/bookmarks/bookmarks.dart
@@ -3,19 +3,19 @@ import 'dart:async';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/pages/home/widgets/multitype_overview.dart';
-import 'package:didvan/pages/home/widgets/search_field.dart';
-import 'package:didvan/widgets/item_title.dart';
-import 'package:didvan/widgets/state_handlers/empty_list.dart';
-import 'package:didvan/widgets/state_handlers/empty_result.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/settings/bookmarks/bookmark_state.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/home/widgets/multitype_overview.dart';
+import 'package:didvan/views/home/widgets/search_field.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/item_title.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_list.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_result.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -60,7 +60,7 @@ class _BookmarksState extends State {
child: Column(
children: [
MenuItem(
- onTap: () => _onCategorySelected('radars'),
+ onTap: () => _onCategorySelected('radar'),
title: 'تحلیلهای رادار',
icon: DidvanIcons.radar_regular,
iconSize: 24,
@@ -122,7 +122,7 @@ class _BookmarksState extends State {
}
void _onCategorySelected(String type) {
- if (type != 'radars' && type != 'news') return;
+ if (type != 'radar' && type != 'news') return;
FocusScope.of(context).unfocus();
Navigator.of(context).pushNamed(Routes.filteredBookmarks, arguments: type);
}
diff --git a/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart b/lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart
similarity index 75%
rename from lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart
rename to lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart
index ac5bee1..f9a5454 100644
--- a/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart
+++ b/lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart
@@ -1,12 +1,10 @@
-import 'package:didvan/models/news_overview.dart';
-import 'package:didvan/models/radar_overview.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
-import 'package:didvan/pages/home/widgets/news_overview.dart';
-import 'package:didvan/pages/home/widgets/radar_overview.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/state_handlers/empty_list.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
+import 'package:didvan/views/home/widgets/news_overview.dart';
+import 'package:didvan/views/home/widgets/radar_overview.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_list.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@@ -29,13 +27,13 @@ class _FilteredBookmarksState extends State {
String get _appBarTitle {
switch (context.read().type) {
- case 'radars':
+ case 'radar':
return 'تحلیلهای رادار';
case 'news':
return 'اخبار';
- case 'videos':
+ case 'video':
return 'ویدئوها';
- case 'podcasts':
+ case 'podcast':
return 'پادکستها';
default:
return 'پادکستها';
@@ -56,16 +54,16 @@ class _FilteredBookmarksState extends State {
placeholder: RadarOverview.placeholder,
emptyState: const EmptyList(),
builder: (context, state, index) {
- if (state.type == 'radars') {
+ if (state.type == 'radar') {
return RadarOverview(
- radar: state.bookmarks[index] as RadarOverviewData,
+ radar: state.bookmarks[index],
onMarkChanged: _onBookmarkChanged,
onCommentsChanged: state.onCommentsChanged,
hasUnmarkConfirmation: true,
);
}
return NewsOverview(
- news: state.bookmarks[index] as NewsOverviewData,
+ news: state.bookmarks[index],
onMarkChanged: _onBookmarkChanged,
hasUnmarkConfirmation: true,
);
diff --git a/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart b/lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart
similarity index 66%
rename from lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart
rename to lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart
index ff5d20b..fffd1dc 100644
--- a/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart
+++ b/lib/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart
@@ -1,7 +1,5 @@
import 'package:didvan/models/enums.dart';
-import 'package:didvan/models/item_overview.dart';
-import 'package:didvan/models/news_overview.dart';
-import 'package:didvan/models/radar_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/services/network/request.dart';
@@ -22,20 +20,14 @@ class FilteredBookmarksState extends CoreProvier {
lastSearch = search;
}
appState = AppState.busy;
- final service = RequestService(
- RequestHelper.bookmarks(type: type == 'radars' ? 'radar' : type));
+ final service = RequestService(RequestHelper.bookmarks(type: type));
await service.httpGet();
if (service.isSuccess) {
- final marks = service.result[type];
+ final marks = service.result[type != 'news' ? type + 's' : type];
bookmarks.clear();
for (var i = 0; i < marks.length; i++) {
- if (type == 'radars') {
- bookmarks.add(RadarOverviewData.fromJson(marks[i]));
- }
- if (type == 'news') {
- bookmarks.add(NewsOverviewData.fromJson(marks[i]));
- }
+ bookmarks.add(OverviewData.fromJson(marks[i]));
}
appState = AppState.idle;
return;
@@ -45,7 +37,7 @@ class FilteredBookmarksState extends CoreProvier {
void onMarkChanged(int id, bool value) {
switch (type) {
- case 'radars':
+ case 'radar':
UserProvider.changeRadarMark(id, value);
break;
case 'news':
@@ -58,8 +50,7 @@ class FilteredBookmarksState extends CoreProvier {
}
void onCommentsChanged(int id, int value) {
- (bookmarks.firstWhere((radar) => radar.id == id) as RadarOverviewData)
- .comments = value;
+ bookmarks.firstWhere((radar) => radar.id == id).comments = value;
notifyListeners();
}
}
diff --git a/lib/pages/home/settings/direct_list/direct_list.dart b/lib/views/home/settings/direct_list/direct_list.dart
similarity index 84%
rename from lib/pages/home/settings/direct_list/direct_list.dart
rename to lib/views/home/settings/direct_list/direct_list.dart
index 5a13fc4..7c8d264 100644
--- a/lib/pages/home/settings/direct_list/direct_list.dart
+++ b/lib/views/home/settings/direct_list/direct_list.dart
@@ -1,13 +1,13 @@
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
-import 'package:didvan/pages/home/settings/direct_list/widgets/chat_room_item.dart';
-import 'package:didvan/widgets/didvan/badge.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
-import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart';
+import 'package:didvan/views/home/settings/direct_list/direct_list_state.dart';
+import 'package:didvan/views/home/settings/direct_list/widgets/direct_item.dart';
+import 'package:didvan/views/widgets/didvan/badge.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
+import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/settings/direct_list/direct_list_state.dart b/lib/views/home/settings/direct_list/direct_list_state.dart
similarity index 100%
rename from lib/pages/home/settings/direct_list/direct_list_state.dart
rename to lib/views/home/settings/direct_list/direct_list_state.dart
diff --git a/lib/pages/home/settings/direct_list/widgets/chat_room_item.dart b/lib/views/home/settings/direct_list/widgets/direct_item.dart
similarity index 56%
rename from lib/pages/home/settings/direct_list/widgets/chat_room_item.dart
rename to lib/views/home/settings/direct_list/widgets/direct_item.dart
index 16f3215..6aa9a45 100644
--- a/lib/pages/home/settings/direct_list/widgets/chat_room_item.dart
+++ b/lib/views/home/settings/direct_list/widgets/direct_item.dart
@@ -2,9 +2,10 @@ import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/chat_room/chat_room.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/didvan/badge.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/utils/date_time.dart';
+import 'package:didvan/views/widgets/didvan/badge.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class ChatRoomItem extends StatelessWidget {
@@ -14,10 +15,13 @@ class ChatRoomItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
- onTap: () => Navigator.of(context).pushNamed(
- Routes.direct,
- arguments: chatRoom.id,
- ),
+ onTap: () {
+ Navigator.of(context).pushNamed(
+ Routes.direct,
+ arguments: {'type': chatRoom.type},
+ );
+ chatRoom.unread = 0;
+ },
child: Container(
color: Colors.transparent,
child: Column(
@@ -35,15 +39,18 @@ class ChatRoomItem extends StatelessWidget {
style: Theme.of(context).textTheme.bodyText1,
),
),
- DidvanBadge(text: chatRoom.unread.toString()),
+ if (chatRoom.unread != 0)
+ DidvanBadge(text: chatRoom.unread.toString()),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 40),
- const Icon(
- DidvanIcons.check_double_light,
+ Icon(
+ chatRoom.lastMessage.readed
+ ? DidvanIcons.check_double_light
+ : DidvanIcons.check_light,
size: 16,
),
const SizedBox(width: 4),
@@ -51,12 +58,24 @@ class ChatRoomItem extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- DidvanText(
- chatRoom.lastMessage.text ?? '',
- maxLines: 1,
+ Row(
+ children: [
+ if (chatRoom.lastMessage.text == null)
+ const Icon(
+ DidvanIcons.mic_light,
+ size: 18,
+ ),
+ Expanded(
+ child: DidvanText(
+ chatRoom.lastMessage.text ?? 'پیام صوتی',
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ ],
),
DidvanText(
- chatRoom.updatedAt,
+ DateTimeUtils.momentGenerator(chatRoom.updatedAt),
style: Theme.of(context).textTheme.caption,
color: Theme.of(context).colorScheme.caption,
)
diff --git a/lib/pages/home/settings/general_settings/settings.dart b/lib/views/home/settings/general_settings/settings.dart
similarity index 92%
rename from lib/pages/home/settings/general_settings/settings.dart
rename to lib/views/home/settings/general_settings/settings.dart
index a02499b..c3cc3eb 100644
--- a/lib/pages/home/settings/general_settings/settings.dart
+++ b/lib/views/home/settings/general_settings/settings.dart
@@ -6,16 +6,16 @@ import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/item_title.dart';
-import 'package:didvan/widgets/state_handlers/state_handler.dart';
+import 'package:didvan/views/home/settings/general_settings/settings_state.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/item_title.dart';
+import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/settings/general_settings/settings_state.dart b/lib/views/home/settings/general_settings/settings_state.dart
similarity index 100%
rename from lib/pages/home/settings/general_settings/settings_state.dart
rename to lib/views/home/settings/general_settings/settings_state.dart
diff --git a/lib/pages/home/settings/profile/profile.dart b/lib/views/home/settings/profile/profile.dart
similarity index 91%
rename from lib/pages/home/settings/profile/profile.dart
rename to lib/views/home/settings/profile/profile.dart
index 0dfb2f3..071d6ac 100644
--- a/lib/pages/home/settings/profile/profile.dart
+++ b/lib/views/home/settings/profile/profile.dart
@@ -2,17 +2,17 @@ import 'dart:async';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/pages/home/settings/profile/widgets/profile_photo.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/scaffold.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/didvan/text_field.dart';
+import 'package:didvan/views/home/settings/profile/widgets/profile_photo.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/scaffold.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
diff --git a/lib/pages/home/settings/profile/widgets/profile_photo.dart b/lib/views/home/settings/profile/widgets/profile_photo.dart
similarity index 50%
rename from lib/pages/home/settings/profile/widgets/profile_photo.dart
rename to lib/views/home/settings/profile/widgets/profile_photo.dart
index 3b307ee..62f1018 100644
--- a/lib/pages/home/settings/profile/widgets/profile_photo.dart
+++ b/lib/views/home/settings/profile/widgets/profile_photo.dart
@@ -1,19 +1,22 @@
+import 'dart:io';
+
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/providers/user_provider.dart';
-import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/media/media.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
+import 'package:image_cropper/image_cropper.dart';
class ProfilePhoto extends StatefulWidget {
const ProfilePhoto({Key? key}) : super(key: key);
@@ -78,60 +81,88 @@ class _ProfilePhotoState extends State {
Future _openImagePickerSheet() async {
FocusScope.of(context).unfocus();
- await showModalBottomSheet(
- context: context,
- isScrollControlled: true,
- backgroundColor: Colors.transparent,
- builder: (context) => DidvanCard(
- enableBorder: false,
- child: Column(
+ await ActionSheetUtils.showBottomSheet(
+ data: ActionSheetData(
+ content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const DidvanText('بارگذاری تصویر از:'),
const SizedBox(height: 16),
- MenuItem(
- title: 'دوربین',
- onTap: () => _setProfilePhoto(ImageSource.camera),
- icon: DidvanIcons.camera_regular,
+ Padding(
+ padding: const EdgeInsets.only(right: 20),
+ child: Column(
+ children: [
+ MenuItem(
+ title: 'دوربین',
+ onTap: () => _setProfilePhoto(ImageSource.camera),
+ icon: DidvanIcons.camera_regular,
+ ),
+ const DidvanDivider(),
+ MenuItem(
+ title: 'گالری',
+ onTap: () => _setProfilePhoto(ImageSource.gallery),
+ icon: DidvanIcons.gallery_file_regular,
+ ),
+ ],
+ ),
),
const DidvanDivider(),
MenuItem(
- title: 'گالری',
- onTap: () => _setProfilePhoto(ImageSource.gallery),
- icon: DidvanIcons.gallery_file_regular,
+ title: 'حذف تصویر',
+ onTap: () => _setProfilePhoto(null),
+ icon: DidvanIcons.trash_solid,
+ color: Theme.of(context).colorScheme.secondary,
),
],
),
+ hasConfirmButton: false,
+ hasDismissButton: false,
+ title: 'بارگذاری تصویر از:',
),
);
}
- Future _setProfilePhoto(ImageSource source) async {
+ Future _setProfilePhoto(ImageSource? source) async {
ActionSheetUtils.pop();
- final pickedFile = await MediaService.pickImage(source: source);
- if (pickedFile != null) {
- ActionSheetUtils.showLogoLoadingIndicator();
- final bytes = await pickedFile.readAsBytes();
- ActionSheetUtils.pop();
- Navigator.of(context).pushNamed(
- Routes.imageCropper,
- arguments: {
- 'bytes': bytes,
- 'onCropped': () async {
- final state = context.read();
- final result = await state.setProfilePhoto(pickedFile);
- ActionSheetUtils.showAlert(
- AlertData(
- message: result
- ? 'تصویر پروفایل بارگذاری شد.'
- : 'بارگذاری تصویر موفقیت آمیز نبود.',
- aLertType: result ? ALertType.success : ALertType.error,
- ),
- );
- }
- },
+ final state = context.read();
+ if (source == null) {
+ final result = await state.deleteProfilePhoto();
+ ActionSheetUtils.showAlert(
+ AlertData(
+ message:
+ result ? 'تصویر پروفایل حذف شد.' : 'حذف تصویر موفقیت آمیز نبود.',
+ aLertType: result ? ALertType.success : ALertType.error,
+ ),
);
+ return;
}
+ final pickedFile = await MediaService.pickImage(source: source);
+ File? file;
+ if (pickedFile != null && !kIsWeb) {
+ file = await ImageCropper().cropImage(
+ sourcePath: pickedFile.path,
+ aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1),
+ iosUiSettings: const IOSUiSettings(
+ title: 'برش تصویر',
+ doneButtonTitle: 'تایید',
+ cancelButtonTitle: 'بازگشت',
+ ),
+ androidUiSettings: const AndroidUiSettings(toolbarTitle: 'برش تصویر'),
+ compressQuality: 70,
+ );
+ if (file == null) return;
+ }
+ if (pickedFile == null) return;
+ final uploadFile = kIsWeb ? pickedFile : file;
+ final result = await state.setProfilePhoto(uploadFile);
+ ActionSheetUtils.showAlert(
+ AlertData(
+ message: result
+ ? 'تصویر پروفایل بارگذاری شد.'
+ : 'بارگذاری تصویر موفقیت آمیز نبود.',
+ aLertType: result ? ALertType.success : ALertType.error,
+ ),
+ );
}
}
diff --git a/lib/pages/home/settings/settings.dart b/lib/views/home/settings/settings.dart
similarity index 92%
rename from lib/pages/home/settings/settings.dart
rename to lib/views/home/settings/settings.dart
index 5a4a048..7753d26 100644
--- a/lib/pages/home/settings/settings.dart
+++ b/lib/views/home/settings/settings.dart
@@ -1,14 +1,14 @@
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
-import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/storage/storage.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/item_title.dart';
+import 'package:didvan/views/home/widgets/logo_app_bar.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/item_title.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
diff --git a/lib/pages/home/statistics/statistics.dart b/lib/views/home/statistics/statistics.dart
similarity index 83%
rename from lib/pages/home/statistics/statistics.dart
rename to lib/views/home/statistics/statistics.dart
index e727b5a..eef8150 100644
--- a/lib/pages/home/statistics/statistics.dart
+++ b/lib/views/home/statistics/statistics.dart
@@ -1,7 +1,7 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/assets.dart';
-import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
+import 'package:didvan/views/home/widgets/logo_app_bar.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:flutter/material.dart';
class Statictics extends StatelessWidget {
diff --git a/lib/views/home/studio/studio.dart b/lib/views/home/studio/studio.dart
new file mode 100644
index 0000000..a6f675a
--- /dev/null
+++ b/lib/views/home/studio/studio.dart
@@ -0,0 +1,57 @@
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/views/home/studio/widgets/slider.dart';
+import 'package:didvan/views/home/studio/widgets/tab_bar.dart';
+import 'package:didvan/views/home/widgets/logo_app_bar.dart';
+import 'package:didvan/views/home/widgets/search_field.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:flutter/material.dart';
+
+class Studio extends StatefulWidget {
+ const Studio({Key? key}) : super(key: key);
+
+ @override
+ State createState() => _StudioState();
+}
+
+class _StudioState extends State {
+ final FocusNode _focusNode = FocusNode();
+
+ @override
+ Widget build(BuildContext context) {
+ return CustomScrollView(
+ slivers: [
+ SliverToBoxAdapter(
+ child: Row(
+ children: [
+ const Expanded(child: LogoAppBar(type: 'studio')),
+ Padding(
+ padding:
+ EdgeInsets.only(top: MediaQuery.of(context).padding.top),
+ child: DidvanIconButton(
+ icon: DidvanIcons.bookmark_regular,
+ onPressed: () {},
+ ),
+ ),
+ ],
+ ),
+ ),
+ const SliverToBoxAdapter(
+ child: StudioTabBar(),
+ ),
+ SliverToBoxAdapter(
+ child: Padding(
+ padding: const EdgeInsets.all(16.0),
+ child: SearchField(
+ title: 'جستجو در استودیو',
+ onChanged: (value) {},
+ focusNode: _focusNode,
+ ),
+ ),
+ ),
+ const SliverToBoxAdapter(
+ child: StudioSlider(),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/views/home/studio/studio_state.dart b/lib/views/home/studio/studio_state.dart
new file mode 100644
index 0000000..ffa0282
--- /dev/null
+++ b/lib/views/home/studio/studio_state.dart
@@ -0,0 +1,5 @@
+import 'package:didvan/providers/core_provider.dart';
+
+class StudioState extends CoreProvier {
+ bool videosSelected = true;
+}
diff --git a/lib/views/home/studio/widgets/slider.dart b/lib/views/home/studio/widgets/slider.dart
new file mode 100644
index 0000000..d312b2b
--- /dev/null
+++ b/lib/views/home/studio/widgets/slider.dart
@@ -0,0 +1,51 @@
+import 'package:carousel_slider/carousel_slider.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:flutter/material.dart';
+
+class StudioSlider extends StatelessWidget {
+ const StudioSlider({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ CarouselSlider(
+ items: [
+ Image.network('https://wallpapercave.com/wp/wp10731650.jpg'),
+ Image.network('https://wallpapercave.com/wp/wp10731650.jpg'),
+ Image.network('https://wallpapercave.com/wp/wp10731650.jpg'),
+ Image.network('https://wallpapercave.com/wp/wp10731650.jpg'),
+ ],
+ options: CarouselOptions(
+ viewportFraction: 0.94,
+ aspectRatio: 16 / 9,
+ autoPlay: true,
+ ),
+ ),
+ Row(),
+ ],
+ );
+ }
+}
+
+class _SliderIndicator extends StatelessWidget {
+ final bool isCurrentIndex;
+ const _SliderIndicator({Key? key, required this.isCurrentIndex})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: 8,
+ width: 8,
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ shape: BoxShape.circle,
+ color:
+ isCurrentIndex ? Theme.of(context).colorScheme.focusedBorder : null,
+ ),
+ );
+ }
+}
diff --git a/lib/views/home/studio/widgets/tab_bar.dart b/lib/views/home/studio/widgets/tab_bar.dart
new file mode 100644
index 0000000..c5caacb
--- /dev/null
+++ b/lib/views/home/studio/widgets/tab_bar.dart
@@ -0,0 +1,100 @@
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:flutter/material.dart';
+
+class StudioTabBar extends StatelessWidget {
+ const StudioTabBar({
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ margin: const EdgeInsets.symmetric(horizontal: 16),
+ padding: const EdgeInsets.all(4),
+ decoration: BoxDecoration(
+ border: Border.all(color: Theme.of(context).colorScheme.border),
+ borderRadius: DesignConfig.lowBorderRadius,
+ ),
+ child: Row(
+ children: [
+ Expanded(
+ child: _StudioTypeButton(
+ icon: DidvanIcons.video_solid,
+ selectedColor: Theme.of(context).colorScheme.secondary,
+ title: 'ویدئو',
+ onTap: () {},
+ isSelected: true,
+ ),
+ ),
+ Container(
+ width: 1,
+ height: 32,
+ color: Theme.of(context).colorScheme.border,
+ ),
+ Expanded(
+ child: _StudioTypeButton(
+ icon: DidvanIcons.podcast_solid,
+ selectedColor: Theme.of(context).colorScheme.focusedBorder,
+ title: 'پادکست',
+ onTap: () {},
+ isSelected: true,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _StudioTypeButton extends StatelessWidget {
+ final IconData icon;
+ final String title;
+ final VoidCallback onTap;
+ final bool isSelected;
+ final Color selectedColor;
+ const _StudioTypeButton({
+ Key? key,
+ required this.icon,
+ required this.selectedColor,
+ required this.title,
+ required this.onTap,
+ required this.isSelected,
+ }) : super(key: key);
+
+ Color? get _color => isSelected ? selectedColor : null;
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: onTap,
+ child: Container(
+ color: Colors.transparent,
+ child: Column(
+ children: [
+ Icon(
+ icon,
+ size: 32,
+ color: _color,
+ ),
+ if (!isSelected) const SizedBox(height: 18),
+ if (isSelected)
+ Container(
+ width: 88,
+ height: 1,
+ color: _color,
+ ),
+ if (isSelected)
+ DidvanText(
+ title,
+ style: Theme.of(context).textTheme.overline,
+ color: _color,
+ )
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/views/home/widgets/audio_slider.dart b/lib/views/home/widgets/audio_slider.dart
new file mode 100644
index 0000000..b9edf70
--- /dev/null
+++ b/lib/views/home/widgets/audio_slider.dart
@@ -0,0 +1,39 @@
+import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
+import 'package:didvan/services/media/media.dart';
+import 'package:flutter/material.dart';
+
+class AudioSlider extends StatelessWidget {
+ final String tag;
+ const AudioSlider({Key? key, required this.tag}) : super(key: key);
+
+ bool get _isPlaying => MediaService.audioPlayerTag == tag;
+
+ @override
+ Widget build(BuildContext context) {
+ return IgnorePointer(
+ ignoring: MediaService.audioPlayerTag != tag,
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: StreamBuilder(
+ stream: _isPlaying ? MediaService.audioPlayer.positionStream : null,
+ builder: (context, snapshot) {
+ return ProgressBar(
+ total: MediaService.audioPlayer.duration ?? Duration.zero,
+ progress: snapshot.data ?? Duration.zero,
+ buffered:
+ _isPlaying ? MediaService.audioPlayer.bufferedPosition : null,
+ thumbRadius: 6,
+ barHeight: 3,
+ timeLabelTextStyle: const TextStyle(fontSize: 0),
+ onSeek: (value) => _onSeek(value.inMilliseconds),
+ );
+ },
+ ),
+ ),
+ );
+ }
+
+ void _onSeek(int value) {
+ MediaService.audioPlayer.seek(Duration(milliseconds: value));
+ }
+}
diff --git a/lib/views/home/widgets/audio_visualizer.dart b/lib/views/home/widgets/audio_visualizer.dart
new file mode 100644
index 0000000..c39ca3d
--- /dev/null
+++ b/lib/views/home/widgets/audio_visualizer.dart
@@ -0,0 +1,314 @@
+// import 'dart:io';
+// import 'dart:math';
+
+// import 'package:didvan/config/design_config.dart';
+// import 'package:didvan/config/theme_data.dart';
+// import 'package:didvan/constants/app_icons.dart';
+// import 'package:didvan/constants/assets.dart';
+// import 'package:didvan/pages/home/direct/direct_state.dart';
+// import 'package:didvan/services/media/media.dart';
+// import 'package:didvan/services/storage/storage.dart';
+// import 'package:didvan/utils/date_time.dart';
+// import 'package:didvan/widgets/didvan/icon_button.dart';
+// import 'package:didvan/widgets/didvan/text.dart';
+// import 'package:flutter/foundation.dart';
+// import 'package:flutter/material.dart';
+// import 'package:flutter_svg/flutter_svg.dart';
+// import 'package:just_waveform/just_waveform.dart';
+// import 'package:provider/provider.dart';
+
+// class AudioVisualizer extends StatefulWidget {
+// final File? audioFile;
+// final Waveform? waveform;
+// final String? audioUrl;
+// final int? duration;
+// final Color? backgroundColor;
+
+// const AudioVisualizer({
+// Key? key,
+// this.audioFile,
+// this.waveform,
+// this.audioUrl,
+// this.duration,
+// this.backgroundColor,
+// }) : super(key: key);
+
+// @override
+// State createState() => _AudioVisualizerState();
+// }
+
+// class _AudioVisualizerState extends State {
+// Stream? waveDataStream;
+
+// @override
+// void initState() {
+// if (!kIsWeb && widget.audioFile != null) {
+// waveDataStream = JustWaveform.extract(
+// audioInFile: widget.audioFile!,
+// waveOutFile: File(StorageService.appTempsDir + '/rec-wave.wave'),
+// zoom: const WaveformZoom.pixelsPerSecond(100),
+// );
+// }
+// super.initState();
+// }
+
+// bool get _nowPlaying =>
+// MediaService.lastAudioPath == widget.audioFile ||
+// MediaService.lastAudioPath == widget.audioUrl;
+
+// @override
+// Widget build(BuildContext context) {
+// return Container(
+// decoration: BoxDecoration(
+// color: widget.backgroundColor ??
+// (DesignConfig.isDark
+// ? Theme.of(context).colorScheme.black
+// : Theme.of(context).colorScheme.background),
+// borderRadius: DesignConfig.mediumBorderRadius,
+// ),
+// child: Row(
+// children: [
+// const SizedBox(width: 12),
+// StreamBuilder(
+// stream:
+// _nowPlaying ? MediaService.audioPlayer.positionStream : null,
+// builder: (context, snapshot) {
+// String text = '';
+// if (MediaService.audioPlayer.duration == null) {
+// Future.delayed(Duration.zero, () {
+// if (mounted) {
+// setState(() {});
+// }
+// });
+// }
+// if (snapshot.data == null || snapshot.data == Duration.zero) {
+// text = DateTimeUtils.normalizeTimeDuration(
+// MediaService.audioPlayer.duration ??
+// widget.waveform?.duration ??
+// Duration.zero);
+// } else {
+// text = DateTimeUtils.normalizeTimeDuration(snapshot.data!);
+// }
+// return DidvanText(
+// text,
+// color: Theme.of(context).colorScheme.focusedBorder,
+// isEnglishFont: true,
+// );
+// },
+// ),
+// const SizedBox(width: 12),
+// Expanded(
+// child: Builder(
+// builder: (context) {
+// if (kIsWeb) {
+// return SvgPicture.asset(Assets.record);
+// }
+// if (widget.audioFile != null) {
+// return StreamBuilder(
+// stream: waveDataStream,
+// builder: (context, snapshot) {
+// if (snapshot.data == null ||
+// snapshot.data!.waveform == null) {
+// return const SizedBox();
+// }
+// final waveform = snapshot.data!.waveform!;
+// context.read().waveform = waveform;
+// return _waveWidget(waveform);
+// },
+// );
+// }
+// if (widget.waveform == null && waveDataStream == null) {
+// return SvgPicture.asset(Assets.record);
+// }
+// return _waveWidget(widget.waveform!);
+// },
+// ),
+// ),
+// StreamBuilder(
+// stream: _nowPlaying ? MediaService.audioPlayer.playingStream : null,
+// builder: (context, snapshot) {
+// return DidvanIconButton(
+// icon: snapshot.data == true
+// ? DidvanIcons.pause_circle_solid
+// : DidvanIcons.play_circle_solid,
+// color: Theme.of(context).colorScheme.focusedBorder,
+// onPressed: () {
+// MediaService.handleAudioPlayback(
+// audioSource: widget.audioFile ?? widget.audioUrl,
+// isNetworkAudio: widget.audioFile == null,
+// );
+// setState(() {});
+// },
+// );
+// },
+// ),
+// ],
+// ),
+// );
+// }
+
+// Widget _waveWidget(Waveform waveform) => IgnorePointer(
+// ignoring: !_nowPlaying,
+// child: GestureDetector(
+// onHorizontalDragUpdate: _changePosition,
+// onTapDown: _changePosition,
+// child: SizedBox(
+// height: double.infinity,
+// width: double.infinity,
+// child: _AudioWaveformWidget(
+// waveform: waveform,
+// start: Duration.zero,
+// scale: 2,
+// strokeWidth: 3,
+// nowPlaying: _nowPlaying,
+// duration: waveform.duration,
+// waveColor: Theme.of(context).colorScheme.focusedBorder,
+// ),
+// ),
+// ),
+// );
+
+// void _changePosition(details) {
+// if (MediaService.audioPlayer.audioSource == null) return;
+// double posper =
+// details.localPosition.dx / (MediaQuery.of(context).size.width - 200);
+// if (posper >= 1 || posper < 0) return;
+// final position = MediaService.audioPlayer.duration!.inMilliseconds;
+// MediaService.audioPlayer.seek(
+// Duration(milliseconds: (posper * position).toInt()),
+// );
+// }
+// }
+
+// class _AudioWaveformWidget extends StatelessWidget {
+// final Color waveColor;
+// final double scale;
+// final double strokeWidth;
+// final double pixelsPerStep;
+// final Waveform waveform;
+// final Duration start;
+// final bool nowPlaying;
+// final Duration duration;
+
+// const _AudioWaveformWidget({
+// Key? key,
+// required this.waveform,
+// required this.start,
+// required this.duration,
+// required this.nowPlaying,
+// this.waveColor = Colors.blue,
+// this.scale = 1.0,
+// this.strokeWidth = 5.0,
+// this.pixelsPerStep = 8.0,
+// }) : super(key: key);
+
+// @override
+// Widget build(BuildContext context) {
+// return ClipRect(
+// child: StreamBuilder(
+// stream: nowPlaying ? MediaService.audioPlayer.positionStream : null,
+// builder: (context, snapshot) {
+// double progress = 0;
+// if (snapshot.data == null ||
+// MediaService.audioPlayer.duration == null) {
+// progress = 0;
+// } else {
+// progress = snapshot.data!.inMilliseconds /
+// MediaService.audioPlayer.duration!.inMilliseconds *
+// 100;
+// }
+// if (progress >= 100) {
+// progress = 0;
+// MediaService.audioPlayer.stop();
+// MediaService.audioPlayer.seek(Duration.zero);
+// }
+// return CustomPaint(
+// painter: _AudioWaveformPainter(
+// waveColor: waveColor,
+// waveform: waveform,
+// start: start,
+// duration: duration,
+// scale: scale,
+// strokeWidth: strokeWidth,
+// pixelsPerStep: pixelsPerStep,
+// progressPercentage: progress,
+// progressColor: Theme.of(context).colorScheme.focusedBorder,
+// color: Theme.of(context).colorScheme.border,
+// ),
+// );
+// }),
+// );
+// }
+// }
+
+// class _AudioWaveformPainter extends CustomPainter {
+// final double scale;
+// final double strokeWidth;
+// final double pixelsPerStep;
+// final Waveform waveform;
+// final Duration start;
+// final Duration duration;
+// final double progressPercentage;
+// final Color progressColor;
+// final Color color;
+
+// _AudioWaveformPainter({
+// required this.waveform,
+// required this.start,
+// required this.duration,
+// required this.progressPercentage,
+// required this.color,
+// required this.progressColor,
+// Color waveColor = Colors.blue,
+// this.scale = 1.0,
+// this.strokeWidth = 5.0,
+// this.pixelsPerStep = 8.0,
+// });
+
+// @override
+// void paint(Canvas canvas, Size size) {
+// if (duration == Duration.zero) return;
+// double width = size.width;
+// double height = size.height;
+
+// final waveformPixelsPerWindow = waveform.positionToPixel(duration).toInt();
+// final waveformPixelsPerDevicePixel = waveformPixelsPerWindow / width;
+// final waveformPixelsPerStep = waveformPixelsPerDevicePixel * pixelsPerStep;
+// final sampleOffset = waveform.positionToPixel(start);
+// final sampleStart = -sampleOffset % waveformPixelsPerStep;
+// final totalLength = waveformPixelsPerWindow;
+// final wavePaintB = Paint()
+// ..style = PaintingStyle.stroke
+// ..strokeWidth = strokeWidth
+// ..strokeCap = StrokeCap.round
+// ..color = progressColor;
+// final wavePaintA = Paint()
+// ..style = PaintingStyle.stroke
+// ..strokeWidth = strokeWidth
+// ..strokeCap = StrokeCap.round
+// ..color = color;
+// for (var i = sampleStart.toDouble();
+// i <= waveformPixelsPerWindow + 1.0;
+// i += waveformPixelsPerStep) {
+// final sampleIdx = (sampleOffset + i).toInt();
+// final x = i / waveformPixelsPerDevicePixel;
+// final minY = normalise(waveform.getPixelMin(sampleIdx), height);
+// final maxY = normalise(waveform.getPixelMax(sampleIdx), height);
+// canvas.drawLine(
+// Offset(x + strokeWidth / 2, max(strokeWidth * 0.75, minY)),
+// Offset(x + strokeWidth / 2, min(height - strokeWidth * 0.75, maxY)),
+// i / totalLength < progressPercentage / 100 ? wavePaintB : wavePaintA,
+// );
+// }
+// }
+
+// @override
+// bool shouldRepaint(covariant _AudioWaveformPainter oldDelegate) {
+// return oldDelegate.progressPercentage != progressPercentage;
+// }
+
+// double normalise(int s, double height) {
+// final y = 32768 + (scale * s).clamp(-32768.0, 32767.0).toDouble();
+// return height - 1 - y * height / 65536;
+// }
+// }
diff --git a/lib/pages/home/widgets/bnb.dart b/lib/views/home/widgets/bnb.dart
similarity index 98%
rename from lib/pages/home/widgets/bnb.dart
rename to lib/views/home/widgets/bnb.dart
index 01e2927..42d8ad9 100644
--- a/lib/pages/home/widgets/bnb.dart
+++ b/lib/views/home/widgets/bnb.dart
@@ -1,7 +1,7 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanBNB extends StatelessWidget {
diff --git a/lib/pages/home/widgets/bookmark_button.dart b/lib/views/home/widgets/bookmark_button.dart
similarity index 94%
rename from lib/pages/home/widgets/bookmark_button.dart
rename to lib/views/home/widgets/bookmark_button.dart
index eb4aa46..4de2621 100644
--- a/lib/pages/home/widgets/bookmark_button.dart
+++ b/lib/views/home/widgets/bookmark_button.dart
@@ -1,8 +1,8 @@
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class BookmarkButton extends StatefulWidget {
diff --git a/lib/pages/home/widgets/date_picker_button.dart b/lib/views/home/widgets/date_picker_button.dart
similarity index 97%
rename from lib/pages/home/widgets/date_picker_button.dart
rename to lib/views/home/widgets/date_picker_button.dart
index a2ac7f7..ac5164c 100644
--- a/lib/pages/home/widgets/date_picker_button.dart
+++ b/lib/views/home/widgets/date_picker_button.dart
@@ -1,7 +1,7 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
diff --git a/lib/pages/home/widgets/floating_navigation_bar.dart b/lib/views/home/widgets/floating_navigation_bar.dart
similarity index 81%
rename from lib/pages/home/widgets/floating_navigation_bar.dart
rename to lib/views/home/widgets/floating_navigation_bar.dart
index 25bf4ef..3cc0323 100644
--- a/lib/pages/home/widgets/floating_navigation_bar.dart
+++ b/lib/views/home/widgets/floating_navigation_bar.dart
@@ -1,29 +1,25 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/models/category.dart';
+import 'package:didvan/models/message_data/radar_attachment.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
-import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/pages/home/widgets/bookmark_button.dart';
-import 'package:didvan/widgets/didvan/chip.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/item_title.dart';
+import 'package:didvan/views/home/widgets/bookmark_button.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
+import 'package:didvan/views/widgets/didvan/chip.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/item_title.dart';
import 'package:flutter/material.dart';
class FloatingNavigationBar extends StatefulWidget {
final ScrollController scrollController;
+ final dynamic item;
final bool hasUnmarkConfirmation;
final void Function(int count) onCommentsChanged;
final bool isRadar;
- final bool marked;
- final int comments;
- final int id;
- final String title;
- final List? categories;
final void Function(bool value) onMarkChanged;
const FloatingNavigationBar({
@@ -32,11 +28,7 @@ class FloatingNavigationBar extends StatefulWidget {
required this.onCommentsChanged,
required this.onMarkChanged,
required this.isRadar,
- required this.marked,
- required this.comments,
- required this.id,
- required this.title,
- this.categories,
+ required this.item,
this.hasUnmarkConfirmation = false,
}) : super(key: key);
@@ -50,7 +42,9 @@ class _FloatingNavigationBarState extends State {
@override
void didUpdateWidget(covariant FloatingNavigationBar oldWidget) {
- _comments = widget.comments;
+ _comments = widget.item.comments;
+ _isScrolled = false;
+ _handleScroll();
super.didUpdateWidget(oldWidget);
}
@@ -58,7 +52,7 @@ class _FloatingNavigationBarState extends State {
void initState() {
_handleScroll();
_isScrolled = false;
- _comments = widget.comments;
+ _comments = widget.item.comments;
super.initState();
}
@@ -111,7 +105,7 @@ class _FloatingNavigationBarState extends State {
if (widget.isRadar)
BookmarkButton(
askForConfirmation: widget.hasUnmarkConfirmation,
- value: widget.marked,
+ value: widget.item.marked,
onMarkChanged: (value) {
widget.onMarkChanged(value);
if (widget.hasUnmarkConfirmation && !value) {
@@ -135,9 +129,9 @@ class _FloatingNavigationBarState extends State {
onPressed: () => Navigator.of(context).pushNamed(
Routes.comments,
arguments: {
- 'id': widget.id,
+ 'id': widget.item.id,
'isRadar': widget.isRadar,
- 'title': widget.title,
+ 'title': widget.item.title,
'onCommentsChanged': widget.onCommentsChanged,
},
),
@@ -150,7 +144,7 @@ class _FloatingNavigationBarState extends State {
if (!widget.isRadar)
BookmarkButton(
askForConfirmation: widget.hasUnmarkConfirmation,
- value: widget.marked,
+ value: widget.item.marked,
onMarkChanged: (value) {
widget.onMarkChanged(value);
if (widget.hasUnmarkConfirmation && !value) {
@@ -189,7 +183,7 @@ class _FloatingNavigationBarState extends State {
}
void _showMoreOptions() {
- final categories = widget.categories!;
+ final categories = widget.item.categories!;
ActionSheetUtils.showBottomSheet(
data: ActionSheetData(
content: Column(
@@ -209,7 +203,19 @@ class _FloatingNavigationBarState extends State {
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
Routes.direct,
- arguments: categories[i].id,
+ arguments: {
+ 'radarAttachment': RadarAttachment(
+ id: widget.item.id,
+ title: widget.item.title,
+ description: widget.item.contents.first.text,
+ timeToRead: widget.item.timeToRead,
+ image: widget.item.image,
+ forManagers: widget.item.forManagers,
+ categories: widget.item.categories,
+ createdAt: widget.item.createdAt,
+ ),
+ 'type': categories[i].label,
+ },
);
},
),
@@ -227,7 +233,7 @@ class _FloatingNavigationBarState extends State {
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
Routes.direct,
- arguments: 0,
+ arguments: {},
);
},
icon: DidvanIcons.description_regular,
diff --git a/lib/pages/home/widgets/logo_app_bar.dart b/lib/views/home/widgets/logo_app_bar.dart
similarity index 55%
rename from lib/pages/home/widgets/logo_app_bar.dart
rename to lib/views/home/widgets/logo_app_bar.dart
index b8f2803..50f0bfc 100644
--- a/lib/pages/home/widgets/logo_app_bar.dart
+++ b/lib/views/home/widgets/logo_app_bar.dart
@@ -1,23 +1,26 @@
-import 'package:didvan/widgets/logos/didvan_vertical_logo.dart';
+import 'package:didvan/views/widgets/logos/didvan_vertical_logo.dart';
import 'package:flutter/material.dart';
class LogoAppBar extends StatelessWidget {
+ final String? type;
final bool hasExtraPadding;
- const LogoAppBar({Key? key, this.hasExtraPadding = true}) : super(key: key);
+ const LogoAppBar({Key? key, this.hasExtraPadding = true, this.type})
+ : super(key: key);
@override
Widget build(BuildContext context) {
final MediaQueryData d = MediaQuery.of(context);
final double extraPadding = hasExtraPadding ? 0 : 16;
return Container(
+ margin: EdgeInsets.only(top: d.padding.top),
padding: EdgeInsets.only(
- left: 140 - extraPadding,
- top: d.padding.top + 16 - extraPadding,
+ left: (type == null ? 140 : 0) - extraPadding,
+ top: 16 - extraPadding,
bottom: 16 - extraPadding,
right: 16 - extraPadding,
),
alignment: Alignment.centerRight,
- child: const DidvanHorizontalLogo(),
+ child: DidvanHorizontalLogo(type: type),
);
}
}
diff --git a/lib/pages/home/widgets/menu_item.dart b/lib/views/home/widgets/menu_item.dart
similarity index 97%
rename from lib/pages/home/widgets/menu_item.dart
rename to lib/views/home/widgets/menu_item.dart
index bd65501..d0612c7 100644
--- a/lib/pages/home/widgets/menu_item.dart
+++ b/lib/views/home/widgets/menu_item.dart
@@ -1,6 +1,6 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class MenuItem extends StatelessWidget {
diff --git a/lib/pages/home/widgets/multitype_overview.dart b/lib/views/home/widgets/multitype_overview.dart
similarity index 91%
rename from lib/pages/home/widgets/multitype_overview.dart
rename to lib/views/home/widgets/multitype_overview.dart
index ef0a944..0076a05 100644
--- a/lib/pages/home/widgets/multitype_overview.dart
+++ b/lib/views/home/widgets/multitype_overview.dart
@@ -1,13 +1,13 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/models/item_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/routes/routes.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
@@ -72,6 +72,8 @@ class MultitypeOverview extends StatelessWidget {
DidvanText(
item.title,
style: Theme.of(context).textTheme.bodyText1,
+ maxLines: 2,
+ overflow: TextOverflow.ellipsis,
),
Row(
children: [
diff --git a/lib/pages/home/widgets/news_overview.dart b/lib/views/home/widgets/news_overview.dart
similarity index 89%
rename from lib/pages/home/widgets/news_overview.dart
rename to lib/views/home/widgets/news_overview.dart
index 0c625de..e998acf 100644
--- a/lib/pages/home/widgets/news_overview.dart
+++ b/lib/views/home/widgets/news_overview.dart
@@ -1,17 +1,17 @@
-import 'package:didvan/models/news_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/pages/home/widgets/bookmark_button.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
+import 'package:didvan/views/home/widgets/bookmark_button.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
class NewsOverview extends StatelessWidget {
- final NewsOverviewData news;
+ final OverviewData news;
final NewsRequestArgs? newsRequestArgs;
final void Function(int id, bool value) onMarkChanged;
final bool hasUnmarkConfirmation;
@@ -69,7 +69,7 @@ class NewsOverview extends StatelessWidget {
Row(
children: [
DidvanText(
- news.reference,
+ news.reference!,
style: Theme.of(context).textTheme.caption,
),
DidvanText(
diff --git a/lib/views/home/widgets/player_controller_button.dart b/lib/views/home/widgets/player_controller_button.dart
new file mode 100644
index 0000000..7e2cc14
--- /dev/null
+++ b/lib/views/home/widgets/player_controller_button.dart
@@ -0,0 +1,34 @@
+import 'dart:io';
+
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/services/media/media.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:flutter/material.dart';
+
+class AudioControllerButton extends StatelessWidget {
+ final String? audioUrl;
+ final File? audioFile;
+
+ const AudioControllerButton({Key? key, this.audioUrl, this.audioFile})
+ : super(key: key);
+
+ bool get _nowPlaying =>
+ MediaService.audioPlayerTag == audioUrl ||
+ audioFile != null && MediaService.audioPlayerTag == audioFile!.path;
+
+ @override
+ Widget build(BuildContext context) {
+ return DidvanIconButton(
+ icon: MediaService.audioPlayer.playing == true && _nowPlaying
+ ? DidvanIcons.pause_circle_solid
+ : DidvanIcons.play_circle_solid,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ onPressed: () {
+ MediaService.handleAudioPlayback(
+ audioSource: audioFile ?? audioUrl,
+ );
+ },
+ );
+ }
+}
diff --git a/lib/pages/home/widgets/radar_overview.dart b/lib/views/home/widgets/radar_overview.dart
similarity index 89%
rename from lib/pages/home/widgets/radar_overview.dart
rename to lib/views/home/widgets/radar_overview.dart
index 35be2a4..5616994 100644
--- a/lib/pages/home/widgets/radar_overview.dart
+++ b/lib/views/home/widgets/radar_overview.dart
@@ -1,20 +1,20 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/models/radar_overview.dart';
+import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/pages/home/widgets/bookmark_button.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
+import 'package:didvan/views/home/widgets/bookmark_button.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
class RadarOverview extends StatelessWidget {
- final RadarOverviewData radar;
+ final OverviewData radar;
final void Function(int id, int count) onCommentsChanged;
final void Function(int id, bool value) onMarkChanged;
final bool hasUnmarkConfirmation;
@@ -44,7 +44,6 @@ class RadarOverview extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- const SizedBox(height: 8),
DidvanText(
radar.title,
fontWeight: FontWeight.w600,
@@ -82,13 +81,13 @@ class RadarOverview extends StatelessWidget {
Row(
children: [
DidvanText(
- radar.categories.first.label,
+ radar.categories!.first.label,
style: Theme.of(context).textTheme.overline,
color: Theme.of(context).colorScheme.caption,
),
const Spacer(),
DidvanText(
- '${DateTimeUtils.momentGenerator(radar.createdAt)} | خواندن ${radar.timeToRead} دقیقه',
+ '${DateTimeUtils.momentGenerator(radar.createdAt)} | خواندن در ${radar.timeToRead} دقیقه',
style: Theme.of(context).textTheme.overline,
color: Theme.of(context).colorScheme.caption,
),
@@ -139,11 +138,13 @@ class RadarOverview extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
+ const ShimmerPlaceholder(height: 16),
+ const SizedBox(height: 8),
const ShimmerPlaceholder(
width: 200,
height: 16,
),
- const SizedBox(height: 8),
+ const SizedBox(height: 16),
const AspectRatio(aspectRatio: 16 / 9, child: ShimmerPlaceholder()),
const SizedBox(height: 8),
Row(
diff --git a/lib/pages/home/widgets/search_field.dart b/lib/views/home/widgets/search_field.dart
similarity index 98%
rename from lib/pages/home/widgets/search_field.dart
rename to lib/views/home/widgets/search_field.dart
index 1dd684c..dea0aa1 100644
--- a/lib/pages/home/widgets/search_field.dart
+++ b/lib/views/home/widgets/search_field.dart
@@ -1,6 +1,6 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:flutter/material.dart';
class SearchField extends StatefulWidget {
diff --git a/lib/views/home/widgets/tag_item.dart b/lib/views/home/widgets/tag_item.dart
new file mode 100644
index 0000000..1265361
--- /dev/null
+++ b/lib/views/home/widgets/tag_item.dart
@@ -0,0 +1,52 @@
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/models/tag.dart';
+import 'package:didvan/routes/routes.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/ink_wrapper.dart';
+import 'package:flutter/material.dart';
+
+class TagItem extends StatelessWidget {
+ final Tag tag;
+
+ const TagItem({
+ Key? key,
+ required this.tag,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return InkWrapper(
+ borderRadius: DesignConfig.lowBorderRadius,
+ onPressed: () =>
+ Navigator.of(context).pushNamed(Routes.hashtag, arguments: tag),
+ child: Container(
+ padding: const EdgeInsets.symmetric(
+ vertical: 4,
+ horizontal: 8,
+ ),
+ decoration: BoxDecoration(
+ borderRadius: DesignConfig.lowBorderRadius,
+ border: Border.all(
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Icon(
+ DidvanIcons.hashtag_regular,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ ),
+ DidvanText(
+ tag.label,
+ color: Theme.of(context).colorScheme.focusedBorder,
+ style: Theme.of(context).textTheme.bodyText1,
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/splash/splash.dart b/lib/views/splash/splash.dart
similarity index 93%
rename from lib/pages/splash/splash.dart
rename to lib/views/splash/splash.dart
index 4486bec..a66e8d1 100644
--- a/lib/pages/splash/splash.dart
+++ b/lib/views/splash/splash.dart
@@ -10,8 +10,8 @@ import 'package:didvan/services/app_initalizer.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:didvan/utils/action_sheet.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/logos/didvan_horizontal_logo.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/logos/didvan_horizontal_logo.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -64,7 +64,7 @@ class _SplashState extends State {
SpinKitSpinningLines(
color: Theme.of(context).colorScheme.primary,
),
- if (_errorOccured) const SizedBox(height: 38),
+ if (_errorOccured) const SizedBox(height: 30),
if (_errorOccured)
DidvanButton(
width: 120,
@@ -108,7 +108,7 @@ class _SplashState extends State {
log(token);
RequestService.token = token;
await userProvider.getUserInfo();
- await context.read().getData();
+ await ServerDataProvider.getData();
}
Navigator.of(context).pushReplacementNamed(
token == null ? Routes.authenticaion : Routes.home,
diff --git a/lib/widgets/animated_visibility.dart b/lib/views/widgets/animated_visibility.dart
similarity index 100%
rename from lib/widgets/animated_visibility.dart
rename to lib/views/widgets/animated_visibility.dart
diff --git a/lib/widgets/didvan/app_bar.dart b/lib/views/widgets/didvan/app_bar.dart
similarity index 68%
rename from lib/widgets/didvan/app_bar.dart
rename to lib/views/widgets/didvan/app_bar.dart
index 764e588..1de49fe 100644
--- a/lib/widgets/didvan/app_bar.dart
+++ b/lib/views/widgets/didvan/app_bar.dart
@@ -1,23 +1,44 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanAppBar extends StatelessWidget {
final AppBarData appBarData;
- const DidvanAppBar({Key? key, required this.appBarData}) : super(key: key);
+ final bool hasBorder;
+ final Color? backgroundColor;
+ const DidvanAppBar({
+ Key? key,
+ required this.appBarData,
+ this.hasBorder = false,
+ this.backgroundColor = Colors.transparent,
+ }) : super(key: key);
@override
Widget build(BuildContext context) {
- return Padding(
+ return Container(
+ height: kToolbarHeight + MediaQuery.of(context).padding.top,
+ width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(right: 4, left: 20),
+ decoration: BoxDecoration(
+ color: backgroundColor,
+ border: hasBorder
+ ? Border(
+ bottom: BorderSide(
+ color: Theme.of(context).colorScheme.cardBorder,
+ ),
+ )
+ : null,
+ ),
child: Row(
children: [
IconButton(
onPressed: () => Navigator.of(context).pop(),
color: Theme.of(context).colorScheme.title,
- icon: const Icon(DidvanIcons.back_regular),
+ icon: const Icon(
+ DidvanIcons.back_regular,
+ ),
),
const SizedBox(width: 16),
Expanded(
diff --git a/lib/widgets/didvan/badge.dart b/lib/views/widgets/didvan/badge.dart
similarity index 93%
rename from lib/widgets/didvan/badge.dart
rename to lib/views/widgets/didvan/badge.dart
index 5223d0a..c88c0fd 100644
--- a/lib/widgets/didvan/badge.dart
+++ b/lib/views/widgets/didvan/badge.dart
@@ -1,5 +1,5 @@
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanBadge extends StatelessWidget {
diff --git a/lib/widgets/didvan/button.dart b/lib/views/widgets/didvan/button.dart
similarity index 97%
rename from lib/widgets/didvan/button.dart
rename to lib/views/widgets/didvan/button.dart
index 9160709..de7498b 100644
--- a/lib/widgets/didvan/button.dart
+++ b/lib/views/widgets/didvan/button.dart
@@ -1,7 +1,7 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/enums.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanButton extends StatelessWidget {
@@ -75,5 +75,6 @@ class DidvanButton extends StatelessWidget {
color: enabled ? color : Theme.of(context).colorScheme.disabledText,
);
}
+ return null;
}
}
diff --git a/lib/widgets/didvan/card.dart b/lib/views/widgets/didvan/card.dart
similarity index 100%
rename from lib/widgets/didvan/card.dart
rename to lib/views/widgets/didvan/card.dart
diff --git a/lib/widgets/didvan/checkbox.dart b/lib/views/widgets/didvan/checkbox.dart
similarity index 95%
rename from lib/widgets/didvan/checkbox.dart
rename to lib/views/widgets/didvan/checkbox.dart
index 588234c..dfeb454 100644
--- a/lib/widgets/didvan/checkbox.dart
+++ b/lib/views/widgets/didvan/checkbox.dart
@@ -1,4 +1,4 @@
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanCheckbox extends StatefulWidget {
diff --git a/lib/widgets/didvan/chip.dart b/lib/views/widgets/didvan/chip.dart
similarity index 89%
rename from lib/widgets/didvan/chip.dart
rename to lib/views/widgets/didvan/chip.dart
index 358bcef..a1a7e73 100644
--- a/lib/widgets/didvan/chip.dart
+++ b/lib/views/widgets/didvan/chip.dart
@@ -1,7 +1,7 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/ink_wrapper.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/ink_wrapper.dart';
import 'package:flutter/material.dart';
class DidvanChip extends StatelessWidget {
diff --git a/lib/widgets/didvan/divider.dart b/lib/views/widgets/didvan/divider.dart
similarity index 100%
rename from lib/widgets/didvan/divider.dart
rename to lib/views/widgets/didvan/divider.dart
diff --git a/lib/widgets/didvan/icon_button.dart b/lib/views/widgets/didvan/icon_button.dart
similarity index 74%
rename from lib/widgets/didvan/icon_button.dart
rename to lib/views/widgets/didvan/icon_button.dart
index 6f12245..3046757 100644
--- a/lib/widgets/didvan/icon_button.dart
+++ b/lib/views/widgets/didvan/icon_button.dart
@@ -1,9 +1,10 @@
-import 'package:didvan/widgets/ink_wrapper.dart';
+import 'package:didvan/views/widgets/ink_wrapper.dart';
import 'package:flutter/material.dart';
class DidvanIconButton extends StatelessWidget {
final IconData icon;
final Color? color;
+ final Color? backgroundColor;
final double? size;
final double? gestureSize;
final VoidCallback onPressed;
@@ -14,6 +15,7 @@ class DidvanIconButton extends StatelessWidget {
this.color,
this.size,
this.gestureSize,
+ this.backgroundColor,
}) : super(key: key);
@override
@@ -21,7 +23,11 @@ class DidvanIconButton extends StatelessWidget {
return InkWrapper(
onPressed: onPressed,
borderRadius: BorderRadius.circular(200),
- child: SizedBox(
+ child: Container(
+ decoration: BoxDecoration(
+ color: backgroundColor,
+ shape: BoxShape.circle,
+ ),
height: gestureSize ?? 48,
width: gestureSize ?? 48,
child: Icon(
diff --git a/lib/views/widgets/didvan/page_view.dart b/lib/views/widgets/didvan/page_view.dart
new file mode 100644
index 0000000..e42744c
--- /dev/null
+++ b/lib/views/widgets/didvan/page_view.dart
@@ -0,0 +1,343 @@
+import 'package:carousel_slider/carousel_slider.dart';
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/config/theme_data.dart';
+import 'package:didvan/constants/app_icons.dart';
+import 'package:didvan/utils/date_time.dart';
+import 'package:didvan/views/home/widgets/multitype_overview.dart';
+import 'package:didvan/views/home/widgets/tag_item.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/card.dart';
+import 'package:didvan/views/widgets/didvan/divider.dart';
+import 'package:didvan/views/widgets/didvan/icon_button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/ink_wrapper.dart';
+import 'package:didvan/views/widgets/item_title.dart';
+import 'package:didvan/views/widgets/skeleton_image.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_html/flutter_html.dart';
+
+class DidvanPageView extends StatefulWidget {
+ final List items;
+ final int initialIndex;
+ final int currentIndex;
+ final bool isRadar;
+ final ScrollController scrollController;
+
+ final void Function(int index) onPageChanged;
+ const DidvanPageView({
+ Key? key,
+ required this.initialIndex,
+ required this.items,
+ required this.scrollController,
+ required this.onPageChanged,
+ required this.isRadar,
+ required this.currentIndex,
+ }) : super(key: key);
+
+ @override
+ State createState() => _DidvanPageViewState();
+}
+
+class _DidvanPageViewState extends State {
+ @override
+ Widget build(BuildContext context) {
+ final double deviceTopPadding = MediaQuery.of(context).padding.top;
+ return Stack(
+ children: [
+ Directionality(
+ textDirection: TextDirection.ltr,
+ child: CarouselSlider.builder(
+ itemCount: widget.items.length,
+ options: CarouselOptions(
+ onPageChanged: (index, reason) => widget.onPageChanged(index),
+ height: double.infinity,
+ initialPage: widget.initialIndex,
+ viewportFraction: 0.94,
+ enableInfiniteScroll: false,
+ ),
+ itemBuilder: (context, index, realIndex) => Directionality(
+ textDirection: TextDirection.rtl,
+ child: SizedBox(
+ height: MediaQuery.of(context).size.height,
+ child: SingleChildScrollView(
+ controller: index == widget.currentIndex
+ ? widget.scrollController
+ : null,
+ physics: const BouncingScrollPhysics(),
+ padding: EdgeInsets.only(
+ left: 4,
+ right: 4,
+ top: 16 + deviceTopPadding,
+ bottom: 92,
+ ),
+ child: DidvanCard(
+ padding: EdgeInsets.zero,
+ enableBorder: false,
+ child: Builder(
+ builder: (context) {
+ final item = widget.items[index];
+ if (item == null) {
+ return const SizedBox();
+ }
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SkeletonImage(
+ imageUrl: item.image,
+ aspectRatio: 16 / 9,
+ ),
+ const SizedBox(height: 20),
+ Padding(
+ padding:
+ const EdgeInsets.symmetric(horizontal: 16),
+ child: DidvanText(
+ item.title,
+ style: Theme.of(context).textTheme.subtitle1,
+ ),
+ ),
+ const SizedBox(height: 8),
+ Padding(
+ padding:
+ const EdgeInsets.symmetric(horizontal: 16),
+ child: _subtitle(item),
+ ),
+ for (var i = 0; i < item.contents.length; i++)
+ Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 16,
+ vertical: 4,
+ ),
+ child: _contentBuilder(item, i),
+ ),
+ if (item.tags.isNotEmpty)
+ const SizedBox(height: 20),
+ Padding(
+ padding:
+ const EdgeInsets.symmetric(horizontal: 16),
+ child: Wrap(
+ spacing: 8,
+ runSpacing: 8,
+ children: [
+ for (var i = 0; i < item.tags.length; i++)
+ TagItem(tag: item.tags[i]),
+ ],
+ ),
+ ),
+ const Padding(
+ padding: EdgeInsets.only(
+ left: 16,
+ right: 16,
+ top: 16,
+ ),
+ child: DidvanDivider(verticalPadding: 0),
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+ child: ItemTitle(title: 'مطالب مشابه'),
+ ),
+ if (item.relatedContents.isEmpty)
+ for (var i = 0; i < 3; i++)
+ Padding(
+ padding: const EdgeInsets.only(
+ bottom: 8,
+ left: 16,
+ right: 16,
+ ),
+ child: MultitypeOverview.placeholder,
+ ),
+ for (var i = 0;
+ i < item.relatedContents.length;
+ i++)
+ Padding(
+ padding: const EdgeInsets.only(
+ bottom: 8,
+ left: 16,
+ right: 16,
+ ),
+ child: MultitypeOverview(
+ item: item.relatedContents[i],
+ onMarkChanged: (id, value) {},
+ ),
+ ),
+ const SizedBox(height: 8),
+ ],
+ );
+ },
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Positioned(
+ child: _BackButton(scrollController: widget.scrollController),
+ right: 24,
+ top: 24 + deviceTopPadding,
+ ),
+ ],
+ );
+ }
+
+ Widget _contentBuilder(dynamic item, int index) {
+ final content = item.contents[index];
+ if (content.text != null) {
+ return Html(
+ data: content.text,
+ style: {
+ '*': Style(
+ direction: TextDirection.rtl,
+ lineHeight: LineHeight.percent(135),
+ margin: EdgeInsets.zero,
+ padding: EdgeInsets.zero,
+ ),
+ 'span': Style(
+ textAlign: TextAlign.center,
+ fontSize: FontSize.small,
+ alignment: Alignment.center,
+ ),
+ },
+ );
+ }
+ if (content.image != null) {
+ return GestureDetector(
+ onTap: () {
+ showDialog(
+ context: context,
+ builder: (context) => Stack(
+ children: [
+ Positioned.fill(
+ child: InteractiveViewer(
+ child: Center(
+ child: SkeletonImage(
+ width: MediaQuery.of(context).size.width,
+ height: 200,
+ imageUrl: content.image,
+ ),
+ ),
+ ),
+ ),
+ Positioned(
+ right: 16,
+ child: DidvanIconButton(
+ backgroundColor: Theme.of(context).colorScheme.primary,
+ icon: DidvanIcons.back_regular,
+ onPressed: Navigator.of(context).pop,
+ ),
+ ),
+ ],
+ ),
+ );
+ },
+ child: SkeletonImage(
+ imageUrl: content.image!,
+ aspectRatio: 16 / 9,
+ ),
+ );
+ }
+ return const SizedBox();
+ }
+
+ Widget _subtitle(dynamic item) {
+ if (widget.isRadar) {
+ return Wrap(
+ crossAxisAlignment: WrapCrossAlignment.center,
+ children: [
+ DidvanText(
+ 'رادار ',
+ style: Theme.of(context).textTheme.caption,
+ ),
+ for (var i = 0; i < item.categories.length; i++)
+ DidvanText(
+ item.categories[i].label +
+ '${i != item.categories.length - 1 ? '،' : ''} ',
+ style: Theme.of(context).textTheme.caption,
+ ),
+ DidvanText(
+ ' - ' + DateTimeUtils.momentGenerator(item.createdAt),
+ style: Theme.of(context).textTheme.caption,
+ ),
+ ],
+ );
+ } else {
+ return Row(
+ children: [
+ DidvanText(
+ item.reference,
+ style: Theme.of(context).textTheme.caption,
+ ),
+ DidvanText(
+ ' - ' + DateTimeUtils.momentGenerator(item.createdAt),
+ style: Theme.of(context).textTheme.caption,
+ ),
+ ],
+ );
+ }
+ }
+}
+
+class _BackButton extends StatefulWidget {
+ final ScrollController scrollController;
+ const _BackButton({Key? key, required this.scrollController})
+ : super(key: key);
+
+ @override
+ __BackButtonState createState() => __BackButtonState();
+}
+
+class __BackButtonState extends State<_BackButton> {
+ bool _isVisible = false;
+
+ @override
+ void didUpdateWidget(covariant _BackButton oldWidget) {
+ _isVisible = false;
+ _handleScroll();
+ super.didUpdateWidget(oldWidget);
+ }
+
+ @override
+ void initState() {
+ _handleScroll();
+ super.initState();
+ }
+
+ void _handleScroll() {
+ widget.scrollController.addListener(() {
+ final position = widget.scrollController.position.pixels;
+ final size = MediaQuery.of(context).size.height * 0.3;
+ if (position > size && _isVisible == false) {
+ setState(() {
+ _isVisible = true;
+ });
+ }
+ if (position < size && _isVisible == true) {
+ setState(() {
+ _isVisible = false;
+ });
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AnimatedVisibility(
+ duration: DesignConfig.lowAnimationDuration,
+ isVisible: _isVisible,
+ child: InkWrapper(
+ borderRadius: DesignConfig.lowBorderRadius,
+ onPressed: Navigator.of(context).pop,
+ child: Container(
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.splash,
+ border: Border.all(color: Theme.of(context).colorScheme.border),
+ borderRadius: DesignConfig.lowBorderRadius,
+ ),
+ child: const Icon(
+ DidvanIcons.back_regular,
+ size: 32,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/views/widgets/didvan/scaffold.dart b/lib/views/widgets/didvan/scaffold.dart
new file mode 100644
index 0000000..db75ac9
--- /dev/null
+++ b/lib/views/widgets/didvan/scaffold.dart
@@ -0,0 +1,136 @@
+import 'package:didvan/models/view/app_bar_data.dart';
+import 'package:didvan/views/widgets/didvan/app_bar.dart';
+import 'package:flutter/material.dart';
+
+class DidvanScaffold extends StatefulWidget {
+ final List? slivers;
+ final List? children;
+ final AppBarData appBarData;
+ final EdgeInsets padding;
+ final Color? backgroundColor;
+ final bool reverse;
+
+ const DidvanScaffold({
+ Key? key,
+ this.slivers,
+ required this.appBarData,
+ this.children,
+ this.padding = const EdgeInsets.symmetric(horizontal: 16),
+ this.backgroundColor,
+ this.reverse = false,
+ }) : super(key: key);
+
+ @override
+ State createState() => _DidvanScaffoldState();
+}
+
+class _DidvanScaffoldState extends State {
+ final _scrollController = ScrollController();
+
+ @override
+ Widget build(BuildContext context) {
+ final double statusBarHeight = MediaQuery.of(context).padding.top;
+ return Scaffold(
+ backgroundColor: widget.backgroundColor,
+ body: Padding(
+ padding: EdgeInsets.only(top: statusBarHeight),
+ child: Stack(
+ children: [
+ CustomScrollView(
+ controller: _scrollController,
+ reverse: widget.reverse,
+ slivers: [
+ if (!widget.reverse)
+ SliverAppBar(
+ toolbarHeight: kToolbarHeight,
+ backgroundColor: widget.backgroundColor ??
+ Theme.of(context).colorScheme.background,
+ automaticallyImplyLeading: false,
+ pinned: true,
+ flexibleSpace: DidvanAppBar(appBarData: widget.appBarData),
+ ),
+ if (!widget.reverse)
+ const SliverToBoxAdapter(
+ child: SizedBox(height: 16),
+ ),
+ if (widget.children != null)
+ SliverPadding(
+ padding: widget.padding,
+ sliver: SliverList(
+ delegate: SliverChildBuilderDelegate(
+ (context, index) => widget.children![index],
+ childCount: widget.children!.length,
+ ),
+ ),
+ ),
+ if (widget.slivers != null)
+ for (var i = 0; i < widget.slivers!.length; i++)
+ SliverPadding(
+ padding: widget.padding,
+ sliver: widget.slivers![i],
+ ),
+ if (widget.reverse)
+ SliverToBoxAdapter(
+ child: SizedBox(
+ height: kToolbarHeight +
+ MediaQuery.of(context).padding.top +
+ 12,
+ ),
+ ),
+ ],
+ ),
+ if (widget.reverse)
+ _AppBar(
+ appBarData: widget.appBarData,
+ scrollController: _scrollController,
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class _AppBar extends StatefulWidget {
+ final AppBarData appBarData;
+ final ScrollController scrollController;
+ const _AppBar({
+ Key? key,
+ required this.appBarData,
+ required this.scrollController,
+ }) : super(key: key);
+
+ @override
+ __AppBarState createState() => __AppBarState();
+}
+
+class __AppBarState extends State<_AppBar> {
+ bool _isScrolled = false;
+
+ @override
+ void initState() {
+ widget.scrollController.addListener(() {
+ final position = widget.scrollController.position.pixels;
+ if (position > 10 && _isScrolled == false) {
+ setState(() {
+ _isScrolled = true;
+ });
+ }
+ if (position < 10 && _isScrolled == true) {
+ setState(() {
+ _isScrolled = false;
+ });
+ }
+ });
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return DidvanAppBar(
+ backgroundColor: Theme.of(context).colorScheme.surface,
+ appBarData: widget.appBarData,
+ hasBorder: _isScrolled,
+ );
+ }
+}
diff --git a/lib/widgets/didvan/switch.dart b/lib/views/widgets/didvan/switch.dart
similarity index 95%
rename from lib/widgets/didvan/switch.dart
rename to lib/views/widgets/didvan/switch.dart
index 6b6841d..558a2f7 100644
--- a/lib/widgets/didvan/switch.dart
+++ b/lib/views/widgets/didvan/switch.dart
@@ -1,4 +1,4 @@
-import 'package:didvan/pages/home/widgets/menu_item.dart';
+import 'package:didvan/views/home/widgets/menu_item.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
diff --git a/lib/widgets/didvan/text.dart b/lib/views/widgets/didvan/text.dart
similarity index 100%
rename from lib/widgets/didvan/text.dart
rename to lib/views/widgets/didvan/text.dart
diff --git a/lib/widgets/didvan/text_field.dart b/lib/views/widgets/didvan/text_field.dart
similarity index 97%
rename from lib/widgets/didvan/text_field.dart
rename to lib/views/widgets/didvan/text_field.dart
index e8fbeb4..bf01ab4 100644
--- a/lib/widgets/didvan/text_field.dart
+++ b/lib/views/widgets/didvan/text_field.dart
@@ -1,8 +1,8 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
-import 'package:didvan/widgets/animated_visibility.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/animated_visibility.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
@@ -152,6 +152,7 @@ class _DidvanTextFieldState extends State {
if (_error != null) {
return Theme.of(context).colorScheme.error;
}
+ return null;
}
Color _fillColor() {
@@ -185,6 +186,7 @@ class _DidvanTextFieldState extends State {
),
);
}
+ return null;
}
void _onChanged(String value) {
@@ -209,6 +211,7 @@ class _DidvanTextFieldState extends State {
});
}
}
+ return null;
}
@override
diff --git a/lib/widgets/ink_wrapper.dart b/lib/views/widgets/ink_wrapper.dart
similarity index 100%
rename from lib/widgets/ink_wrapper.dart
rename to lib/views/widgets/ink_wrapper.dart
diff --git a/lib/widgets/item_title.dart b/lib/views/widgets/item_title.dart
similarity index 94%
rename from lib/widgets/item_title.dart
rename to lib/views/widgets/item_title.dart
index 1c0a89d..0477d87 100644
--- a/lib/widgets/item_title.dart
+++ b/lib/views/widgets/item_title.dart
@@ -1,5 +1,5 @@
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class ItemTitle extends StatelessWidget {
diff --git a/lib/widgets/logos/didvan_horizontal_logo.dart b/lib/views/widgets/logos/didvan_horizontal_logo.dart
similarity index 100%
rename from lib/widgets/logos/didvan_horizontal_logo.dart
rename to lib/views/widgets/logos/didvan_horizontal_logo.dart
diff --git a/lib/views/widgets/logos/didvan_vertical_logo.dart b/lib/views/widgets/logos/didvan_vertical_logo.dart
new file mode 100644
index 0000000..75cf9d5
--- /dev/null
+++ b/lib/views/widgets/logos/didvan_vertical_logo.dart
@@ -0,0 +1,21 @@
+import 'package:didvan/constants/assets.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+
+class DidvanHorizontalLogo extends StatelessWidget {
+ final String? type;
+ const DidvanHorizontalLogo({Key? key, this.type}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SvgPicture.asset(_asset);
+ }
+
+ String get _asset {
+ if (type == 'studio') {
+ return Assets.studioLogo;
+ } else {
+ return Assets.horizontalLogoWithText;
+ }
+ }
+}
diff --git a/lib/widgets/process_indicators.dart b/lib/views/widgets/process_indicators.dart
similarity index 100%
rename from lib/widgets/process_indicators.dart
rename to lib/views/widgets/process_indicators.dart
diff --git a/lib/widgets/shimmer_placeholder.dart b/lib/views/widgets/shimmer_placeholder.dart
similarity index 100%
rename from lib/widgets/shimmer_placeholder.dart
rename to lib/views/widgets/shimmer_placeholder.dart
diff --git a/lib/views/widgets/skeleton_image.dart b/lib/views/widgets/skeleton_image.dart
new file mode 100644
index 0000000..bf7db1c
--- /dev/null
+++ b/lib/views/widgets/skeleton_image.dart
@@ -0,0 +1,57 @@
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:didvan/config/design_config.dart';
+import 'package:didvan/services/network/request.dart';
+import 'package:didvan/services/network/request_helper.dart';
+import 'package:didvan/views/widgets/shimmer_placeholder.dart';
+import 'package:flutter/material.dart';
+import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
+
+class SkeletonImage extends StatelessWidget {
+ final String imageUrl;
+ final double width;
+ final double height;
+ final BorderRadius? borderRadius;
+ final double? aspectRatio;
+ const SkeletonImage({
+ Key? key,
+ required this.imageUrl,
+ this.width = 300,
+ this.height = 140,
+ this.borderRadius = DesignConfig.lowBorderRadius,
+ this.aspectRatio,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return _aspectRatioGenerator(
+ child: CachedNetworkImage(
+ imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet,
+ httpHeaders: {'Authorization': 'Bearer ${RequestService.token}'},
+ width: width,
+ height: height,
+ imageUrl: RequestHelper.baseUrl + imageUrl,
+ imageBuilder: (context, imageProvider) => Container(
+ decoration: BoxDecoration(
+ borderRadius: borderRadius ?? DesignConfig.lowBorderRadius,
+ image: DecorationImage(
+ image: imageProvider,
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ progressIndicatorBuilder: (context, url, progress) =>
+ ShimmerPlaceholder(
+ borderRadius: borderRadius,
+ ),
+ ),
+ );
+ }
+
+ Widget _aspectRatioGenerator({required Widget child}) => aspectRatio == null
+ ? SizedBox(key: ValueKey(imageUrl), child: child)
+ : AspectRatio(
+ key: ValueKey(imageUrl),
+ aspectRatio: aspectRatio!,
+ child: child,
+ );
+}
diff --git a/lib/widgets/state_handlers/empty_connection.dart b/lib/views/widgets/state_handlers/empty_connection.dart
similarity index 87%
rename from lib/widgets/state_handlers/empty_connection.dart
rename to lib/views/widgets/state_handlers/empty_connection.dart
index 53e87a6..c6543bb 100644
--- a/lib/widgets/state_handlers/empty_connection.dart
+++ b/lib/views/widgets/state_handlers/empty_connection.dart
@@ -1,5 +1,5 @@
import 'package:didvan/constants/assets.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:flutter/material.dart';
class EmptyConnection extends StatelessWidget {
diff --git a/lib/widgets/state_handlers/empty_list.dart b/lib/views/widgets/state_handlers/empty_list.dart
similarity index 82%
rename from lib/widgets/state_handlers/empty_list.dart
rename to lib/views/widgets/state_handlers/empty_list.dart
index da00ac7..9be66b6 100644
--- a/lib/widgets/state_handlers/empty_list.dart
+++ b/lib/views/widgets/state_handlers/empty_list.dart
@@ -1,5 +1,5 @@
import 'package:didvan/constants/assets.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:flutter/material.dart';
class EmptyList extends StatelessWidget {
diff --git a/lib/widgets/state_handlers/empty_result.dart b/lib/views/widgets/state_handlers/empty_result.dart
similarity index 87%
rename from lib/widgets/state_handlers/empty_result.dart
rename to lib/views/widgets/state_handlers/empty_result.dart
index bbb5fbb..1ae6b8f 100644
--- a/lib/widgets/state_handlers/empty_result.dart
+++ b/lib/views/widgets/state_handlers/empty_result.dart
@@ -1,5 +1,5 @@
import 'package:didvan/constants/assets.dart';
-import 'package:didvan/widgets/state_handlers/empty_state.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:flutter/material.dart';
class EmptyResult extends StatelessWidget {
diff --git a/lib/widgets/state_handlers/empty_state.dart b/lib/views/widgets/state_handlers/empty_state.dart
similarity index 92%
rename from lib/widgets/state_handlers/empty_state.dart
rename to lib/views/widgets/state_handlers/empty_state.dart
index 6d4a883..abfe420 100644
--- a/lib/widgets/state_handlers/empty_state.dart
+++ b/lib/views/widgets/state_handlers/empty_state.dart
@@ -1,6 +1,6 @@
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/widgets/didvan/button.dart';
-import 'package:didvan/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/didvan/button.dart';
+import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
diff --git a/lib/widgets/state_handlers/sliver_state_handler.dart b/lib/views/widgets/state_handlers/sliver_state_handler.dart
similarity index 96%
rename from lib/widgets/state_handlers/sliver_state_handler.dart
rename to lib/views/widgets/state_handlers/sliver_state_handler.dart
index e160f70..cb762f5 100644
--- a/lib/widgets/state_handlers/sliver_state_handler.dart
+++ b/lib/views/widgets/state_handlers/sliver_state_handler.dart
@@ -1,6 +1,6 @@
import 'package:didvan/models/enums.dart';
import 'package:didvan/providers/core_provider.dart';
-import 'package:didvan/widgets/state_handlers/empty_connection.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_connection.dart';
import 'package:flutter/material.dart';
class SliverStateHandler extends SliverList {
diff --git a/lib/widgets/state_handlers/state_handler.dart b/lib/views/widgets/state_handlers/state_handler.dart
similarity index 95%
rename from lib/widgets/state_handlers/state_handler.dart
rename to lib/views/widgets/state_handlers/state_handler.dart
index 107db8e..513ac3f 100644
--- a/lib/widgets/state_handlers/state_handler.dart
+++ b/lib/views/widgets/state_handlers/state_handler.dart
@@ -1,6 +1,6 @@
import 'package:didvan/models/enums.dart';
import 'package:didvan/providers/core_provider.dart';
-import 'package:didvan/widgets/state_handlers/empty_connection.dart';
+import 'package:didvan/views/widgets/state_handlers/empty_connection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
diff --git a/lib/widgets/didvan/page_view.dart b/lib/widgets/didvan/page_view.dart
deleted file mode 100644
index efbe19b..0000000
--- a/lib/widgets/didvan/page_view.dart
+++ /dev/null
@@ -1,188 +0,0 @@
-import 'package:carousel_slider/carousel_slider.dart';
-import 'package:didvan/utils/date_time.dart';
-import 'package:didvan/widgets/didvan/card.dart';
-import 'package:didvan/widgets/didvan/divider.dart';
-import 'package:didvan/widgets/didvan/text.dart';
-import 'package:didvan/widgets/skeleton_image.dart';
-import 'package:didvan/pages/home/widgets/tag_item.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_html/flutter_html.dart';
-
-class DidvanPageView extends StatefulWidget {
- final List items;
- final int initialIndex;
- final int currentIndex;
- final bool isRadar;
- final ScrollController scrollController;
-
- final void Function(int index) onPageChanged;
- const DidvanPageView({
- Key? key,
- required this.initialIndex,
- required this.items,
- required this.scrollController,
- required this.onPageChanged,
- required this.isRadar,
- required this.currentIndex,
- }) : super(key: key);
-
- @override
- State createState() => _DidvanPageViewState();
-}
-
-class _DidvanPageViewState extends State {
- @override
- Widget build(BuildContext context) {
- final double deviceTopPadding = MediaQuery.of(context).padding.top;
- return Directionality(
- textDirection: TextDirection.ltr,
- child: CarouselSlider.builder(
- itemCount: widget.items.length,
- options: CarouselOptions(
- onPageChanged: (index, reason) => widget.onPageChanged(index),
- height: double.infinity,
- initialPage: widget.initialIndex,
- viewportFraction: 0.94,
- enableInfiniteScroll: false,
- ),
- itemBuilder: (context, index, realIndex) => Directionality(
- textDirection: TextDirection.rtl,
- child: SizedBox(
- height: MediaQuery.of(context).size.height,
- child: SingleChildScrollView(
- controller:
- index == widget.currentIndex ? widget.scrollController : null,
- physics: const BouncingScrollPhysics(),
- padding: EdgeInsets.only(
- left: 4,
- right: 4,
- top: 16 + deviceTopPadding,
- bottom: 92,
- ),
- child: DidvanCard(
- padding: EdgeInsets.zero,
- enableBorder: false,
- child: Builder(
- builder: (context) {
- final item = widget.items[index];
- if (item == null) {
- return const SizedBox();
- }
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SkeletonImage(
- imageUrl: item.image,
- aspectRatio: 16 / 9,
- ),
- const SizedBox(height: 20),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: DidvanText(
- item.title,
- style: Theme.of(context).textTheme.subtitle1,
- ),
- ),
- const SizedBox(height: 8),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: _subtitle(item),
- ),
- for (var i = 0; i < item.contents.length; i++)
- Padding(
- padding: const EdgeInsets.symmetric(
- horizontal: 16,
- vertical: 4,
- ),
- child: _contentBuilder(item, i),
- ),
- if (item.tags.isNotEmpty) const SizedBox(height: 20),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Wrap(
- spacing: 8,
- runSpacing: 8,
- children: [
- for (var i = 0; i < item.tags.length; i++)
- TagItem(label: item.tags[i].label),
- ],
- ),
- ),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 16),
- child: DidvanDivider(),
- ),
- ],
- );
- },
- ),
- ),
- ),
- ),
- ),
- ),
- );
- }
-
- Widget _contentBuilder(dynamic item, int index) {
- final content = item.contents[index];
- if (content.text != null) {
- return Html(
- data: content.text,
- style: {
- '*': Style(
- direction: TextDirection.rtl,
- lineHeight: LineHeight.percent(135),
- // textAlign: TextAlign.justify,
- margin: EdgeInsets.zero,
- padding: EdgeInsets.zero,
- ),
- },
- );
- }
- if (content.image != null) {
- return SkeletonImage(
- imageUrl: content.image!,
- aspectRatio: 16 / 9,
- );
- }
- return const SizedBox();
- }
-
- Widget _subtitle(dynamic item) {
- if (widget.isRadar) {
- return Wrap(
- crossAxisAlignment: WrapCrossAlignment.center,
- children: [
- DidvanText(
- 'رادار ',
- style: Theme.of(context).textTheme.caption,
- ),
- for (var i = 0; i < item.categories.length; i++)
- DidvanText(
- item.categories[i].label +
- '${i != item.categories.length - 1 ? '،' : ''} ',
- style: Theme.of(context).textTheme.caption,
- ),
- DidvanText(
- ' - ' + DateTimeUtils.momentGenerator(item.createdAt),
- style: Theme.of(context).textTheme.caption,
- ),
- ],
- );
- } else {
- return Row(
- children: [
- DidvanText(
- item.reference,
- style: Theme.of(context).textTheme.caption,
- ),
- DidvanText(
- ' - ' + DateTimeUtils.momentGenerator(item.createdAt),
- style: Theme.of(context).textTheme.caption,
- ),
- ],
- );
- }
- }
-}
diff --git a/lib/widgets/didvan/scaffold.dart b/lib/widgets/didvan/scaffold.dart
deleted file mode 100644
index 6e00a7a..0000000
--- a/lib/widgets/didvan/scaffold.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-import 'package:didvan/models/view/app_bar_data.dart';
-import 'package:didvan/widgets/didvan/app_bar.dart';
-import 'package:flutter/material.dart';
-
-class DidvanScaffold extends StatelessWidget {
- final List? slivers;
- final List? children;
- final AppBarData appBarData;
- final EdgeInsets padding;
- final Color? backgroundColor;
- const DidvanScaffold({
- Key? key,
- this.slivers,
- required this.appBarData,
- this.children,
- this.padding = const EdgeInsets.symmetric(horizontal: 16),
- this.backgroundColor,
- }) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- final double statusBarHeight = MediaQuery.of(context).padding.top;
- return Scaffold(
- backgroundColor: backgroundColor,
- body: Padding(
- padding: EdgeInsets.only(top: statusBarHeight),
- child: CustomScrollView(
- slivers: [
- SliverAppBar(
- toolbarHeight: kToolbarHeight,
- backgroundColor:
- backgroundColor ?? Theme.of(context).colorScheme.background,
- automaticallyImplyLeading: false,
- pinned: true,
- flexibleSpace: DidvanAppBar(appBarData: appBarData),
- ),
- const SliverToBoxAdapter(
- child: SizedBox(height: 16),
- ),
- if (children != null)
- SliverPadding(
- padding: padding,
- sliver: SliverList(
- delegate: SliverChildBuilderDelegate(
- (context, index) => children![index],
- childCount: children!.length,
- ),
- ),
- ),
- if (slivers != null)
- for (var i = 0; i < slivers!.length; i++)
- SliverPadding(
- padding: padding,
- sliver: slivers![i],
- ),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/widgets/image_cropper.dart b/lib/widgets/image_cropper.dart
deleted file mode 100644
index fd67e93..0000000
--- a/lib/widgets/image_cropper.dart
+++ /dev/null
@@ -1,201 +0,0 @@
-import 'package:crop/crop.dart';
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart';
-import 'package:flutter/material.dart';
-
-class ImageCropper extends StatefulWidget {
- final Map data;
-
- const ImageCropper({Key? key, required this.data}) : super(key: key);
-
- @override
- State createState() => _ImageCropperState();
-}
-
-class _ImageCropperState extends State {
- double _rotation = 0;
- BoxShape shape = BoxShape.rectangle;
-
- final _controller = CropController();
-
- get _bytes => widget.data['bytes'];
- get _onCropped => widget.data['onCropped'];
-
- @override
- Widget build(BuildContext context) {
- final theme = Theme.of(context);
- return Scaffold(
- appBar: AppBar(
- title: const Text('برش عکس'),
- centerTitle: true,
- actions: [
- IconButton(
- onPressed: _cropImage,
- tooltip: 'Crop',
- icon: const Icon(Icons.crop),
- )
- ],
- ),
- body: Column(
- children: [
- Expanded(
- child: Container(
- color: Colors.black,
- padding: const EdgeInsets.all(8),
- child: Crop(
- onChanged: (decomposition) {
- if (_rotation != decomposition.rotation) {
- setState(() {
- _rotation = ((decomposition.rotation + 180) % 360) - 180;
- });
- }
- },
- controller: _controller,
- shape: shape,
- child: Image.memory(
- _bytes,
- fit: BoxFit.cover,
- ),
- helper: shape == BoxShape.rectangle
- ? Container(
- decoration: BoxDecoration(
- border: Border.all(color: Colors.white, width: 2),
- ),
- )
- : null,
- ),
- ),
- ),
- Row(
- children: [
- IconButton(
- icon: const Icon(Icons.redo),
- tooltip: 'برگرداندن',
- onPressed: () {
- _controller.rotation = 0;
- _controller.scale = 1;
- _controller.offset = Offset.zero;
- setState(() {
- _rotation = 0;
- });
- },
- ),
- Expanded(
- child: SliderTheme(
- data: theme.sliderTheme.copyWith(
- trackShape: const RectangularSliderTrackShape(),
- ),
- child: Slider(
- thumbColor: Theme.of(context).colorScheme.title,
- divisions: 360,
- value: _rotation,
- min: -180,
- max: 180,
- label: '$_rotation°',
- onChanged: (n) {
- setState(() {
- _rotation = n.roundToDouble();
- _controller.rotation = _rotation;
- });
- },
- ),
- ),
- ),
- // PopupMenuButton(
- // icon: const Icon(Icons.crop_free),
- // itemBuilder: (context) => [
- // const PopupMenuItem(
- // child: Text("Box"),
- // value: BoxShape.rectangle,
- // ),
- // const PopupMenuItem(
- // child: Text("Oval"),
- // value: BoxShape.circle,
- // ),
- // ],
- // tooltip: 'Crop Shape',
- // onSelected: (x) {
- // setState(() {
- // shape = x;
- // });
- // },
- // ),
- // PopupMenuButton(
- // icon: const Icon(Icons.aspect_ratio),
- // itemBuilder: (context) => [
- // const PopupMenuItem(
- // child: Text("Original"),
- // value: 1000 / 667.0,
- // ),
- // const PopupMenuDivider(),
- // const PopupMenuItem(
- // child: Text("16:9"),
- // value: 16.0 / 9.0,
- // ),
- // const PopupMenuItem(
- // child: Text("4:3"),
- // value: 4.0 / 3.0,
- // ),
- // const PopupMenuItem(
- // child: Text("1:1"),
- // value: 1,
- // ),
- // const PopupMenuItem(
- // child: Text("3:4"),
- // value: 3.0 / 4.0,
- // ),
- // const PopupMenuItem(
- // child: Text("9:16"),
- // value: 9.0 / 16.0,
- // ),
- // ],
- // tooltip: 'Aspect Ratio',
- // onSelected: (x) {
- // _controller.aspectRatio = x;
- // setState(() {});
- // },
- // ),
- ],
- ),
- ],
- ),
- );
- }
-
- void _cropImage() async {
- final pixelRatio = MediaQuery.of(context).devicePixelRatio;
- final cropped = await _controller.crop(pixelRatio: pixelRatio);
-
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (context) => Scaffold(
- appBar: AppBar(
- title: const Text('تایید برش'),
- centerTitle: true,
- actions: [
- Builder(
- builder: (context) => IconButton(
- icon: const Icon(
- DidvanIcons.check_circle_solid,
- size: 32,
- ),
- onPressed: () {
- Navigator.of(context).pop();
- Navigator.of(context).pop();
- _onCropped();
- },
- ),
- ),
- ],
- ),
- body: Center(
- child: RawImage(
- image: cropped,
- ),
- ),
- ),
- fullscreenDialog: true,
- ),
- );
- }
-}
diff --git a/lib/widgets/logos/didvan_vertical_logo.dart b/lib/widgets/logos/didvan_vertical_logo.dart
deleted file mode 100644
index 4f5637a..0000000
--- a/lib/widgets/logos/didvan_vertical_logo.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:didvan/constants/assets.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_svg/svg.dart';
-
-class DidvanHorizontalLogo extends StatelessWidget {
- const DidvanHorizontalLogo({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return SvgPicture.asset(Assets.horizontalLogoWithText);
- }
-}
diff --git a/lib/widgets/skeleton_image.dart b/lib/widgets/skeleton_image.dart
deleted file mode 100644
index ed1f93d..0000000
--- a/lib/widgets/skeleton_image.dart
+++ /dev/null
@@ -1,108 +0,0 @@
-import 'dart:typed_data';
-
-import 'package:didvan/widgets/shimmer_placeholder.dart';
-import 'package:http/http.dart' as http;
-import 'package:cached_network_image/cached_network_image.dart';
-import 'package:didvan/config/design_config.dart';
-import 'package:didvan/services/network/request.dart';
-import 'package:didvan/services/network/request_helper.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-
-class SkeletonImage extends StatefulWidget {
- final String imageUrl;
- final double width;
- final double height;
- final BorderRadius? borderRadius;
- final double? aspectRatio;
- const SkeletonImage({
- Key? key,
- required this.imageUrl,
- this.width = 300,
- this.height = 140,
- this.borderRadius = DesignConfig.lowBorderRadius,
- this.aspectRatio,
- }) : super(key: key);
-
- @override
- State createState() => _SkeletonImageState();
-}
-
-class _SkeletonImageState extends State {
- late Uint8List _bytes;
- bool _isLoading = true;
- @override
- void initState() {
- if (kIsWeb) _getImage();
- super.initState();
- }
-
- Future _getImage() async {
- final url = RequestHelper.baseUrl + widget.imageUrl;
- _bytes = (await http.get(
- Uri.parse(url),
- headers: {'Authorization': 'Bearer ${RequestService.token}'},
- ))
- .bodyBytes;
- if (mounted) {
- setState(() {
- _isLoading = false;
- });
- }
- }
-
- @override
- Widget build(BuildContext context) {
- if (kIsWeb) {
- if (_isLoading) {
- return _aspectRatioGenerator(
- child: ShimmerPlaceholder(
- borderRadius: widget.borderRadius,
- width: widget.aspectRatio == null ? widget.width : null,
- height: widget.aspectRatio == null ? widget.height : null,
- ),
- );
- }
- return _aspectRatioGenerator(
- child: ClipRRect(
- borderRadius: widget.borderRadius,
- child: Image.memory(
- _bytes,
- fit: BoxFit.cover,
- width: widget.width,
- height: widget.height,
- ),
- ),
- );
- }
- return _aspectRatioGenerator(
- child: CachedNetworkImage(
- httpHeaders: {'Authorization': 'Bearer ${RequestService.token}'},
- width: widget.width,
- height: widget.height,
- imageUrl: RequestHelper.baseUrl + widget.imageUrl,
- imageBuilder: (context, imageProvider) => Container(
- decoration: BoxDecoration(
- borderRadius: widget.borderRadius ?? DesignConfig.lowBorderRadius,
- image: DecorationImage(
- image: imageProvider,
- fit: BoxFit.cover,
- ),
- ),
- ),
- progressIndicatorBuilder: (context, url, progress) =>
- ShimmerPlaceholder(
- borderRadius: widget.borderRadius,
- ),
- ),
- );
- }
-
- Widget _aspectRatioGenerator({required Widget child}) =>
- widget.aspectRatio == null
- ? SizedBox(child: child)
- : AspectRatio(
- aspectRatio: widget.aspectRatio!,
- child: child,
- );
-}
diff --git a/pubspec.lock b/pubspec.lock
index fce966d..6942b4d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -15,6 +15,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.6+1"
+ audio_video_progress_bar:
+ dependency: "direct main"
+ description:
+ name: audio_video_progress_bar
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.10.0"
boolean_selector:
dependency: transitive
description:
@@ -85,20 +92,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
- collision:
- dependency: transitive
- description:
- name: collision
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.3"
- crop:
- dependency: "direct main"
- description:
- name: crop
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.5.2"
cross_file:
dependency: transitive
description:
@@ -155,48 +148,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
- firebase_core:
- dependency: "direct main"
- description:
- name: firebase_core
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.12.0"
- firebase_core_platform_interface:
- dependency: transitive
- description:
- name: firebase_core_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.2.4"
- firebase_core_web:
- dependency: transitive
- description:
- name: firebase_core_web
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.5.4"
- firebase_messaging:
- dependency: "direct main"
- description:
- name: firebase_messaging
- url: "https://pub.dartlang.org"
- source: hosted
- version: "11.2.6"
- firebase_messaging_platform_interface:
- dependency: transitive
- description:
- name: firebase_messaging_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.1.6"
- firebase_messaging_web:
- dependency: transitive
- description:
- name: firebase_messaging_web
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.2.7"
flutter:
dependency: "direct main"
description: flutter
@@ -343,6 +294,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
+ image_cropper:
+ dependency: "direct main"
+ description:
+ name: image_cropper
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.5.0"
image_picker:
dependency: "direct main"
description:
@@ -399,13 +357,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
- just_waveform:
- dependency: "direct main"
- description:
- name: just_waveform
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.1"
lints:
dependency: transitive
description:
@@ -420,6 +371,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.3"
meta:
dependency: transitive
description:
@@ -690,7 +648,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.3"
+ version: "0.4.8"
typed_data:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 90f4ef2..119a748 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -52,17 +52,15 @@ dependencies:
record: ^3.0.2
just_audio: ^0.9.18
record_web: ^0.2.1
- just_waveform: ^0.0.1
persian_datetime_picker: ^2.4.0
persian_number_utility: ^1.1.1
bot_toast: ^4.0.1
flutter_secure_storage: ^5.0.2
flutter_html: ^3.0.0-alpha.2
- crop: ^0.5.2
url_launcher: ^6.0.18
- firebase_messaging: ^11.2.6
- firebase_core: ^1.12.0
-
+ audio_video_progress_bar: ^0.10.0
+ image_cropper: ^1.5.0
+
dev_dependencies:
flutter_test:
@@ -92,6 +90,8 @@ flutter:
- lib/assets/images/logos/logo-vertical-light.svg
- lib/assets/images/logos/logo-horizontal-dark.svg
- lib/assets/images/logos/logo-horizontal-light.svg
+ - lib/assets/images/logos/studio-dark.svg
+ - lib/assets/images/logos/studio-light.svg
- lib/assets/images/categories/business-light.svg
- lib/assets/images/categories/economic-light.svg
- lib/assets/images/categories/enviromental-light.svg
@@ -122,6 +122,7 @@ flutter:
- lib/assets/images/empty_states/studio-dark.svg
- lib/assets/animations/indicator-light.riv
- lib/assets/animations/indicator-dark.riv
+ - lib/assets/loading.gif
diff --git a/web/index.html b/web/index.html
index 96d3c9c..a2dfb65 100644
--- a/web/index.html
+++ b/web/index.html
@@ -46,7 +46,7 @@
-

+