mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-27 08:55:54 +03:00
Merge commit '863052b53e3051bb7e0fd4904d348fa294835821'
This commit is contained in:
commit
3a90d17649
10 changed files with 491 additions and 435 deletions
|
@ -42,7 +42,7 @@ android {
|
|||
namespace 'com.nextcloud.talk'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 31
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -1,371 +0,0 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* @author Andy Scherzinger
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.adapters.items;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.data.user.model.User;
|
||||
import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.models.json.status.Status;
|
||||
import com.nextcloud.talk.ui.StatusDrawable;
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
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;
|
||||
import eu.davidea.flexibleadapter.items.ISectionable;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
|
||||
public class ConversationItem extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements
|
||||
ISectionable<ConversationItem.ConversationItemViewHolder, GenericTextHeaderItem>, IFilterable<String> {
|
||||
|
||||
public static final int VIEW_TYPE = R.layout.rv_item_conversation_with_last_message;
|
||||
|
||||
private static final float STATUS_SIZE_IN_DP = 9f;
|
||||
|
||||
private final Conversation conversation;
|
||||
private final User user;
|
||||
private final Context context;
|
||||
private GenericTextHeaderItem header;
|
||||
private final Status status;
|
||||
private final ViewThemeUtils viewThemeUtils;
|
||||
|
||||
|
||||
public ConversationItem(Conversation conversation, User user, Context activityContext, Status status, final ViewThemeUtils viewThemeUtils) {
|
||||
this.conversation = conversation;
|
||||
this.user = user;
|
||||
this.context = activityContext;
|
||||
this.status = status;
|
||||
this.viewThemeUtils = viewThemeUtils;
|
||||
}
|
||||
|
||||
public ConversationItem(Conversation conversation, User user,
|
||||
Context activityContext, GenericTextHeaderItem genericTextHeaderItem, Status status,
|
||||
final ViewThemeUtils viewThemeUtils) {
|
||||
this(conversation, user, activityContext, status, viewThemeUtils);
|
||||
this.header = genericTextHeaderItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof ConversationItem) {
|
||||
ConversationItem inItem = (ConversationItem) o;
|
||||
return conversation.equals(inItem.getModel()) && Objects.equals(status, inItem.status);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Conversation getModel() {
|
||||
return conversation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = conversation.hashCode();
|
||||
result = 31 * result + (status != null ? status.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.rv_item_conversation_with_last_message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType() {
|
||||
return VIEW_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
|
||||
return new ConversationItemViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter,
|
||||
ConversationItemViewHolder holder,
|
||||
int position,
|
||||
List<Object> payloads) {
|
||||
Context appContext =
|
||||
NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
|
||||
holder.binding.dialogAvatar.setController(null);
|
||||
|
||||
holder.binding.dialogName.setTextColor(ResourcesCompat.getColor(context.getResources(),
|
||||
R.color.conversation_item_header,
|
||||
null));
|
||||
|
||||
if (adapter.hasFilter()) {
|
||||
viewThemeUtils.platform.highlightText(holder.binding.dialogName,
|
||||
conversation.getDisplayName(),
|
||||
String.valueOf(adapter.getFilter(String.class)));
|
||||
} else {
|
||||
holder.binding.dialogName.setText(conversation.getDisplayName());
|
||||
}
|
||||
|
||||
if (conversation.getUnreadMessages() > 0) {
|
||||
holder.binding.dialogName.setTypeface(holder.binding.dialogName.getTypeface(), Typeface.BOLD);
|
||||
holder.binding.dialogLastMessage.setTypeface(holder.binding.dialogLastMessage.getTypeface(), Typeface.BOLD);
|
||||
holder.binding.dialogUnreadBubble.setVisibility(View.VISIBLE);
|
||||
if (conversation.getUnreadMessages() < 1000) {
|
||||
holder.binding.dialogUnreadBubble.setText(Long.toString(conversation.getUnreadMessages()));
|
||||
} else {
|
||||
holder.binding.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages);
|
||||
}
|
||||
|
||||
ColorStateList lightBubbleFillColor = ColorStateList.valueOf(
|
||||
ContextCompat.getColor(context,
|
||||
R.color.conversation_unread_bubble));
|
||||
int lightBubbleTextColor = ContextCompat.getColor(
|
||||
context,
|
||||
R.color.conversation_unread_bubble_text);
|
||||
|
||||
if (conversation.getType() == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
|
||||
} else if (conversation.getUnreadMention()) {
|
||||
if (CapabilitiesUtilNew.hasSpreedFeatureCapability(user, "direct-mention-flag")) {
|
||||
if (conversation.getUnreadMentionDirect()) {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
|
||||
} else {
|
||||
viewThemeUtils.material.colorChipOutlined(holder.binding.dialogUnreadBubble, 6.0f);
|
||||
}
|
||||
} else {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogUnreadBubble.setChipBackgroundColor(lightBubbleFillColor);
|
||||
holder.binding.dialogUnreadBubble.setTextColor(lightBubbleTextColor);
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogName.setTypeface(null, Typeface.NORMAL);
|
||||
holder.binding.dialogDate.setTypeface(null, Typeface.NORMAL);
|
||||
holder.binding.dialogLastMessage.setTypeface(null, Typeface.NORMAL);
|
||||
holder.binding.dialogUnreadBubble.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (conversation.getFavorite()) {
|
||||
holder.binding.favoriteConversationImageView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.binding.favoriteConversationImageView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (status != null && Conversation.ConversationType.ROOM_SYSTEM != conversation.getType()) {
|
||||
float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, appContext);
|
||||
|
||||
holder.binding.userStatusImage.setVisibility(View.VISIBLE);
|
||||
holder.binding.userStatusImage.setImageDrawable(new StatusDrawable(
|
||||
status.getStatus(),
|
||||
status.getIcon(),
|
||||
size,
|
||||
context.getResources().getColor(R.color.bg_default),
|
||||
appContext));
|
||||
} else {
|
||||
holder.binding.userStatusImage.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (conversation.getLastMessage() != null) {
|
||||
holder.binding.dialogDate.setVisibility(View.VISIBLE);
|
||||
holder.binding.dialogDate.setText(
|
||||
DateUtils.getRelativeTimeSpanString(conversation.getLastActivity() * 1000L,
|
||||
System.currentTimeMillis(),
|
||||
0,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE));
|
||||
|
||||
if (!TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage()) ||
|
||||
Conversation.ConversationType.ROOM_SYSTEM == conversation.getType()) {
|
||||
holder.binding.dialogLastMessage.setText(conversation.getLastMessage().getText());
|
||||
} else {
|
||||
String authorDisplayName = "";
|
||||
conversation.getLastMessage().setActiveUser(user);
|
||||
String text;
|
||||
if (conversation.getLastMessage().getCalculateMessageType() == ChatMessage.MessageType.REGULAR_TEXT_MESSAGE) {
|
||||
if (conversation.getLastMessage().getActorId().equals(user.getUserId())) {
|
||||
text = String.format(appContext.getString(R.string.nc_formatted_message_you),
|
||||
conversation.getLastMessage().getLastMessageDisplayText());
|
||||
} else {
|
||||
authorDisplayName = !TextUtils.isEmpty(conversation.getLastMessage().getActorDisplayName()) ?
|
||||
conversation.getLastMessage().getActorDisplayName() :
|
||||
"guests".equals(conversation.getLastMessage().getActorType()) ?
|
||||
appContext.getString(R.string.nc_guest) : "";
|
||||
text = String.format(appContext.getString(R.string.nc_formatted_message),
|
||||
authorDisplayName,
|
||||
conversation.getLastMessage().getLastMessageDisplayText());
|
||||
}
|
||||
} else {
|
||||
text = conversation.getLastMessage().getLastMessageDisplayText();
|
||||
}
|
||||
|
||||
holder.binding.dialogLastMessage.setText(text);
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogDate.setVisibility(View.GONE);
|
||||
holder.binding.dialogLastMessage.setText(R.string.nc_no_messages_yet);
|
||||
}
|
||||
|
||||
holder.binding.dialogAvatar.setVisibility(View.VISIBLE);
|
||||
|
||||
boolean shouldLoadAvatar = true;
|
||||
String objectType;
|
||||
if (!TextUtils.isEmpty(objectType = conversation.getObjectType())) {
|
||||
switch (objectType) {
|
||||
case "share:password":
|
||||
shouldLoadAvatar = false;
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_circular_lock));
|
||||
break;
|
||||
case "file":
|
||||
shouldLoadAvatar = false;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_document)));
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_document));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
Drawable[] layers = new Drawable[2];
|
||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background);
|
||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground);
|
||||
LayerDrawable layerDrawable = new LayerDrawable(layers);
|
||||
|
||||
holder.binding.dialogAvatar.getHierarchy().setPlaceholderImage(
|
||||
DisplayUtils.getRoundedDrawable(layerDrawable));
|
||||
} else {
|
||||
holder.binding.dialogAvatar.getHierarchy().setPlaceholderImage(R.mipmap.ic_launcher);
|
||||
}
|
||||
shouldLoadAvatar = false;
|
||||
}
|
||||
|
||||
if (shouldLoadAvatar) {
|
||||
switch (conversation.getType()) {
|
||||
case ROOM_TYPE_ONE_TO_ONE_CALL:
|
||||
if (!TextUtils.isEmpty(conversation.getName())) {
|
||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(holder.binding.dialogAvatar.getController())
|
||||
.setAutoPlayAnimations(true)
|
||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(
|
||||
ApiUtils.getUrlForAvatar(user.getBaseUrl(),
|
||||
conversation.getName(),
|
||||
true),
|
||||
user))
|
||||
.build();
|
||||
holder.binding.dialogAvatar.setController(draweeController);
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case ROOM_GROUP_CALL:
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_group)));
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_group));
|
||||
}
|
||||
break;
|
||||
case ROOM_PUBLIC_CALL:
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_link)));
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_link));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
holder.binding.dialogAvatar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filter(String constraint) {
|
||||
return conversation.getDisplayName() != null &&
|
||||
Pattern
|
||||
.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
|
||||
.matcher(conversation.getDisplayName().trim())
|
||||
.find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericTextHeaderItem getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(GenericTextHeaderItem header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
static class ConversationItemViewHolder extends FlexibleViewHolder {
|
||||
|
||||
RvItemConversationWithLastMessageBinding binding;
|
||||
|
||||
ConversationItemViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
binding = RvItemConversationWithLastMessageBinding.bind(view);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* @author Andy Scherzinger
|
||||
* @author Marcel Hibbe
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.nextcloud.talk.adapters.items
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.text.format.DateUtils
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding
|
||||
import com.nextcloud.talk.extensions.loadAvatar
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
||||
import com.nextcloud.talk.models.json.status.Status
|
||||
import com.nextcloud.talk.ui.StatusDrawable
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFilterable
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.flexibleadapter.items.ISectionable
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ConversationItem(
|
||||
val model: Conversation,
|
||||
private val user: User,
|
||||
private val context: Context,
|
||||
private val status: Status?,
|
||||
private val viewThemeUtils: ViewThemeUtils
|
||||
) : AbstractFlexibleItem<ConversationItemViewHolder>(),
|
||||
ISectionable<ConversationItemViewHolder, GenericTextHeaderItem?>,
|
||||
IFilterable<String?> {
|
||||
private var header: GenericTextHeaderItem? = null
|
||||
|
||||
constructor(
|
||||
conversation: Conversation,
|
||||
user: User,
|
||||
activityContext: Context,
|
||||
genericTextHeaderItem: GenericTextHeaderItem?,
|
||||
status: Status?,
|
||||
viewThemeUtils: ViewThemeUtils
|
||||
) : this(conversation, user, activityContext, status, viewThemeUtils) {
|
||||
header = genericTextHeaderItem
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other is ConversationItem) {
|
||||
return model == other.model && status == other.status
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = model.hashCode()
|
||||
result = 31 * result + (status?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.rv_item_conversation_with_last_message
|
||||
}
|
||||
|
||||
override fun getItemViewType(): Int {
|
||||
return VIEW_TYPE
|
||||
}
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>?>?): ConversationItemViewHolder {
|
||||
return ConversationItemViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun bindViewHolder(
|
||||
adapter: FlexibleAdapter<IFlexible<*>?>,
|
||||
holder: ConversationItemViewHolder,
|
||||
position: Int,
|
||||
payloads: List<Any>
|
||||
) {
|
||||
val appContext = sharedApplication!!.applicationContext
|
||||
holder.binding.dialogName.setTextColor(
|
||||
ResourcesCompat.getColor(
|
||||
context.resources,
|
||||
R.color.conversation_item_header,
|
||||
null
|
||||
)
|
||||
)
|
||||
if (adapter.hasFilter()) {
|
||||
viewThemeUtils.platform.highlightText(
|
||||
holder.binding.dialogName,
|
||||
model.displayName!!, adapter.getFilter(String::class.java).toString()
|
||||
)
|
||||
} else {
|
||||
holder.binding.dialogName.text = model.displayName
|
||||
}
|
||||
if (model.unreadMessages > 0) {
|
||||
holder.binding.dialogName.setTypeface(holder.binding.dialogName.typeface, Typeface.BOLD)
|
||||
holder.binding.dialogLastMessage.setTypeface(holder.binding.dialogLastMessage.typeface, Typeface.BOLD)
|
||||
holder.binding.dialogUnreadBubble.visibility = View.VISIBLE
|
||||
if (model.unreadMessages < 1000) {
|
||||
holder.binding.dialogUnreadBubble.text = model.unreadMessages.toLong().toString()
|
||||
} else {
|
||||
holder.binding.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages)
|
||||
}
|
||||
val lightBubbleFillColor = ColorStateList.valueOf(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
R.color.conversation_unread_bubble
|
||||
)
|
||||
)
|
||||
val lightBubbleTextColor = ContextCompat.getColor(
|
||||
context,
|
||||
R.color.conversation_unread_bubble_text
|
||||
)
|
||||
if (model.type === ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||
} else if (model.unreadMention) {
|
||||
if (hasSpreedFeatureCapability(user, "direct-mention-flag")) {
|
||||
if (model.unreadMentionDirect!!) {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||
} else {
|
||||
viewThemeUtils.material.colorChipOutlined(holder.binding.dialogUnreadBubble, 6.0f)
|
||||
}
|
||||
} else {
|
||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogUnreadBubble.chipBackgroundColor = lightBubbleFillColor
|
||||
holder.binding.dialogUnreadBubble.setTextColor(lightBubbleTextColor)
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogName.setTypeface(null, Typeface.NORMAL)
|
||||
holder.binding.dialogDate.setTypeface(null, Typeface.NORMAL)
|
||||
holder.binding.dialogLastMessage.setTypeface(null, Typeface.NORMAL)
|
||||
holder.binding.dialogUnreadBubble.visibility = View.GONE
|
||||
}
|
||||
if (model.favorite) {
|
||||
holder.binding.favoriteConversationImageView.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.binding.favoriteConversationImageView.visibility = View.GONE
|
||||
}
|
||||
if (status != null && ConversationType.ROOM_SYSTEM !== model.type) {
|
||||
val size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, appContext)
|
||||
holder.binding.userStatusImage.visibility = View.VISIBLE
|
||||
holder.binding.userStatusImage.setImageDrawable(
|
||||
StatusDrawable(
|
||||
status.status,
|
||||
status.icon,
|
||||
size,
|
||||
context.resources.getColor(R.color.bg_default),
|
||||
appContext
|
||||
)
|
||||
)
|
||||
} else {
|
||||
holder.binding.userStatusImage.visibility = View.GONE
|
||||
}
|
||||
if (model.lastMessage != null) {
|
||||
holder.binding.dialogDate.visibility = View.VISIBLE
|
||||
holder.binding.dialogDate.text = DateUtils.getRelativeTimeSpanString(
|
||||
model.lastActivity * 1000L,
|
||||
System.currentTimeMillis(),
|
||||
0,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
if (!TextUtils.isEmpty(model.lastMessage!!.systemMessage) ||
|
||||
ConversationType.ROOM_SYSTEM === model.type
|
||||
) {
|
||||
holder.binding.dialogLastMessage.text = model.lastMessage!!.text
|
||||
} else {
|
||||
model.lastMessage!!.activeUser = user
|
||||
val text: String
|
||||
if (model.lastMessage!!.getCalculateMessageType() === ChatMessage.MessageType.REGULAR_TEXT_MESSAGE) {
|
||||
if (model.lastMessage!!.actorId == user.userId) {
|
||||
text = String.format(
|
||||
appContext.getString(R.string.nc_formatted_message_you),
|
||||
model.lastMessage!!.lastMessageDisplayText
|
||||
)
|
||||
} else {
|
||||
val authorDisplayName =
|
||||
if (!TextUtils.isEmpty(model.lastMessage!!.actorDisplayName)) {
|
||||
model.lastMessage!!.actorDisplayName
|
||||
} else if ("guests" == model.lastMessage!!.actorType) {
|
||||
appContext.getString(R.string.nc_guest)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
text = String.format(
|
||||
appContext.getString(R.string.nc_formatted_message),
|
||||
authorDisplayName,
|
||||
model.lastMessage!!.lastMessageDisplayText
|
||||
)
|
||||
}
|
||||
} else {
|
||||
text = model.lastMessage!!.lastMessageDisplayText
|
||||
}
|
||||
holder.binding.dialogLastMessage.text = text
|
||||
}
|
||||
} else {
|
||||
holder.binding.dialogDate.visibility = View.GONE
|
||||
holder.binding.dialogLastMessage.setText(R.string.nc_no_messages_yet)
|
||||
}
|
||||
holder.binding.dialogAvatar.visibility = View.VISIBLE
|
||||
var shouldLoadAvatar = true
|
||||
var objectType: String?
|
||||
if (!TextUtils.isEmpty(model.objectType.also { objectType = it })) {
|
||||
when (objectType) {
|
||||
"share:password" -> {
|
||||
shouldLoadAvatar = false
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.ic_circular_lock
|
||||
)
|
||||
)
|
||||
}
|
||||
"file" -> {
|
||||
shouldLoadAvatar = false
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
||||
holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_document
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_document)
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
if (ConversationType.ROOM_SYSTEM == model.type) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val layers = arrayOfNulls<Drawable>(2)
|
||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
||||
val layerDrawable = LayerDrawable(layers)
|
||||
holder.binding.dialogAvatar.loadAvatar(DisplayUtils.getRoundedDrawable(layerDrawable))
|
||||
} else {
|
||||
holder.binding.dialogAvatar.loadAvatar(R.mipmap.ic_launcher)
|
||||
}
|
||||
shouldLoadAvatar = false
|
||||
}
|
||||
if (shouldLoadAvatar) {
|
||||
when (model.type) {
|
||||
ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(model.name)) {
|
||||
holder.binding.dialogAvatar.loadAvatar(user, model.name!!)
|
||||
} else {
|
||||
holder.binding.dialogAvatar.visibility = View.GONE
|
||||
}
|
||||
ConversationType.ROOM_GROUP_CALL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
||||
holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_group
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_group)
|
||||
)
|
||||
}
|
||||
ConversationType.ROOM_PUBLIC_CALL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
DisplayUtils.getRoundedDrawable(
|
||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
||||
holder.binding.dialogAvatar,
|
||||
R.drawable.ic_avatar_link
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
holder.binding.dialogAvatar.setImageDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_link)
|
||||
)
|
||||
}
|
||||
else -> holder.binding.dialogAvatar.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun filter(constraint: String?): Boolean {
|
||||
return model.displayName != null &&
|
||||
Pattern
|
||||
.compile(constraint!!, Pattern.CASE_INSENSITIVE or Pattern.LITERAL)
|
||||
.matcher(model.displayName!!.trim { it <= ' ' })
|
||||
.find()
|
||||
}
|
||||
|
||||
override fun getHeader(): GenericTextHeaderItem? {
|
||||
return header
|
||||
}
|
||||
|
||||
override fun setHeader(header: GenericTextHeaderItem?) {
|
||||
this.header = header
|
||||
}
|
||||
|
||||
class ConversationItemViewHolder(view: View?, adapter: FlexibleAdapter<*>?) : FlexibleViewHolder(view, adapter) {
|
||||
var binding: RvItemConversationWithLastMessageBinding
|
||||
|
||||
init {
|
||||
binding = RvItemConversationWithLastMessageBinding.bind(view!!)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = R.layout.rv_item_conversation_with_last_message
|
||||
private const val STATUS_SIZE_IN_DP = 9f
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Álvaro Brey
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2022 Álvaro Brey
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
|
@ -27,9 +29,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.databinding.RvItemSearchMessageBinding
|
||||
import com.nextcloud.talk.extensions.loadThumbnail
|
||||
import com.nextcloud.talk.models.domain.SearchMessageEntry
|
||||
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
|
||||
|
@ -72,7 +74,7 @@ data class MessageResultItem constructor(
|
|||
) {
|
||||
holder.binding.conversationTitle.text = messageEntry.title
|
||||
bindMessageExcerpt(holder)
|
||||
loadImage(holder)
|
||||
holder.binding.thumbnail.loadThumbnail(messageEntry.thumbnailURL, currentUser)
|
||||
}
|
||||
|
||||
private fun bindMessageExcerpt(holder: ViewHolder) {
|
||||
|
@ -83,17 +85,6 @@ data class MessageResultItem constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun loadImage(holder: ViewHolder) {
|
||||
DisplayUtils.loadAvatarPlaceholder(holder.binding.thumbnail)
|
||||
if (messageEntry.thumbnailURL != null) {
|
||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
||||
messageEntry.thumbnailURL,
|
||||
currentUser
|
||||
)
|
||||
DisplayUtils.loadImage(holder.binding.thumbnail, imageRequest)
|
||||
}
|
||||
}
|
||||
|
||||
override fun filter(constraint: String?): Boolean = true
|
||||
|
||||
override fun getItemViewType(): Int {
|
||||
|
|
|
@ -587,16 +587,16 @@ class ConversationsListController(bundle: Bundle) :
|
|||
if (activity != null) {
|
||||
val conversationItem = ConversationItem(
|
||||
conversation,
|
||||
currentUser,
|
||||
activity,
|
||||
currentUser!!,
|
||||
activity!!,
|
||||
userStatuses[conversation.name],
|
||||
viewThemeUtils
|
||||
)
|
||||
conversationItems.add(conversationItem)
|
||||
val conversationItemWithHeader = ConversationItem(
|
||||
conversation,
|
||||
currentUser,
|
||||
activity,
|
||||
currentUser!!,
|
||||
activity!!,
|
||||
callHeaderItems[headerTitle],
|
||||
userStatuses[conversation.name],
|
||||
viewThemeUtils
|
||||
|
@ -659,8 +659,8 @@ class ConversationsListController(bundle: Bundle) :
|
|||
}
|
||||
val conversationItem = ConversationItem(
|
||||
conversation,
|
||||
currentUser,
|
||||
activity,
|
||||
currentUser!!,
|
||||
activity!!,
|
||||
callHeaderItems[headerTitle],
|
||||
userStatuses[conversation.name],
|
||||
viewThemeUtils
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.extensions
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Build
|
||||
import android.widget.ImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import coil.load
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.CircleCropTransformation
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
|
||||
fun ImageView.loadAvatar(user: User, avatar: String): io.reactivex.disposables.Disposable {
|
||||
|
||||
val imageRequestUri = ApiUtils.getUrlForAvatar(
|
||||
user.baseUrl,
|
||||
avatar,
|
||||
true
|
||||
)
|
||||
|
||||
return DisposableWrapper(
|
||||
load(imageRequestUri) {
|
||||
addHeader(
|
||||
"Authorization",
|
||||
ApiUtils.getCredentials(user.username, user.token)
|
||||
)
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun ImageView.loadThumbnail(url: String?, user: User): io.reactivex.disposables.Disposable {
|
||||
val requestBuilder = ImageRequest.Builder(context)
|
||||
.data(url)
|
||||
.crossfade(true)
|
||||
.target(this)
|
||||
.transformations(CircleCropTransformation())
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val layers = arrayOfNulls<Drawable>(2)
|
||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
||||
requestBuilder.placeholder(LayerDrawable(layers))
|
||||
} else {
|
||||
requestBuilder.placeholder(R.mipmap.ic_launcher)
|
||||
}
|
||||
|
||||
if (url != null &&
|
||||
url.startsWith(user.baseUrl!!) &&
|
||||
(url.contains("index.php/core/preview?fileId=") || url.contains("/avatar/"))
|
||||
) {
|
||||
requestBuilder.addHeader(
|
||||
"Authorization",
|
||||
ApiUtils.getCredentials(user.username, user.token)
|
||||
)
|
||||
}
|
||||
|
||||
return DisposableWrapper(load(requestBuilder.build()))
|
||||
}
|
||||
|
||||
fun ImageView.loadAvatar(any: Any?): io.reactivex.disposables.Disposable {
|
||||
return DisposableWrapper(load(any))
|
||||
}
|
||||
|
||||
private class DisposableWrapper(private val disposable: coil.request.Disposable) : io.reactivex.disposables
|
||||
.Disposable {
|
||||
|
||||
override fun dispose() {
|
||||
disposable.dispose()
|
||||
}
|
||||
|
||||
override fun isDisposed(): Boolean {
|
||||
return disposable.isDisposed
|
||||
}
|
||||
}
|
|
@ -32,6 +32,11 @@ import android.content.res.Resources;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
@ -164,21 +169,28 @@ public class DisplayUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Bitmap roundBitmap(Bitmap bitmap) {
|
||||
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
final Canvas canvas = new Canvas(output);
|
||||
|
||||
final Paint paint = new Paint();
|
||||
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
final RectF rectF = new RectF(rect);
|
||||
|
||||
paint.setAntiAlias(true);
|
||||
canvas.drawARGB(0, 0, 0, 0);
|
||||
canvas.drawOval(rectF, paint);
|
||||
|
||||
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||
canvas.drawBitmap(bitmap, rect, rect, paint);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static Drawable getRoundedDrawable(Drawable drawable) {
|
||||
Bitmap bitmap = getBitmap(drawable);
|
||||
new RoundAsCirclePostprocessor(true).process(bitmap);
|
||||
return new BitmapDrawable(bitmap);
|
||||
}
|
||||
|
||||
public static Bitmap getRoundedBitmapFromVectorDrawableResource(Resources resources, int resource) {
|
||||
VectorDrawable vectorDrawable = (VectorDrawable) ResourcesCompat.getDrawable(resources, resource, null);
|
||||
Bitmap bitmap = getBitmap(vectorDrawable);
|
||||
new RoundPostprocessor(true).process(bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Drawable getRoundedBitmapDrawableFromVectorDrawableResource(Resources resources, int resource) {
|
||||
return new BitmapDrawable(getRoundedBitmapFromVectorDrawableResource(resources, resource));
|
||||
return new BitmapDrawable(roundBitmap(bitmap));
|
||||
}
|
||||
|
||||
public static Bitmap getBitmap(Drawable drawable) {
|
||||
|
@ -605,30 +617,6 @@ public class DisplayUtils {
|
|||
avatarImageView.setController(draweeController);
|
||||
}
|
||||
|
||||
public static void loadAvatarPlaceholder(final SimpleDraweeView targetView) {
|
||||
final Context context = targetView.getContext();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Drawable[] layers = new Drawable[2];
|
||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background);
|
||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground);
|
||||
LayerDrawable layerDrawable = new LayerDrawable(layers);
|
||||
|
||||
targetView.getHierarchy().setPlaceholderImage(
|
||||
DisplayUtils.getRoundedDrawable(layerDrawable));
|
||||
} else {
|
||||
targetView.getHierarchy().setPlaceholderImage(R.mipmap.ic_launcher);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadImage(final SimpleDraweeView targetView, final ImageRequest imageRequest) {
|
||||
final DraweeController newController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(targetView.getController())
|
||||
.setAutoPlayAnimations(true)
|
||||
.setImageRequest(imageRequest)
|
||||
.build();
|
||||
targetView.setController(newController);
|
||||
}
|
||||
|
||||
public static @StringRes
|
||||
int getSortOrderStringId(FileSortOrder sortOrder) {
|
||||
switch (sortOrder.getName()) {
|
||||
|
|
|
@ -38,7 +38,6 @@ import com.facebook.common.references.CloseableReference
|
|||
import com.facebook.datasource.DataSources
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.imagepipeline.image.CloseableBitmap
|
||||
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor
|
||||
import com.nextcloud.talk.BuildConfig
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
|
@ -334,10 +333,7 @@ object NotificationUtils {
|
|||
val closeableImageRef = DataSources.waitForFinalResult(dataSource) as CloseableReference<CloseableBitmap>?
|
||||
val bitmap = closeableImageRef?.get()?.underlyingBitmap
|
||||
if (bitmap != null) {
|
||||
// According to Fresco documentation a copy of the bitmap should be made before closing the references.
|
||||
// However, it seems to work without making a copy... ;-)
|
||||
RoundAsCirclePostprocessor(true).process(bitmap)
|
||||
avatarIcon = IconCompat.createWithBitmap(bitmap)
|
||||
avatarIcon = IconCompat.createWithBitmap(DisplayUtils.roundBitmap(bitmap))
|
||||
}
|
||||
CloseableReference.closeSafely(closeableImageRef)
|
||||
dataSource.close()
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/double_margin_between_elements">
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
<ImageView
|
||||
android:id="@id/dialogAvatar"
|
||||
android:layout_width="@dimen/small_item_height"
|
||||
android:layout_height="@dimen/small_item_height"
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
~
|
||||
~ @author Mario Danic
|
||||
~ @author Andy Scherzinger
|
||||
~ @author Tim Krüger
|
||||
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
|
@ -35,7 +37,7 @@
|
|||
android:layout_margin="@dimen/double_margin_between_elements"
|
||||
tools:background="@color/white">
|
||||
|
||||
<com.facebook.drawee.view.SimpleDraweeView
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/small_item_height"
|
||||
android:layout_height="@dimen/small_item_height"
|
||||
|
|
Loading…
Reference in a new issue