Cache conversation icon shortcuts.

fork-5.53.8
Alex Hart 2020-12-01 16:56:10 -04:00 zatwierdzone przez Greyson Parrelli
rodzic adee104899
commit 283ff44da9
3 zmienionych plików z 161 dodań i 28 usunięć

Wyświetl plik

@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.stickers.StickerRemoteUri;
import org.thoughtcrime.securesms.stickers.StickerRemoteUriLoader;
import org.thoughtcrime.securesms.util.ConversationShortcutPhoto;
import java.io.File;
import java.io.InputStream;
@ -89,6 +90,7 @@ public class SignalGlideModule extends AppGlideModule {
registry.prepend(BlurHash.class, Bitmap.class, new BlurHashResourceDecoder());
registry.append(ConversationShortcutPhoto.class, Bitmap.class, new ConversationShortcutPhoto.Loader.Factory(context));
registry.append(ContactPhoto.class, InputStream.class, new ContactPhotoLoader.Factory(context));
registry.append(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory(context));
registry.append(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory());

Wyświetl plik

@ -112,20 +112,20 @@ public final class AvatarUtil {
@RequiresApi(ConversationUtil.CONVERSATION_SUPPORT_VERSION)
@WorkerThread
public static Icon getIconForShortcut(@NonNull Context context, @NonNull Recipient recipient) {
public static @NonNull Icon getIconForShortcut(@NonNull Context context, @NonNull Recipient recipient) {
try {
return Icon.createWithAdaptiveBitmap(getShortcutInfoBitmap(context, recipient));
return Icon.createWithAdaptiveBitmap(GlideApp.with(context).asBitmap().load(new ConversationShortcutPhoto(recipient)).submit().get());
} catch (ExecutionException | InterruptedException e) {
return Icon.createWithAdaptiveBitmap(getFallbackForShortcut(context, recipient));
throw new AssertionError("This call should not fail.");
}
}
@WorkerThread
public static IconCompat getIconCompatForShortcut(@NonNull Context context, @NonNull Recipient recipient) {
public static @NonNull IconCompat getIconCompatForShortcut(@NonNull Context context, @NonNull Recipient recipient) {
try {
return IconCompat.createWithAdaptiveBitmap(getShortcutInfoBitmap(context, recipient));
return IconCompat.createWithAdaptiveBitmap(GlideApp.with(context).asBitmap().load(new ConversationShortcutPhoto(recipient)).submit().get());
} catch (ExecutionException | InterruptedException e) {
return IconCompat.createWithAdaptiveBitmap(getFallbackForShortcut(context, recipient));
throw new AssertionError("This call should not fail.");
}
}
@ -138,10 +138,6 @@ public final class AvatarUtil {
}
}
private static @NonNull Bitmap getShortcutInfoBitmap(@NonNull Context context, @NonNull Recipient recipient) throws ExecutionException, InterruptedException {
return DrawableUtil.wrapBitmapForShortcutInfo(request(GlideApp.with(context).asBitmap(), context, recipient, false).circleCrop().submit().get());
}
private static <T> GlideRequest<T> requestCircle(@NonNull GlideRequest<T> glideRequest, @NonNull Context context, @NonNull Recipient recipient) {
return request(glideRequest, context, recipient).circleCrop();
}
@ -167,24 +163,6 @@ public final class AvatarUtil {
.diskCacheStrategy(DiskCacheStrategy.ALL);
}
private static @NonNull Bitmap getFallbackForShortcut(@NonNull Context context, @NonNull Recipient recipient) {
@DrawableRes final int photoSource;
if (recipient.isSelf()) {
photoSource = R.drawable.ic_note_80;
} else if (recipient.isGroup()) {
photoSource = R.drawable.ic_group_80;
} else {
photoSource = R.drawable.ic_profile_80;
}
Bitmap toWrap = DrawableUtil.toBitmap(new FallbackPhoto80dp(photoSource, recipient.getColor()).asDrawable(context, -1), ViewUtil.dpToPx(80), ViewUtil.dpToPx(80));
Bitmap wrapped = DrawableUtil.wrapBitmapForShortcutInfo(toWrap);
toWrap.recycle();
return wrapped;
}
private static Drawable getFallback(@NonNull Context context, @NonNull Recipient recipient) {
String name = Optional.fromNullable(recipient.getDisplayName(context)).or("");
MaterialColor fallbackColor = recipient.getColor();

Wyświetl plik

@ -0,0 +1,153 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.graphics.Bitmap;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequest;
import org.thoughtcrime.securesms.recipients.Recipient;
import java.security.MessageDigest;
import java.util.concurrent.ExecutionException;
public final class ConversationShortcutPhoto implements Key {
private final Recipient recipient;
@WorkerThread
public ConversationShortcutPhoto(@NonNull Recipient recipient) {
this.recipient = recipient.resolve();
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(recipient.getDisplayName(ApplicationDependencies.getApplication()).getBytes());
if (recipient.getProfileAvatar() != null) {
messageDigest.update(recipient.getProfileAvatar().getBytes());
}
}
public static final class Loader implements ModelLoader<ConversationShortcutPhoto, Bitmap> {
private final Context context;
private Loader(@NonNull Context context) {
this.context = context;
}
@Override
public @Nullable LoadData<Bitmap> buildLoadData(@NonNull ConversationShortcutPhoto conversationShortcutPhoto, int width, int height, @NonNull Options options) {
return new LoadData<>(conversationShortcutPhoto, new Fetcher(context, conversationShortcutPhoto));
}
@Override
public boolean handles(@NonNull ConversationShortcutPhoto conversationShortcutPhoto) {
return true;
}
public static class Factory implements ModelLoaderFactory<ConversationShortcutPhoto, Bitmap> {
private final Context context;
public Factory(@NonNull Context context) {
this.context = context;
}
@Override
public @NonNull ModelLoader<ConversationShortcutPhoto, Bitmap> build(@NonNull MultiModelLoaderFactory multiFactory) {
return new Loader(context);
}
@Override
public void teardown() {
}
}
}
static final class Fetcher implements DataFetcher<Bitmap> {
private final Context context;
private final ConversationShortcutPhoto photo;
private Fetcher(@NonNull Context context, @NonNull ConversationShortcutPhoto photo) {
this.context = context;
this.photo = photo;
}
@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super Bitmap> callback) {
Bitmap bitmap;
try {
bitmap = getShortcutInfoBitmap(context);
} catch (ExecutionException | InterruptedException e) {
bitmap = getFallbackForShortcut(context);
}
callback.onDataReady(bitmap);
}
@Override
public void cleanup() {
}
@Override
public void cancel() {
}
@Override
public @NonNull Class<Bitmap> getDataClass() {
return Bitmap.class;
}
@Override
public @NonNull DataSource getDataSource() {
return DataSource.LOCAL;
}
private @NonNull Bitmap getShortcutInfoBitmap(@NonNull Context context) throws ExecutionException, InterruptedException {
return DrawableUtil.wrapBitmapForShortcutInfo(request(GlideApp.with(context).asBitmap(), context, false).circleCrop().submit().get());
}
private @NonNull Bitmap getFallbackForShortcut(@NonNull Context context) {
@DrawableRes final int photoSource;
if (photo.recipient.isSelf()) {
photoSource = R.drawable.ic_note_80;
} else if (photo.recipient.isGroup()) {
photoSource = R.drawable.ic_group_80;
} else {
photoSource = R.drawable.ic_profile_80;
}
Bitmap toWrap = DrawableUtil.toBitmap(new FallbackPhoto80dp(photoSource, photo.recipient.getColor()).asDrawable(context, -1), ViewUtil.dpToPx(80), ViewUtil.dpToPx(80));
Bitmap wrapped = DrawableUtil.wrapBitmapForShortcutInfo(toWrap);
toWrap.recycle();
return wrapped;
}
private <T> GlideRequest<T> request(@NonNull GlideRequest<T> glideRequest, @NonNull Context context, boolean loadSelf) {
return glideRequest.load(photo.recipient.getContactPhoto()).diskCacheStrategy(DiskCacheStrategy.ALL);
}
}
}