Add Init action + corresponding initialized event
This commit is contained in:
parent
e437c9e131
commit
fd85ad0f1b
|
@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.rename
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
|
||||||
sealed class RenameSessionAction : VectorViewModelAction {
|
sealed class RenameSessionAction : VectorViewModelAction {
|
||||||
|
object InitWithLastEditedName : RenameSessionAction()
|
||||||
object SaveModifications : RenameSessionAction()
|
object SaveModifications : RenameSessionAction()
|
||||||
data class EditLocally(val editedName: String) : RenameSessionAction()
|
data class EditLocally(val editedName: String) : RenameSessionAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,6 @@ class RenameSessionFragment :
|
||||||
|
|
||||||
@Inject lateinit var viewNavigator: RenameSessionViewNavigator
|
@Inject lateinit var viewNavigator: RenameSessionViewNavigator
|
||||||
|
|
||||||
private var renameEditTextInitialized = false
|
|
||||||
|
|
||||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionRenameBinding {
|
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionRenameBinding {
|
||||||
return FragmentSessionRenameBinding.inflate(inflater, container, false)
|
return FragmentSessionRenameBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
@ -52,6 +50,7 @@ class RenameSessionFragment :
|
||||||
initToolbar()
|
initToolbar()
|
||||||
initEditText()
|
initEditText()
|
||||||
initSaveButton()
|
initSaveButton()
|
||||||
|
initWithLastEditedName()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initToolbar() {
|
private fun initToolbar() {
|
||||||
|
@ -72,9 +71,17 @@ class RenameSessionFragment :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initWithLastEditedName() {
|
||||||
|
viewModel.handle(RenameSessionAction.InitWithLastEditedName)
|
||||||
|
}
|
||||||
|
|
||||||
private fun observeViewEvents() {
|
private fun observeViewEvents() {
|
||||||
viewModel.observeViewEvents {
|
viewModel.observeViewEvents {
|
||||||
when (it) {
|
when (it) {
|
||||||
|
is RenameSessionViewEvent.Initialized -> {
|
||||||
|
views.renameSessionEditText.setText(it.deviceName)
|
||||||
|
views.renameSessionEditText.setSelection(views.renameSessionEditText.length())
|
||||||
|
}
|
||||||
is RenameSessionViewEvent.SessionRenamed -> {
|
is RenameSessionViewEvent.SessionRenamed -> {
|
||||||
viewNavigator.goBack(requireActivity())
|
viewNavigator.goBack(requireActivity())
|
||||||
}
|
}
|
||||||
|
@ -86,11 +93,6 @@ class RenameSessionFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun invalidate() = withState(viewModel) { state ->
|
override fun invalidate() = withState(viewModel) { state ->
|
||||||
if (renameEditTextInitialized.not()) {
|
|
||||||
views.renameSessionEditText.setText(state.editedDeviceName)
|
|
||||||
views.renameSessionEditText.setSelection(views.renameSessionEditText.length())
|
|
||||||
renameEditTextInitialized = true
|
|
||||||
}
|
|
||||||
views.renameSessionSave.isEnabled = state.editedDeviceName.isNotEmpty()
|
views.renameSessionSave.isEnabled = state.editedDeviceName.isNotEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ package im.vector.app.features.settings.devices.v2.rename
|
||||||
import im.vector.app.core.platform.VectorViewEvents
|
import im.vector.app.core.platform.VectorViewEvents
|
||||||
|
|
||||||
sealed class RenameSessionViewEvent : VectorViewEvents {
|
sealed class RenameSessionViewEvent : VectorViewEvents {
|
||||||
|
data class Initialized(val deviceName: String) : RenameSessionViewEvent()
|
||||||
object SessionRenamed : RenameSessionViewEvent()
|
object SessionRenamed : RenameSessionViewEvent()
|
||||||
data class Failure(val throwable: Throwable) : RenameSessionViewEvent()
|
data class Failure(val throwable: Throwable) : RenameSessionViewEvent()
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings.devices.v2.rename
|
package im.vector.app.features.settings.devices.v2.rename
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
@ -24,8 +25,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase
|
import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class RenameSessionViewModel @AssistedInject constructor(
|
class RenameSessionViewModel @AssistedInject constructor(
|
||||||
|
@ -41,23 +41,41 @@ class RenameSessionViewModel @AssistedInject constructor(
|
||||||
override fun create(initialState: RenameSessionViewState): RenameSessionViewModel
|
override fun create(initialState: RenameSessionViewState): RenameSessionViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
@VisibleForTesting
|
||||||
observeSessionInfo(initialState.deviceId)
|
var hasRetrievedOriginalDeviceName = false
|
||||||
}
|
|
||||||
|
|
||||||
private fun observeSessionInfo(deviceId: String) {
|
|
||||||
getDeviceFullInfoUseCase.execute(deviceId)
|
|
||||||
.onEach { setState { copy(editedDeviceName = it.deviceInfo.displayName.orEmpty()) } }
|
|
||||||
.launchIn(viewModelScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handle(action: RenameSessionAction) {
|
override fun handle(action: RenameSessionAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
|
is RenameSessionAction.InitWithLastEditedName -> handleInitWithLastEditedName()
|
||||||
is RenameSessionAction.EditLocally -> handleEditLocally(action.editedName)
|
is RenameSessionAction.EditLocally -> handleEditLocally(action.editedName)
|
||||||
is RenameSessionAction.SaveModifications -> handleSaveModifications()
|
is RenameSessionAction.SaveModifications -> handleSaveModifications()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleInitWithLastEditedName() = withState { state ->
|
||||||
|
if (hasRetrievedOriginalDeviceName) {
|
||||||
|
postInitEvent()
|
||||||
|
} else {
|
||||||
|
hasRetrievedOriginalDeviceName = true
|
||||||
|
viewModelScope.launch {
|
||||||
|
setStateWithOriginalDeviceName(state.deviceId)
|
||||||
|
postInitEvent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun setStateWithOriginalDeviceName(deviceId: String) {
|
||||||
|
getDeviceFullInfoUseCase.execute(deviceId)
|
||||||
|
.firstOrNull()
|
||||||
|
?.let { deviceFullInfo ->
|
||||||
|
setState { copy(editedDeviceName = deviceFullInfo.deviceInfo.displayName.orEmpty()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun postInitEvent() = withState { state ->
|
||||||
|
_viewEvents.post(RenameSessionViewEvent.Initialized(state.editedDeviceName))
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleEditLocally(editedName: String) {
|
private fun handleEditLocally(editedName: String) {
|
||||||
setState { copy(editedDeviceName = editedName) }
|
setState { copy(editedDeviceName = editedName) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,38 +51,72 @@ class RenameSessionViewModelTest {
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given the viewModel has been initialized then viewState is updated with current session name`() {
|
fun `given the original device name has not been retrieved when handling init with last edited name action then view state and view events are updated`() {
|
||||||
// Given
|
// Given
|
||||||
givenSessionWithName(A_SESSION_NAME)
|
givenSessionWithName(A_SESSION_NAME)
|
||||||
|
val action = RenameSessionAction.InitWithLastEditedName
|
||||||
val expectedState = RenameSessionViewState(
|
val expectedState = RenameSessionViewState(
|
||||||
deviceId = A_SESSION_ID,
|
deviceId = A_SESSION_ID,
|
||||||
editedDeviceName = A_SESSION_NAME,
|
editedDeviceName = A_SESSION_NAME,
|
||||||
)
|
)
|
||||||
|
val expectedEvent = RenameSessionViewEvent.Initialized(
|
||||||
|
deviceName = A_SESSION_NAME,
|
||||||
|
)
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
viewModel.hasRetrievedOriginalDeviceName = false
|
||||||
|
|
||||||
// When
|
// When
|
||||||
val viewModel = createViewModel()
|
val viewModelTest = viewModel.test()
|
||||||
|
viewModel.handle(action)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
viewModel.test()
|
viewModelTest.assertLatestState { state -> state == expectedState }
|
||||||
.assertLatestState { state -> state == expectedState }
|
.assertEvent { event -> event == expectedEvent }
|
||||||
.finish()
|
.finish()
|
||||||
verify {
|
verify {
|
||||||
getDeviceFullInfoUseCase.execute(A_SESSION_ID)
|
getDeviceFullInfoUseCase.execute(A_SESSION_ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given the original device name has been retrieved when handling init with last edited name action then view state and view events are updated`() {
|
||||||
|
// Given
|
||||||
|
val action = RenameSessionAction.InitWithLastEditedName
|
||||||
|
val expectedState = RenameSessionViewState(
|
||||||
|
deviceId = A_SESSION_ID,
|
||||||
|
editedDeviceName = AN_EDITED_SESSION_NAME,
|
||||||
|
)
|
||||||
|
val expectedEvent = RenameSessionViewEvent.Initialized(
|
||||||
|
deviceName = AN_EDITED_SESSION_NAME,
|
||||||
|
)
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
viewModel.handle(RenameSessionAction.EditLocally(AN_EDITED_SESSION_NAME))
|
||||||
|
viewModel.hasRetrievedOriginalDeviceName = true
|
||||||
|
|
||||||
|
// When
|
||||||
|
val viewModelTest = viewModel.test()
|
||||||
|
viewModel.handle(action)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
viewModelTest.assertLatestState { state -> state == expectedState }
|
||||||
|
.assertEvent { event -> event == expectedEvent }
|
||||||
|
.finish()
|
||||||
|
verify(inverse = true) {
|
||||||
|
getDeviceFullInfoUseCase.execute(A_SESSION_ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `given a new edited name when handling edit name locally action then view state is updated accordingly`() {
|
fun `given a new edited name when handling edit name locally action then view state is updated accordingly`() {
|
||||||
// Given
|
// Given
|
||||||
givenSessionWithName(A_SESSION_NAME)
|
|
||||||
val action = RenameSessionAction.EditLocally(AN_EDITED_SESSION_NAME)
|
val action = RenameSessionAction.EditLocally(AN_EDITED_SESSION_NAME)
|
||||||
val expectedState = RenameSessionViewState(
|
val expectedState = RenameSessionViewState(
|
||||||
deviceId = A_SESSION_ID,
|
deviceId = A_SESSION_ID,
|
||||||
editedDeviceName = AN_EDITED_SESSION_NAME,
|
editedDeviceName = AN_EDITED_SESSION_NAME,
|
||||||
)
|
)
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
// When
|
// When
|
||||||
val viewModel = createViewModel()
|
|
||||||
val viewModelTest = viewModel.test()
|
val viewModelTest = viewModel.test()
|
||||||
viewModel.handle(action)
|
viewModel.handle(action)
|
||||||
|
|
||||||
|
@ -95,12 +129,11 @@ class RenameSessionViewModelTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given current edited name when handling save modifications action with success then correct view event is posted`() {
|
fun `given current edited name when handling save modifications action with success then correct view event is posted`() {
|
||||||
// Given
|
// Given
|
||||||
givenSessionWithName(A_SESSION_NAME)
|
coEvery { renameSessionUseCase.execute(A_SESSION_ID, any()) } returns Result.success(Unit)
|
||||||
coEvery { renameSessionUseCase.execute(A_SESSION_ID, A_SESSION_NAME) } returns Result.success(Unit)
|
|
||||||
val action = RenameSessionAction.SaveModifications
|
val action = RenameSessionAction.SaveModifications
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
// When
|
// When
|
||||||
val viewModel = createViewModel()
|
|
||||||
val viewModelTest = viewModel.test()
|
val viewModelTest = viewModel.test()
|
||||||
viewModel.handle(action)
|
viewModel.handle(action)
|
||||||
|
|
||||||
|
@ -113,13 +146,12 @@ class RenameSessionViewModelTest {
|
||||||
@Test
|
@Test
|
||||||
fun `given current edited name when handling save modifications action with error then correct view event is posted`() {
|
fun `given current edited name when handling save modifications action with error then correct view event is posted`() {
|
||||||
// Given
|
// Given
|
||||||
givenSessionWithName(A_SESSION_NAME)
|
|
||||||
val error = Exception()
|
val error = Exception()
|
||||||
coEvery { renameSessionUseCase.execute(A_SESSION_ID, A_SESSION_NAME) } returns Result.failure(error)
|
coEvery { renameSessionUseCase.execute(A_SESSION_ID, any()) } returns Result.failure(error)
|
||||||
val action = RenameSessionAction.SaveModifications
|
val action = RenameSessionAction.SaveModifications
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
// When
|
// When
|
||||||
val viewModel = createViewModel()
|
|
||||||
val viewModelTest = viewModel.test()
|
val viewModelTest = viewModel.test()
|
||||||
viewModel.handle(action)
|
viewModel.handle(action)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue