Add PagingMappingAdapter and convert GiphyMp4Adapter.
This commit is contained in:
parent
dd79688f48
commit
5918227bff
6 changed files with 96 additions and 67 deletions
|
@ -9,8 +9,9 @@ import androidx.annotation.Nullable;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.thoughtcrime.securesms.util.ByteUnit;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel;
|
||||
|
||||
public class GiphyImage {
|
||||
public class GiphyImage implements MappingModel<GiphyImage> {
|
||||
|
||||
private static final int MAX_SIZE = (int) ByteUnit.MEGABYTES.toBytes(2);
|
||||
|
||||
|
@ -20,6 +21,16 @@ public class GiphyImage {
|
|||
@JsonProperty("is_sticker")
|
||||
private boolean isSticker;
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull GiphyImage newItem) {
|
||||
return getMp4Url().equals(newItem.getMp4Url());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull GiphyImage newItem) {
|
||||
return areItemsTheSame(newItem);
|
||||
}
|
||||
|
||||
public boolean isSticker() {
|
||||
return isSticker;
|
||||
}
|
||||
|
|
|
@ -1,77 +1,24 @@
|
|||
package org.thoughtcrime.securesms.giph.mp4;
|
||||
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListAdapter;
|
||||
|
||||
import org.signal.paging.PagingController;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
|
||||
|
||||
/**
|
||||
* Maintains and displays a list of GiphyImage objects. This Adapter always displays gifs
|
||||
* as MP4 videos.
|
||||
*/
|
||||
final class GiphyMp4Adapter extends ListAdapter<GiphyImage, GiphyMp4ViewHolder> {
|
||||
|
||||
private final Callback listener;
|
||||
|
||||
private PagingController pagingController;
|
||||
|
||||
final class GiphyMp4Adapter extends PagingMappingAdapter<String> {
|
||||
public GiphyMp4Adapter(@Nullable Callback listener) {
|
||||
super(new GiphyImageDiffUtilCallback());
|
||||
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull GiphyMp4ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View itemView = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.giphy_mp4, parent, false);
|
||||
|
||||
return new GiphyMp4ViewHolder(itemView, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull GiphyMp4ViewHolder holder, int position) {
|
||||
holder.onBind(getItem(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GiphyImage getItem(int position) {
|
||||
if (pagingController != null) {
|
||||
pagingController.onDataNeededAroundIndex(position);
|
||||
}
|
||||
|
||||
return super.getItem(position);
|
||||
}
|
||||
|
||||
void setPagingController(@Nullable PagingController pagingController) {
|
||||
this.pagingController = pagingController;
|
||||
registerFactory(GiphyImage.class, new LayoutFactory<>(v -> new GiphyMp4ViewHolder(v, listener), R.layout.giphy_mp4));
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
void onClick(@NonNull GiphyImage giphyImage);
|
||||
}
|
||||
|
||||
private static final class GiphyImageDiffUtilCallback extends DiffUtil.ItemCallback<GiphyImage> {
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull GiphyImage oldItem, @NonNull GiphyImage newItem) {
|
||||
return Objects.equals(oldItem.getMp4Url(), newItem.getMp4Url());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull GiphyImage oldItem, @NonNull GiphyImage newItem) {
|
||||
return areItemsTheSame(oldItem, newItem);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import android.widget.ImageView;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
|
@ -24,11 +23,12 @@ import org.thoughtcrime.securesms.mms.GlideApp;
|
|||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder;
|
||||
|
||||
/**
|
||||
* Holds a view which will either play back an MP4 gif or show its still.
|
||||
*/
|
||||
final class GiphyMp4ViewHolder extends RecyclerView.ViewHolder implements GiphyMp4Playable {
|
||||
final class GiphyMp4ViewHolder extends MappingViewHolder<GiphyImage> implements GiphyMp4Playable {
|
||||
|
||||
private static final Projection.Corners CORNERS = new Projection.Corners(ViewUtil.dpToPx(8));
|
||||
|
||||
|
@ -52,7 +52,8 @@ final class GiphyMp4ViewHolder extends RecyclerView.ViewHolder implements GiphyM
|
|||
container.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);
|
||||
}
|
||||
|
||||
void onBind(@NonNull GiphyImage giphyImage) {
|
||||
@Override
|
||||
public void bind(@NonNull GiphyImage giphyImage) {
|
||||
aspectRatio = giphyImage.getGifAspectRatio();
|
||||
mediaItem = MediaItem.fromUri(Uri.parse(giphyImage.getMp4PreviewUrl()));
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.signal.paging.PagingConfig;
|
|||
import org.signal.paging.PagingController;
|
||||
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingModelList;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -30,7 +31,7 @@ public final class GiphyMp4ViewModel extends ViewModel {
|
|||
|
||||
private final GiphyMp4Repository repository;
|
||||
private final MutableLiveData<PagedData<String, GiphyImage>> pagedData;
|
||||
private final LiveData<List<GiphyImage>> images;
|
||||
private final LiveData<MappingModelList> images;
|
||||
private final LiveData<PagingController<String>> pagingController;
|
||||
private final SingleLiveEvent<GiphyMp4SaveResult> saveResultEvents;
|
||||
private final boolean isForMms;
|
||||
|
@ -49,7 +50,7 @@ public final class GiphyMp4ViewModel extends ViewModel {
|
|||
.filterNot(g -> TextUtils.isEmpty(isForMms ? g.getGifMmsUrl() : g.getGifUrl()))
|
||||
.filterNot(g -> TextUtils.isEmpty(g.getMp4PreviewUrl()))
|
||||
.filterNot(g -> TextUtils.isEmpty(g.getStillUrl()))
|
||||
.toList()));
|
||||
.collect(MappingModelList.toMappingModelList())));
|
||||
}
|
||||
|
||||
LiveData<PagedData<String, GiphyImage>> getPagedData() {
|
||||
|
@ -73,7 +74,7 @@ public final class GiphyMp4ViewModel extends ViewModel {
|
|||
return saveResultEvents;
|
||||
}
|
||||
|
||||
public @NonNull LiveData<List<GiphyImage>> getImages() {
|
||||
public @NonNull LiveData<MappingModelList> getImages() {
|
||||
return images;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ import kotlin.jvm.functions.Function1;
|
|||
*/
|
||||
public class MappingAdapter extends ListAdapter<MappingModel<?>, MappingViewHolder<?>> {
|
||||
|
||||
private final Map<Integer, Factory<?>> factories;
|
||||
private final Map<Class<?>, Integer> itemTypes;
|
||||
private int typeCount;
|
||||
final Map<Integer, Factory<?>> factories;
|
||||
final Map<Class<?>, Integer> itemTypes;
|
||||
int typeCount;
|
||||
|
||||
public MappingAdapter() {
|
||||
super(new MappingDiffCallback());
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package org.thoughtcrime.securesms.util.adapter.mapping;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.paging.PagingController;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
/**
|
||||
* A specialized {@link MappingAdapter} backed by a {@link PagingController}.
|
||||
*/
|
||||
public class PagingMappingAdapter<Key> extends MappingAdapter {
|
||||
|
||||
private PagingController<Key> pagingController;
|
||||
|
||||
public PagingMappingAdapter() {
|
||||
this(1, ViewUtil.dpToPx(100));
|
||||
}
|
||||
|
||||
public PagingMappingAdapter(int placeHolderWidth, int placeHolderHeight) {
|
||||
registerFactory(Placeholder.class, parent -> {
|
||||
View view = new FrameLayout(parent.getContext());
|
||||
view.setLayoutParams(new FrameLayout.LayoutParams(placeHolderWidth, placeHolderHeight));
|
||||
return new MappingViewHolder.SimpleViewHolder<>(view);
|
||||
});
|
||||
}
|
||||
|
||||
public void setPagingController(@Nullable PagingController<Key> pagingController) {
|
||||
this.pagingController = pagingController;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable MappingModel<?> getItem(int position) {
|
||||
if (pagingController != null) {
|
||||
pagingController.onDataNeededAroundIndex(position);
|
||||
}
|
||||
return super.getItem(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
MappingModel<?> item = getItem(position);
|
||||
if (item == null) {
|
||||
//noinspection ConstantConditions
|
||||
return itemTypes.get(Placeholder.class);
|
||||
}
|
||||
|
||||
Integer type = itemTypes.get(item.getClass());
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
throw new AssertionError("No view holder factory for type: " + item.getClass());
|
||||
}
|
||||
|
||||
private static class Placeholder implements MappingModel<Placeholder> {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull Placeholder newItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull Placeholder newItem) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue