Create a LoggedInNode, used as a PermanentNode in LoggedInFlowNode

This commit is contained in:
Benoit Marty 2023-03-31 10:15:51 +02:00 committed by Benoit Marty
parent c1f80cda80
commit eaff43de3a
7 changed files with 85 additions and 46 deletions

View file

@ -35,8 +35,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.loggedin.LoggedInPresenter import io.element.android.appnav.loggedin.LoggedInNode
import io.element.android.appnav.loggedin.LoggedInView
import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.createroom.api.CreateRoomEntryPoint
import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.features.preferences.api.PreferencesEntryPoint
import io.element.android.features.roomlist.api.RoomListEntryPoint import io.element.android.features.roomlist.api.RoomListEntryPoint
@ -72,7 +71,6 @@ class LoggedInFlowNode @AssistedInject constructor(
private val verifySessionEntryPoint: VerifySessionEntryPoint, private val verifySessionEntryPoint: VerifySessionEntryPoint,
private val coroutineScope: CoroutineScope, private val coroutineScope: CoroutineScope,
snackbarDispatcher: SnackbarDispatcher, snackbarDispatcher: SnackbarDispatcher,
private val loggedInPresenter: LoggedInPresenter,
) : BackstackNode<LoggedInFlowNode.NavTarget>( ) : BackstackNode<LoggedInFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = NavTarget.RoomList, initialElement = NavTarget.RoomList,
@ -128,6 +126,9 @@ class LoggedInFlowNode @AssistedInject constructor(
} }
sealed interface NavTarget : Parcelable { sealed interface NavTarget : Parcelable {
@Parcelize
object Permanent : NavTarget
@Parcelize @Parcelize
object RoomList : NavTarget object RoomList : NavTarget
@ -146,6 +147,9 @@ class LoggedInFlowNode @AssistedInject constructor(
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) { return when (navTarget) {
NavTarget.Permanent -> {
createNode<LoggedInNode>(buildContext)
}
NavTarget.RoomList -> { NavTarget.RoomList -> {
val callback = object : RoomListEntryPoint.Callback { val callback = object : RoomListEntryPoint.Callback {
override fun onRoomClicked(roomId: RoomId) { override fun onRoomClicked(roomId: RoomId) {
@ -205,16 +209,15 @@ class LoggedInFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val loggedInState = loggedInPresenter.present() Box(modifier = modifier) {
LoggedInView(
state = loggedInState
) {
Children( Children(
navModel = backstack, navModel = backstack,
modifier = modifier, modifier = Modifier,
// Animate navigation to settings and to a room // Animate navigation to settings and to a room
transitionHandler = rememberDefaultTransitionHandler(), transitionHandler = rememberDefaultTransitionHandler(),
) )
PermanentChild(navTarget = NavTarget.Permanent)
} }
} }
} }

View file

@ -0,0 +1,44 @@
/*
* 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.appnav.loggedin
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.di.SessionScope
@ContributesNode(SessionScope::class)
class LoggedInNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val loggedInPresenter: LoggedInPresenter,
) : Node(buildContext, plugins = plugins) {
@Composable
override fun View(modifier: Modifier) {
val loggedInState = loggedInPresenter.present()
LoggedInView(
state = loggedInState,
modifier = modifier
)
}
}

View file

@ -19,6 +19,7 @@ package io.element.android.appnav.loggedin
import android.Manifest import android.Manifest
import android.os.Build import android.os.Build
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.api.PermissionsPresenter
@ -27,9 +28,9 @@ import io.element.android.libraries.push.api.PushService
import javax.inject.Inject import javax.inject.Inject
class LoggedInPresenter @Inject constructor( class LoggedInPresenter @Inject constructor(
private val matrixClient: MatrixClient,
private val permissionsPresenterFactory: PermissionsPresenter.Factory, private val permissionsPresenterFactory: PermissionsPresenter.Factory,
// private val matrixClient: MatrixClient, private val pushService: PushService,
// private val pushService: PushService,
) : Presenter<LoggedInState> { ) : Presenter<LoggedInState> {
private val postNotificationPermissionsPresenter by lazy { private val postNotificationPermissionsPresenter by lazy {
@ -43,8 +44,10 @@ class LoggedInPresenter @Inject constructor(
@Composable @Composable
override fun present(): LoggedInState { override fun present(): LoggedInState {
LaunchedEffect(Unit) {
// TODO EAx pushService.registerPusher(matrixClient.sessionId) // Ensure pusher is registered
pushService.registerPusher(matrixClient)
}
val permissionsState = postNotificationPermissionsPresenter.present() val permissionsState = postNotificationPermissionsPresenter.present()

View file

@ -17,11 +17,7 @@
package io.element.android.appnav.loggedin package io.element.android.appnav.loggedin
import android.app.Activity import android.app.Activity
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
@ -29,31 +25,22 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.libraries.androidutils.system.openAppSettingsPage import io.element.android.libraries.androidutils.system.openAppSettingsPage
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.permissions.api.PermissionsView import io.element.android.libraries.permissions.api.PermissionsView
@Composable @Composable
fun LoggedInView( fun LoggedInView(
state: LoggedInState, state: LoggedInState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier
children: @Composable BoxScope.() -> Unit,
) { ) {
val activity = LocalContext.current as? Activity val activity = LocalContext.current as? Activity
Box( PermissionsView(
modifier = modifier state = state.permissionsState,
.fillMaxSize(), modifier = modifier,
contentAlignment = Alignment.TopCenter, openSystemSettings = {
) { activity?.let { openAppSettingsPage(it, "") }
children() }
)
PermissionsView(
state = state.permissionsState,
openSystemSettings = {
activity?.let { openAppSettingsPage(it, "") }
}
)
}
} }
@Preview @Preview
@ -70,7 +57,5 @@ fun LoggedInViewDarkPreview(@PreviewParameter(LoggedInStateProvider::class) stat
private fun ContentToPreview(state: LoggedInState) { private fun ContentToPreview(state: LoggedInState) {
LoggedInView( LoggedInView(
state = state state = state
) { )
Text("Children")
}
} }

View file

@ -16,15 +16,19 @@
package io.element.android.libraries.push.api package io.element.android.libraries.push.api
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.MatrixClient
interface PushService { interface PushService {
// TODO EAx remove
fun setCurrentRoom(roomId: String?) fun setCurrentRoom(roomId: String?)
// TODO EAx remove
fun setCurrentThread(threadId: String?) fun setCurrentThread(threadId: String?)
fun notificationStyleChanged() fun notificationStyleChanged()
// Ensure pusher is registered // Ensure pusher is registered
suspend fun registerPusher(userId: UserId) suspend fun registerPusher(matrixClient: MatrixClient)
suspend fun testPush() suspend fun testPush()
} }

View file

@ -18,7 +18,7 @@ package io.element.android.libraries.push.impl
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.api.PushService
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
import javax.inject.Inject import javax.inject.Inject
@ -40,8 +40,8 @@ class DefaultPushService @Inject constructor(
notificationDrawerManager.notificationStyleChanged() notificationDrawerManager.notificationStyleChanged()
} }
override suspend fun registerPusher(userId: UserId) { override suspend fun registerPusher(matrixClient: MatrixClient) {
pusherManager.registerPusher(userId) pusherManager.registerPusher(matrixClient)
} }
override suspend fun testPush() { override suspend fun testPush() {

View file

@ -16,9 +16,9 @@
package io.element.android.libraries.push.impl package io.element.android.libraries.push.impl
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
import io.element.android.libraries.push.impl.clientsecret.PushClientSecret import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
import io.element.android.libraries.push.impl.config.PushConfig import io.element.android.libraries.push.impl.config.PushConfig
@ -71,12 +71,12 @@ class PushersManager @Inject constructor(
} }
} }
suspend fun registerPusher(userId: UserId) { suspend fun registerPusher(matrixClient: MatrixClient) {
val pushKey = fcmHelper.getFcmToken() ?: return val pushKey = fcmHelper.getFcmToken() ?: return
// Register the pusher for the session // Register the pusher for the session
val client = matrixAuthenticationService.restoreSession(userId).getOrNull() ?: return matrixClient.pushersService().setHttpPusher(
client.pushersService().setHttpPusher(createHttpPusher(pushKey, PushConfig.pusher_http_url, userId.value)) createHttpPusher(pushKey, PushConfig.pusher_http_url, matrixClient.sessionId.value)
// TODO EAx Close sessions )
} }
private suspend fun createHttpPusher( private suspend fun createHttpPusher(