- android bumblebee gradle migration

- lint driverDebug
 - view binding migration

Took 12 hours 10 minutes
This commit is contained in:
2023-03-24 19:15:48 +00:00
parent 7f4060f1c2
commit 1b00d7d40d
125 changed files with 1163 additions and 1013 deletions

View File

@@ -1,16 +1,9 @@
apply plugin: 'com.android.application' plugins {
apply plugin: 'kotlin-android' id 'com.android.application'
apply plugin: 'kotlin-android-extensions' id 'org.jetbrains.kotlin.android'
id 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services' id 'kotlin-kapt'
id 'androidx.navigation.safeargs'
// kotlin kapt
apply plugin: 'kotlin-kapt'
// Android navigation
apply plugin: 'androidx.navigation.safeargs'
repositories {
mavenCentral()
} }
def relStorePassword = System.getenv("RELEASE_STORE_PASSWORD") def relStorePassword = System.getenv("RELEASE_STORE_PASSWORD")
@@ -59,10 +52,16 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "1.8"
} }
buildFeatures {
viewBinding true
}
flavorDimensions "Default" flavorDimensions "Default"
productFlavors { productFlavors {
@@ -139,7 +138,7 @@ dependencies {
/ * coroutines support for firebase operations */ / * coroutines support for firebase operations */
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.1"
/ * Circle Image View */ / * Circle Image View */
implementation "com.mikhaellopez:circularimageview:4.2.0" implementation "com.mikhaellopez:circularimageview:4.3.0"
/ * Kodein Dependency Injection */ / * Kodein Dependency Injection */
def kodein_version = "6.2.1" def kodein_version = "6.2.1"
implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version" implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version"
@@ -151,4 +150,6 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
/ * OKHttp */ / * OKHttp */
implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.squareup.okhttp3:okhttp:4.10.0'
/ * Kotlin Reflect */
implementation "org.jetbrains.kotlin:kotlin-reflect:1.8.10"
} }

View File

@@ -1,7 +1,6 @@
package h_mal.appttude.com.objects package h_mal.appttude.com.objects
class ApprovalsObject { class ApprovalsObject {
var driver_details_approval: Int = 0 var driver_details_approval: Int = 0
var driver_license_approval: Int = 0 var driver_license_approval: Int = 0

View File

@@ -1,7 +1,6 @@
package h_mal.appttude.com.objects package h_mal.appttude.com.objects
class UserObject { class UserObject {
var profileName: String? = null var profileName: String? = null
var profileEmail: String? = null var profileEmail: String? = null

View File

@@ -29,14 +29,15 @@ class MappedObject : Parcelable {
companion object { companion object {
@JvmField @JvmField
val CREATOR: Parcelable.Creator<MappedObject?> = object : Parcelable.Creator<MappedObject?> { val CREATOR: Parcelable.Creator<MappedObject?> =
override fun createFromParcel(`in`: Parcel): MappedObject? { object : Parcelable.Creator<MappedObject?> {
return MappedObject(`in`) override fun createFromParcel(`in`: Parcel): MappedObject? {
} return MappedObject(`in`)
}
override fun newArray(size: Int): Array<MappedObject?> { override fun newArray(size: Int): Array<MappedObject?> {
return arrayOfNulls(size) return arrayOfNulls(size)
}
} }
}
} }
} }

View File

@@ -12,7 +12,7 @@ import h_mal.appttude.com.R
class ApprovalListAdapter( class ApprovalListAdapter(
private val activity: Activity, private val activity: Activity,
objects: Array<MappedObject?> objects: Array<MappedObject?>
): ArrayAdapter<MappedObject?>(activity, 0, objects) { ) : ArrayAdapter<MappedObject?>(activity, 0, objects) {
var mappedObject: MappedObject? = objects[0] var mappedObject: MappedObject? = objects[0]

View File

@@ -125,7 +125,9 @@ class HomeSuperUserFragment : Fragment() {
} }
return s1!!.compareTo((s2)!!) return s1!!.compareTo((s2)!!)
} }
else -> { throw IOException("dfdfs") } else -> {
throw IOException("dfdfs")
}
// 2 -> return MainActivity.approvalsClass.getOverApprovalStatusCode(o1.wholeDriverObject) - // 2 -> return MainActivity.approvalsClass.getOverApprovalStatusCode(o1.wholeDriverObject) -
// MainActivity.approvalsClass.getOverApprovalStatusCode(o2.wholeDriverObject) // MainActivity.approvalsClass.getOverApprovalStatusCode(o2.wholeDriverObject)
// else -> return MainActivity.approvalsClass.getOverApprovalStatusCode( // else -> return MainActivity.approvalsClass.getOverApprovalStatusCode(

View File

@@ -70,7 +70,7 @@ class MainActivity : BaseActivity<MainViewModel>(),
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {
super.onSuccess(data) super.onSuccess(data)
when(data){ when (data) {
is FirebaseUser -> { is FirebaseUser -> {
setupDrawer(data) setupDrawer(data)
} }
@@ -84,7 +84,7 @@ class MainActivity : BaseActivity<MainViewModel>(),
header.profileImage.setGlideImage(user.photoUrl) header.profileImage.setGlideImage(user.photoUrl)
} }
private fun setupLogoutInDrawer(){ private fun setupLogoutInDrawer() {
logout.setOnClickListener { logout.setOnClickListener {
getViewModel().logOut() getViewModel().logOut()
} }
@@ -93,7 +93,7 @@ class MainActivity : BaseActivity<MainViewModel>(),
override fun onNavigationItemSelected(item: MenuItem): Boolean { override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here. // Handle navigation view item clicks here.
when (item.itemId) { when (item.itemId) {
R.id.nav_user_settings -> { } R.id.nav_user_settings -> {}
} }
drawer_layout.closeDrawer(GravityCompat.START) drawer_layout.closeDrawer(GravityCompat.START)
return true return true

View File

@@ -18,7 +18,8 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/cardviewoutline"/> android:src="@drawable/cardviewoutline" />
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@@ -75,7 +76,7 @@
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center"/> android:layout_gravity="center" />
<ImageView <ImageView
android:id="@+id/archive_icon" android:id="@+id/archive_icon"

View File

@@ -12,6 +12,6 @@
android:numColumns="2" android:numColumns="2"
android:rowCount="4" android:rowCount="4"
android:stretchMode="columnWidth" android:stretchMode="columnWidth"
tools:listitem="@layout/approval_list_grid_item"/> tools:listitem="@layout/approval_list_grid_item" />
</RelativeLayout> </RelativeLayout>

View File

@@ -21,6 +21,7 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/choice_img_round" /> tools:src="@drawable/choice_img_round" />
<ImageView <ImageView
android:id="@+id/approval_iv" android:id="@+id/approval_iv"
android:layout_width="10dp" android:layout_width="10dp"

View File

@@ -15,9 +15,13 @@ import org.hamcrest.CoreMatchers.anything
open class BaseTestRobot { open class BaseTestRobot {
fun fillEditText(resId: Int, text: String?): ViewInteraction = fun fillEditText(resId: Int, text: String?): ViewInteraction =
onView(withId(resId)).perform(ViewActions.replaceText(text), ViewActions.closeSoftKeyboard()) onView(withId(resId)).perform(
ViewActions.replaceText(text),
ViewActions.closeSoftKeyboard()
)
fun clickButton(resId: Int): ViewInteraction = onView((withId(resId))).perform(ViewActions.click()) fun clickButton(resId: Int): ViewInteraction =
onView((withId(resId))).perform(ViewActions.click())
fun textView(resId: Int): ViewInteraction = onView(withId(resId)) fun textView(resId: Int): ViewInteraction = onView(withId(resId))
@@ -35,6 +39,7 @@ open class BaseTestRobot {
fun checkErrorOnTextEntry(resId: Int, errorMessage: String): ViewInteraction = fun checkErrorOnTextEntry(resId: Int, errorMessage: String): ViewInteraction =
onView(withId(resId)).check(matches(checkErrorMessage(errorMessage))) onView(withId(resId)).check(matches(checkErrorMessage(errorMessage)))
fun getStringFromResource(@StringRes resId: Int): String = Resources.getSystem().getString(resId) fun getStringFromResource(@StringRes resId: Int): String =
Resources.getSystem().getString(resId)
} }

View File

@@ -16,7 +16,7 @@ import org.junit.After
import org.junit.Before import org.junit.Before
open class BaseUiTest<T : BaseActivity<*>>( open class BaseUiTest<T : BaseActivity<*,*>>(
private val activity: Class<T> private val activity: Class<T>
) { ) {

View File

@@ -3,7 +3,8 @@ package h_mal.appttude.com
private const val apiKey = "test_key" private const val apiKey = "test_key"
const val signUpFirebase = "http://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$apiKey" const val signUpFirebase = "http://identitytoolkit.googleapis.com/v1/accounts:signUp?key=$apiKey"
const val deleteAccountFirebase = "http://10.0.2.2:9099/identitytoolkit.googleapis.com/v1/accounts:delete?key=$apiKey" const val deleteAccountFirebase =
"http://10.0.2.2:9099/identitytoolkit.googleapis.com/v1/accounts:delete?key=$apiKey"
const val USER_PASSWORD = "LetMeIn123!" const val USER_PASSWORD = "LetMeIn123!"

View File

@@ -23,6 +23,7 @@ fun checkErrorMessage(expectedErrorText: String): Matcher<View?>? {
val error = view.error ?: return false val error = view.error ?: return false
return expectedErrorText == error.toString() return expectedErrorText == error.toString()
} }
override fun describeTo(d: Description?) {} override fun describeTo(d: Description?) {}
} }
} }

View File

@@ -10,7 +10,7 @@ import kotlinx.coroutines.tasks.await
import org.junit.After import org.junit.After
import org.junit.BeforeClass import org.junit.BeforeClass
open class FirebaseTest<T : BaseActivity<*>>( open class FirebaseTest<T : BaseActivity<*,*>>(
activity: Class<T>, activity: Class<T>,
private val registered: Boolean = false, private val registered: Boolean = false,
private val signedIn: Boolean = false private val signedIn: Boolean = false
@@ -62,7 +62,10 @@ open class FirebaseTest<T : BaseActivity<*>>(
suspend fun removeUser() { suspend fun removeUser() {
try { try {
getEmail()?.let { getEmail()?.let {
if (firebaseAuthSource.getUser() == null) firebaseAuthSource.signIn(email = it, password = USER_PASSWORD).await() if (firebaseAuthSource.getUser() == null) firebaseAuthSource.signIn(
email = it,
password = USER_PASSWORD
).await()
firebaseAuthSource.reauthenticate(it, USER_PASSWORD).await() firebaseAuthSource.reauthenticate(it, USER_PASSWORD).await()
firebaseAuthSource.deleteProfile().await() firebaseAuthSource.deleteProfile().await()
} }
@@ -74,7 +77,7 @@ open class FirebaseTest<T : BaseActivity<*>>(
fun generateEmailAddress(): String { fun generateEmailAddress(): String {
val suffix = (1000..50000).random() val suffix = (1000..50000).random()
email ="test-${suffix}@test-account.com" email = "test-${suffix}@test-account.com"
return email!! return email!!
} }

View File

@@ -1,10 +1,10 @@
package h_mal.appttude.com.firebase package h_mal.appttude.com.firebase
data class SignUpResponse( data class SignUpResponse(
val expiresIn: String? = null, val expiresIn: String? = null,
val kind: String? = null, val kind: String? = null,
val idToken: String? = null, val idToken: String? = null,
val localId: String? = null, val localId: String? = null,
val email: String? = null, val email: String? = null,
val refreshToken: String? = null val refreshToken: String? = null
) )

View File

@@ -4,7 +4,7 @@ import h_mal.appttude.com.BaseTestRobot
import h_mal.appttude.com.R import h_mal.appttude.com.R
fun home(func: HomeRobot.() -> Unit) = HomeRobot().apply { func() } fun home(func: HomeRobot.() -> Unit) = HomeRobot().apply { func() }
class HomeRobot: BaseTestRobot() { class HomeRobot : BaseTestRobot() {
fun checkTitleExists(title: String) = matchText(R.id.prova_title_tv, title) fun checkTitleExists(title: String) = matchText(R.id.prova_title_tv, title)

View File

@@ -5,7 +5,7 @@ import h_mal.appttude.com.R
fun login(func: LoginRobot.() -> Unit) = LoginRobot().apply { func() } fun login(func: LoginRobot.() -> Unit) = LoginRobot().apply { func() }
class LoginRobot: BaseTestRobot() { class LoginRobot : BaseTestRobot() {
fun setEmail(email: String?) = fillEditText(R.id.email, email) fun setEmail(email: String?) = fillEditText(R.id.email, email)

View File

@@ -4,7 +4,7 @@ import h_mal.appttude.com.BaseTestRobot
import h_mal.appttude.com.R import h_mal.appttude.com.R
fun register(func: RegisterRobot.() -> Unit) = RegisterRobot().apply { func() } fun register(func: RegisterRobot.() -> Unit) = RegisterRobot().apply { func() }
class RegisterRobot: BaseTestRobot() { class RegisterRobot : BaseTestRobot() {
fun setName(name: String) = fillEditText(R.id.name_register, name) fun setName(name: String) = fillEditText(R.id.name_register, name)

View File

@@ -8,7 +8,6 @@ import h_mal.appttude.com.R
import h_mal.appttude.com.USER_PASSWORD import h_mal.appttude.com.USER_PASSWORD
import h_mal.appttude.com.robots.home import h_mal.appttude.com.robots.home
import h_mal.appttude.com.robots.login import h_mal.appttude.com.robots.login
import h_mal.appttude.com.robots.register
import h_mal.appttude.com.ui.user.LoginActivity import h_mal.appttude.com.ui.user.LoginActivity
import org.junit.* import org.junit.*
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -16,7 +15,8 @@ import org.junit.runner.RunWith
@LargeTest @LargeTest
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class RegisteredUserAuthenticationActivityTest : FirebaseTest<LoginActivity>(LoginActivity::class.java, registered = true, signedIn = false) { class RegisteredUserAuthenticationActivityTest :
FirebaseTest<LoginActivity>(LoginActivity::class.java, registered = true, signedIn = false) {
@Test @Test
fun verifyUserLogin_validUsernameAndPassword_loggedIn() { fun verifyUserLogin_validUsernameAndPassword_loggedIn() {

View File

@@ -1,7 +1,9 @@
<manifest xmlns:tools="http://schemas.android.com/tools" <manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application android:usesCleartextTraffic="true" <application
android:usesCleartextTraffic="true"
tools:ignore="MissingApplicationIcon" /> tools:ignore="MissingApplicationIcon" />
</manifest> </manifest>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<network-security-config> <network-security-config>
<domain-config cleartextTrafficPermitted="true"> <domain-config cleartextTrafficPermitted="true">
<domain>10.0.2.2</domain> <domain includeSubdomains="true">10.0.2.2</domain>
</domain-config> </domain-config>
</network-security-config> </network-security-config>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:icon="@mipmap/ic_launcher" <application
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"> android:roundIcon="@mipmap/ic_launcher_round">
<activity <activity
android:name="h_mal.appttude.com.ui.user.LoginActivity" android:name="h_mal.appttude.com.ui.user.LoginActivity"
@@ -23,6 +24,7 @@
<activity <activity
android:name="h_mal.appttude.com.ui.update.UpdateActivity" android:name="h_mal.appttude.com.ui.update.UpdateActivity"
android:theme="@style/AppTheme.NoActionBar.Update" /> android:theme="@style/AppTheme.NoActionBar.Update" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="h_mal.appttude.com.driver" android:authorities="h_mal.appttude.com.driver"

View File

@@ -1,25 +1,32 @@
package h_mal.appttude.com.ui package h_mal.appttude.com.ui
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.databinding.FragmentDriverOverallBinding
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import kotlinx.android.synthetic.main.fragment_driver_overall.*
class DriverOverallFragment : Fragment(R.layout.fragment_driver_overall) { class DriverOverallFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onCreateView(
super.onViewCreated(view, savedInstanceState) inflater: LayoutInflater,
container: ViewGroup?,
driver_prof.setOnClickListener { savedInstanceState: Bundle?
it.navigateTo(R.id.to_driverProfileFragment) ): View {
} return FragmentDriverOverallBinding.inflate(inflater, container, false).apply {
private_hire.setOnClickListener { driverProf.setOnClickListener {
it.navigateTo(R.id.to_privateHireLicenseFragment2) it.navigateTo(R.id.to_driverProfileFragment)
} }
drivers_license.setOnClickListener { privateHire.setOnClickListener {
it.navigateTo(R.id.to_driverLicenseFragment) it.navigateTo(R.id.to_privateHireLicenseFragment2)
} }
driversLicense.setOnClickListener {
it.navigateTo(R.id.to_driverLicenseFragment)
}
}.root
} }
} }

View File

@@ -5,54 +5,56 @@ import android.view.View
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.data.DRIVER import h_mal.appttude.com.data.DRIVER
import h_mal.appttude.com.databinding.FragmentHomeDriverBinding
import h_mal.appttude.com.utils.hide import h_mal.appttude.com.utils.hide
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import h_mal.appttude.com.utils.show import h_mal.appttude.com.utils.show
import h_mal.appttude.com.viewmodels.RoleViewModel import h_mal.appttude.com.viewmodels.RoleViewModel
import kotlinx.android.synthetic.main.driver_profile_request.*
import kotlinx.android.synthetic.main.fragment_home_driver.*
import kotlinx.android.synthetic.main.home_buttons_container.*
class HomeFragment : DataSubmissionBaseFragment<RoleViewModel, String>(R.layout.fragment_home_driver) { class HomeFragment :
DataSubmissionBaseFragment<RoleViewModel, FragmentHomeDriverBinding, String>() {
private val viewmodel: RoleViewModel by getFragmentViewModel()
override fun getViewModel(): RoleViewModel = viewmodel
override var model = String() override var model = String()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewmodel.getDataFromDatabase() viewModel.getDataFromDatabase()
} }
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {
super.onSuccess(data) super.onSuccess(data)
if (data == DRIVER){ if (data == DRIVER) {
loadDriver() loadDriver()
return return
} }
loadNonDriver() loadNonDriver()
} }
private fun loadNonDriver(){ private fun loadNonDriver() {
home_buttons_container.hide() applyBinding {
profile_request_container.show() homeButtonsContainer.root.hide()
profileRequestContainer.root.show()
request_driver_button.setOnClickListener { profileRequestContainer.requestDriverButton.setOnClickListener {
viewmodel.setDataInDatabase(DRIVER) viewModel.setDataInDatabase(DRIVER)
}
} }
} }
private fun loadDriver(){ private fun loadDriver() {
home_buttons_container.show() applyBinding {
profile_request_container.hide() homeButtonsContainer.apply {
driver.setOnClickListener {
driver.setOnClickListener { view?.navigateTo(R.id.to_driverOverallFragment)
view?.navigateTo(R.id.to_driverOverallFragment) }
} car.setOnClickListener {
car.setOnClickListener { view?.navigateTo(R.id.to_vehicleOverallFragment)
view?.navigateTo(R.id.to_vehicleOverallFragment) }
root.show()
}
profileRequestContainer.root.hide()
} }
} }

View File

@@ -1,9 +1,7 @@
package h_mal.appttude.com.ui package h_mal.appttude.com.ui
import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.findNavController import androidx.navigation.findNavController
@@ -15,36 +13,30 @@ import com.google.android.material.navigation.NavigationView
import com.google.firebase.auth.FirebaseUser import com.google.firebase.auth.FirebaseUser
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseActivity import h_mal.appttude.com.base.BaseActivity
import h_mal.appttude.com.databinding.ActivityMainBinding
import h_mal.appttude.com.databinding.NavHeaderMainBinding
import h_mal.appttude.com.dialogs.ExitDialog.displayExitDialog import h_mal.appttude.com.dialogs.ExitDialog.displayExitDialog
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.MainViewModel import h_mal.appttude.com.viewmodels.MainViewModel
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.*
import kotlinx.android.synthetic.main.nav_header_main.view.*
class MainActivity : BaseActivity<MainViewModel>(), class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
NavigationView.OnNavigationItemSelectedListener { NavigationView.OnNavigationItemSelectedListener {
private val vm by createLazyViewModel<MainViewModel>()
override fun getViewModel(): MainViewModel = vm
override val layoutId: Int = R.layout.activity_main
lateinit var navController: NavController lateinit var navController: NavController
lateinit var appBarConfiguration: AppBarConfiguration lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) { override fun setupView(binding: ActivityMainBinding) = binding.run {
super.onCreate(savedInstanceState) setSupportActionBar(appBarLayout.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false) supportActionBar?.setDisplayShowTitleEnabled(false)
navController = findNavController(R.id.container) navController = findNavController(R.id.container)
appBarConfiguration = AppBarConfiguration(navController.graph, drawer_layout) appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
nav_view.setupWithNavController(navController) navView.setupWithNavController(navController)
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
getViewModel().getUserDetails() viewModel.getUserDetails()
setupLogoutInDrawer() setupLogoutInDrawer()
} }
@@ -53,24 +45,29 @@ class MainActivity : BaseActivity<MainViewModel>(),
} }
override fun setTitle(title: CharSequence) { override fun setTitle(title: CharSequence) {
toolbar.title = title applyBinding {
appBarLayout.toolbar.title = title
}
} }
override fun onBackPressed() { override fun onBackPressed() {
if (drawer_layout.isDrawerOpen(GravityCompat.START)) { applyBinding {
drawer_layout.closeDrawer(GravityCompat.START) if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
} else { drawerLayout.closeDrawer(GravityCompat.START)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.container) } else {
navHostFragment?.childFragmentManager?.backStackEntryCount?.takeIf { it >= 1 }?.let { val navHostFragment = supportFragmentManager.findFragmentById(R.id.container)
return super.onBackPressed() navHostFragment?.childFragmentManager?.backStackEntryCount?.let { it >= 1 }?.isTrue {
super.onBackPressed()
}
displayExitDialog()
} }
displayExitDialog()
} }
} }
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {
super.onSuccess(data) super.onSuccess(data)
when(data){ when (data) {
is FirebaseUser -> { is FirebaseUser -> {
setupDrawer(data) setupDrawer(data)
} }
@@ -78,24 +75,32 @@ class MainActivity : BaseActivity<MainViewModel>(),
} }
private fun setupDrawer(user: FirebaseUser) { private fun setupDrawer(user: FirebaseUser) {
val header: View = nav_view.getHeaderView(0) applyBinding {
header.driver_email.text = user.email NavHeaderMainBinding.inflate(layoutInflater).apply {
header.driver_name.text = user.displayName driverEmail.text = user.email
header.profileImage.setGlideImage(user.photoUrl) driverName.text = user.displayName
profileImage.setGlideImage(user.photoUrl)
}
}
} }
private fun setupLogoutInDrawer(){ private fun setupLogoutInDrawer() {
logout.setOnClickListener { applyBinding {
getViewModel().logOut() logout.setOnClickListener {
viewModel.logOut()
}
} }
} }
override fun onNavigationItemSelected(item: MenuItem): Boolean { override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here. // Handle navigation view item clicks here.
when (item.itemId) { when (item.itemId) {
R.id.nav_user_settings -> { } R.id.nav_user_settings -> {}
} }
drawer_layout.closeDrawer(GravityCompat.START) applyBinding {
drawerLayout.closeDrawer(GravityCompat.START)
}
return true return true
} }
} }

View File

@@ -1,23 +1,30 @@
package h_mal.appttude.com.ui package h_mal.appttude.com.ui
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.databinding.FragmentVehicleOverallBinding
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import kotlinx.android.synthetic.main.fragment_vehicle_overall.*
class VehicleOverallFragment : Fragment(R.layout.fragment_vehicle_overall) { class VehicleOverallFragment : Fragment() {
override fun onCreateView(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { inflater: LayoutInflater,
super.onViewCreated(view, savedInstanceState) container: ViewGroup?,
savedInstanceState: Bundle?
vehicle_prof.setOnClickListener { it.navigateTo(R.id.to_vehicleSetupFragment) } ): View {
insurance.setOnClickListener { it.navigateTo(R.id.to_insuranceFragment) } return FragmentVehicleOverallBinding.inflate(inflater, container, false).apply {
mot.setOnClickListener { it.navigateTo(R.id.to_motFragment) } vehicleProf.setOnClickListener {
logbook.setOnClickListener { it.navigateTo(R.id.to_logbookFragment) } it.navigateTo(R.id.to_vehicleSetupFragment)
private_hire_vehicle_license.setOnClickListener { it.navigateTo(R.id.to_privateHireVehicleFragment) } }
insurance.setOnClickListener { it.navigateTo(R.id.to_insuranceFragment) }
mot.setOnClickListener { it.navigateTo(R.id.to_motFragment) }
logbook.setOnClickListener { it.navigateTo(R.id.to_logbookFragment) }
privateHireVehicleLicense.setOnClickListener { it.navigateTo(R.id.to_privateHireVehicleFragment) }
}.root
} }
} }

View File

@@ -1,20 +1,26 @@
package h_mal.appttude.com.ui package h_mal.appttude.com.ui
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.databinding.FragmentWelcomeBinding
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import kotlinx.android.synthetic.driver.fragment_welcome.*
class WelcomeFragment : Fragment(R.layout.fragment_welcome) { class WelcomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onCreateView(
super.onViewCreated(view, savedInstanceState) inflater: LayoutInflater,
container: ViewGroup?,
email_sign_in_button.setOnClickListener { savedInstanceState: Bundle?
view.navigateTo(R.id.to_driverOverallFragment) ): View {
} return FragmentWelcomeBinding.inflate(inflater, container, false).apply {
emailSignInButton.setOnClickListener {
it.navigateTo(R.id.to_driverOverallFragment)
}
}.root
} }
} }

View File

@@ -1,59 +1,54 @@
package h_mal.appttude.com.ui.driverprofile package h_mal.appttude.com.ui.driverprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentDriverLicenseBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.DriversLicenseObject import h_mal.appttude.com.model.DriversLicense
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.DriverLicenseViewModel import h_mal.appttude.com.viewmodels.DriverLicenseViewModel
import kotlinx.android.synthetic.main.fragment_driver_license.*
class DriverLicenseFragment : class DriverLicenseFragment :
DataSubmissionBaseFragment<DriverLicenseViewModel, DriversLicenseObject>(R.layout.fragment_driver_license) { DataSubmissionBaseFragment<DriverLicenseViewModel, FragmentDriverLicenseBinding, DriversLicense>() {
private val viewmodel: DriverLicenseViewModel by getFragmentViewModel() override var model = DriversLicense()
override fun getViewModel(): DriverLicenseViewModel = viewmodel
override var model = DriversLicenseObject()
private var imageUri: Uri? = null override fun setupView(binding: FragmentDriverLicenseBinding) {
binding.apply {
licExpiry.apply {
setTextOnChange { model.licenseExpiry = it }
setOnClickListener {
DateDialog(this) { date ->
model.licenseExpiry = date
}
}
}
licNo.setTextOnChange { model.licenseNumber = it }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { searchImage.setOnClickListener { openGalleryWithPermissionRequest() }
super.onViewCreated(view, savedInstanceState) submit.setOnClickListener {
validateEditTexts(licExpiry, licNo).isTrue {
lic_expiry.apply { viewModel.setDataInDatabase(model, picUri)
setTextOnChange { model.licenseExpiry = it }
setOnClickListener {
DateDialog(this) { date ->
model.licenseExpiry = date
} }
} }
} }
lic_no.setTextOnChange { model.licenseNumber = it }
search_image.setOnClickListener { openGalleryWithPermissionRequest() }
submit.setOnClickListener { submit() }
} }
override fun submit() { override fun setFields(data: DriversLicense) {
validateEditTexts(lic_expiry, lic_no).takeIf { !it }?.let { return }
viewmodel.setDataInDatabase(model, imageUri)
}
override fun setFields(data: DriversLicenseObject) {
super.setFields(data) super.setFields(data)
driversli_img.setGlideImage(data.licenseImageString) applyBinding {
lic_no.setText(data.licenseNumber) driversliImg.setGlideImage(data.licenseImageString)
lic_expiry.setText(data.licenseExpiry) licNo.setText(data.licenseNumber)
licExpiry.setText(data.licenseExpiry)
}
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
this.imageUri = imageUri applyBinding {
driversli_img.setGlideImage(imageUri) driversliImg.setGlideImage(imageUri)
}
} }
} }

View File

@@ -1,77 +1,74 @@
package h_mal.appttude.com.ui.driverprofile package h_mal.appttude.com.ui.driverprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentDriverProfileBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.DriverProfileObject import h_mal.appttude.com.model.DriverProfile
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.DriverProfileViewModel import h_mal.appttude.com.viewmodels.DriverProfileViewModel
import kotlinx.android.synthetic.main.fragment_driver_profile.*
class DriverProfileFragment: DataSubmissionBaseFragment class DriverProfileFragment :
<DriverProfileViewModel, DriverProfileObject>(R.layout.fragment_driver_profile) { DataSubmissionBaseFragment<DriverProfileViewModel, FragmentDriverProfileBinding, DriverProfile>() {
var localUri: Uri? = null override var model = DriverProfile()
private val viewmodel by getFragmentViewModel<DriverProfileViewModel>() override fun setupView(binding: FragmentDriverProfileBinding) = binding.run {
override fun getViewModel(): DriverProfileViewModel = viewmodel namesInput.setTextOnChange { model.forenames = it }
override var model = DriverProfileObject() addressInput.setTextOnChange { model.address = it }
postcodeInput.setTextOnChange { model.postcode = it }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { dobInput.apply {
super.onViewCreated(view, savedInstanceState) setTextOnChange { model.dob = it }
setOnClickListener {
names_input.setTextOnChange{ model.forenames = it } DateDialog(this) { date ->
address_input.setTextOnChange{ model.address = it } model.dob = date
postcode_input.setTextOnChange{ model.postcode = it }
dob_input.apply {
setTextOnChange{ model.dob = it }
setOnClickListener {
DateDialog(this){ date ->
model.dob = date
}
} }
} }
ni_number.setTextOnChange{ model.ni = it } }
date_first.apply { niNumber.setTextOnChange { model.ni = it }
setTextOnChange{ model.dateFirst = it } dateFirst.apply {
setTextOnChange { model.dateFirst = it }
setOnClickListener { setOnClickListener {
DateDialog(this){ date -> DateDialog(this) { date ->
model.dateFirst = date model.dateFirst = date
} }
} }
} }
add_photo.setOnClickListener { openGalleryWithPermissionRequest() } addPhoto.setOnClickListener { openGalleryWithPermissionRequest() }
submit_driver.setOnClickListener{ submit() } submitDriver.setOnClickListener { submit() }
} }
override fun submit(){ override fun submit() {
validateEditTexts(names_input, address_input, postcode_input, applyBinding {
dob_input, ni_number, date_first) validateEditTexts(
.takeIf { !it } namesInput, addressInput, postcodeInput,
?.let { return } dobInput, niNumber, dateFirst
).isTrue {
viewmodel.setDataInDatabase(model, localUri) viewModel.setDataInDatabase(model, picUri)
}
}
} }
override fun setFields(data: DriverProfileObject) { override fun setFields(data: DriverProfile) {
super.setFields(data) super.setFields(data)
driver_pic.setGlideImage(data.driverPic) applyBinding {
names_input.setText(data.forenames) driverPic.setGlideImage(data.driverPic)
address_input.setText(data.address) namesInput.setText(data.forenames)
postcode_input.setText(data.postcode) addressInput.setText(data.address)
dob_input.setText(data.dob) postcodeInput.setText(data.postcode)
ni_number.setText(data.ni) dobInput.setText(data.dob)
date_first.setText(data.dateFirst) niNumber.setText(data.ni)
dateFirst.setText(data.dateFirst)
}
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
localUri = imageUri applyBinding {
driver_pic.setGlideImage(imageUri) driverPic.setGlideImage(imageUri)
}
} }
} }

View File

@@ -1,57 +1,57 @@
package h_mal.appttude.com.ui.driverprofile package h_mal.appttude.com.ui.driverprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentPrivateHireLicenseBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.PrivateHireObject import h_mal.appttude.com.model.PrivateHireLicense
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.PrivateHireLicenseViewModel import h_mal.appttude.com.viewmodels.PrivateHireLicenseViewModel
import kotlinx.android.synthetic.main.fragment_private_hire_license.*
class PrivateHireLicenseFragment : DataSubmissionBaseFragment class PrivateHireLicenseFragment : DataSubmissionBaseFragment
<PrivateHireLicenseViewModel, PrivateHireObject>(R.layout.fragment_private_hire_license) { <PrivateHireLicenseViewModel, FragmentPrivateHireLicenseBinding, PrivateHireLicense>() {
val viewmodel by getFragmentViewModel<PrivateHireLicenseViewModel>() override var model = PrivateHireLicense()
override fun getViewModel(): PrivateHireLicenseViewModel = viewmodel
override var model = PrivateHireObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun setupView(binding: FragmentPrivateHireLicenseBinding) = binding.run {
super.onViewCreated(view, savedInstanceState) phNo.setTextOnChange { model.phNumber = it }
phExpiry.apply {
ph_no.setTextOnChange{ model.phNumber = it } setTextOnChange { model.phExpiry = it }
ph_expiry.apply {
setTextOnChange{ model.phExpiry = it }
setOnClickListener { setOnClickListener {
DateDialog(this){ date -> DateDialog(this) { date ->
model.phExpiry = date model.phExpiry = date
} }
} }
} }
uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() } uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() }
submit.setOnClickListener{ submit() } submit.setOnClickListener { submit() }
} }
override fun submit(){ override fun submit() {
validateEditTexts(ph_no,ph_expiry).takeIf { !it }?.let { return } applyBinding {
validateEditTexts(phNo, phExpiry).isTrue {
viewmodel.setDataInDatabase(model, picUri) viewModel.setDataInDatabase(model, picUri)
}
}
} }
override fun setFields(data: PrivateHireObject) { override fun setFields(data: PrivateHireLicense) {
super.setFields(data) super.setFields(data)
imageView2.setGlideImage(data.phImageString) applyBinding {
ph_no.setText(data.phNumber) imageView2.setGlideImage(data.phImageString)
ph_expiry.setText(data.phExpiry) phNo.setText(data.phNumber)
phExpiry.setText(data.phExpiry)
}
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
imageView2.setGlideImage(imageUri) applyBinding {
imageView2.setGlideImage(imageUri)
}
} }
} }

View File

@@ -4,66 +4,71 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentInsuranceBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.InsuranceObject import h_mal.appttude.com.model.Insurance
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.InsuranceViewModel import h_mal.appttude.com.viewmodels.InsuranceViewModel
import kotlinx.android.synthetic.main.fragment_insurance.*
class InsuranceFragment : DataSubmissionBaseFragment<InsuranceViewModel, InsuranceObject>(R.layout.fragment_insurance) { class InsuranceFragment :
DataSubmissionBaseFragment<InsuranceViewModel, FragmentInsuranceBinding, Insurance>() {
private var selectedImages: List<Uri>? = listOf() private var selectedImages: List<Uri>? = listOf()
private val viewmodel: InsuranceViewModel by getFragmentViewModel() override var model = Insurance()
override fun getViewModel(): InsuranceViewModel = viewmodel
override var model = InsuranceObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setImageSelectionAsMultiple() setImageSelectionAsMultiple()
insurer.setTextOnChange { model.insurerName = it } applyBinding {
insurance_exp.apply { insurer.setTextOnChange { model.insurerName = it }
setOnClickListener { insuranceExp.apply {
DateDialog(this) { date -> setOnClickListener {
model.expiryDate = date DateDialog(this) { date ->
model.expiryDate = date
}
} }
} }
uploadInsurance.setOnClickListener { openGalleryWithPermissionRequest() }
submitIns.setOnClickListener { submit() }
} }
uploadInsurance.setOnClickListener { openGalleryWithPermissionRequest() }
submit_ins.setOnClickListener { submit() }
} }
private fun updateImageCarousal(list: List<Any?>) { private fun updateImageCarousal(list: List<Any?>) {
carouselView.setImageClickListener(null) applyBinding {
carouselView.setImageListener { i: Int, imageView: ImageView -> carouselView.setImageClickListener(null)
when (list[i]) { carouselView.setImageListener { i: Int, imageView: ImageView ->
is Uri -> { when (list[i]) {
imageView.setGlideImage(list[i] as Uri) is Uri -> {
imageView.setGlideImage(list[i] as Uri)
}
is String -> imageView.setGlideImage(list[i] as String)
} }
is String -> imageView.setGlideImage(list[i] as String)
} }
carouselView.pageCount = list.size
} }
carouselView.pageCount = list.size
} }
override fun submit() { override fun submit() {
super.submit() super.submit()
validateEditTexts(insurer, insurance_exp).takeIf { !it }?.let { return } applyBinding {
viewmodel.setDataInDatabase(model, selectedImages) validateEditTexts(insurer, insuranceExp).isTrue {
viewModel.setDataInDatabase(model, selectedImages)
}
}
} }
override fun setFields(data: InsuranceObject) { override fun setFields(data: Insurance) {
super.setFields(data) super.setFields(data)
applyBinding {
insurer.setText(model.insurerName) insurer.setText(model.insurerName)
insurance_exp.setText(model.expiryDate) insuranceExp.setText(model.expiryDate)
model.photoStrings?.let { updateImageCarousal(it) } model.photoStrings?.let { updateImageCarousal(it) }
}
} }
override fun onImageGalleryResult(imageUris: List<Uri>?) { override fun onImageGalleryResult(imageUris: List<Uri>?) {

View File

@@ -1,50 +1,47 @@
package h_mal.appttude.com.ui.vehicleprofile package h_mal.appttude.com.ui.vehicleprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.databinding.FragmentLogbookBinding
import h_mal.appttude.com.model.Logbook
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.LogbookViewModel import h_mal.appttude.com.viewmodels.LogbookViewModel
import kotlinx.android.synthetic.main.fragment_logbook.*
class LogbookFragment : DataSubmissionBaseFragment<LogbookViewModel, LogbookObject>(R.layout.fragment_logbook) { class LogbookFragment :
DataSubmissionBaseFragment<LogbookViewModel, FragmentLogbookBinding, Logbook>() {
private val viewmodel by getFragmentViewModel<LogbookViewModel>() override var model = Logbook()
override fun getViewModel(): LogbookViewModel = viewmodel
override var model = LogbookObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun setupView(binding: FragmentLogbookBinding) = binding.run {
super.onViewCreated(view, savedInstanceState) v5cNo.setTextOnChange { model.v5cnumber = it }
uploadLb.setOnClickListener { openGalleryWithPermissionRequest() }
v5c_no.setTextOnChange{ model.v5cnumber = it } submitLb.setOnClickListener { submit() }
upload_lb.setOnClickListener { openGalleryWithPermissionRequest() }
submit_lb.setOnClickListener { submit() }
} }
override fun submit() { override fun submit() {
super.submit() super.submit()
validateEditTexts(v5c_no) applyBinding {
.takeIf { !it } validateEditTexts(v5cNo).isTrue {
?.let { return } viewModel.setDataInDatabase(model, picUri)
}
viewmodel.setDataInDatabase(model, picUri) }
} }
override fun setFields(data: LogbookObject) { override fun setFields(data: Logbook) {
super.setFields(data) super.setFields(data)
applyBinding {
logBookImg.setGlideImage(data.photoString)
v5cNo.setText(data.v5cnumber)
}
log_book_img.setGlideImage(data.photoString)
v5c_no.setText(data.v5cnumber)
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
applyBinding {
picUri = imageUri logBookImg.setGlideImage(picUri)
log_book_img.setGlideImage(picUri) }
} }
} }

View File

@@ -1,52 +1,48 @@
package h_mal.appttude.com.ui.vehicleprofile package h_mal.appttude.com.ui.vehicleprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentMotBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.MotObject import h_mal.appttude.com.model.Mot
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.MotViewModel import h_mal.appttude.com.viewmodels.MotViewModel
import kotlinx.android.synthetic.main.fragment_mot.*
class MotFragment: DataSubmissionBaseFragment<MotViewModel, MotObject>(R.layout.fragment_mot){ class MotFragment : DataSubmissionBaseFragment<MotViewModel, FragmentMotBinding, Mot>() {
private val viewmodel by getFragmentViewModel<MotViewModel>() override var model = Mot()
override fun getViewModel(): MotViewModel = viewmodel
override var model = MotObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun setupView(binding: FragmentMotBinding) = binding.run {
super.onViewCreated(view, savedInstanceState) motExpiry.apply {
mot_expiry.apply {
setOnClickListener { setOnClickListener {
DateDialog(this){ date -> DateDialog(this) { date ->
model.motExpiry = date model.motExpiry = date
} }
} }
} }
uploadmot.setOnClickListener { openGalleryWithPermissionRequest() } uploadmot.setOnClickListener { openGalleryWithPermissionRequest() }
submit_mot.setOnClickListener { submit() } submitMot.setOnClickListener {
validateEditTexts(motExpiry).isTrue {
viewModel.setDataInDatabase(model, picUri)
}
}
} }
override fun submit() { override fun setFields(data: Mot) {
super.submit()
validateEditTexts(mot_expiry).takeIf { !it }?.let { return }
viewmodel.setDataInDatabase(model, picUri)
}
override fun setFields(data: MotObject) {
super.setFields(data) super.setFields(data)
mot_img.setGlideImage(data.motImageString) applyBinding {
mot_expiry.setText(data.motExpiry) motImg.setGlideImage(data.motImageString)
motExpiry.setText(data.motExpiry)
}
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
mot_img.setGlideImage(imageUri) applyBinding {
motImg.setGlideImage(imageUri)
}
} }
} }

View File

@@ -1,55 +1,52 @@
package h_mal.appttude.com.ui.vehicleprofile package h_mal.appttude.com.ui.vehicleprofile
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentPrivateHireLicenseBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.model.PrivateHireVehicle
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.PrivateHireVehicleViewModel import h_mal.appttude.com.viewmodels.PrivateHireVehicleViewModel
import kotlinx.android.synthetic.main.fragment_private_hire_vehicle.*
class PrivateHireVehicleFragment: DataSubmissionBaseFragment class PrivateHireVehicleFragment :
<PrivateHireVehicleViewModel, PrivateHireVehicleObject>(R.layout.fragment_private_hire_vehicle){ DataSubmissionBaseFragment<PrivateHireVehicleViewModel, FragmentPrivateHireLicenseBinding, PrivateHireVehicle>() {
private val viewmodel by getFragmentViewModel<PrivateHireVehicleViewModel>() override var model = PrivateHireVehicle()
override fun getViewModel(): PrivateHireVehicleViewModel = viewmodel
override var model = PrivateHireVehicleObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun setupView(binding: FragmentPrivateHireLicenseBinding) = binding.run {
super.onViewCreated(view, savedInstanceState) phNo.setTextOnChange { model.phCarNumber = it }
phExpiry.apply {
ph_no.setTextOnChange{ model.phCarNumber = it }
ph_expiry.apply {
setOnClickListener { setOnClickListener {
DateDialog(this){ date -> DateDialog(this) { date ->
model.phCarExpiry = date model.phCarExpiry = date
} }
} }
} }
uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() } uploadphlic.setOnClickListener { openGalleryWithPermissionRequest() }
submit.setOnClickListener { submit() } submit.setOnClickListener {
validateEditTexts(phNo, phExpiry).isTrue {
viewModel.setDataInDatabase(model, picUri)
}
}
} }
override fun submit() { override fun setFields(data: PrivateHireVehicle) {
super.submit()
validateEditTexts(ph_no, ph_expiry).takeIf { !it }?.let { return }
viewmodel.setDataInDatabase(model, picUri)
}
override fun setFields(data: PrivateHireVehicleObject) {
super.setFields(data) super.setFields(data)
imageView2.setGlideImage(data.phCarImageString) applyBinding {
ph_no.setText(data.phCarNumber) imageView2.setGlideImage(data.phCarImageString)
ph_expiry.setText(data.phCarExpiry) phNo.setText(data.phCarNumber)
phExpiry.setText(data.phCarExpiry)
}
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
imageView2.setGlideImage(imageUri) applyBinding {
imageView2.setGlideImage(imageUri)
}
} }
} }

View File

@@ -1,62 +1,63 @@
package h_mal.appttude.com.ui.vehicleprofile package h_mal.appttude.com.ui.vehicleprofile
import android.os.Bundle
import android.view.View
import h_mal.appttude.com.R
import h_mal.appttude.com.base.DataSubmissionBaseFragment import h_mal.appttude.com.base.DataSubmissionBaseFragment
import h_mal.appttude.com.databinding.FragmentVehicleSetupBinding
import h_mal.appttude.com.dialogs.DateDialog import h_mal.appttude.com.dialogs.DateDialog
import h_mal.appttude.com.model.VehicleProfileObject import h_mal.appttude.com.model.VehicleProfile
import h_mal.appttude.com.utils.isTrue
import h_mal.appttude.com.viewmodels.VehicleProfileViewModel import h_mal.appttude.com.viewmodels.VehicleProfileViewModel
import kotlinx.android.synthetic.main.fragment_vehicle_setup.*
class VehicleProfileFragment: DataSubmissionBaseFragment class VehicleProfileFragment : DataSubmissionBaseFragment
<VehicleProfileViewModel, VehicleProfileObject>(R.layout.fragment_vehicle_setup){ <VehicleProfileViewModel, FragmentVehicleSetupBinding, VehicleProfile>() {
private val viewmodel by getFragmentViewModel<VehicleProfileViewModel>() override var model = VehicleProfile()
override fun getViewModel(): VehicleProfileViewModel = viewmodel
override var model = VehicleProfileObject()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun setupView(binding: FragmentVehicleSetupBinding) = binding.run {
reg.setTextOnChange { model.reg = it } reg.setTextOnChange { model.reg = it }
make.setTextOnChange { model.make = it } make.setTextOnChange { model.make = it }
car_model.setTextOnChange { model.model = it } carModel.setTextOnChange { model.model = it }
colour.setTextOnChange { model.colour = it } colour.setTextOnChange { model.colour = it }
keeper_name.setTextOnChange { model.keeperName = it } keeperName.setTextOnChange { model.keeperName = it }
address.setTextOnChange { model.keeperAddress = it } address.setTextOnChange { model.keeperAddress = it }
postcode.setTextOnChange { model.keeperPostCode = it } postcode.setTextOnChange { model.keeperPostCode = it }
start_date.apply { startDate.apply {
setOnClickListener { setOnClickListener {
DateDialog(this){ date -> DateDialog(this) { date ->
model.startDate = date model.startDate = date
} }
} }
} }
seized_checkbox.setOnCheckedChangeListener { _, res -> model.isSeized = res} seizedCheckbox.setOnCheckedChangeListener { _, res -> model.isSeized = res }
submit_vehicle.setOnClickListener { submit() } submitVehicle.setOnClickListener {
validateEditTexts(
reg,
make,
carModel,
colour,
keeperName,
address,
postcode,
startDate
).isTrue {
viewModel.setDataInDatabase(model)
}
}
} }
override fun submit() { override fun setFields(data: VehicleProfile) {
validateEditTexts(reg, make, car_model, colour, keeper_name, address, postcode, start_date)
.takeIf { !it }
?.let { return }
viewmodel.setDataInDatabase(model)
}
override fun setFields(data: VehicleProfileObject) {
super.setFields(data) super.setFields(data)
reg.setText(data.reg) applyBinding {
make.setText(data.make) reg.setText(data.reg)
car_model.setText(data.model) make.setText(data.make)
colour.setText(data.colour) carModel.setText(data.model)
keeper_name.setText(data.keeperName) colour.setText(data.colour)
address.setText(data.keeperAddress) keeperName.setText(data.keeperName)
postcode.setText(data.keeperPostCode) address.setText(data.keeperAddress)
start_date.setText(data.startDate) postcode.setText(data.keeperPostCode)
seized_checkbox.isChecked = data.isSeized startDate.setText(data.startDate)
seizedCheckbox.isChecked = data.isSeized
}
} }
} }

View File

@@ -54,7 +54,7 @@
android:textColor="@android:color/white" android:textColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginTop="32dp"/> android:layout_marginTop="32dp" />
<TextView <TextView
android:id="@+id/textView4" android:id="@+id/textView4"
@@ -66,7 +66,7 @@
android:textSize="24sp" android:textSize="24sp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
android:textColor="@android:color/white" android:textColor="@android:color/white"
app:layout_constraintTop_toBottomOf="@id/textView3"/> app:layout_constraintTop_toBottomOf="@id/textView3" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -10,31 +10,10 @@ import com.google.firebase.database.DatabaseReference
import h_mal.appttude.com.R import h_mal.appttude.com.R
class ArchiveFragment : Fragment() { class ArchiveFragment : Fragment() {
// var archive: ArchiveObject? = null // var archive: ArchiveObject? = null
private var reference: DatabaseReference? = null private var reference: DatabaseReference? = null
private var listView: ListView? = null private var listView: ListView? = null
var archiveString: String? = null var archiveString: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// reference =
// MainActivity.mDatabase!!.child(FirebaseClass.USER_FIREBASE).child(
// requireArguments().getString("user_id")
// )
// .child(FirebaseClass.ARCHIVE_FIREBASE)
// archiveString = requireArguments().getString("archive")
// var s: String = ""
// when (archiveString) {
// FirebaseClass.PRIVATE_HIRE_FIREBASE -> s = "Private Hire"
// FirebaseClass.DRIVERS_LICENSE_FIREBASE -> s = "License"
// FirebaseClass.VEHICLE_DETAILS_FIREBASE -> s = "Vehicle"
// FirebaseClass.MOT_FIREBASE -> s = "M.O.T"
// FirebaseClass.INSURANCE_FIREBASE -> s = "Insurance"
// FirebaseClass.LOG_BOOK_FIREBASE -> s = "Logbook"
// FirebaseClass.PRIVATE_HIRE_VEHICLE_LICENSE -> s = "Private Hire Vehicle"
// }
// requireActivity().title = s + " Archive"
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,

View File

@@ -174,7 +174,8 @@ class ArchiveObjectListAdapter(
private fun dateString(position: Int) { private fun dateString(position: Int) {
var success: Boolean = true var success: Boolean = true
try { try {
dateArchivedText!!.text = mKeys[position].convertDateStringDatePattern("yyyyMMdd_HHmmss", "dd/MM/yyyy") dateArchivedText!!.text =
mKeys[position].convertDateStringDatePattern("yyyyMMdd_HHmmss", "dd/MM/yyyy")
} catch (e: ParseException) { } catch (e: ParseException) {
e.printStackTrace() e.printStackTrace()
success = false success = false
@@ -206,9 +207,9 @@ class ArchiveObjectListAdapter(
// //
// } // }
private fun setUp(map: HashMap<String,*>?){ private fun setUp(map: HashMap<String, *>?) {
size = map?.size ?: 0 size = map?.size ?: 0
map?.keys?.toTypedArray()?.let{ map?.keys?.toTypedArray()?.let {
mKeys = it mKeys = it
} }
} }

View File

@@ -15,20 +15,55 @@ class ApplicationViewModelFactory(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
with(modelClass){ with(modelClass) {
return when{ return when {
isAssignableFrom(UserViewModel::class.java) -> UserViewModel(auth) isAssignableFrom(UserViewModel::class.java) -> UserViewModel(auth)
isAssignableFrom(MainViewModel::class.java) -> MainViewModel(auth, database) isAssignableFrom(MainViewModel::class.java) -> MainViewModel(auth, database)
isAssignableFrom(UpdateUserViewModel::class.java) -> UpdateUserViewModel(auth, storage) isAssignableFrom(UpdateUserViewModel::class.java) -> UpdateUserViewModel(
isAssignableFrom(DriverLicenseViewModel::class.java) -> DriverLicenseViewModel(auth, database, storage) auth,
isAssignableFrom(DriverProfileViewModel::class.java) -> DriverProfileViewModel(auth, database, storage) storage
isAssignableFrom(PrivateHireLicenseViewModel::class.java) -> PrivateHireLicenseViewModel(auth, database, storage) )
isAssignableFrom(VehicleProfileViewModel::class.java) -> VehicleProfileViewModel(auth, database, storage) isAssignableFrom(DriverLicenseViewModel::class.java) -> DriverLicenseViewModel(
isAssignableFrom(InsuranceViewModel::class.java) -> InsuranceViewModel(auth, database, storage) auth,
database,
storage
)
isAssignableFrom(DriverProfileViewModel::class.java) -> DriverProfileViewModel(
auth,
database,
storage
)
isAssignableFrom(PrivateHireLicenseViewModel::class.java) -> PrivateHireLicenseViewModel(
auth,
database,
storage
)
isAssignableFrom(VehicleProfileViewModel::class.java) -> VehicleProfileViewModel(
auth,
database,
storage
)
isAssignableFrom(InsuranceViewModel::class.java) -> InsuranceViewModel(
auth,
database,
storage
)
isAssignableFrom(MotViewModel::class.java) -> MotViewModel(auth, database, storage) isAssignableFrom(MotViewModel::class.java) -> MotViewModel(auth, database, storage)
isAssignableFrom(LogbookViewModel::class.java) -> LogbookViewModel(auth, database, storage) isAssignableFrom(LogbookViewModel::class.java) -> LogbookViewModel(
isAssignableFrom(PrivateHireVehicleViewModel::class.java) -> PrivateHireVehicleViewModel(auth, database, storage) auth,
isAssignableFrom(RoleViewModel::class.java) -> RoleViewModel(auth, database, storage) database,
storage
)
isAssignableFrom(PrivateHireVehicleViewModel::class.java) -> PrivateHireVehicleViewModel(
auth,
database,
storage
)
isAssignableFrom(RoleViewModel::class.java) -> RoleViewModel(
auth,
database,
storage
)
else -> throw IllegalArgumentException("Unknown ViewModel class") else -> throw IllegalArgumentException("Unknown ViewModel class")
} as T } as T
} }

View File

@@ -12,7 +12,7 @@ import org.kodein.di.generic.instance
import org.kodein.di.generic.provider import org.kodein.di.generic.provider
import org.kodein.di.generic.singleton import org.kodein.di.generic.singleton
class DriverApplication : Application(), KodeinAware{ class DriverApplication : Application(), KodeinAware {
// Kodein aware to initialise the classes used for DI // Kodein aware to initialise the classes used for DI
override val kodein = Kodein.lazy { override val kodein = Kodein.lazy {

View File

@@ -2,15 +2,16 @@ package h_mal.appttude.com.base
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup.LayoutParams import android.view.ViewGroup.LayoutParams
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import androidx.activity.viewModels import android.view.ViewGroup.inflate
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelLazy
import androidx.lifecycle.ViewModelProvider
import androidx.test.espresso.IdlingResource import androidx.test.espresso.IdlingResource
import androidx.viewbinding.ViewBinding
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.application.ApplicationViewModelFactory import h_mal.appttude.com.application.ApplicationViewModelFactory
import h_mal.appttude.com.data.ViewState import h_mal.appttude.com.data.ViewState
@@ -18,30 +19,65 @@ import h_mal.appttude.com.utils.*
import org.kodein.di.KodeinAware import org.kodein.di.KodeinAware
import org.kodein.di.android.kodein import org.kodein.di.android.kodein
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import java.lang.reflect.ParameterizedType
import kotlin.reflect.KClass
abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAware { abstract class BaseActivity<V : BaseViewModel, VB : ViewBinding> : AppCompatActivity(), KodeinAware {
// The Idling Resource which will be null in production. // The Idling Resource which will be null in production.
private var mIdlingResource: BasicIdlingResource? = null private var mIdlingResource: BasicIdlingResource? = null
private lateinit var loadingView: View private lateinit var loadingView: View
abstract fun getViewModel(): V? private var _binding: VB? = null
abstract val layoutId: Int private val binding: VB
get() = _binding ?: error("Must only access binding while fragment is attached.")
val viewModel: V by createLazyViewModel()
override val kodein by kodein() override val kodein by kodein()
val factory by instance<ApplicationViewModelFactory>() val factory by instance<ApplicationViewModelFactory>()
inline fun <reified VM : ViewModel> createLazyViewModel(): Lazy<VM> = viewModels { factory } fun createLazyViewModel(): Lazy<V> = ViewModelLazy(
inline fun <reified VM : ViewModel> createViewModel(): VM = getGenericClassAt(0),
ViewModelProvider(viewModelStore, factory).get(VM::class.java) { viewModelStore },
{ factory },
{ defaultViewModelCreationExtras }
)
@Suppress("UNCHECKED_CAST")
fun <CLASS : Any> Any.getGenericClassAt(position: Int): KClass<CLASS> =
((javaClass.genericSuperclass as? ParameterizedType)
?.actualTypeArguments?.getOrNull(position) as? Class<CLASS>)
?.kotlin
?: throw IllegalStateException("Can not find class from generic argument")
fun inflateBindingByType(
genericClassAt: KClass<VB>
): VB = try {
@Suppress("UNCHECKED_CAST")
genericClassAt.java.methods.first { viewBinding ->
viewBinding.parameterTypes.size == 1
&& viewBinding.parameterTypes.getOrNull(0) == LayoutInflater::class.java
}.invoke(null, layoutInflater) as VB
} catch (exception: Exception) {
throw IllegalStateException("Can not inflate binding from generic")
}
private var loading: Boolean = false private var loading: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
configureObserver() configureObserver()
setContentView(layoutId) _binding = inflateBindingByType(getGenericClassAt(1))
setContentView(requireNotNull(_binding).root)
setupView(binding)
}
open fun setupView(binding: VB) {}
fun applyBinding(block: VB.() -> Unit) {
block(binding)
} }
/** /**
@@ -50,9 +86,8 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
* #setOnClickListener(null) is an ugly work around to prevent under being clicked during * #setOnClickListener(null) is an ugly work around to prevent under being clicked during
* loading * loading
*/ */
private fun instantiateLoadingView(){ private fun instantiateLoadingView() {
// loadingView = View.inflate(this, R.layout.progress_layout, null) loadingView = inflate(this, R.layout.progress_layout, null)
loadingView = layoutInflater.inflate(R.layout.progress_layout, null)
loadingView.setOnClickListener(null) loadingView.setOnClickListener(null)
addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT)) addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT))
loadingView.hide() loadingView.hide()
@@ -97,7 +132,7 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
} }
private fun configureObserver() { private fun configureObserver() {
getViewModel()?.uiState?.observe(this) { viewModel.uiState.observe(this) {
when (it) { when (it) {
is ViewState.HasStarted -> onStarted() is ViewState.HasStarted -> onStarted()
is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled()) is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled())

View File

@@ -5,24 +5,33 @@ import android.content.ClipData
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.annotation.LayoutRes import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.createViewModelLazy
import androidx.lifecycle.ViewModel import androidx.viewbinding.ViewBinding
import h_mal.appttude.com.application.ApplicationViewModelFactory import h_mal.appttude.com.application.ApplicationViewModelFactory
import h_mal.appttude.com.data.ViewState import h_mal.appttude.com.data.ViewState
import h_mal.appttude.com.utils.PermissionsUtils import h_mal.appttude.com.utils.PermissionsUtils
import org.kodein.di.KodeinAware import org.kodein.di.KodeinAware
import org.kodein.di.android.x.kodein import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance import org.kodein.di.generic.instance
import java.lang.reflect.ParameterizedType
import kotlin.reflect.KClass
const val IMAGE_SELECT_REQUEST_CODE = 401 const val IMAGE_SELECT_REQUEST_CODE = 401
abstract class BaseFragment<V : BaseViewModel>(@LayoutRes contentLayoutId: Int) : abstract class BaseFragment<V : BaseViewModel, VB : ViewBinding>(
Fragment(contentLayoutId), KodeinAware { ) : Fragment(), KodeinAware {
var mActivity: BaseActivity<V>? = null private var _binding: VB? = null
abstract fun getViewModel(): V private val binding: VB
get() = _binding ?: error("Must only access binding while fragment is attached.")
var mActivity: BaseActivity<V, *>? = null
val viewModel: V by getFragmentViewModel()
private var multipleImage: Boolean = false private var multipleImage: Boolean = false
@@ -33,13 +42,57 @@ abstract class BaseFragment<V : BaseViewModel>(@LayoutRes contentLayoutId: Int)
override val kodein by kodein() override val kodein by kodein()
val factory by instance<ApplicationViewModelFactory>() val factory by instance<ApplicationViewModelFactory>()
inline fun <reified VM : ViewModel> getFragmentViewModel(): Lazy<VM> = viewModels { factory } fun getFragmentViewModel(): Lazy<V> =
createViewModelLazy(getGenericClassAt(0), { viewModelStore }, factoryProducer = { factory })
fun LayoutInflater.inflateBindingByType(
container: ViewGroup?,
genericClassAt: KClass<VB>
): VB = try {
@Suppress("UNCHECKED_CAST")
genericClassAt.java.methods.first { inflateFun ->
inflateFun.parameterTypes.size == 3
&& inflateFun.parameterTypes.getOrNull(0) == LayoutInflater::class.java
&& inflateFun.parameterTypes.getOrNull(1) == ViewGroup::class.java
&& inflateFun.parameterTypes.getOrNull(2) == Boolean::class.java
}.invoke(null, this, container, false) as VB
} catch (exception: Exception) {
throw IllegalStateException("Can not inflate binding from generic")
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun onActivityCreated(savedInstanceState: Bundle?) { fun <CLASS : Any> Any.getGenericClassAt(position: Int): KClass<CLASS> =
super.onActivityCreated(savedInstanceState) ((javaClass.genericSuperclass as? ParameterizedType)
mActivity = activity as BaseActivity<V> ?.actualTypeArguments?.getOrNull(position) as? Class<CLASS>)
?.kotlin
?: throw IllegalStateException("Can not find class from generic argument")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = inflater.inflateBindingByType(container, getGenericClassAt(1))
return requireNotNull(_binding).root
}
@Suppress("UNCHECKED_CAST")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mActivity = activity as BaseActivity<V, *>
configureObserver() configureObserver()
setupView(binding)
}
open fun setupView(binding: VB) {}
fun applyBinding(block: VB.() -> Unit) {
block(binding)
}
override fun onDestroy() {
super.onDestroy()
_binding = null
} }
/** /**
@@ -64,7 +117,7 @@ abstract class BaseFragment<V : BaseViewModel>(@LayoutRes contentLayoutId: Int)
} }
private fun configureObserver() { private fun configureObserver() {
getViewModel().uiState.observe(viewLifecycleOwner) { viewModel.uiState.observe(viewLifecycleOwner) {
when (it) { when (it) {
is ViewState.HasStarted -> onStarted() is ViewState.HasStarted -> onStarted()
is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled()) is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled())

View File

@@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel
import h_mal.appttude.com.data.ViewState import h_mal.appttude.com.data.ViewState
import h_mal.appttude.com.utils.Event import h_mal.appttude.com.utils.Event
abstract class BaseViewModel: ViewModel(){ abstract class BaseViewModel : ViewModel() {
open val uiState: MutableLiveData<ViewState> = MutableLiveData() open val uiState: MutableLiveData<ViewState> = MutableLiveData()
fun onStart() { fun onStart() {
@@ -23,11 +23,11 @@ abstract class BaseViewModel: ViewModel(){
suspend fun doTryOperation( suspend fun doTryOperation(
defaultErrorMessage: String?, defaultErrorMessage: String?,
operation: suspend () -> Unit operation: suspend () -> Unit
){ ) {
try { try {
onStart() onStart()
operation() operation()
}catch (e: Exception){ } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
e.message?.let { e.message?.let {
onError(it) onError(it)

View File

@@ -6,25 +6,25 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import androidx.annotation.LayoutRes
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.viewbinding.ViewBinding
import h_mal.appttude.com.data.UserAuthState import h_mal.appttude.com.data.UserAuthState
import h_mal.appttude.com.ui.user.LoginActivity import h_mal.appttude.com.ui.user.LoginActivity
import h_mal.appttude.com.utils.PermissionsUtils.askForPermissions import h_mal.appttude.com.utils.PermissionsUtils.askForPermissions
import h_mal.appttude.com.utils.TextValidationUtils.validateEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEditText
private const val IMAGE_PERMISSION_RESULT = 402 private const val IMAGE_PERMISSION_RESULT = 402
abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, T: Any>
(@LayoutRes contentLayoutId: Int) : BaseFragment<BaseViewModel>(contentLayoutId){ abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, VB : ViewBinding, T : Any> :
BaseFragment<V, VB>() {
var picUri: Uri? = null var picUri: Uri? = null
abstract override fun getViewModel(): V
abstract var model: T abstract var model: T
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
getViewModel().stateLiveData.observe(viewLifecycleOwner) { viewModel.stateLiveData.observe(viewLifecycleOwner) {
if (it is UserAuthState.LoggedOut) { if (it is UserAuthState.LoggedOut) {
val intent = Intent(requireContext(), LoginActivity::class.java) val intent = Intent(requireContext(), LoginActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -32,7 +32,7 @@ abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, T:
requireActivity().finish() requireActivity().finish()
} }
} }
getViewModel().getDataFromDatabase() viewModel.getDataFromDatabase()
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -41,17 +41,17 @@ abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, T:
data?.let { data?.let {
if (it::class.java == model::class.java) if (it::class.java == model::class.java)
setFields(data as T) setFields(data as T)
} }
} }
open fun setFields(data: T){ open fun setFields(data: T) {
model = data model = data
} }
open fun submit(){} open fun submit() {}
fun openGalleryWithPermissionRequest(){ fun openGalleryWithPermissionRequest() {
if (askForPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, IMAGE_PERMISSION_RESULT)) { if (askForPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, IMAGE_PERMISSION_RESULT)) {
openGalleryForImage() openGalleryForImage()
} }
@@ -65,9 +65,9 @@ abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, T:
openGalleryForImage() openGalleryForImage()
} }
fun validateEditTexts(vararg editTexts: EditText): Boolean{ fun validateEditTexts(vararg editTexts: EditText): Boolean {
editTexts.forEach { editTexts.forEach {
if (it.text.isNullOrBlank()){ if (it.text.isNullOrBlank()) {
it.validateEditText() it.validateEditText()
return false return false
} }
@@ -75,13 +75,13 @@ abstract class DataSubmissionBaseFragment<V : DataSubmissionBaseViewModel<T>, T:
return true return true
} }
fun EditText.setTextOnChange(output: (m: String) -> Unit){ fun EditText.setTextOnChange(output: (m: String) -> Unit) {
doAfterTextChanged { doAfterTextChanged {
output(text.toString()) output(text.toString())
} }
} }
override fun onImageGalleryResult(imageUri: Uri?){ override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
picUri = imageUri picUri = imageUri
} }

View File

@@ -30,7 +30,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
abstract fun getDataFromDatabase(): Job abstract fun getDataFromDatabase(): Job
open fun setDataInDatabase(data: T, localImageUri: Uri?): Job = Job() open fun setDataInDatabase(data: T, localImageUri: Uri?): Job = Job()
open fun setDataInDatabase(data: T, localImageUris: List<Uri?>?): Job = Job() open fun setDataInDatabase(data: T, localImageUris: List<Uri?>?): Job = Job()
open fun setDataInDatabase(data: T) { } open fun setDataInDatabase(data: T) {}
inline fun <reified T : Any> getDataClass() = io { inline fun <reified T : Any> getDataClass() = io {
doTryOperation("Failed to retrieve $objectName") { doTryOperation("Failed to retrieve $objectName") {
@@ -60,7 +60,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
} }
suspend fun getImageUrl(localImageUri: Uri?, imageUrl: String?): String { suspend fun getImageUrl(localImageUri: Uri?, imageUrl: String?): String {
if (localImageUri == null && imageUrl.isNullOrBlank()){ if (localImageUri == null && imageUrl.isNullOrBlank()) {
throw IOException("No image is selected") throw IOException("No image is selected")
} }
@@ -68,7 +68,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
} }
suspend fun getImageUrls(localImageUris: List<Uri?>?): List<String?> { suspend fun getImageUrls(localImageUris: List<Uri?>?): List<String?> {
if (localImageUris.isNullOrEmpty()){ if (localImageUris.isNullOrEmpty()) {
throw IOException("No images is selected") throw IOException("No images is selected")
} }
val listOfUrls = mutableListOf<String>() val listOfUrls = mutableListOf<String>()
@@ -81,10 +81,19 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
return listOfUrls return listOfUrls
} }
suspend fun <T, R> Iterable<T>.mapSuspend(transform: suspend (T) -> R): List<R> = suspend fun <T, R> Iterable<T>.mapSuspend(transform: suspend (T) -> R): List<R> =
coroutineScope { map { t: T -> async { transform(t) } }.map { it.await() } } coroutineScope { map { t: T -> async { transform(t) } }.map { it.await() } }
suspend fun <T, R> Iterable<T>.mapIndexSuspend(transform: suspend (index: Int, T) -> R) = suspend fun <T, R> Iterable<T>.mapIndexSuspend(transform: suspend (index: Int, T) -> R) =
coroutineScope { mapIndexed { index: Int, t: T -> async { transform(index, t) } }.map { it.await() } } coroutineScope {
mapIndexed { index: Int, t: T ->
async {
transform(
index,
t
)
}
}.map { it.await() }
}
} }

View File

@@ -1,7 +0,0 @@
package h_mal.appttude.com.data
sealed class DataFieldState {
object DefaultState : DataFieldState()
object NonUserStateUpdated: DataFieldState()
object UserUpdateState: DataFieldState()
}

View File

@@ -4,6 +4,6 @@ import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError import com.google.firebase.database.DatabaseError
sealed class EventResponse { sealed class EventResponse {
data class Changed(val snapshot: DataSnapshot): EventResponse() data class Changed(val snapshot: DataSnapshot) : EventResponse()
data class Cancelled(val error: DatabaseError): EventResponse() data class Cancelled(val error: DatabaseError) : EventResponse()
} }

View File

@@ -5,8 +5,8 @@ import com.google.android.gms.tasks.Task
import com.google.firebase.auth.* import com.google.firebase.auth.*
import java.io.IOException import java.io.IOException
class FirebaseAuthSource: FirebaseAuthentication{ class FirebaseAuthSource : FirebaseAuthentication {
private val auth = FirebaseAuth.getInstance() private val auth = FirebaseAuth.getInstance()
override fun getUid(): String? = auth.uid override fun getUid(): String? = auth.uid
@@ -19,7 +19,7 @@ class FirebaseAuthSource: FirebaseAuthentication{
auth.createUserWithEmailAndPassword(email, password) auth.createUserWithEmailAndPassword(email, password)
override fun logOut() = auth.signOut() override fun logOut() = auth.signOut()
override fun forgotPassword(email: String): Task<Void> = auth.sendPasswordResetEmail(email) override fun forgotPassword(email: String): Task<Void> = auth.sendPasswordResetEmail(email)
override fun updateProfile( override fun updateProfile(
@@ -42,15 +42,17 @@ class FirebaseAuthSource: FirebaseAuthentication{
} }
override fun updateEmail(email: String): Task<Void> = getCurrentUser().updateEmail(email) override fun updateEmail(email: String): Task<Void> = getCurrentUser().updateEmail(email)
override fun updatePassword(password: String): Task<Void> = getCurrentUser().updatePassword(password) override fun updatePassword(password: String): Task<Void> =
getCurrentUser().updatePassword(password)
override fun deleteProfile(): Task<Void> = getCurrentUser().delete() override fun deleteProfile(): Task<Void> = getCurrentUser().delete()
override fun userStateListener() : FirebaseLiveData { override fun userStateListener(): FirebaseAuthStateLiveData {
return FirebaseLiveData(auth) return FirebaseAuthStateLiveData(auth)
} }
private fun getCurrentUser(): FirebaseUser{ private fun getCurrentUser(): FirebaseUser {
return getUser() ?: throw IOException("User not signed in") return getUser() ?: throw IOException("User not signed in")
} }
} }

View File

@@ -3,9 +3,12 @@ package h_mal.appttude.com.data
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseAuth
class FirebaseLiveData( /**
* Creates #LiveDate out of {UserAuthState} for firebase user state
*/
class FirebaseAuthStateLiveData(
private val firebaseAuth: FirebaseAuth private val firebaseAuth: FirebaseAuth
): LiveData<UserAuthState>(){ ) : LiveData<UserAuthState>() {
override fun onActive() { override fun onActive() {
super.onActive() super.onActive()
@@ -24,4 +27,4 @@ class FirebaseLiveData(
postValue(UserAuthState.LoggedIn(p0.currentUser!!)) postValue(UserAuthState.LoggedIn(p0.currentUser!!))
} }
} }
} }

View File

@@ -5,7 +5,7 @@ import com.google.android.gms.tasks.Task
import com.google.firebase.auth.AuthResult import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseUser import com.google.firebase.auth.FirebaseUser
interface FirebaseAuthentication{ interface FirebaseAuthentication {
fun getUid(): String? fun getUid(): String?
fun getUser(): FirebaseUser? fun getUser(): FirebaseUser?
fun signIn(email: String, password: String): Task<AuthResult> fun signIn(email: String, password: String): Task<AuthResult>
@@ -16,12 +16,14 @@ interface FirebaseAuthentication{
name: String?, name: String?,
profilePic: Uri? profilePic: Uri?
): Task<Void> ): Task<Void>
fun reauthenticate( fun reauthenticate(
email: String, email: String,
password: String password: String
): Task<Void> ): Task<Void>
fun updateEmail(email: String): Task<Void> fun updateEmail(email: String): Task<Void>
fun updatePassword(password: String): Task<Void> fun updatePassword(password: String): Task<Void>
fun deleteProfile(): Task<Void> fun deleteProfile(): Task<Void>
fun userStateListener() : FirebaseLiveData fun userStateListener(): FirebaseAuthStateLiveData
} }

View File

@@ -1,7 +1,7 @@
package h_mal.appttude.com.data package h_mal.appttude.com.data
sealed class FirebaseCompletion{ sealed class FirebaseCompletion {
object Default: FirebaseCompletion() object Default : FirebaseCompletion()
data class Changed(val message: String): FirebaseCompletion() data class Changed(val message: String) : FirebaseCompletion()
data class ProfileDeleted(val message: String): FirebaseCompletion() data class ProfileDeleted(val message: String) : FirebaseCompletion()
} }

View File

@@ -5,7 +5,7 @@ import com.google.firebase.database.FirebaseDatabase
import kotlinx.coroutines.tasks.await import kotlinx.coroutines.tasks.await
const val USER_CONST = "user" const val USER_CONST = "user"
const val PROFILE_ROLE ="role" const val PROFILE_ROLE = "role"
const val DRIVER_NUMBER = "driver_number" const val DRIVER_NUMBER = "driver_number"
const val USER_DETAILS = "user_details" const val USER_DETAILS = "user_details"
const val VEHICLE_PROFILE = "vehicle_profile" const val VEHICLE_PROFILE = "vehicle_profile"
@@ -20,10 +20,17 @@ const val MOT = "mot_details"
const val PRIVATE_HIRE_VEHICLE = "private_hire_vehicle" const val PRIVATE_HIRE_VEHICLE = "private_hire_vehicle"
const val VEHICLE_DETAILS = "vehicle_details" const val VEHICLE_DETAILS = "vehicle_details"
const val ARCHIVE = "archive" const val ARCHIVE = "archive"
class FirebaseDatabaseSource { class FirebaseDatabaseSource {
private val database = FirebaseDatabase.getInstance() private val database = FirebaseDatabase.getInstance()
suspend fun <T: Any> postToDatabaseRed(ref: DatabaseReference, data: T) : T{ /**
* Post object to the databse on reference
*
* @param ref - Database reference
* @return T returns data posted
*/
suspend fun <T : Any> postToDatabaseRed(ref: DatabaseReference, data: T): T {
ref.setValue(data).await() ref.setValue(data).await()
return data return data
} }
@@ -52,6 +59,8 @@ class FirebaseDatabaseSource {
fun getArchiveLogbookRef(uid: String) = getArchiveRef(uid).child(LOG_BOOK) fun getArchiveLogbookRef(uid: String) = getArchiveRef(uid).child(LOG_BOOK)
fun getArchiveMotDetailsRef(uid: String) = getArchiveRef(uid).child(MOT) fun getArchiveMotDetailsRef(uid: String) = getArchiveRef(uid).child(MOT)
fun getArchivePrivateHireLicenseRef(uid: String) = getArchiveRef(uid).child(PRIVATE_HIRE) fun getArchivePrivateHireLicenseRef(uid: String) = getArchiveRef(uid).child(PRIVATE_HIRE)
fun getArchivePrivateHireVehicleRef(uid: String) = getArchiveRef(uid).child(PRIVATE_HIRE_VEHICLE) fun getArchivePrivateHireVehicleRef(uid: String) =
getArchiveRef(uid).child(PRIVATE_HIRE_VEHICLE)
fun getArchiveVehicleDetailsRef(uid: String) = getArchiveRef(uid).child(VEHICLE_DETAILS) fun getArchiveVehicleDetailsRef(uid: String) = getArchiveRef(uid).child(VEHICLE_DETAILS)
} }

View File

@@ -13,6 +13,7 @@ const val LOG_BOOK_SREF = "log_book"
const val MOT_SREF = "mot_Details" const val MOT_SREF = "mot_Details"
const val PRIVATE_HIRE_SREF = "private_hire" const val PRIVATE_HIRE_SREF = "private_hire"
const val PRIVATE_HIRE_VEHICLE_SREF = "private_hire_vehicle" const val PRIVATE_HIRE_VEHICLE_SREF = "private_hire_vehicle"
class FirebaseStorageSource { class FirebaseStorageSource {
private val storage = FirebaseStorage.getInstance() private val storage = FirebaseStorage.getInstance()
private val storageRef: StorageReference by lazy { storage.reference } private val storageRef: StorageReference by lazy { storage.reference }
@@ -26,10 +27,13 @@ class FirebaseStorageSource {
private fun usersImagesStorageRef(uid: String) = storageRef.child(IMAGE_CONST).child(uid) private fun usersImagesStorageRef(uid: String) = storageRef.child(IMAGE_CONST).child(uid)
fun profileImageStorageRef(uid: String) = usersImagesStorageRef(uid).child(PROFILE_SREF) fun profileImageStorageRef(uid: String) = usersImagesStorageRef(uid).child(PROFILE_SREF)
fun driversLicenseStorageRef(uid: String) = usersImagesStorageRef(uid).child(DRIVERS_LICENSE_SREF) fun driversLicenseStorageRef(uid: String) =
usersImagesStorageRef(uid).child(DRIVERS_LICENSE_SREF)
fun insuranceStorageRef(uid: String) = usersImagesStorageRef(uid).child(INSURANCE_SREF) fun insuranceStorageRef(uid: String) = usersImagesStorageRef(uid).child(INSURANCE_SREF)
fun logBookStorageRef(uid: String) = usersImagesStorageRef(uid).child(LOG_BOOK_SREF) fun logBookStorageRef(uid: String) = usersImagesStorageRef(uid).child(LOG_BOOK_SREF)
fun motStorageRef(uid: String) = usersImagesStorageRef(uid).child(MOT_SREF) fun motStorageRef(uid: String) = usersImagesStorageRef(uid).child(MOT_SREF)
fun privateHireStorageRef(uid: String) = usersImagesStorageRef(uid).child(PRIVATE_HIRE_SREF) fun privateHireStorageRef(uid: String) = usersImagesStorageRef(uid).child(PRIVATE_HIRE_SREF)
fun privateHireVehicleStorageRef(uid: String) = usersImagesStorageRef(uid).child(PRIVATE_HIRE_VEHICLE_SREF) fun privateHireVehicleStorageRef(uid: String) =
usersImagesStorageRef(uid).child(PRIVATE_HIRE_VEHICLE_SREF)
} }

View File

@@ -1,7 +1,6 @@
package h_mal.appttude.com.dialogs package h_mal.appttude.com.dialogs
import android.app.AlertDialog
import android.app.DatePickerDialog import android.app.DatePickerDialog
import android.app.DatePickerDialog.OnDateSetListener import android.app.DatePickerDialog.OnDateSetListener
import android.icu.util.Calendar import android.icu.util.Calendar
@@ -11,11 +10,12 @@ import h_mal.appttude.com.utils.DateUtils
private const val DATE_FORMAT = "dd/MM/yyyy" private const val DATE_FORMAT = "dd/MM/yyyy"
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class DateDialog( class DateDialog(
private val editText: EditText, private val editText: EditText,
dateSelected:(String?) -> Unit dateSelected: (String?) -> Unit
) : DatePickerDialog(editText.context, AlertDialog.THEME_HOLO_LIGHT) { ) : DatePickerDialog(editText.context) {
private val dateSetListener: OnDateSetListener = private val dateSetListener: OnDateSetListener =
OnDateSetListener { _, year, month, dayOfMonth -> OnDateSetListener { _, year, month, dayOfMonth ->
@@ -29,11 +29,15 @@ class DateDialog(
} }
init { init {
datePicker.apply {
spinnersShown = true
calendarViewShown = false
}
val dateString = editText.text?.toString() val dateString = editText.text?.toString()
val date = if (dateString.isNullOrBlank()){ val date = if (dateString.isNullOrBlank()) {
// Set time to now // Set time to now
Calendar.getInstance() Calendar.getInstance()
}else{ } else {
// Parse current edit text string and set value // Parse current edit text string and set value
DateUtils.parseDateStringIntoCalender(dateString, DATE_FORMAT) DateUtils.parseDateStringIntoCalender(dateString, DATE_FORMAT)
?: Calendar.getInstance() ?: Calendar.getInstance()
@@ -44,7 +48,7 @@ class DateDialog(
show() show()
} }
private fun setDateFromCalender(calendar: Calendar){ private fun setDateFromCalender(calendar: Calendar) {
val mYear = calendar.get(Calendar.YEAR) val mYear = calendar.get(Calendar.YEAR)
val mMonth = calendar.get(Calendar.MONTH) val mMonth = calendar.get(Calendar.MONTH)
val mDay = calendar.get(Calendar.DAY_OF_MONTH) val mDay = calendar.get(Calendar.DAY_OF_MONTH)
@@ -52,5 +56,4 @@ class DateDialog(
updateDate(mYear, mMonth, mDay) updateDate(mYear, mMonth, mDay)
} }
} }

View File

@@ -2,23 +2,22 @@ package h_mal.appttude.com.dialogs
import android.app.Activity import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import androidx.fragment.app.Fragment import h_mal.appttude.com.R
import kotlin.system.exitProcess import kotlin.system.exitProcess
object ExitDialog{ object ExitDialog {
fun Activity.displayExitDialog() = AlertDialog.Builder(this) fun Activity.displayExitDialog() = AlertDialog.Builder(this)
.setTitle("Leave?") .setTitle(getString(R.string.leave_header))
.setMessage("Are you sure you want to exit?") .setMessage(getString(R.string.leave_message))
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton( .setPositiveButton(
android.R.string.ok android.R.string.ok
) { _, _ -> ) { _, _ ->
finish() finish()
exitProcess(0) exitProcess(0)
} }
.create() .create()
.show() .show()
fun Fragment.displayExitDialog() = requireActivity().displayExitDialog()
} }

View File

@@ -1,8 +1,6 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class DriverProfile(
data class DriverProfileObject(
var driverPic: String? = null, var driverPic: String? = null,
var forenames: String? = null, var forenames: String? = null,
var address: String? = null, var address: String? = null,

View File

@@ -1,7 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class DriversLicenseObject( data class DriversLicense(
var licenseImageString: String? = null, var licenseImageString: String? = null,
var licenseNumber: String? = null, var licenseNumber: String? = null,
var licenseExpiry: String? = null var licenseExpiry: String? = null

View File

@@ -1,8 +1,6 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class Insurance(
data class InsuranceObject (
var photoStrings: MutableList<String?>? = null, var photoStrings: MutableList<String?>? = null,
var insurerName: String? = null, var insurerName: String? = null,
var expiryDate: String? = null var expiryDate: String? = null

View File

@@ -1,8 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class Logbook(
data class LogbookObject(
var photoString: String? = null, var photoString: String? = null,
var v5cnumber: String? = null var v5cnumber: String? = null
) )

View File

@@ -1,8 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class Mot(
data class MotObject(
var motImageString: String? = null, var motImageString: String? = null,
var motExpiry: String? = null var motExpiry: String? = null
) )

View File

@@ -1,8 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class PrivateHireLicense(
data class PrivateHireObject (
var phImageString: String? = null, var phImageString: String? = null,
var phNumber: String? = null, var phNumber: String? = null,
var phExpiry: String? = null var phExpiry: String? = null

View File

@@ -1,8 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
class PrivateHireVehicle(
class PrivateHireVehicleObject(
var phCarImageString: String? = null, var phCarImageString: String? = null,
var phCarNumber: String? = null, var phCarNumber: String? = null,
var phCarExpiry: String? = null var phCarExpiry: String? = null

View File

@@ -1,8 +1,7 @@
package h_mal.appttude.com.model package h_mal.appttude.com.model
data class VehicleProfile(
data class VehicleProfileObject(
var reg: String? = null, var reg: String? = null,
var make: String? = null, var make: String? = null,
var model: String? = null, var model: String? = null,

View File

@@ -1,33 +1,25 @@
package h_mal.appttude.com.ui.update package h_mal.appttude.com.ui.update
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentDeleteProfileBinding
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_delete_profile.*
class DeleteProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragment_delete_profile) { class DeleteProfileFragment :
BaseFragment<UpdateUserViewModel, FragmentDeleteProfileBinding>() {
private val viewmodel: UpdateUserViewModel by activityViewModels() override fun setupView(binding: FragmentDeleteProfileBinding) = binding.run {
override fun getViewModel(): UpdateUserViewModel = viewmodel passwordTop.setEnterPressedListener { deleteUser() }
submissionButtonLabel.setOnClickListener { deleteUser() }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
password_top.setEnterPressedListener { deleteUser() }
submission_button_label.setOnClickListener { deleteUser() }
} }
private fun deleteUser(){ private fun deleteUser() = applyBinding {
val emailString = email_update.validatePasswordEditText() ?: return val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
val passwordText = password_top.validatePasswordEditText() ?: return val passwordText = passwordTop.validatePasswordEditText() ?: return@applyBinding
getViewModel().deleteProfile(emailString, passwordText) viewModel.deleteProfile(emailString, passwordText)
} }
} }

View File

@@ -1,25 +1,16 @@
package h_mal.appttude.com.ui.update package h_mal.appttude.com.ui.update
import android.os.Bundle
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseActivity import h_mal.appttude.com.base.BaseActivity
import h_mal.appttude.com.data.FirebaseCompletion import h_mal.appttude.com.data.FirebaseCompletion
import h_mal.appttude.com.databinding.UpdateActivityBinding
import h_mal.appttude.com.utils.displayToast import h_mal.appttude.com.utils.displayToast
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
class UpdateActivity : BaseActivity<UpdateUserViewModel>() { class UpdateActivity : BaseActivity<UpdateUserViewModel, UpdateActivityBinding>() {
override val layoutId: Int = R.layout.update_activity
override fun getViewModel(): UpdateUserViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
createViewModel<UpdateUserViewModel>()
}
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {
super.onSuccess(data) super.onSuccess(data)
when(data){ when (data) {
is FirebaseCompletion.Changed -> displayToast(data.message) is FirebaseCompletion.Changed -> displayToast(data.message)
} }
} }

View File

@@ -1,36 +1,28 @@
package h_mal.appttude.com.ui.update package h_mal.appttude.com.ui.update
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentUpdateEmailBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_update_email.*
class UpdateEmailFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragment_update_email) { class UpdateEmailFragment : BaseFragment<UpdateUserViewModel, FragmentUpdateEmailBinding>() {
private val viewmodel: UpdateUserViewModel by activityViewModels() override fun setupView(binding: FragmentUpdateEmailBinding) = binding.run {
override fun getViewModel(): UpdateUserViewModel = viewmodel newEmail.setEnterPressedListener { registerUser() }
submissionButtonLabel.setOnClickListener { registerUser() }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
new_email.setEnterPressedListener { registerUser() }
submission_button_label.setOnClickListener { registerUser() }
} }
private fun registerUser(){ private fun registerUser() {
val emailString = email_update.validatePasswordEditText() ?: return applyBinding {
val passwordText = password_top.validatePasswordEditText() ?: return val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
val newEmail = new_email.validateEmailEditText() ?: return val passwordText = passwordTop.validatePasswordEditText() ?: return@applyBinding
val newEmail = newEmail.validateEmailEditText() ?: return@applyBinding
getViewModel().updateEmail(emailString, passwordText, newEmail) viewModel.updateEmail(emailString, passwordText, newEmail)
}
} }
} }

View File

@@ -1,30 +1,25 @@
package h_mal.appttude.com.ui.update package h_mal.appttude.com.ui.update
import android.os.Bundle
import android.view.View import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.UpdateOverviewFragmentBinding
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.update_overview_fragment.*
class UpdateOverviewFragment : BaseFragment<UpdateUserViewModel>(R.layout.update_overview_fragment), View.OnClickListener { class UpdateOverviewFragment : BaseFragment<UpdateUserViewModel, UpdateOverviewFragmentBinding>(),
View.OnClickListener {
private val vm by activityViewModels<UpdateUserViewModel>() override fun setupView(binding: UpdateOverviewFragmentBinding) = binding.run {
override fun getViewModel(): UpdateUserViewModel = vm updateEmailButton.setOnClickListener(this@UpdateOverviewFragment)
updatePasswordButton.setOnClickListener(this@UpdateOverviewFragment)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { updateProfileButton.setOnClickListener(this@UpdateOverviewFragment)
super.onViewCreated(view, savedInstanceState) deleteProfile.setOnClickListener(this@UpdateOverviewFragment)
update_email_button.setOnClickListener(this)
update_password_button.setOnClickListener(this)
update_profile_button.setOnClickListener(this)
delete_profile.setOnClickListener(this)
} }
private fun View.submit(){
when(id){ private fun View.submit() {
when (id) {
R.id.update_email_button -> navigateTo(R.id.to_updateEmailFragment) R.id.update_email_button -> navigateTo(R.id.to_updateEmailFragment)
R.id.update_password_button -> navigateTo(R.id.to_updatePasswordFragment) R.id.update_password_button -> navigateTo(R.id.to_updatePasswordFragment)
R.id.update_profile_button -> navigateTo(R.id.to_updateProfileFragment) R.id.update_profile_button -> navigateTo(R.id.to_updateProfileFragment)
@@ -32,9 +27,8 @@ class UpdateOverviewFragment : BaseFragment<UpdateUserViewModel>(R.layout.update
} }
} }
override fun onClick(v: View?){ override fun onClick(v: View?) {
v?.submit() v?.submit()
} }
} }

View File

@@ -1,36 +1,30 @@
package h_mal.appttude.com.ui.update package h_mal.appttude.com.ui.update
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentUpdatePasswordBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_update_password.*
class UpdatePasswordFragment : class UpdatePasswordFragment : BaseFragment<UpdateUserViewModel, FragmentUpdatePasswordBinding>() {
BaseFragment<UpdateUserViewModel>(R.layout.fragment_update_password) {
private val viewmodel: UpdateUserViewModel by activityViewModels() override fun setupView(binding: FragmentUpdatePasswordBinding) {
override fun getViewModel(): UpdateUserViewModel = viewmodel applyBinding {
emailUpdate.setEnterPressedListener { registerUser() }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { emailSignUp.setOnClickListener { registerUser() }
super.onViewCreated(view, savedInstanceState) }
email_update.setEnterPressedListener { registerUser() }
email_sign_up.setOnClickListener { registerUser() }
} }
private fun registerUser() { private fun registerUser() {
val emailString = email_update.validatePasswordEditText() ?: return applyBinding {
val passwordText = password_top.validatePasswordEditText() ?: return val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
val newPassword = password_bottom.validateEmailEditText() ?: return val passwordText = passwordTop.validatePasswordEditText() ?: return@applyBinding
val newPassword = passwordBottom.validateEmailEditText() ?: return@applyBinding
getViewModel().updatePassword(emailString, passwordText, newPassword) viewModel.updatePassword(emailString, passwordText, newPassword)
}
} }
} }

View File

@@ -2,39 +2,29 @@ package h_mal.appttude.com.ui.update
import android.Manifest.permission.READ_EXTERNAL_STORAGE import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.activityViewModels
import com.google.firebase.auth.FirebaseUser import com.google.firebase.auth.FirebaseUser
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentUpdateProfileBinding
import h_mal.appttude.com.utils.PermissionsUtils.askForPermissions import h_mal.appttude.com.utils.PermissionsUtils.askForPermissions
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.utils.setGlideImage import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.UpdateUserViewModel import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_update_profile.*
const val TAG_CONST = "non-user" const val TAG_CONST = "non-user"
private const val IMAGE_PERMISSION_RESULT = 402 private const val IMAGE_PERMISSION_RESULT = 402
class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragment_update_profile) { class UpdateProfileFragment : BaseFragment<UpdateUserViewModel, FragmentUpdateProfileBinding>() {
private val viewmodel: UpdateUserViewModel by activityViewModels()
override fun getViewModel(): UpdateUserViewModel = viewmodel
private var imageChangeListener: Boolean = false private var imageChangeListener: Boolean = false
private var nameChangeListener: Boolean = false private var nameChangeListener: Boolean = false
private var imageUri: Uri? = null private var imageUri: Uri? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun setupView(binding: FragmentUpdateProfileBinding) = binding.run {
super.onViewCreated(view, savedInstanceState) viewModel.getUser()
viewmodel.getUser() updateName.apply {
update_name.apply {
doAfterTextChanged { doAfterTextChanged {
if (tag == TAG_CONST) { if (tag == TAG_CONST) {
tag = null tag = null
@@ -45,20 +35,22 @@ class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragmen
setEnterPressedListener { submitProfileUpdate() } setEnterPressedListener { submitProfileUpdate() }
} }
profile_img.setOnClickListener { profileImg.setOnClickListener {
if (askForPermissions(READ_EXTERNAL_STORAGE, IMAGE_PERMISSION_RESULT)) { if (askForPermissions(READ_EXTERNAL_STORAGE, IMAGE_PERMISSION_RESULT)) {
openGalleryForImage() openGalleryForImage()
} }
} }
submit_update_profile.setOnClickListener { submitProfileUpdate() } submitUpdateProfile.setOnClickListener { submitProfileUpdate() }
} }
private fun submitProfileUpdate() { private fun submitProfileUpdate() {
val name: String? = takeIf { nameChangeListener }?.update_name?.text?.toString() applyBinding {
val imgUri = takeIf { imageChangeListener }?.let { imageUri } val name: String? = takeIf { nameChangeListener }?.updateName?.text?.toString()
val imgUri = takeIf { imageChangeListener }?.let { imageUri }
viewmodel.updateProfile(name, imgUri) viewModel.updateProfile(name, imgUri)
}
} }
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(
@@ -76,18 +68,24 @@ class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragmen
} }
private fun setFields(firebaseUser: FirebaseUser) { private fun setFields(firebaseUser: FirebaseUser) {
profile_img.setGlideImage(firebaseUser.photoUrl) applyBinding {
update_name.apply { profileImg.setGlideImage(firebaseUser.photoUrl)
setText(firebaseUser.displayName) updateName.apply {
tag = TAG_CONST setText(firebaseUser.displayName)
tag = TAG_CONST
}
} }
} }
override fun onImageGalleryResult(imageUri: Uri?) { override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri) super.onImageGalleryResult(imageUri)
this.imageUri = imageUri this.imageUri = imageUri
profile_img.setGlideImage(imageUri) applyBinding {
imageChangeListener = true profileImg.setGlideImage(imageUri)
imageChangeListener = true
}
} }
} }

View File

@@ -1,26 +1,17 @@
package h_mal.appttude.com.ui.user package h_mal.appttude.com.ui.user
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentForgotPasswordBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.viewmodels.UserViewModel import h_mal.appttude.com.viewmodels.UserViewModel
import kotlinx.android.synthetic.main.fragment_forgot_password.*
class ForgotPasswordFragment : BaseFragment<UserViewModel>(R.layout.fragment_forgot_password) { class ForgotPasswordFragment : BaseFragment<UserViewModel, FragmentForgotPasswordBinding>() {
private val userViewModel: UserViewModel by activityViewModels() override fun setupView(binding: FragmentForgotPasswordBinding) = binding.run {
override fun getViewModel(): UserViewModel = userViewModel submissionButton.setOnClickListener {
val emailString = submissionEt.validateEmailEditText() ?: return@setOnClickListener
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { viewModel.forgotPassword(emailString)
super.onViewCreated(view, savedInstanceState)
submission_button.setOnClickListener {
val emailString = submission_et.validateEmailEditText() ?: return@setOnClickListener
userViewModel.forgotPassword(emailString)
} }
} }

View File

@@ -2,11 +2,10 @@ package h_mal.appttude.com.ui.user
import android.content.Intent import android.content.Intent
import android.os.Bundle
import com.google.firebase.auth.AuthResult import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseUser import com.google.firebase.auth.FirebaseUser
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseActivity import h_mal.appttude.com.base.BaseActivity
import h_mal.appttude.com.databinding.ActivityLoginBinding
import h_mal.appttude.com.ui.MainActivity import h_mal.appttude.com.ui.MainActivity
import h_mal.appttude.com.viewmodels.UserViewModel import h_mal.appttude.com.viewmodels.UserViewModel
@@ -14,15 +13,7 @@ import h_mal.appttude.com.viewmodels.UserViewModel
/** /**
* A login screen that offers login via email/password. * A login screen that offers login via email/password.
*/ */
class LoginActivity : BaseActivity<UserViewModel>() { class LoginActivity : BaseActivity<UserViewModel, ActivityLoginBinding>() {
override fun getViewModel(): UserViewModel? = null
override val layoutId: Int = R.layout.activity_login
override fun onCreate(savedInstanceState: Bundle?) {
createViewModel<UserViewModel>()
super.onCreate(savedInstanceState)
}
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {
super.onSuccess(data) super.onSuccess(data)

View File

@@ -1,39 +1,32 @@
package h_mal.appttude.com.ui.user package h_mal.appttude.com.ui.user
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentLoginBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UserViewModel import h_mal.appttude.com.viewmodels.UserViewModel
import kotlinx.android.synthetic.main.fragment_login.*
class LoginFragment : BaseFragment<UserViewModel>(R.layout.fragment_login) { class LoginFragment : BaseFragment<UserViewModel, FragmentLoginBinding>() {
private val userViewModel: UserViewModel by activityViewModels()
override fun getViewModel(): UserViewModel = userViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun setupView(binding: FragmentLoginBinding) = binding.run {
password.setEnterPressedListener { attemptLogin() } password.setEnterPressedListener { attemptLogin() }
emailSignInButton.setOnClickListener { attemptLogin() }
email_sign_in_button.setOnClickListener { attemptLogin() } registerButton.setOnClickListener { it.navigateTo(R.id.to_register) }
register_button.setOnClickListener { it.navigateTo(R.id.to_register) }
forgot.setOnClickListener { it.navigateTo(R.id.to_forgotPassword) } forgot.setOnClickListener { it.navigateTo(R.id.to_forgotPassword) }
} }
private fun attemptLogin(){ private fun attemptLogin() {
// Store values at the time of the login attempt. applyBinding {
val emailString = email.validateEmailEditText() ?: return // Store values at the time of the login attempt.
val passwordString = password.validatePasswordEditText() ?: return val emailString = email.validateEmailEditText() ?: return@applyBinding
val passwordString = password.validatePasswordEditText() ?: return@applyBinding
// attempt to login user // attempt to login user
getViewModel().signInUser(emailString, passwordString) viewModel.signInUser(emailString, passwordString)
}
} }
} }

View File

@@ -1,42 +1,37 @@
package h_mal.appttude.com.ui.user package h_mal.appttude.com.ui.user
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.databinding.FragmentRegisterBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UserViewModel import h_mal.appttude.com.viewmodels.UserViewModel
import kotlinx.android.synthetic.main.fragment_register.*
class RegisterFragment : BaseFragment<UserViewModel>(R.layout.fragment_register) { class RegisterFragment :
BaseFragment<UserViewModel, FragmentRegisterBinding>() {
override fun getViewModel(): UserViewModel { override fun setupView(binding: FragmentRegisterBinding) = binding.run {
val userViewModel: UserViewModel by activityViewModels() passwordBottom.setEnterPressedListener { registerUser() }
return userViewModel emailSignUp.setOnClickListener { registerUser() }
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { private fun registerUser() {
super.onViewCreated(view, savedInstanceState) applyBinding {
val nameString = nameRegister.validatePasswordEditText() ?: return@applyBinding
val emailText = emailRegister.validateEmailEditText() ?: return@applyBinding
val passwordText = passwordTop.validatePasswordEditText() ?: return@applyBinding
val passwordTextBottom =
passwordBottom.validatePasswordEditText() ?: return@applyBinding
password_bottom.setEnterPressedListener { registerUser() } if ((passwordText != passwordTextBottom)) {
email_sign_up.setOnClickListener { registerUser() } passwordBottom.error = getString(R.string.no_match_password)
} passwordBottom.requestFocus()
return@applyBinding
}
private fun registerUser(){ viewModel.registerUser(nameString, emailText, passwordText)
val nameString = name_register.validatePasswordEditText() ?: return
val emailText = email_register.validateEmailEditText() ?: return
val passwordText = password_top.validatePasswordEditText() ?: return
val passwordTextBottom = password_bottom.validatePasswordEditText() ?: return
if ((passwordText != passwordTextBottom)) {
password_bottom.error = getString(R.string.no_match_password)
password_bottom.requestFocus()
return
} }
getViewModel().registerUser(nameString, emailText, passwordText)
} }
} }

View File

@@ -2,23 +2,20 @@ package h_mal.appttude.com.ui.user
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.fragment.app.activityViewModels
import h_mal.appttude.com.R import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseFragment import h_mal.appttude.com.base.BaseFragment
import h_mal.appttude.com.data.FirebaseCompletion import h_mal.appttude.com.data.FirebaseCompletion
import h_mal.appttude.com.databinding.SplashScreenBinding
import h_mal.appttude.com.utils.navigateTo import h_mal.appttude.com.utils.navigateTo
import h_mal.appttude.com.viewmodels.UserViewModel import h_mal.appttude.com.viewmodels.UserViewModel
class SplashScreenFragment : BaseFragment<UserViewModel>(R.layout.fragment_splash_screen) { class SplashScreenFragment : BaseFragment<UserViewModel, SplashScreenBinding>() {
private val userViewModel by activityViewModels<UserViewModel>()
override fun getViewModel(): UserViewModel = userViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
userViewModel.splashscreenCheckUserIsLoggedIn() viewModel.splashscreenCheckUserIsLoggedIn()
} }
override fun onSuccess(data: Any?) { override fun onSuccess(data: Any?) {

View File

@@ -5,7 +5,7 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import androidx.annotation.AnimRes import androidx.annotation.AnimRes
fun View.triggerAnimation(@AnimRes id:Int, complete:(View) -> Unit){ fun View.triggerAnimation(@AnimRes id: Int, complete: (View) -> Unit) {
val animation = AnimationUtils.loadAnimation(context, id) val animation = AnimationUtils.loadAnimation(context, id)
animation.setAnimationListener(object : Animation.AnimationListener { animation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationEnd(animation: Animation?) = complete(this@triggerAnimation) override fun onAnimationEnd(animation: Animation?) = complete(this@triggerAnimation)

View File

@@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
object Coroutines{ object Coroutines {
fun io(work: suspend () -> Unit) = CoroutineScope(Dispatchers.IO).launch { work() } fun io(work: suspend () -> Unit) = CoroutineScope(Dispatchers.IO).launch { work() }
fun main(work: suspend () -> Unit) = CoroutineScope(Dispatchers.Main).launch { work() } fun main(work: suspend () -> Unit) = CoroutineScope(Dispatchers.Main).launch { work() }

View File

@@ -11,7 +11,7 @@ object DateUtils {
return sdf.format(Date()) return sdf.format(Date())
} }
fun getDateTimeStamp(): String{ fun getDateTimeStamp(): String {
val sdf: SimpleDateFormat = getSimpleDateFormat("yyyyMMdd_HHmmss") val sdf: SimpleDateFormat = getSimpleDateFormat("yyyyMMdd_HHmmss")
return sdf.format(Date()) return sdf.format(Date())
} }
@@ -23,7 +23,7 @@ object DateUtils {
val sdfOut = getSimpleDateFormat(formatOut) val sdfOut = getSimpleDateFormat(formatOut)
val newDate: Date = sdfIn.parse(this) val newDate: Date = sdfIn.parse(this)
sdfOut.format(newDate) sdfOut.format(newDate)
}catch (e: Exception){ } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
this this
} }

View File

@@ -0,0 +1,16 @@
package h_mal.appttude.com.utils
inline fun Boolean.isTrue(block: () -> Unit){
if (this) {
block()
}
}
inline fun <T, R> T.isNotNull(block: (T) -> R): R?{
return if (this != null) {
block(this)
} else {
null
}
}

View File

@@ -8,10 +8,14 @@ import h_mal.appttude.com.data.EventResponse
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
/**
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
*
*
* @return EventResponse
*/
suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCoroutine { continuation -> suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCoroutine { continuation ->
val valueEventListener = object: ValueEventListener { val valueEventListener = object : ValueEventListener {
override fun onCancelled(error: DatabaseError) { override fun onCancelled(error: DatabaseError) {
continuation.resume(EventResponse.Cancelled(error)) continuation.resume(EventResponse.Cancelled(error))
} }
@@ -23,7 +27,13 @@ suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCorouti
addListenerForSingleValueEvent(valueEventListener) addListenerForSingleValueEvent(valueEventListener)
} }
suspend inline fun <reified T: Any> DatabaseReference.getDataFromDatabaseRef(): T?{ /**
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
*
*
* @return T
*/
suspend inline fun <reified T : Any> DatabaseReference.getDataFromDatabaseRef(): T? {
return when (val response: EventResponse = singleValueEvent()) { return when (val response: EventResponse = singleValueEvent()) {
is EventResponse.Changed -> { is EventResponse.Changed -> {
response.snapshot.getValue(T::class.java) response.snapshot.getValue(T::class.java)

View File

@@ -19,7 +19,7 @@ fun navigateToActivity(context: Context, navigationActivity: Navigations) {
} }
} }
fun View.navigateTo(@IdRes navId: Int){ fun View.navigateTo(@IdRes navId: Int) {
Navigation Navigation
.findNavController(this) .findNavController(this)
.navigate(navId) .navigate(navId)

View File

@@ -103,6 +103,7 @@ fun ImageView.setPicassoImage(
context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
} }
} }
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {} override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
}) })

View File

@@ -7,23 +7,23 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.DriversLicenseObject import h_mal.appttude.com.model.DriversLicense
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class DriverLicenseViewModel( class DriverLicenseViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<DriversLicenseObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<DriversLicense>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getDriverLicenseRef(uid) override val databaseRef: DatabaseReference = database.getDriverLicenseRef(uid)
override val storageRef: StorageReference = storage.driversLicenseStorageRef(uid) override val storageRef: StorageReference = storage.driversLicenseStorageRef(uid)
override val objectName: String = "drivers license" override val objectName: String = "drivers license"
override fun getDataFromDatabase() = getDataClass<DriversLicenseObject>() override fun getDataFromDatabase() = getDataClass<DriversLicense>()
override fun setDataInDatabase(data: DriversLicenseObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: DriversLicense, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){ doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.licenseImageString) val imageUrl = getImageUrl(localImageUri, data.licenseImageString)
data.licenseImageString = imageUrl data.licenseImageString = imageUrl
postDataToDatabase(data) postDataToDatabase(data)

View File

@@ -7,23 +7,23 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.DriverProfileObject import h_mal.appttude.com.model.DriverProfile
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class DriverProfileViewModel( class DriverProfileViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<DriverProfileObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<DriverProfile>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getDriverDetailsRef(uid) override val databaseRef: DatabaseReference = database.getDriverDetailsRef(uid)
override val storageRef: StorageReference = storage.profileImageStorageRef(uid) override val storageRef: StorageReference = storage.profileImageStorageRef(uid)
override val objectName: String = "drivers profile" override val objectName: String = "drivers profile"
override fun getDataFromDatabase() = getDataClass<DriverProfileObject>() override fun getDataFromDatabase() = getDataClass<DriverProfile>()
override fun setDataInDatabase(data: DriverProfileObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: DriverProfile, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){ doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.driverPic) val imageUrl = getImageUrl(localImageUri, data.driverPic)
data.driverPic = imageUrl data.driverPic = imageUrl

View File

@@ -7,29 +7,29 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.InsuranceObject import h_mal.appttude.com.model.Insurance
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class InsuranceViewModel ( class InsuranceViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<InsuranceObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<Insurance>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid) override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid)
override val storageRef: StorageReference = storage.insuranceStorageRef(uid) override val storageRef: StorageReference = storage.insuranceStorageRef(uid)
override val objectName: String = "insurance" override val objectName: String = "insurance"
override fun getDataFromDatabase() = getDataClass<InsuranceObject>() override fun getDataFromDatabase() = getDataClass<Insurance>()
override fun setDataInDatabase(data: InsuranceObject, localImageUris: List<Uri?>?) = io { override fun setDataInDatabase(data: Insurance, localImageUris: List<Uri?>?) = io {
doTryOperation("Failed to upload $objectName") { doTryOperation("Failed to upload $objectName") {
val imageUrls = if (!localImageUris.isNullOrEmpty()){ val imageUrls = if (!localImageUris.isNullOrEmpty()) {
getImageUrls(localImageUris).toMutableList() getImageUrls(localImageUris).toMutableList()
}else{ } else {
data.photoStrings data.photoStrings
} }
if (imageUrls.isNullOrEmpty()){ if (imageUrls.isNullOrEmpty()) {
onError("no images selected") onError("no images selected")
return@doTryOperation return@doTryOperation
} }

View File

@@ -7,22 +7,22 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.LogbookObject import h_mal.appttude.com.model.Logbook
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class LogbookViewModel ( class LogbookViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<LogbookObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<Logbook>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getLogbookRef(uid) override val databaseRef: DatabaseReference = database.getLogbookRef(uid)
override val storageRef: StorageReference = storage.logBookStorageRef(uid) override val storageRef: StorageReference = storage.logBookStorageRef(uid)
override val objectName: String = "Log book" override val objectName: String = "Log book"
override fun getDataFromDatabase() = getDataClass<LogbookObject>() override fun getDataFromDatabase() = getDataClass<Logbook>()
override fun setDataInDatabase(data: LogbookObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: Logbook, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName") { doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.photoString) val imageUrl = getImageUrl(localImageUri, data.photoString)
data.photoString = imageUrl data.photoString = imageUrl

View File

@@ -9,25 +9,25 @@ import h_mal.appttude.com.utils.getDataFromDatabaseRef
class MainViewModel( class MainViewModel(
private val firebaseAuth: FirebaseAuthentication, private val firebaseAuth: FirebaseAuthentication,
private val firebaseDatabase: FirebaseDatabaseSource private val firebaseDatabase: FirebaseDatabaseSource
) : BaseViewModel(){ ) : BaseViewModel() {
fun getRole() = io { fun getRole() = io {
doTryOperation("failed to retrieve data") { doTryOperation("failed to retrieve data") {
val uid = firebaseAuth.getUid() ?: return@doTryOperation val uid = firebaseAuth.getUid() ?: return@doTryOperation
val ref = firebaseDatabase.getUserRoleRef(uid) val ref = firebaseDatabase.getUserRoleRef(uid)
val role = ref.getDataFromDatabaseRef<String>() val role = ref.getDataFromDatabaseRef<String>()
role?.apply { onSuccess(this) } ?: onError("No role found") role?.apply { onSuccess(this) } ?: onError("No role found")
}
} }
}
fun getUserDetails(){ fun getUserDetails() {
firebaseAuth.getUser()?.let { firebaseAuth.getUser()?.let {
onSuccess(it) onSuccess(it)
} }
} }
fun logOut(){ fun logOut() {
firebaseAuth.logOut() firebaseAuth.logOut()
} }
} }

View File

@@ -7,23 +7,23 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.MotObject import h_mal.appttude.com.model.Mot
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class MotViewModel ( class MotViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<MotObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<Mot>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getMotDetailsRef(uid) override val databaseRef: DatabaseReference = database.getMotDetailsRef(uid)
override val storageRef: StorageReference? = storage.motStorageRef(uid) override val storageRef: StorageReference? = storage.motStorageRef(uid)
override val objectName: String = "vehicle profile" override val objectName: String = "vehicle profile"
override fun getDataFromDatabase() = getDataClass<MotObject>() override fun getDataFromDatabase() = getDataClass<Mot>()
override fun setDataInDatabase(data: MotObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: Mot, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){ doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.motImageString) val imageUrl = getImageUrl(localImageUri, data.motImageString)
data.motImageString = imageUrl data.motImageString = imageUrl
postDataToDatabase(data) postDataToDatabase(data)

View File

@@ -7,25 +7,25 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.PrivateHireObject import h_mal.appttude.com.model.PrivateHireLicense
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class PrivateHireLicenseViewModel( class PrivateHireLicenseViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<PrivateHireObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<PrivateHireLicense>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getPrivateHireRef(uid) override val databaseRef: DatabaseReference = database.getPrivateHireRef(uid)
override val storageRef: StorageReference = storage.privateHireStorageRef(uid) override val storageRef: StorageReference = storage.privateHireStorageRef(uid)
override val objectName: String = "private hire license" override val objectName: String = "private hire license"
override fun getDataFromDatabase() = getDataClass<PrivateHireObject>() override fun getDataFromDatabase() = getDataClass<PrivateHireLicense>()
override fun setDataInDatabase(data: PrivateHireObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: PrivateHireLicense, localImageUri: Uri?) = io {
doTryOperation("Failed to upload private hire license"){ doTryOperation("Failed to upload private hire license") {
val imageUrl = getImageUrl(localImageUri, data.phImageString) val imageUrl = getImageUrl(localImageUri, data.phImageString)
val driverLicense = PrivateHireObject( val driverLicense = PrivateHireLicense(
phExpiry = data.phExpiry, phExpiry = data.phExpiry,
phNumber = data.phNumber, phNumber = data.phNumber,
phImageString = imageUrl phImageString = imageUrl

View File

@@ -7,22 +7,22 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.PrivateHireVehicleObject import h_mal.appttude.com.model.PrivateHireVehicle
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class PrivateHireVehicleViewModel ( class PrivateHireVehicleViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<PrivateHireVehicleObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<PrivateHireVehicle>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid) override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid)
override val storageRef: StorageReference = storage.privateHireVehicleStorageRef(uid) override val storageRef: StorageReference = storage.privateHireVehicleStorageRef(uid)
override val objectName: String = "private hire vehicle license" override val objectName: String = "private hire vehicle license"
override fun getDataFromDatabase() = getDataClass<PrivateHireVehicleObject>() override fun getDataFromDatabase() = getDataClass<PrivateHireVehicle>()
override fun setDataInDatabase(data: PrivateHireVehicleObject, localImageUri: Uri?) = io { override fun setDataInDatabase(data: PrivateHireVehicle, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName") { doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.phCarImageString) val imageUrl = getImageUrl(localImageUri, data.phCarImageString)
data.phCarImageString = imageUrl data.phCarImageString = imageUrl

View File

@@ -6,24 +6,24 @@ import h_mal.appttude.com.base.DataSubmissionBaseViewModel
import h_mal.appttude.com.data.FirebaseAuthentication import h_mal.appttude.com.data.FirebaseAuthentication
import h_mal.appttude.com.data.FirebaseDatabaseSource import h_mal.appttude.com.data.FirebaseDatabaseSource
import h_mal.appttude.com.data.FirebaseStorageSource import h_mal.appttude.com.data.FirebaseStorageSource
import h_mal.appttude.com.model.VehicleProfileObject import h_mal.appttude.com.model.VehicleProfile
import h_mal.appttude.com.utils.Coroutines.io import h_mal.appttude.com.utils.Coroutines.io
class VehicleProfileViewModel ( class VehicleProfileViewModel(
auth: FirebaseAuthentication, auth: FirebaseAuthentication,
database: FirebaseDatabaseSource, database: FirebaseDatabaseSource,
storage: FirebaseStorageSource storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<VehicleProfileObject>(auth, database, storage) { ) : DataSubmissionBaseViewModel<VehicleProfile>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getVehicleDetailsRef(uid) override val databaseRef: DatabaseReference = database.getVehicleDetailsRef(uid)
override val storageRef: StorageReference? = null override val storageRef: StorageReference? = null
override val objectName: String = "vehicle profile" override val objectName: String = "vehicle profile"
override fun getDataFromDatabase() = getDataClass<VehicleProfileObject>() override fun getDataFromDatabase() = getDataClass<VehicleProfile>()
override fun setDataInDatabase(data: VehicleProfileObject) { override fun setDataInDatabase(data: VehicleProfile) {
io { io {
doTryOperation("Failed to upload $objectName"){ doTryOperation("Failed to upload $objectName") {
postDataToDatabase(data) postDataToDatabase(data)
} }
} }

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent"/>
<stroke android:width="2dip" android:color="#03a9f4" />
<corners android:radius="22dip"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent" />
<stroke
android:width="2dip"
android:color="#03a9f4" />
<corners android:radius="22dip" />
<padding
android:left="0dip"
android:top="0dip"
android:right="0dip"
android:bottom="0dip" />
</shape>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#FFffffff" android:fillColor="#FFffffff"
android:pathData="M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5V19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5zM5.12,5l0.81,-1h12l0.94,1H5.12z"/> android:pathData="M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5V19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5zM5.12,5l0.81,-1h12l0.94,1H5.12z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24" android:tint="#FFFFFF"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportHeight="24"
<path android:fillColor="@android:color/white" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/> android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@android:color/white"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24" android:tint="#FFFFFF"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportHeight="24"
<path android:fillColor="@android:color/white" android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1c-1.3,0 -2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM12,7c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM18,19L6,19v-1.4c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1L18,19z"/> android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1c-1.3,0 -2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM12,7c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM18,19L6,19v-1.4c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1L18,19z" />
</vector> </vector>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24" android:tint="#FFFFFF"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportHeight="24"
<path android:fillColor="@android:color/white" android:pathData="M22,16L22,4c0,-1.1 -0.9,-2 -2,-2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zM11,12l2.03,2.71L16,11l4,5L8,16l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6L2,6z"/> android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@android:color/white"
android:pathData="M22,16L22,4c0,-1.1 -0.9,-2 -2,-2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zM11,12l2.03,2.71L16,11l4,5L8,16l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6L2,6z" />
</vector> </vector>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#ffffff" android:fillColor="#ffffff"
android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/> android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z" />
</vector> </vector>

View File

@@ -1,9 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" xmlns:tools="http://schemas.android.com/tools"
android:height="24dp" android:width="24dp"
android:viewportWidth="24.0" android:height="24dp"
android:viewportHeight="24.0"> android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path <path
android:fillColor="#FF000000" android:fillColor="#FF000000"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/> android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"
tools:ignore="VectorPath" />
</vector> </vector>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path
android:fillColor="#ffffff" android:fillColor="#ffffff"
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/> android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z" />
</vector> </vector>

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