mirror of
https://github.com/hmalik144/Driver.git
synced 2025-12-10 02:45:20 +00:00
- retrieve thumbnail or no image
- changes to storage ref in process retrieval in process ** broken commit **
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"licenseExpiry": "27/04/2019",
|
||||
"licenseExpiry": "27/04/2032",
|
||||
"licenseImageString": "driver_license_driver.jpg",
|
||||
"licenseNumber": "FARME100165AB5EW"
|
||||
}
|
||||
@@ -16,12 +16,14 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.internal.util.Checks
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import androidx.test.rule.GrantPermissionRule
|
||||
import com.google.gson.Gson
|
||||
import h_mal.appttude.com.driver.base.BaseActivity
|
||||
import h_mal.appttude.com.driver.helpers.BaseViewAction
|
||||
import h_mal.appttude.com.driver.helpers.SnapshotRule
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.core.AllOf
|
||||
@@ -60,9 +62,11 @@ open class BaseUiTest<T : BaseActivity<*, *>>(
|
||||
beforeLaunch()
|
||||
mActivityScenarioRule = ActivityScenario.launch(activity)
|
||||
mActivityScenarioRule.onActivity {
|
||||
runBlocking {
|
||||
mIdlingResource = it.getIdlingResource()!!
|
||||
IdlingRegistry.getInstance().register(mIdlingResource)
|
||||
}
|
||||
}
|
||||
afterLaunch()
|
||||
}
|
||||
|
||||
|
||||
@@ -35,12 +35,15 @@ open class FirebaseTest<T : BaseActivity<*, *>>(
|
||||
val localHost = "10.0.2.2"
|
||||
|
||||
FirebaseAuth.getInstance().useEmulator(localHost, 9099)
|
||||
FirebaseDatabase.getInstance().useEmulator(localHost, 9000)
|
||||
FirebaseDatabase.getInstance().useEmulator(localHost, 9001)
|
||||
FirebaseStorage.getInstance().useEmulator(localHost, 9199)
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeLaunch() {
|
||||
// // sign out if it failed to sign out
|
||||
// if (firebaseAuthSource.getUser() != null) firebaseAuthSource.logOut()
|
||||
|
||||
if (registered) {
|
||||
runBlocking {
|
||||
setupUser()
|
||||
|
||||
@@ -7,7 +7,7 @@ import androidx.test.espresso.action.ViewActions.scrollTo
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import h_mal.appttude.com.driver.helpers.EspressoHelper.trying
|
||||
import h_mal.appttude.com.driver.model.Model
|
||||
import h_mal.appttude.com.driver.base.Model
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@@ -21,7 +21,7 @@ class HomeRobot : BaseTestRobot() {
|
||||
|
||||
fun updateProfile() {
|
||||
openDrawer()
|
||||
clickButton(R.id.nav_user_settings)
|
||||
clickButton(R.id.nav_update_profile)
|
||||
}
|
||||
|
||||
fun openDriverProfile() = clickButton(R.id.driver)
|
||||
|
||||
@@ -9,7 +9,7 @@ import h_mal.appttude.com.driver.model.DriverProfile
|
||||
import h_mal.appttude.com.driver.model.DriversLicense
|
||||
import h_mal.appttude.com.driver.model.Insurance
|
||||
import h_mal.appttude.com.driver.model.Logbook
|
||||
import h_mal.appttude.com.driver.model.Model
|
||||
import h_mal.appttude.com.driver.base.Model
|
||||
import h_mal.appttude.com.driver.model.Mot
|
||||
import h_mal.appttude.com.driver.model.PrivateHireLicense
|
||||
import h_mal.appttude.com.driver.model.PrivateHireVehicle
|
||||
|
||||
@@ -7,6 +7,7 @@ open class DriverProfileTest : DataSubmissionTest() {
|
||||
override fun afterLaunch() {
|
||||
super.afterLaunch()
|
||||
home {
|
||||
waitFor(1500)
|
||||
openDriverProfile()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ class SubmitNewDriverDataTest : DriverProfileTest() {
|
||||
driversLicense {
|
||||
val data = getAssetData<DriversLicense>()
|
||||
submitAndValidate(data)
|
||||
|
||||
waitFor(17000)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ class ApplicationViewModelFactory(
|
||||
)
|
||||
isAssignableFrom(VehicleProfileViewModel::class.java) -> VehicleProfileViewModel(
|
||||
auth,
|
||||
database,
|
||||
storage
|
||||
database
|
||||
)
|
||||
isAssignableFrom(InsuranceViewModel::class.java) -> InsuranceViewModel(
|
||||
auth,
|
||||
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.driverprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentDriverLicenseBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.DriversLicense
|
||||
@@ -11,7 +11,7 @@ import h_mal.appttude.com.driver.utils.setGlideImage
|
||||
import h_mal.appttude.com.driver.viewmodels.DriverLicenseViewModel
|
||||
|
||||
class DriverLicenseFragment :
|
||||
DataSubmissionBaseFragment<DriverLicenseViewModel, FragmentDriverLicenseBinding, DriversLicense>() {
|
||||
ImageFormSubmissionFragment<DriverLicenseViewModel, FragmentDriverLicenseBinding, DriversLicense>() {
|
||||
|
||||
override fun setupView(binding: FragmentDriverLicenseBinding) {
|
||||
binding.apply {
|
||||
@@ -25,32 +25,31 @@ class DriverLicenseFragment :
|
||||
}
|
||||
licNo.setTextOnChange { model.licenseNumber = it }
|
||||
|
||||
searchImage.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
searchImage.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener {
|
||||
validateEditTexts(licExpiry, licNo).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
}
|
||||
validateEditTexts(licExpiry, licNo).isTrue { submitDocument() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: DriversLicense) {
|
||||
super.setFields(data)
|
||||
applyBinding {
|
||||
licNo.setText(data.licenseNumber)
|
||||
licExpiry.setText(data.licenseExpiry)
|
||||
|
||||
data.licenseImageString?.setImages{
|
||||
driversliImg.setGlideImage(it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun setImage(image: StorageReference?, thumbnail: StorageReference?) {
|
||||
thumbnail?.let {
|
||||
binding.driversliImg.setGlideImage(it)
|
||||
return
|
||||
}
|
||||
binding.driversliImg.setGlideImage(image)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
driversliImg.setGlideImage(imageUri)
|
||||
}
|
||||
binding.driversliImg.setGlideImage(imageUri)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.driverprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentDriverProfileBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.DriverProfile
|
||||
@@ -12,7 +12,7 @@ import h_mal.appttude.com.driver.viewmodels.DriverProfileViewModel
|
||||
|
||||
|
||||
class DriverProfileFragment :
|
||||
DataSubmissionBaseFragment<DriverProfileViewModel, FragmentDriverProfileBinding, DriverProfile>() {
|
||||
ImageFormSubmissionFragment<DriverProfileViewModel, FragmentDriverProfileBinding, DriverProfile>() {
|
||||
|
||||
override fun setupView(binding: FragmentDriverProfileBinding) = binding.run {
|
||||
namesInput.setTextOnChange { model.forenames = it }
|
||||
@@ -35,7 +35,7 @@ class DriverProfileFragment :
|
||||
}
|
||||
}
|
||||
}
|
||||
addPhoto.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
addPhoto.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener { submit() }
|
||||
}
|
||||
|
||||
@@ -45,13 +45,12 @@ class DriverProfileFragment :
|
||||
namesInput, addressInput, postcodeInput,
|
||||
dobInput, niNumber, dateFirst
|
||||
).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: DriverProfile) {
|
||||
super.setFields(data)
|
||||
applyBinding {
|
||||
namesInput.setText(data.forenames)
|
||||
addressInput.setText(data.address)
|
||||
@@ -59,18 +58,16 @@ class DriverProfileFragment :
|
||||
dobInput.setText(data.dob)
|
||||
niNumber.setText(data.ni)
|
||||
dateFirst.setText(data.dateFirst)
|
||||
|
||||
data.driverPic?.setImages {
|
||||
driverPic.setGlideImage(it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun setImage(image: StorageReference, thumbnail: StorageReference) {
|
||||
binding.driverPic.setGlideImage(thumbnail)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
driverPic.setGlideImage(imageUri)
|
||||
}
|
||||
binding.driverPic.setGlideImage(imageUri)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.driverprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentPrivateHireLicenseBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.PrivateHireLicense
|
||||
@@ -11,7 +11,7 @@ import h_mal.appttude.com.driver.utils.setGlideImage
|
||||
import h_mal.appttude.com.driver.viewmodels.PrivateHireLicenseViewModel
|
||||
|
||||
|
||||
class PrivateHireLicenseFragment : DataSubmissionBaseFragment
|
||||
class PrivateHireLicenseFragment : ImageFormSubmissionFragment
|
||||
<PrivateHireLicenseViewModel, FragmentPrivateHireLicenseBinding, PrivateHireLicense>() {
|
||||
|
||||
override fun setupView(binding: FragmentPrivateHireLicenseBinding) = binding.run {
|
||||
@@ -25,14 +25,14 @@ class PrivateHireLicenseFragment : DataSubmissionBaseFragment
|
||||
}
|
||||
}
|
||||
|
||||
uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
uploadphlic.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener { submit() }
|
||||
}
|
||||
|
||||
override fun submit() {
|
||||
applyBinding {
|
||||
validateEditTexts(phNo, phExpiry).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,15 +42,16 @@ class PrivateHireLicenseFragment : DataSubmissionBaseFragment
|
||||
applyBinding {
|
||||
phNo.setText(data.phNumber)
|
||||
phExpiry.setText(data.phExpiry)
|
||||
data.phImageString?.setImages { imageView2.setGlideImage(it.second) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun setImage(image: StorageReference, thumbnail: StorageReference) {
|
||||
binding.imageView2.setGlideImage(thumbnail)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
imageView2.setGlideImage(imageUri)
|
||||
}
|
||||
binding.imageView2.setGlideImage(imageUri)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.MultiImageFormSubmissionFragment3
|
||||
import h_mal.appttude.com.driver.data.ImageCollection
|
||||
import h_mal.appttude.com.driver.databinding.FragmentInsuranceBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.Insurance
|
||||
@@ -15,13 +16,10 @@ import h_mal.appttude.com.driver.viewmodels.InsuranceViewModel
|
||||
|
||||
|
||||
class InsuranceFragment :
|
||||
DataSubmissionBaseFragment<InsuranceViewModel, FragmentInsuranceBinding, Insurance>() {
|
||||
|
||||
private var selectedImages: List<Uri>? = listOf()
|
||||
MultiImageFormSubmissionFragment3<InsuranceViewModel, FragmentInsuranceBinding, Insurance>() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setImageSelectionAsMultiple()
|
||||
|
||||
applyBinding {
|
||||
insurer.setTextOnChange { model.insurerName = it }
|
||||
@@ -32,7 +30,7 @@ class InsuranceFragment :
|
||||
}
|
||||
}
|
||||
}
|
||||
uploadInsurance.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
uploadInsurance.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener { submit() }
|
||||
}
|
||||
}
|
||||
@@ -57,35 +55,24 @@ class InsuranceFragment :
|
||||
super.submit()
|
||||
applyBinding {
|
||||
validateEditTexts(insurer, insuranceExp).isTrue {
|
||||
viewModel.setDataInDatabase(model, selectedImages)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: Insurance) {
|
||||
super.setFields(data)
|
||||
applyBinding {
|
||||
insurer.setText(model.insurerName)
|
||||
insuranceExp.setText(model.expiryDate)
|
||||
|
||||
data.photoStrings?.also {
|
||||
val keys = viewModel.getMultipleImagesAndThumbnails(it).map {i -> i.key }
|
||||
updateImageCarousal(keys)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUris: List<Uri>?) {
|
||||
selectedImages = imageUris
|
||||
selectedImages?.let { updateImageCarousal(it) }
|
||||
}
|
||||
|
||||
override fun onSuccess(data: Any?) {
|
||||
super.onSuccess(data)
|
||||
|
||||
if (data is Map<*,*>) {
|
||||
updateImageCarousal(data.map { it.value })
|
||||
}
|
||||
}
|
||||
|
||||
override fun setImages(collection: ImageCollection) {
|
||||
updateImageCarousal(collection.collection.map { it.second })
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUris: List<Uri>) {
|
||||
updateImageCarousal(imageUris)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.vehicleprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentLogbookBinding
|
||||
import h_mal.appttude.com.driver.model.Logbook
|
||||
import h_mal.appttude.com.driver.utils.isTrue
|
||||
@@ -11,11 +11,11 @@ import h_mal.appttude.com.driver.viewmodels.LogbookViewModel
|
||||
|
||||
|
||||
class LogbookFragment :
|
||||
DataSubmissionBaseFragment<LogbookViewModel, FragmentLogbookBinding, Logbook>() {
|
||||
ImageFormSubmissionFragment<LogbookViewModel, FragmentLogbookBinding, Logbook>() {
|
||||
|
||||
override fun setupView(binding: FragmentLogbookBinding) = binding.run {
|
||||
v5cNo.setTextOnChange { model.v5cnumber = it }
|
||||
uploadLb.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
uploadLb.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener { submit() }
|
||||
}
|
||||
|
||||
@@ -23,24 +23,23 @@ class LogbookFragment :
|
||||
super.submit()
|
||||
applyBinding {
|
||||
validateEditTexts(v5cNo).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: Logbook) {
|
||||
super.setFields(data)
|
||||
applyBinding {
|
||||
v5cNo.setText(data.v5cnumber)
|
||||
data.photoString?.setImages { logBookImg.setGlideImage(it.second) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun setImage(image: StorageReference, thumbnail: StorageReference) {
|
||||
binding.logBookImg.setGlideImage(thumbnail)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
logBookImg.setGlideImage(picUri)
|
||||
}
|
||||
binding.logBookImg.setGlideImage(imageUri)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.vehicleprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentMotBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.Mot
|
||||
@@ -11,7 +11,7 @@ import h_mal.appttude.com.driver.utils.setGlideImage
|
||||
import h_mal.appttude.com.driver.viewmodels.MotViewModel
|
||||
|
||||
|
||||
class MotFragment : DataSubmissionBaseFragment<MotViewModel, FragmentMotBinding, Mot>() {
|
||||
class MotFragment : ImageFormSubmissionFragment<MotViewModel, FragmentMotBinding, Mot>() {
|
||||
|
||||
override fun setupView(binding: FragmentMotBinding) = binding.run {
|
||||
motExpiry.apply {
|
||||
@@ -22,26 +22,26 @@ class MotFragment : DataSubmissionBaseFragment<MotViewModel, FragmentMotBinding,
|
||||
}
|
||||
}
|
||||
|
||||
uploadmot.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
uploadmot.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener {
|
||||
validateEditTexts(motExpiry).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: Mot) {
|
||||
super.setFields(data)
|
||||
applyBinding {
|
||||
motExpiry.setText(data.motExpiry)
|
||||
data.motImageString?.setImages { motImg.setGlideImage(it.second) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun setImage(image: StorageReference, thumbnail: StorageReference) {
|
||||
binding.motImg.setGlideImage(thumbnail)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
motImg.setGlideImage(imageUri)
|
||||
}
|
||||
binding.motImg.setGlideImage(imageUri)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package h_mal.appttude.com.driver.ui.vehicleprofile
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.ImageFormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentPrivateHireLicenseBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.PrivateHireVehicle
|
||||
@@ -12,7 +12,7 @@ import h_mal.appttude.com.driver.viewmodels.PrivateHireVehicleViewModel
|
||||
|
||||
|
||||
class PrivateHireVehicleFragment :
|
||||
DataSubmissionBaseFragment<PrivateHireVehicleViewModel, FragmentPrivateHireLicenseBinding, PrivateHireVehicle>() {
|
||||
ImageFormSubmissionFragment<PrivateHireVehicleViewModel, FragmentPrivateHireLicenseBinding, PrivateHireVehicle>() {
|
||||
|
||||
override fun setupView(binding: FragmentPrivateHireLicenseBinding) = binding.run {
|
||||
phNo.setTextOnChange { model.phCarNumber = it }
|
||||
@@ -24,28 +24,29 @@ class PrivateHireVehicleFragment :
|
||||
}
|
||||
}
|
||||
|
||||
uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() }
|
||||
uploadphlic.setOnClickListener { openGalleryForImageSelection() }
|
||||
submit.setOnClickListener {
|
||||
validateEditTexts(phNo, phExpiry).isTrue {
|
||||
viewModel.setDataInDatabase(model, picUri)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFields(data: PrivateHireVehicle) {
|
||||
super.setFields(data)
|
||||
override fun setFields(
|
||||
data: PrivateHireVehicle
|
||||
) {
|
||||
applyBinding {
|
||||
phNo.setText(data.phCarNumber)
|
||||
phExpiry.setText(data.phCarExpiry)
|
||||
data.phCarImageString?.setImages { imageView2.setGlideImage(it.second) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun setImage(image: StorageReference, thumbnail: StorageReference) {
|
||||
binding.imageView2.setGlideImage(thumbnail)
|
||||
}
|
||||
|
||||
override fun onImageGalleryResult(imageUri: Uri?) {
|
||||
override fun onImageGalleryResult(imageUri: Uri) {
|
||||
super.onImageGalleryResult(imageUri)
|
||||
applyBinding {
|
||||
imageView2.setGlideImage(imageUri)
|
||||
}
|
||||
binding.imageView2.setGlideImage(imageUri)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package h_mal.appttude.com.driver.ui.vehicleprofile
|
||||
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseFragment
|
||||
import h_mal.appttude.com.driver.base.FormSubmissionFragment
|
||||
import h_mal.appttude.com.driver.databinding.FragmentVehicleSetupBinding
|
||||
import h_mal.appttude.com.driver.dialogs.DateDialog
|
||||
import h_mal.appttude.com.driver.model.VehicleProfile
|
||||
@@ -8,8 +8,7 @@ import h_mal.appttude.com.driver.utils.isTrue
|
||||
import h_mal.appttude.com.driver.viewmodels.VehicleProfileViewModel
|
||||
|
||||
|
||||
class VehicleProfileFragment : DataSubmissionBaseFragment
|
||||
<VehicleProfileViewModel, FragmentVehicleSetupBinding, VehicleProfile>() {
|
||||
class VehicleProfileFragment : FormSubmissionFragment<VehicleProfileViewModel, FragmentVehicleSetupBinding, VehicleProfile>() {
|
||||
|
||||
override fun setupView(binding: FragmentVehicleSetupBinding) = binding.run {
|
||||
reg.setTextOnChange { model.reg = it }
|
||||
@@ -39,7 +38,7 @@ class VehicleProfileFragment : DataSubmissionBaseFragment
|
||||
postcode,
|
||||
startDate
|
||||
).isTrue {
|
||||
viewModel.setDataInDatabase(model)
|
||||
submitDocument()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.data.DRIVERS_LICENSE_SREF
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.DriversLicense
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import kotlinx.coroutines.Job
|
||||
import h_mal.appttude.com.driver.utils.DateUtils.parseDateStringIntoCalender
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class DriverLicenseViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<DriversLicense>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<DriversLicense>(auth, database, storage, Storage.DRIVERS_LICENSE) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getDriverLicenseRef(uid)
|
||||
override val storageRef: StorageReference = storage.driversLicenseStorageRef(uid)
|
||||
override val objectName: String = "drivers license"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<DriversLicense>()
|
||||
|
||||
override fun setDataInDatabase(data: DriversLicense, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
val imageUrl = getImageUrl(localImageUri, data.licenseImageString)
|
||||
data.licenseImageString = imageUrl
|
||||
postDataToDatabase(data)
|
||||
override fun validateData(data: DriversLicense): Boolean {
|
||||
data.licenseNumber.validateStringOrThrow("License number")
|
||||
if (parseDateStringIntoCalender(data.licenseExpiry!!).isBefore(LocalDate.now())) {
|
||||
onError("License expiry cannot be before today")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.DRIVERS_LICENSE_SREF
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.DriversLicense
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
class DriverLicenseViewModel2(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionViewModel2<DriversLicense>(auth, database, storage) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getDriverLicenseRef(uid)
|
||||
override val storageRef: StorageReference = storage.driversLicenseStorageRef(uid)
|
||||
|
||||
override fun validateData(data: DriversLicense): Boolean {
|
||||
// TODO Not yet implemented
|
||||
return true
|
||||
}
|
||||
override fun setDataAfterUpload(data: DriversLicense, filename: String): DriversLicense {
|
||||
return data.apply {
|
||||
licenseImageString = filename
|
||||
}
|
||||
}
|
||||
|
||||
fun postDataToDatabase(imageUri: Uri, data: DriversLicense) {
|
||||
postDataToDatabase(imageUri, data, Storage.DRIVERS_LICENSE)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,33 +4,39 @@ import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.DRIVER_PROFILE
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.PROFILE_SREF
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.DriverProfile
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import kotlinx.coroutines.Job
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class DriverProfileViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<DriverProfile>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<DriverProfile>(auth, database, storage, Storage.PROFILE) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getDriverDetailsRef(uid)
|
||||
override val storageRef: StorageReference = storage.profileImageStorageRef(uid)
|
||||
override val objectName: String = "drivers profile"
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<DriverProfile>()
|
||||
|
||||
override fun setDataInDatabase(data: DriverProfile, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
|
||||
val imageUrl = getImageUrl(localImageUri, data.driverPic)
|
||||
data.driverPic = imageUrl
|
||||
postDataToDatabase(data)
|
||||
override fun validateData(data: DriverProfile): Boolean {
|
||||
data.ni.validateStringOrThrow("National Insurance number")
|
||||
data.address.validateStringOrThrow("Address")
|
||||
data.postcode.validateStringOrThrow("Postcode")
|
||||
data.forenames.validateStringOrThrow("Name")
|
||||
data.dob
|
||||
if (DateUtils.parseDateStringIntoCalender(data.dob!!).isAfter(LocalDate.now().minusYears(17))) {
|
||||
onError("Driver cannot be under 17")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +1,32 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel3
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.INSURANCE_SREF
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.Insurance
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import kotlinx.coroutines.Job
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class InsuranceViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<Insurance>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel3<Insurance>(auth, database, storage, Storage.INSURANCE) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid)
|
||||
override val storageRef: StorageReference = storage.insuranceStorageRef(uid)
|
||||
override val objectName: String = "insurance"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<Insurance>()
|
||||
|
||||
override fun setDataInDatabase(data: Insurance, localImageUris: List<Uri?>?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
val imageUrls = if (!localImageUris.isNullOrEmpty()) {
|
||||
getImageUrls(localImageUris).toMutableList()
|
||||
} else {
|
||||
data.photoStrings
|
||||
override fun validateData(data: Insurance): Boolean {
|
||||
data.insurerName.validateStringOrThrow("Insurer name")
|
||||
if (DateUtils.parseDateStringIntoCalender(data.expiryDate!!).isBefore(LocalDate.now())) {
|
||||
onError("Insurance expiry cannot be before today")
|
||||
return false
|
||||
}
|
||||
if (imageUrls.isNullOrEmpty()) {
|
||||
onError("no images selected")
|
||||
return@doTryOperation
|
||||
return true
|
||||
}
|
||||
|
||||
data.photoStrings = imageUrls
|
||||
postDataToDatabase(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,26 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.data.DRIVER_PROFILE
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.LOG_BOOK_SREF
|
||||
import h_mal.appttude.com.driver.model.DriverProfile
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.Logbook
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
class LogbookViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<Logbook>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<Logbook>(auth, database, storage, Storage.LOG_BOOK) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getLogbookRef(uid)
|
||||
override val storageRef: StorageReference = storage.logBookStorageRef(uid)
|
||||
override val objectName: String = "Log book"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<Logbook>()
|
||||
|
||||
override fun setDataInDatabase(data: Logbook, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
val imageUrl = getImageUrl(localImageUri, data.photoString)
|
||||
data.photoString = imageUrl
|
||||
postDataToDatabase(data)
|
||||
}
|
||||
override fun validateData(data: Logbook): Boolean {
|
||||
data.v5cnumber.validateStringOrThrow("V5C number")
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,35 +4,36 @@ import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.LOG_BOOK_SREF
|
||||
import h_mal.appttude.com.driver.data.MOT
|
||||
import h_mal.appttude.com.driver.data.MOT_SREF
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.Logbook
|
||||
import h_mal.appttude.com.driver.model.Mot
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import kotlinx.coroutines.Job
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class MotViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<Mot>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<Mot>(auth, database, storage, Storage.MOT) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getMotDetailsRef(uid)
|
||||
override val storageRef: StorageReference? = storage.motStorageRef(uid)
|
||||
override val objectName: String = "vehicle profile"
|
||||
override val storageRef: StorageReference = storage.motStorageRef(uid)
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<Mot>()
|
||||
|
||||
override fun setDataInDatabase(data: Mot, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
val imageUrl = getImageUrl(localImageUri, data.motImageString)
|
||||
data.motImageString = imageUrl
|
||||
postDataToDatabase(data)
|
||||
override fun validateData(data: Mot): Boolean {
|
||||
if (DateUtils.parseDateStringIntoCalender(data.motExpiry!!).isBefore(LocalDate.now())) {
|
||||
onError("MOT expiry cannot be before today")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,39 +4,37 @@ import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.MOT_SREF
|
||||
import h_mal.appttude.com.driver.data.PRIVATE_HIRE_SREF
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.Mot
|
||||
import h_mal.appttude.com.driver.model.PrivateHireLicense
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import kotlinx.coroutines.Job
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class PrivateHireLicenseViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<PrivateHireLicense>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<PrivateHireLicense>(auth, database, storage, Storage.DRIVERS_LICENSE) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getPrivateHireRef(uid)
|
||||
override val storageRef: StorageReference = storage.privateHireStorageRef(uid)
|
||||
override val objectName: String = "private hire license"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<PrivateHireLicense>()
|
||||
|
||||
override fun setDataInDatabase(data: PrivateHireLicense, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload private hire license") {
|
||||
val imageUrl = getImageUrl(localImageUri, data.phImageString)
|
||||
val driverLicense = PrivateHireLicense(
|
||||
phExpiry = data.phExpiry,
|
||||
phNumber = data.phNumber,
|
||||
phImageString = imageUrl
|
||||
)
|
||||
|
||||
postDataToDatabase(driverLicense)
|
||||
override fun validateData(data: PrivateHireLicense): Boolean {
|
||||
data.phNumber.validateStringOrThrow("License number")
|
||||
if (DateUtils.parseDateStringIntoCalender(data.phExpiry!!).isBefore(LocalDate.now())) {
|
||||
onError("License expiry cannot be before today")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +1,37 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel2
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.PRIVATE_HIRE_SREF
|
||||
import h_mal.appttude.com.driver.data.PRIVATE_HIRE_VEHICLE_SREF
|
||||
import h_mal.appttude.com.driver.model.PrivateHireLicense
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.model.PrivateHireVehicle
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import kotlinx.coroutines.Job
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import org.joda.time.LocalDate
|
||||
|
||||
class PrivateHireVehicleViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<PrivateHireVehicle>(auth, database, storage) {
|
||||
) : DataSubmissionViewModel2<PrivateHireVehicle>(
|
||||
auth,
|
||||
database,
|
||||
storage,
|
||||
Storage.PRIVATE_HIRE_VEHICLE
|
||||
) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid)
|
||||
override val storageRef: StorageReference = storage.privateHireVehicleStorageRef(uid)
|
||||
override val objectName: String = "private hire vehicle license"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<PrivateHireVehicle>()
|
||||
override fun validateData(data: PrivateHireVehicle): Boolean {
|
||||
data.phCarNumber.validateStringOrThrow("License number")
|
||||
if (DateUtils.parseDateStringIntoCalender(data.phCarExpiry!!).isBefore(LocalDate.now())) {
|
||||
onError("License expiry cannot be before today")
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setDataInDatabase(data: PrivateHireVehicle, localImageUri: Uri?) = io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
val imageUrl = getImageUrl(localImageUri, data.phCarImageString)
|
||||
data.phCarImageString = imageUrl
|
||||
postDataToDatabase(data)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package h_mal.appttude.com.driver.viewmodels
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
@@ -11,22 +12,22 @@ import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
|
||||
class VehicleProfileViewModel(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
storage: FirebaseStorageSource
|
||||
) : DataSubmissionBaseViewModel<VehicleProfile>(auth, database, storage) {
|
||||
database: FirebaseDatabaseSource
|
||||
) : DataSubmissionViewModel<VehicleProfile>(auth, database) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getVehicleDetailsRef(uid)
|
||||
override val storageRef: StorageReference? = null
|
||||
override val objectName: String = "vehicle profile"
|
||||
|
||||
override fun getDataFromDatabase() = retrieveDataFromDatabase<VehicleProfile>()
|
||||
override fun validateData(data: VehicleProfile): Boolean {
|
||||
data.colour.validateStringOrThrow("Vehicle colour")
|
||||
data.model.validateStringOrThrow("Vehicle model")
|
||||
data.reg.validateStringOrThrow("Vehicle registration plate")
|
||||
data.make.validateStringOrThrow("Vehicle make")
|
||||
data.keeperAddress.validateStringOrThrow("Keeper address")
|
||||
data.keeperName.validateStringOrThrow("Keeper name")
|
||||
data.keeperPostCode.validateStringOrThrow("Keeper post code")
|
||||
|
||||
override fun setDataInDatabase(data: VehicleProfile) {
|
||||
io {
|
||||
doTryOperation("Failed to upload $objectName") {
|
||||
postDataToDatabase(data)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package h_mal.appttude.com.driver.viewmodels
|
||||
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionBaseViewModel
|
||||
import h_mal.appttude.com.driver.base.DataSubmissionViewModel
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.model.VehicleProfile
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import java.io.IOException
|
||||
|
||||
class VehicleProfileViewModel2(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource
|
||||
) : DataSubmissionViewModel<VehicleProfile>(auth, database) {
|
||||
|
||||
override val databaseRef: DatabaseReference = database.getVehicleDetailsRef(uid)
|
||||
|
||||
override fun validateData(data: VehicleProfile): Boolean {
|
||||
if (data.model.isNullOrEmpty()) {
|
||||
throw IOException("Vehicle model cannot be empty")
|
||||
}
|
||||
if (data.reg.isNullOrEmpty()) {
|
||||
throw IOException("Vehicle registration cannot be empty")
|
||||
}
|
||||
if (data.make.isNullOrEmpty()) {
|
||||
throw IOException("Vehicle make cannot be empty")
|
||||
}
|
||||
if (data.colour.isNullOrEmpty()) {
|
||||
throw IOException("Vehicle colour cannot be empty")
|
||||
}
|
||||
if (data.keeperName.isNullOrEmpty()) {
|
||||
throw IOException("Keepers name cannot be empty")
|
||||
}
|
||||
if (data.keeperAddress.isNullOrEmpty()) {
|
||||
throw IOException("Keepers address cannot be empty")
|
||||
}
|
||||
if (data.keeperPostCode.isNullOrEmpty()) {
|
||||
throw IOException("Keepers post code cannot be empty")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import org.kodein.di.generic.instance
|
||||
abstract class BaseFragment<V : BaseViewModel, VB : ViewBinding> : Fragment(), KodeinAware {
|
||||
|
||||
private var _binding: VB? = null
|
||||
private val binding: VB
|
||||
val binding: VB
|
||||
get() = _binding ?: error("Must only access binding while fragment is attached.")
|
||||
|
||||
var mActivity: BaseActivity<V, *>? = null
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
@@ -9,11 +8,9 @@ import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.data.UserAuthState
|
||||
import h_mal.appttude.com.driver.model.Model
|
||||
import h_mal.appttude.com.driver.ui.user.LoginActivity
|
||||
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
||||
import h_mal.appttude.com.driver.utils.TextValidationUtils.validateEditText
|
||||
import h_mal.appttude.com.driver.utils.setGlideImage
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, VB : ViewBinding, T : Model> :
|
||||
|
||||
@@ -53,8 +53,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
|
||||
|
||||
return localImageUri?.let { uri ->
|
||||
storageRef?.let {
|
||||
val image = storage?.uploadImage(uri, it, imageString)
|
||||
image.toString()
|
||||
storage!!.uploadImageReturnRef(uri, it, imageString)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,6 +66,14 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
|
||||
return uploadImage(localImageUri) ?: imageUrl!!
|
||||
}
|
||||
|
||||
suspend fun getImageStorageRefAfterUpload(localImageUri: Uri?): String {
|
||||
if (localImageUri == null) {
|
||||
throw IOException("No image is selected")
|
||||
}
|
||||
|
||||
return uploadImage(localImageUri) ?: throw IOException("Image ")
|
||||
}
|
||||
|
||||
suspend fun getImageUrls(localImageUris: List<Uri?>?): List<String?> {
|
||||
if (localImageUris.isNullOrEmpty()) {
|
||||
throw IOException("No images is selected")
|
||||
|
||||
@@ -2,17 +2,22 @@ package h_mal.appttude.com.driver.base
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.google.firebase.database.DataSnapshot
|
||||
import com.google.firebase.database.DatabaseError
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.database.ValueEventListener
|
||||
import h_mal.appttude.com.driver.data.DataState
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseCompletion
|
||||
import h_mal.appttude.com.driver.data.FirebaseDataLiveData
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
||||
import h_mal.appttude.com.driver.utils.toLiveData
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
abstract class DataSubmissionViewModel<T : Any>(
|
||||
abstract class DataSubmissionViewModel<T : Document>(
|
||||
auth: FirebaseAuthentication,
|
||||
private val database: FirebaseDatabaseSource
|
||||
) : BaseViewModel() {
|
||||
@@ -21,15 +26,33 @@ abstract class DataSubmissionViewModel<T : Any>(
|
||||
|
||||
abstract val databaseRef: DatabaseReference
|
||||
|
||||
private val refLiveData: LiveData<DataState> by lazy { databaseRef.toLiveData<T>() }
|
||||
private val refLiveData: LiveData<DataState> by lazy { FirebaseDataLiveData<T>(databaseRef, getGenericClassAt<T>(0).java) }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val observer = Observer<DataState> {
|
||||
when (it) {
|
||||
is DataState.HasData<*> -> onSuccess(it.data)
|
||||
is DataState.HasData<*> -> {
|
||||
if (it.data is Document) setData(it.data as T)
|
||||
}
|
||||
is DataState.HasError -> onError(it.error.message)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
private val valueListener = object : ValueEventListener {
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
snapshot.getValue(getGenericClassAt<T>(0).javaObjectType)
|
||||
}
|
||||
|
||||
override fun onCancelled(error: DatabaseError) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
open fun setData(data: T) {
|
||||
onSuccess(data)
|
||||
}
|
||||
|
||||
fun init() {
|
||||
// databaseRef.addValueEventListener()
|
||||
refLiveData.observeForever(observer)
|
||||
}
|
||||
|
||||
@@ -51,13 +74,19 @@ abstract class DataSubmissionViewModel<T : Any>(
|
||||
|
||||
open fun postDataToDatabase(data: T) {
|
||||
io {
|
||||
if (!validateData(data)) return@io
|
||||
if (getDataFromDatabase() == data) return@io
|
||||
doTryOperation("Failed to submit document") {
|
||||
if (!validateData(data)) return@doTryOperation
|
||||
|
||||
val postObject = database.postToDatabaseRed(databaseRef, data)
|
||||
onSuccess(postObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun String?.validateStringOrThrow(fieldName: String) {
|
||||
if (isNullOrEmpty()) {
|
||||
throw IOException("$fieldName cannot be empty")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +1,38 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.ImageDocumentFile
|
||||
import h_mal.appttude.com.driver.data.ImageResults
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import h_mal.appttude.com.driver.utils.isNotNull
|
||||
import kotlinx.coroutines.tasks.await
|
||||
|
||||
|
||||
abstract class DataSubmissionViewModel2<T : Any>(
|
||||
abstract class DataSubmissionViewModel2<T : ImageDocument>(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
private val storage: FirebaseStorageSource
|
||||
private val storage: FirebaseStorageSource,
|
||||
private val storageType: Storage
|
||||
) : DataSubmissionViewModel<T>(auth, database) {
|
||||
|
||||
abstract val storageRef: StorageReference
|
||||
|
||||
// retrieve image and thumbnail as a pair
|
||||
fun getImageAndThumbnail(filename: String): Pair<StorageReference, StorageReference> {
|
||||
fun getImageAndThumbnail(filename: String): ImageResults {
|
||||
val thumbnail = StringBuilder()
|
||||
.append("thumb_")
|
||||
.append(filename.split(".")[0])
|
||||
.append(".png")
|
||||
.toString()
|
||||
|
||||
return Pair(
|
||||
return ImageResults(
|
||||
storageRef.child(filename),
|
||||
storageRef.child(thumbnail)
|
||||
)
|
||||
@@ -42,14 +48,44 @@ abstract class DataSubmissionViewModel2<T : Any>(
|
||||
return storage.uploadImageReturnName(localImageUri, storageRef, imageString)
|
||||
}
|
||||
|
||||
fun postDataToDatabase(localImageUri: Uri, data: T, storages: Storage) {
|
||||
fun postDataToDatabase(localImageUri: Uri?, data: T) {
|
||||
io {
|
||||
val fileName = uploadImage(localImageUri, storages)
|
||||
val afterData = setDataAfterUpload(data, fileName)
|
||||
val documentFileName = data.getImageFileName()
|
||||
// Validate at least image selector image or previously uploaded documents photo available
|
||||
if (localImageUri == null && documentFileName.isNullOrEmpty()) {
|
||||
onError("Please select an image")
|
||||
return@io
|
||||
}
|
||||
// Upload a new image or keep old image
|
||||
val fileName = localImageUri?.let { uploadImage(it, storageType) } ?: documentFileName
|
||||
|
||||
super.postDataToDatabase(afterData)
|
||||
fileName.isNotNull {
|
||||
data.setImageFileName(it)
|
||||
super.postDataToDatabase(data)
|
||||
return@io
|
||||
}
|
||||
onError("Could not upload document")
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun setDataAfterUpload(data: T, filename: String): T
|
||||
override fun postDataToDatabase(data: T) {}
|
||||
|
||||
override fun setData(data: T) {
|
||||
val fileName = data.getImageFileName()
|
||||
io {
|
||||
fileName?.let {
|
||||
val pair = getImageAndThumbnail(it)
|
||||
|
||||
val img = if (pair.image?.downloadUrl?.await() != null) pair.image else null
|
||||
val tmb = if (pair.thumbnail?.downloadUrl?.await() != null) pair.image else null
|
||||
|
||||
val image = ImageResults(img, tmb)
|
||||
|
||||
val document = ImageDocumentFile(data, image)
|
||||
onSuccess(document)
|
||||
}
|
||||
super.setData(data)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,30 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.android.gms.tasks.Tasks
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.data.FirebaseAuthentication
|
||||
import h_mal.appttude.com.driver.data.FirebaseDatabaseSource
|
||||
import h_mal.appttude.com.driver.data.FirebaseStorageSource
|
||||
import h_mal.appttude.com.driver.data.ImageCollection
|
||||
import h_mal.appttude.com.driver.data.Storage
|
||||
import h_mal.appttude.com.driver.utils.Coroutines.io
|
||||
import h_mal.appttude.com.driver.utils.DateUtils
|
||||
import h_mal.appttude.com.driver.utils.isNotNull
|
||||
import h_mal.appttude.com.driver.utils.mapIndexSuspend
|
||||
|
||||
|
||||
abstract class DataSubmissionViewModel3<T : Any>(
|
||||
abstract class DataSubmissionViewModel3<T : MultiImageDocument>(
|
||||
auth: FirebaseAuthentication,
|
||||
database: FirebaseDatabaseSource,
|
||||
private val storage: FirebaseStorageSource
|
||||
private val storage: FirebaseStorageSource,
|
||||
private val storageType: Storage
|
||||
) : DataSubmissionViewModel<T>(auth, database) {
|
||||
|
||||
abstract val storageRef: StorageReference
|
||||
|
||||
fun getImagesAndThumbnails(filenames: List<String>): List<Pair<StorageReference, StorageReference>> {
|
||||
return filenames.map {
|
||||
fun getImagesAndThumbnails(filenames: List<String>): ImageCollection {
|
||||
val listMap = filenames.map {
|
||||
val thumbnail = StringBuilder()
|
||||
.append("thumb_")
|
||||
.append(it.split(".")[0])
|
||||
@@ -32,6 +36,7 @@ abstract class DataSubmissionViewModel3<T : Any>(
|
||||
storageRef.child(thumbnail)
|
||||
)
|
||||
}
|
||||
return ImageCollection(listMap)
|
||||
}
|
||||
|
||||
suspend fun uploadImages(localImageUris: List<Uri>, storages: Storage): List<String> {
|
||||
@@ -47,15 +52,43 @@ abstract class DataSubmissionViewModel3<T : Any>(
|
||||
}
|
||||
}
|
||||
|
||||
fun postDataToDatabase(localImageUris: List<Uri>, data: T, storages: Storage) {
|
||||
fun postDataToDatabase(localImageUris: List<Uri>, data: T) {
|
||||
io {
|
||||
val files = uploadImages(localImageUris, storages)
|
||||
val postData = setDataAfterUpload(data, files)
|
||||
// Validate document fore upload
|
||||
if (!validateData(data)) return@io
|
||||
val documentFileNames = data.getImageFileNames()
|
||||
// Validate at least image selector image or previously uploaded documents photo available
|
||||
if (localImageUris.isEmpty() && documentFileNames.isNullOrEmpty()) {
|
||||
onError("Please select an image")
|
||||
return@io
|
||||
}
|
||||
// Upload a new image or keep old image
|
||||
val fileNames =
|
||||
localImageUris.takeIf { it.isNotEmpty() }?.let { uploadImages(it, storageType) }
|
||||
?: documentFileNames
|
||||
|
||||
super.postDataToDatabase(postData)
|
||||
fileNames.isNotNull {
|
||||
data.setImageFileNames(it)
|
||||
super.postDataToDatabase(data)
|
||||
return@io
|
||||
}
|
||||
onError("Could not upload document")
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun setDataAfterUpload(data: T, filename: List<String>): T
|
||||
override fun setData(data: T) {
|
||||
val fileNames = data.getImageFileNames()
|
||||
fileNames?.let { l ->
|
||||
val list = getImagesAndThumbnails(l).collection
|
||||
|
||||
val results = list.map { it.second.downloadUrl }.let { Tasks.whenAllComplete(it) }
|
||||
results.addOnSuccessListener {
|
||||
onSuccess(list)
|
||||
}
|
||||
}
|
||||
super.setData(data)
|
||||
}
|
||||
|
||||
override fun postDataToDatabase(data: T) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import h_mal.appttude.com.driver.data.UserAuthState
|
||||
import h_mal.appttude.com.driver.ui.user.LoginActivity
|
||||
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
||||
import h_mal.appttude.com.driver.utils.TextValidationUtils.validateEditText
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
abstract class FormSubmissionFragment<V : DataSubmissionViewModel<T>, VB : ViewBinding, T : Document> :
|
||||
BaseFragment<V, VB>() {
|
||||
|
||||
var model: T = getGenericClassAt<T>(2).createInstance()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
viewModel.init()
|
||||
}
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// If user is logged out then navigate to LoginActivity
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner) {
|
||||
if (it is UserAuthState.LoggedOut) {
|
||||
val intent = Intent(requireContext(), LoginActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
requireActivity().finish()
|
||||
return@observe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun onSuccess(data: Any?) {
|
||||
super.onSuccess(data)
|
||||
|
||||
when (data) {
|
||||
is Model -> {
|
||||
model = data as T
|
||||
setFields(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun setFields(data: T) { }
|
||||
|
||||
open fun submit() {}
|
||||
|
||||
fun validateEditTexts(vararg editTexts: EditText): Boolean {
|
||||
editTexts.forEach {
|
||||
if (it.text.isNullOrBlank()) {
|
||||
it.validateEditText()
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun EditText.setTextOnChange(output: (m: String) -> Unit) {
|
||||
doAfterTextChanged {
|
||||
output(text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
open fun submitDocument() {
|
||||
viewModel.postDataToDatabase(model)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.Manifest
|
||||
import android.net.Uri
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import h_mal.appttude.com.driver.data.ImageDocumentFile
|
||||
import h_mal.appttude.com.driver.data.ImageResults
|
||||
import h_mal.appttude.com.driver.ui.permission.PermissionsDeclarationDialog
|
||||
import permissions.dispatcher.NeedsPermission
|
||||
import permissions.dispatcher.OnNeverAskAgain
|
||||
import permissions.dispatcher.OnPermissionDenied
|
||||
import permissions.dispatcher.OnShowRationale
|
||||
import permissions.dispatcher.PermissionRequest
|
||||
import permissions.dispatcher.RuntimePermissions
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
@RuntimePermissions
|
||||
abstract class ImageFormSubmissionFragment<V : DataSubmissionViewModel2<T>, VB : ViewBinding, T : ImageDocument> :
|
||||
FormSubmissionFragment<V, VB, T>(), ImageSelectionHelper {
|
||||
|
||||
private val selectedImage: AtomicReference<Uri> = AtomicReference()
|
||||
|
||||
private fun setSelectedImages(image: Uri) {
|
||||
selectedImage.set(image)
|
||||
}
|
||||
|
||||
fun getSelectedImages(): Uri? {
|
||||
return selectedImage.get()
|
||||
}
|
||||
|
||||
override fun onSuccess(data: Any?) {
|
||||
super.onSuccess(data)
|
||||
if (data is ImageDocumentFile<*>) {
|
||||
setImage(data.image.image, data.image.thumbnail)
|
||||
setFields(data.document as T)
|
||||
}
|
||||
}
|
||||
|
||||
open fun setImage(image: StorageReference?, thumbnail: StorageReference?) {}
|
||||
|
||||
private val permissionRequest =
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { result ->
|
||||
result?.let { onImageGalleryResult(result) }
|
||||
}
|
||||
|
||||
override fun openGalleryForImageSelection() {
|
||||
permissionRequest.launch("image/*")
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
// NOTE: delegate the permission handling to generated method
|
||||
onRequestPermissionsResult(requestCode, grantResults)
|
||||
}
|
||||
|
||||
@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun showStorage() {
|
||||
openGalleryForImageSelection()
|
||||
}
|
||||
|
||||
@OnShowRationale(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun showRationaleForStorage(request: PermissionRequest) {
|
||||
PermissionsDeclarationDialog(requireContext()).showDialog({
|
||||
request.proceed()
|
||||
}, {
|
||||
request.cancel()
|
||||
})
|
||||
}
|
||||
|
||||
@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun onStorageDenied() {
|
||||
showToast("Storage permissions have been denied")
|
||||
}
|
||||
|
||||
@OnNeverAskAgain(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun onStorageNeverAskAgain() {
|
||||
showToast("Storage permissions have been to never ask again")
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the result of image selection
|
||||
*/
|
||||
open fun onImageGalleryResult(imageUri: Uri) {
|
||||
setSelectedImages(imageUri)
|
||||
}
|
||||
|
||||
override fun submitDocument() {
|
||||
viewModel.postDataToDatabase(getSelectedImages(), model)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
|
||||
interface ImageSelectionHelper {
|
||||
|
||||
fun openGalleryForImageSelection()
|
||||
fun imageSelectorIntent(multiImage: Boolean = false) = Intent(Intent.ACTION_GET_CONTENT)
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiImage)
|
||||
.setType("image/*")
|
||||
|
||||
fun Intent?.parseMultiImageIntent(): List<Uri> {
|
||||
this?.clipData?.takeIf { it.itemCount > 1 }?.convertToList()?.let { clip ->
|
||||
val list = clip.takeIf { it.size > 10 }?.let {
|
||||
clip.subList(0, 9)
|
||||
} ?: clip
|
||||
return list
|
||||
}
|
||||
return listOfNotNull(this?.data)
|
||||
}
|
||||
|
||||
private fun ClipData.convertToList(): List<Uri> = 0.rangeTo(itemCount).map { getItemAt(it).uri }
|
||||
|
||||
}
|
||||
@@ -16,14 +16,11 @@ import permissions.dispatcher.PermissionRequest
|
||||
import permissions.dispatcher.RuntimePermissions
|
||||
|
||||
@RuntimePermissions
|
||||
open class ImageSelectorFragment<V : BaseViewModel, VB : ViewBinding> : BaseFragment<V, VB>() {
|
||||
private var multipleImage: Boolean = false
|
||||
open class ImageSelectorFragment<V : BaseViewModel, VB : ViewBinding>(
|
||||
private val multipleImage: Boolean = false
|
||||
) : BaseFragment<V, VB>() {
|
||||
var picUri: Uri? = null
|
||||
|
||||
fun setImageSelectionAsMultiple() {
|
||||
multipleImage = true
|
||||
}
|
||||
|
||||
fun openGalleryForImage() {
|
||||
permissionRequest.launch(multipleImage)
|
||||
}
|
||||
|
||||
14
app/src/main/java/h_mal/appttude/com/driver/base/Model.kt
Normal file
14
app/src/main/java/h_mal/appttude/com/driver/base/Model.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
interface Model
|
||||
|
||||
interface Document : Model
|
||||
interface ImageDocument : Document {
|
||||
fun getImageFileName(): String?
|
||||
fun setImageFileName(fileName: String)
|
||||
}
|
||||
|
||||
interface MultiImageDocument : Document {
|
||||
fun getImageFileNames(): List<String>?
|
||||
fun setImageFileNames(images: List<String>)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package h_mal.appttude.com.driver.base
|
||||
|
||||
import android.Manifest
|
||||
import android.net.Uri
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import h_mal.appttude.com.driver.data.ImageCollection
|
||||
import h_mal.appttude.com.driver.ui.permission.PermissionsDeclarationDialog
|
||||
import permissions.dispatcher.NeedsPermission
|
||||
import permissions.dispatcher.OnNeverAskAgain
|
||||
import permissions.dispatcher.OnPermissionDenied
|
||||
import permissions.dispatcher.OnShowRationale
|
||||
import permissions.dispatcher.PermissionRequest
|
||||
import permissions.dispatcher.RuntimePermissions
|
||||
|
||||
@RuntimePermissions
|
||||
abstract class MultiImageFormSubmissionFragment3<V : DataSubmissionViewModel3<T>, VB : ViewBinding, T : MultiImageDocument> :
|
||||
FormSubmissionFragment<V, VB, T>(), ImageSelectionHelper {
|
||||
|
||||
private val selectedImages: MutableList<Uri> = mutableListOf()
|
||||
|
||||
private fun setSelectedImages(images: List<Uri>) {
|
||||
selectedImages.clear()
|
||||
selectedImages.addAll(images)
|
||||
}
|
||||
|
||||
fun getSelectedImages(): List<Uri> {
|
||||
return selectedImages
|
||||
}
|
||||
|
||||
override fun onSuccess(data: Any?) {
|
||||
super.onSuccess(data)
|
||||
if (data is ImageCollection) {
|
||||
setImages(data)
|
||||
}
|
||||
}
|
||||
|
||||
open fun setImages(collection: ImageCollection) {}
|
||||
|
||||
private val permissionRequest =
|
||||
registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { result ->
|
||||
result?.let { onImageGalleryResult(result) }
|
||||
}
|
||||
|
||||
override fun openGalleryForImageSelection() {
|
||||
permissionRequest.launch("image/*")
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
// NOTE: delegate the permission handling to generated method
|
||||
onRequestPermissionsResult(requestCode, grantResults)
|
||||
}
|
||||
|
||||
@NeedsPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun showStorage() {
|
||||
openGalleryForImageSelection()
|
||||
}
|
||||
|
||||
@OnShowRationale(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun showRationaleForStorage(request: PermissionRequest) {
|
||||
PermissionsDeclarationDialog(requireContext()).showDialog({
|
||||
request.proceed()
|
||||
}, {
|
||||
request.cancel()
|
||||
})
|
||||
}
|
||||
|
||||
@OnPermissionDenied(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun onStorageDenied() {
|
||||
showToast("Storage permissions have been denied")
|
||||
}
|
||||
|
||||
@OnNeverAskAgain(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
fun onStorageNeverAskAgain() {
|
||||
showToast("Storage permissions have been to never ask again")
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the result of image selection
|
||||
*/
|
||||
open fun onImageGalleryResult(imageUris: List<Uri>) {
|
||||
setSelectedImages(imageUris)
|
||||
}
|
||||
|
||||
override fun submitDocument() {
|
||||
viewModel.postDataToDatabase(getSelectedImages(), model)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package h_mal.appttude.com.driver.data
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.google.firebase.database.DataSnapshot
|
||||
import com.google.firebase.database.DatabaseError
|
||||
import com.google.firebase.database.DatabaseReference
|
||||
import com.google.firebase.database.ValueEventListener
|
||||
|
||||
/**
|
||||
* Creates #LiveDate out of {UserAuthState} for firebase user state
|
||||
*/
|
||||
class FirebaseDataLiveData<T : Any>(
|
||||
private val reference: DatabaseReference,
|
||||
private val cls: Class<T>
|
||||
) : LiveData<DataState>() {
|
||||
|
||||
override fun onActive() {
|
||||
super.onActive()
|
||||
reference.addValueEventListener(stateListener)
|
||||
}
|
||||
|
||||
override fun onInactive() {
|
||||
super.onInactive()
|
||||
reference.addValueEventListener(stateListener)
|
||||
}
|
||||
|
||||
private val stateListener = object : ValueEventListener {
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
val data = snapshot.getValue(cls)
|
||||
postValue(DataState.HasData(data ?: FirebaseCompletion.Default))
|
||||
}
|
||||
|
||||
override fun onCancelled(error: DatabaseError) {
|
||||
postValue(DataState.HasError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package h_mal.appttude.com.driver.data
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.firebase.storage.FirebaseStorage
|
||||
import com.google.firebase.storage.StorageMetadata
|
||||
import com.google.firebase.storage.StorageReference
|
||||
import kotlinx.coroutines.tasks.await
|
||||
|
||||
@@ -27,7 +28,7 @@ class FirebaseStorageSource {
|
||||
|
||||
suspend fun uploadImageReturnName(localFilePath: Uri, path: StorageReference, filename: String): String {
|
||||
val ref = path.child("$filename.jpeg")
|
||||
return ref.putFile(localFilePath)
|
||||
return ref.putFile(localFilePath, StorageMetadata.Builder().setContentType("image/jpeg").build())
|
||||
.continueWith { ref.name }
|
||||
.await()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package h_mal.appttude.com.driver.data
|
||||
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
data class ImageDocumentFile<T : ImageDocument>(
|
||||
val document: T,
|
||||
val image: ImageResults
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package h_mal.appttude.com.driver.data
|
||||
|
||||
import com.google.firebase.storage.StorageReference
|
||||
|
||||
data class ImageResults(
|
||||
val image: StorageReference?,
|
||||
val thumbnail: StorageReference?
|
||||
)
|
||||
|
||||
data class ImageCollection(
|
||||
val collection: List<Pair<StorageReference, StorageReference>>
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
package h_mal.appttude.com.driver.data
|
||||
|
||||
import com.google.firebase.database.DataSnapshot
|
||||
import h_mal.appttude.com.driver.utils.GenericsHelper.getGenericClassAt
|
||||
|
||||
class SnapshotResults<T: Any>(
|
||||
private val snapshot: DataSnapshot
|
||||
) {
|
||||
private val cls = this.getGenericClassAt<T>(0).getGenericClassAt<T>(0).java
|
||||
|
||||
fun getData(): T? {
|
||||
return snapshot.getValue(cls)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.Document
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class DriverProfile(
|
||||
var driverPic: String? = null,
|
||||
var forenames: String? = null,
|
||||
@@ -8,4 +14,14 @@ data class DriverProfile(
|
||||
var dob: String? = null,
|
||||
var ni: String? = null,
|
||||
var dateFirst: String? = null
|
||||
) : Model
|
||||
) : ImageDocument {
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return driverPic
|
||||
}
|
||||
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
driverPic = fileName
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,22 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class DriversLicense(
|
||||
var licenseImageString: String? = null,
|
||||
var licenseNumber: String? = null,
|
||||
var licenseExpiry: String? = null
|
||||
) : Model
|
||||
) : ImageDocument {
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return licenseImageString
|
||||
}
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
licenseImageString = fileName
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,31 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.MultiImageDocument
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class Insurance(
|
||||
var photoStrings: MutableList<String>? = null,
|
||||
var insurerName: String? = null,
|
||||
var expiryDate: String? = null
|
||||
) : Model
|
||||
) : MultiImageDocument {
|
||||
@Exclude
|
||||
override fun getImageFileNames(): List<String>? {
|
||||
return photoStrings
|
||||
}
|
||||
|
||||
@Exclude
|
||||
override fun setImageFileNames(images: List<String>) {
|
||||
// update existing array
|
||||
photoStrings?.run{
|
||||
clear()
|
||||
addAll(images)
|
||||
return
|
||||
}
|
||||
// set new array of images
|
||||
photoStrings = mutableListOf<String>().apply {
|
||||
addAll(images)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,20 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import h_mal.appttude.com.driver.base.Document
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
|
||||
data class Logbook(
|
||||
var photoString: String? = null,
|
||||
var v5cnumber: String? = null
|
||||
) : Model
|
||||
) : ImageDocument{
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return photoString
|
||||
}
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
photoString = fileName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
interface Model
|
||||
@@ -1,7 +1,21 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class Mot(
|
||||
var motImageString: String? = null,
|
||||
var motExpiry: String? = null
|
||||
) : Model
|
||||
) : ImageDocument {
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return motImageString
|
||||
}
|
||||
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
motImageString = fileName
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,23 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class PrivateHireLicense(
|
||||
var phImageString: String? = null,
|
||||
var phNumber: String? = null,
|
||||
var phExpiry: String? = null
|
||||
) : Model
|
||||
) : ImageDocument {
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return phImageString
|
||||
}
|
||||
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
phImageString = fileName
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,23 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.Exclude
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.ImageDocument
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class PrivateHireVehicle(
|
||||
var phCarImageString: String? = null,
|
||||
var phCarNumber: String? = null,
|
||||
var phCarExpiry: String? = null
|
||||
) : Model
|
||||
) : ImageDocument {
|
||||
|
||||
@Exclude
|
||||
override fun getImageFileName(): String? {
|
||||
return phCarImageString
|
||||
}
|
||||
|
||||
@Exclude
|
||||
override fun setImageFileName(fileName: String) {
|
||||
phCarImageString = fileName
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package h_mal.appttude.com.driver.model
|
||||
|
||||
import com.google.firebase.database.IgnoreExtraProperties
|
||||
import h_mal.appttude.com.driver.base.Document
|
||||
|
||||
@IgnoreExtraProperties
|
||||
data class VehicleProfile(
|
||||
var reg: String? = null,
|
||||
var make: String? = null,
|
||||
@@ -11,4 +14,4 @@ data class VehicleProfile(
|
||||
var keeperPostCode: String? = null,
|
||||
var startDate: String? = null,
|
||||
var isSeized: Boolean = false
|
||||
) : Model
|
||||
) : Document
|
||||
@@ -76,7 +76,7 @@ suspend fun <T : Any> DatabaseReference.getDataFromDatabaseRef(clazz: Class<T>):
|
||||
|
||||
fun <T : Any> DatabaseReference.toLiveData(): LiveData<DataState> {
|
||||
return object : LiveData<DataState>() {
|
||||
private val listener = addValueEventListener(object : ValueEventListener{
|
||||
private val listener = object : ValueEventListener{
|
||||
override fun onDataChange(snapshot: DataSnapshot) {
|
||||
val data = snapshot.getValue(object : GenericTypeIndicator<T>() {})
|
||||
postValue(DataState.HasData(data ?: FirebaseCompletion.Default))
|
||||
@@ -84,7 +84,7 @@ fun <T : Any> DatabaseReference.toLiveData(): LiveData<DataState> {
|
||||
override fun onCancelled(error: DatabaseError) {
|
||||
postValue(DataState.HasError(error))
|
||||
}
|
||||
})
|
||||
}
|
||||
override fun onActive() {
|
||||
super.onActive()
|
||||
// add listener
|
||||
|
||||
@@ -12,7 +12,7 @@ object GenericsHelper {
|
||||
((javaClass.genericSuperclass as? ParameterizedType)
|
||||
?.actualTypeArguments?.getOrNull(position) as? Class<CLASS>)
|
||||
?.kotlin
|
||||
?: throw IllegalStateException("Can not find class from generic argument")
|
||||
?: throw IllegalStateException("Can not find class from generic argument ${this}")
|
||||
|
||||
/**
|
||||
* Create a view binding out of the the generic [VB]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"port": 9099
|
||||
},
|
||||
"database": {
|
||||
"port": 9000
|
||||
"port": 9001
|
||||
},
|
||||
"storage": {
|
||||
"port": 9199
|
||||
@@ -12,12 +12,27 @@
|
||||
"ui": {
|
||||
"enabled": true
|
||||
},
|
||||
"singleProjectMode": true
|
||||
"singleProjectMode": true,
|
||||
"functions": {
|
||||
"port": 5001
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"rules": "database.rules.json"
|
||||
},
|
||||
"storage": {
|
||||
"rules": "storage.rules"
|
||||
},
|
||||
"functions": [
|
||||
{
|
||||
"source": "functions",
|
||||
"codebase": "default",
|
||||
"ignore": [
|
||||
"venv",
|
||||
".git",
|
||||
"firebase-debug.log",
|
||||
"firebase-debug.*.log"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user