NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextViewWavesDra...

439 lines
19 KiB
Java

package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.SystemClock;
import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.voip.VoIPService;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
public class FragmentContextViewWavesDrawable {
public final static int MUTE_BUTTON_STATE_MUTE = 1;
public final static int MUTE_BUTTON_STATE_UNMUTE = 0;
public final static int MUTE_BUTTON_STATE_CONNECTING = 2;
public final static int MUTE_BUTTON_STATE_MUTED_BY_ADMIN = 3;
WeavingState[] states = new WeavingState[4];
WeavingState currentState;
WeavingState previousState;
WeavingState pausedState;
private float amplitude;
private float amplitude2;
private float animateToAmplitude;
private float animateAmplitudeDiff;
private float animateAmplitudeDiff2;
private long lastUpdateTime;
float progressToState = 1f;
ArrayList<View> parents = new ArrayList<>();
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
LineBlobDrawable lineBlobDrawable = new LineBlobDrawable(5);
LineBlobDrawable lineBlobDrawable1 = new LineBlobDrawable(7);
LineBlobDrawable lineBlobDrawable2 = new LineBlobDrawable(8);
RectF rect = new RectF();
Path path = new Path();
private final Paint selectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public FragmentContextViewWavesDrawable() {
for (int i = 0; i < 4; i++) {
states[i] = new WeavingState(i);
}
}
public void draw(float left, float top, float right, float bottom, Canvas canvas, FragmentContextView parentView, float progress) {
boolean update;
checkColors();
if (parentView == null) {
update = false;
} else {
update = parents.size() > 0 && parentView == parents.get(0);
}
if (top > bottom) {
return;
}
long dt = 0;
boolean rippleTransition = currentState != null && previousState != null && ((currentState.currentState == MUTE_BUTTON_STATE_MUTE && previousState.currentState == MUTE_BUTTON_STATE_UNMUTE) || (previousState.currentState == MUTE_BUTTON_STATE_MUTE && currentState.currentState == MUTE_BUTTON_STATE_UNMUTE));
if (update) {
long newTime = SystemClock.elapsedRealtime();
dt = newTime - lastUpdateTime;
lastUpdateTime = newTime;
if (dt > 20) {
dt = 17;
}
if (dt < 3) {
update = false;
}
}
if (update) {
if (animateToAmplitude != amplitude) {
amplitude += animateAmplitudeDiff * dt;
if (animateAmplitudeDiff > 0) {
if (amplitude > animateToAmplitude) {
amplitude = animateToAmplitude;
}
} else {
if (amplitude < animateToAmplitude) {
amplitude = animateToAmplitude;
}
}
parentView.invalidate();
}
if (animateToAmplitude != amplitude2) {
amplitude2 += animateAmplitudeDiff2 * dt;
if (animateAmplitudeDiff2 > 0) {
if (amplitude2 > animateToAmplitude) {
amplitude2 = animateToAmplitude;
}
} else {
if (amplitude2 < animateToAmplitude) {
amplitude2 = animateToAmplitude;
}
}
parentView.invalidate();
}
if (previousState != null) {
progressToState += dt / 250f;
if (progressToState > 1f) {
progressToState = 1f;
previousState = null;
}
parentView.invalidate();
}
}
for (int i = 0; i < 2; i++) {
float alpha;
if (i == 0 && previousState == null) {
continue;
}
if (i == 0) {
alpha = 1f - progressToState;
previousState.setToPaint(paint);
} else {
if (currentState == null) {
return;
}
alpha = previousState != null ? progressToState : 1f;
if (update) {
currentState.update((int) (bottom - top), (int) (right - left), dt, amplitude);
}
currentState.setToPaint(paint);
}
lineBlobDrawable.minRadius = 0;
lineBlobDrawable.maxRadius = AndroidUtilities.dp(2) + AndroidUtilities.dp(2) * amplitude;
lineBlobDrawable1.minRadius = AndroidUtilities.dp(0);
lineBlobDrawable1.maxRadius = AndroidUtilities.dp(3) + AndroidUtilities.dp(9) * amplitude;
lineBlobDrawable2.minRadius = AndroidUtilities.dp(0);
lineBlobDrawable2.maxRadius = AndroidUtilities.dp(3) + AndroidUtilities.dp(9) * amplitude;
if (i == 1 && update) {
lineBlobDrawable.update(amplitude, 0.3f);
lineBlobDrawable1.update(amplitude, 0.7f);
lineBlobDrawable2.update(amplitude, 0.7f);
}
// if (rippleTransition) {
// paint.setAlpha(76);
// canvas.save();
// float cx = right - AndroidUtilities.dp(18);
// float r = (right - left) * 1.1f * progressToState;
// float offset = (float) Math.sqrt(r * r - (bottom - top) * (bottom - top));
// if (i == 0) {
// if (cx - offset > left) {
// canvas.clipRect(left, top - AndroidUtilities.dp(20), cx - offset, bottom);
// float top1 = AndroidUtilities.dp(6) * amplitude2;
// float top2 = AndroidUtilities.dp(6) * amplitude2;
// lineBlobDrawable1.draw(left, top - top1, right, bottom, canvas, paint, top, progress);
// lineBlobDrawable2.draw(left, top - top2, right, bottom, canvas, paint, top, progress);
// }
// } else {
// if (cx - offset > left) {
// canvas.clipRect(cx - offset, top - AndroidUtilities.dp(20), right, bottom);
// }
// float top1 = AndroidUtilities.dp(6) * amplitude2;
// float top2 = AndroidUtilities.dp(6) * amplitude2;
// lineBlobDrawable1.draw(left, top - top1, right, bottom, canvas, paint, top, progress);
// lineBlobDrawable2.draw(left, top - top2, right, bottom, canvas, paint, top, progress);
// }
// canvas.restore();
// } else {
paint.setAlpha((int) (76 * alpha));
float top1 = AndroidUtilities.dp(6) * amplitude2;
float top2 = AndroidUtilities.dp(6) * amplitude2;
lineBlobDrawable1.draw(left, top - top1, right, bottom, canvas, paint, top, progress);
lineBlobDrawable2.draw(left, top - top2, right, bottom, canvas, paint, top, progress);
//}
if (i == 1 && rippleTransition) {
paint.setAlpha(255);
} else if (i == 1) {
paint.setAlpha((int) (255 * alpha));
} else {
paint.setAlpha(255);
}
if (i == 1 && rippleTransition) {
path.reset();
float cx = right - AndroidUtilities.dp(18);
float cy = top + (bottom - top) / 2;
float r = (right - left) * 1.1f * alpha;
path.addCircle(cx, cy, r, Path.Direction.CW);
canvas.save();
canvas.clipPath(path);
lineBlobDrawable.draw(left, top, right, bottom, canvas, paint, top, progress);
canvas.restore();
} else {
lineBlobDrawable.draw(left, top, right, bottom, canvas, paint, top, progress);
}
}
// if (Build.VERSION.SDK_INT > 21 && parentView != null && (parentView.isPressed() || pressedRemoveProgress != 0)) {
// if (parentView.isPressed()) {
// pressedRemoveProgress = 1f;
// }
// if (pressedProgress != 1f) {
// pressedProgress += 16f / 150f;
// if (pressedProgress > 1f) {
// pressedProgress = 1f;
// }
// } else if (!parentView.isPressed() && pressedRemoveProgress != 0) {
// pressedRemoveProgress -= 16f / 150f;
// if (pressedRemoveProgress < 0) {
// pressedRemoveProgress = 0;
// pressedProgress = 0;
// }
// }
// rect.set(left, top - AndroidUtilities.dp(20), right, bottom);
// canvas.saveLayerAlpha(rect, 255, Canvas.ALL_SAVE_FLAG);
// Theme.getColor(Theme.key_listSelector);
// selectedPaint.setColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (16 * pressedRemoveProgress)));
//
// float hotspotX = left + parentView.hotspotX;
// float rad = Math.max(right - hotspotX, hotspotX - left) * 0.8f;
// canvas.drawCircle(hotspotX, top + parentView.hotspotY, rad * 1.3f * CubicBezierInterpolator.DEFAULT.getInterpolation(pressedProgress), selectedPaint);
//
// lineBlobDrawable.path.toggleInverseFillType();
// canvas.drawPath(lineBlobDrawable.path, xRefP);
// lineBlobDrawable.path.toggleInverseFillType();
// canvas.restore();
// }
}
float pressedProgress;
float pressedRemoveProgress;
private void checkColors() {
for (int i = 0; i < states.length; i++) {
states[i].checkColor();
}
}
private void setState(int state, boolean animated) {
if (currentState != null && currentState.currentState == state) {
return;
}
if (VoIPService.getSharedInstance() == null && currentState == null) {
currentState = pausedState;
} else {
previousState = animated ? currentState : null;
currentState = states[state];
if (previousState != null) {
progressToState = 0;
} else {
progressToState = 1;
}
}
}
public void setAmplitude(float value) {
animateToAmplitude = value;
animateAmplitudeDiff = (animateToAmplitude - amplitude) / (250);
animateAmplitudeDiff2 = (animateToAmplitude - amplitude) / (120);
}
public void addParent(View parent) {
if (!parents.contains(parent)) {
parents.add(parent);
}
}
public void removeParent(View parent) {
parents.remove(parent);
if (parents.isEmpty()) {
pausedState = currentState;
currentState = null;
previousState = null;
}
}
public void updateState(boolean animated) {
VoIPService voIPService = VoIPService.getSharedInstance();
if (voIPService != null) {
int currentCallState = voIPService.getCallState();
if (!voIPService.isSwitchingStream() && (currentCallState == VoIPService.STATE_WAIT_INIT || currentCallState == VoIPService.STATE_WAIT_INIT_ACK || currentCallState == VoIPService.STATE_CREATING || currentCallState == VoIPService.STATE_RECONNECTING)) {
setState(FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_CONNECTING, animated);
} else {
if (voIPService.groupCall != null) {
TLRPC.TL_groupCallParticipant participant = voIPService.groupCall.participants.get(voIPService.getSelfId());
if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(voIPService.getChat()) || voIPService.groupCall.call.rtmp_stream) {
voIPService.setMicMute(true, false, false);
setState(FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTED_BY_ADMIN, animated);
} else {
boolean isMuted = voIPService.isMicMute();
setState(isMuted ? FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTE : FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_UNMUTE, animated);
}
} else {
boolean isMuted = voIPService.isMicMute();
setState(isMuted ? FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTE : FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_UNMUTE, animated);
}
}
}
}
public int getState() {
return currentState != null ? currentState.currentState : FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_UNMUTE;
}
public long getRippleFinishedDelay() {
if (pressedProgress != 0 && pressedProgress != 1) {
return (long) ((1f - pressedProgress) * 150);
}
return 0;
}
public static class WeavingState {
private float targetX = -1f;
private float targetY = -1f;
private float startX;
private float startY;
private float duration;
private float time;
public Shader shader;
private final Matrix matrix = new Matrix();
private final int currentState;
int color1;
int color2;
int color3;
public WeavingState(int state) {
currentState = state;
createGradients();
}
String greenKey1 = Theme.key_voipgroup_topPanelGreen1;
String greenKey2 = Theme.key_voipgroup_topPanelGreen2;
String blueKey1 = Theme.key_voipgroup_topPanelBlue1;
String blueKey2 = Theme.key_voipgroup_topPanelBlue2;
String mutedByAdmin = Theme.key_voipgroup_mutedByAdminGradient;
String mutedByAdmin2 = Theme.key_voipgroup_mutedByAdminGradient2;
String mutedByAdmin3 = Theme.key_voipgroup_mutedByAdminGradient3;
private void createGradients() {
if (currentState == MUTE_BUTTON_STATE_UNMUTE) {
shader = new RadialGradient(200, 200, 200, new int[]{color1 = Theme.getColor(greenKey1), color2 = Theme.getColor(greenKey2)}, null, Shader.TileMode.CLAMP);
} else if (currentState == MUTE_BUTTON_STATE_MUTE){
shader = new RadialGradient(200, 200, 200, new int[]{color1 = Theme.getColor(blueKey1), color2 = Theme.getColor(blueKey2)}, null, Shader.TileMode.CLAMP);
} else if (currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) {
shader = new RadialGradient(200, 200, 200, new int[]{color1 = Theme.getColor(mutedByAdmin), color3 = Theme.getColor(mutedByAdmin3), color2 = Theme.getColor(mutedByAdmin2)}, new float[]{0f, 0.6f, 1f}, Shader.TileMode.CLAMP);
}
}
public void update(int height, int width, long dt, float amplitude) {
if (currentState == MUTE_BUTTON_STATE_CONNECTING) {
return;
}
if (duration == 0 || time >= duration) {
duration = Utilities.random.nextInt(700) + 500;
time = 0;
if (targetX == -1f) {
if (currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) {
targetX = -0.3f + 0.05f * Utilities.random.nextInt(100) / 100f;
targetY = 0.7f + 0.05f * Utilities.random.nextInt(100) / 100f;
} else if (currentState == MUTE_BUTTON_STATE_UNMUTE) {
targetX = -0.3f + 0.2f * Utilities.random.nextInt(100) / 100f;
targetY = 0.7f + 0.3f * Utilities.random.nextInt(100) / 100f;
} else {
targetX = 1.1f + 0.2f * (Utilities.random.nextInt(100) / 100f);
targetY = 4f * Utilities.random.nextInt(100) / 100f;
}
}
startX = targetX;
startY = targetY;
if (currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) {
targetX = -0.3f + 0.05f * Utilities.random.nextInt(100) / 100f;
targetY = 0.7f + 0.05f * Utilities.random.nextInt(100) / 100f;
} else if (currentState == MUTE_BUTTON_STATE_UNMUTE) {
targetX = -0.3f + 0.2f * Utilities.random.nextInt(100) / 100f;
targetY = 0.7f + 0.3f * Utilities.random.nextInt(100) / 100f;
} else {
targetX = 1.1f + 0.2f * (Utilities.random.nextInt(100) / 100f);
targetY = 4f * Utilities.random.nextInt(100) / 100f;
}
}
time += dt * (0.5f + BlobDrawable.GRADIENT_SPEED_MIN) + dt * (BlobDrawable.GRADIENT_SPEED_MAX * 2) * amplitude;
if (time > duration) {
time = duration;
}
float interpolation = CubicBezierInterpolator.EASE_OUT.getInterpolation(time / duration);
float x = width * (startX + (targetX - startX) * interpolation) - 200;
float y = height * (startY + (targetY - startY) * interpolation) - 200;
float scale = width / 400.0f * ((currentState == MUTE_BUTTON_STATE_UNMUTE || currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN)? 3f : 1.5f);
matrix.reset();
matrix.postTranslate(x, y);
matrix.postScale(scale, scale, x + 200, y + 200);
shader.setLocalMatrix(matrix);
}
public void checkColor() {
if (currentState == MUTE_BUTTON_STATE_UNMUTE) {
if (color1 != Theme.getColor(greenKey1) || color2 != Theme.getColor(greenKey2)) {
createGradients();
}
} else if (currentState == MUTE_BUTTON_STATE_MUTE) {
if (color1 != Theme.getColor(blueKey1) || color2 != Theme.getColor(blueKey2)) {
createGradients();
}
} else if (currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) {
if (color1 != Theme.getColor(mutedByAdmin) || color2 != Theme.getColor(mutedByAdmin2)) {
createGradients();
}
}
}
public void setToPaint(Paint paint) {
if (currentState == MUTE_BUTTON_STATE_UNMUTE || currentState == MUTE_BUTTON_STATE_MUTE || currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) {
paint.setShader(shader);
} else {
paint.setShader(null);
paint.setColor(Theme.getColor(Theme.key_voipgroup_topPanelGray));
}
}
}
}