Skip to content

Commit d5a7a79

Browse files
style(reactions): Pin reactions to the bottom of the message bubble and make them Material Cards
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
1 parent 633c6a0 commit d5a7a79

24 files changed

+1225
-1021
lines changed

app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public void onBind(@NonNull ChatMessage message) {
4444
&& !Objects.equals(message.getMessage(), "{file}")
4545
) {
4646
Spanned processedMessageText = null;
47-
binding.incomingPreviewMessageBubble.setBackgroundResource(R.drawable.shape_grouped_incoming_message);
47+
binding.bubble.setBackgroundResource(R.drawable.shape_grouped_incoming_message);
4848
if (viewThemeUtils != null ) {
4949
processedMessageText = messageUtils.enrichChatMessageText(
5050
binding.messageCaption.getContext(),
5151
message,
5252
true,
5353
viewThemeUtils);
54-
viewThemeUtils.talk.themeIncomingMessageBubble(binding.incomingPreviewMessageBubble, true, false,
54+
viewThemeUtils.talk.themeIncomingMessageBubble(binding.bubble, true, false,
5555
false);
5656
}
5757

@@ -61,9 +61,9 @@ public void onBind(@NonNull ChatMessage message) {
6161
viewThemeUtils,
6262
processedMessageText,
6363
message,
64-
binding.incomingPreviewMessageBubble);
64+
binding.bubble);
6565
}
66-
binding.incomingPreviewMessageBubble.setOnClickListener(null);
66+
binding.bubble.setOnClickListener(null);
6767

6868
float textSize = 0;
6969
if (context != null) {
@@ -81,7 +81,7 @@ public void onBind(@NonNull ChatMessage message) {
8181
binding.messageCaption.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
8282
binding.messageCaption.setText(processedMessageText);
8383
} else {
84-
binding.incomingPreviewMessageBubble.setBackground(null);
84+
binding.bubble.setBackground(null);
8585
binding.messageCaption.setVisibility(View.GONE);
8686
}
8787
binding.messageAuthor.setText(message.getActorDisplayName());

app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public void onBind(@NonNull ChatMessage message) {
4444
&& !Objects.equals(message.getMessage(), "{file}")
4545
) {
4646
Spanned processedMessageText = null;
47-
binding.outgoingPreviewMessageBubble.setBackgroundResource(R.drawable.shape_grouped_outcoming_message);
47+
binding.bubble.setBackgroundResource(R.drawable.shape_grouped_outcoming_message);
4848
if (viewThemeUtils != null) {
4949
processedMessageText = messageUtils.enrichChatMessageText(
5050
binding.messageCaption.getContext(),
5151
message,
5252
false,
5353
viewThemeUtils);
54-
viewThemeUtils.talk.themeOutgoingMessageBubble(binding.outgoingPreviewMessageBubble, true, false,
54+
viewThemeUtils.talk.themeOutgoingMessageBubble(binding.bubble, true, false,
5555
false);
5656
}
5757

@@ -61,9 +61,9 @@ public void onBind(@NonNull ChatMessage message) {
6161
viewThemeUtils,
6262
processedMessageText,
6363
message,
64-
binding.outgoingPreviewMessageBubble);
64+
binding.bubble);
6565
}
66-
binding.outgoingPreviewMessageBubble.setOnClickListener(null);
66+
binding.bubble.setOnClickListener(null);
6767

6868
float textSize = 0;
6969
if (context != null) {
@@ -81,7 +81,7 @@ public void onBind(@NonNull ChatMessage message) {
8181
binding.messageCaption.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
8282
binding.messageCaption.setText(processedMessageText);
8383
} else {
84-
binding.outgoingPreviewMessageBubble.setBackground(null);
84+
binding.bubble.setBackground(null);
8585
binding.messageCaption.setVisibility(View.GONE);
8686
}
8787

app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.view.View
1111
import android.view.ViewGroup
1212
import android.widget.LinearLayout
1313
import android.widget.TextView
14+
import com.google.android.material.card.MaterialCardView
1415
import com.nextcloud.talk.chat.data.model.ChatMessage
1516
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
1617
import com.nextcloud.talk.ui.theme.ViewThemeUtils
@@ -39,9 +40,6 @@ class Reaction {
3940
true
4041
}
4142

42-
val amountParams = getAmountLayoutParams(context)
43-
val wrapperParams = getWrapperLayoutParams(context)
44-
4543
val paddingSide = DisplayUtils.convertDpToPixel(EMOJI_AND_AMOUNT_PADDING_SIDE, context).toInt()
4644
val paddingTop = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_TOP, context).toInt()
4745
val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt()
@@ -57,8 +55,6 @@ class Reaction {
5755
amount,
5856
EmojiWithAmountWrapperLayoutInfo(
5957
textColor,
60-
amountParams,
61-
wrapperParams,
6258
paddingSide,
6359
paddingTop,
6460
paddingBottom,
@@ -90,18 +86,23 @@ class Reaction {
9086
amount: Int,
9187
layoutInfo: EmojiWithAmountWrapperLayoutInfo,
9288
isBubbled: Boolean
93-
): LinearLayout {
89+
): MaterialCardView {
90+
val amountParams = getAmountLayoutParams(context)
91+
val wrapperParams = getWrapperLayoutParams(context)
92+
93+
val emojiContainer = MaterialCardView(context)
9494
val emojiWithAmountWrapper = LinearLayout(context)
9595
emojiWithAmountWrapper.orientation = LinearLayout.HORIZONTAL
9696

97-
emojiWithAmountWrapper.addView(getEmojiTextView(context, emoji))
98-
emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, layoutInfo.amountParams))
99-
emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams
97+
emojiWithAmountWrapper.addView(getEmojiTextView(context, emoji, amountParams))
98+
emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, amountParams))
99+
emojiWithAmountWrapper.layoutParams = wrapperParams
100100

101101
layoutInfo.viewThemeUtils.talk.setReactionsBackground(
102-
emojiWithAmountWrapper,
102+
emojiContainer,
103103
layoutInfo.isOutgoingMessage,
104-
layoutInfo.isSelfReaction
104+
layoutInfo.isSelfReaction,
105+
isBubbled
105106
)
106107

107108
emojiWithAmountWrapper.setPaddingRelative(
@@ -111,34 +112,49 @@ class Reaction {
111112
layoutInfo.paddingBottom
112113
)
113114

114-
return emojiWithAmountWrapper
115+
emojiContainer.addView(emojiWithAmountWrapper)
116+
val containerParams = getWrapperLayoutParams(context, REACTION_END_MARGIN)
117+
containerParams.marginStart = 0
118+
emojiContainer.layoutParams = containerParams
119+
emojiContainer.setStrokeWidth(DisplayUtils.convertDpToPixel(EMOJI_CONTAINER_STROKE_WIDTH, context).toInt())
120+
121+
return emojiContainer
115122
}
116123

117-
private fun getEmojiTextView(context: Context, emoji: String): EmojiTextView {
124+
private fun getEmojiTextView(
125+
context: Context,
126+
emoji: String,
127+
layoutParams: LinearLayout.LayoutParams
128+
): EmojiTextView {
118129
val reactionEmoji = EmojiTextView(context)
119130
reactionEmoji.text = emoji
131+
reactionEmoji.layoutParams = layoutParams
120132
return reactionEmoji
121133
}
122134

123135
private fun getReactionCount(
124136
context: Context,
125137
textColor: Int,
126138
amount: Int,
127-
amountParams: LinearLayout.LayoutParams
139+
layoutParams: LinearLayout.LayoutParams
128140
): TextView {
129141
val reactionAmount = TextView(context)
130142
reactionAmount.setTextColor(textColor)
131143
reactionAmount.text = amount.toString()
132-
reactionAmount.layoutParams = amountParams
144+
reactionAmount.layoutParams = layoutParams
133145
return reactionAmount
134146
}
135147

136-
private fun getWrapperLayoutParams(context: Context): LinearLayout.LayoutParams {
148+
private fun getWrapperLayoutParams(
149+
context: Context,
150+
endMarginInDp: Float = EMOJI_END_MARGIN
151+
): LinearLayout
152+
.LayoutParams {
137153
val wrapperParams = LinearLayout.LayoutParams(
138154
ViewGroup.LayoutParams.WRAP_CONTENT,
139155
ViewGroup.LayoutParams.WRAP_CONTENT
140156
)
141-
wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(EMOJI_END_MARGIN, context).toInt()
157+
wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(endMarginInDp, context).toInt()
142158
return wrapperParams
143159
}
144160

@@ -153,8 +169,6 @@ class Reaction {
153169

154170
private data class EmojiWithAmountWrapperLayoutInfo(
155171
val textColor: Int,
156-
val amountParams: LinearLayout.LayoutParams,
157-
val wrapperParams: LinearLayout.LayoutParams,
158172
val paddingSide: Int,
159173
val paddingTop: Int,
160174
val paddingBottom: Int,
@@ -164,10 +178,12 @@ class Reaction {
164178
)
165179

166180
companion object {
167-
const val AMOUNT_START_MARGIN: Float = 2F
168-
const val EMOJI_END_MARGIN: Float = 6F
181+
const val AMOUNT_START_MARGIN: Float = 4F
182+
const val EMOJI_END_MARGIN: Float = 4F
183+
const val REACTION_END_MARGIN: Float = 6F
169184
const val EMOJI_AND_AMOUNT_PADDING_SIDE: Float = 4F
170185
const val WRAPPER_PADDING_TOP: Float = 2F
171186
const val WRAPPER_PADDING_BOTTOM: Float = 3F
187+
const val EMOJI_CONTAINER_STROKE_WIDTH: Float = 1.5F
172188
}
173189
}

app/src/main/java/com/nextcloud/talk/adapters/messages/ThreadButton.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ 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.graphics.Color
2322
import androidx.compose.ui.res.colorResource
2423
import androidx.compose.ui.res.painterResource
2524
import androidx.compose.ui.res.pluralStringResource
@@ -43,14 +42,14 @@ fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {})
4342
OutlinedButton(
4443
onClick = onButtonClick,
4544
modifier = Modifier
46-
.padding(8.dp)
45+
.padding(0.dp)
4746
.height(24.dp),
48-
shape = RoundedCornerShape(9.dp),
49-
border = BorderStroke(1.dp, colorResource(R.color.grey_600)),
47+
shape = RoundedCornerShape(12.dp),
48+
border = BorderStroke(1.dp, colorResource(R.color.nc_incoming_text_default)),
5049
contentPadding = PaddingValues(0.dp),
5150
colors = ButtonDefaults.outlinedButtonColors(
52-
containerColor = Color.Transparent,
53-
contentColor = colorResource(R.color.grey_600)
51+
containerColor = colorResource(R.color.bg_message_list_incoming_bubble),
52+
contentColor = colorResource(R.color.nc_incoming_text_default)
5453
)
5554
) {
5655
Icon(
@@ -59,12 +58,12 @@ fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {})
5958
modifier = Modifier
6059
.size(20.dp)
6160
.padding(start = 5.dp, end = 2.dp),
62-
tint = colorResource(R.color.grey_600)
61+
tint = colorResource(R.color.nc_incoming_text_default)
6362
)
6463
Text(
6564
text = replyAmountText,
6665
modifier = Modifier
67-
.padding(end = 5.dp)
66+
.padding(end = 6.dp)
6867
)
6968
}
7069
}

