Identity change: handle click on "learn more"
This commit is contained in:
@@ -9,4 +9,5 @@ package io.element.android.appconfig
|
||||
|
||||
object LearnMoreConfig {
|
||||
const val SECURE_BACKUP_URL: String = "https://element.io/help#encryption5"
|
||||
const val IDENTITY_CHANGE_URL: String = "https://element.io/help#encryption18"
|
||||
}
|
||||
|
||||
@@ -27,13 +27,14 @@ import com.bumble.appyx.core.plugin.plugins
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.messages.impl.attachments.Attachment
|
||||
import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents
|
||||
import io.element.android.features.messages.impl.timeline.TimelineEvents
|
||||
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
|
||||
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.androidutils.system.openUrlInExternalApp
|
||||
import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
|
||||
import io.element.android.libraries.androidutils.system.toast
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
@@ -122,7 +123,8 @@ class MessagesNode @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun onLinkClick(
|
||||
context: Context,
|
||||
activity: Activity,
|
||||
darkTheme: Boolean,
|
||||
url: String,
|
||||
eventSink: (TimelineEvents) -> Unit,
|
||||
) {
|
||||
@@ -133,11 +135,11 @@ class MessagesNode @AssistedInject constructor(
|
||||
callbacks.forEach { it.onUserDataClick(permalink.userId) }
|
||||
}
|
||||
is PermalinkData.RoomLink -> {
|
||||
handleRoomLinkClick(context, permalink, eventSink)
|
||||
handleRoomLinkClick(activity, permalink, eventSink)
|
||||
}
|
||||
is PermalinkData.FallbackLink,
|
||||
is PermalinkData.RoomEmailInviteLink -> {
|
||||
context.openUrlInExternalApp(url)
|
||||
activity.openUrlInChromeCustomTab(null, darkTheme, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,6 +197,7 @@ class MessagesNode @AssistedInject constructor(
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val activity = LocalContext.current as Activity
|
||||
val isDark = ElementTheme.isLightTheme.not()
|
||||
CompositionLocalProvider(
|
||||
LocalTimelineItemPresenterFactories provides timelineItemPresenterFactories,
|
||||
) {
|
||||
@@ -212,7 +215,7 @@ class MessagesNode @AssistedInject constructor(
|
||||
onEventClick = this::onEventClick,
|
||||
onPreviewAttachments = this::onPreviewAttachments,
|
||||
onUserDataClick = this::onUserDataClick,
|
||||
onLinkClick = { onLinkClick(activity, it, state.timelineState.eventSink) },
|
||||
onLinkClick = { url -> onLinkClick(activity, isDark, url, state.timelineState.eventSink) },
|
||||
onSendLocationClick = this::onSendLocationClick,
|
||||
onCreatePollClick = this::onCreatePollClick,
|
||||
onJoinCallClick = this::onJoinCallClick,
|
||||
|
||||
@@ -417,6 +417,7 @@ private fun MessagesViewContent(
|
||||
MessagesViewComposerBottomSheetContents(
|
||||
subcomposing = subcomposing,
|
||||
state = state,
|
||||
onLinkClick = onLinkClick,
|
||||
)
|
||||
},
|
||||
sheetContentKey = sheetResizeContentKey.intValue,
|
||||
@@ -430,6 +431,7 @@ private fun MessagesViewContent(
|
||||
private fun MessagesViewComposerBottomSheetContents(
|
||||
subcomposing: Boolean,
|
||||
state: MessagesState,
|
||||
onLinkClick: (String) -> Unit,
|
||||
) {
|
||||
if (state.userEventPermissions.canSendMessage) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
@@ -453,7 +455,10 @@ private fun MessagesViewComposerBottomSheetContents(
|
||||
// Do not show the identity change if user is composing a Rich message or is seeing suggestion(s).
|
||||
if (state.composerState.suggestions.isEmpty() &&
|
||||
state.composerState.textEditorState is TextEditorState.Markdown) {
|
||||
IdentityChangeStateView(state.identityChangeState)
|
||||
IdentityChangeStateView(
|
||||
state = state.identityChangeState,
|
||||
onLinkClick = onLinkClick,
|
||||
)
|
||||
}
|
||||
MessageComposerView(
|
||||
state = state.composerState,
|
||||
|
||||
@@ -10,11 +10,13 @@ package io.element.android.features.messages.impl.crypto.identity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.appconfig.LearnMoreConfig
|
||||
import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
@@ -26,6 +28,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||
@Composable
|
||||
fun IdentityChangeStateView(
|
||||
state: IdentityChangeState,
|
||||
onLinkClick: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
// Pick the first identity change to PinViolation
|
||||
@@ -38,27 +41,31 @@ fun IdentityChangeStateView(
|
||||
modifier = modifier,
|
||||
avatar = identityChange.roomMember.getAvatarData(AvatarSize.ComposerAlert),
|
||||
content = buildAnnotatedString {
|
||||
val coloredPart = stringResource(CommonStrings.action_learn_more)
|
||||
val learnMoreStr = stringResource(CommonStrings.action_learn_more)
|
||||
val fullText = stringResource(
|
||||
CommonStrings.crypto_identity_change_pin_violation,
|
||||
id = CommonStrings.crypto_identity_change_pin_violation,
|
||||
identityChange.roomMember.disambiguatedDisplayName,
|
||||
coloredPart,
|
||||
learnMoreStr,
|
||||
)
|
||||
val startIndex = fullText.indexOf(coloredPart)
|
||||
val learnMoreStartIndex = fullText.indexOf(learnMoreStr)
|
||||
append(fullText)
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
textDecoration = TextDecoration.Underline,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
start = startIndex,
|
||||
end = startIndex + coloredPart.length,
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
addStringAnnotation(
|
||||
tag = "LEARN_MORE",
|
||||
annotation = "TODO",
|
||||
start = startIndex,
|
||||
end = startIndex + coloredPart.length
|
||||
addLink(
|
||||
url = LinkAnnotation.Url(
|
||||
url = LearnMoreConfig.IDENTITY_CHANGE_URL,
|
||||
linkInteractionListener = { t ->
|
||||
onLinkClick(LearnMoreConfig.IDENTITY_CHANGE_URL)
|
||||
}
|
||||
),
|
||||
start = learnMoreStartIndex,
|
||||
end = learnMoreStartIndex + learnMoreStr.length,
|
||||
)
|
||||
},
|
||||
onSubmitClick = { state.eventSink(IdentityChangeEvent.Submit(identityChange.roomMember.userId)) },
|
||||
@@ -74,5 +81,6 @@ internal fun IdentityChangeStateViewPreview(
|
||||
) = ElementPreview {
|
||||
IdentityChangeStateView(
|
||||
state = state,
|
||||
onLinkClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user