Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,6 @@ private fun MessageContent(
conversationId = message.conversationId,
attachments = messageContent.attachments,
messageStyle = messageStyle,
accent = accent,
onImageAttachmentClick = onMultipartImageClick
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/

@file:Suppress("TooManyFunctions")

package com.wire.android.ui.home.conversations.messages.preview

import androidx.compose.foundation.background
Expand All @@ -35,6 +38,7 @@ import com.wire.android.ui.home.conversations.mock.mockMessageWithMarkdownTables
import com.wire.android.ui.home.conversations.mock.mockMessageWithMarkdownTextAndLinks
import com.wire.android.ui.home.conversations.mock.mockMessageWithText
import com.wire.android.ui.home.conversations.mock.mockMessageWithTextContent
import com.wire.android.ui.home.conversations.mock.mockedMultipartMessage
import com.wire.android.ui.home.conversations.model.ExpirationStatus
import com.wire.android.ui.home.conversations.model.MessageEditStatus
import com.wire.android.ui.home.conversations.model.MessageSource
Expand Down Expand Up @@ -407,3 +411,33 @@ fun PreviewMessageBubbleOtherWithMarkdownTablesAndBlocks() {
}
}
}

@PreviewMultipleThemes
@Composable
fun PreviewMessageBubbleSelfWithMultipartAsset() {
WireTheme {
Box(modifier = Modifier.background(color = colorsScheme().surface)) {
RegularMessageItem(
message = mockedMultipartMessage(source = MessageSource.Self),
conversationDetailsData = ConversationDetailsData.None(null),
clickActions = MessageClickActions.Content(),
isBubbleUiEnabled = true
)
}
}
}

