From 28dd1f8dd383d2f67b41c927f652c0183cfff2fc Mon Sep 17 00:00:00 2001 From: Isidro Henoch Date: Mon, 6 Dec 2021 01:04:55 -0600 Subject: WIP: Implements the Login functionality - Adds multiple android dependencies, for DI and some utilities - Updates colors and styles - Adds an Application - Adds the Login Fragment and ViewModel --- .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 30 +++++++++ .../TrackerMap/android/session/LoginActivity.kt | 14 ++++ .../TrackerMap/android/session/LoginFragment.kt | 76 ++++++++++++++++++++++ .../TrackerMap/android/session/LoginViewModel.kt | 57 ++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt (limited to 'androidApp/src/main/java') diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt new file mode 100644 index 0000000..a8efbf2 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -0,0 +1,30 @@ +package mx.trackermap.TrackerMap.android + +import android.app.Application +import mx.trackermap.TrackerMap.android.session.LoginViewModel +import mx.trackermap.TrackerMap.client.apis.SessionApi +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.core.context.startKoin +import org.koin.core.logger.Level +import org.koin.dsl.module + +class TrackerApp: Application() { + override fun onCreate() { + super.onCreate() + + val appModule = module { + single { "https://etbsa.net/api/" } + single { SessionApi(get()) } + + viewModel { LoginViewModel(get(), get()) } + } + + startKoin { + androidLogger(Level.ERROR) + androidContext(this@TrackerApp) + modules(appModule) + } + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt new file mode 100644 index 0000000..3aec7b8 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginActivity.kt @@ -0,0 +1,14 @@ +package mx.trackermap.TrackerMap.android.session + +import android.os.Bundle +import android.os.PersistableBundle +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import mx.trackermap.TrackerMap.android.R + +class LoginActivity: AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.login_activity) + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt new file mode 100644 index 0000000..5039a7c --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt @@ -0,0 +1,76 @@ +package mx.trackermap.TrackerMap.android.session + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.core.widget.doAfterTextChanged +import androidx.fragment.app.Fragment +import com.zhuinden.liveevent.observe +import mx.trackermap.TrackerMap.android.databinding.LoginBinding +import org.koin.androidx.viewmodel.ext.android.viewModel + +class LoginFragment : Fragment() { + + private var _binding: LoginBinding? = null + private val binding get() = _binding!! + private val loginViewModel: LoginViewModel by viewModel() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = LoginBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupEvents() + setupObservers() + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun setupEvents() { + binding.usernameEditText.doAfterTextChanged { + loginViewModel.email.value = it.toString() + } + binding.passwordEditText.doAfterTextChanged { + loginViewModel.password.value = it.toString() + } + binding.signinButton.setOnClickListener { + loginViewModel.login() + } + } + + private fun setupObservers() { + loginViewModel.loginResult.observe(this) { result -> + Log.d("LoginFragment", result.toString()) + when (result) { + LoginViewModel.LoginResult.Loading -> { + Toast.makeText(context, "Loading...", Toast.LENGTH_SHORT).show() + } + LoginViewModel.LoginResult.EmailMissing -> { + Toast.makeText(context, "Email is missing", Toast.LENGTH_SHORT).show() + } + LoginViewModel.LoginResult.PasswordMissing -> { + Toast.makeText(context, "Password is missing", Toast.LENGTH_SHORT).show() + } + LoginViewModel.LoginResult.Failure -> { + Toast.makeText(context, "Failed login", Toast.LENGTH_SHORT).show() + } + LoginViewModel.LoginResult.Success -> { + Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show() + } + } + } + } +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt new file mode 100644 index 0000000..9df78aa --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginViewModel.kt @@ -0,0 +1,57 @@ +package mx.trackermap.TrackerMap.android.session + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.zhuinden.eventemitter.EventEmitter +import com.zhuinden.eventemitter.EventSource +import kotlinx.coroutines.launch +import mx.trackermap.TrackerMap.client.apis.SessionApi + +class LoginViewModel( + private val sessionApi: SessionApi, + savedStateHandle: SavedStateHandle +) : ViewModel() { + + sealed class LoginResult { + object Loading: LoginResult() + object EmailMissing : LoginResult() + object PasswordMissing : LoginResult() + object Failure : LoginResult() + object Success : LoginResult() + } + + val email: MutableLiveData = savedStateHandle.getLiveData("user", "") + val password: MutableLiveData = savedStateHandle.getLiveData("password", "") + + private val loginResultEmitter = EventEmitter() + val loginResult: EventSource = loginResultEmitter + + fun login() { + val email = email.value!!.toString().trim() + val password = password.value!!.toString().trim() + + if (email.isEmpty()) { + loginResultEmitter.emit(LoginResult.EmailMissing) + return + } + + if (password.isEmpty()) { + loginResultEmitter.emit(LoginResult.PasswordMissing) + return + } + + loginResultEmitter.emit(LoginResult.Loading) + viewModelScope.launch { + try { + val user = sessionApi.sessionPost(email, password) + Log.d("LoginViewModel", user.toString()) + loginResultEmitter.emit(LoginResult.Success) + } catch (e: Exception) { + loginResultEmitter.emit(LoginResult.Failure) + } + } + } +} \ No newline at end of file -- cgit v1.2.3