WIP 2
This commit is contained in:
parent
ef83b93fa6
commit
417e9ea322
@ -35,8 +35,9 @@ class MainActivity : ComponentActivity() {
|
||||
val currentToken = authRepository.getCurrentToken()
|
||||
|
||||
if(currentToken == null) {
|
||||
|
||||
signInActivityResult.launch(Intent(this@MainActivity, LogInActivity::class.java))
|
||||
val loginIntent = Intent(this@MainActivity, LogInActivity::class.java)
|
||||
loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
signInActivityResult.launch(loginIntent)
|
||||
} else {
|
||||
val homeActivityIntent = Intent(this@MainActivity, HomeActivity::class.java)
|
||||
homeActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
|
||||
@ -58,12 +58,4 @@ class LogInViewModel @Inject constructor(private val authRepository: AuthReposit
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun signUp() {
|
||||
|
||||
}
|
||||
|
||||
fun forgotPassword() {
|
||||
|
||||
}
|
||||
}
|
||||
25
app/src/main/java/com/isolaatti/sign_up/Module.kt
Normal file
25
app/src/main/java/com/isolaatti/sign_up/Module.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.isolaatti.sign_up
|
||||
|
||||
import com.isolaatti.connectivity.RetrofitClient
|
||||
import com.isolaatti.sign_up.data.SignUpApi
|
||||
import com.isolaatti.sign_up.data.SignUpRepositoryImpl
|
||||
import com.isolaatti.sign_up.domain.SignUpRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class Module {
|
||||
|
||||
@Provides
|
||||
fun provideSignUpApi(retrofitClient: RetrofitClient): SignUpApi {
|
||||
return retrofitClient.client.create(SignUpApi::class.java)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideSignUpRepository(signUpApi: SignUpApi): SignUpRepository {
|
||||
return SignUpRepositoryImpl(signUpApi)
|
||||
}
|
||||
}
|
||||
34
app/src/main/java/com/isolaatti/sign_up/data/SignUpApi.kt
Normal file
34
app/src/main/java/com/isolaatti/sign_up/data/SignUpApi.kt
Normal file
@ -0,0 +1,34 @@
|
||||
package com.isolaatti.sign_up.data
|
||||
|
||||
import com.isolaatti.sign_up.data.dto.CodeValidationDto
|
||||
import com.isolaatti.sign_up.data.dto.DataDto
|
||||
import com.isolaatti.sign_up.data.dto.ResultDto
|
||||
import com.isolaatti.sign_up.data.dto.SignUpWithCodeDto
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.POST
|
||||
|
||||
interface SignUpApi {
|
||||
|
||||
@POST("signUp/get_code")
|
||||
fun getCode(
|
||||
@Header("clientId") apiClientId: String,
|
||||
@Header("clientSecret") apiSecret: String,
|
||||
@Body email: DataDto
|
||||
): Call<ResultDto>
|
||||
|
||||
@POST("signUp/validate_code")
|
||||
fun validateCode(
|
||||
@Header("clientId") apiClientId: String,
|
||||
@Header("clientSecret") apiSecret: String,
|
||||
@Body code: DataDto
|
||||
): Call<CodeValidationDto>
|
||||
|
||||
@POST("signUp/sign_up_with_code")
|
||||
fun signUpWithCode(
|
||||
@Header("clientId") apiClientId: String,
|
||||
@Header("clientSecret") apiSecret: String,
|
||||
@Body dto: SignUpWithCodeDto
|
||||
): Call<ResultDto>
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package com.isolaatti.sign_up.data
|
||||
|
||||
import com.isolaatti.BuildConfig
|
||||
import com.isolaatti.sign_up.data.dto.DataDto
|
||||
import com.isolaatti.sign_up.data.dto.SignUpWithCodeDto
|
||||
import com.isolaatti.sign_up.domain.SignUpRepository
|
||||
import com.isolaatti.sign_up.domain.entity.GetCodeResult
|
||||
import com.isolaatti.sign_up.domain.entity.SignUpResult
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import retrofit2.awaitResponse
|
||||
import javax.inject.Inject
|
||||
|
||||
class SignUpRepositoryImpl @Inject constructor(private val signUpApi: SignUpApi): SignUpRepository {
|
||||
override fun getCode(email: String): Flow<Resource<GetCodeResult>> = flow {
|
||||
emit(Resource.Loading())
|
||||
try {
|
||||
val response = signUpApi.getCode(BuildConfig.clientId, BuildConfig.secret, DataDto(email)).awaitResponse()
|
||||
if(response.isSuccessful){
|
||||
response.body()?.let { emit(Resource.Success(GetCodeResult.valueOf(it.result)))}
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.OtherError, "Could not map response. $e"))
|
||||
} catch(_: Exception) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
|
||||
override fun validateCode(code: String): Flow<Resource<Boolean>> = flow {
|
||||
emit(Resource.Loading())
|
||||
try {
|
||||
val response = signUpApi.validateCode(BuildConfig.clientId, BuildConfig.secret, DataDto(code)).awaitResponse()
|
||||
if(response.isSuccessful) {
|
||||
response.body()?.let { emit(Resource.Success(it.valid)) }
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
|
||||
override fun signUpWithCode(
|
||||
username: String,
|
||||
displayName: String,
|
||||
password: String,
|
||||
code: String
|
||||
): Flow<Resource<SignUpResult>> = flow {
|
||||
emit(Resource.Loading())
|
||||
try {
|
||||
val response = signUpApi.signUpWithCode(
|
||||
BuildConfig.clientId,
|
||||
BuildConfig.secret,
|
||||
SignUpWithCodeDto(username, password, displayName, code)
|
||||
).awaitResponse()
|
||||
if(response.isSuccessful){
|
||||
response.body()?.let { GetCodeResult.valueOf(it.result)}
|
||||
} else {
|
||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.OtherError, "Could not map response. $e"))
|
||||
} catch(_: Exception) {
|
||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.sign_up.data.dto
|
||||
|
||||
data class CodeValidationDto(
|
||||
val valid: Boolean
|
||||
)
|
||||
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.sign_up.data.dto
|
||||
|
||||
data class DataDto(
|
||||
val data: String
|
||||
)
|
||||
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.sign_up.data.dto
|
||||
|
||||
data class ResultDto(
|
||||
val result: String
|
||||
)
|
||||
@ -0,0 +1,8 @@
|
||||
package com.isolaatti.sign_up.data.dto
|
||||
|
||||
data class SignUpWithCodeDto(
|
||||
val username: String,
|
||||
val password: String,
|
||||
val displayName: String,
|
||||
val code: String
|
||||
)
|
||||
@ -0,0 +1,12 @@
|
||||
package com.isolaatti.sign_up.domain
|
||||
|
||||
import com.isolaatti.sign_up.domain.entity.GetCodeResult
|
||||
import com.isolaatti.sign_up.domain.entity.SignUpResult
|
||||
import com.isolaatti.utils.Resource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SignUpRepository {
|
||||
fun getCode(email: String): Flow<Resource<GetCodeResult>>
|
||||
fun validateCode(code: String): Flow<Resource<Boolean>>
|
||||
fun signUpWithCode(username: String, displayName: String, password: String, code: String): Flow<Resource<SignUpResult>>
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.sign_up.domain.entity
|
||||
|
||||
enum class GetCodeResult {
|
||||
EmailUsed, Success, EmailValidationError, CodesSentLimitReached
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package com.isolaatti.sign_up.domain.entity
|
||||
|
||||
enum class SignUpResult {
|
||||
EmailNotAvailable, ValidationProblems, Ok, Error, UsernameUnavailable
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.isolaatti.sign_up.presentation
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.isolaatti.sign_up.domain.SignUpRepository
|
||||
import com.isolaatti.sign_up.domain.entity.GetCodeResult
|
||||
import com.isolaatti.utils.Resource
|
||||
import com.isolaatti.utils.Validators
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class GetCodeViewModel @Inject constructor(private val signUpRepository: SignUpRepository) : ViewModel() {
|
||||
|
||||
var email: String = ""
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
emailIsValid.value = Validators.isEmailValid(value)
|
||||
}
|
||||
|
||||
|
||||
val emailIsValid: MutableLiveData<Boolean> = MutableLiveData(false)
|
||||
val response: MutableLiveData<Resource<GetCodeResult>?> = MutableLiveData()
|
||||
|
||||
fun getCode() {
|
||||
if(!Validators.isEmailValid(email)) {
|
||||
return
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
signUpRepository.getCode(email).onEach {
|
||||
response.postValue(it)
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.isolaatti.sign_up.presentation
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.isolaatti.sign_up.domain.SignUpRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class SignUpViewModel : ViewModel(){
|
||||
var code: String? = null
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.isolaatti.sign_up.presentation
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.isolaatti.sign_up.domain.SignUpRepository
|
||||
import com.isolaatti.utils.Resource
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ValidateCodeViewModel @Inject constructor(private val signUpRepository: SignUpRepository) : ViewModel() {
|
||||
var code: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
codeIsValid.value = value?.isNotBlank() == true && value.contains(" ") == false
|
||||
}
|
||||
|
||||
val codeIsValid: MutableLiveData<Boolean> = MutableLiveData(false)
|
||||
val result: MutableLiveData<Resource<Boolean>?> = MutableLiveData()
|
||||
fun validateCode() {
|
||||
if(code != null && code!!.isBlank() || code!!.contains(" ")) {
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
signUpRepository.validateCode(code!!.trim()).onEach {
|
||||
result.postValue(it)
|
||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,21 +1,124 @@
|
||||
package com.isolaatti.sign_up.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.SignUpNavigationDirections
|
||||
import com.isolaatti.common.ErrorMessageViewModel
|
||||
import com.isolaatti.databinding.FragmentGetCodeBinding
|
||||
import com.isolaatti.sign_up.domain.entity.GetCodeResult
|
||||
import com.isolaatti.sign_up.presentation.GetCodeViewModel
|
||||
import com.isolaatti.sign_up.presentation.SignUpViewModel
|
||||
import com.isolaatti.utils.Resource
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class GetCodeFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentGetCodeBinding
|
||||
private val errorViewModel: ErrorMessageViewModel by activityViewModels()
|
||||
private val viewModel: GetCodeViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
): View {
|
||||
binding = FragmentGetCodeBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupListeners()
|
||||
setupObservers()
|
||||
}
|
||||
|
||||
private fun retry() {
|
||||
// TODO retry here
|
||||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
binding.goToCodeButton.setOnClickListener {
|
||||
findNavController().navigate(SignUpNavigationDirections.actionGlobalValidateCodeFragment())
|
||||
}
|
||||
binding.backButton.setOnClickListener {
|
||||
requireActivity().finish()
|
||||
}
|
||||
binding.sendButton.setOnClickListener {
|
||||
binding.sendButton.isEnabled = false
|
||||
viewModel.getCode()
|
||||
}
|
||||
binding.textFieldEmail.editText?.doOnTextChanged { text, _, _, _ ->
|
||||
viewModel.email = text.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupObservers() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
errorViewModel.retry.collect {
|
||||
retry()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.emailIsValid.observe(viewLifecycleOwner) {
|
||||
binding.sendButton.isEnabled = it
|
||||
}
|
||||
viewModel.response.observe(viewLifecycleOwner) {
|
||||
binding.sendButton.isEnabled = true
|
||||
|
||||
when(it) {
|
||||
is Resource.Error -> {
|
||||
errorViewModel.error.postValue(it.errorType)
|
||||
viewModel.response.value = null
|
||||
}
|
||||
is Resource.Loading -> {
|
||||
viewModel.response.value = null
|
||||
}
|
||||
is Resource.Success -> {
|
||||
viewModel.response.value = null
|
||||
if(it.data == GetCodeResult.Success) {
|
||||
findNavController().navigate(GetCodeFragmentDirections.actionGetCodeFragmentToValidateCodeFragment())
|
||||
return@observe
|
||||
}
|
||||
showResultDialog(it.data!!)
|
||||
|
||||
}
|
||||
|
||||
null -> {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun showResultDialog(result: GetCodeResult) {
|
||||
val message = when(result) {
|
||||
GetCodeResult.EmailUsed -> R.string.email_used_when_getting_code
|
||||
GetCodeResult.EmailValidationError -> R.string.invalid_email
|
||||
GetCodeResult.CodesSentLimitReached -> R.string.codes_sent_limit_reached
|
||||
else -> 0
|
||||
}
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.accept, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,22 @@
|
||||
package com.isolaatti.sign_up.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.isolaatti.databinding.FragmentMakeAccountBinding
|
||||
|
||||
class MakeAccountFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentMakeAccountBinding
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentMakeAccountBinding.inflate(inflater)
|
||||
|
||||
return binding.root
|
||||
}
|
||||
}
|
||||
@ -3,12 +3,17 @@ package com.isolaatti.sign_up.ui
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import com.isolaatti.common.IsolaattiBaseActivity
|
||||
import com.isolaatti.databinding.ActivitySignUpBinding
|
||||
import com.isolaatti.sign_up.presentation.SignUpViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
class SignUpActivity : AppCompatActivity() {
|
||||
@AndroidEntryPoint
|
||||
class SignUpActivity : IsolaattiBaseActivity() {
|
||||
private lateinit var binding: ActivitySignUpBinding
|
||||
private val viewModel: SignUpViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@ -1,6 +1,126 @@
|
||||
package com.isolaatti.sign_up.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.isolaatti.R
|
||||
import com.isolaatti.common.ErrorMessageViewModel
|
||||
import com.isolaatti.databinding.FragmentValidateCodeBinding
|
||||
import com.isolaatti.sign_up.presentation.SignUpViewModel
|
||||
import com.isolaatti.sign_up.presentation.ValidateCodeViewModel
|
||||
import com.isolaatti.utils.Resource
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ValidateCodeFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentValidateCodeBinding
|
||||
private val activityViewModel: SignUpViewModel by activityViewModels()
|
||||
private val errorViewModel: ErrorMessageViewModel by activityViewModels()
|
||||
private val viewModel: ValidateCodeViewModel by viewModels()
|
||||
|
||||
private val loadingDialog: AlertDialog by lazy {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.loading)
|
||||
.show()
|
||||
}
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentValidateCodeBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupListeners()
|
||||
setupObservers()
|
||||
}
|
||||
|
||||
private fun retry() {
|
||||
// TODO retry here
|
||||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
binding.backButton.setOnClickListener {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
binding.textFieldCode.editText?.doOnTextChanged { text, _, _, _ ->
|
||||
viewModel.code = text.toString()
|
||||
}
|
||||
binding.acceptButton.setOnClickListener {
|
||||
viewModel.validateCode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupObservers() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
errorViewModel.retry.collect {
|
||||
retry()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.codeIsValid.observe(viewLifecycleOwner) {
|
||||
binding.acceptButton.isEnabled = it
|
||||
}
|
||||
viewModel.result.observe(viewLifecycleOwner) {
|
||||
when(it) {
|
||||
is Resource.Error -> {
|
||||
errorViewModel.error.postValue(it.errorType)
|
||||
}
|
||||
is Resource.Loading -> {
|
||||
showLoading(true)
|
||||
}
|
||||
is Resource.Success -> {
|
||||
showLoading(false)
|
||||
if(it.data!!) {
|
||||
viewModel.result.value = null
|
||||
|
||||
activityViewModel.code = viewModel.code
|
||||
findNavController().navigate(ValidateCodeFragmentDirections.actionValidateCodeFragmentToMakeAccountFragment())
|
||||
} else {
|
||||
showError()
|
||||
}
|
||||
}
|
||||
null -> {}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun showLoading(loading: Boolean) {
|
||||
binding.acceptButton.isEnabled = !loading
|
||||
binding.textFieldCode.isEnabled = !loading
|
||||
if(loading) {
|
||||
loadingDialog.show()
|
||||
} else {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showError() {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setMessage(R.string.invalid_code)
|
||||
.setPositiveButton(R.string.accept) {_,_ ->
|
||||
binding.acceptButton.isEnabled = true
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ package com.isolaatti.utils
|
||||
sealed class Resource<T> {
|
||||
class Success<T>(val data: T?): Resource<T>()
|
||||
class Loading<T>: Resource<T>()
|
||||
class Error<T>(val errorType: ErrorType? = null): Resource<T>() {
|
||||
class Error<T>(val errorType: ErrorType? = null, val message: String? = null): Resource<T>() {
|
||||
enum class ErrorType {
|
||||
NetworkError, AuthError, NotFoundError, ServerError, OtherError
|
||||
}
|
||||
|
||||
9
app/src/main/java/com/isolaatti/utils/Validators.kt
Normal file
9
app/src/main/java/com/isolaatti/utils/Validators.kt
Normal file
@ -0,0 +1,9 @@
|
||||
package com.isolaatti.utils
|
||||
|
||||
object Validators {
|
||||
fun isEmailValid(email: String): Boolean {
|
||||
val emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\$".toRegex()
|
||||
|
||||
return email.matches(emailRegex)
|
||||
}
|
||||
}
|
||||
@ -25,10 +25,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="24dp"
|
||||
android:fontFamily="@font/zen_dots_regular"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="?attr/textAppearanceHeadlineLarge" />
|
||||
style="@style/toolbar_text" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@ -20,20 +20,35 @@
|
||||
android:textAlignment="center"
|
||||
android:layout_marginTop="30dp"
|
||||
style="@style/toolbar_text"/>
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textSize="28sp"
|
||||
android:text="@string/sign_up"/>
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_arrow_back_24"
|
||||
style="?attr/materialIconButtonStyle" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textSize="28sp"
|
||||
android:lines="2"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/sign_up"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/get_code_info"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginHorizontal="16dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/goToCodeButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
@ -42,6 +57,7 @@
|
||||
style="@style/Widget.Material3.Button.TextButton"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textFieldEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/textInputOutlinedStyle"
|
||||
@ -54,6 +70,7 @@
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
|
||||
@ -1,6 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView 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">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/brand"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginTop="30dp"
|
||||
style="@style/toolbar_text"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textSize="28sp"
|
||||
android:lines="2"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/let_s_make_your_account"/>
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/textInputOutlinedStyle"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:hint="@string/unique_username">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textDisplayName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/textInputOutlinedStyle"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:hint="@string/display_name">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/create_a_password"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginHorizontal="16dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/textInputOutlinedStyle"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:hint="@string/password">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/before_making_your_account_please_read_these_legal_terms"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginHorizontal="16dp"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/readTermsAndConditions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/terms_and_conditions"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
style="@style/Widget.Material3.Button.TextButton"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/privacy_policy"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/privacy_policy"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="2dp"
|
||||
style="@style/Widget.Material3.Button.TextButton"/>
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:text="Go"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</ScrollView>
|
||||
@ -1,6 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/brand"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginTop="30dp"
|
||||
style="@style/toolbar_text"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
<Button
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/baseline_arrow_back_24"
|
||||
style="?attr/materialIconButtonStyle" />
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textSize="28sp"
|
||||
android:text="@string/enter_the_code_we_sent_you_by_email"/>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/code_extended_description"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginHorizontal="16dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textFieldCode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/textInputOutlinedStyle"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:hint="@string/code">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxLines="1" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/acceptButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accept"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -91,4 +91,23 @@
|
||||
<string name="get_code_info">The first step to create an account is to provide your email address. We will send a code that you will need to enter in the next step.</string>
|
||||
<string name="send">Send</string>
|
||||
<string name="already_have_a_code">Already have a code?</string>
|
||||
<string name="code">Code</string>
|
||||
<string name="code_extended_description">
|
||||
Your account is almost there, you just have to enter the code that we sent to your email.
|
||||
\n\n
|
||||
If you can\'t see it, check your spam folder. If you still can\'t see it, wait a few minutes for the email to arrive.
|
||||
</string>
|
||||
<string name="enter_the_code_we_sent_you_by_email">Enter the code we sent you by email</string>
|
||||
<string name="email_used_when_getting_code">The email address you want to use to create this account has already been used previously.</string>
|
||||
<string name="invalid_code">The code you entered is invalid. Some reasons may be that the code is misspelled or it has already expired.</string>
|
||||
<string name="invalid_email">Email is invalid</string>
|
||||
<string name="codes_sent_limit_reached">It is not possible to send more codes, you have reached the limit. Contact the administrator.</string>
|
||||
<string name="loading">Loading...</string>
|
||||
<string name="unique_username">Unique username</string>
|
||||
<string name="display_name">Display name</string>
|
||||
<string name="create_a_password">Create a fairly password</string>
|
||||
<string name="let_s_make_your_account">Let\'s make your account</string>
|
||||
<string name="before_making_your_account_please_read_these_legal_terms">Before making your account, please read and accept these legal terms.</string>
|
||||
<string name="terms_and_conditions">Terms and conditions</string>
|
||||
<string name="privacy_policy">Privacy policy</string>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user