That fuck shit the fascists are using
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}