diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt index a655cffc4..576ddccae 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.kt @@ -37,20 +37,18 @@ import android.text.format.DateUtils import android.view.View import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat -import com.facebook.drawee.backends.pipeline.Fresco -import com.facebook.drawee.interfaces.DraweeController 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.ApiUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability import eu.davidea.flexibleadapter.FlexibleAdapter @@ -116,7 +114,6 @@ class ConversationItem( payloads: List ) { val appContext = sharedApplication!!.applicationContext - holder.binding.dialogAvatar.controller = null holder.binding.dialogName.setTextColor( ResourcesCompat.getColor( context.resources, @@ -278,32 +275,16 @@ class ConversationItem( 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.hierarchy.setPlaceholderImage( - DisplayUtils.getRoundedDrawable(layerDrawable) - ) + holder.binding.dialogAvatar.loadAvatar(DisplayUtils.getRoundedDrawable(layerDrawable)) } else { - holder.binding.dialogAvatar.hierarchy.setPlaceholderImage(R.mipmap.ic_launcher) + 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)) { - val draweeController: DraweeController = Fresco.newDraweeControllerBuilder() - .setOldController(holder.binding.dialogAvatar.controller) - .setAutoPlayAnimations(true) - .setImageRequest( - DisplayUtils.getImageRequestForUrl( - ApiUtils.getUrlForAvatar( - user.baseUrl, - model.name, - true - ), - user - ) - ) - .build() - holder.binding.dialogAvatar.controller = draweeController + holder.binding.dialogAvatar.loadAvatar(user, model.name!!) } else { holder.binding.dialogAvatar.visibility = View.GONE } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt b/app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt index d00df59d4..76b17cba9 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt @@ -2,6 +2,8 @@ * Nextcloud Talk application * * @author Álvaro Brey + * @author Tim Krüger + * Copyright (C) 2022 Tim Krüger * 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 { diff --git a/app/src/main/java/com/nextcloud/talk/extensions/ImageViewExtensions.kt b/app/src/main/java/com/nextcloud/talk/extensions/ImageViewExtensions.kt new file mode 100644 index 000000000..d23ba8f37 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/extensions/ImageViewExtensions.kt @@ -0,0 +1,98 @@ +/* + * Nextcloud Talk application + * + * @author Tim Krüger + * Copyright (C) 2022 Tim Krüger + * 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 . + */ + +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(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 + } +} diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index dbd094b08..7668215c6 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -617,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()) { diff --git a/app/src/main/res/layout/rv_item_conversation_with_last_message.xml b/app/src/main/res/layout/rv_item_conversation_with_last_message.xml index 0428af241..c13b8fe72 100644 --- a/app/src/main/res/layout/rv_item_conversation_with_last_message.xml +++ b/app/src/main/res/layout/rv_item_conversation_with_last_message.xml @@ -38,7 +38,7 @@ android:layout_centerVertical="true" android:layout_marginEnd="@dimen/double_margin_between_elements"> - ~ Copyright (C) 2021 Andy Scherzinger ~ Copyright (C) 2017-2018 Mario Danic ~ @@ -35,7 +37,7 @@ android:layout_margin="@dimen/double_margin_between_elements" tools:background="@color/white"> -