Skip to content

Commit 72bac46

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 72bac46

19 files changed

+1328
-1113
lines changed

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

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import android.view.View
1111
import android.view.ViewGroup
1212
import android.widget.LinearLayout
1313
import android.widget.TextView
14+
import androidx.core.content.ContextCompat
15+
import com.google.android.material.card.MaterialCardView
16+
import com.nextcloud.talk.R
1417
import com.nextcloud.talk.chat.data.model.ChatMessage
1518
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
1619
import com.nextcloud.talk.ui.theme.ViewThemeUtils
@@ -39,9 +42,6 @@ class Reaction {
3942
true
4043
}
4144

42-
val amountParams = getAmountLayoutParams(context)
43-
val wrapperParams = getWrapperLayoutParams(context)
44-
4545
val paddingSide = DisplayUtils.convertDpToPixel(EMOJI_AND_AMOUNT_PADDING_SIDE, context).toInt()
4646
val paddingTop = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_TOP, context).toInt()
4747
val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt()
@@ -57,8 +57,6 @@ class Reaction {
5757
amount,
5858
EmojiWithAmountWrapperLayoutInfo(
5959
textColor,
60-
amountParams,
61-
wrapperParams,
6260
paddingSide,
6361
paddingTop,
6462
paddingBottom,
@@ -90,18 +88,23 @@ class Reaction {
9088
amount: Int,
9189
layoutInfo: EmojiWithAmountWrapperLayoutInfo,
9290
isBubbled: Boolean
93-
): LinearLayout {
91+
): MaterialCardView {
92+
val amountParams = getAmountLayoutParams(context)
93+
val wrapperParams = getWrapperLayoutParams(context)
94+
95+
val emojiContainer = MaterialCardView(context)
9496
val emojiWithAmountWrapper = LinearLayout(context)
9597
emojiWithAmountWrapper.orientation = LinearLayout.HORIZONTAL
9698

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

101103
layoutInfo.viewThemeUtils.talk.setReactionsBackground(
102-
emojiWithAmountWrapper,
104+
emojiContainer,
103105
layoutInfo.isOutgoingMessage,
104-
layoutInfo.isSelfReaction
106+
layoutInfo.isSelfReaction,
107+
isBubbled
105108
)
106109

107110
emojiWithAmountWrapper.setPaddingRelative(
@@ -111,34 +114,49 @@ class Reaction {
111114
layoutInfo.paddingBottom
112115
)
113116

114-
return emojiWithAmountWrapper
117+
emojiContainer.addView(emojiWithAmountWrapper)
118+
val containerParams = getWrapperLayoutParams(context, REACTION_END_MARGIN)
119+
containerParams.marginStart = 0
120+
emojiContainer.layoutParams = containerParams
121+
emojiContainer.setStrokeWidth(DisplayUtils.convertDpToPixel(1.5F, context).toInt())
122+
123+
return emojiContainer
115124
}
116125

117-
private fun getEmojiTextView(context: Context, emoji: String): EmojiTextView {
126+
private fun getEmojiTextView(
127+
context: Context,
128+
emoji: String,
129+
layoutParams: LinearLayout.LayoutParams
130+
): EmojiTextView {
118131
val reactionEmoji = EmojiTextView(context)
119132
reactionEmoji.text = emoji
133+
reactionEmoji.layoutParams = layoutParams
120134
return reactionEmoji
121135
}
122136

123137
private fun getReactionCount(
124138
context: Context,
125139
textColor: Int,
126140
amount: Int,
127-
amountParams: LinearLayout.LayoutParams
141+
layoutParams: LinearLayout.LayoutParams
128142
): TextView {
129143
val reactionAmount = TextView(context)
130144
reactionAmount.setTextColor(textColor)
131145
reactionAmount.text = amount.toString()
132-
reactionAmount.layoutParams = amountParams
146+
reactionAmount.layoutParams = layoutParams
133147
return reactionAmount
134148
}
135149

136-
private fun getWrapperLayoutParams(context: Context): LinearLayout.LayoutParams {
150+
private fun getWrapperLayoutParams(
151+
context: Context,
152+
endMarginInDp: Float = EMOJI_END_MARGIN
153+
): LinearLayout
154+
.LayoutParams {
137155
val wrapperParams = LinearLayout.LayoutParams(
138156
ViewGroup.LayoutParams.WRAP_CONTENT,
139157
ViewGroup.LayoutParams.WRAP_CONTENT
140158
)
141-
wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(EMOJI_END_MARGIN, context).toInt()
159+
wrapperParams.marginEnd = DisplayUtils.convertDpToPixel(endMarginInDp, context).toInt()
142160
return wrapperParams
143161
}
144162

@@ -153,8 +171,6 @@ class Reaction {
153171

154172
private data class EmojiWithAmountWrapperLayoutInfo(
155173
val textColor: Int,
156-
val amountParams: LinearLayout.LayoutParams,
157-
val wrapperParams: LinearLayout.LayoutParams,
158174
val paddingSide: Int,
159175
val paddingTop: Int,
160176
val paddingBottom: Int,
@@ -164,8 +180,9 @@ class Reaction {
164180
)
165181

166182
companion object {
167-
const val AMOUNT_START_MARGIN: Float = 2F
168-
const val EMOJI_END_MARGIN: Float = 6F
183+
const val AMOUNT_START_MARGIN: Float = 4F
184+
const val EMOJI_END_MARGIN: Float = 4F
185+
const val REACTION_END_MARGIN: Float = 6F
169186
const val EMOJI_AND_AMOUNT_PADDING_SIDE: Float = 4F
170187
const val WRAPPER_PADDING_TOP: Float = 2F
171188
const val WRAPPER_PADDING_BOTTOM: Float = 3F

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.size
1515
import androidx.compose.foundation.shape.RoundedCornerShape
1616
import androidx.compose.material3.ButtonDefaults
1717
import androidx.compose.material3.Icon
18+
import androidx.compose.material3.MaterialTheme
1819
import androidx.compose.material3.OutlinedButton
1920
import androidx.compose.material3.Text
2021
import androidx.compose.runtime.Composable
@@ -26,10 +27,14 @@ import androidx.compose.ui.res.pluralStringResource
2627
import androidx.compose.ui.res.stringResource
2728
import androidx.compose.ui.tooling.preview.Preview
2829
import androidx.compose.ui.unit.dp
30+
import com.nextcloud.android.common.ui.theme.MaterialSchemes
2931
import com.nextcloud.talk.R
3032

3133
@Composable
32-
fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {}) {
34+
fun ThreadButtonComposable(
35+
replyAmount: Int = 0,
36+
onButtonClick: () -> Unit = {}
37+
) {
3338
val replyAmountText = if (replyAmount == 0) {
3439
stringResource(R.string.thread_reply)
3540
} else {
@@ -43,14 +48,14 @@ fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {})
4348
OutlinedButton(
4449
onClick = onButtonClick,
4550
modifier = Modifier
46-
.padding(8.dp)
51+
.padding(0.dp)
4752
.height(24.dp),
4853
shape = RoundedCornerShape(9.dp),
49-
border = BorderStroke(1.dp, colorResource(R.color.grey_600)),
54+
border = BorderStroke(1.dp, colorResource(R.color.nc_incoming_text_default)),
5055
contentPadding = PaddingValues(0.dp),
5156
colors = ButtonDefaults.outlinedButtonColors(
52-
containerColor = Color.Transparent,
53-
contentColor = colorResource(R.color.grey_600)
57+
containerColor = colorResource(R.color.bg_message_list_incoming_bubble),
58+
contentColor = colorResource(R.color.nc_incoming_text_default)
5459
)
5560
) {
5661
Icon(
@@ -59,12 +64,12 @@ fun ThreadButtonComposable(replyAmount: Int = 0, onButtonClick: () -> Unit = {})
5964
modifier = Modifier
6065
.size(20.dp)
6166
.padding(start = 5.dp, end = 2.dp),
62-
tint = colorResource(R.color.grey_600)
67+
tint = colorResource(R.color.nc_incoming_text_default)
6368
)
6469
Text(
6570
text = replyAmountText,
6671
modifier = Modifier
67-
.padding(end = 5.dp)
72+
.padding(end = 6.dp)
6873
)
6974
}
7075
}

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)