From 415a61a09b8d648ebcaf8c915f71591c2ff72f7e Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Mon, 7 Sep 2015 15:08:44 -1000 Subject: [PATCH] TransferControlView Closes #4044 // FREEBIE --- res/layout/thumbnail_view.xml | 12 +- res/layout/thumbnail_view_progress_wheel.xml | 12 -- res/layout/transfer_controls_stub.xml | 8 ++ res/layout/transfer_controls_view.xml | 22 ++++ .../securesms/components/AnimatingToggle.java | 28 ++--- .../securesms/components/ThumbnailView.java | 113 +++++------------- .../components/TransferControlView.java | 87 ++++++++++++++ src/org/thoughtcrime/securesms/mms/Slide.java | 6 + .../thoughtcrime/securesms/util/ViewUtil.java | 5 + 9 files changed, 173 insertions(+), 120 deletions(-) delete mode 100644 res/layout/thumbnail_view_progress_wheel.xml create mode 100644 res/layout/transfer_controls_stub.xml create mode 100644 res/layout/transfer_controls_view.xml create mode 100644 src/org/thoughtcrime/securesms/components/TransferControlView.java diff --git a/res/layout/thumbnail_view.xml b/res/layout/thumbnail_view.xml index 80590293de..58b8325d10 100644 --- a/res/layout/thumbnail_view.xml +++ b/res/layout/thumbnail_view.xml @@ -9,23 +9,15 @@ android:contentDescription="@string/conversation_item__mms_image_description" android:layout_margin="@dimen/media_bubble_border_width" /> - + android:layout="@layout/transfer_controls_stub" /> - - diff --git a/res/layout/thumbnail_view_progress_wheel.xml b/res/layout/thumbnail_view_progress_wheel.xml deleted file mode 100644 index 6aeefdf7b2..0000000000 --- a/res/layout/thumbnail_view_progress_wheel.xml +++ /dev/null @@ -1,12 +0,0 @@ - - diff --git a/res/layout/transfer_controls_stub.xml b/res/layout/transfer_controls_stub.xml new file mode 100644 index 0000000000..63c6545c11 --- /dev/null +++ b/res/layout/transfer_controls_stub.xml @@ -0,0 +1,8 @@ + + + diff --git a/res/layout/transfer_controls_view.xml b/res/layout/transfer_controls_view.xml new file mode 100644 index 0000000000..2a8888929f --- /dev/null +++ b/res/layout/transfer_controls_view.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/components/AnimatingToggle.java b/src/org/thoughtcrime/securesms/components/AnimatingToggle.java index 01f45faebe..03a13f73b8 100644 --- a/src/org/thoughtcrime/securesms/components/AnimatingToggle.java +++ b/src/org/thoughtcrime/securesms/components/AnimatingToggle.java @@ -2,22 +2,19 @@ package org.thoughtcrime.securesms.components; import android.content.Context; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; -import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; -import android.view.animation.TranslateAnimation; import android.widget.FrameLayout; import org.thoughtcrime.securesms.R; public class AnimatingToggle extends FrameLayout { - private static final int SPEED_MILLIS = 200; - private View current; public AnimatingToggle(Context context) { @@ -45,11 +42,20 @@ public class AnimatingToggle extends FrameLayout { child.setClickable(false); } - public void display(View view) { + public void display(@Nullable View view) { + display(view, true); + } + + protected void display(@Nullable View view, boolean animated) { if (view == current) return; - animateOut(current, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_out)); - animateIn(view, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_in)); + if (animated) { + if (current != null) animateOut(current, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_out)); + if (view != null) animateIn(view, AnimationUtils.loadAnimation(getContext(), R.anim.animation_toggle_in)); + } else { + if (current != null) current.setVisibility(GONE); + if (view != null) view.setVisibility(VISIBLE); + } current = view; } @@ -78,12 +84,4 @@ public class AnimatingToggle extends FrameLayout { view.setVisibility(View.VISIBLE); view.startAnimation(animation); } - - private int getViewIndex(View view) { - for (int i=0;i slideDeckFuture = null; private SlideDeckListener slideDeckListener = null; @@ -73,13 +65,8 @@ public class ThumbnailView extends FrameLayout { public ThumbnailView(final Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); inflate(context, R.layout.thumbnail_view, this); - radius = getResources().getDimensionPixelSize(R.dimen.message_bubble_corner_radius); - image = (ImageView) findViewById(R.id.thumbnail_image); - progress = (ProgressWheel) findViewById(R.id.progress_wheel); - downloadButton = (ImageButton) findViewById(R.id.download_button); - - setOnClickListener(new ThumbnailClickDispatcher()); - downloadButton.setOnClickListener(new DownloadClickDispatcher()); + radius = getResources().getDimensionPixelSize(R.dimen.message_bubble_corner_radius); + image = (ImageView) findViewById(R.id.thumbnail_image); if (attrs != null) { TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ThumbnailView, 0, 0); @@ -97,40 +84,15 @@ public class ThumbnailView extends FrameLayout { } } - @Override protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (!EventBus.getDefault().isRegistered(this)) EventBus.getDefault().registerSticky(this); - } - - @Override protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - EventBus.getDefault().unregister(this); - } - - private ProgressWheel getProgressWheel() { - if (progress == null) progress = ViewUtil.inflateStub(this, R.id.progress_wheel_stub); - return progress; - } - - private void hideProgressWheel() { - if (progress != null) progress.setVisibility(GONE); - } - private ImageView getRemoveButton() { if (removeButton == null) removeButton = ViewUtil.inflateStub(this, R.id.remove_button_stub); return removeButton; } - @SuppressWarnings("unused") - public void onEventAsync(final PartProgressEvent event) { - if (this.slide != null && event.partId.equals(this.slide.getPart().getPartId())) { - Util.runOnMain(new Runnable() { - @Override public void run() { - getProgressWheel().setInstantProgress(((float)event.progress) / event.total); - if (event.progress >= event.total) animateOutProgress(); - } - }); - } + private TransferControlView getTransferControls() { + if (transferControls == null) transferControls = ViewUtil.inflateStub(this, R.id.transfer_controls_stub); + + return transferControls; } public void setBackgroundColorHint(int color) { @@ -148,7 +110,7 @@ public class ThumbnailView extends FrameLayout { String slideId = id + "::" + timestamp; if (!slideId.equals(this.slideId)) { - hideProgressWheel(); + if (transferControls != null) transferControls.clear(); image.setImageDrawable(null); this.slide = null; this.slideId = slideId; @@ -170,22 +132,21 @@ public class ThumbnailView extends FrameLayout { } Log.w(TAG, "loading part with id " + slide.getPart().getPartId() + ", progress " + slide.getTransferProgress()); - if (!hideControls && slide.getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_STARTED) { - getProgressWheel().spin(); - getProgressWheel().setVisibility(VISIBLE); - downloadButton.setVisibility(GONE); - } else if (!hideControls && slide.getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_AUTO_PENDING || - slide.getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_FAILED) - { - hideProgressWheel(); - downloadButton.setVisibility(VISIBLE); - } else { - hideProgressWheel(); - downloadButton.setVisibility(GONE); - } this.slide = slide; buildGlideRequest(slide, masterSecret).into(image); + + if (this.slide.getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_DONE) { + setOnClickListener(new ThumbnailClickDispatcher()); + } else { + setOnClickListener(null); + } + + if (!hideControls) { + getTransferControls().setSlide(slide); + getTransferControls().setDownloadClickListener(new DownloadClickDispatcher()); + getTransferControls().setVisibility(View.VISIBLE); + } } public void setThumbnailClickListener(ThumbnailClickListener listener) { @@ -201,8 +162,9 @@ public class ThumbnailView extends FrameLayout { } public void clear() { - if (isContextValid()) Glide.clear(image); - if (slideDeckFuture != null) slideDeckFuture.removeListener(slideDeckListener); + if (isContextValid()) Glide.clear(image); + if (slideDeckFuture != null) slideDeckFuture.removeListener(slideDeckListener); + if (transferControls != null) transferControls.clear(); slide = null; slideId = null; slideDeckFuture = null; @@ -211,12 +173,11 @@ public class ThumbnailView extends FrameLayout { public void hideControls(boolean hideControls) { this.hideControls = hideControls; - if (hideControls) hideProgressWheel(); + if (hideControls && transferControls != null) transferControls.setVisibility(View.GONE); } public void showProgressSpinner() { - getProgressWheel().spin(); - getProgressWheel().setVisibility(VISIBLE); + getTransferControls().showProgressSpinner(); } @TargetApi(VERSION_CODES.JELLY_BEAN_MR1) @@ -276,20 +237,6 @@ public class ThumbnailView extends FrameLayout { .fitCenter(); } - private void animateOutProgress() { - if (progress == null) return; - AlphaAnimation animation = new AlphaAnimation(1f, 0f); - animation.setDuration(200); - animation.setAnimationListener(new AnimationListener() { - @Override public void onAnimationStart(Animation animation) { } - @Override public void onAnimationRepeat(Animation animation) { } - @Override public void onAnimationEnd(Animation animation) { - getProgressWheel().setVisibility(View.GONE); - } - }); - getProgressWheel().startAnimation(animation); - } - private class SlideDeckListener implements FutureTaskListener { private final MasterSecret masterSecret; diff --git a/src/org/thoughtcrime/securesms/components/TransferControlView.java b/src/org/thoughtcrime/securesms/components/TransferControlView.java new file mode 100644 index 0000000000..c2406e1b00 --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/TransferControlView.java @@ -0,0 +1,87 @@ +package org.thoughtcrime.securesms.components; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.ImageButton; + +import com.pnikosis.materialishprogress.ProgressWheel; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.database.PartDatabase; +import org.thoughtcrime.securesms.jobs.PartProgressEvent; +import org.thoughtcrime.securesms.mms.Slide; +import org.thoughtcrime.securesms.util.Util; +import org.thoughtcrime.securesms.util.ViewUtil; + +import de.greenrobot.event.EventBus; + +public class TransferControlView extends AnimatingToggle { + private Slide slide; + private ProgressWheel progressWheel; + private ImageButton downloadButton; + + public TransferControlView(Context context) { + this(context, null); + } + + public TransferControlView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TransferControlView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + inflate(context, R.layout.transfer_controls_view, this); + this.progressWheel = ViewUtil.findById(this, R.id.progress_wheel); + this.downloadButton = ViewUtil.findById(this, R.id.download_button); + } + + @Override protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!EventBus.getDefault().isRegistered(this)) EventBus.getDefault().registerSticky(this); + } + + @Override protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + EventBus.getDefault().unregister(this); + } + + public void setSlide(final @NonNull Slide slide) { + this.slide = slide; + + if (slide.getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_STARTED) { + showProgressSpinner(); + } else if (slide.isPendingDownload()) { + display(downloadButton); + } else { + display(null, false); + } + } + + public void showProgressSpinner() { + progressWheel.spin(); + display(progressWheel); + } + + public void setDownloadClickListener(final @Nullable OnClickListener listener) { + downloadButton.setOnClickListener(listener); + } + + public void clear() { + display(null, false); + slide = null; + } + + @SuppressWarnings("unused") + public void onEventAsync(final PartProgressEvent event) { + if (this.slide != null && event.partId.equals(this.slide.getPart().getPartId())) { + Util.runOnMain(new Runnable() { + @Override public void run() { + progressWheel.setInstantProgress(((float)event.progress) / event.total); + if (event.progress >= event.total) display(null); + } + }); + } + } +} diff --git a/src/org/thoughtcrime/securesms/mms/Slide.java b/src/org/thoughtcrime/securesms/mms/Slide.java index 60e925576d..f23ff2e653 100644 --- a/src/org/thoughtcrime/securesms/mms/Slide.java +++ b/src/org/thoughtcrime/securesms/mms/Slide.java @@ -25,6 +25,7 @@ import android.support.annotation.Nullable; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.MediaUtil; +import org.thoughtcrime.securesms.database.PartDatabase; import org.thoughtcrime.securesms.util.Util; import java.io.IOException; @@ -74,6 +75,11 @@ public abstract class Slide { return part.isInProgress(); } + public boolean isPendingDownload() { + return getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_FAILED || + getTransferProgress() == PartDatabase.TRANSFER_PROGRESS_AUTO_PENDING; + } + public long getTransferProgress() { return part.getTransferProgress(); } diff --git a/src/org/thoughtcrime/securesms/util/ViewUtil.java b/src/org/thoughtcrime/securesms/util/ViewUtil.java index 8e41190b80..9f82db6625 100644 --- a/src/org/thoughtcrime/securesms/util/ViewUtil.java +++ b/src/org/thoughtcrime/securesms/util/ViewUtil.java @@ -68,4 +68,9 @@ public class ViewUtil { public static T inflateStub(@NonNull View parent, @IdRes int stubId) { return (T)((ViewStub)parent.findViewById(stubId)).inflate(); } + + @SuppressWarnings("unchecked") + public static T findById(@NonNull View parent, @IdRes int resId) { + return (T) parent.findViewById(resId); + } }