Merge branch 'dev' into 'test'
merge test from dev See merge request Didvan/didvan-app!3
|
|
@ -1,6 +1,7 @@
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- build/web
|
- build/web
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- push
|
- push
|
||||||
|
|
@ -11,9 +12,10 @@ build:
|
||||||
image: cirrusci/flutter:latest
|
image: cirrusci/flutter:latest
|
||||||
script:
|
script:
|
||||||
- flutter clean
|
- flutter clean
|
||||||
- flutter build web --web-renderer canvaskit
|
- flutter build web --web-renderer html
|
||||||
only:
|
only:
|
||||||
- test
|
- test
|
||||||
|
- dev
|
||||||
|
|
||||||
push:
|
push:
|
||||||
stage: push
|
stage: push
|
||||||
|
|
@ -26,8 +28,9 @@ push:
|
||||||
- docker push registry.gitlab.com/didvan/didvan-app/api:latest
|
- docker push registry.gitlab.com/didvan/didvan-app/api:latest
|
||||||
only:
|
only:
|
||||||
- test
|
- test
|
||||||
|
- dev
|
||||||
|
|
||||||
deploy:
|
deploy-test:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: python:3.10.2
|
image: python:3.10.2
|
||||||
variables:
|
variables:
|
||||||
|
|
@ -35,6 +38,18 @@ deploy:
|
||||||
script:
|
script:
|
||||||
- pip install fandogh_cli --upgrade
|
- pip install fandogh_cli --upgrade
|
||||||
- fandogh login --username=$FAN_USR --password=$FAN_PASS
|
- 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:
|
only:
|
||||||
- test
|
- 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
|
||||||
|
|
@ -22,7 +22,6 @@ if (flutterVersionName == null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
|
@ -66,7 +65,5 @@ flutter {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<application
|
<application
|
||||||
android:label="Didvan"
|
android:label="Didvan"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:usesCleartextTraffic="true">
|
||||||
<activity
|
<activity
|
||||||
|
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
|
|
@ -17,6 +19,9 @@
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="flutterEmbedding"
|
||||||
|
android:value="2" />
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
|
|
@ -31,10 +36,11 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
|
||||||
android:name="flutterEmbedding"
|
|
||||||
android:value="2" />
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.6.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.google.gms:google-services:4.3.10'
|
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 46;
|
objectVersion = 51;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
|
@ -31,9 +32,11 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
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 = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
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 = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
|
|
@ -42,6 +45,8 @@
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
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 = "<group>"; };
|
||||||
|
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 = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -49,12 +54,31 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
650C3E9A238A953E4E8E6AED /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
75DBECA488F412614712FB74 /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
8170350417391B7E9B77985B /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
C97DED20C4A171F16FB949CD /* Pods-Runner.debug.xcconfig */,
|
||||||
|
98ACB01D5FA5A78DB2686183 /* Pods-Runner.release.xcconfig */,
|
||||||
|
1CDA6531AC975E620DBA1134 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -72,6 +96,8 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
8170350417391B7E9B77985B /* Pods */,
|
||||||
|
650C3E9A238A953E4E8E6AED /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
|
@ -105,12 +131,14 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
9F9C99F59A6A1134B656560D /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
AE20B55CEF8506DDEEBE3543 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
|
@ -127,7 +155,7 @@
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1020;
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
|
|
@ -197,6 +225,45 @@
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
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 */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
|
@ -287,12 +354,19 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = W2PAW454F9;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
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_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
@ -411,12 +485,19 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = W2PAW454F9;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
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_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|
@ -430,12 +511,19 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = W2PAW454F9;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
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_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1020"
|
LastUpgradeVersion = "1300"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,7 @@
|
||||||
<FileRef
|
<FileRef
|
||||||
location = "group:Runner.xcodeproj">
|
location = "group:Runner.xcodeproj">
|
||||||
</FileRef>
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 516 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 974 B |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 564 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
|
@ -26,6 +26,12 @@
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>We need to access to the microphone to record audio file</string>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>We need to access to the user gallery to add user profile photo</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>We need to access to the user gallery to add user profile photo</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
|
@ -36,9 +36,9 @@ class LightThemeConfig {
|
||||||
|
|
||||||
static const ColorScheme _colorScheme = ColorScheme(
|
static const ColorScheme _colorScheme = ColorScheme(
|
||||||
primary: _primary,
|
primary: _primary,
|
||||||
primaryVariant: _white,
|
primaryContainer: _white,
|
||||||
secondary: Color(0xFFD61515),
|
secondary: Color(0xFFD61515),
|
||||||
secondaryVariant: _white,
|
secondaryContainer: _white,
|
||||||
surface: _white,
|
surface: _white,
|
||||||
background: _background,
|
background: _background,
|
||||||
error: Color(0xFFF00505),
|
error: Color(0xFFF00505),
|
||||||
|
|
@ -116,9 +116,9 @@ class DarkThemeConfig {
|
||||||
|
|
||||||
static const ColorScheme _colorScheme = ColorScheme(
|
static const ColorScheme _colorScheme = ColorScheme(
|
||||||
primary: _primary,
|
primary: _primary,
|
||||||
primaryVariant: _white,
|
primaryContainer: _white,
|
||||||
secondary: Color(0xFFE53939),
|
secondary: Color(0xFFE53939),
|
||||||
secondaryVariant: _white,
|
secondaryContainer: _white,
|
||||||
surface: Color(0xFF181B1F),
|
surface: Color(0xFF181B1F),
|
||||||
background: _background,
|
background: _background,
|
||||||
error: Color(0xFFF53B3B),
|
error: Color(0xFFF53B3B),
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@ class Assets {
|
||||||
static const String _baseEmptyStatesPath = _basePath + '/images/empty_states';
|
static const String _baseEmptyStatesPath = _basePath + '/images/empty_states';
|
||||||
static const String _baseAnimationsPath = _basePath + '/animations';
|
static const String _baseAnimationsPath = _basePath + '/animations';
|
||||||
static const String _baseRecordsPath = _basePath + '/images/records';
|
static const String _baseRecordsPath = _basePath + '/images/records';
|
||||||
|
static const String _baseLogosPath = _basePath + '/images/logos';
|
||||||
|
|
||||||
static String get verticalLogoWithText =>
|
static String get verticalLogoWithText =>
|
||||||
_baseImagesPath + '/logos/logo-vertical-$_themeSuffix.svg';
|
_baseLogosPath + '/logo-vertical-$_themeSuffix.svg';
|
||||||
static String get horizontalLogoWithText =>
|
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 =>
|
static String get logoLoadingAnimation =>
|
||||||
_baseAnimationsPath + '/indicator-$_themeSuffix.riv';
|
_baseAnimationsPath + '/indicator-$_themeSuffix.riv';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:didvan/config/theme_data.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/theme_provider.dart';
|
||||||
import 'package:didvan/providers/user_provider.dart';
|
import 'package:didvan/providers/user_provider.dart';
|
||||||
import 'package:didvan/routes/route_generator.dart';
|
import 'package:didvan/routes/route_generator.dart';
|
||||||
|
|
@ -24,9 +23,6 @@ class Didvan extends StatelessWidget {
|
||||||
ChangeNotifierProvider<UserProvider>(
|
ChangeNotifierProvider<UserProvider>(
|
||||||
create: (context) => UserProvider(),
|
create: (context) => UserProvider(),
|
||||||
),
|
),
|
||||||
ChangeNotifierProvider<ServerDataProvider>(
|
|
||||||
create: (context) => ServerDataProvider(),
|
|
||||||
),
|
|
||||||
ChangeNotifierProvider<ThemeProvider>(
|
ChangeNotifierProvider<ThemeProvider>(
|
||||||
create: (context) => ThemeProvider(),
|
create: (context) => ThemeProvider(),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
class Category {
|
class CategoryData {
|
||||||
final int id;
|
final int id;
|
||||||
final String label;
|
final String label;
|
||||||
|
|
||||||
const Category({required this.id, required this.label});
|
const CategoryData({required this.id, required this.label});
|
||||||
|
|
||||||
factory Category.fromJson(Map<String, dynamic> json) => Category(
|
factory CategoryData.fromJson(Map<String, dynamic> json) => CategoryData(
|
||||||
id: json['id'],
|
id: json['id'],
|
||||||
label: json['label'],
|
label: json['label'],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ class ChatRoom {
|
||||||
final int id;
|
final int id;
|
||||||
final String type;
|
final String type;
|
||||||
final String updatedAt;
|
final String updatedAt;
|
||||||
final int unread;
|
int unread;
|
||||||
final LastMessage lastMessage;
|
final LastMessage lastMessage;
|
||||||
|
|
||||||
const ChatRoom({
|
ChatRoom({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.type,
|
required this.type,
|
||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
|
|
|
||||||
|
|
@ -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<String, dynamic> json) => OverviewData(
|
|
||||||
id: json['id'],
|
|
||||||
title: json['title'],
|
|
||||||
image: json['image'],
|
|
||||||
description: json['description'],
|
|
||||||
createdAt: json['createdAt'],
|
|
||||||
type: json['type'],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'radar_attachment.dart';
|
import 'radar_attachment.dart';
|
||||||
|
|
||||||
class MessageData {
|
class MessageData {
|
||||||
|
|
@ -8,15 +11,19 @@ class MessageData {
|
||||||
final bool readed;
|
final bool readed;
|
||||||
final String createdAt;
|
final String createdAt;
|
||||||
final RadarAttachment? radar;
|
final RadarAttachment? radar;
|
||||||
|
final File? audioFile;
|
||||||
|
final int? audioDuration;
|
||||||
|
|
||||||
const MessageData({
|
const MessageData({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.writedByAdmin,
|
required this.writedByAdmin,
|
||||||
required this.readed,
|
required this.readed,
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
required this.text,
|
this.text,
|
||||||
required this.audio,
|
this.audio,
|
||||||
required this.radar,
|
this.radar,
|
||||||
|
this.audioFile,
|
||||||
|
this.audioDuration,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory MessageData.fromJson(Map<String, dynamic> json) => MessageData(
|
factory MessageData.fromJson(Map<String, dynamic> json) => MessageData(
|
||||||
|
|
@ -26,9 +33,12 @@ class MessageData {
|
||||||
writedByAdmin: json['writedByAdmin'],
|
writedByAdmin: json['writedByAdmin'],
|
||||||
readed: json['readed'],
|
readed: json['readed'],
|
||||||
createdAt: json['createdAt'],
|
createdAt: json['createdAt'],
|
||||||
|
audioDuration: json['waveform'] == null
|
||||||
|
? null
|
||||||
|
: jsonDecode(json['waveform'])['duration'] ?? 0,
|
||||||
radar: json['radar'] == null
|
radar: json['radar'] == null
|
||||||
? null
|
? null
|
||||||
: RadarAttachment.fromJson(json['radar'] as Map<String, dynamic>),
|
: RadarAttachment.fromJson(json['radar']),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:didvan/models/category.dart';
|
||||||
|
|
||||||
class RadarAttachment {
|
class RadarAttachment {
|
||||||
final int id;
|
final int id;
|
||||||
final String title;
|
final String title;
|
||||||
|
|
@ -5,6 +7,8 @@ class RadarAttachment {
|
||||||
final int timeToRead;
|
final int timeToRead;
|
||||||
final String image;
|
final String image;
|
||||||
final bool forManagers;
|
final bool forManagers;
|
||||||
|
final String createdAt;
|
||||||
|
final List<CategoryData> categories;
|
||||||
|
|
||||||
const RadarAttachment({
|
const RadarAttachment({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
|
@ -13,6 +17,8 @@ class RadarAttachment {
|
||||||
required this.timeToRead,
|
required this.timeToRead,
|
||||||
required this.image,
|
required this.image,
|
||||||
required this.forManagers,
|
required this.forManagers,
|
||||||
|
required this.categories,
|
||||||
|
required this.createdAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
|
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|
@ -22,7 +28,13 @@ class RadarAttachment {
|
||||||
description: json['description'],
|
description: json['description'],
|
||||||
timeToRead: json['timeToRead'],
|
timeToRead: json['timeToRead'],
|
||||||
image: json['image'],
|
image: json['image'],
|
||||||
|
createdAt: json['createdAt'],
|
||||||
forManagers: json['forManagers'],
|
forManagers: json['forManagers'],
|
||||||
|
categories: List<CategoryData>.from(
|
||||||
|
json['categories'].map(
|
||||||
|
(cat) => CategoryData.fromJson(cat),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:didvan/models/content.dart';
|
import 'package:didvan/models/content.dart';
|
||||||
|
import 'package:didvan/models/overview_data.dart';
|
||||||
import 'package:didvan/models/tag.dart';
|
import 'package:didvan/models/tag.dart';
|
||||||
|
|
||||||
class NewsDetailsData {
|
class NewsDetailsData {
|
||||||
|
|
@ -12,6 +13,7 @@ class NewsDetailsData {
|
||||||
final int order;
|
final int order;
|
||||||
final List<Tag> tags;
|
final List<Tag> tags;
|
||||||
final List<Content> contents;
|
final List<Content> contents;
|
||||||
|
final List<OverviewData> relatedContents = [];
|
||||||
|
|
||||||
NewsDetailsData({
|
NewsDetailsData({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
|
|
||||||
|
|
@ -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<String, dynamic> json) =>
|
|
||||||
NewsOverviewData(
|
|
||||||
id: json['id'],
|
|
||||||
title: json['title'],
|
|
||||||
reference: json['reference'],
|
|
||||||
description: json['description'],
|
|
||||||
image: json['image'],
|
|
||||||
createdAt: json['createdAt'],
|
|
||||||
marked: json['marked'] ?? true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -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<CategoryData>? 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<String, dynamic> 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<dynamic>?)
|
||||||
|
?.map((e) => CategoryData.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> 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(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:didvan/models/category.dart';
|
import 'package:didvan/models/category.dart';
|
||||||
|
import 'package:didvan/models/overview_data.dart';
|
||||||
|
|
||||||
import 'content.dart';
|
import 'content.dart';
|
||||||
import 'tag.dart';
|
import 'tag.dart';
|
||||||
|
|
@ -15,8 +16,9 @@ class RadarDetailsData {
|
||||||
int comments;
|
int comments;
|
||||||
final List<Tag> tags;
|
final List<Tag> tags;
|
||||||
final List<Content> contents;
|
final List<Content> contents;
|
||||||
final List<Category> categories;
|
final List<CategoryData> categories;
|
||||||
final int order;
|
final int order;
|
||||||
|
final List<OverviewData> relatedContents = [];
|
||||||
|
|
||||||
RadarDetailsData({
|
RadarDetailsData({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
|
@ -52,9 +54,9 @@ class RadarDetailsData {
|
||||||
(content) => Content.fromJson(content),
|
(content) => Content.fromJson(content),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
categories: List<Category>.from(
|
categories: List<CategoryData>.from(
|
||||||
json['categories'].map(
|
json['categories'].map(
|
||||||
(cat) => Category.fromJson(cat),
|
(cat) => CategoryData.fromJson(cat),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
import 'package:didvan/models/item_overview.dart';
|
|
||||||
|
|
||||||
import 'category.dart';
|
|
||||||
|
|
||||||
class RadarOverviewData extends OverviewData {
|
|
||||||
final bool forManagers;
|
|
||||||
final List<Category> 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<String, dynamic> 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<Category>.from(
|
|
||||||
json['categories'].map(
|
|
||||||
(category) => Category.fromJson(category),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -43,11 +43,11 @@ class User {
|
||||||
}) {
|
}) {
|
||||||
return User(
|
return User(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
username: username ?? this.username,
|
username: this.username,
|
||||||
phoneNumber: phoneNumber ?? this.phoneNumber,
|
phoneNumber: phoneNumber ?? this.phoneNumber,
|
||||||
photo: photo ?? this.photo,
|
photo: photo,
|
||||||
fullName: fullName ?? this.fullName,
|
fullName: fullName ?? this.fullName,
|
||||||
email: email ?? this.email,
|
email: email,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class ActionSheetData {
|
||||||
final IconData? titleIcon;
|
final IconData? titleIcon;
|
||||||
final Color? titleColor;
|
final Color? titleColor;
|
||||||
final bool hasDismissButton;
|
final bool hasDismissButton;
|
||||||
|
final bool hasConfirmButton;
|
||||||
final bool withoutButtonMode;
|
final bool withoutButtonMode;
|
||||||
final bool smallDismissButton;
|
final bool smallDismissButton;
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ class ActionSheetData {
|
||||||
this.onConfirmed,
|
this.onConfirmed,
|
||||||
this.titleColor,
|
this.titleColor,
|
||||||
this.hasDismissButton = true,
|
this.hasDismissButton = true,
|
||||||
|
this.hasConfirmButton = true,
|
||||||
this.titleIcon,
|
this.titleIcon,
|
||||||
this.dismissTitle,
|
this.dismissTitle,
|
||||||
this.onDismissed,
|
this.onDismissed,
|
||||||
|
|
|
||||||
|
|
@ -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<Direct> createState() => _DirectState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DirectState extends State<Direct> {
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
Future.delayed(Duration.zero, () {
|
|
||||||
context.read<DirectState>().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(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<void> 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<void> startRecording() async {
|
|
||||||
await _recorder.hasPermission();
|
|
||||||
if (!kIsWeb) {
|
|
||||||
Vibrate.feedback(FeedbackType.medium);
|
|
||||||
}
|
|
||||||
isRecording = true;
|
|
||||||
_recorder.start();
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> 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<void> sendMessage() async {}
|
|
||||||
}
|
|
||||||
|
|
@ -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<DirectState>(
|
|
||||||
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<DirectState>();
|
|
||||||
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<DirectState>();
|
|
||||||
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<DirectState>();
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<AudioVisualizer> createState() => _AudioVisualizerState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AudioVisualizerState extends State<AudioVisualizer> {
|
|
||||||
final AudioPlayer _audioPlayer = AudioPlayer();
|
|
||||||
|
|
||||||
Stream<WaveformProgress>? 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<Duration>(
|
|
||||||
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<WaveformProgress>(
|
|
||||||
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<bool>(
|
|
||||||
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<void> _setupAudioPlayer() async {
|
|
||||||
if (kIsWeb) {
|
|
||||||
await _audioPlayer.setUrl(
|
|
||||||
widget.audioFile.uri.path.replaceAll('%3A', ':'),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await _audioPlayer.setFilePath(widget.audioFile.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
import 'package:didvan/providers/core_provider.dart';
|
|
||||||
import 'package:didvan/services/network/request.dart';
|
import 'package:didvan/services/network/request.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
|
|
||||||
class ServerDataProvider extends CoreProvier {
|
class ServerDataProvider {
|
||||||
final List<MapEntry> directTypes = [];
|
static final List<MapEntry> directTypes = [];
|
||||||
|
|
||||||
Future<void> getData() async {
|
static Future<void> getData() async {
|
||||||
await _getDirectTypes();
|
await _getDirectTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _getDirectTypes() async {
|
static int labelToTypeId(String? label) => label == null
|
||||||
|
? 7
|
||||||
|
: directTypes.firstWhere((element) => element.value.contains(label)).key;
|
||||||
|
|
||||||
|
static Future<void> _getDirectTypes() async {
|
||||||
final service = RequestService(RequestHelper.directTypes);
|
final service = RequestService(RequestHelper.directTypes);
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
|
|
@ -17,6 +20,8 @@ class ServerDataProvider extends CoreProvier {
|
||||||
for (var i = 0; i < types.length; i++) {
|
for (var i = 0; i < types.length; i++) {
|
||||||
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
|
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
throw 'Fetchin direct types failed!';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class UserProvider extends CoreProvier {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
await StorageService.setValue(key: 'token', value: newToken);
|
await StorageService.setValue(key: 'token', value: newToken);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getUserInfo() async {
|
Future<void> getUserInfo() async {
|
||||||
|
|
@ -35,8 +36,15 @@ class UserProvider extends CoreProvier {
|
||||||
Future<bool> setProfilePhoto(dynamic file) async {
|
Future<bool> setProfilePhoto(dynamic file) async {
|
||||||
appState = AppState.isolatedBusy;
|
appState = AppState.isolatedBusy;
|
||||||
final RequestService service =
|
final RequestService service =
|
||||||
RequestService(RequestHelper.updateUserProfile);
|
RequestService(RequestHelper.updateProfilePhoto);
|
||||||
await service.multipart(file);
|
await service.multipart(
|
||||||
|
file: file,
|
||||||
|
method: 'PUT',
|
||||||
|
fileName: 'user-profile',
|
||||||
|
fieldName: 'photo',
|
||||||
|
mediaExtension: 'jpg',
|
||||||
|
mediaFormat: 'image',
|
||||||
|
);
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
user = user.copyWith(photo: service.result['photo']);
|
user = user.copyWith(photo: service.result['photo']);
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
|
|
@ -46,6 +54,20 @@ class UserProvider extends CoreProvier {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> 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<bool?> checkUsername(String username) async {
|
Future<bool?> checkUsername(String username) async {
|
||||||
if (user.username == username) return true;
|
if (user.username == username) return true;
|
||||||
final RequestService service = RequestService(
|
final RequestService service = RequestService(
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,32 @@
|
||||||
import 'package:didvan/pages/authentication/authentication.dart';
|
import 'package:didvan/models/tag.dart';
|
||||||
import 'package:didvan/pages/authentication/authentication_state.dart';
|
import 'package:didvan/views/authentication/authentication.dart';
|
||||||
import 'package:didvan/pages/home/comments/comments.dart';
|
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||||
import 'package:didvan/pages/home/comments/comments_state.dart';
|
import 'package:didvan/views/home/comments/comments.dart';
|
||||||
import 'package:didvan/pages/home/direct/direct.dart';
|
import 'package:didvan/views/home/comments/comments_state.dart';
|
||||||
import 'package:didvan/pages/home/direct/direct_state.dart';
|
import 'package:didvan/views/home/direct/direct.dart';
|
||||||
import 'package:didvan/pages/home/home.dart';
|
import 'package:didvan/views/home/direct/direct_state.dart';
|
||||||
import 'package:didvan/pages/home/home_state.dart';
|
import 'package:didvan/views/home/hashtag/hashtag.dart';
|
||||||
import 'package:didvan/pages/home/news/news_details/news_details.dart';
|
import 'package:didvan/views/home/hashtag/hashtag_state.dart';
|
||||||
import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
|
import 'package:didvan/views/home/home.dart';
|
||||||
import 'package:didvan/pages/home/news/news_state.dart';
|
import 'package:didvan/views/home/home_state.dart';
|
||||||
import 'package:didvan/pages/home/radar/radar_details/radar_details.dart';
|
import 'package:didvan/views/home/news/news_details/news_details.dart';
|
||||||
import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart';
|
import 'package:didvan/views/home/news/news_details/news_details_state.dart';
|
||||||
import 'package:didvan/pages/home/radar/radar_state.dart';
|
import 'package:didvan/views/home/news/news_state.dart';
|
||||||
import 'package:didvan/pages/home/settings/about_us/about_us.dart';
|
import 'package:didvan/views/home/radar/radar_details/radar_details.dart';
|
||||||
import 'package:didvan/pages/home/settings/bookmarks/bookmarks.dart';
|
import 'package:didvan/views/home/radar/radar_details/radar_details_state.dart';
|
||||||
import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
|
import 'package:didvan/views/home/radar/radar_state.dart';
|
||||||
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
|
import 'package:didvan/views/home/settings/about_us/about_us.dart';
|
||||||
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
|
import 'package:didvan/views/home/settings/bookmarks/bookmarks.dart';
|
||||||
import 'package:didvan/pages/home/settings/direct_list/direct_list.dart';
|
import 'package:didvan/views/home/settings/bookmarks/bookmark_state.dart';
|
||||||
import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
|
import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
|
||||||
import 'package:didvan/pages/home/settings/general_settings/settings.dart';
|
import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
|
||||||
import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
|
import 'package:didvan/views/home/settings/direct_list/direct_list.dart';
|
||||||
import 'package:didvan/pages/home/settings/profile/profile.dart';
|
import 'package:didvan/views/home/settings/direct_list/direct_list_state.dart';
|
||||||
import 'package:didvan/pages/splash/splash.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/routes/routes.dart';
|
||||||
import 'package:didvan/widgets/image_cropper.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
@ -67,12 +69,6 @@ class RouteGenerator {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
const AboutUs(),
|
const AboutUs(),
|
||||||
);
|
);
|
||||||
case Routes.imageCropper:
|
|
||||||
return _createRoute(
|
|
||||||
ImageCropper(
|
|
||||||
data: settings.arguments as Map<String, dynamic>,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
case Routes.generalSettings:
|
case Routes.generalSettings:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<GeneralSettingsState>(
|
ChangeNotifierProvider<GeneralSettingsState>(
|
||||||
|
|
@ -109,7 +105,7 @@ class RouteGenerator {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<DirectState>(
|
ChangeNotifierProvider<DirectState>(
|
||||||
create: (context) => DirectState(),
|
create: (context) => DirectState(),
|
||||||
child: Direct(id: settings.arguments as int),
|
child: Direct(pageData: settings.arguments as Map<String, dynamic>),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case Routes.comments:
|
case Routes.comments:
|
||||||
|
|
@ -128,6 +124,14 @@ class RouteGenerator {
|
||||||
child: const Bookmarks(),
|
child: const Bookmarks(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
case Routes.hashtag:
|
||||||
|
return _createRoute(
|
||||||
|
ChangeNotifierProvider<HashtagState>(
|
||||||
|
create: (context) => HashtagState(),
|
||||||
|
child: Hashtag(tag: settings.arguments as Tag),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
case Routes.filteredBookmarks:
|
case Routes.filteredBookmarks:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<FilteredBookmarksState>(
|
ChangeNotifierProvider<FilteredBookmarksState>(
|
||||||
|
|
@ -157,7 +161,13 @@ class RouteGenerator {
|
||||||
|
|
||||||
static Route _createRoute(page) {
|
static Route _createRoute(page) {
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (context) => page,
|
builder: (context) => Container(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
child: SafeArea(
|
||||||
|
child: page,
|
||||||
|
top: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@ class Routes {
|
||||||
static const String bookmarks = '/bookmarks';
|
static const String bookmarks = '/bookmarks';
|
||||||
static const String filteredBookmarks = '/filtered-bookmarks';
|
static const String filteredBookmarks = '/filtered-bookmarks';
|
||||||
static const String imageCropper = '/image-cropper';
|
static const String imageCropper = '/image-cropper';
|
||||||
|
static const String hashtag = '/hashtag';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
|
import 'package:didvan/services/media/media.dart';
|
||||||
import 'package:didvan/services/storage/storage.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/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
@ -11,8 +10,8 @@ class AppInitializer {
|
||||||
StorageService.appDocsDir =
|
StorageService.appDocsDir =
|
||||||
(await getApplicationDocumentsDirectory()).path;
|
(await getApplicationDocumentsDirectory()).path;
|
||||||
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
||||||
|
MediaService.init();
|
||||||
}
|
}
|
||||||
await _initializeFirebase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<ThemeMode> initilizeSettings() async {
|
static Future<ThemeMode> initilizeSettings() async {
|
||||||
|
|
@ -43,29 +42,4 @@ class AppInitializer {
|
||||||
return ThemeMode.light;
|
return ThemeMode.light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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:image_picker/image_picker.dart';
|
||||||
|
import 'package:just_audio/just_audio.dart';
|
||||||
|
|
||||||
class MediaService {
|
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<void> 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<XFile?> pickImage({required ImageSource source}) async {
|
static Future<XFile?> pickImage({required ImageSource source}) async {
|
||||||
final imagePicker = ImagePicker();
|
final imagePicker = ImagePicker();
|
||||||
final XFile? pickedFile = await imagePicker.pickImage(source: source);
|
final XFile? pickedFile = await imagePicker.pickImage(source: source);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:http_parser/http_parser.dart' as parser;
|
import 'package:http_parser/http_parser.dart' as parser;
|
||||||
import 'package:image_picker/image_picker.dart';
|
|
||||||
|
|
||||||
class RequestService {
|
class RequestService {
|
||||||
static late String token;
|
static late String token;
|
||||||
|
|
@ -100,19 +99,31 @@ class RequestService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> multipart(XFile file) async {
|
Future<void> multipart({
|
||||||
|
required dynamic file,
|
||||||
|
required String method,
|
||||||
|
required String fileName,
|
||||||
|
required String fieldName,
|
||||||
|
required String mediaFormat,
|
||||||
|
required String mediaExtension,
|
||||||
|
}) async {
|
||||||
try {
|
try {
|
||||||
final request = http.MultipartRequest('PUT', Uri.parse(url));
|
final request = http.MultipartRequest(method, Uri.parse(url));
|
||||||
_headers.update('Content-Type', (_) => 'multipart/form-data');
|
_headers.update('Content-Type', (_) => 'multipart/form-data');
|
||||||
request.headers.addAll(_headers);
|
request.headers.addAll(_headers);
|
||||||
final length = await file.length();
|
final length = await file.length();
|
||||||
|
if (_requestBody != null) {
|
||||||
|
_requestBody!.forEach((key, value) {
|
||||||
|
request.fields.addAll({key.toString(): value.toString()});
|
||||||
|
});
|
||||||
|
}
|
||||||
request.files.add(
|
request.files.add(
|
||||||
http.MultipartFile(
|
http.MultipartFile(
|
||||||
'photo',
|
fieldName,
|
||||||
file.readAsBytes().asStream(),
|
file.readAsBytes().asStream(),
|
||||||
length,
|
length,
|
||||||
filename: 'profile-photo',
|
filename: fileName + '.' + mediaExtension,
|
||||||
contentType: parser.MediaType('image', 'jpg'),
|
contentType: parser.MediaType(mediaFormat, mediaExtension),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final streamedResponse = await request
|
final streamedResponse = await request
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,37 @@ class RequestHelper {
|
||||||
static const String _baseUserUrl = baseUrl + '/user';
|
static const String _baseUserUrl = baseUrl + '/user';
|
||||||
static const String _baseRadarUrl = baseUrl + '/radar';
|
static const String _baseRadarUrl = baseUrl + '/radar';
|
||||||
static const String _baseNewsUrl = baseUrl + '/news';
|
static const String _baseNewsUrl = baseUrl + '/news';
|
||||||
|
static const String _baseDirectUrl = _baseUserUrl + '/direct';
|
||||||
|
|
||||||
static const String confirmUsername = _baseUserUrl + '/confirmUsername';
|
static const String confirmUsername = _baseUserUrl + '/confirmUsername';
|
||||||
static const String login = _baseUserUrl + '/login';
|
static const String login = _baseUserUrl + '/login';
|
||||||
static const String directs = _baseUserUrl + '/direct';
|
static const String directs = _baseUserUrl + '/direct';
|
||||||
static const String userInfo = _baseUserUrl + '/info';
|
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 checkUsername = _baseUserUrl + '/CheckUsername';
|
||||||
static const String updateProfile = _baseUserUrl + '/profile/edit';
|
static const String updateProfile = _baseUserUrl + '/profile/edit';
|
||||||
static String bookmarks({String? type}) =>
|
static String bookmarks({String? type}) =>
|
||||||
_baseUserUrl + '/marked/${type ?? ''}';
|
_baseUserUrl + '/marked/${type ?? ''}';
|
||||||
|
|
||||||
static const String directTypes = baseUrl + '/direct/types';
|
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<int> 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 markRadar(int id) => _baseRadarUrl + '/$id/mark';
|
||||||
static String radarComments(int id) => _baseRadarUrl + '/$id/comments';
|
static String radarComments(int id) => _baseRadarUrl + '/$id/comments';
|
||||||
|
|
@ -96,5 +114,6 @@ class RequestHelper {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import 'package:didvan/constants/assets.dart';
|
||||||
import 'package:didvan/models/enums.dart';
|
import 'package:didvan/models/enums.dart';
|
||||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
import 'package:didvan/models/view/alert_data.dart';
|
import 'package:didvan/models/view/alert_data.dart';
|
||||||
import 'package:didvan/widgets/didvan/button.dart';
|
import 'package:didvan/views/widgets/didvan/button.dart';
|
||||||
import 'package:didvan/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:rive/rive.dart';
|
import 'package:rive/rive.dart';
|
||||||
|
|
||||||
|
|
@ -83,9 +83,7 @@ class ActionSheetUtils {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: const BorderRadius.vertical(
|
borderRadius: const BorderRadius.vertical(
|
||||||
top: Radius.circular(
|
top: Radius.circular(10),
|
||||||
10,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
|
|
@ -136,6 +134,7 @@ class ActionSheetUtils {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (data.hasDismissButton) const SizedBox(width: 20),
|
if (data.hasDismissButton) const SizedBox(width: 20),
|
||||||
|
if (data.hasConfirmButton)
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: data.smallDismissButton ? 2 : 1,
|
flex: data.smallDismissButton ? 2 : 1,
|
||||||
child: DidvanButton(
|
child: DidvanButton(
|
||||||
|
|
@ -160,6 +159,7 @@ class ActionSheetUtils {
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Dialog(
|
builder: (context) => Dialog(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: DesignConfig.mediumBorderRadius,
|
borderRadius: DesignConfig.mediumBorderRadius,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,31 @@ class DateTimeUtils {
|
||||||
return result?.toDateTime().toString();
|
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) {
|
static String momentGenerator(String input) {
|
||||||
final date = DateTime.parse(input);
|
final date = DateTime.parse(input);
|
||||||
final int seconds = (DateTime.now().difference(date).inSeconds).floor();
|
final int seconds = (DateTime.now().difference(date).inSeconds).floor();
|
||||||
|
|
@ -67,6 +92,7 @@ class DateTimeUtils {
|
||||||
}
|
}
|
||||||
interval = seconds / 86400;
|
interval = seconds / 86400;
|
||||||
if (interval > 1) {
|
if (interval > 1) {
|
||||||
|
if (interval.floor() == 1) return 'دیروز';
|
||||||
return interval.floor().toString() + " روز پیش";
|
return interval.floor().toString() + " روز پیش";
|
||||||
}
|
}
|
||||||
interval = seconds / 3600;
|
interval = seconds / 3600;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/pages/authentication/authentication_state.dart';
|
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||||
import 'package:didvan/pages/authentication/screens/password.dart';
|
import 'package:didvan/views/authentication/screens/password.dart';
|
||||||
import 'package:didvan/pages/authentication/screens/username.dart';
|
import 'package:didvan/views/authentication/screens/reset_password.dart';
|
||||||
import 'package:didvan/pages/authentication/screens/reset_password.dart';
|
import 'package:didvan/views/authentication/screens/username.dart';
|
||||||
import 'package:didvan/pages/authentication/screens/verification.dart';
|
import 'package:didvan/views/authentication/screens/verification.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
@ -55,5 +55,6 @@ class AuthenticationState extends CoreProvier {
|
||||||
appState = AppState.failed;
|
appState = AppState.failed;
|
||||||
ActionSheetUtils.showAlert(AlertData(message: service.errorMessage));
|
ActionSheetUtils.showAlert(AlertData(message: service.errorMessage));
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
import 'package:didvan/pages/authentication/authentication_state.dart';
|
import 'dart:developer';
|
||||||
import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
|
|
||||||
|
import 'package:didvan/providers/server_data_provider.dart';
|
||||||
import 'package:didvan/providers/user_provider.dart';
|
import 'package:didvan/providers/user_provider.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/widgets/didvan/button.dart';
|
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||||
import 'package:didvan/widgets/didvan/text.dart';
|
import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
|
||||||
import 'package:didvan/widgets/didvan/text_field.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:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
@ -70,6 +73,8 @@ class _PasswordInputState extends State<PasswordInput> {
|
||||||
final userProvider = context.read<UserProvider>();
|
final userProvider = context.read<UserProvider>();
|
||||||
final token = await state.login(userProvider);
|
final token = await state.login(userProvider);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
|
log(token);
|
||||||
|
await ServerDataProvider.getData();
|
||||||
Navigator.of(context).pushReplacementNamed(Routes.home);
|
Navigator.of(context).pushReplacementNamed(Routes.home);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||