- 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

@@ -10,31 +10,10 @@ import com.google.firebase.database.DatabaseReference
import h_mal.appttude.com.R
class ArchiveFragment : Fragment() {
// var archive: ArchiveObject? = null
// var archive: ArchiveObject? = null
private var reference: DatabaseReference? = null
private var listView: ListView? = 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(
inflater: LayoutInflater, container: ViewGroup?,

View File

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

View File

@@ -15,20 +15,55 @@ class ApplicationViewModelFactory(
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
with(modelClass){
return when{
with(modelClass) {
return when {
isAssignableFrom(UserViewModel::class.java) -> UserViewModel(auth)
isAssignableFrom(MainViewModel::class.java) -> MainViewModel(auth, database)
isAssignableFrom(UpdateUserViewModel::class.java) -> UpdateUserViewModel(auth, storage)
isAssignableFrom(DriverLicenseViewModel::class.java) -> DriverLicenseViewModel(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(UpdateUserViewModel::class.java) -> UpdateUserViewModel(
auth,
storage
)
isAssignableFrom(DriverLicenseViewModel::class.java) -> DriverLicenseViewModel(
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(LogbookViewModel::class.java) -> LogbookViewModel(auth, database, storage)
isAssignableFrom(PrivateHireVehicleViewModel::class.java) -> PrivateHireVehicleViewModel(auth, database, storage)
isAssignableFrom(RoleViewModel::class.java) -> RoleViewModel(auth, database, storage)
isAssignableFrom(LogbookViewModel::class.java) -> LogbookViewModel(
auth,
database,
storage
)
isAssignableFrom(PrivateHireVehicleViewModel::class.java) -> PrivateHireVehicleViewModel(
auth,
database,
storage
)
isAssignableFrom(RoleViewModel::class.java) -> RoleViewModel(
auth,
database,
storage
)
else -> throw IllegalArgumentException("Unknown ViewModel class")
} 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.singleton
class DriverApplication : Application(), KodeinAware{
class DriverApplication : Application(), KodeinAware {
// Kodein aware to initialise the classes used for DI
override val kodein = Kodein.lazy {

View File

@@ -2,15 +2,16 @@ package h_mal.appttude.com.base
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup.LayoutParams
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import androidx.activity.viewModels
import android.view.ViewGroup.inflate
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelLazy
import androidx.test.espresso.IdlingResource
import androidx.viewbinding.ViewBinding
import h_mal.appttude.com.R
import h_mal.appttude.com.application.ApplicationViewModelFactory
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.android.kodein
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.
private var mIdlingResource: BasicIdlingResource? = null
private lateinit var loadingView: View
abstract fun getViewModel(): V?
abstract val layoutId: Int
private var _binding: VB? = null
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()
val factory by instance<ApplicationViewModelFactory>()
inline fun <reified VM : ViewModel> createLazyViewModel(): Lazy<VM> = viewModels { factory }
inline fun <reified VM : ViewModel> createViewModel(): VM =
ViewModelProvider(viewModelStore, factory).get(VM::class.java)
fun createLazyViewModel(): Lazy<V> = ViewModelLazy(
getGenericClassAt(0),
{ 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
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
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
* loading
*/
private fun instantiateLoadingView(){
// loadingView = View.inflate(this, R.layout.progress_layout, null)
loadingView = layoutInflater.inflate(R.layout.progress_layout, null)
private fun instantiateLoadingView() {
loadingView = inflate(this, R.layout.progress_layout, null)
loadingView.setOnClickListener(null)
addContentView(loadingView, LayoutParams(MATCH_PARENT, MATCH_PARENT))
loadingView.hide()
@@ -97,7 +132,7 @@ abstract class BaseActivity<V : BaseViewModel> : AppCompatActivity(), KodeinAwar
}
private fun configureObserver() {
getViewModel()?.uiState?.observe(this) {
viewModel.uiState.observe(this) {
when (it) {
is ViewState.HasStarted -> onStarted()
is ViewState.HasData<*> -> onSuccess(it.data.getContentIfNotHandled())

View File

@@ -5,24 +5,33 @@ import android.content.ClipData
import android.content.Intent
import android.net.Uri
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.viewModels
import androidx.lifecycle.ViewModel
import androidx.fragment.app.createViewModelLazy
import androidx.viewbinding.ViewBinding
import h_mal.appttude.com.application.ApplicationViewModelFactory
import h_mal.appttude.com.data.ViewState
import h_mal.appttude.com.utils.PermissionsUtils
import org.kodein.di.KodeinAware
import org.kodein.di.android.x.kodein
import org.kodein.di.generic.instance
import java.lang.reflect.ParameterizedType
import kotlin.reflect.KClass
const val IMAGE_SELECT_REQUEST_CODE = 401
abstract class BaseFragment<V : BaseViewModel>(@LayoutRes contentLayoutId: Int) :
Fragment(contentLayoutId), KodeinAware {
abstract class BaseFragment<V : BaseViewModel, VB : ViewBinding>(
) : Fragment(), KodeinAware {
var mActivity: BaseActivity<V>? = null
abstract fun getViewModel(): V
private var _binding: VB? = null
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
@@ -33,13 +42,57 @@ abstract class BaseFragment<V : BaseViewModel>(@LayoutRes contentLayoutId: Int)
override val kodein by kodein()
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")
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mActivity = activity as BaseActivity<V>
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")
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()
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() {
getViewModel().uiState.observe(viewLifecycleOwner) {
viewModel.uiState.observe(viewLifecycleOwner) {
when (it) {
is ViewState.HasStarted -> onStarted()
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.utils.Event
abstract class BaseViewModel: ViewModel(){
abstract class BaseViewModel : ViewModel() {
open val uiState: MutableLiveData<ViewState> = MutableLiveData()
fun onStart() {
@@ -23,11 +23,11 @@ abstract class BaseViewModel: ViewModel(){
suspend fun doTryOperation(
defaultErrorMessage: String?,
operation: suspend () -> Unit
){
) {
try {
onStart()
operation()
}catch (e: Exception){
} catch (e: Exception) {
e.printStackTrace()
e.message?.let {
onError(it)

View File

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

View File

@@ -30,7 +30,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
abstract fun getDataFromDatabase(): 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) { }
open fun setDataInDatabase(data: T) {}
inline fun <reified T : Any> getDataClass() = io {
doTryOperation("Failed to retrieve $objectName") {
@@ -60,7 +60,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
}
suspend fun getImageUrl(localImageUri: Uri?, imageUrl: String?): String {
if (localImageUri == null && imageUrl.isNullOrBlank()){
if (localImageUri == null && imageUrl.isNullOrBlank()) {
throw IOException("No image is selected")
}
@@ -68,7 +68,7 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
}
suspend fun getImageUrls(localImageUris: List<Uri?>?): List<String?> {
if (localImageUris.isNullOrEmpty()){
if (localImageUris.isNullOrEmpty()) {
throw IOException("No images is selected")
}
val listOfUrls = mutableListOf<String>()
@@ -81,10 +81,19 @@ abstract class DataSubmissionBaseViewModel<T : Any>(
return listOfUrls
}
suspend fun <T, R> Iterable<T>.mapSuspend(transform: suspend (T) -> R): List<R> =
coroutineScope { map { t: T -> async { transform(t) } }.map { it.await() } }
suspend fun <T, R> Iterable<T>.mapSuspend(transform: suspend (T) -> R): List<R> =
coroutineScope { map { t: T -> async { transform(t) } }.map { it.await() } }
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
sealed class EventResponse {
data class Changed(val snapshot: DataSnapshot): EventResponse()
data class Cancelled(val error: DatabaseError): EventResponse()
data class Changed(val snapshot: DataSnapshot) : 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 java.io.IOException
class FirebaseAuthSource: FirebaseAuthentication{
private val auth = FirebaseAuth.getInstance()
class FirebaseAuthSource : FirebaseAuthentication {
private val auth = FirebaseAuth.getInstance()
override fun getUid(): String? = auth.uid
@@ -19,7 +19,7 @@ class FirebaseAuthSource: FirebaseAuthentication{
auth.createUserWithEmailAndPassword(email, password)
override fun logOut() = auth.signOut()
override fun forgotPassword(email: String): Task<Void> = auth.sendPasswordResetEmail(email)
override fun updateProfile(
@@ -42,15 +42,17 @@ class FirebaseAuthSource: FirebaseAuthentication{
}
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 userStateListener() : FirebaseLiveData {
return FirebaseLiveData(auth)
override fun userStateListener(): FirebaseAuthStateLiveData {
return FirebaseAuthStateLiveData(auth)
}
private fun getCurrentUser(): FirebaseUser{
private fun getCurrentUser(): FirebaseUser {
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 com.google.firebase.auth.FirebaseAuth
class FirebaseLiveData(
/**
* Creates #LiveDate out of {UserAuthState} for firebase user state
*/
class FirebaseAuthStateLiveData(
private val firebaseAuth: FirebaseAuth
): LiveData<UserAuthState>(){
) : LiveData<UserAuthState>() {
override fun onActive() {
super.onActive()
@@ -24,4 +27,4 @@ class FirebaseLiveData(
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.FirebaseUser
interface FirebaseAuthentication{
interface FirebaseAuthentication {
fun getUid(): String?
fun getUser(): FirebaseUser?
fun signIn(email: String, password: String): Task<AuthResult>
@@ -16,12 +16,14 @@ interface FirebaseAuthentication{
name: String?,
profilePic: Uri?
): Task<Void>
fun reauthenticate(
email: String,
password: String
): Task<Void>
fun updateEmail(email: String): Task<Void>
fun updatePassword(password: String): Task<Void>
fun deleteProfile(): Task<Void>
fun userStateListener() : FirebaseLiveData
fun userStateListener(): FirebaseAuthStateLiveData
}

View File

@@ -1,7 +1,7 @@
package h_mal.appttude.com.data
sealed class FirebaseCompletion{
object Default: FirebaseCompletion()
data class Changed(val message: String): FirebaseCompletion()
data class ProfileDeleted(val message: String): FirebaseCompletion()
sealed class FirebaseCompletion {
object Default : FirebaseCompletion()
data class Changed(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
const val USER_CONST = "user"
const val PROFILE_ROLE ="role"
const val PROFILE_ROLE = "role"
const val DRIVER_NUMBER = "driver_number"
const val USER_DETAILS = "user_details"
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 VEHICLE_DETAILS = "vehicle_details"
const val ARCHIVE = "archive"
class FirebaseDatabaseSource {
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()
return data
}
@@ -52,6 +59,8 @@ class FirebaseDatabaseSource {
fun getArchiveLogbookRef(uid: String) = getArchiveRef(uid).child(LOG_BOOK)
fun getArchiveMotDetailsRef(uid: String) = getArchiveRef(uid).child(MOT)
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)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,33 +1,25 @@
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.databinding.FragmentDeleteProfileBinding
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener
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 getViewModel(): UpdateUserViewModel = viewmodel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
password_top.setEnterPressedListener { deleteUser() }
submission_button_label.setOnClickListener { deleteUser() }
override fun setupView(binding: FragmentDeleteProfileBinding) = binding.run {
passwordTop.setEnterPressedListener { deleteUser() }
submissionButtonLabel.setOnClickListener { deleteUser() }
}
private fun deleteUser(){
val emailString = email_update.validatePasswordEditText() ?: return
val passwordText = password_top.validatePasswordEditText() ?: return
private fun deleteUser() = applyBinding {
val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
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
import android.os.Bundle
import h_mal.appttude.com.R
import h_mal.appttude.com.base.BaseActivity
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.viewmodels.UpdateUserViewModel
class UpdateActivity : BaseActivity<UpdateUserViewModel>() {
override val layoutId: Int = R.layout.update_activity
override fun getViewModel(): UpdateUserViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
createViewModel<UpdateUserViewModel>()
}
class UpdateActivity : BaseActivity<UpdateUserViewModel, UpdateActivityBinding>() {
override fun onSuccess(data: Any?) {
super.onSuccess(data)
when(data){
when (data) {
is FirebaseCompletion.Changed -> displayToast(data.message)
}
}

View File

@@ -1,36 +1,28 @@
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.databinding.FragmentUpdateEmailBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener
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 getViewModel(): UpdateUserViewModel = viewmodel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
new_email.setEnterPressedListener { registerUser() }
submission_button_label.setOnClickListener { registerUser() }
override fun setupView(binding: FragmentUpdateEmailBinding) = binding.run {
newEmail.setEnterPressedListener { registerUser() }
submissionButtonLabel.setOnClickListener { registerUser() }
}
private fun registerUser(){
val emailString = email_update.validatePasswordEditText() ?: return
val passwordText = password_top.validatePasswordEditText() ?: return
val newEmail = new_email.validateEmailEditText() ?: return
private fun registerUser() {
applyBinding {
val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
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
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.databinding.UpdateOverviewFragmentBinding
import h_mal.appttude.com.utils.navigateTo
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 getViewModel(): UpdateUserViewModel = vm
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
update_email_button.setOnClickListener(this)
update_password_button.setOnClickListener(this)
update_profile_button.setOnClickListener(this)
delete_profile.setOnClickListener(this)
override fun setupView(binding: UpdateOverviewFragmentBinding) = binding.run {
updateEmailButton.setOnClickListener(this@UpdateOverviewFragment)
updatePasswordButton.setOnClickListener(this@UpdateOverviewFragment)
updateProfileButton.setOnClickListener(this@UpdateOverviewFragment)
deleteProfile.setOnClickListener(this@UpdateOverviewFragment)
}
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_password_button -> navigateTo(R.id.to_updatePasswordFragment)
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()
}
}

View File

@@ -1,36 +1,30 @@
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.databinding.FragmentUpdatePasswordBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener
import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_update_password.*
class UpdatePasswordFragment :
BaseFragment<UpdateUserViewModel>(R.layout.fragment_update_password) {
class UpdatePasswordFragment : BaseFragment<UpdateUserViewModel, FragmentUpdatePasswordBinding>() {
private val viewmodel: UpdateUserViewModel by activityViewModels()
override fun getViewModel(): UpdateUserViewModel = viewmodel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
email_update.setEnterPressedListener { registerUser() }
email_sign_up.setOnClickListener { registerUser() }
override fun setupView(binding: FragmentUpdatePasswordBinding) {
applyBinding {
emailUpdate.setEnterPressedListener { registerUser() }
emailSignUp.setOnClickListener { registerUser() }
}
}
private fun registerUser() {
val emailString = email_update.validatePasswordEditText() ?: return
val passwordText = password_top.validatePasswordEditText() ?: return
val newPassword = password_bottom.validateEmailEditText() ?: return
applyBinding {
val emailString = emailUpdate.validatePasswordEditText() ?: return@applyBinding
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.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.activityViewModels
import com.google.firebase.auth.FirebaseUser
import h_mal.appttude.com.R
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.setEnterPressedListener
import h_mal.appttude.com.utils.setGlideImage
import h_mal.appttude.com.viewmodels.UpdateUserViewModel
import kotlinx.android.synthetic.main.fragment_update_profile.*
const val TAG_CONST = "non-user"
private const val IMAGE_PERMISSION_RESULT = 402
class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragment_update_profile) {
private val viewmodel: UpdateUserViewModel by activityViewModels()
override fun getViewModel(): UpdateUserViewModel = viewmodel
class UpdateProfileFragment : BaseFragment<UpdateUserViewModel, FragmentUpdateProfileBinding>() {
private var imageChangeListener: Boolean = false
private var nameChangeListener: Boolean = false
private var imageUri: Uri? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun setupView(binding: FragmentUpdateProfileBinding) = binding.run {
viewModel.getUser()
viewmodel.getUser()
update_name.apply {
updateName.apply {
doAfterTextChanged {
if (tag == TAG_CONST) {
tag = null
@@ -45,20 +35,22 @@ class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragmen
setEnterPressedListener { submitProfileUpdate() }
}
profile_img.setOnClickListener {
profileImg.setOnClickListener {
if (askForPermissions(READ_EXTERNAL_STORAGE, IMAGE_PERMISSION_RESULT)) {
openGalleryForImage()
}
}
submit_update_profile.setOnClickListener { submitProfileUpdate() }
submitUpdateProfile.setOnClickListener { submitProfileUpdate() }
}
private fun submitProfileUpdate() {
val name: String? = takeIf { nameChangeListener }?.update_name?.text?.toString()
val imgUri = takeIf { imageChangeListener }?.let { imageUri }
applyBinding {
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(
@@ -76,18 +68,24 @@ class UpdateProfileFragment : BaseFragment<UpdateUserViewModel>(R.layout.fragmen
}
private fun setFields(firebaseUser: FirebaseUser) {
profile_img.setGlideImage(firebaseUser.photoUrl)
update_name.apply {
setText(firebaseUser.displayName)
tag = TAG_CONST
applyBinding {
profileImg.setGlideImage(firebaseUser.photoUrl)
updateName.apply {
setText(firebaseUser.displayName)
tag = TAG_CONST
}
}
}
override fun onImageGalleryResult(imageUri: Uri?) {
super.onImageGalleryResult(imageUri)
this.imageUri = imageUri
profile_img.setGlideImage(imageUri)
imageChangeListener = true
applyBinding {
profileImg.setGlideImage(imageUri)
imageChangeListener = true
}
}
}

View File

@@ -1,26 +1,17 @@
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.databinding.FragmentForgotPasswordBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
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 getViewModel(): UserViewModel = userViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
submission_button.setOnClickListener {
val emailString = submission_et.validateEmailEditText() ?: return@setOnClickListener
userViewModel.forgotPassword(emailString)
override fun setupView(binding: FragmentForgotPasswordBinding) = binding.run {
submissionButton.setOnClickListener {
val emailString = submissionEt.validateEmailEditText() ?: return@setOnClickListener
viewModel.forgotPassword(emailString)
}
}

View File

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

View File

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

View File

@@ -1,42 +1,37 @@
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.databinding.FragmentRegisterBinding
import h_mal.appttude.com.utils.TextValidationUtils.validateEmailEditText
import h_mal.appttude.com.utils.TextValidationUtils.validatePasswordEditText
import h_mal.appttude.com.utils.setEnterPressedListener
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 {
val userViewModel: UserViewModel by activityViewModels()
return userViewModel
override fun setupView(binding: FragmentRegisterBinding) = binding.run {
passwordBottom.setEnterPressedListener { registerUser() }
emailSignUp.setOnClickListener { registerUser() }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
private fun registerUser() {
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() }
email_sign_up.setOnClickListener { registerUser() }
}
if ((passwordText != passwordTextBottom)) {
passwordBottom.error = getString(R.string.no_match_password)
passwordBottom.requestFocus()
return@applyBinding
}
private fun registerUser(){
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
viewModel.registerUser(nameString, emailText, passwordText)
}
getViewModel().registerUser(nameString, emailText, passwordText)
}
}

View File

@@ -2,23 +2,20 @@ 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.data.FirebaseCompletion
import h_mal.appttude.com.databinding.SplashScreenBinding
import h_mal.appttude.com.utils.navigateTo
import h_mal.appttude.com.viewmodels.UserViewModel
class SplashScreenFragment : BaseFragment<UserViewModel>(R.layout.fragment_splash_screen) {
private val userViewModel by activityViewModels<UserViewModel>()
override fun getViewModel(): UserViewModel = userViewModel
class SplashScreenFragment : BaseFragment<UserViewModel, SplashScreenBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userViewModel.splashscreenCheckUserIsLoggedIn()
viewModel.splashscreenCheckUserIsLoggedIn()
}
override fun onSuccess(data: Any?) {

View File

@@ -5,7 +5,7 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils
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)
animation.setAnimationListener(object : Animation.AnimationListener {
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.launch
object Coroutines{
object Coroutines {
fun io(work: suspend () -> Unit) = CoroutineScope(Dispatchers.IO).launch { work() }
fun main(work: suspend () -> Unit) = CoroutineScope(Dispatchers.Main).launch { work() }

View File

@@ -11,7 +11,7 @@ object DateUtils {
return sdf.format(Date())
}
fun getDateTimeStamp(): String{
fun getDateTimeStamp(): String {
val sdf: SimpleDateFormat = getSimpleDateFormat("yyyyMMdd_HHmmss")
return sdf.format(Date())
}
@@ -23,7 +23,7 @@ object DateUtils {
val sdfOut = getSimpleDateFormat(formatOut)
val newDate: Date = sdfIn.parse(this)
sdfOut.format(newDate)
}catch (e: Exception){
} catch (e: Exception) {
e.printStackTrace()
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.suspendCoroutine
/**
* Read database reference once {@link #DatabaseReference.addListenerForSingleValueEvent}
*
*
* @return EventResponse
*/
suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCoroutine { continuation ->
val valueEventListener = object: ValueEventListener {
val valueEventListener = object : ValueEventListener {
override fun onCancelled(error: DatabaseError) {
continuation.resume(EventResponse.Cancelled(error))
}
@@ -23,7 +27,13 @@ suspend fun DatabaseReference.singleValueEvent(): EventResponse = suspendCorouti
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()) {
is EventResponse.Changed -> {
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
.findNavController(this)
.navigate(navId)

View File

@@ -103,6 +103,7 @@ fun ImageView.setPicassoImage(
context?.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
}
override fun onBitmapFailed(e: Exception?, errorDrawable: 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.FirebaseDatabaseSource
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
class DriverLicenseViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<DriversLicenseObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<DriversLicense>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getDriverLicenseRef(uid)
override val storageRef: StorageReference = storage.driversLicenseStorageRef(uid)
override val objectName: String = "drivers license"
override fun getDataFromDatabase() = getDataClass<DriversLicenseObject>()
override fun getDataFromDatabase() = getDataClass<DriversLicense>()
override fun setDataInDatabase(data: DriversLicenseObject, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){
override fun setDataInDatabase(data: DriversLicense, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.licenseImageString)
data.licenseImageString = imageUrl
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.FirebaseDatabaseSource
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
class DriverProfileViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<DriverProfileObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<DriverProfile>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getDriverDetailsRef(uid)
override val storageRef: StorageReference = storage.profileImageStorageRef(uid)
override val objectName: String = "drivers profile"
override fun getDataFromDatabase() = getDataClass<DriverProfileObject>()
override fun getDataFromDatabase() = getDataClass<DriverProfile>()
override fun setDataInDatabase(data: DriverProfileObject, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){
override fun setDataInDatabase(data: DriverProfile, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.driverPic)
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.FirebaseDatabaseSource
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
class InsuranceViewModel (
class InsuranceViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<InsuranceObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<Insurance>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getInsuranceDetailsRef(uid)
override val storageRef: StorageReference = storage.insuranceStorageRef(uid)
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") {
val imageUrls = if (!localImageUris.isNullOrEmpty()){
val imageUrls = if (!localImageUris.isNullOrEmpty()) {
getImageUrls(localImageUris).toMutableList()
}else{
} else {
data.photoStrings
}
if (imageUrls.isNullOrEmpty()){
if (imageUrls.isNullOrEmpty()) {
onError("no images selected")
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.FirebaseDatabaseSource
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
class LogbookViewModel (
class LogbookViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<LogbookObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<Logbook>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getLogbookRef(uid)
override val storageRef: StorageReference = storage.logBookStorageRef(uid)
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") {
val imageUrl = getImageUrl(localImageUri, data.photoString)
data.photoString = imageUrl

View File

@@ -9,25 +9,25 @@ import h_mal.appttude.com.utils.getDataFromDatabaseRef
class MainViewModel(
private val firebaseAuth: FirebaseAuthentication,
private val firebaseDatabase: FirebaseDatabaseSource
) : BaseViewModel(){
) : BaseViewModel() {
fun getRole() = io {
doTryOperation("failed to retrieve data") {
val uid = firebaseAuth.getUid() ?: return@doTryOperation
val ref = firebaseDatabase.getUserRoleRef(uid)
val role = ref.getDataFromDatabaseRef<String>()
role?.apply { onSuccess(this) } ?: onError("No role found")
}
doTryOperation("failed to retrieve data") {
val uid = firebaseAuth.getUid() ?: return@doTryOperation
val ref = firebaseDatabase.getUserRoleRef(uid)
val role = ref.getDataFromDatabaseRef<String>()
role?.apply { onSuccess(this) } ?: onError("No role found")
}
}
fun getUserDetails(){
fun getUserDetails() {
firebaseAuth.getUser()?.let {
onSuccess(it)
}
}
fun logOut(){
fun 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.FirebaseDatabaseSource
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
class MotViewModel (
class MotViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<MotObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<Mot>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getMotDetailsRef(uid)
override val storageRef: StorageReference? = storage.motStorageRef(uid)
override val objectName: String = "vehicle profile"
override fun getDataFromDatabase() = getDataClass<MotObject>()
override fun getDataFromDatabase() = getDataClass<Mot>()
override fun setDataInDatabase(data: MotObject, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName"){
override fun setDataInDatabase(data: Mot, localImageUri: Uri?) = io {
doTryOperation("Failed to upload $objectName") {
val imageUrl = getImageUrl(localImageUri, data.motImageString)
data.motImageString = imageUrl
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.FirebaseDatabaseSource
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
class PrivateHireLicenseViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<PrivateHireObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<PrivateHireLicense>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getPrivateHireRef(uid)
override val storageRef: StorageReference = storage.privateHireStorageRef(uid)
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 {
doTryOperation("Failed to upload private hire license"){
override fun setDataInDatabase(data: PrivateHireLicense, localImageUri: Uri?) = io {
doTryOperation("Failed to upload private hire license") {
val imageUrl = getImageUrl(localImageUri, data.phImageString)
val driverLicense = PrivateHireObject(
val driverLicense = PrivateHireLicense(
phExpiry = data.phExpiry,
phNumber = data.phNumber,
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.FirebaseDatabaseSource
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
class PrivateHireVehicleViewModel (
class PrivateHireVehicleViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<PrivateHireVehicleObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<PrivateHireVehicle>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getPrivateHireVehicleRef(uid)
override val storageRef: StorageReference = storage.privateHireVehicleStorageRef(uid)
override val objectName: String = "private hire vehicle license"
override fun getDataFromDatabase() = 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") {
val imageUrl = getImageUrl(localImageUri, data.phCarImageString)
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.FirebaseDatabaseSource
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
class VehicleProfileViewModel (
class VehicleProfileViewModel(
auth: FirebaseAuthentication,
database: FirebaseDatabaseSource,
storage: FirebaseStorageSource
) : DataSubmissionBaseViewModel<VehicleProfileObject>(auth, database, storage) {
) : DataSubmissionBaseViewModel<VehicleProfile>(auth, database, storage) {
override val databaseRef: DatabaseReference = database.getVehicleDetailsRef(uid)
override val storageRef: StorageReference? = null
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 {
doTryOperation("Failed to upload $objectName"){
doTryOperation("Failed to upload $objectName") {
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"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
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>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" 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 android:height="24dp"
android:tint="#FFFFFF"
android:viewportHeight="24"
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>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" 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 android:height="24dp"
android:tint="#FFFFFF"
android:viewportHeight="24"
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>

View File

@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" 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 android:height="24dp"
android:tint="#FFFFFF"
android:viewportHeight="24"
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>

View File

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

View File

@@ -1,9 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
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>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
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>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:padding="10dp">
<solid android:color="#03a9f4" />
<corners
android:bottomRightRadius="22dp"

View File

@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cars"
android:background="@drawable/background_with_curve"
tools:context="h_mal.appttude.com.ui.user.LoginActivity">
<fragment
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
@@ -21,5 +20,4 @@
app:navGraph="@navigation/auth_navigation"
tools:context=".ui.auth.AuthActivity" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
@@ -10,6 +9,7 @@
tools:openDrawer="start">
<include
android:id="@+id/app_bar_layout"
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
@@ -22,7 +22,7 @@
android:fitsSystemWindows="true"
app:itemTextColor="@android:color/white"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" >
app:menu="@menu/activity_main_drawer">
<LinearLayout
android:layout_width="match_parent"

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_margin="12dp"
@@ -20,12 +21,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/or"
android:layout_toStartOf="@id/or"
android:background="#616161"
android:gravity="center" />
@@ -35,14 +37,14 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="4dp"
android:text="OR" />
android:text="@string/or" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/or"
android:layout_toEndOf="@id/or"
android:background="#616161"
android:gravity="center" />
@@ -60,4 +62,4 @@
android:textColor="@android:color/black"
android:textStyle="bold" />
</LinearLayout>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -13,5 +13,5 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/driver_profile_request_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
@@ -17,7 +16,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="You are not a driver, request a driver profile to use this app" />
android:text="@string/not_a_driver_message" />
<androidx.cardview.widget.CardView
android:id="@+id/request_driver_button"
@@ -32,7 +31,7 @@
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:gravity="center"
android:text="Request driver profile"
android:text="@string/request_driver_profile"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold" />

View File

@@ -1,79 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/parent_constraint_layout"
tools:context=".ui.driverprofile.DriverLicenseFragment">
<androidx.cardview.widget.CardView
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardCornerRadius="28dp"
app:cardElevation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/til_lic_no">
<ImageView
android:id="@+id/driversli_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
app:cardCornerRadius="28dp"
app:cardElevation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/til_lic_no">
android:layout_height="200dp"
android:layout_alignParentStart="true"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
tools:src="@drawable/choice_img_round"
android:contentDescription="@string/image_description" />
<ImageView
android:id="@+id/driversli_img"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_alignParentStart="true"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
tools:src="@drawable/choice_img_round"
android:contentDescription="@string/image_description" />
<com.mikhaellopez.circularimageview.CircularImageView
android:id="@+id/search_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_baseline_photo_library_24"
android:scaleType="centerInside"
android:elevation="1dp"
app:civ_border_width="1dp"
app:civ_shadow_radius="0.5dp"
android:alpha="1"
app:civ_circle_color="@color/colour_one"
android:layout_margin="18dp"
android:layout_gravity="bottom|end" />
<com.mikhaellopez.circularimageview.CircularImageView
android:id="@+id/search_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_baseline_photo_library_24"
android:scaleType="centerInside"
android:elevation="1dp"
app:civ_border_width="1dp"
app:civ_shadow_radius="0.5dp"
android:alpha="1"
app:civ_circle_color="@color/colour_one"
android:layout_margin="18dp"
android:layout_gravity="bottom|end" />
</androidx.cardview.widget.CardView>
</androidx.cardview.widget.CardView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_lic_no"
style="@style/text_input_layout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_lic_no"
style="@style/text_input_layout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText
android:id="@+id/lic_no"
style="@style/EditTextStyle.Date"
android:hint="@string/drivers_license_no"
android:inputType="none"
android:maxLines="1"
android:importantForAutofill="no" />
<EditText
android:id="@+id/lic_no"
style="@style/EditTextStyle.Date"
android:hint="@string/drivers_license_no"
android:inputType="none"
android:maxLines="1"
android:importantForAutofill="no" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_submission"
style="@style/text_input_layout"
app:layout_constraintTop_toBottomOf="@id/til_lic_no"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_submission"
style="@style/text_input_layout"
app:layout_constraintTop_toBottomOf="@id/til_lic_no"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:hint="@string/license_expiry_date"
android:id="@+id/lic_expiry"
style="@style/EditTextStyle.Date"
android:autofillHints="date" />
<EditText
android:hint="@string/license_expiry_date"
android:id="@+id/lic_expiry"
style="@style/EditTextStyle.Date"
android:autofillHints="date" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/submit"
@@ -84,6 +83,6 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.8"/>
app:layout_constraintVertical_bias="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -10,19 +10,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:src="@drawable/cars"/>
tools:src="@drawable/cars" />
<android.support.design.widget.FloatingActionButton
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/download_pic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:src="@drawable/ic_file_download_black_24dp" />
android:src="@drawable/ic_file_download_black_24dp"
android:contentDescription="@string/floating_action_button" />
</RelativeLayout>

View File

@@ -35,7 +35,7 @@
android:text="@string/upload_mot"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/til_submission"/>
app:layout_constraintBottom_toTopOf="@+id/til_submission" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_submission"

View File

@@ -3,7 +3,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@drawable/cars"
tools:context=".ui.user.SplashScreenFragment">
</FrameLayout>

View File

@@ -16,7 +16,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/login_subtitle_tv"
@@ -27,7 +27,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_old_email"
@@ -85,6 +85,6 @@
app:layout_constraintVertical_bias="0.8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/til_password_top"/>
app:layout_constraintTop_toBottomOf="@+id/til_password_top" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -12,8 +12,7 @@
android:layout_margin="12dp"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/reg"
@@ -25,8 +24,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/make"
@@ -39,8 +37,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/car_model"
@@ -53,8 +50,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/colour"
@@ -67,8 +63,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/keeper_name"
@@ -84,8 +79,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/address"
@@ -104,8 +98,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/postcode"
@@ -122,8 +115,7 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
style="@style/text_input_layout">
<com.google.android.material.textfield.TextInputLayout style="@style/text_input_layout">
<EditText
android:id="@+id/start_date"
@@ -142,7 +134,7 @@
android:hint="@string/vehicle_seized"
android:buttonTint="@color/colour_eight"
android:padding="12dp"
android:textSize="18sp"/>
android:textSize="18sp" />
<com.google.android.material.button.MaterialButton

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/driver_profile_request_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -14,9 +13,10 @@
android:id="@+id/driver"
style="@style/TextButton.WithIcon"
android:text="@string/driver_profile"
android:layout_marginBottom="12dp"/>
android:layout_marginBottom="12dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/car"
style="@style/TextButton.WithIcon"
android:text="@string/vehicle_profile"/>
android:text="@string/vehicle_profile" />
</LinearLayout>

View File

@@ -17,6 +17,7 @@
android:layout_width="200dp"
android:layout_height="200dp"
android:adjustViewBounds="true">
<androidx.viewpager.widget.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content">

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background_with_curve">
<ImageView
android:id="@+id/background_img"
android:src="@drawable/welcome_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="@style/imageBackground"
android:contentDescription="@string/image_description" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"

View File

@@ -32,7 +32,7 @@
app:layout_constraintBottom_toTopOf="@id/update_password_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/update_email"/>
android:text="@string/update_email" />
<com.google.android.material.button.MaterialButton
style="@style/TextButton.WithIcon"
@@ -41,7 +41,7 @@
app:layout_constraintBottom_toTopOf="@id/update_profile_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/update_password"/>
android:text="@string/update_password" />
<com.google.android.material.button.MaterialButton
style="@style/TextButton.WithIcon"
@@ -50,7 +50,7 @@
app:layout_constraintBottom_toTopOf="@id/delete_profile"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/update_profile"/>
android:text="@string/update_profile" />
<com.google.android.material.button.MaterialButton
style="@style/TextButton.WithIcon"
@@ -60,6 +60,6 @@
android:backgroundTint="@color/colour_nine"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -16,20 +16,20 @@
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_forgotPassword"
app:destination="@id/forgotPasswordFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
</fragment>
<fragment
android:id="@+id/registerFragment"
android:name="h_mal.appttude.com.ui.user.RegisterFragment"
android:label="RegisterFragment"
tools:layout="@layout/fragment_register"/>
tools:layout="@layout/fragment_register" />
<fragment
android:id="@+id/forgotPasswordFragment"
android:name="h_mal.appttude.com.ui.user.ForgotPasswordFragment"
@@ -39,7 +39,7 @@
android:id="@+id/splashScreenFragment"
android:name="h_mal.appttude.com.ui.user.SplashScreenFragment"
android:label="fragment_splash_screen"
tools:layout="@layout/fragment_splash_screen" >
tools:layout="@layout/fragment_splash_screen">
<action
android:id="@+id/to_loginFragment"
app:destination="@id/loginFragment"

View File

@@ -8,21 +8,21 @@
android:id="@+id/homeDriverFragment"
android:name="h_mal.appttude.com.ui.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home_driver" >
tools:layout="@layout/fragment_home_driver">
<action
android:id="@+id/to_driverOverallFragment"
app:destination="@id/driverOverallFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_vehicleOverallFragment"
app:destination="@id/vehicleOverallFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
</fragment>
<fragment
android:id="@+id/driverOverallFragment"
@@ -35,21 +35,21 @@
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_driverLicenseFragment"
app:destination="@id/driverLicenseFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_privateHireLicenseFragment2"
app:destination="@id/privateHireLicenseFragment2"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
</fragment>
<fragment
@@ -63,35 +63,35 @@
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_insuranceFragment"
app:destination="@id/insuranceFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_motFragment"
app:destination="@id/motFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_logbookFragment"
app:destination="@id/logbookFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_privateHireVehicleFragment"
app:destination="@id/privateHireVehicleFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
</fragment>
<fragment
@@ -110,17 +110,17 @@
android:id="@+id/vehicleSetupFragment"
android:name="h_mal.appttude.com.ui.vehicleprofile.VehicleProfileFragment"
android:label="VehicleSetupFragment"
tools:layout="@layout/fragment_vehicle_setup"/>
tools:layout="@layout/fragment_vehicle_setup" />
<fragment
android:id="@+id/insuranceFragment"
android:name="h_mal.appttude.com.ui.vehicleprofile.InsuranceFragment"
android:label="InsuranceFragment"
tools:layout="@layout/fragment_insurance"/>
tools:layout="@layout/fragment_insurance" />
<fragment
android:id="@+id/motFragment"
android:name="h_mal.appttude.com.ui.vehicleprofile.MotFragment"
android:label="MotFragment"
tools:layout="@layout/fragment_mot"/>
tools:layout="@layout/fragment_mot" />
<fragment
android:id="@+id/logbookFragment"
android:name="h_mal.appttude.com.ui.vehicleprofile.LogbookFragment"

View File

@@ -15,39 +15,39 @@
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_updatePasswordFragment"
app:destination="@id/updatePasswordFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_updateProfileFragment"
app:destination="@id/updateProfileFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
<action
android:id="@+id/to_deleteProfileFragment"
app:destination="@id/deleteProfileFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_enter_anim"
app:popExitAnim="@anim/nav_default_exit_anim"/>
app:popExitAnim="@anim/nav_default_exit_anim" />
</fragment>
<fragment
android:id="@+id/updateEmailFragment"
android:name="h_mal.appttude.com.ui.update.UpdateEmailFragment"
android:label="UpdateEmailFragment"
tools:layout="@layout/fragment_update_email"/>
tools:layout="@layout/fragment_update_email" />
<fragment
android:id="@+id/updatePasswordFragment"
android:name="h_mal.appttude.com.ui.update.UpdatePasswordFragment"
android:label="UpdatePasswordFragment"
tools:layout="@layout/fragment_update_password"/>
tools:layout="@layout/fragment_update_password" />
<fragment
android:id="@+id/updateProfileFragment"
android:name="h_mal.appttude.com.ui.update.UpdateProfileFragment"

View File

@@ -89,4 +89,10 @@
<string name="insurance_expiry">Insurance expiry</string>
<string name="logout">Logout</string>
<string name="forgot_password">Forgot password?</string>
<string name="leave_header">Leave?</string>
<string name="leave_message">Are you sure you want to exit?</string>
<string name="not_a_driver_message">You are not a driver, request a driver profile to use this app</string>
<string name="request_driver_profile">Request driver profile</string>
<string name="or">OR</string>
<string name="floating_action_button">Floating action button</string>
</resources>

View File

@@ -35,7 +35,7 @@
<!--<item name="android:autofilledHighlight">@android:color/transparent</item>-->
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" >
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
</style>
@@ -115,7 +115,7 @@
<item name="tint">@android:color/white</item>
</style>
<style name="TextButton.WithIcon.SubmitConstraints" parent="TextButton.WithIcon" >
<style name="TextButton.WithIcon.SubmitConstraints" parent="TextButton.WithIcon">
<item name="layout_constraintTop_toTopOf">parent</item>
<item name="layout_constraintBottom_toBottomOf">parent</item>
<item name="layout_constraintLeft_toLeftOf">parent</item>

View File

@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="my_images" path="Android/data/h_mal.appttude.com.driver/files/Pictures" />
<external-path
name="my_images"
path="Android/data/h_mal.appttude.com.driver/files/Pictures" />
</paths>