For #4125: Migrate Sign in to Sync to Libstate
parent
65de521ccf
commit
faf0ecbcc0
@ -0,0 +1,62 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.settings.account
|
||||||
|
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.nav
|
||||||
|
|
||||||
|
interface AccountSettingsUserActions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever the "Sync now" button is tapped
|
||||||
|
*/
|
||||||
|
fun onSyncNow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever user sets a new device name
|
||||||
|
* @param newDeviceName the device name to change to
|
||||||
|
* @return Boolean indicating whether the new device name has been accepted or not
|
||||||
|
*/
|
||||||
|
fun onChangeDeviceName(newDeviceName: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called whenever the "Sign out" button is tapped
|
||||||
|
*/
|
||||||
|
fun onSignOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountSettingsInteractor(
|
||||||
|
private val navController: NavController,
|
||||||
|
private val syncNow: () -> Unit,
|
||||||
|
private val checkValidName: (String) -> Boolean,
|
||||||
|
private val setDeviceName: (String) -> Unit,
|
||||||
|
private val store: AccountSettingsStore
|
||||||
|
) : AccountSettingsUserActions {
|
||||||
|
|
||||||
|
override fun onSyncNow() {
|
||||||
|
syncNow.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChangeDeviceName(newDeviceName: String): Boolean {
|
||||||
|
val isValidName = checkValidName.invoke(newDeviceName)
|
||||||
|
if (!isValidName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Optimistically set the device name to what user requested.
|
||||||
|
store.dispatch(AccountSettingsAction.UpdateDeviceName(newDeviceName))
|
||||||
|
|
||||||
|
setDeviceName.invoke(newDeviceName)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSignOut() {
|
||||||
|
val directions = AccountSettingsFragmentDirections.actionAccountSettingsFragmentToSignOutFragment()
|
||||||
|
navController.nav(
|
||||||
|
R.id.accountSettingsFragment,
|
||||||
|
directions
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.settings.account
|
||||||
|
|
||||||
|
import mozilla.components.lib.state.Action
|
||||||
|
import mozilla.components.lib.state.State
|
||||||
|
import mozilla.components.lib.state.Store
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [Store] for holding the [AccountSettingsState] and applying [AccountAction]s.
|
||||||
|
*/
|
||||||
|
class AccountSettingsStore(
|
||||||
|
initialState: AccountSettingsState
|
||||||
|
) : Store<AccountSettingsState, AccountSettingsAction>(
|
||||||
|
initialState,
|
||||||
|
::accountStateReducer
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class LastSyncTime {
|
||||||
|
object Never : LastSyncTime()
|
||||||
|
data class Failed(val lastSync: Long) : LastSyncTime()
|
||||||
|
data class Success(val lastSync: Long) : LastSyncTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The state for the Account Settings Screen
|
||||||
|
*/
|
||||||
|
data class AccountSettingsState(
|
||||||
|
val lastSyncedDate: LastSyncTime,
|
||||||
|
val deviceName: String
|
||||||
|
) : State
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions to dispatch through the `SearchStore` to modify `SearchState` through the reducer.
|
||||||
|
*/
|
||||||
|
sealed class AccountSettingsAction : Action {
|
||||||
|
data class SyncFailed(val time: Long) : AccountSettingsAction()
|
||||||
|
data class SyncEnded(val time: Long) : AccountSettingsAction()
|
||||||
|
data class UpdateDeviceName(val name: String) : AccountSettingsAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SearchState Reducer.
|
||||||
|
*/
|
||||||
|
fun accountStateReducer(state: AccountSettingsState, action: AccountSettingsAction): AccountSettingsState {
|
||||||
|
return when (action) {
|
||||||
|
is AccountSettingsAction.SyncFailed -> state.copy(lastSyncedDate = LastSyncTime.Failed(action.time))
|
||||||
|
is AccountSettingsAction.SyncEnded -> state.copy(lastSyncedDate = LastSyncTime.Success(action.time))
|
||||||
|
is AccountSettingsAction.UpdateDeviceName -> state.copy(deviceName = action.name)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.settings
|
||||||
|
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavDestination
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.settings.account.AccountSettingsAction
|
||||||
|
import org.mozilla.fenix.settings.account.AccountSettingsFragmentDirections
|
||||||
|
import org.mozilla.fenix.settings.account.AccountSettingsInteractor
|
||||||
|
import org.mozilla.fenix.settings.account.AccountSettingsStore
|
||||||
|
|
||||||
|
class AccountSettingsInteractorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onSyncNow() {
|
||||||
|
var ranSyncNow = false
|
||||||
|
|
||||||
|
val interactor = AccountSettingsInteractor(
|
||||||
|
mockk(),
|
||||||
|
{ ranSyncNow = true },
|
||||||
|
mockk(),
|
||||||
|
mockk(),
|
||||||
|
mockk()
|
||||||
|
)
|
||||||
|
|
||||||
|
interactor.onSyncNow()
|
||||||
|
|
||||||
|
assertEquals(ranSyncNow, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onChangeDeviceName() {
|
||||||
|
val store: AccountSettingsStore = mockk(relaxed = true)
|
||||||
|
|
||||||
|
val interactor = AccountSettingsInteractor(
|
||||||
|
mockk(),
|
||||||
|
mockk(),
|
||||||
|
{ true },
|
||||||
|
{},
|
||||||
|
store
|
||||||
|
)
|
||||||
|
|
||||||
|
interactor.onChangeDeviceName("New Name")
|
||||||
|
|
||||||
|
verify { store.dispatch(AccountSettingsAction.UpdateDeviceName("New Name")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onSignOut() {
|
||||||
|
val navController: NavController = mockk(relaxed = true)
|
||||||
|
every { navController.currentDestination } returns NavDestination("").apply { id = R.id.accountSettingsFragment }
|
||||||
|
|
||||||
|
val interactor = AccountSettingsInteractor(
|
||||||
|
navController,
|
||||||
|
mockk(),
|
||||||
|
mockk(),
|
||||||
|
mockk(),
|
||||||
|
mockk()
|
||||||
|
)
|
||||||
|
|
||||||
|
interactor.onSignOut()
|
||||||
|
|
||||||
|
verify {
|
||||||
|
navController.navigate(AccountSettingsFragmentDirections.actionAccountSettingsFragmentToSignOutFragment())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue