Skip to content

Commit f054ed8

Browse files
Merge pull request #6157 from nextcloud/feat/6073/scheduledMsgViewMessageComposables
Scheduled msg view using message composables
2 parents 1999cc3 + b82eb78 commit f054ed8

9 files changed

Lines changed: 400 additions & 518 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ScheduledMessagesActivity.kt

Lines changed: 256 additions & 460 deletions
Large diffs are not rendered by default.

app/src/main/java/com/nextcloud/talk/chat/data/model/ChatMessage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ data class ChatMessage(
155155
val hasFileAttachment get() = messageParameters?.containsKey("file") == true
156156
val hasGeoLocation get() = messageParameters?.get("object")?.get("type") == "geo-location"
157157
val hasPoll get() = messageParameters?.get("object")?.get("type") == "talk-poll"
158-
val hasDeckCard get() = messageParameters?.containsKey("deck-card") == true
158+
val hasDeckCard get() = messageParameters?.get("object")?.get("type") == "deck-card"
159159

160160
val isSystemMessage = systemMessageType?.let { it != SystemMessageType.DUMMY } ?: false
161161

app/src/main/java/com/nextcloud/talk/chat/data/model/DeckCardParameters.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
package com.nextcloud.talk.chat.data.model
99

1010
class DeckCardParameters(messageParameters: HashMap<String?, HashMap<String?, String?>>?) :
11-
RichObjectParameters(messageParameters, "deck-card") {
11+
RichObjectParameters(messageParameters, "object") {
1212

1313
val id = string("id")
1414
val name = string("name")

app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import com.nextcloud.talk.utils.ApiUtils
1919
import com.nextcloud.talk.utils.CapabilitiesUtil
2020
import com.nextcloud.talk.utils.DrawableUtils
2121
import com.nextcloud.talk.utils.MimetypeUtils
22+
import java.time.Instant
2223
import java.time.LocalDate
24+
import java.time.ZoneId
2325

2426
// immutable class for chat message UI. only val, no vars!
2527
@Stable // Consider evaluating @Immutable once all nested types comply.
@@ -31,6 +33,7 @@ data class ChatMessageUi(
3133
val actorDisplayName: String,
3234
val isThread: Boolean,
3335
val threadTitle: String,
36+
val threadTitleIconRes: Int = R.drawable.outline_forum_24,
3437
val threadReplies: Int,
3538
val incoming: Boolean,
3639
val isDeleted: Boolean,
@@ -95,7 +98,8 @@ enum class MessageStatusIcon {
9598
FAILED,
9699
SENDING,
97100
READ,
98-
SENT
101+
SENT,
102+
SCHEDULED
99103
}
100104

101105
// Domain model (ChatMessage) to UI model (ChatMessageUi)
@@ -149,6 +153,42 @@ fun ChatMessage.toUiModel(
149153
isHiddenByCollapse = hiddenByCollapse
150154
)
151155

156+
fun ChatMessage.toScheduledMessageUiModel(
157+
user: User,
158+
roomToken: String,
159+
parentMessage: ChatMessage? = null
160+
): ChatMessageUi {
161+
val sendAtTimestamp = sendAt?.toLong() ?: timestamp
162+
return ChatMessageUi(
163+
id = token?.toIntOrNull() ?: token.hashCode(),
164+
message = getRichText(),
165+
plainMessage = message.orEmpty(),
166+
renderMarkdown = renderMarkdown != false,
167+
actorDisplayName = actorDisplayName.orEmpty(),
168+
isThread = isThread,
169+
threadTitle = threadTitle.orEmpty(),
170+
threadReplies = threadReplies ?: 0,
171+
incoming = false,
172+
isDeleted = isDeleted,
173+
avatarUrl = null,
174+
statusIcon = MessageStatusIcon.SCHEDULED,
175+
timestamp = sendAtTimestamp,
176+
date = Instant.ofEpochSecond(sendAtTimestamp).atZone(ZoneId.systemDefault()).toLocalDate(),
177+
content = getMessageTypeContent(user, this),
178+
roomToken = roomToken,
179+
activeUserId = user.userId,
180+
activeUserBaseUrl = user.baseUrl,
181+
messageParameters = normalizeMessageParameters(),
182+
reactions = emptyList(),
183+
isEdited = lastEditTimestamp != 0L,
184+
parentMessage = parentMessage?.toScheduledMessageUiModel(user, roomToken),
185+
replyable = false,
186+
isGrouped = false,
187+
isGroupedWithNext = false,
188+
isSilent = silent
189+
)
190+
}
191+
152192
private fun ChatMessage.normalizeMessageParameters(): Map<String, Map<String, String>> =
153193
messageParameters
154194
.orEmpty()

app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ internal val LocalReactionLongClickHandler = compositionLocalOf<(Int) -> Unit> {
9797
internal val LocalOpenThreadHandler = compositionLocalOf<(Int) -> Unit> { {} }
9898
internal val LocalQuotedMessageClickHandler = compositionLocalOf<(Int) -> Unit> { {} }
9999
internal val LocalMessageLongClickHandler = compositionLocalOf<(Int) -> Unit> { {} }
100+
internal val LocalShowThreadButton = compositionLocalOf { true }
100101

101102
private enum class MetadataLayoutMode {
102103
CAPTION,
@@ -463,7 +464,8 @@ private fun BoxScope.OverlayMetadataBadge(uiMessage: ChatMessageUi) {
463464

464465
@Composable
465466
private fun PinnedReactionsRow(uiMessage: ChatMessageUi, conversationThreadId: Long?, modifier: Modifier = Modifier) {
466-
val showThreadButton = isFirstMessageOfThreadInNormalChat(uiMessage, conversationThreadId)
467+
val showThreadButton = isFirstMessageOfThreadInNormalChat(uiMessage, conversationThreadId) &&
468+
LocalShowThreadButton.current
467469
if (!showThreadButton && uiMessage.reactions.isEmpty()) return
468470

469471
val onReactionClick = LocalReactionClickHandler.current
@@ -480,6 +482,7 @@ private fun PinnedReactionsRow(uiMessage: ChatMessageUi, conversationThreadId: L
480482
if (showThreadButton) {
481483
ThreadButtonComposable(
482484
replyAmount = uiMessage.threadReplies,
485+
incoming = uiMessage.incoming,
483486
onButtonClick = { onOpenThread(uiMessage.id) }
484487
)
485488
}
@@ -731,13 +734,15 @@ fun ReadStatus(message: ChatMessageUi, color: Color = colorScheme.onSurfaceVaria
731734
MessageStatusIcon.SENDING -> painterResource(R.drawable.baseline_schedule_24)
732735
MessageStatusIcon.READ -> painterResource(R.drawable.ic_check_all)
733736
MessageStatusIcon.SENT -> painterResource(R.drawable.ic_check)
737+
MessageStatusIcon.SCHEDULED -> painterResource(R.drawable.outline_schedule_24)
734738
}
735739

736740
val contentDescription = when (message.statusIcon) {
737741
MessageStatusIcon.FAILED -> stringResource(R.string.nc_message_failed)
738742
MessageStatusIcon.SENDING -> stringResource(R.string.nc_message_sending)
739743
MessageStatusIcon.READ -> stringResource(R.string.nc_message_read)
740744
MessageStatusIcon.SENT -> stringResource(R.string.nc_message_sent)
745+
MessageStatusIcon.SCHEDULED -> stringResource(R.string.nc_message_scheduled)
741746
}
742747

743748
Icon(
@@ -761,19 +766,21 @@ fun ThreadTitle(
761766
modifier = Modifier
762767
.padding(horizontal = padding, vertical = 10.dp)
763768
) {
764-
val threadIcon = painterResource(R.drawable.outline_forum_24)
769+
val threadIcon = painterResource(message.threadTitleIconRes)
765770
Icon(
766771
threadIcon,
767772
"",
773+
tint = colorScheme.onSurface,
768774
modifier = Modifier
769-
.padding(end = 6.dp)
775+
.padding(top = 2.dp, end = 6.dp)
770776
.size(18.dp)
771-
.align(Alignment.CenterVertically)
777+
.align(Alignment.Top)
772778
)
773779
Text(
774780
text = message.threadTitle,
775781
fontSize = regularTextSize,
776-
fontWeight = FontWeight.SemiBold
782+
fontWeight = FontWeight.SemiBold,
783+
color = colorScheme.onSurface
777784
)
778785
}
779786
}

app/src/main/java/com/nextcloud/talk/ui/chat/DeckMessage.kt

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ package com.nextcloud.talk.ui.chat
99

1010
import androidx.compose.foundation.layout.Column
1111
import androidx.compose.foundation.layout.Row
12-
import androidx.compose.foundation.layout.Spacer
12+
import androidx.compose.foundation.layout.fillMaxWidth
1313
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
1415
import androidx.compose.material3.Icon
16+
import androidx.compose.material3.MaterialTheme
1517
import androidx.compose.material3.MaterialTheme.colorScheme
18+
import androidx.compose.material3.Surface
1619
import androidx.compose.material3.Text
1720
import androidx.compose.runtime.Composable
21+
import androidx.compose.ui.Alignment
1822
import androidx.compose.ui.Modifier
1923
import androidx.compose.ui.platform.LocalResources
2024
import androidx.compose.ui.res.painterResource
@@ -25,7 +29,8 @@ import com.nextcloud.talk.R
2529
import com.nextcloud.talk.chat.ui.model.ChatMessageUi
2630
import com.nextcloud.talk.chat.ui.model.MessageTypeContent
2731

28-
private const val AUTHOR_TEXT_SIZE = 12
32+
private val headerTextSize = 16.sp
33+
private val headerIconSize = 18.dp
2934

3035
@Composable
3136
fun DeckMessage(
@@ -40,32 +45,43 @@ fun DeckMessage(
4045
conversationThreadId = conversationThreadId,
4146
forceTimeBelow = true,
4247
content = {
43-
Column {
44-
if (typeContent.cardName.isNotEmpty()) {
45-
val cardDescription = String.format(
46-
LocalResources.current.getString(R.string.deck_card_description),
47-
typeContent.stackName,
48-
typeContent.boardName
49-
)
50-
Row {
51-
Icon(
52-
painter = painterResource(R.drawable.deck),
53-
tint = colorScheme.onSurface,
54-
contentDescription = null
55-
)
56-
Spacer(modifier = Modifier.padding(start = 8.dp))
48+
if (typeContent.cardName.isNotEmpty()) {
49+
val cardDescription = String.format(
50+
LocalResources.current.getString(R.string.deck_card_description),
51+
typeContent.stackName,
52+
typeContent.boardName
53+
)
54+
Surface(
55+
shape = MaterialTheme.shapes.small,
56+
tonalElevation = 1.dp,
57+
modifier = Modifier
58+
.fillMaxWidth()
59+
.padding(start = 8.dp, end = 8.dp, bottom = 8.dp, top = 4.dp)
60+
) {
61+
Column(modifier = Modifier.padding(8.dp)) {
62+
Row {
63+
Icon(
64+
painter = painterResource(R.drawable.deck),
65+
tint = colorScheme.onSurface,
66+
contentDescription = null,
67+
modifier = Modifier
68+
.padding(top = 2.dp, end = 6.dp)
69+
.size(headerIconSize)
70+
.align(Alignment.Top)
71+
)
72+
Text(
73+
text = typeContent.cardName,
74+
fontSize = headerTextSize,
75+
color = colorScheme.onSurface,
76+
fontWeight = FontWeight.SemiBold
77+
)
78+
}
5779
Text(
58-
text = typeContent.cardName,
59-
fontSize = AUTHOR_TEXT_SIZE.sp,
80+
text = cardDescription,
6081
color = colorScheme.onSurface,
61-
fontWeight = FontWeight.Bold
82+
fontSize = headerTextSize
6283
)
6384
}
64-
Text(
65-
text = cardDescription,
66-
color = colorScheme.onSurface,
67-
fontSize = AUTHOR_TEXT_SIZE.sp
68-
)
6985
}
7086
}
7187
}

app/src/main/java/com/nextcloud/talk/ui/chat/PollMessage.kt

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ package com.nextcloud.talk.ui.chat
99

1010
import androidx.compose.foundation.layout.Column
1111
import androidx.compose.foundation.layout.Row
12+
import androidx.compose.foundation.layout.fillMaxWidth
1213
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
1315
import androidx.compose.material3.Icon
16+
import androidx.compose.material3.MaterialTheme
1417
import androidx.compose.material3.MaterialTheme.colorScheme
18+
import androidx.compose.material3.Surface
1519
import androidx.compose.material3.Text
1620
import androidx.compose.material3.TextButton
1721
import androidx.compose.runtime.Composable
@@ -26,7 +30,8 @@ import com.nextcloud.talk.R
2630
import com.nextcloud.talk.chat.ui.model.ChatMessageUi
2731
import com.nextcloud.talk.chat.ui.model.MessageTypeContent
2832

29-
private const val AUTHOR_TEXT_SIZE = 12
33+
private val headerTextSize = 16.sp
34+
private val headerIconSize = 18.dp
3035

3136
@Composable
3237
fun PollMessage(
@@ -42,26 +47,34 @@ fun PollMessage(
4247
conversationThreadId = conversationThreadId,
4348
forceTimeBelow = true,
4449
content = {
45-
Column {
46-
Row(
47-
verticalAlignment = Alignment.CenterVertically
48-
) {
49-
Icon(
50-
painter = painterResource(R.drawable.ic_baseline_bar_chart_24),
51-
tint = colorScheme.onSurface,
52-
contentDescription = null
53-
)
54-
Text(
55-
typeContent.pollName,
56-
fontSize = AUTHOR_TEXT_SIZE.sp,
57-
color = colorScheme.onSurface,
58-
fontWeight = FontWeight.Bold,
59-
modifier = Modifier.padding(start = 4.dp)
60-
)
61-
}
62-
63-
TextButtonNoStyling(stringResource(R.string.message_poll_tap_to_open)) {
64-
onPollClick(typeContent.pollId, typeContent.pollName)
50+
Surface(
51+
shape = MaterialTheme.shapes.small,
52+
tonalElevation = 1.dp,
53+
modifier = Modifier
54+
.fillMaxWidth()
55+
.padding(start = 8.dp, end = 8.dp, bottom = 8.dp, top = 4.dp)
56+
) {
57+
Column(modifier = Modifier.padding(8.dp)) {
58+
Row {
59+
Icon(
60+
painter = painterResource(R.drawable.ic_baseline_bar_chart_24),
61+
tint = colorScheme.onSurface,
62+
contentDescription = null,
63+
modifier = Modifier
64+
.padding(top = 2.dp, end = 6.dp)
65+
.size(headerIconSize)
66+
.align(Alignment.Top)
67+
)
68+
Text(
69+
typeContent.pollName,
70+
fontSize = headerTextSize,
71+
color = colorScheme.onSurface,
72+
fontWeight = FontWeight.SemiBold
73+
)
74+
}
75+
TextButtonNoStyling(stringResource(R.string.message_poll_tap_to_open)) {
76+
onPollClick(typeContent.pollId, typeContent.pollName)
77+
}
6578
}
6679
}
6780
}
@@ -73,7 +86,7 @@ private fun TextButtonNoStyling(text: String, onClick: () -> Unit) {
7386
TextButton(onClick = onClick) {
7487
Text(
7588
text,
76-
fontSize = AUTHOR_TEXT_SIZE.sp
89+
fontSize = headerTextSize
7790
)
7891
}
7992
}

app/src/main/java/com/nextcloud/talk/ui/chat/ThreadButton.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@ import androidx.compose.material3.OutlinedButton
1919
import androidx.compose.material3.Text
2020
import androidx.compose.runtime.Composable
2121
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.platform.LocalContext
2223
import androidx.compose.ui.res.colorResource
2324
import androidx.compose.ui.res.painterResource
25+
import com.nextcloud.talk.ui.theme.LocalViewThemeUtils
2426
import androidx.compose.ui.res.pluralStringResource
2527
import androidx.compose.ui.res.stringResource
2628
import androidx.compose.ui.tooling.preview.Preview
2729
import androidx.compose.ui.unit.dp
2830
import com.nextcloud.talk.R
2931

3032
@Composable
31-
fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {}) {
33+
fun ThreadButtonComposable(replyAmount: Int = 0, incoming: Boolean = true, onButtonClick: () -> Unit = {}) {
34+
val themedColors = LocalViewThemeUtils.current.getColorScheme(LocalContext.current)
35+
val backgroundColor = if (incoming) {
36+
colorResource(R.color.bg_message_list_incoming_bubble)
37+
} else {
38+
themedColors.surfaceVariant
39+
}
3240
val replyAmountText = if (replyAmount == 0) {
3341
stringResource(R.string.thread_reply)
3442
} else {
@@ -45,10 +53,10 @@ fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {})
4553
.padding(0.dp)
4654
.height(24.dp),
4755
shape = RoundedCornerShape(12.dp),
48-
border = BorderStroke(1.dp, colorResource(R.color.nc_incoming_text_default)),
56+
border = BorderStroke(1.5.dp, themedColors.surface),
4957
contentPadding = PaddingValues(0.dp),
5058
colors = ButtonDefaults.outlinedButtonColors(
51-
containerColor = colorResource(R.color.bg_message_list_incoming_bubble),
59+
containerColor = backgroundColor,
5260
contentColor = colorResource(R.color.nc_incoming_text_default)
5361
)
5462
) {

app/src/main/res/values/strings.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ How to translate with transifex:
488488
<string name="nc_message_sent">Message sent</string>
489489
<string name="nc_message_read">Message read</string>
490490
<string name="nc_message_sending">Sending message</string>
491+
<string name="nc_message_scheduled">Message scheduled</string>
492+
<string name="nc_scheduled_thread">Scheduled thread</string>
493+
<string name="nc_reply_to_thread">Reply to thread: %1$s</string>
491494
<string name="nc_message_added_to_notes">Message added to notes</string>
492495
<string name="nc_message_failed">Failed to send message</string>
493496
<string name="nc_message_failed_to_send">Failed to send message:</string>
@@ -976,7 +979,6 @@ How to translate with transifex:
976979
<string name="nc_send_later">Send later</string>
977980
<string name="nc_schedule_message">Schedule message</string>
978981
<string name="nc_scheduled_messages">Scheduled messages</string>
979-
<string name="nc_message_scheduled">Message scheduled</string>
980982
<string name="nc_message_scheduled_at">Message scheduled for %1$s</string>
981983
<string name="nc_scheduled_time">Scheduled time</string>
982984
<string name="nc_reschedule_message_with_notification">Reschedule with notification</string>

0 commit comments

Comments
 (0)