Fix: make sure we ignore notifications for open rooms (#867)
* Make sure we ignore notifications for open rooms - Listen to process lifecycle changes in `AppForegroundStateService`. Use initializers to reliable create it. - Merge `AppNavigationState` with `AppForegroundState`. Renamed the previous `AppNavigationState` to `NavigationState`, created a new `AppNavigationState` which contains both the navigation state and the foreground state.
This commit is contained in:
parent
a852465554
commit
e61af2eb7d
26 changed files with 552 additions and 246 deletions
|
|
@ -24,5 +24,8 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation(libs.coroutines.core)
|
||||
implementation(libs.androidx.lifecycle.runtime)
|
||||
implementation(libs.androidx.lifecycle.process)
|
||||
implementation(libs.androidx.startup)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.services.appnavstate.api
|
||||
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* A service that tracks the foreground state of the app.
|
||||
*/
|
||||
interface AppForegroundStateService {
|
||||
/**
|
||||
* Any updates to the foreground state of the app will be emitted here.
|
||||
*/
|
||||
val isInForeground: StateFlow<Boolean>
|
||||
|
||||
/**
|
||||
* Start observing the foreground state.
|
||||
*/
|
||||
fun start()
|
||||
}
|
||||
|
|
@ -16,43 +16,10 @@
|
|||
|
||||
package io.element.android.services.appnavstate.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.SpaceId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
|
||||
/**
|
||||
* Can represent the current global app navigation state.
|
||||
* @param owner mostly a Node identifier associated with the state.
|
||||
* We are using the owner parameter to check when calling onLeaving methods is still using the same owner than his companion onNavigate.
|
||||
* Why this is needed : for now we rely on lifecycle methods of the node, which are async.
|
||||
* If you navigate quickly between nodes, onCreate of the new node is called before onDestroy of the previous node.
|
||||
* So we assume if we don't get the same owner, we can skip the onLeaving action as we already replaced it.
|
||||
* A wrapper for the current navigation state of the app, along with its foreground/background state.
|
||||
*/
|
||||
sealed class AppNavigationState(open val owner: String) {
|
||||
object Root : AppNavigationState("ROOT")
|
||||
|
||||
data class Session(
|
||||
override val owner: String,
|
||||
val sessionId: SessionId,
|
||||
) : AppNavigationState(owner)
|
||||
|
||||
data class Space(
|
||||
override val owner: String,
|
||||
// Can be fake value, if no space is selected
|
||||
val spaceId: SpaceId,
|
||||
val parentSession: Session,
|
||||
) : AppNavigationState(owner)
|
||||
|
||||
data class Room(
|
||||
override val owner: String,
|
||||
val roomId: RoomId,
|
||||
val parentSpace: Space,
|
||||
) : AppNavigationState(owner)
|
||||
|
||||
data class Thread(
|
||||
override val owner: String,
|
||||
val threadId: ThreadId,
|
||||
val parentRoom: Room,
|
||||
) : AppNavigationState(owner)
|
||||
}
|
||||
data class AppNavigationState(
|
||||
val navigationState: NavigationState,
|
||||
val isInForeground: Boolean,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.services.appnavstate.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.SpaceId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
|
||||
fun AppNavigationState.currentSessionId(): SessionId? {
|
||||
return when (this) {
|
||||
AppNavigationState.Root -> null
|
||||
is AppNavigationState.Session -> sessionId
|
||||
is AppNavigationState.Space -> parentSession.sessionId
|
||||
is AppNavigationState.Room -> parentSpace.parentSession.sessionId
|
||||
is AppNavigationState.Thread -> parentRoom.parentSpace.parentSession.sessionId
|
||||
}
|
||||
}
|
||||
|
||||
fun AppNavigationState.currentSpaceId(): SpaceId? {
|
||||
return when (this) {
|
||||
AppNavigationState.Root -> null
|
||||
is AppNavigationState.Session -> null
|
||||
is AppNavigationState.Space -> spaceId
|
||||
is AppNavigationState.Room -> parentSpace.spaceId
|
||||
is AppNavigationState.Thread -> parentRoom.parentSpace.spaceId
|
||||
}
|
||||
}
|
||||
|
||||
fun AppNavigationState.currentRoomId(): RoomId? {
|
||||
return when (this) {
|
||||
AppNavigationState.Root -> null
|
||||
is AppNavigationState.Session -> null
|
||||
is AppNavigationState.Space -> null
|
||||
is AppNavigationState.Room -> roomId
|
||||
is AppNavigationState.Thread -> parentRoom.roomId
|
||||
}
|
||||
}
|
||||
|
||||
fun AppNavigationState.currentThreadId(): ThreadId? {
|
||||
return when (this) {
|
||||
AppNavigationState.Root -> null
|
||||
is AppNavigationState.Session -> null
|
||||
is AppNavigationState.Space -> null
|
||||
is AppNavigationState.Room -> null
|
||||
is AppNavigationState.Thread -> threadId
|
||||
}
|
||||
}
|
||||
|
|
@ -22,8 +22,11 @@ import io.element.android.libraries.matrix.api.core.SpaceId
|
|||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* A service that tracks the navigation and foreground states of the app.
|
||||
*/
|
||||
interface AppNavigationStateService {
|
||||
val appNavigationStateFlow: StateFlow<AppNavigationState>
|
||||
val appNavigationState: StateFlow<AppNavigationState>
|
||||
|
||||
fun onNavigateToSession(owner: String, sessionId: SessionId)
|
||||
fun onLeavingSession(owner: String)
|
||||
|
|
@ -37,3 +40,4 @@ interface AppNavigationStateService {
|
|||
fun onNavigateToThread(owner: String, threadId: ThreadId)
|
||||
fun onLeavingThread(owner: String)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.services.appnavstate.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.SpaceId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
|
||||
/**
|
||||
* Can represent the current global app navigation state.
|
||||
* @param owner mostly a Node identifier associated with the state.
|
||||
* We are using the owner parameter to check when calling onLeaving methods is still using the same owner than his companion onNavigate.
|
||||
* Why this is needed : for now we rely on lifecycle methods of the node, which are async.
|
||||
* If you navigate quickly between nodes, onCreate of the new node is called before onDestroy of the previous node.
|
||||
* So we assume if we don't get the same owner, we can skip the onLeaving action as we already replaced it.
|
||||
*/
|
||||
sealed class NavigationState(open val owner: String) {
|
||||
object Root : NavigationState("ROOT")
|
||||
|
||||
data class Session(
|
||||
override val owner: String,
|
||||
val sessionId: SessionId,
|
||||
) : NavigationState(owner)
|
||||
|
||||
data class Space(
|
||||
override val owner: String,
|
||||
// Can be fake value, if no space is selected
|
||||
val spaceId: SpaceId,
|
||||
val parentSession: Session,
|
||||
) : NavigationState(owner)
|
||||
|
||||
data class Room(
|
||||
override val owner: String,
|
||||
val roomId: RoomId,
|
||||
val parentSpace: Space,
|
||||
) : NavigationState(owner)
|
||||
|
||||
data class Thread(
|
||||
override val owner: String,
|
||||
val threadId: ThreadId,
|
||||
val parentRoom: Room,
|
||||
) : NavigationState(owner)
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.services.appnavstate.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.SpaceId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
|
||||
fun NavigationState.currentSessionId(): SessionId? {
|
||||
return when (this) {
|
||||
NavigationState.Root -> null
|
||||
is NavigationState.Session -> sessionId
|
||||
is NavigationState.Space -> parentSession.sessionId
|
||||
is NavigationState.Room -> parentSpace.parentSession.sessionId
|
||||
is NavigationState.Thread -> parentRoom.parentSpace.parentSession.sessionId
|
||||
}
|
||||
}
|
||||
|
||||
fun NavigationState.currentSpaceId(): SpaceId? {
|
||||
return when (this) {
|
||||
NavigationState.Root -> null
|
||||
is NavigationState.Session -> null
|
||||
is NavigationState.Space -> spaceId
|
||||
is NavigationState.Room -> parentSpace.spaceId
|
||||
is NavigationState.Thread -> parentRoom.parentSpace.spaceId
|
||||
}
|
||||
}
|
||||
|
||||
fun NavigationState.currentRoomId(): RoomId? {
|
||||
return when (this) {
|
||||
NavigationState.Root -> null
|
||||
is NavigationState.Session -> null
|
||||
is NavigationState.Space -> null
|
||||
is NavigationState.Room -> roomId
|
||||
is NavigationState.Thread -> parentRoom.roomId
|
||||
}
|
||||
}
|
||||
|
||||
fun NavigationState.currentThreadId(): ThreadId? {
|
||||
return when (this) {
|
||||
NavigationState.Root -> null
|
||||
is NavigationState.Session -> null
|
||||
is NavigationState.Space -> null
|
||||
is NavigationState.Room -> null
|
||||
is NavigationState.Thread -> threadId
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue