mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-23 13:35:33 +03:00
[WIP] Replace Fresco with Coil
Fresco is replaced with Coil verywhere. But Coil is not used directly to avoid splintering the dependency everywhere in the code. Coil is wrapped by extension functions for 'ImageView'. Some shared functionality is moved from 'DisplayUtils' into the 'ImageViewExtensions'. Resolves: #2227, #2376 Signed-off-by: Tim Krüger <t@timkrueger.me>
This commit is contained in:
parent
b2d6211b3c
commit
863052b53e
6 changed files with 110 additions and 62 deletions
|
@ -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<Any>
|
||||
) {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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()) {
|
||||
|
|
|
@ -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