File: new design for file timeline item

This commit is contained in:
ganfra
2023-06-01 18:41:54 +02:00
parent 04d4b6369a
commit d4eb60f2eb
7 changed files with 104 additions and 18 deletions

View File

@@ -18,12 +18,13 @@ package io.element.android.features.messages.impl.timeline.components.event
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Attachment
import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -33,6 +34,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContentProvider
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@@ -47,7 +49,6 @@ fun TimelineItemFileView(
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
@@ -57,16 +58,23 @@ fun TimelineItemFileView(
contentAlignment = Alignment.Center,
) {
Icon(
imageVector = Icons.Filled.Attachment,
modifier = Modifier.size(20.dp),
imageVector = Icons.Filled.AttachFile,
contentDescription = "OpenFile"
)
}
Text(
text = content.body,
modifier = Modifier.padding(horizontal = 8.dp),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Column(modifier = Modifier.padding(horizontal = 8.dp),) {
Text(
text = content.name,
maxLines = 2,
fontSize = 16.sp,
overflow = TextOverflow.Ellipsis
)
Text(
text = content.fileExtensionAndSize,
color = MaterialTheme.colorScheme.secondary,
)
}
}
}

View File

@@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
import io.element.android.features.messages.impl.timeline.util.FileSizeFormatter
import io.element.android.features.messages.impl.timeline.util.toHtmlDocument
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
@@ -34,7 +35,9 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import javax.inject.Inject
class TimelineItemContentMessageFactory @Inject constructor() {
class TimelineItemContentMessageFactory @Inject constructor(
private val fileSizeFormatter: FileSizeFormatter
) {
fun create(content: MessageContent): TimelineItemEventContent {
return when (val messageType = content.type) {
@@ -70,11 +73,13 @@ class TimelineItemContentMessageFactory @Inject constructor() {
)
}
is FileMessageType -> TimelineItemFileContent(
body = messageType.body,
name = messageType.body,
thumbnailSource = messageType.info?.thumbnailSource,
fileSource = messageType.source,
mimeType = messageType.info?.mimetype,
size = messageType.info?.size,
formattedFileSize = messageType.info?.size?.let {
fileSizeFormatter.format(it)
},
)
is NoticeMessageType -> TimelineItemNoticeContent(
body = messageType.body,

View File

@@ -19,11 +19,20 @@ package io.element.android.features.messages.impl.timeline.model.event
import io.element.android.libraries.matrix.api.media.MediaSource
data class TimelineItemFileContent(
val body: String,
val name: String,
val fileSource: MediaSource,
val thumbnailSource: MediaSource?,
val size: Long?,
val formattedFileSize: String?,
val mimeType: String?,
) : TimelineItemEventContent {
override val type: String = "TimelineItemFileContent"
private val fileExtension = name.substringAfterLast('.', "").uppercase()
val fileExtensionAndSize = buildString {
append(fileExtension)
if (formattedFileSize != null) {
append(' ')
append("($formattedFileSize)")
}
}
}

View File

@@ -25,14 +25,14 @@ open class TimelineItemFileContentProvider : PreviewParameterProvider<TimelineIt
get() = sequenceOf(
aTimelineItemFileContent("A file.pdf"),
aTimelineItemFileContent("A bigger name file.pdf"),
aTimelineItemFileContent("An even bigger file name which doesn't fit.pdf"),
aTimelineItemFileContent("An even bigger bigger bigger bigger bigger bigger bigger file name which doesn't fit .pdf"),
)
}
fun aTimelineItemFileContent(fileName: String) = TimelineItemFileContent(
body = fileName,
name = fileName,
thumbnailSource = MediaSource(url = ""),
fileSource = MediaSource(url = ""),
mimeType = MimeTypes.OctetStream,
size = 100
formattedFileSize = "100kB"
)

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.util
import android.content.Context
import android.text.format.Formatter
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import javax.inject.Inject
interface FileSizeFormatter {
/**
* Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
*/
fun format(fileSize: Long): String
}
@ContributesBinding(AppScope::class)
class AndroidFileSizeFormatter @Inject constructor(@ApplicationContext private val context: Context) : FileSizeFormatter {
override fun format(fileSize: Long): String {
return Formatter.formatShortFileSize(context, fileSize)
}
}

View File

@@ -31,6 +31,7 @@ import io.element.android.features.messages.impl.timeline.factories.event.Timeli
import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemDaySeparatorFactory
import io.element.android.features.messages.impl.timeline.factories.virtual.TimelineItemVirtualFactory
import io.element.android.features.messages.impl.timeline.groups.TimelineItemGrouper
import io.element.android.features.messages.timeline.FakeFileSizeFormatter
import io.element.android.libraries.dateformatter.test.FakeDaySeparatorFormatter
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
@@ -42,7 +43,7 @@ internal fun aTimelineItemsFactory(): TimelineItemsFactory {
dispatchers = testCoroutineDispatchers(),
eventItemFactory = TimelineItemEventFactory(
TimelineItemContentFactory(
messageFactory = TimelineItemContentMessageFactory(),
messageFactory = TimelineItemContentMessageFactory(FakeFileSizeFormatter()),
redactedMessageFactory = TimelineItemContentRedactedFactory(),
stickerFactory = TimelineItemContentStickerFactory(),
utdFactory = TimelineItemContentUTDFactory(),

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.timeline
import io.element.android.features.messages.impl.timeline.util.FileSizeFormatter
class FakeFileSizeFormatter : FileSizeFormatter {
override fun format(fileSize: Long): String {
return "$fileSize Bytes"
}
}