mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 21:05:28 +00:00
Add content scanner support to media gallery and viewer (Element Pro) (#7233)
* Add content scanner support to media gallery and viewer * Improve UI and previews * Remove default content validation state in media content views * Disable click for invalid media items in the gallery events * Update screenshots --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
committed by
GitHub
parent
19724aaa78
commit
2705efad15
+2
-1
@@ -22,8 +22,8 @@ import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentVal
|
||||
fun TimelineItemAudioView(
|
||||
content: TimelineItemAudioContent,
|
||||
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
|
||||
contentValidationValue: ContentValidationValue,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationValue: ContentValidationValue = ContentValidationValue.Valid,
|
||||
) {
|
||||
TimelineItemAttachmentView(
|
||||
icon = CompoundIcons.Audio(),
|
||||
@@ -43,5 +43,6 @@ internal fun TimelineItemAudioViewPreview(@PreviewParameter(TimelineItemAudioCon
|
||||
TimelineItemAudioView(
|
||||
content,
|
||||
onContentLayoutChange = {},
|
||||
contentValidationValue = ContentValidationValue.Valid,
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -27,8 +27,8 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||
fun TimelineItemFileView(
|
||||
content: TimelineItemFileContent,
|
||||
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
|
||||
contentValidationValue: ContentValidationValue,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationValue: ContentValidationValue = ContentValidationValue.Valid,
|
||||
) {
|
||||
TimelineItemAttachmentView(
|
||||
icon = CompoundIcons.Attachment(),
|
||||
@@ -48,6 +48,7 @@ internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileConte
|
||||
TimelineItemFileView(
|
||||
content,
|
||||
onContentLayoutChange = {},
|
||||
contentValidationValue = ContentValidationValue.Valid,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -288,9 +288,15 @@ private fun GalleryItemCell(
|
||||
Box(
|
||||
modifier = modifier
|
||||
.blurHashBackground(item.blurhash, alpha = 0.9f)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
.then(
|
||||
if (itemContentValidationState.isValid()) {
|
||||
Modifier.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
|
||||
+36
-29
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -43,7 +44,9 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.libraries.ui.utils.a11y.isTalkbackActive
|
||||
@@ -55,8 +58,8 @@ fun TimelineItemImageView(
|
||||
onContentClick: (() -> Unit)?,
|
||||
onLongClick: (() -> Unit)?,
|
||||
onShowContentClick: () -> Unit,
|
||||
contentValidationState: ContentValidationState,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationState: ContentValidationState = remember { DefaultContentValidationState() },
|
||||
) {
|
||||
val a11yLabel = stringResource(CommonStrings.common_image)
|
||||
val description = content.caption?.let { "$a11yLabel: $it" } ?: a11yLabel
|
||||
@@ -129,52 +132,56 @@ internal fun TimelineItemImageViewPreview(@PreviewParameter(TimelineItemImageCon
|
||||
onShowContentClick = {},
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
contentValidationState = NoopContentValidationState(),
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun TimelineItemImageViewHideMediaContentPreview() = ElementPreview {
|
||||
TimelineItemImageView(
|
||||
content = aTimelineItemImageContent(),
|
||||
hideMediaContent = true,
|
||||
onShowContentClick = {},
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
)
|
||||
TimelineItemImageView(
|
||||
content = aTimelineItemImageContent(),
|
||||
hideMediaContent = true,
|
||||
onShowContentClick = {},
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
contentValidationState = NoopContentValidationState(),
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun ATimelineItemEventRowPreview() = ElementPreview {
|
||||
Column {
|
||||
sequenceOf(false, true).forEach { isMine ->
|
||||
CompositionLocalProvider(LocalEventContentValidationState provides NoopEventContentValidationCache()) {
|
||||
Column {
|
||||
sequenceOf(false, true).forEach { isMine ->
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
isMine = isMine,
|
||||
content = aTimelineItemImageContent(
|
||||
filename = "image.jpg",
|
||||
caption = "A long caption that may wrap into several lines",
|
||||
width = 40,
|
||||
height = 20,
|
||||
aspectRatio = 40f / 20f,
|
||||
),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
),
|
||||
)
|
||||
}
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
isMine = isMine,
|
||||
isMine = false,
|
||||
content = aTimelineItemImageContent(
|
||||
filename = "image.jpg",
|
||||
caption = "A long caption that may wrap into several lines",
|
||||
width = 40,
|
||||
height = 20,
|
||||
aspectRatio = 40f / 20f,
|
||||
caption = "Narrow image with null aspectRatio",
|
||||
width = 80,
|
||||
height = 150,
|
||||
aspectRatio = null,
|
||||
),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
),
|
||||
)
|
||||
}
|
||||
ATimelineItemEventRow(
|
||||
event = aTimelineItemEvent(
|
||||
isMine = false,
|
||||
content = aTimelineItemImageContent(
|
||||
filename = "image.jpg",
|
||||
caption = "Narrow image with null aspectRatio",
|
||||
width = 80,
|
||||
height = 150,
|
||||
aspectRatio = null,
|
||||
),
|
||||
groupPosition = TimelineItemGroupPosition.Last,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -39,7 +39,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@@ -52,8 +52,8 @@ fun TimelineItemStickerView(
|
||||
onContentClick: (() -> Unit)?,
|
||||
onLongClick: (() -> Unit)?,
|
||||
onShowClick: () -> Unit,
|
||||
contentValidationState: ContentValidationState,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationState: ContentValidationState = remember { DefaultContentValidationState() },
|
||||
) {
|
||||
val description = content.bestDescription.takeIf { it.isNotEmpty() } ?: stringResource(CommonStrings.common_image)
|
||||
|
||||
@@ -130,5 +130,6 @@ internal fun TimelineItemStickerViewPreview(@PreviewParameter(TimelineItemSticke
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
onShowClick = {},
|
||||
contentValidationState = NoopContentValidationState(),
|
||||
)
|
||||
}
|
||||
|
||||
+4
-2
@@ -51,7 +51,7 @@ import io.element.android.libraries.matrix.ui.media.MAX_THUMBNAIL_HEIGHT
|
||||
import io.element.android.libraries.matrix.ui.media.MAX_THUMBNAIL_WIDTH
|
||||
import io.element.android.libraries.matrix.ui.media.MediaRequestData
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState
|
||||
import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.libraries.ui.utils.a11y.isTalkbackActive
|
||||
@@ -63,8 +63,8 @@ fun TimelineItemVideoView(
|
||||
onContentClick: (() -> Unit)?,
|
||||
onLongClick: (() -> Unit)?,
|
||||
onShowContentClick: () -> Unit,
|
||||
contentValidationState: ContentValidationState,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationState: ContentValidationState = remember { DefaultContentValidationState() },
|
||||
) {
|
||||
val isTalkbackActive = isTalkbackActive()
|
||||
val a11yLabel = stringResource(CommonStrings.common_video)
|
||||
@@ -157,6 +157,7 @@ internal fun TimelineItemVideoViewPreview(@PreviewParameter(TimelineItemVideoCon
|
||||
onShowContentClick = {},
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
contentValidationState = NoopContentValidationState(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -169,5 +170,6 @@ internal fun TimelineItemVideoViewHideMediaContentPreview() = ElementPreview {
|
||||
onShowContentClick = {},
|
||||
onContentClick = {},
|
||||
onLongClick = {},
|
||||
contentValidationState = NoopContentValidationState(),
|
||||
)
|
||||
}
|
||||
|
||||
+3
-1
@@ -64,8 +64,8 @@ fun TimelineItemVoiceView(
|
||||
state: VoiceMessageState,
|
||||
content: TimelineItemVoiceContent,
|
||||
onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit,
|
||||
contentValidationValue: ContentValidationValue,
|
||||
modifier: Modifier = Modifier,
|
||||
contentValidationValue: ContentValidationValue = ContentValidationValue.Valid,
|
||||
) {
|
||||
fun playPause() {
|
||||
state.eventSink(VoiceMessageEvent.PlayPause)
|
||||
@@ -289,6 +289,7 @@ internal fun TimelineItemVoiceViewPreview(
|
||||
state = timelineItemVoiceViewParameters.state,
|
||||
content = timelineItemVoiceViewParameters.content,
|
||||
onContentLayoutChange = {},
|
||||
contentValidationValue = ContentValidationValue.Valid,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -302,6 +303,7 @@ internal fun TimelineItemVoiceViewUnifiedPreview() = ElementPreview {
|
||||
state = it.state,
|
||||
content = it.content,
|
||||
onContentLayoutChange = {},
|
||||
contentValidationValue = ContentValidationValue.Valid,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user