Merge pull request #4473 from nextcloud/feature/4363/displayEmailGuests

Feature/4363/display email guests
This commit is contained in:
Marcel Hibbe 2024-11-26 22:12:19 +01:00 committed by GitHub
commit a1315d3689
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 152 additions and 106 deletions

View file

@ -172,6 +172,10 @@ public class ParticipantDisplayItem {
return raisedHand; return raisedHand;
} }
public Participant.ActorType getActorType() {
return actorType;
}
public void addObserver(Observer observer) { public void addObserver(Observer observer) {
participantDisplayItemNotifier.addObserver(observer); participantDisplayItemNotifier.addObserver(observer);
} }

View file

@ -22,6 +22,7 @@ import android.widget.TextView;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.activities.CallActivity; import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.extensions.ImageViewExtensionsKt; import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
import com.nextcloud.talk.models.json.participants.Participant;
import org.webrtc.MediaStream; import org.webrtc.MediaStream;
import org.webrtc.MediaStreamTrack; import org.webrtc.MediaStreamTrack;
@ -143,8 +144,16 @@ public class ParticipantsAdapter extends BaseAdapter {
nickTextView.setVisibility(View.VISIBLE); nickTextView.setVisibility(View.VISIBLE);
nickTextView.setText(participantDisplayItem.getNick()); nickTextView.setText(participantDisplayItem.getNick());
} }
if (participantDisplayItem.getActorType() == Participant.ActorType.GUESTS ||
participantDisplayItem.getActorType() == Participant.ActorType.EMAILS) {
ImageViewExtensionsKt.loadFirstLetterAvatar(
imageView,
String.valueOf(participantDisplayItem.getNick().charAt(0))
);
} else {
ImageViewExtensionsKt.loadAvatarWithUrl(imageView,null, participantDisplayItem.getUrlForAvatar()); ImageViewExtensionsKt.loadAvatarWithUrl(imageView,null, participantDisplayItem.getUrlForAvatar());
} }
}
ImageView audioOffView = convertView.findViewById(R.id.remote_audio_off); ImageView audioOffView = convertView.findViewById(R.id.remote_audio_off);
if (!participantDisplayItem.isAudioEnabled()) { if (!participantDisplayItem.isAudioEnabled()) {

View file

@ -17,6 +17,7 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.adapters.items.ParticipantItem.ParticipantItemViewHolder import com.nextcloud.talk.adapters.items.ParticipantItem.ParticipantItemViewHolder
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.extensions.loadGuestAvatar
import com.nextcloud.talk.extensions.loadUserAvatar import com.nextcloud.talk.extensions.loadUserAvatar
import com.nextcloud.talk.models.json.mention.Mention import com.nextcloud.talk.models.json.mention.Mention
import com.nextcloud.talk.models.json.status.StatusType import com.nextcloud.talk.models.json.status.StatusType
@ -109,7 +110,6 @@ class MentionAutocompleteItem(
) )
} else { } else {
holder.binding.nameText.text = displayName holder.binding.nameText.text = displayName
holder.binding.secondaryText.text = "@$objectId"
} }
var avatarId = objectId var avatarId = objectId
when (source) { when (source) {
@ -147,9 +147,9 @@ class MentionAutocompleteItem(
) )
} }
SOURCE_GUESTS -> { SOURCE_GUESTS, SOURCE_EMAILS -> {
run { avatarId = displayName } avatarId = displayName
run { holder.binding.avatarView.loadUserAvatar(currentUser, avatarId!!, true, false) } holder.binding.avatarView.loadGuestAvatar(currentUser, avatarId!!, false)
} }
else -> { else -> {
@ -218,6 +218,7 @@ class MentionAutocompleteItem(
const val SOURCE_CALLS = "calls" const val SOURCE_CALLS = "calls"
const val SOURCE_GUESTS = "guests" const val SOURCE_GUESTS = "guests"
const val SOURCE_GROUPS = "groups" const val SOURCE_GROUPS = "groups"
const val SOURCE_EMAILS = "emails"
const val SOURCE_FEDERATION = "federated_users" const val SOURCE_FEDERATION = "federated_users"
} }
} }

View file

@ -21,16 +21,18 @@ import com.nextcloud.talk.adapters.items.ParticipantItem.ParticipantItemViewHold
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.RvItemConversationInfoParticipantBinding import com.nextcloud.talk.databinding.RvItemConversationInfoParticipantBinding
import com.nextcloud.talk.extensions.loadDefaultAvatar
import com.nextcloud.talk.extensions.loadDefaultGroupCallAvatar import com.nextcloud.talk.extensions.loadDefaultGroupCallAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.extensions.loadGuestAvatar import com.nextcloud.talk.extensions.loadFirstLetterAvatar
import com.nextcloud.talk.extensions.loadMailAvatar
import com.nextcloud.talk.extensions.loadUserAvatar import com.nextcloud.talk.extensions.loadUserAvatar
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.participants.Participant.InCallFlags import com.nextcloud.talk.models.json.participants.Participant.InCallFlags
import com.nextcloud.talk.models.json.status.StatusType import com.nextcloud.talk.models.json.status.StatusType
import com.nextcloud.talk.ui.StatusDrawable import com.nextcloud.talk.ui.StatusDrawable
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ConversationUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.DisplayUtils.convertDpToPixel import com.nextcloud.talk.utils.DisplayUtils.convertDpToPixel
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -45,7 +47,7 @@ class ParticipantItem(
val model: Participant, val model: Participant,
private val user: User, private val user: User,
private val viewThemeUtils: ViewThemeUtils, private val viewThemeUtils: ViewThemeUtils,
private val roomToken: String private val conversation: ConversationModel
) : AbstractFlexibleItem<ParticipantItemViewHolder>(), IFilterable<String?> { ) : AbstractFlexibleItem<ParticipantItemViewHolder>(), IFilterable<String?> {
var isOnline = true var isOnline = true
override fun equals(o: Any?): Boolean { override fun equals(o: Any?): Boolean {
@ -128,7 +130,13 @@ class ParticipantItem(
Participant.ParticipantType.GUEST -> { Participant.ParticipantType.GUEST -> {
userType = sharedApplication!!.getString(R.string.nc_guest) userType = sharedApplication!!.getString(R.string.nc_guest)
if (model.calculatedActorType == Participant.ActorType.EMAILS) { if (model.calculatedActorType == Participant.ActorType.EMAILS) {
userType = sharedApplication!!.getString(R.string.nc_email) userType = sharedApplication!!.getString(R.string.nc_guest)
}
if (model.invitedActorId?.isNotEmpty() == true &&
ConversationUtils.isParticipantOwnerOrModerator(conversation)) {
holder.binding.conversationInfoStatusMessage.text = model.invitedActorId
alignUsernameVertical(holder, 0f)
} }
} }
@ -165,6 +173,7 @@ class ParticipantItem(
} }
} }
@SuppressLint("StringFormatInvalid")
private fun showCallIcons(holder: ParticipantItemViewHolder) { private fun showCallIcons(holder: ParticipantItemViewHolder) {
val resources = sharedApplication!!.resources val resources = sharedApplication!!.resources
val inCallFlag = model.inCall val inCallFlag = model.inCall
@ -197,20 +206,18 @@ class ParticipantItem(
holder.binding.avatarView.loadDefaultGroupCallAvatar(viewThemeUtils) holder.binding.avatarView.loadDefaultGroupCallAvatar(viewThemeUtils)
} }
Participant.ActorType.EMAILS -> {
holder.binding.avatarView.loadMailAvatar(viewThemeUtils)
}
Participant.ActorType.USERS -> { Participant.ActorType.USERS -> {
holder.binding.avatarView.loadUserAvatar(user, model.calculatedActorId!!, true, false) holder.binding.avatarView.loadUserAvatar(user, model.calculatedActorId!!, true, false)
} }
Participant.ActorType.GUESTS -> { Participant.ActorType.GUESTS, Participant.ActorType.EMAILS -> {
var displayName: String? = sharedApplication!!.resources.getString(R.string.nc_guest) if (model.displayName.isNullOrEmpty()) {
if (!TextUtils.isEmpty(model.displayName)) { holder.binding.avatarView.loadDefaultAvatar(viewThemeUtils)
displayName = model.displayName } else {
holder.binding.avatarView.loadFirstLetterAvatar(
model.displayName!!.first().toString()
)
} }
holder.binding.avatarView.loadGuestAvatar(user, displayName!!, false)
} }
Participant.ActorType.FEDERATED -> { Participant.ActorType.FEDERATED -> {
@ -218,7 +225,7 @@ class ParticipantItem(
holder.binding.avatarView.loadFederatedUserAvatar( holder.binding.avatarView.loadFederatedUserAvatar(
user, user,
user.baseUrl!!, user.baseUrl!!,
roomToken, conversation.token,
model.actorId!!, model.actorId!!,
darkTheme, darkTheme,
true, true,

View file

@ -31,6 +31,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ChatMessageUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -168,7 +169,7 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold
} }
if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) {
setAvatarOnMessage(message) ChatMessageUtils().setAvatarOnMessage(binding.messageUserAvatar, message, viewThemeUtils)
} else { } else {
if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { if (message.isOneToOneConversation || message.isFormerOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -179,19 +180,6 @@ class IncomingDeckCardViewHolder(incomingView: View, payload: Any) : MessageHold
} }
} }
private fun setAvatarOnMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
binding.messageUserAvatar.loadFederatedUserAvatar(message)
}
}
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
} }

View file

@ -28,6 +28,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ChatMessageUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -146,7 +147,7 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
} }
if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) {
setAvatarOnMessage(message) ChatMessageUtils().setAvatarOnMessage(binding.messageUserAvatar, message, viewThemeUtils)
} else { } else {
if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { if (message.isOneToOneConversation || message.isFormerOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -157,19 +158,6 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
} }
} }
private fun setAvatarOnMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
binding.messageUserAvatar.loadFederatedUserAvatar(message)
}
}
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
} }

View file

@ -28,6 +28,7 @@ import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.polls.ui.PollMainDialogFragment import com.nextcloud.talk.polls.ui.PollMainDialogFragment
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ChatMessageUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -153,7 +154,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
} }
if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) {
setAvatarOnMessage(message) ChatMessageUtils().setAvatarOnMessage(binding.messageUserAvatar, message, viewThemeUtils)
} else { } else {
if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { if (message.isOneToOneConversation || message.isFormerOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -164,19 +165,6 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
} }
} }
private fun setAvatarOnMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
binding.messageUserAvatar.loadFederatedUserAvatar(message)
}
}
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
} }

View file

@ -26,9 +26,12 @@ import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding
import com.nextcloud.talk.extensions.loadBotsAvatar import com.nextcloud.talk.extensions.loadBotsAvatar
import com.nextcloud.talk.extensions.loadChangelogBotAvatar import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadDefaultAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.extensions.loadFirstLetterAvatar
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ChatMessageUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.TextMatchers import com.nextcloud.talk.utils.TextMatchers
import com.nextcloud.talk.utils.message.MessageUtils import com.nextcloud.talk.utils.message.MessageUtils
@ -153,7 +156,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
} }
if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) {
setAvatarOnMessage(message) ChatMessageUtils().setAvatarOnMessage(binding.messageUserAvatar, message, viewThemeUtils)
} else { } else {
if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { if (message.isOneToOneConversation || message.isFormerOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -164,19 +167,6 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
} }
} }
private fun setAvatarOnMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
binding.messageUserAvatar.loadFederatedUserAvatar(message)
}
}
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
} }
@ -252,17 +242,6 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
} }
} }
private fun showAvatarOnChatMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
}
}
fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) { fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) {
this.commonMessageInterface = commonMessageInterface this.commonMessageInterface = commonMessageInterface
} }

View file

@ -32,6 +32,7 @@ import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ChatMessageUtils
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -249,7 +250,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
} }
if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) { if (!message.isGrouped && !message.isOneToOneConversation && !message.isFormerOneToOneConversation) {
setAvatarOnMessage(message) ChatMessageUtils().setAvatarOnMessage(binding.messageUserAvatar, message, viewThemeUtils)
} else { } else {
if (message.isOneToOneConversation || message.isFormerOneToOneConversation) { if (message.isOneToOneConversation || message.isFormerOneToOneConversation) {
binding.messageUserAvatar.visibility = View.GONE binding.messageUserAvatar.visibility = View.GONE
@ -260,19 +261,6 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
} }
} }
private fun setAvatarOnMessage(message: ChatMessage) {
binding.messageUserAvatar.visibility = View.VISIBLE
if (message.actorType == "guests") {
// do nothing, avatar is set
} else if (message.actorType == "bots" && message.actorId == "changelog") {
binding.messageUserAvatar.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
binding.messageUserAvatar.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
binding.messageUserAvatar.loadFederatedUserAvatar(message)
}
}
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
} }

View file

@ -856,7 +856,8 @@ class MessageInputFragment : Fragment() {
val shouldQuote = mentionId.contains(" ") || val shouldQuote = mentionId.contains(" ") ||
mentionId.contains("@") || mentionId.contains("@") ||
mentionId.startsWith("guest/") || mentionId.startsWith("guest/") ||
mentionId.startsWith("group/") mentionId.startsWith("group/") ||
mentionId.startsWith("email/")
if (shouldQuote) { if (shouldQuote) {
mentionId = "\"" + mentionId + "\"" mentionId = "\"" + mentionId + "\""
} }

View file

@ -568,7 +568,7 @@ class ConversationInfoActivity :
for (i in participants.indices) { for (i in participants.indices) {
participant = participants[i] participant = participants[i]
userItem = ParticipantItem(this, participant, conversationUser, viewThemeUtils, conversationToken) userItem = ParticipantItem(this, participant, conversationUser, viewThemeUtils, conversation!!)
if (participant.sessionId != null) { if (participant.sessionId != null) {
userItem.isOnline = !participant.sessionId.equals("0") userItem.isOnline = !participant.sessionId.equals("0")
} else { } else {

View file

@ -10,12 +10,19 @@
package com.nextcloud.talk.extensions package com.nextcloud.talk.extensions
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.util.Log import android.util.Log
import android.widget.ImageView import android.widget.ImageView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import coil.annotation.ExperimentalCoilApi import coil.annotation.ExperimentalCoilApi
import coil.imageLoader import coil.imageLoader
import coil.load import coil.load
@ -35,6 +42,7 @@ import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.TextDrawable import com.nextcloud.talk.utils.TextDrawable
import java.util.Locale
private const val ROUNDING_PIXEL = 16f private const val ROUNDING_PIXEL = 16f
private const val TAG = "ImageViewExtensions" private const val TAG = "ImageViewExtensions"
@ -297,6 +305,21 @@ fun ImageView.loadNoteToSelfAvatar(): io.reactivex.disposables.Disposable {
) )
} }
fun ImageView.loadFirstLetterAvatar(letter: String): io.reactivex.disposables.Disposable {
val layers = arrayOfNulls<Drawable>(2)
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
layers[1] = createTextDrawable(context, letter.uppercase(Locale.ROOT))
val layerDrawable = LayerDrawable(layers)
val data: Any = layerDrawable
return DisposableWrapper(
load(data) {
transformations(CircleCropTransformation())
}
)
}
fun ImageView.loadChangelogBotAvatar(): io.reactivex.disposables.Disposable { fun ImageView.loadChangelogBotAvatar(): io.reactivex.disposables.Disposable {
return loadSystemAvatar() return loadSystemAvatar()
} }
@ -320,6 +343,11 @@ fun ImageView.loadDefaultGroupCallAvatar(viewThemeUtils: ViewThemeUtils): io.rea
return loadUserAvatar(data) return loadUserAvatar(data)
} }
fun ImageView.loadDefaultAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable {
val data: Any = viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.account_circle_96dp) as Any
return loadUserAvatar(data)
}
fun ImageView.loadDefaultPublicCallAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable { fun ImageView.loadDefaultPublicCallAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable {
val data: Any = viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.ic_avatar_link) as Any val data: Any = viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.ic_avatar_link) as Any
return loadUserAvatar(data) return loadUserAvatar(data)
@ -350,6 +378,32 @@ fun ImageView.loadGuestAvatar(baseUrl: String, name: String, big: Boolean): io.r
) )
} }
@Suppress("MagicNumber")
private fun createTextDrawable(context: Context, letter: String): Drawable {
val size = 100
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val paint = Paint().apply {
color = ResourcesCompat.getColor(context.resources, R.color.grey_600, null)
style = Paint.Style.FILL
}
canvas.drawRect(0f, 0f, size.toFloat(), size.toFloat(), paint)
val textPaint = Paint().apply {
color = Color.WHITE
textSize = size / 2f
isAntiAlias = true
textAlign = Paint.Align.CENTER
}
val xPos = size / 2f
val yPos = (canvas.height / 2 - (textPaint.descent() + textPaint.ascent()) / 2)
canvas.drawText(letter.take(1), xPos, yPos, textPaint)
return BitmapDrawable(context.resources, bitmap)
}
private class DisposableWrapper(private val disposable: coil.request.Disposable) : io.reactivex.disposables private class DisposableWrapper(private val disposable: coil.request.Disposable) : io.reactivex.disposables
.Disposable { .Disposable {

View file

@ -29,7 +29,7 @@ class ChatUtils {
if (individualHashMap != null) { if (individualHashMap != null) {
val type = individualHashMap["type"] val type = individualHashMap["type"]
resultMessage = if (type == "user" || type == "guest" || type == "call") { resultMessage = if (type == "user" || type == "guest" || type == "call" || type == "email") {
resultMessage?.replace("{$key}", "@" + individualHashMap["name"]) resultMessage?.replace("{$key}", "@" + individualHashMap["name"])
} else if (type == "geo-location") { } else if (type == "geo-location") {
individualHashMap["name"] individualHashMap["name"]

View file

@ -72,6 +72,9 @@ data class Participant(
@JsonField(name = ["statusMessage"]) @JsonField(name = ["statusMessage"])
var statusMessage: String? = null, var statusMessage: String? = null,
@JsonField(name = ["invitedActorId"])
var invitedActorId: String? = null,
var selected: Boolean = false var selected: Boolean = false
) : Parcelable { ) : Parcelable {
// This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject' // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'

View file

@ -0,0 +1,37 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.utils
import android.view.View
import android.widget.ImageView
import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.extensions.loadBotsAvatar
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
import com.nextcloud.talk.extensions.loadDefaultAvatar
import com.nextcloud.talk.extensions.loadFederatedUserAvatar
import com.nextcloud.talk.extensions.loadFirstLetterAvatar
import com.nextcloud.talk.ui.theme.ViewThemeUtils
class ChatMessageUtils {
fun setAvatarOnMessage(view: ImageView, message: ChatMessage, viewThemeUtils : ViewThemeUtils) {
view.visibility = View.VISIBLE
if (message.actorType == "guests" || message.actorType == "emails") {
if (message.actorDisplayName?.isNotEmpty() == true) {
view.loadFirstLetterAvatar(message.actorDisplayName?.first().toString())
} else {
view.loadDefaultAvatar(viewThemeUtils)
}
} else if (message.actorType == "bots" && message.actorId == "changelog") {
view.loadChangelogBotAvatar()
} else if (message.actorType == "bots") {
view.loadBotsAvatar()
} else if (message.actorType == "federated_users") {
view.loadFederatedUserAvatar(message)
}
}
}

View file

@ -176,7 +176,7 @@ object DisplayUtils {
chip.setBounds(0, 0, chip.intrinsicWidth, chip.intrinsicHeight) chip.setBounds(0, 0, chip.intrinsicWidth, chip.intrinsicHeight)
if (!isCallOrGroup) { if (!isCallOrGroup) {
var url = getUrlForAvatar(conversationUser.baseUrl, id, false) var url = getUrlForAvatar(conversationUser.baseUrl, id, false)
if ("guests" == type || "guest" == type) { if ("guests" == type || "guest" == type || "email" == type) {
url = getUrlForGuestAvatar( url = getUrlForGuestAvatar(
conversationUser.baseUrl, label.toString(), true conversationUser.baseUrl, label.toString(), true
) )

View file

@ -107,7 +107,7 @@ class MessageUtils(val context: Context) {
val individualHashMap = message.messageParameters!![key] val individualHashMap = message.messageParameters!![key]
if (individualHashMap != null) { if (individualHashMap != null) {
when (individualHashMap["type"]) { when (individualHashMap["type"]) {
"user", "guest", "call", "user-group" -> { "user", "guest", "call", "user-group", "email" -> {
val chip = if (individualHashMap["id"] == message.activeUser!!.userId) { val chip = if (individualHashMap["id"] == message.activeUser!!.userId) {
R.xml.chip_you R.xml.chip_you
} else { } else {

View file

@ -66,7 +66,6 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="3" android:maxLines="3"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:layout_marginEnd="@dimen/side_margin" android:layout_marginEnd="@dimen/side_margin"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"