Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions app/src/main/java/one/mixin/android/ui/landing/LandingActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,25 @@ class LandingActivity : BaseActivity() {
SystemUIManager.setSafePadding(window, color = colorFromAttribute(R.attr.bg_white), imePadding = true)
checkVersion()
setContentView(binding.root)
val pin = intent.getStringExtra(ARGS_PIN)
val from = intent.getIntExtra(ARGS_FROM, -1)
val phoneNumber = intent.getStringExtra(ARGS_PHONE_NUM)
val fragment =
if (pin != null) {
MobileFragment.newInstance(pin, FROM_CHANGE_PHONE_ACCOUNT)
} else if (from == FROM_CHANGE_PHONE_ACCOUNT) {
MobileFragment.newInstance(from = FROM_CHANGE_PHONE_ACCOUNT)
} else if (from == FROM_VERIFY_MOBILE_REMINDER) {
MobileFragment.newInstance(from = FROM_VERIFY_MOBILE_REMINDER, phoneNumber = phoneNumber)
} else {
lifecycleScope.launch(Dispatchers.IO) {
jobManager.clear()
if (shouldInitializeLanding(savedInstanceState != null)) {
val pin = intent.getStringExtra(ARGS_PIN)
val from = intent.getIntExtra(ARGS_FROM, -1)
val phoneNumber = intent.getStringExtra(ARGS_PHONE_NUM)
val fragment =
if (pin != null) {
MobileFragment.newInstance(pin, FROM_CHANGE_PHONE_ACCOUNT)
} else if (from == FROM_CHANGE_PHONE_ACCOUNT) {
MobileFragment.newInstance(from = FROM_CHANGE_PHONE_ACCOUNT)
} else if (from == FROM_VERIFY_MOBILE_REMINDER) {
MobileFragment.newInstance(from = FROM_VERIFY_MOBILE_REMINDER, phoneNumber = phoneNumber)
} else {
lifecycleScope.launch(Dispatchers.IO) {
jobManager.clear()
}
LandingFragment.newInstance()
}
LandingFragment.newInstance()
}
replaceFragment(fragment, R.id.container)
replaceFragment(fragment, R.id.container)
}
}

private fun checkVersion(){
Expand All @@ -93,3 +95,5 @@ class LandingActivity : BaseActivity() {
}
}
}

internal fun shouldInitializeLanding(hasSavedInstanceState: Boolean) = !hasSavedInstanceState
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) {
const val ARGS_MNEMONIC_PHRASE = "mnemonic_phrase"
private const val ARGS_PENDING_IMPORT_MNEMONIC = "pending_import_mnemonic"
private const val ARGS_PASTED_MNEMONIC = "pasted_mnemonic"
private const val STATE_ERROR_INFO = "error_info"
private const val STATE_REQUEST_FAILED = "request_failed"

fun newInstance(
words: ArrayList<String>? = null,
Expand Down Expand Up @@ -129,12 +131,27 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) {
LogViewerBottomSheet.newInstance().showNow(parentFragmentManager, LogViewerBottomSheet.TAG)
true
}
errorInfo = savedInstanceState?.getString(STATE_ERROR_INFO)
val restoredRequestFailed = savedInstanceState?.getBoolean(STATE_REQUEST_FAILED) == true
binding.compose.setContent {
MnemonicPhrasePage(!words.isNullOrEmpty(), errorInfo) {
anonymousRequest(words)
}
}
anonymousRequest(words)
if (shouldRequestAnonymousLogin(restoredRequestFailed)) {
anonymousRequest(words)
} else {
landingViewModel.updateMnemonicPhraseState(MnemonicPhraseState.Failure)
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
errorInfo?.let { outState.putString(STATE_ERROR_INFO, it) }
outState.putBoolean(
STATE_REQUEST_FAILED,
landingViewModel.mnemonicPhraseState.value == MnemonicPhraseState.Failure,
)
}

private fun applySafeTopPadding(rootView: View) {
Expand Down Expand Up @@ -476,3 +493,5 @@ class MnemonicPhraseFragment : BaseFragment(R.layout.fragment_compose) {
}
}
}

internal fun shouldRequestAnonymousLogin(restoredRequestFailed: Boolean) = !restoredRequestFailed
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package one.mixin.android.ui.landing

import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class LandingActivityStateRestorationTest {
@Test
fun `initializes landing content on first creation`() {
assertTrue(shouldInitializeLanding(hasSavedInstanceState = false))
}

@Test
fun `keeps restored fragment stack after recreation`() {
assertFalse(shouldInitializeLanding(hasSavedInstanceState = true))
}

@Test
fun `preserves captcha failure without an error message`() {
assertFalse(shouldRequestAnonymousLogin(restoredRequestFailed = true))
}

@Test
fun `starts anonymous login when no failure was restored`() {
assertTrue(shouldRequestAnonymousLogin(restoredRequestFailed = false))
}
}