That fuck shit the fascists are using
at master 158 lines 6.4 kB view raw
1package org.tm.archive.conversation; 2 3import android.animation.ValueAnimator; 4import android.content.res.Resources; 5import android.view.View; 6import android.view.animation.Interpolator; 7 8import androidx.annotation.NonNull; 9import androidx.annotation.Nullable; 10 11import org.tm.archive.conversation.v2.items.InteractiveConversationElement; 12import org.tm.archive.util.Util; 13 14import java.util.List; 15 16final class ConversationSwipeAnimationHelper { 17 18 static final float TRIGGER_DX = dpToPx(64); 19 static final float MAX_DX = dpToPx(96); 20 21 private static final float REPLY_SCALE_OVERSHOOT = 1.8f; 22 private static final float REPLY_SCALE_MAX = 1.2f; 23 private static final float REPLY_SCALE_MIN = 1f; 24 private static final long REPLY_SCALE_OVERSHOOT_DURATION = 200; 25 26 private static final Interpolator BUBBLE_INTERPOLATOR = new BubblePositionInterpolator(0f, TRIGGER_DX, MAX_DX); 27 private static final Interpolator REPLY_ALPHA_INTERPOLATOR = new ClampingLinearInterpolator(0f, 1f, 1f); 28 private static final Interpolator REPLY_TRANSITION_INTERPOLATOR = new ClampingLinearInterpolator(0f, dpToPx(10)); 29 private static final Interpolator AVATAR_INTERPOLATOR = new ClampingLinearInterpolator(0f, dpToPx(8)); 30 private static final Interpolator REPLY_SCALE_INTERPOLATOR = new ClampingLinearInterpolator(REPLY_SCALE_MIN, REPLY_SCALE_MAX); 31 private static final Interpolator QUOTED_ALPHA_INTERPOLATOR = new ClampingLinearInterpolator(1f, 0f, 3f); 32 33 private ConversationSwipeAnimationHelper() { 34 } 35 36 public static void update(@NonNull InteractiveConversationElement interactiveConversationElement, float dx, float sign) { 37 float progress = dx / TRIGGER_DX; 38 39 updateBodyBubbleTransition(interactiveConversationElement.getBubbleViews(), dx, sign); 40 updateReactionsTransition(interactiveConversationElement.getReactionsView(), dx, sign); 41 updateQuotedIndicatorTransition(interactiveConversationElement.getQuotedIndicatorView(), dx, progress, sign); 42 updateReplyIconTransition(interactiveConversationElement.getReplyView(), dx, progress, sign); 43 updateContactPhotoHolderTransition(interactiveConversationElement.getContactPhotoHolderView(), progress, sign); 44 updateContactPhotoHolderTransition(interactiveConversationElement.getBadgeImageView(), progress, sign); 45 } 46 47 public static void trigger(@NonNull InteractiveConversationElement interactiveConversationElement) { 48 triggerReplyIcon(interactiveConversationElement.getReplyView()); 49 } 50 51 private static void updateBodyBubbleTransition(@NonNull List<View> bubbleViews, float dx, float sign) { 52 for (View view : bubbleViews) { 53 view.setTranslationX(BUBBLE_INTERPOLATOR.getInterpolation(dx) * sign); 54 } 55 } 56 57 private static void updateReactionsTransition(@NonNull View reactionsContainer, float dx, float sign) { 58 reactionsContainer.setTranslationX(BUBBLE_INTERPOLATOR.getInterpolation(dx) * sign); 59 } 60 61 private static void updateQuotedIndicatorTransition(@Nullable View quotedIndicator, float dx, float progress, float sign) { 62 if (quotedIndicator != null) { 63 quotedIndicator.setTranslationX(BUBBLE_INTERPOLATOR.getInterpolation(dx) * sign); 64 quotedIndicator.setAlpha(QUOTED_ALPHA_INTERPOLATOR.getInterpolation(progress)); 65 } 66 } 67 68 private static void updateReplyIconTransition(@NonNull View replyIcon, float dx, float progress, float sign) { 69 if (progress > 0.05f) { 70 replyIcon.setAlpha(REPLY_ALPHA_INTERPOLATOR.getInterpolation(progress)); 71 } else replyIcon.setAlpha(0f); 72 73 replyIcon.setTranslationX(REPLY_TRANSITION_INTERPOLATOR.getInterpolation(progress) * sign); 74 75 if (dx < TRIGGER_DX) { 76 float scale = REPLY_SCALE_INTERPOLATOR.getInterpolation(progress); 77 replyIcon.setScaleX(scale); 78 replyIcon.setScaleY(scale); 79 } 80 } 81 82 private static void updateContactPhotoHolderTransition(@Nullable View contactPhotoHolder, 83 float progress, 84 float sign) 85 { 86 if (contactPhotoHolder == null) return; 87 contactPhotoHolder.setTranslationX(AVATAR_INTERPOLATOR.getInterpolation(progress) * sign); 88 } 89 90 private static void triggerReplyIcon(@NonNull View replyIcon) { 91 ValueAnimator animator = ValueAnimator.ofFloat(REPLY_SCALE_MAX, REPLY_SCALE_OVERSHOOT, REPLY_SCALE_MAX); 92 animator.setDuration(REPLY_SCALE_OVERSHOOT_DURATION); 93 animator.addUpdateListener(animation -> { 94 replyIcon.setScaleX((float) animation.getAnimatedValue()); 95 replyIcon.setScaleY((float) animation.getAnimatedValue()); 96 }); 97 animator.start(); 98 } 99 100 private static int dpToPx(int dp) { 101 return (int) (dp * Resources.getSystem().getDisplayMetrics().density); 102 } 103 104 private static final class BubblePositionInterpolator implements Interpolator { 105 106 private final float start; 107 private final float middle; 108 private final float end; 109 110 private BubblePositionInterpolator(float start, float middle, float end) { 111 this.start = start; 112 this.middle = middle; 113 this.end = end; 114 } 115 116 @Override 117 public float getInterpolation(float input) { 118 if (input < start) { 119 return start; 120 } else if (input < middle) { 121 return input; 122 } else { 123 float segmentLength = end - middle; 124 float segmentTraveled = input - middle; 125 float segmentCompletion = segmentTraveled / segmentLength; 126 float scaleDownFactor = middle / (input * 2); 127 float output = middle + (segmentLength * segmentCompletion * scaleDownFactor); 128 129 return Math.min(output, end); 130 } 131 } 132 } 133 134 private static final class ClampingLinearInterpolator implements Interpolator { 135 136 private final float slope; 137 private final float yIntercept; 138 private final float max; 139 private final float min; 140 141 ClampingLinearInterpolator(float start, float end) { 142 this(start, end, 1.0f); 143 } 144 145 ClampingLinearInterpolator(float start, float end, float scale) { 146 slope = (end - start) * scale; 147 yIntercept = start; 148 max = Math.max(start, end); 149 min = Math.min(start, end); 150 } 151 152 @Override 153 public float getInterpolation(float input) { 154 return Util.clamp(slope * input + yIntercept, min, max); 155 } 156 } 157 158}