diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java deleted file mode 100644 index 610758002..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * @author Marcel Hibbe - * @author Andy Scherzinger - * Copyright (C) 2021-2022 Andy Scherzinger - * Copyright (C) 2022 Marcel Hibbe - * Copyright (C) 2017 Mario Danic - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.items; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Build; -import android.view.View; - -import com.nextcloud.talk.R; -import com.nextcloud.talk.data.user.model.User; -import com.nextcloud.talk.extensions.ImageViewExtensionsKt; -import com.nextcloud.talk.models.json.mention.Mention; -import com.nextcloud.talk.models.json.status.StatusType; -import com.nextcloud.talk.ui.StatusDrawable; -import com.nextcloud.talk.ui.theme.ViewThemeUtils; -import com.nextcloud.talk.utils.DisplayUtils; - -import java.util.List; -import java.util.Objects; -import java.util.regex.Pattern; - -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.core.content.res.ResourcesCompat; -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; -import eu.davidea.flexibleadapter.items.IFilterable; -import eu.davidea.flexibleadapter.items.IFlexible; - -public class MentionAutocompleteItem extends AbstractFlexibleItem - implements IFilterable { - - private static final float STATUS_SIZE_IN_DP = 9f; - private static final String NO_ICON = ""; - public static final String SOURCE_CALLS = "calls"; - public static final String SOURCE_GUESTS = "guests"; - - public static final String SOURCE_GROUPS = "groups"; - public static final String SOURCE_FEDERATION = "federated_users"; - - private String source; - private final String mentionId; - private final String objectId; - private final String displayName; - private final String status; - private final String statusIcon; - private final String statusMessage; - private final User currentUser; - private final Context context; - private final String roomToken; - private final ViewThemeUtils viewThemeUtils; - - public MentionAutocompleteItem( - Mention mention, - User currentUser, - Context activityContext, String roomToken, ViewThemeUtils viewThemeUtils) { - this.mentionId = mention.getMentionId(); - this.objectId = mention.getId(); - this.displayName = mention.getLabel(); - this.source = mention.getSource(); - this.status = mention.getStatus(); - this.statusIcon = mention.getStatusIcon(); - this.statusMessage = mention.getStatusMessage(); - this.currentUser = currentUser; - this.context = activityContext; - this.viewThemeUtils = viewThemeUtils; - this.roomToken = roomToken; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getMentionId() { - return mentionId; - } - - public String getObjectId() { - return objectId; - } - - public String getDisplayName() { - return displayName; - } - - public String getRoomToken() { - return roomToken; - } - - @Override - public boolean equals(Object o) { - if (o instanceof MentionAutocompleteItem inItem) { - return (objectId.equals(inItem.objectId) && displayName.equals(inItem.displayName)); - } - - return false; - } - - @Override - public int hashCode() { - return Objects.hash(objectId, displayName); - } - - @Override - public int getLayoutRes() { - return R.layout.rv_item_conversation_info_participant; - } - - @Override - public ParticipantItem.ParticipantItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new ParticipantItem.ParticipantItemViewHolder(view, adapter); - } - - @SuppressLint("SetTextI18n") - @Override - public void bindViewHolder(FlexibleAdapter adapter, - ParticipantItem.ParticipantItemViewHolder holder, - int position, - List payloads) { - - holder.binding.nameText.setTextColor( - ResourcesCompat.getColor(context.getResources(), - R.color.conversation_item_header, - null)); - if (adapter.hasFilter()) { - viewThemeUtils.talk.themeAndHighlightText(holder.binding.nameText, - displayName, - String.valueOf(adapter.getFilter(String.class))); - viewThemeUtils.talk.themeAndHighlightText(holder.binding.secondaryText, - "@" + objectId, - String.valueOf(adapter.getFilter(String.class))); - } else { - holder.binding.nameText.setText(displayName); - holder.binding.secondaryText.setText("@" + objectId); - } - - String avatarId = objectId; - switch (source) { - case SOURCE_CALLS: {} - case SOURCE_GROUPS: { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - ImageViewExtensionsKt.loadUserAvatar( - holder.binding.avatarView, - viewThemeUtils.talk.themePlaceholderAvatar( - holder.binding.avatarView, - R.drawable.ic_avatar_group)); - } else { - ImageViewExtensionsKt.loadUserAvatar(holder.binding.avatarView, R.drawable.ic_circular_group); - } - break; - } - case SOURCE_FEDERATION: { - int darkTheme = (DisplayUtils.isDarkModeOn(this.context))? 1 : 0; - ImageViewExtensionsKt.loadFederatedUserAvatar(holder.binding.avatarView, - currentUser, - Objects.requireNonNull(currentUser.getBaseUrl()), - roomToken, - avatarId, - darkTheme, - true, - false); - break; - } - case SOURCE_GUESTS: { - avatarId = displayName; - } - default: { - ImageViewExtensionsKt.loadUserAvatar(holder.binding.avatarView, currentUser, avatarId, true, false); - } - } - - drawStatus(holder); - } - - private void drawStatus(ParticipantItem.ParticipantItemViewHolder holder) { - float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context); - holder.binding.userStatusImage.setImageDrawable(new StatusDrawable( - status, - NO_ICON, - size, - context.getResources().getColor(R.color.bg_default), - context)); - - if (statusMessage != null) { - holder.binding.conversationInfoStatusMessage.setText(statusMessage); - alignUsernameVertical(holder, 0); - } else { - holder.binding.conversationInfoStatusMessage.setText(""); - alignUsernameVertical(holder, 10); - } - - if (statusIcon != null && !statusIcon.isEmpty()) { - holder.binding.participantStatusEmoji.setText(statusIcon); - } else { - holder.binding.participantStatusEmoji.setVisibility(View.GONE); - } - - if (status != null && status.equals(StatusType.DND.getString())) { - if (statusMessage == null || statusMessage.isEmpty()) { - holder.binding.conversationInfoStatusMessage.setText(R.string.dnd); - } - } else if (status != null && status.equals(StatusType.AWAY.getString())) { - if (statusMessage == null || statusMessage.isEmpty()) { - holder.binding.conversationInfoStatusMessage.setText(R.string.away); - } - } - } - - private void alignUsernameVertical(ParticipantItem.ParticipantItemViewHolder holder, float densityPixelsFromTop) { - ConstraintLayout.LayoutParams layoutParams = - (ConstraintLayout.LayoutParams) holder.binding.nameText.getLayoutParams(); - layoutParams.topMargin = (int) DisplayUtils.convertDpToPixel(densityPixelsFromTop, context); - holder.binding.nameText.setLayoutParams(layoutParams); - } - - @Override - public boolean filter(String constraint) { - return objectId != null && - Pattern - .compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) - .matcher(objectId) - .find() || - displayName != null && - Pattern - .compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) - .matcher(displayName) - .find(); - } -} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.kt b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.kt new file mode 100644 index 000000000..9751135ed --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.kt @@ -0,0 +1,247 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Marcel Hibbe + * @author Andy Scherzinger + * Copyright (C) 2021-2022 Andy Scherzinger + * Copyright (C) 2022 Marcel Hibbe + * Copyright (C) 2017 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.nextcloud.talk.adapters.items + +import android.annotation.SuppressLint +import android.content.Context +import android.os.Build +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.content.res.ResourcesCompat +import com.nextcloud.talk.R +import com.nextcloud.talk.adapters.items.ParticipantItem.ParticipantItemViewHolder +import com.nextcloud.talk.data.user.model.User +import com.nextcloud.talk.extensions.loadFederatedUserAvatar +import com.nextcloud.talk.extensions.loadUserAvatar +import com.nextcloud.talk.models.json.mention.Mention +import com.nextcloud.talk.models.json.status.StatusType +import com.nextcloud.talk.ui.StatusDrawable +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import com.nextcloud.talk.utils.DisplayUtils +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem +import eu.davidea.flexibleadapter.items.IFilterable +import eu.davidea.flexibleadapter.items.IFlexible +import java.util.Objects +import java.util.regex.Pattern + +class MentionAutocompleteItem( + mention: Mention, + private val currentUser: User, + private val context: Context, + @JvmField val roomToken: String, + private val viewThemeUtils: ViewThemeUtils +) : AbstractFlexibleItem(), IFilterable { + @JvmField + var source: String? + + @JvmField + val mentionId: String? + + @JvmField + val objectId: String? + + @JvmField + val displayName: String? + private val status: String? + private val statusIcon: String? + private val statusMessage: String? + + init { + mentionId = mention.mentionId + objectId = mention.id + displayName = mention.label + source = mention.source + status = mention.status + statusIcon = mention.statusIcon + statusMessage = mention.statusMessage + } + + override fun equals(o: Any?): Boolean { + return if (o is MentionAutocompleteItem) { + objectId == o.objectId && displayName == o.displayName + } else { + false + } + } + + override fun hashCode(): Int { + return Objects.hash(objectId, displayName) + } + + override fun getLayoutRes(): Int { + return R.layout.rv_item_conversation_info_participant + } + + override fun createViewHolder(view: View, adapter: FlexibleAdapter?>?): ParticipantItemViewHolder { + return ParticipantItemViewHolder(view, adapter) + } + + @SuppressLint("SetTextI18n") + override fun bindViewHolder( + adapter: FlexibleAdapter?>, + holder: ParticipantItemViewHolder, + position: Int, + payloads: List + ) { + holder.binding.nameText.setTextColor( + ResourcesCompat.getColor( + context.resources, + R.color.conversation_item_header, + null + ) + ) + if (adapter.hasFilter()) { + viewThemeUtils.talk.themeAndHighlightText( + holder.binding.nameText, + displayName, + adapter.getFilter(String::class.java).toString() + ) + viewThemeUtils.talk.themeAndHighlightText( + holder.binding.secondaryText, + "@$objectId", + adapter.getFilter(String::class.java).toString() + ) + } else { + holder.binding.nameText.text = displayName + holder.binding.secondaryText.text = "@$objectId" + } + var avatarId = objectId + when (source) { + SOURCE_CALLS -> { + run {} + run { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.avatarView.loadUserAvatar( + viewThemeUtils.talk.themePlaceholderAvatar( + holder.binding.avatarView, + R.drawable.ic_avatar_group + ) + ) + } else { + holder.binding.avatarView.loadUserAvatar(R.drawable.ic_circular_group) + } + } + } + + SOURCE_GROUPS -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.avatarView.loadUserAvatar( + viewThemeUtils.talk.themePlaceholderAvatar( + holder.binding.avatarView, + R.drawable.ic_avatar_group + ) + ) + } else { + holder.binding.avatarView.loadUserAvatar(R.drawable.ic_circular_group) + } + } + + SOURCE_FEDERATION -> { + val darkTheme = if (DisplayUtils.isDarkModeOn(context)) 1 else 0 + holder.binding.avatarView.loadFederatedUserAvatar( + currentUser, + currentUser.baseUrl!!, + roomToken, + avatarId!!, + darkTheme, + true, + false + ) + } + + SOURCE_GUESTS -> { + run { avatarId = displayName } + run { holder.binding.avatarView.loadUserAvatar(currentUser, avatarId!!, true, false) } + } + + else -> { + holder.binding.avatarView.loadUserAvatar(currentUser, avatarId!!, true, false) + } + } + drawStatus(holder) + } + + private fun drawStatus(holder: ParticipantItemViewHolder) { + val size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context) + holder.binding.userStatusImage.setImageDrawable( + StatusDrawable( + status, + NO_ICON, + size, + context.resources.getColor(R.color.bg_default), + context + ) + ) + if (statusMessage != null) { + holder.binding.conversationInfoStatusMessage.text = statusMessage + alignUsernameVertical(holder, 0f) + } else { + holder.binding.conversationInfoStatusMessage.text = "" + alignUsernameVertical(holder, 10f) + } + if (!statusIcon.isNullOrEmpty()) { + holder.binding.participantStatusEmoji.setText(statusIcon) + } else { + holder.binding.participantStatusEmoji.visibility = View.GONE + } + if (status != null && status == StatusType.DND.string) { + if (statusMessage.isNullOrEmpty()) { + holder.binding.conversationInfoStatusMessage.setText(R.string.dnd) + } + } else if (status != null && status == StatusType.AWAY.string) { + if (statusMessage.isNullOrEmpty()) { + holder.binding.conversationInfoStatusMessage.setText(R.string.away) + } + } + } + + private fun alignUsernameVertical(holder: ParticipantItemViewHolder, densityPixelsFromTop: Float) { + val layoutParams = holder.binding.nameText.layoutParams as ConstraintLayout.LayoutParams + layoutParams.topMargin = DisplayUtils.convertDpToPixel(densityPixelsFromTop, context).toInt() + holder.binding.nameText.setLayoutParams(layoutParams) + } + + override fun filter(constraint: String?): Boolean { + return objectId != null && + Pattern + .compile(constraint, Pattern.CASE_INSENSITIVE or Pattern.LITERAL) + .matcher(objectId) + .find() || + displayName != null && + Pattern + .compile(constraint, Pattern.CASE_INSENSITIVE or Pattern.LITERAL) + .matcher(displayName) + .find() + } + + companion object { + private const val STATUS_SIZE_IN_DP = 9f + private const val NO_ICON = "" + const val SOURCE_CALLS = "calls" + const val SOURCE_GUESTS = "guests" + const val SOURCE_GROUPS = "groups" + const val SOURCE_FEDERATION = "federated_users" + } +} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java index c6bfc90cc..664062549 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java @@ -301,7 +301,7 @@ public class ParticipantItem extends AbstractFlexibleItem Mention mention = new Mention(); MentionAutocompleteItem mentionAutocompleteItem = (MentionAutocompleteItem) adapter.getItem(position); if (mentionAutocompleteItem != null) { - String mentionId = mentionAutocompleteItem.getMentionId(); + String mentionId = mentionAutocompleteItem.mentionId; if (mentionId != null) { mention.setMentionId(mentionId); } - mention.setId(mentionAutocompleteItem.getObjectId()); - mention.setLabel(mentionAutocompleteItem.getDisplayName()); - mention.setSource(mentionAutocompleteItem.getSource()); - mention.setRoomToken(mentionAutocompleteItem.getRoomToken()); + mention.setId(mentionAutocompleteItem.objectId); + mention.setLabel(mentionAutocompleteItem.displayName); + mention.setSource(mentionAutocompleteItem.source); + mention.setRoomToken(mentionAutocompleteItem.roomToken); dispatchClick(mention); } return true;