/* * Copyright (C) 2020 Conny Duck * * This file is part of Pixelcat. * * Pixelcat is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pixelcat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package at.connyduck.pixelcat.components.login import android.app.Activity import android.content.Context import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.ViewGroup import androidx.activity.viewModels import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat.Type.systemBars import androidx.lifecycle.lifecycleScope import at.connyduck.pixelcat.R import at.connyduck.pixelcat.components.about.AboutActivity import at.connyduck.pixelcat.components.general.BaseActivity import at.connyduck.pixelcat.components.main.MainActivity import at.connyduck.pixelcat.components.settings.SettingsActivity import at.connyduck.pixelcat.components.util.extension.visible import at.connyduck.pixelcat.dagger.ViewModelFactory import at.connyduck.pixelcat.databinding.ActivityLoginBinding import at.connyduck.pixelcat.util.viewBinding import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import javax.inject.Inject @FlowPreview @ExperimentalCoroutinesApi class LoginActivity : BaseActivity() { @Inject lateinit var viewModelFactory: ViewModelFactory private val viewModel: LoginViewModel by viewModels { viewModelFactory } private val binding by viewBinding(ActivityLoginBinding::inflate) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets -> val top = insets.getInsets(systemBars()).top val toolbarParams = binding.loginToolbar.layoutParams as ViewGroup.MarginLayoutParams toolbarParams.topMargin = top WindowInsetsCompat.CONSUMED } setSupportActionBar(binding.loginToolbar) supportActionBar?.run { setDisplayShowTitleEnabled(false) } lifecycleScope.launch { viewModel.observe().collect { loginModel -> onChanged(loginModel) } } binding.loginButton.setOnClickListener { viewModel.startLogin(binding.loginInput.text.toString()) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { val authCode = data?.getStringExtra(LoginWebViewActivity.RESULT_AUTHORIZATION_CODE) if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK && !authCode.isNullOrEmpty()) { viewModel.authCode(authCode) return } super.onActivityResult(requestCode, resultCode, data) } override fun onStart() { super.onStart() if (!intent.hasExtra(LoginWebViewActivity.RESULT_AUTHORIZATION_CODE)) { viewModel.removeError() } } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.login, menu) return super.onCreateOptionsMenu(menu) } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.navigation_settings -> { startActivity(SettingsActivity.newIntent(this)) return true } R.id.navigation_info -> { startActivity(AboutActivity.newIntent(this)) return true } } return super.onOptionsItemSelected(item) } private fun onChanged(loginModel: LoginModel?) { binding.loginInput.setText(loginModel?.input) if (loginModel == null) { return } when (loginModel.state) { LoginState.NO_ERROR -> { binding.loginInputLayout.error = null setLoading(false) } LoginState.AUTH_ERROR -> { binding.loginInputLayout.error = "auth error" setLoading(false) } LoginState.INVALID_DOMAIN -> { binding.loginInputLayout.error = "invalid domain" setLoading(false) } LoginState.NETWORK_ERROR -> { binding.loginInputLayout.error = "network error" setLoading(false) } LoginState.LOADING -> { setLoading(true) } LoginState.SUCCESS -> { setLoading(true) startActivityForResult(LoginWebViewActivity.newIntent(loginModel.domain!!, loginModel.clientId!!, loginModel.clientSecret!!, this), REQUEST_CODE) } LoginState.SUCCESS_FINAL -> { setLoading(true) startActivity(MainActivity.newIntent(this)) finish() } } } private fun setLoading(loading: Boolean) { binding.loginLoading.visible = loading binding.loginImageView.visible = !loading binding.loginInputLayout.visible = !loading binding.loginButton.visible = !loading } companion object { private const val REQUEST_CODE = 14 fun newIntent(context: Context) = Intent(context, LoginActivity::class.java) } }