Merge branch 'dev' into 'test'

merge test from dev

See merge request Didvan/didvan-app!3
This commit is contained in:
MohammadTaha Basiri 2022-03-02 10:27:40 +00:00
commit 66f1808f75
196 changed files with 3206 additions and 2038 deletions

View File

@ -1,6 +1,7 @@
cache:
paths:
cache:
paths:
- build/web
stages:
- build
- push
@ -11,9 +12,10 @@ build:
image: cirrusci/flutter:latest
script:
- flutter clean
- flutter build web --web-renderer canvaskit
- flutter build web --web-renderer html
only:
- test
- dev
push:
stage: push
@ -26,8 +28,9 @@ push:
- docker push registry.gitlab.com/didvan/didvan-app/api:latest
only:
- test
- dev
deploy:
deploy-test:
stage: deploy
image: python:3.10.2
variables:
@ -35,6 +38,18 @@ deploy:
script:
- pip install fandogh_cli --upgrade
- fandogh login --username=$FAN_USR --password=$FAN_PASS
- fandogh service apply -f ./deployment/config.yaml -p SEC_NAME
- fandogh service apply -f ./deployment/test.yaml -p SEC_NAME
only:
- test
deploy-dev:
stage: deploy
image: python:3.10.2
variables:
COLLECT_ERROR: 1
script:
- pip install fandogh_cli --upgrade
- fandogh login --username=$FAN_USR --password=$FAN_PASS
- fandogh service apply -f ./deployment/dev.yaml -p SEC_NAME
only:
- dev

View File

@ -22,7 +22,6 @@ if (flutterVersionName == null) {
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@ -66,7 +65,5 @@ flutter {
}
dependencies {
implementation platform('com.google.firebase:firebase-bom:29.0.4')
implementation 'com.google.firebase:firebase-analytics'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

View File

@ -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"
}

View File

@ -5,8 +5,10 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="Didvan"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
@ -17,6 +19,9 @@
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
@ -31,10 +36,11 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</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.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

View File

@ -1,12 +1,11 @@
buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

14
deployment/dev.yaml Normal file
View File

@ -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

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

41
ios/Podfile Normal file
View File

@ -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

89
ios/Podfile.lock Normal file
View File

@ -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

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -13,6 +13,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75DBECA488F412614712FB74 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -31,9 +32,11 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<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>"; };
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>"; };
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>"; };
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>"; };
@ -42,6 +45,8 @@
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
@ -49,12 +54,31 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
650C3E9A238A953E4E8E6AED /* Frameworks */ = {
isa = PBXGroup;
children = (
75DBECA488F412614712FB74 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<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 */ = {
isa = PBXGroup;
children = (
@ -72,6 +96,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
8170350417391B7E9B77985B /* Pods */,
650C3E9A238A953E4E8E6AED /* Frameworks */,
);
sourceTree = "<group>";
};
@ -105,12 +131,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9F9C99F59A6A1134B656560D /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
AE20B55CEF8506DDEEBE3543 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -127,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@ -197,6 +225,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
9F9C99F59A6A1134B656560D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
AE20B55CEF8506DDEEBE3543 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -287,12 +354,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@ -411,12 +485,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -430,12 +511,19 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = W2PAW454F9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.didvan.didvanapp;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -26,6 +26,12 @@
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<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>
<array>
<string>UIInterfaceOrientationPortrait</string>

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -36,9 +36,9 @@ class LightThemeConfig {
static const ColorScheme _colorScheme = ColorScheme(
primary: _primary,
primaryVariant: _white,
primaryContainer: _white,
secondary: Color(0xFFD61515),
secondaryVariant: _white,
secondaryContainer: _white,
surface: _white,
background: _background,
error: Color(0xFFF00505),
@ -116,9 +116,9 @@ class DarkThemeConfig {
static const ColorScheme _colorScheme = ColorScheme(
primary: _primary,
primaryVariant: _white,
primaryContainer: _white,
secondary: Color(0xFFE53939),
secondaryVariant: _white,
secondaryContainer: _white,
surface: Color(0xFF181B1F),
background: _background,
error: Color(0xFFF53B3B),

View File

@ -8,11 +8,13 @@ class Assets {
static const String _baseEmptyStatesPath = _basePath + '/images/empty_states';
static const String _baseAnimationsPath = _basePath + '/animations';
static const String _baseRecordsPath = _basePath + '/images/records';
static const String _baseLogosPath = _basePath + '/images/logos';
static String get verticalLogoWithText =>
_baseImagesPath + '/logos/logo-vertical-$_themeSuffix.svg';
_baseLogosPath + '/logo-vertical-$_themeSuffix.svg';
static String get horizontalLogoWithText =>
_baseImagesPath + '/logos/logo-horizontal-$_themeSuffix.svg';
_baseLogosPath + '/logo-horizontal-$_themeSuffix.svg';
static String get studioLogo => _baseLogosPath + '/studio-$_themeSuffix.svg';
static String get logoLoadingAnimation =>
_baseAnimationsPath + '/indicator-$_themeSuffix.riv';

View File

@ -1,6 +1,5 @@
import 'package:bot_toast/bot_toast.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/providers/server_data_provider.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/route_generator.dart';
@ -24,9 +23,6 @@ class Didvan extends StatelessWidget {
ChangeNotifierProvider<UserProvider>(
create: (context) => UserProvider(),
),
ChangeNotifierProvider<ServerDataProvider>(
create: (context) => ServerDataProvider(),
),
ChangeNotifierProvider<ThemeProvider>(
create: (context) => ThemeProvider(),
),

View File

@ -1,10 +1,10 @@
class Category {
class CategoryData {
final int id;
final String label;
const Category({required this.id, required this.label});
const CategoryData({required this.id, required this.label});
factory Category.fromJson(Map<String, dynamic> json) => Category(
factory CategoryData.fromJson(Map<String, dynamic> json) => CategoryData(
id: json['id'],
label: json['label'],
);

View File

@ -4,10 +4,10 @@ class ChatRoom {
final int id;
final String type;
final String updatedAt;
final int unread;
int unread;
final LastMessage lastMessage;
const ChatRoom({
ChatRoom({
required this.id,
required this.type,
required this.updatedAt,

View File

@ -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'],
);
}

View File

@ -1,3 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'radar_attachment.dart';
class MessageData {
@ -8,15 +11,19 @@ class MessageData {
final bool readed;
final String createdAt;
final RadarAttachment? radar;
final File? audioFile;
final int? audioDuration;
const MessageData({
required this.id,
required this.writedByAdmin,
required this.readed,
required this.createdAt,
required this.text,
required this.audio,
required this.radar,
this.text,
this.audio,
this.radar,
this.audioFile,
this.audioDuration,
});
factory MessageData.fromJson(Map<String, dynamic> json) => MessageData(
@ -26,9 +33,12 @@ class MessageData {
writedByAdmin: json['writedByAdmin'],
readed: json['readed'],
createdAt: json['createdAt'],
audioDuration: json['waveform'] == null
? null
: jsonDecode(json['waveform'])['duration'] ?? 0,
radar: json['radar'] == null
? null
: RadarAttachment.fromJson(json['radar'] as Map<String, dynamic>),
: RadarAttachment.fromJson(json['radar']),
);
Map<String, dynamic> toJson() => {

View File

@ -1,3 +1,5 @@
import 'package:didvan/models/category.dart';
class RadarAttachment {
final int id;
final String title;
@ -5,6 +7,8 @@ class RadarAttachment {
final int timeToRead;
final String image;
final bool forManagers;
final String createdAt;
final List<CategoryData> categories;
const RadarAttachment({
required this.id,
@ -13,6 +17,8 @@ class RadarAttachment {
required this.timeToRead,
required this.image,
required this.forManagers,
required this.categories,
required this.createdAt,
});
factory RadarAttachment.fromJson(Map<String, dynamic> json) =>
@ -22,7 +28,13 @@ class RadarAttachment {
description: json['description'],
timeToRead: json['timeToRead'],
image: json['image'],
createdAt: json['createdAt'],
forManagers: json['forManagers'],
categories: List<CategoryData>.from(
json['categories'].map(
(cat) => CategoryData.fromJson(cat),
),
),
);
Map<String, dynamic> toJson() => {

View File

@ -1,4 +1,5 @@
import 'package:didvan/models/content.dart';
import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/tag.dart';
class NewsDetailsData {
@ -12,6 +13,7 @@ class NewsDetailsData {
final int order;
final List<Tag> tags;
final List<Content> contents;
final List<OverviewData> relatedContents = [];
NewsDetailsData({
required this.id,

View File

@ -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,
);
}

View File

@ -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(),
};
}

View File

@ -1,4 +1,5 @@
import 'package:didvan/models/category.dart';
import 'package:didvan/models/overview_data.dart';
import 'content.dart';
import 'tag.dart';
@ -15,8 +16,9 @@ class RadarDetailsData {
int comments;
final List<Tag> tags;
final List<Content> contents;
final List<Category> categories;
final List<CategoryData> categories;
final int order;
final List<OverviewData> relatedContents = [];
RadarDetailsData({
required this.id,
@ -52,9 +54,9 @@ class RadarDetailsData {
(content) => Content.fromJson(content),
),
),
categories: List<Category>.from(
categories: List<CategoryData>.from(
json['categories'].map(
(cat) => Category.fromJson(cat),
(cat) => CategoryData.fromJson(cat),
),
),
);

View File

@ -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),
),
),
);
}

View File

@ -43,11 +43,11 @@ class User {
}) {
return User(
id: id ?? this.id,
username: username ?? this.username,
username: this.username,
phoneNumber: phoneNumber ?? this.phoneNumber,
photo: photo ?? this.photo,
photo: photo,
fullName: fullName ?? this.fullName,
email: email ?? this.email,
email: email,
);
}
}

View File

@ -10,6 +10,7 @@ class ActionSheetData {
final IconData? titleIcon;
final Color? titleColor;
final bool hasDismissButton;
final bool hasConfirmButton;
final bool withoutButtonMode;
final bool smallDismissButton;
@ -20,6 +21,7 @@ class ActionSheetData {
this.onConfirmed,
this.titleColor,
this.hasDismissButton = true,
this.hasConfirmButton = true,
this.titleIcon,
this.dismissTitle,
this.onDismissed,

View File

@ -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(),
),
],
),
);
}
}

View File

@ -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 {}
}

View File

@ -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,
),
],
);
}
}

View File

@ -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,
),
),
],
);
}
}

View File

@ -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;
}
}

View File

@ -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,
),
],
),
);
}
}

View File

@ -1,15 +1,18 @@
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
class ServerDataProvider extends CoreProvier {
final List<MapEntry> directTypes = [];
class ServerDataProvider {
static final List<MapEntry> directTypes = [];
Future<void> getData() async {
static Future<void> getData() async {
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);
await service.httpGet();
if (service.isSuccess) {
@ -17,6 +20,8 @@ class ServerDataProvider extends CoreProvier {
for (var i = 0; i < types.length; i++) {
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
}
} else {
throw 'Fetchin direct types failed!';
}
}
}

View File

@ -20,6 +20,7 @@ class UserProvider extends CoreProvier {
return token;
}
await StorageService.setValue(key: 'token', value: newToken);
return null;
}
Future<void> getUserInfo() async {
@ -35,8 +36,15 @@ class UserProvider extends CoreProvier {
Future<bool> setProfilePhoto(dynamic file) async {
appState = AppState.isolatedBusy;
final RequestService service =
RequestService(RequestHelper.updateUserProfile);
await service.multipart(file);
RequestService(RequestHelper.updateProfilePhoto);
await service.multipart(
file: file,
method: 'PUT',
fileName: 'user-profile',
fieldName: 'photo',
mediaExtension: 'jpg',
mediaFormat: 'image',
);
if (service.isSuccess) {
user = user.copyWith(photo: service.result['photo']);
appState = AppState.idle;
@ -46,6 +54,20 @@ class UserProvider extends CoreProvier {
return false;
}
Future<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 {
if (user.username == username) return true;
final RequestService service = RequestService(

View File

@ -1,30 +1,32 @@
import 'package:didvan/pages/authentication/authentication.dart';
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/pages/home/comments/comments.dart';
import 'package:didvan/pages/home/comments/comments_state.dart';
import 'package:didvan/pages/home/direct/direct.dart';
import 'package:didvan/pages/home/direct/direct_state.dart';
import 'package:didvan/pages/home/home.dart';
import 'package:didvan/pages/home/home_state.dart';
import 'package:didvan/pages/home/news/news_details/news_details.dart';
import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
import 'package:didvan/pages/home/news/news_state.dart';
import 'package:didvan/pages/home/radar/radar_details/radar_details.dart';
import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart';
import 'package:didvan/pages/home/radar/radar_state.dart';
import 'package:didvan/pages/home/settings/about_us/about_us.dart';
import 'package:didvan/pages/home/settings/bookmarks/bookmarks.dart';
import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
import 'package:didvan/pages/home/settings/direct_list/direct_list.dart';
import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
import 'package:didvan/pages/home/settings/general_settings/settings.dart';
import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
import 'package:didvan/pages/home/settings/profile/profile.dart';
import 'package:didvan/pages/splash/splash.dart';
import 'package:didvan/models/tag.dart';
import 'package:didvan/views/authentication/authentication.dart';
import 'package:didvan/views/authentication/authentication_state.dart';
import 'package:didvan/views/home/comments/comments.dart';
import 'package:didvan/views/home/comments/comments_state.dart';
import 'package:didvan/views/home/direct/direct.dart';
import 'package:didvan/views/home/direct/direct_state.dart';
import 'package:didvan/views/home/hashtag/hashtag.dart';
import 'package:didvan/views/home/hashtag/hashtag_state.dart';
import 'package:didvan/views/home/home.dart';
import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/views/home/news/news_details/news_details.dart';
import 'package:didvan/views/home/news/news_details/news_details_state.dart';
import 'package:didvan/views/home/news/news_state.dart';
import 'package:didvan/views/home/radar/radar_details/radar_details.dart';
import 'package:didvan/views/home/radar/radar_details/radar_details_state.dart';
import 'package:didvan/views/home/radar/radar_state.dart';
import 'package:didvan/views/home/settings/about_us/about_us.dart';
import 'package:didvan/views/home/settings/bookmarks/bookmarks.dart';
import 'package:didvan/views/home/settings/bookmarks/bookmark_state.dart';
import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
import 'package:didvan/views/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
import 'package:didvan/views/home/settings/direct_list/direct_list.dart';
import 'package:didvan/views/home/settings/direct_list/direct_list_state.dart';
import 'package:didvan/views/home/settings/general_settings/settings.dart';
import 'package:didvan/views/home/settings/general_settings/settings_state.dart';
import 'package:didvan/views/home/settings/profile/profile.dart';
import 'package:didvan/views/splash/splash.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/image_cropper.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -67,12 +69,6 @@ class RouteGenerator {
return _createRoute(
const AboutUs(),
);
case Routes.imageCropper:
return _createRoute(
ImageCropper(
data: settings.arguments as Map<String, dynamic>,
),
);
case Routes.generalSettings:
return _createRoute(
ChangeNotifierProvider<GeneralSettingsState>(
@ -109,7 +105,7 @@ class RouteGenerator {
return _createRoute(
ChangeNotifierProvider<DirectState>(
create: (context) => DirectState(),
child: Direct(id: settings.arguments as int),
child: Direct(pageData: settings.arguments as Map<String, dynamic>),
),
);
case Routes.comments:
@ -128,6 +124,14 @@ class RouteGenerator {
child: const Bookmarks(),
),
);
case Routes.hashtag:
return _createRoute(
ChangeNotifierProvider<HashtagState>(
create: (context) => HashtagState(),
child: Hashtag(tag: settings.arguments as Tag),
),
);
case Routes.filteredBookmarks:
return _createRoute(
ChangeNotifierProvider<FilteredBookmarksState>(
@ -157,7 +161,13 @@ class RouteGenerator {
static Route _createRoute(page) {
return MaterialPageRoute(
builder: (context) => page,
builder: (context) => Container(
color: Theme.of(context).colorScheme.surface,
child: SafeArea(
child: page,
top: false,
),
),
);
}
}

View File

@ -14,4 +14,5 @@ class Routes {
static const String bookmarks = '/bookmarks';
static const String filteredBookmarks = '/filtered-bookmarks';
static const String imageCropper = '/image-cropper';
static const String hashtag = '/hashtag';
}

View File

@ -1,6 +1,5 @@
import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/storage/storage.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
@ -11,8 +10,8 @@ class AppInitializer {
StorageService.appDocsDir =
(await getApplicationDocumentsDirectory()).path;
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
MediaService.init();
}
await _initializeFirebase();
}
static Future<ThemeMode> initilizeSettings() async {
@ -43,29 +42,4 @@ class AppInitializer {
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,
);
}
}

View File

@ -1,6 +1,59 @@
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
import 'package:just_audio/just_audio.dart';
class MediaService {
static final AudioPlayer audioPlayer = AudioPlayer();
static String? audioPlayerTag;
static void init() {
audioPlayer.positionStream.listen((event) {
if (audioPlayer.duration != null && audioPlayer.duration! < event) {
audioPlayer.stop();
audioPlayer.seek(const Duration(seconds: 0));
}
});
}
static Future<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 {
final imagePicker = ImagePicker();
final XFile? pickedFile = await imagePicker.pickImage(source: source);

View File

@ -2,7 +2,6 @@ import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart' as parser;
import 'package:image_picker/image_picker.dart';
class RequestService {
static late String token;
@ -100,19 +99,31 @@ class RequestService {
}
}
Future<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 {
final request = http.MultipartRequest('PUT', Uri.parse(url));
final request = http.MultipartRequest(method, Uri.parse(url));
_headers.update('Content-Type', (_) => 'multipart/form-data');
request.headers.addAll(_headers);
final length = await file.length();
if (_requestBody != null) {
_requestBody!.forEach((key, value) {
request.fields.addAll({key.toString(): value.toString()});
});
}
request.files.add(
http.MultipartFile(
'photo',
fieldName,
file.readAsBytes().asStream(),
length,
filename: 'profile-photo',
contentType: parser.MediaType('image', 'jpg'),
filename: fileName + '.' + mediaExtension,
contentType: parser.MediaType(mediaFormat, mediaExtension),
),
);
final streamedResponse = await request

View File

@ -6,19 +6,37 @@ class RequestHelper {
static const String _baseUserUrl = baseUrl + '/user';
static const String _baseRadarUrl = baseUrl + '/radar';
static const String _baseNewsUrl = baseUrl + '/news';
static const String _baseDirectUrl = _baseUserUrl + '/direct';
static const String confirmUsername = _baseUserUrl + '/confirmUsername';
static const String login = _baseUserUrl + '/login';
static const String directs = _baseUserUrl + '/direct';
static const String userInfo = _baseUserUrl + '/info';
static const String updateUserProfile = _baseUserUrl + '/profile/photo';
static const String updateProfilePhoto = _baseUserUrl + '/profile/photo';
static const String checkUsername = _baseUserUrl + '/CheckUsername';
static const String updateProfile = _baseUserUrl + '/profile/edit';
static String bookmarks({String? type}) =>
_baseUserUrl + '/marked/${type ?? ''}';
static const String directTypes = baseUrl + '/direct/types';
static String direct(int id) => _baseUserUrl + '/direct/$id';
static String direct(int id) => _baseDirectUrl + '/$id';
static String sendDirectMessage(int id) =>
_baseDirectUrl + '/$id/sendMessage';
static String tag({
required List<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 radarComments(int id) => _baseRadarUrl + '/$id/comments';
@ -96,5 +114,6 @@ class RequestHelper {
}
return result;
}
return null;
}
}

View File

@ -7,8 +7,8 @@ import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/widgets/didvan/button.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
@ -83,9 +83,7 @@ class ActionSheetUtils {
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(
10,
),
top: Radius.circular(10),
),
),
child: SingleChildScrollView(
@ -136,17 +134,18 @@ class ActionSheetUtils {
),
),
if (data.hasDismissButton) const SizedBox(width: 20),
Expanded(
flex: data.smallDismissButton ? 2 : 1,
child: DidvanButton(
style: ButtonStyleMode.primary,
onPressed: () {
Navigator.of(context).pop();
data.onConfirmed?.call();
},
title: data.confrimTitle ?? 'تایید',
if (data.hasConfirmButton)
Expanded(
flex: data.smallDismissButton ? 2 : 1,
child: DidvanButton(
style: ButtonStyleMode.primary,
onPressed: () {
Navigator.of(context).pop();
data.onConfirmed?.call();
},
title: data.confrimTitle ?? 'تایید',
),
),
),
],
),
],
@ -160,6 +159,7 @@ class ActionSheetUtils {
await showDialog(
context: context,
builder: (context) => Dialog(
backgroundColor: Theme.of(context).colorScheme.surface,
shape: const RoundedRectangleBorder(
borderRadius: DesignConfig.mediumBorderRadius,
),

View File

@ -52,6 +52,31 @@ class DateTimeUtils {
return result?.toDateTime().toString();
}
static String timeWithAmPm(String input) {
final dateTime = utcToLocalTime(input);
bool isAm = true;
int hour = 0;
int minute = 0;
if (dateTime.hour > 12) {
isAm = false;
hour = dateTime.hour - 12;
} else {
hour = dateTime.hour;
}
minute = dateTime.minute;
return '$hour:${_timeNormalizer(minute)} ${isAm ? 'ق.ظ' : 'ب.ظ'}';
}
static DateTime utcToLocalTime(String input) {
final dateTime = DateTime.parse(input);
return dateTime.add(const Duration(hours: 3, minutes: 30));
}
static String _timeNormalizer(int input) {
if (input < 10) return '0$input';
return input.toString();
}
static String momentGenerator(String input) {
final date = DateTime.parse(input);
final int seconds = (DateTime.now().difference(date).inSeconds).floor();
@ -67,6 +92,7 @@ class DateTimeUtils {
}
interval = seconds / 86400;
if (interval > 1) {
if (interval.floor() == 1) return 'دیروز';
return interval.floor().toString() + " روز پیش";
}
interval = seconds / 3600;

View File

@ -1,9 +1,9 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/pages/authentication/screens/password.dart';
import 'package:didvan/pages/authentication/screens/username.dart';
import 'package:didvan/pages/authentication/screens/reset_password.dart';
import 'package:didvan/pages/authentication/screens/verification.dart';
import 'package:didvan/views/authentication/authentication_state.dart';
import 'package:didvan/views/authentication/screens/password.dart';
import 'package:didvan/views/authentication/screens/reset_password.dart';
import 'package:didvan/views/authentication/screens/username.dart';
import 'package:didvan/views/authentication/screens/verification.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

View File

@ -55,5 +55,6 @@ class AuthenticationState extends CoreProvier {
appState = AppState.failed;
ActionSheetUtils.showAlert(AlertData(message: service.errorMessage));
}
return null;
}
}

View File

@ -1,10 +1,13 @@
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/pages/authentication/widgets/authentication_layout.dart';
import 'dart:developer';
import 'package:didvan/providers/server_data_provider.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/didvan/button.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/didvan/text_field.dart';
import 'package:didvan/views/authentication/authentication_state.dart';
import 'package:didvan/views/authentication/widgets/authentication_layout.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -70,6 +73,8 @@ class _PasswordInputState extends State<PasswordInput> {
final userProvider = context.read<UserProvider>();
final token = await state.login(userProvider);
if (token != null) {
log(token);
await ServerDataProvider.getData();
Navigator.of(context).pushReplacementNamed(Routes.home);
}
}

Some files were not shown because too many files have changed in this diff Show More