kopia lustrzana https://github.com/ryukoposting/Signal-Android
154 wiersze
5.2 KiB
Java
154 wiersze
5.2 KiB
Java
package org.thoughtcrime.securesms.giph.mp4;
|
|
|
|
import android.util.SparseArray;
|
|
import android.view.ViewGroup;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import org.thoughtcrime.securesms.util.Projection;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Logic for updating content and positioning of videos as the user scrolls the list of gifs.
|
|
*/
|
|
public final class GiphyMp4ProjectionRecycler implements GiphyMp4PlaybackController.Callback {
|
|
|
|
private final List<GiphyMp4ProjectionPlayerHolder> holders;
|
|
private final SparseArray<GiphyMp4ProjectionPlayerHolder> playing;
|
|
private final SparseArray<GiphyMp4ProjectionPlayerHolder> notPlaying;
|
|
|
|
public GiphyMp4ProjectionRecycler(@NonNull List<GiphyMp4ProjectionPlayerHolder> holders) {
|
|
this.holders = holders;
|
|
this.playing = new SparseArray<>(holders.size());
|
|
this.notPlaying = new SparseArray<>(holders.size());
|
|
}
|
|
|
|
@Override
|
|
public void update(@NonNull RecyclerView recyclerView,
|
|
@NonNull List<GiphyMp4Playable> holders,
|
|
@NonNull Set<Integer> playbackSet)
|
|
{
|
|
stopAndReleaseAssignedVideos(playbackSet);
|
|
|
|
for (final GiphyMp4Playable holder : holders) {
|
|
if (playbackSet.contains(holder.getAdapterPosition())) {
|
|
startPlayback(recyclerView, acquireHolderForPosition(holder.getAdapterPosition()), holder);
|
|
} else {
|
|
holder.showProjectionArea();
|
|
}
|
|
}
|
|
|
|
for (final GiphyMp4Playable holder : holders) {
|
|
updateVideoDisplayPositionAndSize(recyclerView, holder);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void updateVideoDisplayPositionAndSize(@NonNull RecyclerView recyclerView, @NonNull GiphyMp4Playable holder) {
|
|
GiphyMp4ProjectionPlayerHolder playerHolder = getCurrentHolder(holder.getAdapterPosition());
|
|
if (playerHolder != null) {
|
|
updateVideoDisplayPositionAndSize(recyclerView, playerHolder, holder);
|
|
}
|
|
}
|
|
|
|
private void stopAndReleaseAssignedVideos(@NonNull Set<Integer> playbackSet) {
|
|
List<Integer> markedForDeletion = new ArrayList<>(playing.size());
|
|
for (int i = 0; i < playing.size(); i++) {
|
|
if (!playbackSet.contains(playing.keyAt(i))) {
|
|
notPlaying.put(playing.keyAt(i), playing.valueAt(i));
|
|
playing.valueAt(i).clearMedia();
|
|
playing.valueAt(i).setOnPlaybackReady(null);
|
|
markedForDeletion.add(playing.keyAt(i));
|
|
}
|
|
}
|
|
|
|
for (final Integer key : markedForDeletion) {
|
|
playing.remove(key);
|
|
}
|
|
|
|
for (int i = 0; i < notPlaying.size(); i++) {
|
|
notPlaying.valueAt(i).hide();
|
|
}
|
|
}
|
|
|
|
private void updateVideoDisplayPositionAndSize(@NonNull RecyclerView recyclerView,
|
|
@NonNull GiphyMp4ProjectionPlayerHolder holder,
|
|
@NonNull GiphyMp4Playable giphyMp4Playable)
|
|
{
|
|
if (!giphyMp4Playable.canPlayContent()) {
|
|
return;
|
|
}
|
|
|
|
Projection projection = giphyMp4Playable.getGiphyMp4PlayableProjection(recyclerView);
|
|
|
|
holder.getContainer().setX(projection.getX());
|
|
holder.getContainer().setY(projection.getY() + recyclerView.getTranslationY());
|
|
|
|
ViewGroup.LayoutParams params = holder.getContainer().getLayoutParams();
|
|
if (params.width != projection.getWidth() || params.height != projection.getHeight()) {
|
|
params.width = projection.getWidth();
|
|
params.height = projection.getHeight();
|
|
holder.getContainer().setLayoutParams(params);
|
|
}
|
|
|
|
holder.setCorners(projection.getCorners());
|
|
|
|
projection.release();
|
|
}
|
|
|
|
private void startPlayback(@NonNull RecyclerView parent, @NonNull GiphyMp4ProjectionPlayerHolder holder, @NonNull GiphyMp4Playable giphyMp4Playable) {
|
|
if (!Objects.equals(holder.getMediaItem(), giphyMp4Playable.getMediaItem())) {
|
|
holder.setOnPlaybackReady(null);
|
|
giphyMp4Playable.showProjectionArea();
|
|
|
|
holder.show();
|
|
holder.setOnPlaybackReady(() -> {
|
|
giphyMp4Playable.hideProjectionArea();
|
|
parent.invalidate();
|
|
});
|
|
holder.playContent(giphyMp4Playable.getMediaItem(), giphyMp4Playable.getPlaybackPolicyEnforcer());
|
|
} else {
|
|
holder.setOnPlaybackReady(() -> {
|
|
giphyMp4Playable.hideProjectionArea();
|
|
parent.invalidate();
|
|
});
|
|
}
|
|
}
|
|
|
|
public @Nullable GiphyMp4ProjectionPlayerHolder getCurrentHolder(int adapterPosition) {
|
|
if (playing.get(adapterPosition) != null) {
|
|
return playing.get(adapterPosition);
|
|
} else if (notPlaying.get(adapterPosition) != null) {
|
|
return notPlaying.get(adapterPosition);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private @NonNull GiphyMp4ProjectionPlayerHolder acquireHolderForPosition(int adapterPosition) {
|
|
GiphyMp4ProjectionPlayerHolder holder = playing.get(adapterPosition);
|
|
if (holder == null) {
|
|
if (notPlaying.size() != 0) {
|
|
holder = notPlaying.get(adapterPosition);
|
|
if (holder == null) {
|
|
int key = notPlaying.keyAt(0);
|
|
holder = Objects.requireNonNull(notPlaying.get(key));
|
|
notPlaying.remove(key);
|
|
} else {
|
|
notPlaying.remove(adapterPosition);
|
|
}
|
|
} else {
|
|
holder = holders.remove(0);
|
|
}
|
|
playing.put(adapterPosition, holder);
|
|
}
|
|
return holder;
|
|
}
|
|
}
|