app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,31 @@ class TalkSpecificViewThemeUtils @Inject constructor(
202202
}
203203
}
204204

205+
fun setReactionsBackground(card: MaterialCardView, outgoing: Boolean, isSelfReaction: Boolean, isBubbled: Boolean) {
206+
withScheme(card) { scheme ->
207+
if (isSelfReaction) {
208+
card.setCardBackgroundColor(dynamicColor.primaryContainer().getArgb(scheme))
209+
card.strokeColor = dynamicColor.primary().getArgb(scheme)
210+
} else {
211+
if (isBubbled) {
212+
card.setCardBackgroundColor(
213+
ContextCompat.getColor(
214+
card.context,
215+
R.color.bg_message_list_incoming_bubble
216+
)
217+
)
218+
card.strokeColor = dynamicColor.surface().getArgb(scheme)
219+
} else {
220+
card.setCardBackgroundColor(dynamicColor.surface().getArgb(scheme))
221+
card.strokeColor = ContextCompat.getColor(
222+
card.context,
223+
R.color.bg_message_list_incoming_bubble
224+
)
225+
}
226+
}
227+
}
228+
}
229+
205230
fun getPlaceholderImage(context: Context, mimetype: String?): Drawable? {
206231
val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype)
207232
val drawable = AppCompatResources.getDrawable(

0 commit comments

Comments
 (0)