Update the onboarding process to support crunchyroll

* only save credentials during onboarding, if login was successful
* show onboarding, if login failed
This commit is contained in:
Jannik 2022-01-08 19:20:21 +01:00
parent 349a0e451a
commit e98e75456e
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
8 changed files with 68 additions and 61 deletions

View File

@ -38,6 +38,14 @@ object Crunchyroll {
private val browsingCache = arrayListOf<Item>()
/**
* Login to the crunchyroll API.
*
* @param username The Username/Email of the user to log in
* @param password The Accounts Password
*
* @return Boolean: True if login was successful, else false
*/
fun login(username: String, password: String): Boolean = runBlocking {
val tokenEndpoint = "/auth/v1/token"
val formData = listOf(
@ -47,6 +55,7 @@ object Crunchyroll {
"scope" to "offline_access"
)
var success: Boolean // is false
withContext(Dispatchers.IO) {
val (request, response, result) = Fuel.post("$baseUrl$tokenEndpoint", parameters = formData)
.header("Content-Type", "application/x-www-form-urlencoded")
@ -67,11 +76,10 @@ object Crunchyroll {
// println("response: $result")
Log.i(javaClass.name, "login complete with code ${response.statusCode}")
return@withContext response.statusCode == 200
success = (response.statusCode == 200)
}
return@runBlocking false
return@runBlocking success
}
/**

View File

@ -52,7 +52,6 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
private var activeBaseFragment: Fragment = HomeFragment() // the currently active fragment, home at the start
companion object {
var wasInitialized = false
lateinit var instance: MainActivity
}
@ -63,7 +62,7 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!wasInitialized) { load() }
load() // start the initial loading
theme.applyStyle(getThemeResource(), true)
binding = ActivityMainBinding.inflate(layoutInflater)
@ -132,47 +131,27 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
*/
private fun load() {
val time = measureTimeMillis {
// start the initial loading
// load all saved stuff here
Preferences.load(this)
EncryptedPreferences.readCredentials(this)
// show onboarding TODO rework
if (EncryptedPreferences.password.isEmpty()) {
// show onboarding if no password is set, or login fails
if (EncryptedPreferences.password.isEmpty() || !Crunchyroll.login(
EncryptedPreferences.login,
EncryptedPreferences.password
)
) {
showOnboarding()
} else {
Crunchyroll.login(EncryptedPreferences.login, EncryptedPreferences.password)
runBlocking { initCrunchyroll().joinAll() }
}
// if (EncryptedPreferences.password.isEmpty()) {
// showOnboarding()
// } else {
// try {
// if (!AoDParser.login()) {
// showLoginDialog()
// }
// } catch (ex: SocketTimeoutException) {
// Log.w(javaClass.name, "Timeout during login!")
//
// // show waring dialog before finishing
// MaterialDialog(this).show {
// title(R.string.dialog_timeout_head)
// message(R.string.dialog_timeout_desc)
// onDismiss { exitAndRemoveTask() }
// }
// }
// }
// runBlocking { loadingJob.await() } // wait for initial loading to finish
}
Log.i(javaClass.name, "loading and login in $time ms")
wasInitialized = true
Log.i(javaClass.name, "loading in $time ms")
}
private fun initCrunchyroll(): List<Job> {
println("init")
val scope = CoroutineScope(Dispatchers.IO + CoroutineName("InitialLoadingScope"))
return listOf(
scope.launch { Crunchyroll.index() },

View File

@ -4,16 +4,18 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*
import org.mosad.teapod.R
import org.mosad.teapod.databinding.FragmentOnLoginBinding
import org.mosad.teapod.parser.crunchyroll.Crunchyroll
import org.mosad.teapod.preferences.EncryptedPreferences
class OnLoginFragment: Fragment() {
private lateinit var binding: FragmentOnLoginBinding
private var loginJob: Job? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FragmentOnLoginBinding.inflate(inflater, container, false)
@ -27,26 +29,41 @@ class OnLoginFragment: Fragment() {
private fun initActions() {
binding.buttonLogin.setOnClickListener {
// get login credentials from gui
val email = binding.editTextLogin.text.toString()
val password = binding.editTextPassword.text.toString()
onLogin()
}
EncryptedPreferences.saveCredentials(email, password, requireContext()) // save the credentials
binding.editTextPassword.setOnEditorActionListener { _, actionId, _ ->
return@setOnEditorActionListener when (actionId) {
EditorInfo.IME_ACTION_DONE -> {
onLogin()
false // false will hide the keyboards
}
else -> false
}
}
binding.buttonLogin.isClickable = false
loginJob = lifecycleScope.launch {
// TODO
// if (AoDParser.login()) {
// // if login was successful, switch to main
// if (activity is OnboardingActivity) {
// (activity as OnboardingActivity).launchMainActivity()
// }
// } else {
// withContext(Dispatchers.Main) {
// binding.textLoginDesc.text = getString(R.string.on_login_failed)
// binding.buttonLogin.isClickable = true
// }
// }
}
private fun onLogin() {
// get login credentials from gui
val email = binding.editTextLogin.text.toString()
val password = binding.editTextPassword.text.toString()
binding.buttonLogin.isClickable = false
// FIXME, this seems to run blocking
lifecycleScope.launch {
// try login credentials
val login = Crunchyroll.login(email, password)
if (login) {
// save the credentials and show the main activity
EncryptedPreferences.saveCredentials(email, password, requireContext())
if (activity is OnboardingActivity) (activity as OnboardingActivity).launchMainActivity()
} else {
withContext(Dispatchers.Main) {
binding.textLoginDesc.text = getString(R.string.on_login_failed)
binding.buttonLogin.isClickable = true
}
}
}
}

View File

@ -16,7 +16,7 @@ class OnboardingActivity : AppCompatActivity() {
private lateinit var binding: ActivityOnboardingBinding
private lateinit var pagerAdapter: FragmentStateAdapter
private val fragments = arrayOf(OnLoginFragment())
private val fragments = arrayOf(OnWelcomeFragment(), OnLoginFragment())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@ -65,6 +65,7 @@
android:layout_margin="7dp"
android:ems="10"
android:hint="@string/password"
android:imeOptions="actionDone"
android:importantForAutofill="no"
android:inputType="textPassword" />

View File

@ -38,7 +38,7 @@
android:id="@+id/text_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:text="@string/on_welcome_heading"
android:textAlignment="center"
android:textSize="26sp"
android:textStyle="bold" />

View File

@ -58,7 +58,7 @@
<string name="authors">Autor</string>
<string name="source">Quellcode</string>
<string name="license">Lizenz</string>
<string name="about_info">Eine inoffizielle App für Anime on Demand.</string>
<string name="about_info">Eine inoffizielle App für Crunchyroll.</string>
<string name="third_party_heading">Lizenzen von Drittanbietern</string>
<string name="third_party_component_desc">© %1$s %2$s unter %3$s</string>
<string name="dev_settings_enabled">Du bist jetzt ein Entwickler</string>
@ -81,10 +81,11 @@
<string name="skip">Überspringen</string>
<string name="next">Weiter</string>
<string name="start">Fertig</string>
<string name="on_welcome">Willkommen!\nTeapod ist eine inoffizielle App für AoD.</string>
<string name="on_welcome_heading">Willkommen</string>
<string name="on_welcome">Teapod ist eine inoffizielle App für Crunchyroll, die unter den Bedingungen der GPL 3 lizenziert ist.\n\nHinweis: Die Benutzung von Teapod kann gegen die Nutzungsbedingungen von Crunchyroll verstoßen.</string>
<string name="on_get_started">Los geht\'s</string>
<string name="on_login_heading">Login</string>
<string name="on_login_desc">Um Teapod verwenden zu können musst du dich mit deinem AoD Account anmelden. Deine Login-Daten werden verschlüsselt auf deinem Gerät gespeichert.</string>
<string name="on_login_desc">Um Teapod verwenden zu können musst du dich mit deinem Crunchyroll Account anmelden. Deine Login-Daten werden verschlüsselt auf deinem Gerät gespeichert.</string>
<string name="on_login_failed">Login nicht erfolgreich! Stelle sicher das deine Login-Daten korrekt sind und versuche es erneut.</string>
<!-- dialogs -->

View File

@ -74,7 +74,7 @@
<string name="teapod_repo" translatable="false">git.mosad.xyz/Seil0/teapod</string>
<string name="license">License</string>
<string name="license_desc" translatable="false">GNU General Public License 3</string>
<string name="about_info">An unofficial app for anime on demand.</string>
<string name="about_info">An unofficial app for Crunchyroll.</string>
<string name="tmdb_notice" translatable="false">This product uses the TMDb API but is not endorsed or certified by TMDb.</string>
<string name="third_party_heading">Third Party Licenses</string>
<string name="third_party_component_desc">© %1$s %2$s under %3$s</string>
@ -102,10 +102,11 @@
<string name="skip">Skip</string>
<string name="next">Next</string>
<string name="start">Start</string>
<string name="on_welcome">Welcome!\nTeapod is an unofficial App for AoD.</string>
<string name="on_welcome_heading">Welcome</string>
<string name="on_welcome">Teapod is an unofficial app for Crunchyroll, licensed under the terms and conditions of GPL 3.\n\nPlease note: Using Teapod may violate the ToS of Crunchyroll.</string>
<string name="on_get_started">Get started</string>
<string name="on_login_heading">Login</string>
<string name="on_login_desc">To use Teapod you need to log in with your AoD account. Your Login-Data will be stored encrypted on your device.</string>
<string name="on_login_desc">To use Teapod you have to log in with your Crunchyroll account. Your login data will be stored encrypted on your device.</string>
<string name="on_login_failed">Could not login! Make sure Username and Password are correct and try again.</string>
<!-- dialogs -->