@PreviewMultipleThemes
@Composable
fun PreviewMessageBubbleOtherWithMultipartAsset() {
WireTheme {
Box(modifier = Modifier.background(color = colorsScheme().surface)) {
RegularMessageItem(
message = mockedMultipartMessage(source = MessageSource.OtherUser),
conversationDetailsData = ConversationDetailsData.None(null),
clickActions = MessageClickActions.Content(),
isBubbleUiEnabled = true
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,15 @@ import com.wire.android.ui.home.conversations.model.messagetypes.image.VisualMed
import com.wire.android.ui.home.conversationslist.model.Membership
import com.wire.android.util.ui.UIText
import com.wire.android.util.ui.toUIText
import com.wire.kalium.logic.data.asset.AssetTransferStatus
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.message.AssetContent.AssetMetadata
import com.wire.kalium.logic.data.message.CellAssetContent
import com.wire.kalium.logic.data.user.ConnectionState
import com.wire.kalium.logic.data.user.UserAssetId
import com.wire.kalium.logic.data.user.UserAvailabilityStatus
import kotlinx.collections.immutable.persistentListOf
import kotlinx.datetime.Instant
import okio.Path.Companion.toPath

Expand Down Expand Up @@ -440,6 +444,64 @@ fun mockedImageUIMessage(
source = source
)

private fun mockedCellAssetContent(
name: String,
id: String,
mimeType: String,
transferStatus: AssetTransferStatus = AssetTransferStatus.NOT_DOWNLOADED,
metadata: AssetMetadata? = null
) =
CellAssetContent(
id = id,
versionId = "v1",
mimeType = mimeType,
assetPath = null,
assetSize = 21957335,
localPath = name,
contentUrl = name,
contentUrlExpiresAt = null,
previewUrl = name,
metadata = metadata,
transferStatus = transferStatus
)

fun mockedMultipartMessage(
messageId: String = "messageId",
messageStatus: MessageStatus = MessageStatus(
flowStatus = MessageFlowStatus.Sent,
expirationStatus = ExpirationStatus.NotExpirable
),
header: MessageHeader = MessageHeader(
username = UIText.DynamicString("John Doe"),
membership = Membership.External,
showLegalHoldIndicator = false,
messageTime = mockMessageTime,
messageStatus = messageStatus,
messageId = messageId,
connectionState = ConnectionState.ACCEPTED,
isSenderDeleted = false,
isSenderUnavailable = false
),
source: MessageSource = MessageSource.Self,
content: UIMessageContent.Regular = UIMessageContent.Multipart(
messageBody = MessageBody(UIText.DynamicString("Text")),
attachments = persistentListOf(
mockedCellAssetContent(name = "1.zip", mimeType = "application/zip", id = "1"),
mockedCellAssetContent(name = "2.pdf", mimeType = "application/pdf", id = "2"),
mockedCellAssetContent(name = "3.txt", mimeType = "text/plain", id = "3", transferStatus = AssetTransferStatus.NOT_FOUND),
mockedCellAssetContent(name = "4.png", mimeType = "image/png", id = "4", metadata = AssetMetadata.Image(1920, 1080)),
mockedCellAssetContent(name = "5.mp4", mimeType = "video/mp4", id = "5", metadata = AssetMetadata.Video(1920, 1080, 60000L)),
),
)
) = UIMessage.Regular(
conversationId = ConversationId("value", "domain"),
userAvatarData = UserAvatarData(null, UserAvailabilityStatus.AVAILABLE),
header = header,
messageContent = content,
messageFooter = mockEmptyFooter,
source = source
)

@Suppress("LongMethod", "MagicNumber")
fun getMockedMessages(): List<UIMessage> = listOf(
UIMessage.Regular(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.hilt.navigation.compose.hiltViewModel
import coil.decode.Decoder
import coil.request.ImageRequest
Expand All @@ -39,7 +40,6 @@ import com.wire.android.ui.common.multipart.toUiModel
import com.wire.android.ui.home.conversations.messages.item.MessageStyle
import com.wire.android.ui.home.conversations.model.messagetypes.multipart.grid.AssetGridPreview
import com.wire.android.ui.home.conversations.model.messagetypes.multipart.standalone.AssetPreview
import com.wire.android.ui.theme.Accent
import com.wire.kalium.logic.data.asset.AssetTransferStatus
import com.wire.kalium.logic.data.asset.isFailed
import com.wire.kalium.logic.data.id.ConversationId
Expand All @@ -56,8 +56,10 @@ fun MultipartAttachmentsView(
messageStyle: MessageStyle,
onImageAttachmentClick: (String) -> Unit,
modifier: Modifier = Modifier,
accent: Accent = Accent.Unknown,
viewModel: MultipartAttachmentsViewModel = hiltViewModel<MultipartAttachmentsViewModel>(key = conversationId.value),
viewModel: MultipartAttachmentsViewModel = when {
LocalInspectionMode.current -> MultipartAttachmentsViewModelPreview
else -> hiltViewModel<MultipartAttachmentsViewModelImpl>(key = conversationId.value)
}
) {

// TODO I found out that empty attachments list is not handled here and it shows empty message with no information
Expand All @@ -66,7 +68,6 @@ fun MultipartAttachmentsView(
AssetPreview(
item = it,
messageStyle = messageStyle,
accent = accent,
onClick = {
viewModel.onClick(
attachment = it,
Expand Down Expand Up @@ -106,7 +107,6 @@ fun MultipartAttachmentsView(
openInImageViewer = onImageAttachmentClick,
)
},
accent = accent
)
}
}
Expand All @@ -121,7 +121,6 @@ fun MultipartAttachmentsView(
private fun AttachmentsList(
attachments: List<MultipartAttachmentUi>,
messageStyle: MessageStyle,
accent: Accent,
onClick: (MultipartAttachmentUi) -> Unit,
modifier: Modifier = Modifier,
) {
Expand All @@ -135,7 +134,6 @@ private fun AttachmentsList(
showWithPreview = true,
onClick = { onClick(it) },
modifier = modifier,
accent = accent
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,9 @@
import javax.inject.Inject
import kotlin.time.Duration.Companion.hours

@HiltViewModel
class MultipartAttachmentsViewModel @Inject constructor(
private val refreshAsset: RefreshCellAssetStateUseCase,
private val download: DownloadCellFileUseCase,
private val fileManager: FileManager,
private val kaliumFileSystem: KaliumFileSystem,
) : ViewModel() {

private companion object {
val DEFAULT_CONTENT_URL_EXPIRY_MS = 1.hours.inWholeMilliseconds
}

private val refreshed = ExpiringMap<String, Unit>(
scope = viewModelScope,
expirationMs = DEFAULT_CONTENT_URL_EXPIRY_MS,
delegate = mutableMapOf(),
onEntryExpired = { key, _ ->
viewModelScope.launch { refreshAsset(key) }
}
)

private val uploadProgress = mutableStateMapOf<String, Float>()

interface MultipartAttachmentsViewModel {
fun onClick(attachment: MultipartAttachmentUi, openInImageViewer: (String) -> Unit)
fun refreshAssetState(attachment: MultipartAttachmentUi)
fun mapAttachments(
attachments: List<MessageAttachment>
): List<MultipartAttachmentGroup> {
Expand Down Expand Up @@ -107,8 +87,38 @@
data class Media(val attachments: List<MultipartAttachmentUi>) : MultipartAttachmentGroup
data class Files(val attachments: List<MultipartAttachmentUi>) : MultipartAttachmentGroup
}
}

@Suppress("EmptyFunctionBlock")
object MultipartAttachmentsViewModelPreview : MultipartAttachmentsViewModel {
override fun onClick(attachment: MultipartAttachmentUi, openInImageViewer: (String) -> Unit) {}

Check failure on line 94 in app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this function is empty or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=wireapp_wire-android&issues=AZrukZl-tzhnK5C2WxLz&open=AZrukZl-tzhnK5C2WxLz&pullRequest=4466
override fun refreshAssetState(attachment: MultipartAttachmentUi) {}

Check failure on line 95 in app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a nested comment explaining why this function is empty or complete the implementation.

See more on https://sonarcloud.io/project/issues?id=wireapp_wire-android&issues=AZrukZl-tzhnK5C2WxL0&open=AZrukZl-tzhnK5C2WxL0&pullRequest=4466

Check warning on line 95 in app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt#L94-L95

Added lines #L94 - L95 were not covered by tests
}

@HiltViewModel
class MultipartAttachmentsViewModelImpl @Inject constructor(
private val refreshAsset: RefreshCellAssetStateUseCase,
private val download: DownloadCellFileUseCase,
private val fileManager: FileManager,
private val kaliumFileSystem: KaliumFileSystem,
) : ViewModel(), MultipartAttachmentsViewModel {

private companion object {
val DEFAULT_CONTENT_URL_EXPIRY_MS = 1.hours.inWholeMilliseconds
}

private val refreshed = ExpiringMap<String, Unit>(
scope = viewModelScope,
expirationMs = DEFAULT_CONTENT_URL_EXPIRY_MS,
delegate = mutableMapOf(),
onEntryExpired = { key, _ ->
viewModelScope.launch { refreshAsset(key) }

Check warning on line 115 in app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversations/model/messagetypes/multipart/MultipartAttachmentsViewModel.kt#L115

Added line #L115 was not covered by tests
}
)

private val uploadProgress = mutableStateMapOf<String, Float>()

fun onClick(attachment: MultipartAttachmentUi, openInImageViewer: (String) -> Unit) {
override fun onClick(attachment: MultipartAttachmentUi, openInImageViewer: (String) -> Unit) {
when {
attachment.isImage() && !attachment.fileNotFound() -> openInImageViewer(attachment.uuid)
attachment.fileNotFound() -> { refreshAssetState(attachment) }
Expand All @@ -118,7 +128,7 @@
}
}

fun refreshAssetState(attachment: MultipartAttachmentUi) {
override fun refreshAssetState(attachment: MultipartAttachmentUi) {

if (attachment.source != AssetSource.CELL) return
if (refreshed.contains(attachment.uuid)) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.wire.android.ui.home.conversations.model.messagetypes.multipart.grid

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand All @@ -39,7 +40,6 @@ import com.wire.android.ui.common.dimensions
import com.wire.android.ui.common.multipart.AssetSource
import com.wire.android.ui.common.multipart.MultipartAttachmentUi
import com.wire.android.ui.home.conversations.messages.item.MessageStyle
import com.wire.android.ui.home.conversations.messages.item.isBubble
import com.wire.android.ui.home.conversations.model.messagetypes.multipart.transferProgressColor
import com.wire.android.ui.theme.WireTheme
import com.wire.android.util.ui.PreviewMultipleThemes
Expand All @@ -57,13 +57,24 @@ internal fun AssetGridPreview(
modifier = modifier
.aspectRatio(1f)
.clickable { onClick() }
.applyIf(messageStyle.isBubble()) {
.clip(RoundedCornerShape(dimensions().messageAttachmentCornerSize))
.applyIf(messageStyle == MessageStyle.BUBBLE_SELF) {
background(colorsScheme().selfBubble.secondary)
}
.applyIf(messageStyle == MessageStyle.BUBBLE_OTHER) {
background(colorsScheme().otherBubble.secondary)
}
.applyIf(messageStyle == MessageStyle.NORMAL) {
background(
color = colorsScheme().surfaceVariant,
color = colorsScheme().surface,
shape = RoundedCornerShape(dimensions().messageAttachmentCornerSize)
)
border(
width = dimensions().spacing1x,
color = colorsScheme().outline,
shape = RoundedCornerShape(dimensions().messageAttachmentCornerSize)
)
}
.clip(RoundedCornerShape(dimensions().messageAttachmentCornerSize))
) {

if (item.transferStatus != AssetTransferStatus.NOT_FOUND) {
Expand Down Expand Up @@ -92,7 +103,7 @@ internal fun AssetGridPreview(
)
}
} else {
AssetNotAvailableGridPreview()
AssetNotAvailableGridPreview(messageStyle)
}
}
}
Expand Down
Loading