11/*
22 * Nextcloud Talk - Android Client
33 *
4- * SPDX-FileCopyrightText: 2022 Marcel Hibbe <dev@mhibbe.de>
5- * SPDX-FileCopyrightText: 2021-2022 Andy Scherzinger <infoi@andy-scherzinger.de>
6- * SPDX-FileCopyrightText: 2017 Mario Danic <mario@lovelyhq.com>
4+ * SPDX-FileCopyrightText: 2017-2026 Nextcloud GmbH and Nextcloud contributors
75 * SPDX-License-Identifier: GPL-3.0-or-later
86 */
97package com.nextcloud.talk.adapters.items
108
11- import android.annotation.SuppressLint
129import android.content.Context
13- import android.view.View
14- import androidx.constraintlayout.widget.ConstraintLayout
15- import androidx.core.content.res.ResourcesCompat
16- import com.nextcloud.talk.PhoneUtils.isPhoneNumber
1710import com.nextcloud.talk.R
18- import com.nextcloud.talk.adapters.items.ParticipantItem.ParticipantItemViewHolder
19- import com.nextcloud.talk.data.user.model.User
20- import com.nextcloud.talk.extensions.loadDefaultAvatar
21- import com.nextcloud.talk.extensions.loadFederatedUserAvatar
22- import com.nextcloud.talk.extensions.loadGuestAvatar
23- import com.nextcloud.talk.extensions.loadUserAvatar
2411import com.nextcloud.talk.models.json.mention.Mention
25- import com.nextcloud.talk.models.json.status.StatusType
26- import com.nextcloud.talk.ui.StatusDrawable
27- import com.nextcloud.talk.ui.theme.ViewThemeUtils
28- import com.nextcloud.talk.utils.DisplayUtils
29- import eu.davidea.flexibleadapter.FlexibleAdapter
30- import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
31- import eu.davidea.flexibleadapter.items.IFilterable
32- import eu.davidea.flexibleadapter.items.IFlexible
3312import java.util.Objects
34- import java.util.regex.Pattern
3513
36- class MentionAutocompleteItem (
37- mention : Mention ,
38- private val currentUser : User ,
39- private val context : Context ,
40- @JvmField val roomToken : String ,
41- private val viewThemeUtils : ViewThemeUtils
42- ) : AbstractFlexibleItem<ParticipantItemViewHolder>(),
43- IFilterable <String ?> {
14+ class MentionAutocompleteItem (mention : Mention , context : Context , @JvmField val roomToken : String ) {
4415 @JvmField
4516 var source: String?
4617
@@ -52,9 +23,15 @@ class MentionAutocompleteItem(
5223
5324 @JvmField
5425 val displayName: String?
55- private val status: String?
56- private val statusIcon: String?
57- private val statusMessage: String?
26+
27+ @JvmField
28+ val status: String?
29+
30+ @JvmField
31+ val statusIcon: String?
32+
33+ @JvmField
34+ val statusMessage: String?
5835
5936 init {
6037 mentionId = mention.mentionId
@@ -74,186 +51,16 @@ class MentionAutocompleteItem(
7451 statusMessage = mention.statusMessage
7552 }
7653
77- override fun equals (o : Any? ): Boolean =
78- if (o is MentionAutocompleteItem ) {
79- objectId == o .objectId && displayName == o .displayName
54+ override fun equals (other : Any? ): Boolean =
55+ if (other is MentionAutocompleteItem ) {
56+ objectId == other .objectId && displayName == other .displayName
8057 } else {
8158 false
8259 }
8360
8461 override fun hashCode (): Int = Objects .hash(objectId, displayName)
8562
86- override fun getLayoutRes (): Int = R .layout.rv_item_conversation_info_participant
87-
88- override fun createViewHolder (view : View , adapter : FlexibleAdapter <IFlexible <* >? >? ): ParticipantItemViewHolder =
89- ParticipantItemViewHolder (view, adapter)
90-
91- @SuppressLint(" SetTextI18n" )
92- override fun bindViewHolder (
93- adapter : FlexibleAdapter <IFlexible <* >? >,
94- holder : ParticipantItemViewHolder ,
95- position : Int ,
96- payloads : List <Any >
97- ) {
98- holder.binding.nameText.setTextColor(
99- ResourcesCompat .getColor(
100- context.resources,
101- R .color.conversation_item_header,
102- null
103- )
104- )
105- if (adapter.hasFilter()) {
106- viewThemeUtils.talk.themeAndHighlightText(
107- holder.binding.nameText,
108- displayName,
109- adapter.getFilter(String ::class .java).toString()
110- )
111- viewThemeUtils.talk.themeAndHighlightText(
112- holder.binding.secondaryText,
113- " @$objectId " ,
114- adapter.getFilter(String ::class .java).toString()
115- )
116- } else {
117- holder.binding.nameText.text = displayName
118- }
119- setAvatar(holder, objectId)
120- drawStatus(holder)
121- }
122-
123- private fun setAvatar (holder : ParticipantItemViewHolder , objectId : String? ) {
124- when (source) {
125- SOURCE_CALLS -> {
126- run {
127- if (isPhoneNumber(displayName)) {
128- holder.binding.avatarView.loadUserAvatar(
129- viewThemeUtils.talk.themePlaceholderAvatar(
130- holder.binding.avatarView,
131- R .drawable.ic_phone_small
132- )
133- )
134- } else {
135- holder.binding.avatarView.loadUserAvatar(
136- viewThemeUtils.talk.themePlaceholderAvatar(
137- holder.binding.avatarView,
138- R .drawable.ic_avatar_group_small
139- )
140- )
141- }
142- }
143- }
144-
145- SOURCE_GROUPS -> {
146- holder.binding.avatarView.loadUserAvatar(
147- viewThemeUtils.talk.themePlaceholderAvatar(
148- holder.binding.avatarView,
149- R .drawable
150- .ic_avatar_group_small
151- )
152- )
153- }
154-
155- SOURCE_FEDERATION -> {
156- val darkTheme = if (DisplayUtils .isDarkModeOn(context)) 1 else 0
157- holder.binding.avatarView.loadFederatedUserAvatar(
158- currentUser,
159- currentUser.baseUrl!! ,
160- roomToken,
161- objectId!! ,
162- darkTheme,
163- requestBigSize = true ,
164- ignoreCache = false
165- )
166- }
167-
168- SOURCE_GUESTS , SOURCE_EMAILS -> {
169- if (displayName.equals(context.resources.getString(R .string.nc_guest))) {
170- holder.binding.avatarView.loadDefaultAvatar(viewThemeUtils)
171- } else {
172- holder.binding.avatarView.loadGuestAvatar(currentUser, displayName!! , false )
173- }
174- }
175-
176- SOURCE_TEAMS -> {
177- holder.binding.avatarView.loadUserAvatar(
178- viewThemeUtils.talk.themePlaceholderAvatar(
179- holder.binding.avatarView,
180- R .drawable
181- .ic_avatar_team_small
182- )
183- )
184- }
185-
186- else -> {
187- holder.binding.avatarView.loadUserAvatar(
188- currentUser,
189- objectId!! ,
190- requestBigSize = true ,
191- ignoreCache = false
192- )
193- }
194- }
195- }
196-
197- private fun drawStatus (holder : ParticipantItemViewHolder ) {
198- val size = DisplayUtils .convertDpToPixel(STATUS_SIZE_IN_DP , context)
199- holder.binding.userStatusImage.setImageDrawable(
200- StatusDrawable (
201- status,
202- NO_ICON ,
203- size,
204- context.resources.getColor(R .color.bg_default),
205- context
206- )
207- )
208- if (statusMessage != null ) {
209- holder.binding.conversationInfoStatusMessage.text = statusMessage
210- alignUsernameVertical(holder, 0f )
211- } else {
212- holder.binding.conversationInfoStatusMessage.text = " "
213- alignUsernameVertical(holder, NO_USER_STATUS_DP_FROM_TOP )
214- }
215- if (! statusIcon.isNullOrEmpty()) {
216- holder.binding.participantStatusEmoji.setText(statusIcon)
217- } else {
218- holder.binding.participantStatusEmoji.visibility = View .GONE
219- }
220- if (status != null && status == StatusType .DND .string) {
221- if (statusMessage.isNullOrEmpty()) {
222- holder.binding.conversationInfoStatusMessage.setText(R .string.dnd)
223- }
224- } else if (status != null && status == StatusType .BUSY .string) {
225- if (statusMessage.isNullOrEmpty()) {
226- holder.binding.conversationInfoStatusMessage.setText(R .string.busy)
227- }
228- } else if (status != null && status == StatusType .AWAY .string) {
229- if (statusMessage.isNullOrEmpty()) {
230- holder.binding.conversationInfoStatusMessage.setText(R .string.away)
231- }
232- }
233- }
234-
235- private fun alignUsernameVertical (holder : ParticipantItemViewHolder , densityPixelsFromTop : Float ) {
236- val layoutParams = holder.binding.nameText.layoutParams as ConstraintLayout .LayoutParams
237- layoutParams.topMargin = DisplayUtils .convertDpToPixel(densityPixelsFromTop, context).toInt()
238- holder.binding.nameText.setLayoutParams(layoutParams)
239- }
240-
241- override fun filter (constraint : String? ): Boolean =
242- objectId != null &&
243- Pattern
244- .compile(constraint, Pattern .CASE_INSENSITIVE or Pattern .LITERAL )
245- .matcher(objectId)
246- .find() ||
247- displayName != null &&
248- Pattern
249- .compile(constraint, Pattern .CASE_INSENSITIVE or Pattern .LITERAL )
250- .matcher(displayName)
251- .find()
252-
25363 companion object {
254- private const val STATUS_SIZE_IN_DP = 9f
255- private const val NO_ICON = " "
256- private const val NO_USER_STATUS_DP_FROM_TOP : Float = 10f
25764 const val SOURCE_CALLS = " calls"
25865 const val SOURCE_GUESTS = " guests"
25966 const val SOURCE_GROUPS = " groups"
0 commit comments