AppNav: introduce a owner param so we avoid crash on AppNavigationState when switching quickly between screens
This commit is contained in:
parent
281f90e148
commit
29f3d6d725
6 changed files with 73 additions and 49 deletions
|
|
@ -40,11 +40,10 @@ private val loggerTag = LoggerTag("Navigation")
|
|||
@SingleIn(AppScope::class)
|
||||
class DefaultAppNavigationStateService @Inject constructor() : AppNavigationStateService {
|
||||
|
||||
private val currentAppNavigationState = MutableStateFlow<AppNavigationState>(AppNavigationState.Root)
|
||||
|
||||
private val currentAppNavigationState: MutableStateFlow<AppNavigationState> = MutableStateFlow(AppNavigationState.Root)
|
||||
override val appNavigationStateFlow: StateFlow<AppNavigationState> = currentAppNavigationState
|
||||
|
||||
override fun onNavigateToSession(sessionId: SessionId) {
|
||||
override fun onNavigateToSession(owner: String, sessionId: SessionId) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Navigating to session $sessionId. Current state: $currentValue")
|
||||
val newValue: AppNavigationState.Session = when (currentValue) {
|
||||
|
|
@ -52,53 +51,54 @@ class DefaultAppNavigationStateService @Inject constructor() : AppNavigationStat
|
|||
is AppNavigationState.Space,
|
||||
is AppNavigationState.Room,
|
||||
is AppNavigationState.Thread,
|
||||
AppNavigationState.Root -> AppNavigationState.Session(sessionId)
|
||||
is AppNavigationState.Root -> AppNavigationState.Session(owner, sessionId)
|
||||
}
|
||||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onNavigateToSpace(spaceId: SpaceId) {
|
||||
override fun onNavigateToSpace(owner: String, spaceId: SpaceId) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Navigating to space $spaceId. Current state: $currentValue")
|
||||
val newValue: AppNavigationState.Space = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> AppNavigationState.Space(spaceId, currentValue)
|
||||
is AppNavigationState.Space -> AppNavigationState.Space(spaceId, currentValue.parentSession)
|
||||
is AppNavigationState.Room -> AppNavigationState.Space(spaceId, currentValue.parentSpace.parentSession)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Space(spaceId, currentValue.parentRoom.parentSpace.parentSession)
|
||||
is AppNavigationState.Session -> AppNavigationState.Space(owner, spaceId, currentValue)
|
||||
is AppNavigationState.Space -> AppNavigationState.Space(owner, spaceId, currentValue.parentSession)
|
||||
is AppNavigationState.Room -> AppNavigationState.Space(owner, spaceId, currentValue.parentSpace.parentSession)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Space(owner, spaceId, currentValue.parentRoom.parentSpace.parentSession)
|
||||
}
|
||||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onNavigateToRoom(roomId: RoomId) {
|
||||
override fun onNavigateToRoom(owner: String, roomId: RoomId) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Navigating to room $roomId. Current state: $currentValue")
|
||||
val newValue: AppNavigationState.Room = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> error("onNavigateToSpace() must be called first")
|
||||
is AppNavigationState.Space -> AppNavigationState.Room(roomId, currentValue)
|
||||
is AppNavigationState.Room -> AppNavigationState.Room(roomId, currentValue.parentSpace)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Room(roomId, currentValue.parentRoom.parentSpace)
|
||||
is AppNavigationState.Space -> AppNavigationState.Room(owner, roomId, currentValue)
|
||||
is AppNavigationState.Room -> AppNavigationState.Room(owner, roomId, currentValue.parentSpace)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Room(owner, roomId, currentValue.parentRoom.parentSpace)
|
||||
}
|
||||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onNavigateToThread(threadId: ThreadId) {
|
||||
override fun onNavigateToThread(owner: String, threadId: ThreadId) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Navigating to thread $threadId. Current state: $currentValue")
|
||||
val newValue: AppNavigationState.Thread = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> error("onNavigateToSpace() must be called first")
|
||||
is AppNavigationState.Space -> error("onNavigateToRoom() must be called first")
|
||||
is AppNavigationState.Room -> AppNavigationState.Thread(threadId, currentValue)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Thread(threadId, currentValue.parentRoom)
|
||||
is AppNavigationState.Room -> AppNavigationState.Thread(owner, threadId, currentValue)
|
||||
is AppNavigationState.Thread -> AppNavigationState.Thread(owner, threadId, currentValue.parentRoom)
|
||||
}
|
||||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onLeavingThread() {
|
||||
override fun onLeavingThread(owner: String) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Leaving thread. Current state: $currentValue")
|
||||
if (!currentValue.assertOwner(owner)) return
|
||||
val newValue: AppNavigationState.Room = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> error("onNavigateToSpace() must be called first")
|
||||
|
|
@ -109,9 +109,10 @@ class DefaultAppNavigationStateService @Inject constructor() : AppNavigationStat
|
|||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onLeavingRoom() {
|
||||
override fun onLeavingRoom(owner: String) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Leaving room. Current state: $currentValue")
|
||||
if (!currentValue.assertOwner(owner)) return
|
||||
val newValue: AppNavigationState.Space = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> error("onNavigateToSpace() must be called first")
|
||||
|
|
@ -122,9 +123,10 @@ class DefaultAppNavigationStateService @Inject constructor() : AppNavigationStat
|
|||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onLeavingSpace() {
|
||||
override fun onLeavingSpace(owner: String) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Leaving space. Current state: $currentValue")
|
||||
if (!currentValue.assertOwner(owner)) return
|
||||
val newValue: AppNavigationState.Session = when (currentValue) {
|
||||
AppNavigationState.Root -> error("onNavigateToSession() must be called first")
|
||||
is AppNavigationState.Session -> error("onNavigateToSpace() must be called first")
|
||||
|
|
@ -135,9 +137,18 @@ class DefaultAppNavigationStateService @Inject constructor() : AppNavigationStat
|
|||
currentAppNavigationState.value = newValue
|
||||
}
|
||||
|
||||
override fun onLeavingSession() {
|
||||
override fun onLeavingSession(owner: String) {
|
||||
val currentValue = currentAppNavigationState.value
|
||||
Timber.tag(loggerTag.value).d("Leaving session. Current state: $currentValue")
|
||||
if (!currentValue.assertOwner(owner)) return
|
||||
currentAppNavigationState.value = AppNavigationState.Root
|
||||
}
|
||||
|
||||
private fun AppNavigationState.assertOwner(owner: String): Boolean {
|
||||
if (this.owner != owner) {
|
||||
Timber.tag(loggerTag.value).d("Can't leave current state as the owner is not the same (current = ${this.owner}, new = $owner)")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,23 +30,31 @@ import kotlinx.coroutines.test.runTest
|
|||
import org.junit.Assert.assertThrows
|
||||
import org.junit.Test
|
||||
|
||||
private const val aSessionOwner = "aSessionOwner"
|
||||
private const val aSpaceOwner = "aSpaceOwner"
|
||||
private const val aRoomOwner = "aRoomOwner"
|
||||
private const val aThreadOwner = "aThreadOwner"
|
||||
|
||||
class DefaultAppNavigationStateServiceTest {
|
||||
|
||||
@Test
|
||||
fun testNavigation() = runTest {
|
||||
val service = DefaultAppNavigationStateService()
|
||||
service.onNavigateToSession(A_SESSION_ID)
|
||||
service.onNavigateToSpace(A_SPACE_ID)
|
||||
service.onNavigateToRoom(A_ROOM_ID)
|
||||
service.onNavigateToThread(A_THREAD_ID)
|
||||
service.onNavigateToSession(aSessionOwner, A_SESSION_ID)
|
||||
service.onNavigateToSpace(aSpaceOwner, A_SPACE_ID)
|
||||
service.onNavigateToRoom(aRoomOwner, A_ROOM_ID)
|
||||
service.onNavigateToThread(aThreadOwner, A_THREAD_ID)
|
||||
assertThat(service.appNavigationStateFlow.first()).isEqualTo(
|
||||
AppNavigationState.Thread(
|
||||
A_THREAD_ID,
|
||||
aThreadOwner, A_THREAD_ID,
|
||||
AppNavigationState.Room(
|
||||
aRoomOwner,
|
||||
A_ROOM_ID,
|
||||
AppNavigationState.Space(
|
||||
aSpaceOwner,
|
||||
A_SPACE_ID,
|
||||
AppNavigationState.Session(
|
||||
aSessionOwner,
|
||||
A_SESSION_ID
|
||||
)
|
||||
)
|
||||
|
|
@ -58,6 +66,6 @@ class DefaultAppNavigationStateServiceTest {
|
|||
@Test
|
||||
fun testFailure() = runTest {
|
||||
val service = DefaultAppNavigationStateService()
|
||||
assertThrows(IllegalStateException::class.java) { service.onNavigateToSpace(A_SPACE_ID) }
|
||||
assertThrows(IllegalStateException::class.java) { service.onNavigateToSpace(aSpaceOwner, A_SPACE_ID) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue