Merge branch 'dev' into 'test'
Dev See merge request Didvan/didvan-app!4
This commit is contained in:
commit
bc443339a6
|
|
@ -65,5 +65,6 @@ flutter {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation platform('com.google.firebase:firebase-bom:29.1.0')
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ buildscript {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||||
|
classpath 'com.google.gms:google-services:4.3.10'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '9.0'
|
platform :ios, '10.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,41 @@
|
||||||
PODS:
|
PODS:
|
||||||
- audio_session (0.0.1):
|
- audio_session (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- Firebase/CoreOnly (8.11.0):
|
||||||
|
- FirebaseCore (= 8.11.0)
|
||||||
|
- Firebase/Messaging (8.11.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseMessaging (~> 8.11.0)
|
||||||
|
- firebase_core (1.13.1):
|
||||||
|
- Firebase/CoreOnly (= 8.11.0)
|
||||||
|
- Flutter
|
||||||
|
- firebase_messaging (11.2.8):
|
||||||
|
- Firebase/Messaging (= 8.11.0)
|
||||||
|
- firebase_core
|
||||||
|
- Flutter
|
||||||
|
- FirebaseCore (8.11.0):
|
||||||
|
- FirebaseCoreDiagnostics (~> 8.0)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/Logger (~> 7.7)
|
||||||
|
- FirebaseCoreDiagnostics (8.12.0):
|
||||||
|
- GoogleDataTransport (~> 9.1)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/Logger (~> 7.7)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
|
- FirebaseInstallations (8.12.0):
|
||||||
|
- FirebaseCore (~> 8.0)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||||
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
|
- FirebaseMessaging (8.11.0):
|
||||||
|
- FirebaseCore (~> 8.0)
|
||||||
|
- FirebaseInstallations (~> 8.0)
|
||||||
|
- GoogleDataTransport (~> 9.1)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
|
||||||
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
|
- GoogleUtilities/Reachability (~> 7.7)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_secure_storage (3.3.1):
|
- flutter_secure_storage (3.3.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
@ -9,6 +44,27 @@ PODS:
|
||||||
- FMDB (2.7.5):
|
- FMDB (2.7.5):
|
||||||
- FMDB/standard (= 2.7.5)
|
- FMDB/standard (= 2.7.5)
|
||||||
- FMDB/standard (2.7.5)
|
- FMDB/standard (2.7.5)
|
||||||
|
- GoogleDataTransport (9.1.2):
|
||||||
|
- GoogleUtilities/Environment (~> 7.2)
|
||||||
|
- nanopb (~> 2.30908.0)
|
||||||
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Network
|
||||||
|
- GoogleUtilities/Environment (7.7.0):
|
||||||
|
- PromisesObjC (< 3.0, >= 1.2)
|
||||||
|
- GoogleUtilities/Logger (7.7.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Network (7.7.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- "GoogleUtilities/NSData+zlib"
|
||||||
|
- GoogleUtilities/Reachability
|
||||||
|
- "GoogleUtilities/NSData+zlib (7.7.0)"
|
||||||
|
- GoogleUtilities/Reachability (7.7.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/UserDefaults (7.7.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
- image_cropper (0.0.4):
|
- image_cropper (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- TOCropViewController (~> 2.6.1)
|
- TOCropViewController (~> 2.6.1)
|
||||||
|
|
@ -16,8 +72,14 @@ PODS:
|
||||||
- Flutter
|
- Flutter
|
||||||
- just_audio (0.0.1):
|
- just_audio (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- nanopb (2.30908.0):
|
||||||
|
- nanopb/decode (= 2.30908.0)
|
||||||
|
- nanopb/encode (= 2.30908.0)
|
||||||
|
- nanopb/decode (2.30908.0)
|
||||||
|
- nanopb/encode (2.30908.0)
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- PromisesObjC (2.0.0)
|
||||||
- record (0.0.1):
|
- record (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- sqflite (0.0.2):
|
- sqflite (0.0.2):
|
||||||
|
|
@ -29,6 +91,8 @@ PODS:
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||||
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
|
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
|
||||||
|
|
@ -42,12 +106,25 @@ DEPENDENCIES:
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
|
- Firebase
|
||||||
|
- FirebaseCore
|
||||||
|
- FirebaseCoreDiagnostics
|
||||||
|
- FirebaseInstallations
|
||||||
|
- FirebaseMessaging
|
||||||
- FMDB
|
- FMDB
|
||||||
|
- GoogleDataTransport
|
||||||
|
- GoogleUtilities
|
||||||
|
- nanopb
|
||||||
|
- PromisesObjC
|
||||||
- TOCropViewController
|
- TOCropViewController
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
audio_session:
|
audio_session:
|
||||||
:path: ".symlinks/plugins/audio_session/ios"
|
:path: ".symlinks/plugins/audio_session/ios"
|
||||||
|
firebase_core:
|
||||||
|
:path: ".symlinks/plugins/firebase_core/ios"
|
||||||
|
firebase_messaging:
|
||||||
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
|
|
@ -71,19 +148,30 @@ EXTERNAL SOURCES:
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
|
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
|
||||||
|
Firebase: 44dd9724c84df18b486639e874f31436eaa9a20c
|
||||||
|
firebase_core: 08f6a85f62060111de5e98d6a214810d11365de9
|
||||||
|
firebase_messaging: 36238f3d0b933af8c919aef608408aae06ba22e8
|
||||||
|
FirebaseCore: 2f4f85b453cc8fea4bb2b37e370007d2bcafe3f0
|
||||||
|
FirebaseCoreDiagnostics: 3b40dfadef5b90433a60ae01f01e90fe87aa76aa
|
||||||
|
FirebaseInstallations: 25764cf322e77f99449395870a65b2bef88e1545
|
||||||
|
FirebaseMessaging: 02e248e8997f71fa8cc9d78e9d49ec1a701ba14a
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801
|
flutter_vibrate: 9f4c2ab57008965f78969472367c329dd77eb801
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
|
||||||
|
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
|
||||||
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
||||||
image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6
|
image_picker: 9aa50e1d8cdacdbed739e925b7eea16d014367e6
|
||||||
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
||||||
|
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||||
path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
|
path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
|
||||||
|
PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58
|
||||||
record: 7ee2393532f8553bbb09fa19e95478323b7c0a99
|
record: 7ee2393532f8553bbb09fa19e95478323b7c0a99
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
||||||
url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af
|
url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af
|
||||||
|
|
||||||
PODFILE CHECKSUM: a75497545d4391e2d394c3668e20cfb1c2bbd4aa
|
PODFILE CHECKSUM: fe0e1ee7f3d1f7d00b11b474b62dd62134535aea
|
||||||
|
|
||||||
COCOAPODS: 1.11.2
|
COCOAPODS: 1.11.2
|
||||||
|
|
|
||||||
|
|
@ -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 */; };
|
||||||
|
D194CE3E27D4A4740049AFC7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D194CE3D27D4A4740049AFC7 /* GoogleService-Info.plist */; };
|
||||||
E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75DBECA488F412614712FB74 /* Pods_Runner.framework */; };
|
E870A5F479A60D6704DD5DF2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 75DBECA488F412614712FB74 /* Pods_Runner.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
|
@ -47,6 +48,7 @@
|
||||||
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>"; };
|
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>"; };
|
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>"; };
|
||||||
|
D194CE3D27D4A4740049AFC7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -112,6 +114,7 @@
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D194CE3D27D4A4740049AFC7 /* GoogleService-Info.plist */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
|
@ -189,6 +192,7 @@
|
||||||
files = (
|
files = (
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
|
D194CE3E27D4A4740049AFC7 /* GoogleService-Info.plist in Resources */,
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,30 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import Flutter
|
import Flutter
|
||||||
|
import Firebase
|
||||||
|
|
||||||
|
|
||||||
@UIApplicationMain
|
@UIApplicationMain
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate, MessagingDelegate {
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
FirebaseApp.configure()
|
||||||
|
Messaging.messaging().delegate = self
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
if #available(iOS 10.0, *) {
|
||||||
|
// For iOS 10 display notification (sent via APNS)
|
||||||
|
UNUserNotificationCenter.current().delegate = self
|
||||||
|
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
|
||||||
|
UNUserNotificationCenter.current().requestAuthorization(
|
||||||
|
options: authOptions,
|
||||||
|
completionHandler: {_, _ in })
|
||||||
|
} else {
|
||||||
|
let settings: UIUserNotificationSettings =
|
||||||
|
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
|
||||||
|
application.registerUserNotificationSettings(settings)
|
||||||
|
}
|
||||||
|
application.registerForRemoteNotifications()
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CLIENT_ID</key>
|
||||||
|
<string>935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m.apps.googleusercontent.com</string>
|
||||||
|
<key>REVERSED_CLIENT_ID</key>
|
||||||
|
<string>com.googleusercontent.apps.935017686266-54hu01v9cc5pqpgofo1gk2n3hegj4r2m</string>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyCMa-zg_uVhOfTnea5Klz6aPZlgHwVGj7U</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>935017686266</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.didvan.didvanapp</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>didvan-9b7da</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>didvan-9b7da.appspot.com</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:935017686266:ios:de47638bd662463fd2d543</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -26,12 +26,14 @@
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
|
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||||
|
<false/>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>We need to access to the microphone to record audio file</string>
|
<string>We need to access to the microphone to record audio file</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>We need to access to the user gallery to add user profile photo</string>
|
<string>We need to access to the user gallery to add user profile photo</string>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>We need to access to the user gallery to add user profile photo</string>
|
<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>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ class Content {
|
||||||
final String? audio;
|
final String? audio;
|
||||||
final String? video;
|
final String? video;
|
||||||
final String? image;
|
final String? image;
|
||||||
|
final String? largeImage;
|
||||||
|
final String? caption;
|
||||||
|
|
||||||
const Content({
|
const Content({
|
||||||
required this.order,
|
required this.order,
|
||||||
|
|
@ -11,6 +13,8 @@ class Content {
|
||||||
required this.audio,
|
required this.audio,
|
||||||
required this.video,
|
required this.video,
|
||||||
required this.image,
|
required this.image,
|
||||||
|
required this.largeImage,
|
||||||
|
required this.caption,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Content.fromJson(Map<String, dynamic> json) => Content(
|
factory Content.fromJson(Map<String, dynamic> json) => Content(
|
||||||
|
|
@ -19,6 +23,8 @@ class Content {
|
||||||
audio: json['audio'],
|
audio: json['audio'],
|
||||||
video: json['video'],
|
video: json['video'],
|
||||||
image: json['image'],
|
image: json['image'],
|
||||||
|
largeImage: json['largeImage'],
|
||||||
|
caption: json['caption'],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
|
@ -27,5 +33,7 @@ class Content {
|
||||||
'audio': audio,
|
'audio': audio,
|
||||||
'video': video,
|
'video': video,
|
||||||
'image': image,
|
'image': image,
|
||||||
|
'largeImage': largeImage,
|
||||||
|
'caption': caption,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class ServerDataProvider {
|
||||||
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
|
directTypes.add(MapEntry(types[i]['id'], types[i]['label']));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw 'Fetchin direct types failed!';
|
throw 'Fetching direct types failed!';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,10 @@ 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.dart';
|
||||||
import 'package:didvan/views/home/settings/general_settings/settings_state.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/home/settings/profile/profile.dart';
|
||||||
|
import 'package:didvan/views/home/studio/studio_state.dart';
|
||||||
import 'package:didvan/views/splash/splash.dart';
|
import 'package:didvan/views/splash/splash.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
|
@ -57,6 +59,9 @@ class RouteGenerator {
|
||||||
ChangeNotifierProvider<NewsState>(
|
ChangeNotifierProvider<NewsState>(
|
||||||
create: (context) => NewsState(),
|
create: (context) => NewsState(),
|
||||||
),
|
),
|
||||||
|
ChangeNotifierProvider<StudioState>(
|
||||||
|
create: (context) => StudioState(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: const Home(),
|
child: const Home(),
|
||||||
),
|
),
|
||||||
|
|
@ -161,13 +166,20 @@ class RouteGenerator {
|
||||||
|
|
||||||
static Route _createRoute(page) {
|
static Route _createRoute(page) {
|
||||||
return MaterialPageRoute(
|
return MaterialPageRoute(
|
||||||
builder: (context) => Container(
|
builder: (context) {
|
||||||
|
final shortestSide = MediaQuery.of(context).size.shortestSide;
|
||||||
|
final bool useMobileLayout = shortestSide < 600;
|
||||||
|
if (kIsWeb && !useMobileLayout) {
|
||||||
|
return Center(child: AspectRatio(aspectRatio: 9 / 16, child: page));
|
||||||
|
}
|
||||||
|
return Container(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: page,
|
child: page,
|
||||||
top: false,
|
top: false,
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:didvan/services/media/media.dart';
|
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';
|
||||||
|
|
@ -10,6 +12,7 @@ class AppInitializer {
|
||||||
StorageService.appDocsDir =
|
StorageService.appDocsDir =
|
||||||
(await getApplicationDocumentsDirectory()).path;
|
(await getApplicationDocumentsDirectory()).path;
|
||||||
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
||||||
|
await _initializeFirebase();
|
||||||
MediaService.init();
|
MediaService.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,4 +45,29 @@ 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import 'package:just_audio/just_audio.dart';
|
||||||
class MediaService {
|
class MediaService {
|
||||||
static final AudioPlayer audioPlayer = AudioPlayer();
|
static final AudioPlayer audioPlayer = AudioPlayer();
|
||||||
static String? audioPlayerTag;
|
static String? audioPlayerTag;
|
||||||
|
static String? audioPlayerTitle;
|
||||||
|
static String? audioPlayerCover;
|
||||||
|
|
||||||
static void init() {
|
static void init() {
|
||||||
audioPlayer.positionStream.listen((event) {
|
audioPlayer.positionStream.listen((event) {
|
||||||
|
|
@ -54,6 +56,11 @@ class MediaService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> resetAudioPlayer() async {
|
||||||
|
audioPlayerTag = null;
|
||||||
|
MediaService.audioPlayer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class RequestHelper {
|
||||||
_urlConcatGenerator([
|
_urlConcatGenerator([
|
||||||
MapEntry('limit', limit?.toString() ?? '3'),
|
MapEntry('limit', limit?.toString() ?? '3'),
|
||||||
MapEntry('type', type),
|
MapEntry('type', type),
|
||||||
MapEntry('id', itemId.toString()),
|
MapEntry('id', itemId?.toString() ?? '1'),
|
||||||
MapEntry('tags', _urlListConcatGenerator(ids))
|
MapEntry('tags', _urlListConcatGenerator(ids))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:didvan/views/widgets/didvan/text_field.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class UsernameInput extends StatefulWidget {
|
class UsernameInput extends StatefulWidget {
|
||||||
const UsernameInput({
|
const UsernameInput({
|
||||||
|
|
@ -70,7 +71,7 @@ class _UsernameInputState extends State<UsernameInput> {
|
||||||
.textTheme
|
.textTheme
|
||||||
.caption!
|
.caption!
|
||||||
.copyWith(color: Theme.of(context).colorScheme.primary),
|
.copyWith(color: Theme.of(context).colorScheme.primary),
|
||||||
recognizer: TapGestureRecognizer()..onTap = () {},
|
recognizer: TapGestureRecognizer()..onTap = _openTermsOfUse,
|
||||||
),
|
),
|
||||||
const TextSpan(text: 'و\n'),
|
const TextSpan(text: 'و\n'),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
|
|
@ -79,7 +80,7 @@ class _UsernameInputState extends State<UsernameInput> {
|
||||||
.textTheme
|
.textTheme
|
||||||
.caption!
|
.caption!
|
||||||
.copyWith(color: Theme.of(context).colorScheme.primary),
|
.copyWith(color: Theme.of(context).colorScheme.primary),
|
||||||
recognizer: TapGestureRecognizer()..onTap = () {},
|
recognizer: TapGestureRecognizer()..onTap = _openTermsOfUse,
|
||||||
),
|
),
|
||||||
const TextSpan(text: 'را میپذیرم'),
|
const TextSpan(text: 'را میپذیرم'),
|
||||||
],
|
],
|
||||||
|
|
@ -92,4 +93,8 @@ class _UsernameInputState extends State<UsernameInput> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _openTermsOfUse() {
|
||||||
|
launch('https://didvan.app/termsOfUse.html');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:didvan/models/enums.dart';
|
import 'package:didvan/models/enums.dart';
|
||||||
import 'package:didvan/models/view/app_bar_data.dart';
|
import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
import 'package:didvan/providers/server_data_provider.dart';
|
import 'package:didvan/providers/server_data_provider.dart';
|
||||||
|
import 'package:didvan/services/media/media.dart';
|
||||||
import 'package:didvan/views/home/direct/direct_state.dart';
|
import 'package:didvan/views/home/direct/direct_state.dart';
|
||||||
import 'package:didvan/views/home/direct/widgets/message.dart';
|
import 'package:didvan/views/home/direct/widgets/message.dart';
|
||||||
import 'package:didvan/views/home/direct/widgets/message_box.dart';
|
import 'package:didvan/views/home/direct/widgets/message_box.dart';
|
||||||
|
|
@ -35,7 +36,12 @@ class _DirectState extends State<Direct> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final state = context.watch<DirectState>();
|
final state = context.watch<DirectState>();
|
||||||
final d = MediaQuery.of(context);
|
final d = MediaQuery.of(context);
|
||||||
return Material(
|
return WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
MediaService.resetAudioPlayer();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
child: Material(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|
@ -89,6 +95,7 @@ class _DirectState extends State<Direct> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:didvan/models/enums.dart';
|
import 'package:didvan/models/enums.dart';
|
||||||
|
|
@ -31,7 +32,7 @@ class DirectState extends CoreProvier {
|
||||||
final messageDatas = service.result['messages'];
|
final messageDatas = service.result['messages'];
|
||||||
for (var i = 0; i < messageDatas.length; i++) {
|
for (var i = 0; i < messageDatas.length; i++) {
|
||||||
messages.add(MessageData.fromJson(messageDatas[i]));
|
messages.add(MessageData.fromJson(messageDatas[i]));
|
||||||
_addToDailyGrouped();
|
_addToDailyGrouped(messages.last);
|
||||||
}
|
}
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
return;
|
return;
|
||||||
|
|
@ -75,8 +76,8 @@ class DirectState extends CoreProvier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _addToDailyGrouped() {
|
void _addToDailyGrouped(MessageData message) {
|
||||||
final createdAt = messages.last.createdAt.split('T').first;
|
String createdAt = message.createdAt.replaceAll('T', ' ').split(' ').first;
|
||||||
if (!dailyMessages.containsKey(createdAt)) {
|
if (!dailyMessages.containsKey(createdAt)) {
|
||||||
dailyMessages.addAll({
|
dailyMessages.addAll({
|
||||||
createdAt: [messages.last.id]
|
createdAt: [messages.last.id]
|
||||||
|
|
@ -88,7 +89,6 @@ class DirectState extends CoreProvier {
|
||||||
|
|
||||||
Future<void> sendMessage() async {
|
Future<void> sendMessage() async {
|
||||||
if ((text == null || text!.isEmpty) && recordedFile == null) return;
|
if ((text == null || text!.isEmpty) && recordedFile == null) return;
|
||||||
replyRadar = null;
|
|
||||||
messages.insert(
|
messages.insert(
|
||||||
0,
|
0,
|
||||||
MessageData(
|
MessageData(
|
||||||
|
|
@ -104,7 +104,7 @@ class DirectState extends CoreProvier {
|
||||||
audioDuration: audioDuration,
|
audioDuration: audioDuration,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
_addToDailyGrouped();
|
_addToDailyGrouped(messages.first);
|
||||||
final body = {};
|
final body = {};
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
body.addAll({'text': text});
|
body.addAll({'text': text});
|
||||||
|
|
@ -115,6 +115,7 @@ class DirectState extends CoreProvier {
|
||||||
final uploadFile = recordedFile;
|
final uploadFile = recordedFile;
|
||||||
text = null;
|
text = null;
|
||||||
recordedFile = null;
|
recordedFile = null;
|
||||||
|
replyRadar = null;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
final service =
|
final service =
|
||||||
RequestService(RequestHelper.sendDirectMessage(typeId), body: body);
|
RequestService(RequestHelper.sendDirectMessage(typeId), body: body);
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class Message extends StatelessWidget {
|
||||||
_MessageContainer(
|
_MessageContainer(
|
||||||
writedByAdmin: message.writedByAdmin,
|
writedByAdmin: message.writedByAdmin,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (message.text != null) DidvanText(message.text!),
|
if (message.text != null) DidvanText(message.text!),
|
||||||
if (message.audio != null || message.audioFile != null)
|
if (message.audio != null || message.audioFile != null)
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,19 @@ class _HashtagState extends State<Hashtag> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DidvanScaffold(
|
return DidvanScaffold(
|
||||||
appBarData: AppBarData(title: widget.tag.label, hasBack: true),
|
appBarData: AppBarData(title: '#' + widget.tag.label, hasBack: true),
|
||||||
slivers: [
|
slivers: [
|
||||||
Consumer<HashtagState>(
|
Consumer<HashtagState>(
|
||||||
builder: (context, state, child) => SliverStateHandler<HashtagState>(
|
builder: (context, state, child) => SliverStateHandler<HashtagState>(
|
||||||
|
itemPadding: const EdgeInsets.only(bottom: 8),
|
||||||
state: state,
|
state: state,
|
||||||
|
placeholder: RadarOverview.placeholder,
|
||||||
builder: (context, state, index) {
|
builder: (context, state, index) {
|
||||||
|
index++;
|
||||||
|
if (index % 15 == 0 && index / 15 >= state.page) {
|
||||||
|
state.getTagItems(page: index ~/ 15 + 1);
|
||||||
|
}
|
||||||
|
index--;
|
||||||
final item = state.items[index];
|
final item = state.items[index];
|
||||||
final type = item.type;
|
final type = item.type;
|
||||||
if (type == 'radar') {
|
if (type == 'radar') {
|
||||||
|
|
@ -51,7 +58,7 @@ class _HashtagState extends State<Hashtag> {
|
||||||
return Container();
|
return Container();
|
||||||
},
|
},
|
||||||
childCount: state.items.length,
|
childCount: state.items.length,
|
||||||
onRetry: () {},
|
onRetry: () => state.getTagItems(page: 1),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ class HashtagState extends CoreProvier {
|
||||||
}
|
}
|
||||||
final service = RequestService(RequestHelper.tag(
|
final service = RequestService(RequestHelper.tag(
|
||||||
ids: [id],
|
ids: [id],
|
||||||
|
itemId: 1,
|
||||||
|
type: 'radar',
|
||||||
limit: 15,
|
limit: 15,
|
||||||
page: page,
|
page: page,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ class _RadarState extends State<Radar> {
|
||||||
CustomScrollView(
|
CustomScrollView(
|
||||||
physics: _isAnimating
|
physics: _isAnimating
|
||||||
? const NeverScrollableScrollPhysics()
|
? const NeverScrollableScrollPhysics()
|
||||||
: const ScrollPhysics(),
|
: const ClampingScrollPhysics(),
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
const SliverToBoxAdapter(child: LogoAppBar()),
|
const SliverToBoxAdapter(child: LogoAppBar()),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import 'package:didvan/models/requests/radar.dart';
|
||||||
import 'package:didvan/providers/core_provider.dart';
|
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';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class RadarDetailsState extends CoreProvier {
|
class RadarDetailsState extends CoreProvier {
|
||||||
final List<RadarDetailsData?> radars = [];
|
final List<RadarDetailsData?> radars = [];
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import 'package:didvan/models/view/radar_category.dart';
|
||||||
import 'package:didvan/views/home/radar/radar_state.dart';
|
import 'package:didvan/views/home/radar/radar_state.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
@ -18,6 +19,22 @@ class CategoryItem extends StatelessWidget {
|
||||||
required this.category,
|
required this.category,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
double _width(context) {
|
||||||
|
final Size ds = MediaQuery.of(context).size;
|
||||||
|
if (kIsWeb) {
|
||||||
|
if (!_useWebMobileLayout(context)) {
|
||||||
|
return ds.height / 16 * 9 / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ds.width / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _useWebMobileLayout(context) {
|
||||||
|
final shortestSide = MediaQuery.of(context).size.shortestSide;
|
||||||
|
final bool useMobileLayout = shortestSide < 600;
|
||||||
|
return kIsWeb && useMobileLayout;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final Size ds = MediaQuery.of(context).size;
|
final Size ds = MediaQuery.of(context).size;
|
||||||
|
|
@ -34,7 +51,7 @@ class CategoryItem extends StatelessWidget {
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
duration: DesignConfig.mediumAnimationDuration,
|
duration: DesignConfig.mediumAnimationDuration,
|
||||||
padding: isColapsed ? const EdgeInsets.all(4) : EdgeInsets.zero,
|
padding: isColapsed ? const EdgeInsets.all(4) : EdgeInsets.zero,
|
||||||
width: isColapsed ? 100 : ds.width / 3,
|
width: isColapsed ? 100 : _width(context),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: DesignConfig.lowBorderRadius,
|
borderRadius: DesignConfig.lowBorderRadius,
|
||||||
|
|
@ -48,8 +65,12 @@ class CategoryItem extends StatelessWidget {
|
||||||
duration: DesignConfig.mediumAnimationDuration,
|
duration: DesignConfig.mediumAnimationDuration,
|
||||||
isVisible: !isColapsed,
|
isVisible: !isColapsed,
|
||||||
child: Container(
|
child: Container(
|
||||||
width: ds.width / 5,
|
width: !_useWebMobileLayout(context)
|
||||||
height: ds.width / 5,
|
? _width(context) / 2
|
||||||
|
: ds.width / 5,
|
||||||
|
height: !_useWebMobileLayout(context)
|
||||||
|
? _width(context) / 2
|
||||||
|
: ds.width / 5,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
boxShadow: DesignConfig.defaultShadow,
|
boxShadow: DesignConfig.defaultShadow,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PodcastDetails extends StatelessWidget {
|
||||||
|
const PodcastDetails({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
borderRadius: const BorderRadius.vertical(top: Radius.circular(8)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
|
import 'package:didvan/utils/action_sheet.dart';
|
||||||
|
import 'package:didvan/views/home/studio/studio_state.dart';
|
||||||
import 'package:didvan/views/home/studio/widgets/slider.dart';
|
import 'package:didvan/views/home/studio/widgets/slider.dart';
|
||||||
import 'package:didvan/views/home/studio/widgets/tab_bar.dart';
|
import 'package:didvan/views/home/studio/widgets/tab_bar.dart';
|
||||||
import 'package:didvan/views/home/widgets/logo_app_bar.dart';
|
import 'package:didvan/views/home/widgets/logo_app_bar.dart';
|
||||||
import 'package:didvan/views/home/widgets/search_field.dart';
|
import 'package:didvan/views/home/widgets/search_field.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/radial_button.dart';
|
||||||
|
import 'package:didvan/views/widgets/item_title.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class Studio extends StatefulWidget {
|
class Studio extends StatefulWidget {
|
||||||
const Studio({Key? key}) : super(key: key);
|
const Studio({Key? key}) : super(key: key);
|
||||||
|
|
@ -51,7 +58,73 @@ class _StudioState extends State<Studio> {
|
||||||
const SliverToBoxAdapter(
|
const SliverToBoxAdapter(
|
||||||
child: StudioSlider(),
|
child: StudioSlider(),
|
||||||
),
|
),
|
||||||
|
const SliverPadding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: DidvanDivider(
|
||||||
|
verticalPadding: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const ItemTitle(title: 'تازهترینها'),
|
||||||
|
DidvanIconButton(
|
||||||
|
gestureSize: 36,
|
||||||
|
icon: DidvanIcons.sort_regular,
|
||||||
|
onPressed: _showSortDialog,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showSortDialog() {
|
||||||
|
final state = context.read<StudioState>();
|
||||||
|
ActionSheetUtils.showBottomSheet(
|
||||||
|
data: ActionSheetData(
|
||||||
|
content: StatefulBuilder(
|
||||||
|
builder: (context, setState) => Column(
|
||||||
|
children: [
|
||||||
|
DidvanRadialButton(
|
||||||
|
title: 'جدیدترینها',
|
||||||
|
onSelected: () => setState(
|
||||||
|
() => state.selectedSortTypeIndex = 0,
|
||||||
|
),
|
||||||
|
value: state.selectedSortTypeIndex == 0,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
DidvanRadialButton(
|
||||||
|
title: 'پربازدیدترینها',
|
||||||
|
onSelected: () => setState(
|
||||||
|
() => state.selectedSortTypeIndex = 1,
|
||||||
|
),
|
||||||
|
value: state.selectedSortTypeIndex == 1,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
DidvanRadialButton(
|
||||||
|
title: 'پربحثترینها',
|
||||||
|
onSelected: () => setState(
|
||||||
|
() => state.selectedSortTypeIndex = 2,
|
||||||
|
),
|
||||||
|
value: state.selectedSortTypeIndex == 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: 'مرتبسازی',
|
||||||
|
titleIcon: DidvanIcons.sort_regular,
|
||||||
|
hasDismissButton: false,
|
||||||
|
confrimTitle: 'مرتب سازی',
|
||||||
|
onConfirmed: () {},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:didvan/providers/core_provider.dart';
|
import 'package:didvan/providers/core_provider.dart';
|
||||||
|
|
||||||
class StudioState extends CoreProvier {
|
class StudioState extends CoreProvier {
|
||||||
|
int selectedSortTypeIndex = 0;
|
||||||
|
|
||||||
bool videosSelected = true;
|
bool videosSelected = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
|
import 'package:didvan/views/home/studio/studio_state.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class StudioTabBar extends StatelessWidget {
|
class StudioTabBar extends StatelessWidget {
|
||||||
const StudioTabBar({
|
const StudioTabBar({
|
||||||
|
|
@ -11,11 +13,16 @@ class StudioTabBar extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final state = context.watch<StudioState>();
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16),
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: Theme.of(context).colorScheme.border),
|
border: Border.all(
|
||||||
|
color: state.videosSelected
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
borderRadius: DesignConfig.lowBorderRadius,
|
borderRadius: DesignConfig.lowBorderRadius,
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|
@ -26,7 +33,7 @@ class StudioTabBar extends StatelessWidget {
|
||||||
selectedColor: Theme.of(context).colorScheme.secondary,
|
selectedColor: Theme.of(context).colorScheme.secondary,
|
||||||
title: 'ویدئو',
|
title: 'ویدئو',
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
isSelected: true,
|
isSelected: state.videosSelected,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
|
@ -40,7 +47,7 @@ class StudioTabBar extends StatelessWidget {
|
||||||
selectedColor: Theme.of(context).colorScheme.focusedBorder,
|
selectedColor: Theme.of(context).colorScheme.focusedBorder,
|
||||||
title: 'پادکست',
|
title: 'پادکست',
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
isSelected: true,
|
isSelected: !state.videosSelected,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -64,7 +71,8 @@ class _StudioTypeButton extends StatelessWidget {
|
||||||
required this.isSelected,
|
required this.isSelected,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
Color? get _color => isSelected ? selectedColor : null;
|
Color? _color(context) =>
|
||||||
|
isSelected ? selectedColor : Theme.of(context).colorScheme.hint;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -77,20 +85,20 @@ class _StudioTypeButton extends StatelessWidget {
|
||||||
Icon(
|
Icon(
|
||||||
icon,
|
icon,
|
||||||
size: 32,
|
size: 32,
|
||||||
color: _color,
|
color: _color(context),
|
||||||
),
|
),
|
||||||
if (!isSelected) const SizedBox(height: 18),
|
if (!isSelected) const SizedBox(height: 18),
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
Container(
|
Container(
|
||||||
width: 88,
|
width: 88,
|
||||||
height: 1,
|
height: 1,
|
||||||
color: _color,
|
color: _color(context),
|
||||||
),
|
),
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
DidvanText(
|
DidvanText(
|
||||||
title,
|
title,
|
||||||
style: Theme.of(context).textTheme.overline,
|
style: Theme.of(context).textTheme.overline,
|
||||||
color: _color,
|
color: _color(context),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
|
import 'package:didvan/services/media/media.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DidvanBNB extends StatelessWidget {
|
class DidvanBNB extends StatelessWidget {
|
||||||
|
|
@ -14,11 +17,46 @@ class DidvanBNB extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return StreamBuilder<bool>(
|
||||||
|
stream: MediaService.audioPlayer.playingStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
|
height: snapshot.data == true ? 120 : 72,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: DesignConfig.isDark
|
||||||
|
? Theme.of(context).colorScheme.focused
|
||||||
|
: Theme.of(context).colorScheme.navigation,
|
||||||
|
borderRadius: const BorderRadius.vertical(
|
||||||
|
top: Radius.circular(16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const DidvanIconButton(
|
||||||
|
icon: DidvanIcons.close_regular,
|
||||||
|
gestureSize: 24,
|
||||||
|
onPressed: MediaService.resetAudioPlayer,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
if (MediaService.audioPlayerCover != null)
|
||||||
|
SkeletonImage(imageUrl: MediaService.audioPlayerCover!),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Container(
|
||||||
height: 72,
|
height: 72,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
|
borderRadius:
|
||||||
|
const BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
boxShadow: DesignConfig.defaultShadow,
|
boxShadow: DesignConfig.defaultShadow,
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
|
@ -61,7 +99,11 @@ class DidvanBNB extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
import 'package:didvan/models/overview_data.dart';
|
||||||
|
import 'package:didvan/models/requests/news.dart';
|
||||||
|
import 'package:didvan/routes/routes.dart';
|
||||||
|
import 'package:didvan/utils/date_time.dart';
|
||||||
|
import 'package:didvan/views/home/widgets/bookmark_button.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
||||||
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PodcastOverview extends StatelessWidget {
|
||||||
|
final OverviewData news;
|
||||||
|
final NewsRequestArgs? newsRequestArgs;
|
||||||
|
final void Function(int id, bool value) onMarkChanged;
|
||||||
|
final bool hasUnmarkConfirmation;
|
||||||
|
const PodcastOverview({
|
||||||
|
Key? key,
|
||||||
|
required this.news,
|
||||||
|
required this.onMarkChanged,
|
||||||
|
this.newsRequestArgs,
|
||||||
|
this.hasUnmarkConfirmation = false,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DidvanCard(
|
||||||
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
|
Routes.newsDetails,
|
||||||
|
arguments: {
|
||||||
|
'onMarkChanged': onMarkChanged,
|
||||||
|
'id': news.id,
|
||||||
|
'args': newsRequestArgs,
|
||||||
|
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SkeletonImage(
|
||||||
|
imageUrl: news.image,
|
||||||
|
width: 64,
|
||||||
|
height: 64,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 64,
|
||||||
|
child: DidvanText(
|
||||||
|
news.title,
|
||||||
|
style: Theme.of(context).textTheme.bodyText1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
DidvanText(
|
||||||
|
news.description,
|
||||||
|
maxLines: 3,
|
||||||
|
),
|
||||||
|
const DidvanDivider(verticalPadding: 8),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
DidvanText(
|
||||||
|
news.reference!,
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
DidvanText(
|
||||||
|
' - ' + DateTimeUtils.momentGenerator(news.createdAt),
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
BookmarkButton(
|
||||||
|
value: news.marked,
|
||||||
|
onMarkChanged: (value) => onMarkChanged(news.id, value),
|
||||||
|
askForConfirmation: hasUnmarkConfirmation,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget get placeholder => DidvanCard(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const ShimmerPlaceholder(height: 64, width: 64),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: const [
|
||||||
|
ShimmerPlaceholder(height: 18, width: 200),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
ShimmerPlaceholder(height: 18, width: 100),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const ShimmerPlaceholder(
|
||||||
|
height: 16,
|
||||||
|
width: double.infinity,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const ShimmerPlaceholder(
|
||||||
|
height: 16,
|
||||||
|
width: double.infinity,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const ShimmerPlaceholder(
|
||||||
|
height: 16,
|
||||||
|
width: 100,
|
||||||
|
),
|
||||||
|
const DidvanDivider(verticalPadding: 8),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: const [
|
||||||
|
ShimmerPlaceholder(height: 12, width: 150),
|
||||||
|
ShimmerPlaceholder(height: 24, width: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,6 @@ import 'package:didvan/views/home/widgets/tag_item.dart';
|
||||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/card.dart';
|
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/divider.dart';
|
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||||
import 'package:didvan/views/widgets/item_title.dart';
|
import 'package:didvan/views/widgets/item_title.dart';
|
||||||
|
|
@ -191,14 +190,17 @@ class _DidvanPageViewState extends State<DidvanPageView> {
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
'span': Style(
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
fontSize: FontSize.small,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (content.caption != null) {
|
||||||
|
return Center(
|
||||||
|
child: DidvanText(
|
||||||
|
content.caption,
|
||||||
|
style: Theme.of(context).textTheme.caption,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
if (content.image != null) {
|
if (content.image != null) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|
@ -211,19 +213,15 @@ class _DidvanPageViewState extends State<DidvanPageView> {
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SkeletonImage(
|
child: SkeletonImage(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: 200,
|
imageUrl: content.largeImage ?? content.image,
|
||||||
imageUrl: content.image,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
const Positioned(
|
||||||
right: 16,
|
right: 24,
|
||||||
child: DidvanIconButton(
|
top: 24,
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
child: _BackButton(),
|
||||||
icon: DidvanIcons.back_regular,
|
|
||||||
onPressed: Navigator.of(context).pop,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -231,7 +229,7 @@ class _DidvanPageViewState extends State<DidvanPageView> {
|
||||||
},
|
},
|
||||||
child: SkeletonImage(
|
child: SkeletonImage(
|
||||||
imageUrl: content.image!,
|
imageUrl: content.image!,
|
||||||
aspectRatio: 16 / 9,
|
width: double.infinity,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -277,9 +275,8 @@ class _DidvanPageViewState extends State<DidvanPageView> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BackButton extends StatefulWidget {
|
class _BackButton extends StatefulWidget {
|
||||||
final ScrollController scrollController;
|
final ScrollController? scrollController;
|
||||||
const _BackButton({Key? key, required this.scrollController})
|
const _BackButton({Key? key, this.scrollController}) : super(key: key);
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
__BackButtonState createState() => __BackButtonState();
|
__BackButtonState createState() => __BackButtonState();
|
||||||
|
|
@ -290,20 +287,26 @@ class __BackButtonState extends State<_BackButton> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant _BackButton oldWidget) {
|
void didUpdateWidget(covariant _BackButton oldWidget) {
|
||||||
|
if (widget.scrollController != null) {
|
||||||
_isVisible = false;
|
_isVisible = false;
|
||||||
_handleScroll();
|
_handleScroll();
|
||||||
|
}
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
if (widget.scrollController != null) {
|
||||||
_handleScroll();
|
_handleScroll();
|
||||||
|
} else {
|
||||||
|
_isVisible = true;
|
||||||
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleScroll() {
|
void _handleScroll() {
|
||||||
widget.scrollController.addListener(() {
|
widget.scrollController!.addListener(() {
|
||||||
final position = widget.scrollController.position.pixels;
|
final position = widget.scrollController!.position.pixels;
|
||||||
final size = MediaQuery.of(context).size.height * 0.3;
|
final size = MediaQuery.of(context).size.height * 0.3;
|
||||||
if (position > size && _isVisible == false) {
|
if (position > size && _isVisible == false) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import 'package:didvan/config/theme_data.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DidvanRadialButton extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final VoidCallback onSelected;
|
||||||
|
final bool value;
|
||||||
|
const DidvanRadialButton({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.onSelected,
|
||||||
|
required this.value,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: value ? null : onSelected,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
height: 24,
|
||||||
|
width: 24,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: value
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: Theme.of(context).colorScheme.text,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: value
|
||||||
|
? Theme.of(context).colorScheme.secondary
|
||||||
|
: Colors.transparent,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
DidvanText(title),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,17 +8,17 @@ import 'package:cached_network_image_platform_interface/cached_network_image_pla
|
||||||
|
|
||||||
class SkeletonImage extends StatelessWidget {
|
class SkeletonImage extends StatelessWidget {
|
||||||
final String imageUrl;
|
final String imageUrl;
|
||||||
final double width;
|
final double? width;
|
||||||
final double height;
|
final double? height;
|
||||||
final BorderRadius? borderRadius;
|
final BorderRadius? borderRadius;
|
||||||
final double? aspectRatio;
|
final double? aspectRatio;
|
||||||
const SkeletonImage({
|
const SkeletonImage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.imageUrl,
|
required this.imageUrl,
|
||||||
this.width = 300,
|
|
||||||
this.height = 140,
|
|
||||||
this.borderRadius = DesignConfig.lowBorderRadius,
|
this.borderRadius = DesignConfig.lowBorderRadius,
|
||||||
this.aspectRatio,
|
this.aspectRatio,
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -30,15 +30,13 @@ class SkeletonImage extends StatelessWidget {
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
imageUrl: RequestHelper.baseUrl + imageUrl,
|
imageUrl: RequestHelper.baseUrl + imageUrl,
|
||||||
imageBuilder: (context, imageProvider) => Container(
|
imageBuilder: (context, imageProvider) => ClipRRect(
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: borderRadius ?? DesignConfig.lowBorderRadius,
|
borderRadius: borderRadius ?? DesignConfig.lowBorderRadius,
|
||||||
image: DecorationImage(
|
child: Image(
|
||||||
image: imageProvider,
|
image: imageProvider,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
progressIndicatorBuilder: (context, url, progress) =>
|
progressIndicatorBuilder: (context, url, progress) =>
|
||||||
ShimmerPlaceholder(
|
ShimmerPlaceholder(
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
|
|
|
||||||
44
pubspec.lock
44
pubspec.lock
|
|
@ -148,6 +148,48 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.2"
|
version: "6.1.2"
|
||||||
|
firebase_core:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_core
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.13.1"
|
||||||
|
firebase_core_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.5"
|
||||||
|
firebase_core_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.1"
|
||||||
|
firebase_messaging:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_messaging
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "11.2.8"
|
||||||
|
firebase_messaging_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_messaging_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
|
firebase_messaging_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_messaging_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.9"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
@ -762,5 +804,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.3.1"
|
version: "5.3.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.15.0 <3.0.0"
|
dart: ">=2.16.0 <3.0.0"
|
||||||
flutter: ">=2.5.0"
|
flutter: ">=2.5.0"
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ dependencies:
|
||||||
url_launcher: ^6.0.18
|
url_launcher: ^6.0.18
|
||||||
audio_video_progress_bar: ^0.10.0
|
audio_video_progress_bar: ^0.10.0
|
||||||
image_cropper: ^1.5.0
|
image_cropper: ^1.5.0
|
||||||
|
firebase_messaging: ^11.2.8
|
||||||
|
firebase_core: ^1.13.1
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue