diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java index 1e68d7d5d2..2772ec7535 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/Camera1Fragment.java @@ -39,6 +39,7 @@ import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.LoggingFragment; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.animation.AnimationCompleteListener; +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations; import org.thoughtcrime.securesms.mediasend.v2.MediaCountIndicatorButton; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; import org.thoughtcrime.securesms.mms.GlideApp; @@ -171,6 +172,7 @@ public class Camera1Fragment extends LoggingFragment implements CameraFragment, public void fadeOutControls(@NonNull Runnable onEndAction) { controlsContainer.setEnabled(false); controlsContainer.animate() + .setInterpolator(MediaAnimations.getInterpolator()) .setDuration(250) .alpha(0f) .setListener(new AnimationCompleteListener() { @@ -186,6 +188,7 @@ public class Camera1Fragment extends LoggingFragment implements CameraFragment, public void fadeInControls() { controlsContainer.setEnabled(false); controlsContainer.animate() + .setInterpolator(MediaAnimations.getInterpolator()) .setDuration(250) .alpha(1f) .setListener(new AnimationCompleteListener() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java index 25e36447e1..e53ec3572f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java @@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.animation.AnimationCompleteListener; import org.thoughtcrime.securesms.components.TooltipPopup; import org.thoughtcrime.securesms.mediasend.camerax.CameraXFlashToggleView; import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil; +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations; import org.thoughtcrime.securesms.mediasend.v2.MediaCountIndicatorButton; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; import org.thoughtcrime.securesms.mms.MediaConstraints; @@ -169,6 +170,7 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment { controlsContainer.animate() .setDuration(250) .alpha(0f) + .setInterpolator(MediaAnimations.getInterpolator()) .setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { @@ -184,6 +186,7 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment { controlsContainer.animate() .setDuration(250) .alpha(1f) + .setInterpolator(MediaAnimations.getInterpolator()) .setListener(new AnimationCompleteListener() { @Override public void onAnimationEnd(Animator animation) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaAnimations.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaAnimations.kt index d3de416261..5888e6d10e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaAnimations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaAnimations.kt @@ -1,44 +1,13 @@ package org.thoughtcrime.securesms.mediasend.v2 -import android.animation.Animator -import android.view.View -import org.thoughtcrime.securesms.animation.AnimationCompleteListener -import org.thoughtcrime.securesms.util.visible +import android.view.animation.Interpolator +import androidx.core.graphics.PathParser +import androidx.core.view.animation.PathInterpolatorCompat object MediaAnimations { - private const val FADE_ANIMATION_DURATION = 150L - - fun fadeIn(view: View) { - if (view.visible) { - return - } - - view.visible = true - view.animate() - .setDuration(FADE_ANIMATION_DURATION) - .alpha(1f) - } - - fun fadeOut(view: View) { - if (!view.visible) { - return - } - - view.animate() - .setDuration(FADE_ANIMATION_DURATION) - .setListener(object : AnimationCompleteListener() { - override fun onAnimationEnd(animation: Animator?) { - view.visible = false - } - }) - .alpha(0f) - } - - fun fade(view: View, fadeIn: Boolean) { - if (fadeIn) { - fadeIn(view) - } else { - fadeOut(view) - } - } + /** + * Fast-In-Extra-Slow-Out Interpolator + */ + @JvmStatic + val interpolator: Interpolator = PathInterpolatorCompat.create(PathParser.createPathFromPathData("M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1")) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt index 26c77331ab..6d29419ab7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt @@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectFor import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult import org.thoughtcrime.securesms.mediasend.v2.HudCommand +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionNavigator import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionNavigator.Companion.requestPermissionsForGallery import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionState @@ -273,6 +274,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment) { val animatorSet = AnimatorSet() animatorSet.playTogether(animators) + animatorSet.interpolator = MediaAnimations.interpolator animatorSet.start() this.animatorSet = animatorSet diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java index 8e2abf6328..751cf16ecc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorFragment.java @@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.imageeditor.renderers.FaceBlurRenderer; import org.thoughtcrime.securesms.imageeditor.renderers.MultiLineTextRenderer; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.mediasend.MediaSendPageFragment; +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations; import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.PushMediaConstraints; import org.thoughtcrime.securesms.mms.SentMediaQuality; @@ -648,6 +649,7 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu resizeAnimation = new ResizeAnimation(imageEditorView, targetWidth, targetHeight); resizeAnimation.setDuration(250); + resizeAnimation.setInterpolator(MediaAnimations.getInterpolator()); imageEditorView.startAnimation(resizeAnimation); } @@ -668,6 +670,7 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu resizeAnimation = new ResizeAnimation(imageEditorView, targetWidth, targetHeight); resizeAnimation.setDuration(250); + resizeAnimation.setInterpolator(MediaAnimations.getInterpolator()); imageEditorView.startAnimation(resizeAnimation); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt index ed3f2d626f..580f2846b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/ImageEditorHudV2.kt @@ -11,7 +11,6 @@ import android.util.AttributeSet import android.view.HapticFeedbackConstants import android.view.MotionEvent import android.view.View -import android.view.animation.DecelerateInterpolator import android.widget.FrameLayout import android.widget.ImageView import android.widget.SeekBar @@ -24,6 +23,7 @@ import com.airbnb.lottie.SimpleColorFilter import com.google.android.material.switchmaterial.SwitchMaterial import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.TooltipPopup +import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations import org.thoughtcrime.securesms.scribbles.HSVColorSlider.getColor import org.thoughtcrime.securesms.scribbles.HSVColorSlider.setColor import org.thoughtcrime.securesms.scribbles.HSVColorSlider.setUpForColor @@ -180,15 +180,9 @@ class ImageEditorHudV2 @JvmOverloads constructor( widthSeekBar.setOnTouchListener { v, event -> if (event.action == MotionEvent.ACTION_DOWN) { - v?.animate() - ?.setDuration(ANIMATION_DURATION) - ?.setInterpolator(DecelerateInterpolator()) - ?.translationX(ViewUtil.dpToPx(36).toFloat()) + animateWidthSeekbarIn() } else if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) { - v?.animate() - ?.setDuration(ANIMATION_DURATION) - ?.setInterpolator(DecelerateInterpolator()) - ?.translationX(0f) + animateWidthSeekbarOut() } v.onTouchEvent(event) @@ -197,6 +191,20 @@ class ImageEditorHudV2 @JvmOverloads constructor( widthSeekBar.progress = 20 } + private fun animateWidthSeekbarIn() { + widthSeekBar.animate() + ?.setDuration(ANIMATION_DURATION) + ?.setInterpolator(MediaAnimations.interpolator) + ?.translationX(ViewUtil.dpToPx(36).toFloat()) + } + + private fun animateWidthSeekbarOut() { + widthSeekBar.animate() + ?.setDuration(ANIMATION_DURATION) + ?.setInterpolator(MediaAnimations.interpolator) + ?.translationX(0f) + } + fun setUpForAvatarEditing() { isAvatarEdit = true } @@ -292,6 +300,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( ObjectAnimator.ofFloat(deleteBackground, "scaleY", deleteBackground.scaleY, 1.365f), ) duration = ANIMATION_DURATION + interpolator = MediaAnimations.interpolator start() } } @@ -304,6 +313,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( ObjectAnimator.ofFloat(deleteBackground, "scaleY", deleteBackground.scaleY, 1f), ) duration = ANIMATION_DURATION + interpolator = MediaAnimations.interpolator start() } } @@ -440,6 +450,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( modeAnimatorSet = AnimatorSet().apply { playTogether(animations) duration = ANIMATION_DURATION + interpolator = MediaAnimations.interpolator start() } } @@ -454,6 +465,7 @@ class ImageEditorHudV2 @JvmOverloads constructor( undoAnimatorSet = AnimatorSet().apply { playTogether(animations) duration = ANIMATION_DURATION + interpolator = MediaAnimations.interpolator start() } } diff --git a/app/src/main/res/layout/v2_media_review_fragment.xml b/app/src/main/res/layout/v2_media_review_fragment.xml index e81709d700..17d7966eab 100644 --- a/app/src/main/res/layout/v2_media_review_fragment.xml +++ b/app/src/main/res/layout/v2_media_review_fragment.xml @@ -182,7 +182,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="top" - app:constraint_referenced_ids="crop_and_rotate_tool,draw_tool,quality_selector,save_to_media" + app:constraint_referenced_ids="crop_and_rotate_tool,draw_tool,quality_selector,save_to_media,send" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/witness-verifications.gradle b/app/witness-verifications.gradle index 36b952515a..0d13b3a775 100644 --- a/app/witness-verifications.gradle +++ b/app/witness-verifications.gradle @@ -309,9 +309,15 @@ dependencyVerification { ['com.google.android.datatransport:transport-runtime:3.0.0', '691bd6ee2bf93182d29cb8a3a6f735098337e6f35d7fc9c8a79f17fdae604894'], + ['com.google.android.exoplayer:exoplayer-common:2.15.0', + 'bf8b384deff11676958a29141726df455e23bd7646b10782674fc1b4bb78e00a'], + ['com.google.android.exoplayer:exoplayer-core:2.15.0', '8ae0c0027108181739e8a008377c8eb7fb93c4e04e3efdb5846662dd1ca9eba2'], + ['com.google.android.exoplayer:exoplayer-extractor:2.15.0', + '7e185dd1e4bac1d2569c3741bf9d350591ec07a036720a097a38e1099d6b88c3'], + ['com.google.android.exoplayer:exoplayer-ui:2.15.0', '9e1869798de1ce16d9feb4fd97097f11c7cd54a2018c91d22aafd793f6a8dadf'],