Merge pull request #4198 from cbs228/bugfix/full-browser-for-web-links

Open chat links in regular browser tabs
This commit is contained in:
Benoit Marty 2025-02-06 09:10:23 +01:00 committed by GitHub
commit 79293e1e9d
5 changed files with 21 additions and 12 deletions

View file

@ -40,6 +40,7 @@ import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPr
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
import io.element.android.libraries.androidutils.system.openUrlInExternalApp
import io.element.android.libraries.androidutils.system.toast import io.element.android.libraries.androidutils.system.toast
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
@ -138,6 +139,7 @@ class MessagesNode @AssistedInject constructor(
darkTheme: Boolean, darkTheme: Boolean,
url: String, url: String,
eventSink: (TimelineEvents) -> Unit, eventSink: (TimelineEvents) -> Unit,
customTab: Boolean
) { ) {
when (val permalink = permalinkParser.parse(url)) { when (val permalink = permalinkParser.parse(url)) {
is PermalinkData.UserLink -> { is PermalinkData.UserLink -> {
@ -148,7 +150,13 @@ class MessagesNode @AssistedInject constructor(
is PermalinkData.RoomLink -> { is PermalinkData.RoomLink -> {
handleRoomLinkClick(activity, permalink, eventSink) handleRoomLinkClick(activity, permalink, eventSink)
} }
is PermalinkData.FallbackLink, is PermalinkData.FallbackLink -> {
if (customTab) {
activity.openUrlInChromeCustomTab(null, darkTheme, url)
} else {
activity.openUrlInExternalApp(url)
}
}
is PermalinkData.RoomEmailInviteLink -> { is PermalinkData.RoomEmailInviteLink -> {
activity.openUrlInChromeCustomTab(null, darkTheme, url) activity.openUrlInChromeCustomTab(null, darkTheme, url)
} }
@ -233,7 +241,7 @@ class MessagesNode @AssistedInject constructor(
onRoomDetailsClick = this::onRoomDetailsClick, onRoomDetailsClick = this::onRoomDetailsClick,
onEventContentClick = this::onEventClick, onEventContentClick = this::onEventClick,
onUserDataClick = this::onUserDataClick, onUserDataClick = this::onUserDataClick,
onLinkClick = { url -> onLinkClick(activity, isDark, url, state.timelineState.eventSink) }, onLinkClick = { url, customTab -> onLinkClick(activity, isDark, url, state.timelineState.eventSink, customTab) },
onSendLocationClick = this::onSendLocationClick, onSendLocationClick = this::onSendLocationClick,
onCreatePollClick = this::onCreatePollClick, onCreatePollClick = this::onCreatePollClick,
onJoinCallClick = this::onJoinCallClick, onJoinCallClick = this::onJoinCallClick,

View file

@ -111,7 +111,7 @@ fun MessagesView(
onRoomDetailsClick: () -> Unit, onRoomDetailsClick: () -> Unit,
onEventContentClick: (event: TimelineItem.Event) -> Boolean, onEventContentClick: (event: TimelineItem.Event) -> Boolean,
onUserDataClick: (UserId) -> Unit, onUserDataClick: (UserId) -> Unit,
onLinkClick: (String) -> Unit, onLinkClick: (String, Boolean) -> Unit,
onSendLocationClick: () -> Unit, onSendLocationClick: () -> Unit,
onCreatePollClick: () -> Unit, onCreatePollClick: () -> Unit,
onJoinCallClick: () -> Unit, onJoinCallClick: () -> Unit,
@ -273,7 +273,7 @@ private fun MessagesViewContent(
state: MessagesState, state: MessagesState,
onContentClick: (TimelineItem.Event) -> Unit, onContentClick: (TimelineItem.Event) -> Unit,
onUserDataClick: (UserId) -> Unit, onUserDataClick: (UserId) -> Unit,
onLinkClick: (String) -> Unit, onLinkClick: (String, Boolean) -> Unit,
onReactionClick: (key: String, TimelineItem.Event) -> Unit, onReactionClick: (key: String, TimelineItem.Event) -> Unit,
onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onReactionLongClick: (key: String, TimelineItem.Event) -> Unit,
onMoreReactionsClick: (TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit,
@ -347,7 +347,7 @@ private fun MessagesViewContent(
state = state.timelineState, state = state.timelineState,
timelineProtectionState = state.timelineProtectionState, timelineProtectionState = state.timelineProtectionState,
onUserDataClick = onUserDataClick, onUserDataClick = onUserDataClick,
onLinkClick = onLinkClick, onLinkClick = { url -> onLinkClick(url, false) },
onContentClick = onContentClick, onContentClick = onContentClick,
onMessageLongClick = onMessageLongClick, onMessageLongClick = onMessageLongClick,
onSwipeToReply = onSwipeToReply, onSwipeToReply = onSwipeToReply,
@ -396,7 +396,7 @@ private fun MessagesViewContent(
private fun MessagesViewComposerBottomSheetContents( private fun MessagesViewComposerBottomSheetContents(
subcomposing: Boolean, subcomposing: Boolean,
state: MessagesState, state: MessagesState,
onLinkClick: (String) -> Unit, onLinkClick: (String, Boolean) -> Unit,
) { ) {
if (state.userEventPermissions.canSendMessage) { if (state.userEventPermissions.canSendMessage) {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
@ -537,7 +537,7 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class)
onRoomDetailsClick = {}, onRoomDetailsClick = {},
onEventContentClick = { false }, onEventContentClick = { false },
onUserDataClick = {}, onUserDataClick = {},
onLinkClick = {}, onLinkClick = { _, _ -> },
onSendLocationClick = {}, onSendLocationClick = {},
onCreatePollClick = {}, onCreatePollClick = {},
onJoinCallClick = {}, onJoinCallClick = {},

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
fun IdentityChangeStateView( fun IdentityChangeStateView(
state: IdentityChangeState, state: IdentityChangeState,
onLinkClick: (String) -> Unit, onLinkClick: (String, Boolean) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
// Pick the first identity change to PinViolation // Pick the first identity change to PinViolation
@ -73,7 +73,7 @@ fun IdentityChangeStateView(
url = LinkAnnotation.Url( url = LinkAnnotation.Url(
url = LearnMoreConfig.IDENTITY_CHANGE_URL, url = LearnMoreConfig.IDENTITY_CHANGE_URL,
linkInteractionListener = { linkInteractionListener = {
onLinkClick(LearnMoreConfig.IDENTITY_CHANGE_URL) onLinkClick(LearnMoreConfig.IDENTITY_CHANGE_URL, true)
} }
), ),
start = learnMoreStartIndex, start = learnMoreStartIndex,
@ -93,6 +93,6 @@ internal fun IdentityChangeStateViewPreview(
) = ElementPreview { ) = ElementPreview {
IdentityChangeStateView( IdentityChangeStateView(
state = state, state = state,
onLinkClick = {}, onLinkClick = { _, _ -> },
) )
} }

View file

@ -35,7 +35,7 @@ internal fun MessagesViewWithIdentityChangePreview(
onRoomDetailsClick = {}, onRoomDetailsClick = {},
onEventContentClick = { false }, onEventContentClick = { false },
onUserDataClick = {}, onUserDataClick = {},
onLinkClick = {}, onLinkClick = { _, _ -> },
onSendLocationClick = {}, onSendLocationClick = {},
onCreatePollClick = {}, onCreatePollClick = {},
onJoinCallClick = {}, onJoinCallClick = {},

View file

@ -58,6 +58,7 @@ import io.element.android.tests.testutils.EnsureCalledOnceWithParam
import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EnsureNeverCalledWithParamAndResult import io.element.android.tests.testutils.EnsureNeverCalledWithParamAndResult
import io.element.android.tests.testutils.EnsureNeverCalledWithTwoParams
import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledOnce
@ -514,7 +515,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessa
onRoomDetailsClick: () -> Unit = EnsureNeverCalled(), onRoomDetailsClick: () -> Unit = EnsureNeverCalled(),
onEventClick: (event: TimelineItem.Event) -> Boolean = EnsureNeverCalledWithParamAndResult(), onEventClick: (event: TimelineItem.Event) -> Boolean = EnsureNeverCalledWithParamAndResult(),
onUserDataClick: (UserId) -> Unit = EnsureNeverCalledWithParam(), onUserDataClick: (UserId) -> Unit = EnsureNeverCalledWithParam(),
onLinkClick: (String) -> Unit = EnsureNeverCalledWithParam(), onLinkClick: (String, Boolean) -> Unit = EnsureNeverCalledWithTwoParams(),
onSendLocationClick: () -> Unit = EnsureNeverCalled(), onSendLocationClick: () -> Unit = EnsureNeverCalled(),
onCreatePollClick: () -> Unit = EnsureNeverCalled(), onCreatePollClick: () -> Unit = EnsureNeverCalled(),
onJoinCallClick: () -> Unit = EnsureNeverCalled(), onJoinCallClick: () -> Unit = EnsureNeverCalled(),