mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Added support for multi-image receive.
This commit is contained in:
@@ -15,32 +15,42 @@ import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.nineoldandroids.animation.Animator;
|
||||
import com.nineoldandroids.animation.ValueAnimator;
|
||||
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import com.pnikosis.materialishprogress.ProgressWheel;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TransferControlView extends FrameLayout {
|
||||
private static final int TRANSITION_MS = 300;
|
||||
|
||||
@Nullable private Slide slide;
|
||||
@Nullable private View current;
|
||||
@Nullable private List<Slide> slides;
|
||||
@Nullable private View current;
|
||||
|
||||
private final ProgressWheel progressWheel;
|
||||
private final TextView downloadDetails;
|
||||
private final View downloadDetails;
|
||||
private final TextView downloadDetailsText;
|
||||
private final int contractedWidth;
|
||||
private final int expandedWidth;
|
||||
|
||||
private final Map<Attachment, Float> downloadProgress;
|
||||
|
||||
public TransferControlView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -61,10 +71,12 @@ public class TransferControlView extends FrameLayout {
|
||||
ViewUtil.setBackground(this, background);
|
||||
setVisibility(GONE);
|
||||
|
||||
this.progressWheel = ViewUtil.findById(this, R.id.progress_wheel);
|
||||
this.downloadDetails = ViewUtil.findById(this, R.id.download_details);
|
||||
this.contractedWidth = getResources().getDimensionPixelSize(R.dimen.transfer_controls_contracted_width);
|
||||
this.expandedWidth = getResources().getDimensionPixelSize(R.dimen.transfer_controls_expanded_width);
|
||||
this.downloadProgress = new HashMap<>();
|
||||
this.progressWheel = ViewUtil.findById(this, R.id.progress_wheel);
|
||||
this.downloadDetails = ViewUtil.findById(this, R.id.download_details);
|
||||
this.downloadDetailsText = ViewUtil.findById(this, R.id.download_details_text);
|
||||
this.contractedWidth = getResources().getDimensionPixelSize(R.dimen.transfer_controls_contracted_width);
|
||||
this.expandedWidth = getResources().getDimensionPixelSize(R.dimen.transfer_controls_expanded_width);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,20 +103,54 @@ public class TransferControlView extends FrameLayout {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
public void setSlide(final @NonNull Slide slide) {
|
||||
this.slide = slide;
|
||||
if (slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) {
|
||||
showProgressSpinner();
|
||||
} else if (slide.isPendingDownload()) {
|
||||
downloadDetails.setText(slide.getContentDescription());
|
||||
display(downloadDetails);
|
||||
public void setSlide(final @NonNull Slide slides) {
|
||||
setSlides(Collections.singletonList(slides));
|
||||
}
|
||||
|
||||
public void setSlides(final @NonNull List<Slide> slides) {
|
||||
if (slides.isEmpty()) {
|
||||
throw new IllegalArgumentException("Must provide at least one slide.");
|
||||
}
|
||||
|
||||
this.slides = slides;
|
||||
|
||||
if (!isUpdateToExistingSet(slides)) {
|
||||
downloadProgress.clear();
|
||||
Stream.of(slides).forEach(s -> downloadProgress.put(s.asAttachment(), 0f));
|
||||
} else {
|
||||
display(null);
|
||||
for (Slide slide : slides) {
|
||||
if (slide.asAttachment().getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
|
||||
downloadProgress.put(slide.asAttachment(), 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (getTransferState(slides)) {
|
||||
case AttachmentDatabase.TRANSFER_PROGRESS_STARTED:
|
||||
showProgressSpinner(calculateProgress(downloadProgress));
|
||||
break;
|
||||
case AttachmentDatabase.TRANSFER_PROGRESS_PENDING:
|
||||
case AttachmentDatabase.TRANSFER_PROGRESS_FAILED:
|
||||
downloadDetailsText.setText(getDownloadText(this.slides));
|
||||
display(downloadDetails);
|
||||
break;
|
||||
default:
|
||||
display(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void showProgressSpinner() {
|
||||
progressWheel.spin();
|
||||
showProgressSpinner(calculateProgress(downloadProgress));
|
||||
}
|
||||
|
||||
public void showProgressSpinner(float progress) {
|
||||
if (progress == 0) {
|
||||
progressWheel.spin();
|
||||
} else {
|
||||
progressWheel.setInstantProgress(progress);
|
||||
}
|
||||
|
||||
display(progressWheel);
|
||||
}
|
||||
|
||||
@@ -120,12 +166,51 @@ public class TransferControlView extends FrameLayout {
|
||||
current.setVisibility(GONE);
|
||||
}
|
||||
current = null;
|
||||
slide = null;
|
||||
slides = null;
|
||||
}
|
||||
|
||||
public void setShowDownloadText(boolean showDownloadText) {
|
||||
downloadDetailsText.setVisibility(showDownloadText ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
private boolean isUpdateToExistingSet(@NonNull List<Slide> slides) {
|
||||
if (slides.size() != downloadProgress.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Slide slide : slides) {
|
||||
if (!downloadProgress.containsKey(slide.asAttachment())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getTransferState(@NonNull List<Slide> slides) {
|
||||
int transferState = AttachmentDatabase.TRANSFER_PROGRESS_DONE;
|
||||
for (Slide slide : slides) {
|
||||
if (slide.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_PENDING && transferState == AttachmentDatabase.TRANSFER_PROGRESS_DONE) {
|
||||
transferState = slide.getTransferState();
|
||||
} else {
|
||||
transferState = Math.max(transferState, slide.getTransferState());
|
||||
}
|
||||
}
|
||||
return transferState;
|
||||
}
|
||||
|
||||
private String getDownloadText(@NonNull List<Slide> slides) {
|
||||
if (slides.size() == 1) {
|
||||
return slides.get(0).getContentDescription();
|
||||
} else {
|
||||
int downloadCount = Stream.of(slides).reduce(0, (count, slide) -> slide.getTransferState() != AttachmentDatabase.TRANSFER_PROGRESS_DONE ? count + 1 : count);
|
||||
return getContext().getResources().getQuantityString(R.plurals.TransferControlView_n_items, downloadCount, downloadCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void display(@Nullable final View view) {
|
||||
final int sourceWidth = current == downloadDetails ? expandedWidth : contractedWidth;
|
||||
final int targetWidth = view == downloadDetails ? expandedWidth : contractedWidth;
|
||||
final int sourceWidth = (current == downloadDetails && downloadDetailsText.getVisibility() == VISIBLE) ? expandedWidth : contractedWidth;
|
||||
final int targetWidth = (view == downloadDetails && downloadDetailsText.getVisibility() == VISIBLE) ? expandedWidth : contractedWidth;
|
||||
|
||||
if (current == view || current == null) {
|
||||
ViewGroup.LayoutParams layoutParams = getLayoutParams();
|
||||
@@ -149,28 +234,31 @@ public class TransferControlView extends FrameLayout {
|
||||
|
||||
private Animator getWidthAnimator(final int from, final int to) {
|
||||
final ValueAnimator anim = ValueAnimator.ofInt(from, to);
|
||||
anim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
final int val = (Integer)animation.getAnimatedValue();
|
||||
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
|
||||
layoutParams.width = val;
|
||||
setLayoutParams(layoutParams);
|
||||
}
|
||||
anim.addUpdateListener(animation -> {
|
||||
final int val = (Integer)animation.getAnimatedValue();
|
||||
final ViewGroup.LayoutParams layoutParams = getLayoutParams();
|
||||
layoutParams.width = val;
|
||||
setLayoutParams(layoutParams);
|
||||
});
|
||||
anim.setInterpolator(new FastOutSlowInInterpolator());
|
||||
anim.setDuration(TRANSITION_MS);
|
||||
return anim;
|
||||
}
|
||||
|
||||
private float calculateProgress(@NonNull Map<Attachment, Float> downloadProgress) {
|
||||
float totalProgress = 0;
|
||||
for (float progress : downloadProgress.values()) {
|
||||
totalProgress += progress / downloadProgress.size();
|
||||
}
|
||||
return totalProgress;
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.ASYNC)
|
||||
public void onEventAsync(final PartProgressEvent event) {
|
||||
if (this.slide != null && event.attachment.equals(this.slide.asAttachment())) {
|
||||
Util.runOnMain(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressWheel.setInstantProgress(((float)event.progress) / event.total);
|
||||
}
|
||||
if (downloadProgress.containsKey(event.attachment)) {
|
||||
Util.runOnMain(() -> {
|
||||
downloadProgress.put(event.attachment, ((float)event.progress) / event.total);
|
||||
progressWheel.setInstantProgress(calculateProgress(downloadProgress));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user