Deeplink: handle notification click to open a room.

This commit is contained in:
Benoit Marty 2023-04-13 15:04:51 +02:00
parent 018a5c540a
commit b0f14bfb15
17 changed files with 292 additions and 33 deletions

View file

@ -40,6 +40,14 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Handle deep-link for notification, uncomment to be able to test deeplink with ./tools/adb/deeplink.sh -->
<!--intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="open"
android:scheme="elementx" />
</intent-filter-->
</activity>
<provider

View file

@ -28,6 +28,7 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import com.bumble.appyx.core.integration.NodeHost
import com.bumble.appyx.core.integrationpoint.NodeComponentActivity
import com.bumble.appyx.core.plugin.NodeReadyObserver
import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.designsystem.theme.ElementTheme
import io.element.android.x.di.AppBindings
@ -35,6 +36,8 @@ import timber.log.Timber
class MainActivity : NodeComponentActivity() {
lateinit var mainNode: MainNode
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
@ -44,10 +47,23 @@ class MainActivity : NodeComponentActivity() {
setContent {
ElementTheme {
Box(
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background),
) {
NodeHost(integrationPoint = appyxIntegrationPoint) {
MainNode(it, appBindings.mainDaggerComponentOwner())
MainNode(
it,
appBindings.mainDaggerComponentOwner(),
plugins = listOf(
object : NodeReadyObserver<MainNode> {
override fun init(node: MainNode) {
mainNode = node
mainNode.handleIntent(intent)
}
}
)
)
}
}
}
@ -63,6 +79,8 @@ class MainActivity : NodeComponentActivity() {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
Timber.w("onNewIntent")
intent ?: return
mainNode.handleIntent(intent)
}
override fun onSaveInstanceState(outState: Bundle) {

View file

@ -16,14 +16,17 @@
package io.element.android.x
import android.content.Intent
import android.os.Parcelable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.lifecycleScope
import com.bumble.appyx.core.composable.Children
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.node.ParentNode
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.appnav.LoggedInFlowNode
import io.element.android.appnav.RoomFlowNode
import io.element.android.appnav.RootFlowNode
@ -35,11 +38,13 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.x.di.MainDaggerComponentsOwner
import io.element.android.x.di.RoomComponent
import io.element.android.x.di.SessionComponent
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
class MainNode(
buildContext: BuildContext,
private val mainDaggerComponentOwner: MainDaggerComponentsOwner,
plugins: List<Plugin>,
) :
ParentNode<MainNode.RootNavTarget>(
navModel = PermanentNavModel(
@ -47,6 +52,7 @@ class MainNode(
savedStateMap = buildContext.savedStateMap,
),
buildContext = buildContext,
plugins = plugins,
),
DaggerComponentOwner by mainDaggerComponentOwner {
@ -73,7 +79,13 @@ class MainNode(
}
override fun resolve(navTarget: RootNavTarget, buildContext: BuildContext): Node {
return createNode<RootFlowNode>(buildContext, plugins = listOf(loggedInFlowNodeCallback, roomFlowNodeCallback))
return createNode<RootFlowNode>(
context = buildContext,
plugins = listOf(
loggedInFlowNodeCallback,
roomFlowNodeCallback,
)
)
}
@Composable
@ -81,6 +93,12 @@ class MainNode(
Children(navModel = navModel)
}
fun handleIntent(intent: Intent) {
lifecycleScope.launch {
waitForChildAttached<RootFlowNode>().handleIntent(intent)
}
}
@Parcelize
object RootNavTarget : Parcelable
}

View file

@ -18,7 +18,9 @@ package io.element.android.x.intent
import android.content.Context
import android.content.Intent
import androidx.core.net.toUri
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.deeplink.DeepLinkCreator
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.core.RoomId
@ -28,17 +30,19 @@ import io.element.android.libraries.push.impl.intent.IntentProvider
import io.element.android.x.MainActivity
import javax.inject.Inject
// TODO EAx change to deep-link.
@ContributesBinding(AppScope::class)
class IntentProviderImpl @Inject constructor(
@ApplicationContext private val context: Context,
private val deepLinkCreator: DeepLinkCreator,
) : IntentProvider {
override fun getMainIntent(): Intent {
return Intent(context, MainActivity::class.java)
}
override fun getIntent(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?): Intent {
// TODO Handle deeplink or pass parameters
return Intent(context, MainActivity::class.java)
override fun getViewIntent(
sessionId: SessionId,
roomId: RoomId?,
threadId: ThreadId?,
): Intent {
return Intent(context, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = deepLinkCreator.create(sessionId, roomId, threadId).toUri()
}
}
}