mirror of https://github.com/NekoX-Dev/NekoX.git
1790 lines
82 KiB
Java
1790 lines
82 KiB
Java
package org.telegram.ui.Components.voip;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.animation.ValueAnimator;
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Color;
|
|
import android.graphics.LinearGradient;
|
|
import android.graphics.Paint;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.PorterDuffColorFilter;
|
|
import android.graphics.RadialGradient;
|
|
import android.graphics.Rect;
|
|
import android.graphics.Shader;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.graphics.drawable.ColorDrawable;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.graphics.drawable.GradientDrawable;
|
|
import android.text.Layout;
|
|
import android.text.StaticLayout;
|
|
import android.text.TextPaint;
|
|
import android.util.TypedValue;
|
|
import android.view.Gravity;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.core.graphics.ColorUtils;
|
|
|
|
import org.telegram.messenger.AccountInstance;
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.BuildVars;
|
|
import org.telegram.messenger.ChatObject;
|
|
import org.telegram.messenger.ImageLoader;
|
|
import org.telegram.messenger.ImageLocation;
|
|
import org.telegram.messenger.ImageReceiver;
|
|
import org.telegram.messenger.LocaleController;
|
|
import org.telegram.messenger.MessageObject;
|
|
import org.telegram.messenger.MessagesController;
|
|
import org.telegram.messenger.R;
|
|
import org.telegram.messenger.UserConfig;
|
|
import org.telegram.messenger.UserObject;
|
|
import org.telegram.messenger.Utilities;
|
|
import org.telegram.messenger.voip.Instance;
|
|
import org.telegram.messenger.voip.VideoCapturerDevice;
|
|
import org.telegram.messenger.voip.VoIPService;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.ui.ActionBar.SimpleTextView;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
import org.telegram.ui.Components.AvatarDrawable;
|
|
import org.telegram.ui.Components.BlobDrawable;
|
|
import org.telegram.ui.Components.CrossOutDrawable;
|
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
|
import org.telegram.ui.Components.GroupCallFullscreenAdapter;
|
|
import org.telegram.ui.Components.LayoutHelper;
|
|
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
|
import org.telegram.ui.Components.RLottieImageView;
|
|
import org.telegram.ui.Components.RecyclerListView;
|
|
import org.telegram.ui.GroupCallActivity;
|
|
import org.webrtc.GlGenericDrawer;
|
|
import org.webrtc.RendererCommon;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
@SuppressLint("ViewConstructor")
|
|
public class GroupCallMiniTextureView extends FrameLayout implements GroupCallStatusIcon.Callback {
|
|
|
|
public final VoIPTextureView textureView;
|
|
|
|
public boolean showingInFullscreen;
|
|
public GroupCallGridCell primaryView;
|
|
public GroupCallFullscreenAdapter.GroupCallUserCell secondaryView;
|
|
public GroupCallGridCell tabletGridView;
|
|
public boolean animateToScrimView;
|
|
private boolean showingAsScrimView;
|
|
boolean isFullscreenMode;
|
|
public boolean animateToFullscreen;
|
|
private boolean updateNextLayoutAnimated;
|
|
|
|
boolean attached;
|
|
public ChatObject.VideoParticipant participant;
|
|
GroupCallRenderersContainer parentContainer;
|
|
|
|
ArrayList<GroupCallMiniTextureView> attachedRenderers;
|
|
|
|
Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
LinearGradient gradientShader;
|
|
boolean animateEnter;
|
|
ChatObject.Call call;
|
|
GroupCallActivity activity;
|
|
|
|
boolean useSpanSize;
|
|
float spanCount;
|
|
int gridItemsCount;
|
|
|
|
FrameLayout infoContainer;
|
|
|
|
int currentAccount;
|
|
private final SimpleTextView nameView;
|
|
private int lastSize;
|
|
|
|
private TextView stopSharingTextView;
|
|
|
|
public boolean forceDetached;
|
|
|
|
private boolean invalidateFromChild;
|
|
private boolean checkScale;
|
|
float progressToSpeaking;
|
|
|
|
Paint speakingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
private final RLottieImageView micIconView;
|
|
private final ImageView screencastIcon;
|
|
|
|
public boolean hasVideo;
|
|
public float progressToNoVideoStub = 1f;
|
|
private NoVideoStubLayout noVideoStubLayout;
|
|
ValueAnimator noVideoStubAnimator;
|
|
private boolean lastLandscapeMode;
|
|
|
|
float pinchScale;
|
|
float pinchCenterX;
|
|
float pinchCenterY;
|
|
float pinchTranslationX;
|
|
float pinchTranslationY;
|
|
boolean inPinchToZoom;
|
|
|
|
private float progressToBackground;
|
|
ImageReceiver imageReceiver = new ImageReceiver();
|
|
|
|
ArrayList<Runnable> onFirstFrameRunnables = new ArrayList<>();
|
|
|
|
private GroupCallStatusIcon statusIcon;
|
|
private boolean swipeToBack;
|
|
private float swipeToBackDy;
|
|
|
|
Bitmap thumb;
|
|
Paint thumbPaint;
|
|
private boolean videoIsPaused;
|
|
private float videoIsPausedProgress;
|
|
private CrossOutDrawable pausedVideoDrawable;
|
|
private Drawable castingScreenDrawable;
|
|
float overlayIconAlpha;
|
|
|
|
ImageView blurredFlippingStub;
|
|
|
|
public boolean drawFirst;
|
|
|
|
public GroupCallMiniTextureView(GroupCallRenderersContainer parentContainer, ArrayList<GroupCallMiniTextureView> attachedRenderers, ChatObject.Call call, GroupCallActivity activity) {
|
|
super(parentContainer.getContext());
|
|
this.call = call;
|
|
this.currentAccount = activity.getCurrentAccount();
|
|
pausedVideoDrawable = new CrossOutDrawable(parentContainer.getContext(), R.drawable.calls_video, null);
|
|
pausedVideoDrawable.setCrossOut(true, false);
|
|
pausedVideoDrawable.setOffsets(-AndroidUtilities.dp(4), AndroidUtilities.dp(6), AndroidUtilities.dp(6));
|
|
pausedVideoDrawable.setStrokeWidth(AndroidUtilities.dpf2(3.4f));
|
|
|
|
castingScreenDrawable = parentContainer.getContext().getResources().getDrawable(R.drawable.screencast_big).mutate();
|
|
|
|
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
textPaint.setTextSize(AndroidUtilities.dp(13));
|
|
textPaint.setColor(Color.WHITE);
|
|
|
|
TextPaint textPaint2 = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
|
textPaint2.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
textPaint2.setTextSize(AndroidUtilities.dp(15));
|
|
textPaint2.setColor(Color.WHITE);
|
|
|
|
String videoOnPauseString = LocaleController.getString("VoipVideoOnPause", R.string.VoipVideoOnPause);
|
|
StaticLayout staticLayout = new StaticLayout(LocaleController.getString("VoipVideoScreenSharingTwoLines", R.string.VoipVideoScreenSharingTwoLines), textPaint, AndroidUtilities.dp(400), Layout.Alignment.ALIGN_CENTER, 1.0f, 0, false);
|
|
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(call.chatId);
|
|
String text = LocaleController.formatPluralString("Participants", MessagesController.getInstance(currentAccount).groipCallVideoMaxParticipants);
|
|
StaticLayout noVideoLayout = new StaticLayout(LocaleController.formatString("VoipVideoNotAvailable", R.string.VoipVideoNotAvailable, text), textPaint, AndroidUtilities.dp(400), Layout.Alignment.ALIGN_CENTER, 1.0f, 0, false);
|
|
String sharingScreenString = LocaleController.getString("VoipVideoScreenSharing", R.string.VoipVideoScreenSharing);
|
|
|
|
float textW = textPaint.measureText(videoOnPauseString);
|
|
float textW3 = textPaint2.measureText(sharingScreenString);
|
|
|
|
this.textureView = new VoIPTextureView(parentContainer.getContext(), false, false, true, true) {
|
|
|
|
float overlayIconAlphaFrom;
|
|
|
|
@Override
|
|
public void animateToLayout() {
|
|
super.animateToLayout();
|
|
overlayIconAlphaFrom = overlayIconAlpha;
|
|
}
|
|
|
|
@Override
|
|
protected void updateRendererSize() {
|
|
super.updateRendererSize();
|
|
if (blurredFlippingStub != null && blurredFlippingStub.getParent() != null) {
|
|
blurredFlippingStub.getLayoutParams().width = textureView.renderer.getMeasuredWidth();
|
|
blurredFlippingStub.getLayoutParams().height = textureView.renderer.getMeasuredHeight();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void dispatchDraw(Canvas canvas) {
|
|
if (!renderer.isFirstFrameRendered() || (renderer.getAlpha() != 1f && blurRenderer.getAlpha() != 1f) || videoIsPaused) {
|
|
if (progressToBackground != 1f) {
|
|
progressToBackground += 16f / 150f;
|
|
if (progressToBackground > 1f) {
|
|
progressToBackground = 1f;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
}
|
|
if (thumb != null) {
|
|
canvas.save();
|
|
canvas.scale(currentThumbScale, currentThumbScale, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f);
|
|
if (thumbPaint == null) {
|
|
thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
thumbPaint.setFilterBitmap(true);
|
|
}
|
|
canvas.drawBitmap(thumb, (getMeasuredWidth() - thumb.getWidth()) / 2f, (getMeasuredHeight() - thumb.getHeight()) / 2f, thumbPaint);
|
|
canvas.restore();
|
|
} else {
|
|
imageReceiver.setImageCoords(currentClipHorizontal, currentClipVertical, getMeasuredWidth() - currentClipHorizontal * 2, getMeasuredHeight() - currentClipVertical * 2);
|
|
imageReceiver.setAlpha(progressToBackground);
|
|
imageReceiver.draw(canvas);
|
|
}
|
|
if (participant == call.videoNotAvailableParticipant) {
|
|
if (showingInFullscreen || !parentContainer.inFullscreenMode) {
|
|
float iconSize = AndroidUtilities.dp(48);
|
|
float x = (getMeasuredWidth() - iconSize) / 2f;
|
|
float y = getMeasuredHeight() / 2 - iconSize;
|
|
textPaint.setAlpha(255);
|
|
|
|
canvas.save();
|
|
canvas.translate(x - AndroidUtilities.dp(400) / 2f + iconSize / 2f, y + iconSize + AndroidUtilities.dp(10));
|
|
noVideoLayout.draw(canvas);
|
|
canvas.restore();
|
|
}
|
|
if (stopSharingTextView.getVisibility() != INVISIBLE) {
|
|
stopSharingTextView.setVisibility(INVISIBLE);
|
|
}
|
|
} else if (participant.presentation && participant.participant.self) {
|
|
if (stopSharingTextView.getVisibility() != VISIBLE) {
|
|
stopSharingTextView.setVisibility(VISIBLE);
|
|
stopSharingTextView.setScaleX(1.0f);
|
|
stopSharingTextView.setScaleY(1.0f);
|
|
}
|
|
float progressToFullscreen = drawFirst ? 0 : parentContainer.progressToFullscreenMode;
|
|
int size = AndroidUtilities.dp(33);
|
|
if (animateToFullscreen || showingInFullscreen) {
|
|
size += (AndroidUtilities.dp(10) + AndroidUtilities.dp(39) * parentContainer.progressToFullscreenMode);
|
|
} else {
|
|
size += AndroidUtilities.dp(10) * (1.0f - parentContainer.progressToFullscreenMode);
|
|
}
|
|
|
|
int x = (getMeasuredWidth() - size) / 2;
|
|
float smallProgress;
|
|
float scrimProgress = (showingAsScrimView || animateToScrimView ? parentContainer.progressToScrimView : 0);
|
|
if (showingInFullscreen) {
|
|
smallProgress = progressToFullscreen;
|
|
} else {
|
|
smallProgress = animateToFullscreen ? parentContainer.progressToFullscreenMode : scrimProgress;
|
|
}
|
|
int y = (int) ((getMeasuredHeight() - size) / 2 - AndroidUtilities.dp(11) - (AndroidUtilities.dp(17) + AndroidUtilities.dp(74) * parentContainer.progressToFullscreenMode) * smallProgress);
|
|
castingScreenDrawable.setBounds(x, y, x + size, y + size);
|
|
castingScreenDrawable.draw(canvas);
|
|
|
|
if (parentContainer.progressToFullscreenMode > 0 || scrimProgress > 0) {
|
|
float alpha = Math.max(parentContainer.progressToFullscreenMode, scrimProgress) * smallProgress;
|
|
textPaint2.setAlpha((int) (255 * alpha));
|
|
if (animateToFullscreen || showingInFullscreen) {
|
|
stopSharingTextView.setAlpha(alpha * (1.0f - scrimProgress));
|
|
} else {
|
|
stopSharingTextView.setAlpha(0.0f);
|
|
}
|
|
canvas.drawText(sharingScreenString, x - textW3 / 2f + size / 2f, y + size + AndroidUtilities.dp(32), textPaint2);
|
|
} else {
|
|
stopSharingTextView.setAlpha(0.0f);
|
|
}
|
|
stopSharingTextView.setTranslationY(y + size + AndroidUtilities.dp(72) + swipeToBackDy - currentClipVertical);
|
|
stopSharingTextView.setTranslationX((getMeasuredWidth() - stopSharingTextView.getMeasuredWidth()) / 2 - currentClipHorizontal);
|
|
if (parentContainer.progressToFullscreenMode < 1 && scrimProgress < 1) {
|
|
textPaint.setAlpha((int) (255 * (1.0 - Math.max(parentContainer.progressToFullscreenMode, scrimProgress))));
|
|
canvas.save();
|
|
canvas.translate(x - AndroidUtilities.dp(400) / 2f + size / 2f, y + size + AndroidUtilities.dp(10));
|
|
staticLayout.draw(canvas);
|
|
canvas.restore();
|
|
}
|
|
} else {
|
|
if (stopSharingTextView.getVisibility() != INVISIBLE) {
|
|
stopSharingTextView.setVisibility(INVISIBLE);
|
|
}
|
|
activity.cellFlickerDrawable.draw(canvas, GroupCallMiniTextureView.this);
|
|
}
|
|
invalidate();
|
|
}
|
|
|
|
if (blurredFlippingStub != null && blurredFlippingStub.getParent() != null) {
|
|
blurredFlippingStub.setScaleX(textureView.renderer.getScaleX());
|
|
blurredFlippingStub.setScaleY(textureView.renderer.getScaleY());
|
|
}
|
|
super.dispatchDraw(canvas);
|
|
|
|
float y = getMeasuredHeight() - currentClipVertical - AndroidUtilities.dp(80);
|
|
|
|
if (participant != call.videoNotAvailableParticipant) {
|
|
canvas.save();
|
|
if ((showingInFullscreen || animateToFullscreen) && !GroupCallActivity.isLandscapeMode && !GroupCallActivity.isTabletMode) {
|
|
y -= AndroidUtilities.dp(90) * parentContainer.progressToFullscreenMode * (1f - parentContainer.progressToHideUi);
|
|
}
|
|
canvas.translate(0, y);
|
|
canvas.drawPaint(gradientPaint);
|
|
canvas.restore();
|
|
}
|
|
|
|
|
|
if (videoIsPaused || videoIsPausedProgress != 0) {
|
|
if (videoIsPaused && videoIsPausedProgress != 1f) {
|
|
videoIsPausedProgress += 16 / 250f;
|
|
if (videoIsPausedProgress > 1f) {
|
|
videoIsPausedProgress = 1f;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
} else if (!videoIsPaused && videoIsPausedProgress != 0f) {
|
|
videoIsPausedProgress -= 16 / 250f;
|
|
if (videoIsPausedProgress < 0f) {
|
|
videoIsPausedProgress = 0f;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
float a = videoIsPausedProgress;
|
|
a *= (isInAnimation() ? (overlayIconAlphaFrom * (1f - animationProgress) + overlayIconAlpha * animationProgress) : overlayIconAlpha);
|
|
|
|
if (a > 0) {
|
|
float iconSize = AndroidUtilities.dp(48);
|
|
float x = (getMeasuredWidth() - iconSize) / 2f;
|
|
y = (getMeasuredHeight() - iconSize) / 2f;
|
|
if (participant == call.videoNotAvailableParticipant) {
|
|
y -= iconSize / 2.5f;
|
|
}
|
|
AndroidUtilities.rectTmp.set((int) x, (int) y, (int) (x + iconSize), (int) (y + iconSize));
|
|
if (a != 1) {
|
|
canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * a), Canvas.ALL_SAVE_FLAG);
|
|
} else {
|
|
canvas.save();
|
|
}
|
|
pausedVideoDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom);
|
|
pausedVideoDrawable.draw(canvas);
|
|
canvas.restore();
|
|
|
|
a *= parentContainer.progressToFullscreenMode;
|
|
if (a > 0 && participant != call.videoNotAvailableParticipant) {
|
|
textPaint.setAlpha((int) (255 * a));
|
|
canvas.drawText(videoOnPauseString, x - textW / 2f + iconSize / 2f, y + iconSize + AndroidUtilities.dp(16), textPaint);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
|
if (inPinchToZoom && child == textureView.renderer) {
|
|
canvas.save();
|
|
canvas.scale(pinchScale, pinchScale, pinchCenterX, pinchCenterY);
|
|
canvas.translate(pinchTranslationX, pinchTranslationY);
|
|
boolean b = super.drawChild(canvas, child, drawingTime);
|
|
canvas.restore();
|
|
return b;
|
|
}
|
|
return super.drawChild(canvas, child, drawingTime);
|
|
}
|
|
|
|
@Override
|
|
public void invalidate() {
|
|
super.invalidate();
|
|
invalidateFromChild = true;
|
|
GroupCallMiniTextureView.this.invalidate();
|
|
invalidateFromChild = false;
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
if (attached && checkScale && renderer.rotatedFrameHeight != 0 && renderer.rotatedFrameWidth != 0) {
|
|
if (showingAsScrimView) {
|
|
textureView.scaleType = SCALE_TYPE_FIT;
|
|
} else if (showingInFullscreen) {
|
|
textureView.scaleType = SCALE_TYPE_FIT;
|
|
} else if (parentContainer.inFullscreenMode && !showingInFullscreen) {
|
|
textureView.scaleType = SCALE_TYPE_FILL;
|
|
} else if (!parentContainer.inFullscreenMode) {
|
|
textureView.scaleType = participant.presentation ? SCALE_TYPE_FIT : SCALE_TYPE_ADAPTIVE;
|
|
} else {
|
|
textureView.scaleType = SCALE_TYPE_FIT;
|
|
}
|
|
checkScale = false;
|
|
}
|
|
super.onLayout(changed, left, top, right, bottom);
|
|
|
|
if (renderer.rotatedFrameHeight != 0 && renderer.rotatedFrameWidth != 0 && participant != null) {
|
|
participant.setAspectRatio(renderer.rotatedFrameWidth / (float) renderer.rotatedFrameHeight, call);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void requestLayout() {
|
|
GroupCallMiniTextureView.this.requestLayout();
|
|
super.requestLayout();
|
|
}
|
|
|
|
@Override
|
|
protected void onFirstFrameRendered() {
|
|
invalidate();
|
|
if (!videoIsPaused) {
|
|
if (renderer.getAlpha() != 1f) {
|
|
renderer.animate().setDuration(300).alpha(1f);
|
|
}
|
|
}
|
|
|
|
if (blurRenderer != null && blurRenderer.getAlpha() != 1f) {
|
|
blurRenderer.animate().setDuration(300).alpha(1f);
|
|
}
|
|
|
|
if (blurredFlippingStub != null && blurredFlippingStub.getParent() != null) {
|
|
if (blurredFlippingStub.getAlpha() == 1f) {
|
|
blurredFlippingStub.animate().alpha(0f).setDuration(300).setListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
if (blurredFlippingStub.getParent() != null) {
|
|
textureView.removeView(blurredFlippingStub);
|
|
}
|
|
}
|
|
}).start();
|
|
} else {
|
|
if (blurredFlippingStub.getParent() != null) {
|
|
textureView.removeView(blurredFlippingStub);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
};
|
|
textureView.renderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
|
|
this.parentContainer = parentContainer;
|
|
this.attachedRenderers = attachedRenderers;
|
|
this.activity = activity;
|
|
|
|
textureView.renderer.init(VideoCapturerDevice.getEglBase().getEglBaseContext(), new RendererCommon.RendererEvents() {
|
|
@Override
|
|
public void onFirstFrameRendered() {
|
|
for (int i = 0; i < onFirstFrameRunnables.size(); i++) {
|
|
AndroidUtilities.cancelRunOnUIThread(onFirstFrameRunnables.get(i));
|
|
onFirstFrameRunnables.get(i).run();
|
|
}
|
|
onFirstFrameRunnables.clear();
|
|
}
|
|
|
|
@Override
|
|
public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) {
|
|
|
|
}
|
|
});
|
|
|
|
textureView.attachBackgroundRenderer();
|
|
|
|
setClipChildren(false);
|
|
textureView.renderer.setAlpha(0f);
|
|
addView(textureView);
|
|
|
|
noVideoStubLayout = new NoVideoStubLayout(getContext());
|
|
addView(noVideoStubLayout);
|
|
|
|
nameView = new SimpleTextView(parentContainer.getContext());
|
|
nameView.setTextSize(13);
|
|
nameView.setTextColor(ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.9f)));
|
|
nameView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
nameView.setFullTextMaxLines(1);
|
|
nameView.setBuildFullLayout(true);
|
|
infoContainer = new FrameLayout(parentContainer.getContext());
|
|
infoContainer.addView(nameView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 32, 0, 8, 0));
|
|
addView(infoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32));
|
|
speakingPaint.setStyle(Paint.Style.STROKE);
|
|
speakingPaint.setStrokeWidth(AndroidUtilities.dp(2));
|
|
speakingPaint.setColor(Theme.getColor(Theme.key_voipgroup_speakingText));
|
|
infoContainer.setClipChildren(false);
|
|
|
|
micIconView = new RLottieImageView(parentContainer.getContext());
|
|
addView(micIconView, LayoutHelper.createFrame(24, 24, 0, 4, 6, 4, 0));
|
|
|
|
screencastIcon = new ImageView(parentContainer.getContext());
|
|
addView(screencastIcon, LayoutHelper.createFrame(24, 24, 0, 4, 6, 4, 0));
|
|
screencastIcon.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4));
|
|
screencastIcon.setImageDrawable(ContextCompat.getDrawable(parentContainer.getContext(), R.drawable.voicechat_screencast));
|
|
screencastIcon.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY));
|
|
|
|
final Drawable rippleDrawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(19), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 100));
|
|
stopSharingTextView = new TextView(parentContainer.getContext()) {
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
if (Math.abs(stopSharingTextView.getAlpha() - 1.0f) > 0.001f) {
|
|
return false;
|
|
}
|
|
return super.onTouchEvent(event);
|
|
}
|
|
};
|
|
stopSharingTextView.setText(LocaleController.getString("VoipVideoScreenStopSharing", R.string.VoipVideoScreenStopSharing));
|
|
stopSharingTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
|
stopSharingTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
|
stopSharingTextView.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0);
|
|
stopSharingTextView.setTextColor(0xffffffff);
|
|
stopSharingTextView.setBackground(rippleDrawable);
|
|
stopSharingTextView.setGravity(Gravity.CENTER);
|
|
stopSharingTextView.setOnClickListener(v -> {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().stopScreenCapture();
|
|
}
|
|
stopSharingTextView.animate().alpha(0.0f).scaleX(0.0f).scaleY(0.0f).setDuration(180).start();
|
|
});
|
|
addView(stopSharingTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 38, Gravity.LEFT | Gravity.TOP));
|
|
}
|
|
|
|
private Rect rect = new Rect();
|
|
|
|
public boolean isInsideStopScreenButton(float x, float y) {
|
|
stopSharingTextView.getHitRect(rect);
|
|
return rect.contains((int) x, (int) y);
|
|
}
|
|
|
|
@Override
|
|
protected void dispatchDraw(Canvas canvas) {
|
|
if (attached) {
|
|
float y = textureView.getY() + textureView.getMeasuredHeight() - textureView.currentClipVertical - infoContainer.getMeasuredHeight();
|
|
y += swipeToBackDy;
|
|
if (showingAsScrimView || animateToScrimView) {
|
|
infoContainer.setAlpha(1f - parentContainer.progressToScrimView);
|
|
micIconView.setAlpha(1f - parentContainer.progressToScrimView);
|
|
} else if (showingInFullscreen || animateToFullscreen) {
|
|
if (!GroupCallActivity.isLandscapeMode && !GroupCallActivity.isTabletMode) {
|
|
y -= AndroidUtilities.dp(90) * parentContainer.progressToFullscreenMode * (1f - parentContainer.progressToHideUi);
|
|
}
|
|
infoContainer.setAlpha(1f);
|
|
micIconView.setAlpha(1f);
|
|
} else if (secondaryView != null) {
|
|
infoContainer.setAlpha(1f - parentContainer.progressToFullscreenMode);
|
|
micIconView.setAlpha(1f - parentContainer.progressToFullscreenMode);
|
|
} else {
|
|
infoContainer.setAlpha(1f);
|
|
micIconView.setAlpha(1f);
|
|
}
|
|
|
|
if (showingInFullscreen || animateToFullscreen) {
|
|
nameView.setFullAlpha(parentContainer.progressToFullscreenMode);
|
|
} else {
|
|
nameView.setFullAlpha(0f);
|
|
}
|
|
micIconView.setTranslationX(infoContainer.getX());
|
|
micIconView.setTranslationY(y - AndroidUtilities.dp(2));
|
|
|
|
if (screencastIcon.getVisibility() == View.VISIBLE) {
|
|
screencastIcon.setTranslationX(textureView.getMeasuredWidth() - 2 * textureView.currentClipHorizontal - AndroidUtilities.dp(32));
|
|
screencastIcon.setTranslationY(y - AndroidUtilities.dp(2));
|
|
screencastIcon.setAlpha(Math.min(1f - parentContainer.progressToFullscreenMode, 1f - parentContainer.progressToScrimView));
|
|
}
|
|
infoContainer.setTranslationY(y);
|
|
infoContainer.setTranslationX(drawFirst ? 0 : AndroidUtilities.dp(6) * parentContainer.progressToFullscreenMode);
|
|
}
|
|
super.dispatchDraw(canvas);
|
|
|
|
if (attached) {
|
|
if (statusIcon != null) {
|
|
if (statusIcon.isSpeaking && progressToSpeaking != 1f) {
|
|
progressToSpeaking += 16f / 300f;
|
|
if (progressToSpeaking > 1f) {
|
|
progressToSpeaking = 1f;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
} else if (!statusIcon.isSpeaking && progressToSpeaking != 0) {
|
|
progressToSpeaking -= 16f / 300f;
|
|
if (progressToSpeaking < 0) {
|
|
progressToSpeaking = 0;
|
|
} else {
|
|
invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
float selectionProgress = progressToSpeaking * (1f - parentContainer.progressToFullscreenMode) * (1f - parentContainer.progressToScrimView);
|
|
if (progressToSpeaking > 0) {
|
|
speakingPaint.setAlpha((int) (255 * selectionProgress));
|
|
|
|
float scale = 0.9f + 0.1f * Math.max(0, 1f - Math.abs(swipeToBackDy) / AndroidUtilities.dp(300));
|
|
canvas.save();
|
|
AndroidUtilities.rectTmp.set(textureView.getX() + textureView.currentClipHorizontal, textureView.getY() + textureView.currentClipVertical, textureView.getX() + textureView.getMeasuredWidth() - textureView.currentClipHorizontal, textureView.getY() + textureView.getMeasuredHeight() - textureView.currentClipVertical);
|
|
canvas.scale(scale, scale, AndroidUtilities.rectTmp.centerX(), AndroidUtilities.rectTmp.centerY());
|
|
canvas.translate(0, swipeToBackDy);
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, textureView.roundRadius, textureView.roundRadius, speakingPaint);
|
|
canvas.restore();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void getRenderBufferBitmap(GlGenericDrawer.TextureCallback callback) {
|
|
textureView.renderer.getRenderBufferBitmap(callback);
|
|
}
|
|
|
|
@Override
|
|
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
|
if (swipeToBack && (child == textureView || child == noVideoStubLayout)) {
|
|
float scale = 0.9f + 0.1f * Math.max(0, 1f - Math.abs(swipeToBackDy) / AndroidUtilities.dp(300));
|
|
canvas.save();
|
|
canvas.scale(scale, scale, child.getX() + child.getMeasuredWidth() / 2f, child.getY() + child.getMeasuredHeight() / 2f);
|
|
canvas.translate(0, swipeToBackDy);
|
|
boolean b = super.drawChild(canvas, child, drawingTime);
|
|
canvas.restore();
|
|
return b;
|
|
}
|
|
return super.drawChild(canvas, child, drawingTime);
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
FrameLayout.LayoutParams layoutParams = (LayoutParams) infoContainer.getLayoutParams();
|
|
int lastLeft = layoutParams.leftMargin;
|
|
float nameScale = 1f;
|
|
|
|
if (lastLandscapeMode != GroupCallActivity.isLandscapeMode) {
|
|
checkScale = true;
|
|
lastLandscapeMode = GroupCallActivity.isLandscapeMode;
|
|
}
|
|
layoutParams.leftMargin = layoutParams.rightMargin = AndroidUtilities.dp(2);
|
|
|
|
if (updateNextLayoutAnimated) {
|
|
nameView.animate().scaleX(nameScale).scaleY(nameScale).start();
|
|
micIconView.animate().scaleX(nameScale).scaleY(nameScale).start();
|
|
|
|
} else {
|
|
nameView.animate().cancel();
|
|
nameView.setScaleX(nameScale);
|
|
nameView.setScaleY(nameScale);
|
|
|
|
micIconView.animate().cancel();
|
|
micIconView.setScaleX(nameScale);
|
|
micIconView.setScaleY(nameScale);
|
|
infoContainer.animate().cancel();
|
|
}
|
|
|
|
updateNextLayoutAnimated = false;
|
|
|
|
if (showingInFullscreen) {
|
|
updateSize(0);
|
|
overlayIconAlpha = 1f;
|
|
if (GroupCallActivity.isTabletMode) {
|
|
int w = MeasureSpec.getSize(widthMeasureSpec);
|
|
w -= AndroidUtilities.dp(GroupCallActivity.TABLET_LIST_SIZE + 8);
|
|
int h = MeasureSpec.getSize(heightMeasureSpec);
|
|
h -= AndroidUtilities.dp(4);
|
|
super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
|
|
} else if (!GroupCallActivity.isLandscapeMode) {
|
|
int h = MeasureSpec.getSize(heightMeasureSpec);
|
|
h -= AndroidUtilities.dp(92);
|
|
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
|
|
} else {
|
|
int w = MeasureSpec.getSize(widthMeasureSpec);
|
|
w -= AndroidUtilities.dp(92);
|
|
super.onMeasure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY));
|
|
}
|
|
} else if (showingAsScrimView) {
|
|
overlayIconAlpha = 1f;
|
|
int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) - AndroidUtilities.dp(14) * 2;
|
|
super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(size + getPaddingBottom(), MeasureSpec.EXACTLY));
|
|
} else if (useSpanSize) {
|
|
overlayIconAlpha = 1f;
|
|
int spanCountTotal;
|
|
if (GroupCallActivity.isTabletMode && tabletGridView != null) {
|
|
spanCountTotal = 6;
|
|
} else {
|
|
spanCountTotal = GroupCallActivity.isLandscapeMode ? 6 : 2;
|
|
}
|
|
float listSize;
|
|
if (tabletGridView != null) {
|
|
listSize = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(GroupCallActivity.TABLET_LIST_SIZE + 16 + 8);
|
|
} else if (GroupCallActivity.isTabletMode) {
|
|
listSize = AndroidUtilities.dp(GroupCallActivity.TABLET_LIST_SIZE);
|
|
} else {
|
|
listSize = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(14) * 2 + (GroupCallActivity.isLandscapeMode ? -AndroidUtilities.dp(90) : 0);
|
|
}
|
|
float w = listSize * (spanCount / (float) spanCountTotal);
|
|
float h;
|
|
if (tabletGridView != null) {
|
|
h = tabletGridView.getItemHeight() - AndroidUtilities.dp(4);
|
|
w -= AndroidUtilities.dp(4);
|
|
} else {
|
|
if (GroupCallActivity.isTabletMode) {
|
|
h = listSize / 2f;
|
|
} else {
|
|
h = listSize / (float) (GroupCallActivity.isLandscapeMode ? 3 : 2);
|
|
}
|
|
w -= AndroidUtilities.dp(2);
|
|
}
|
|
float layoutContainerW = w;
|
|
layoutParams = (LayoutParams) infoContainer.getLayoutParams();
|
|
if (screencastIcon.getVisibility() == View.VISIBLE) {
|
|
layoutContainerW -= AndroidUtilities.dp(28);
|
|
}
|
|
updateSize((int) layoutContainerW);
|
|
layoutParams.width = (int) (layoutContainerW - layoutParams.leftMargin * 2);
|
|
|
|
super.onMeasure(MeasureSpec.makeMeasureSpec((int) w, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) h, MeasureSpec.EXACTLY));
|
|
} else {
|
|
overlayIconAlpha = 0f;
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
}
|
|
int size = MeasureSpec.getSize(heightMeasureSpec) + (MeasureSpec.getSize(widthMeasureSpec) << 16);
|
|
if (lastSize != size) {
|
|
lastSize = size;
|
|
gradientShader = new LinearGradient(0, 0, 0, AndroidUtilities.dp(120), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.BLACK, 120), Shader.TileMode.CLAMP);
|
|
gradientPaint.setShader(gradientShader);
|
|
}
|
|
|
|
nameView.setPivotX(0);
|
|
nameView.setPivotY(nameView.getMeasuredHeight() / 2f);
|
|
}
|
|
|
|
public static GroupCallMiniTextureView getOrCreate(ArrayList<GroupCallMiniTextureView> attachedRenderers, GroupCallRenderersContainer renderersContainer, GroupCallGridCell primaryView, GroupCallFullscreenAdapter.GroupCallUserCell secondaryView, GroupCallGridCell tabletGridView, ChatObject.VideoParticipant participant, ChatObject.Call call, GroupCallActivity activity) {
|
|
GroupCallMiniTextureView renderer = null;
|
|
for (int i = 0; i < attachedRenderers.size(); i++) {
|
|
if (participant.equals(attachedRenderers.get(i).participant)) {
|
|
renderer = attachedRenderers.get(i);
|
|
break;
|
|
}
|
|
}
|
|
if (renderer == null) {
|
|
renderer = new GroupCallMiniTextureView(renderersContainer, attachedRenderers, call, activity);
|
|
}
|
|
if (primaryView != null) {
|
|
renderer.setPrimaryView(primaryView);
|
|
}
|
|
if (secondaryView != null) {
|
|
renderer.setSecondaryView(secondaryView);
|
|
}
|
|
if (tabletGridView != null) {
|
|
renderer.setTabletGridView(tabletGridView);
|
|
}
|
|
return renderer;
|
|
}
|
|
|
|
public void setTabletGridView(GroupCallGridCell tabletGridView) {
|
|
if (this.tabletGridView != tabletGridView) {
|
|
this.tabletGridView = tabletGridView;
|
|
updateAttachState(true);
|
|
}
|
|
}
|
|
|
|
public void setPrimaryView(GroupCallGridCell primaryView) {
|
|
if (this.primaryView != primaryView) {
|
|
this.primaryView = primaryView;
|
|
checkScale = true;
|
|
updateAttachState(true);
|
|
}
|
|
}
|
|
|
|
public void setSecondaryView(GroupCallFullscreenAdapter.GroupCallUserCell secondaryView) {
|
|
if (this.secondaryView != secondaryView) {
|
|
this.secondaryView = secondaryView;
|
|
checkScale = true;
|
|
updateAttachState(true);
|
|
}
|
|
}
|
|
|
|
public void setShowingAsScrimView(boolean showing, boolean animated) {
|
|
this.showingAsScrimView = showing;
|
|
updateAttachState(animated);
|
|
}
|
|
|
|
public void setShowingInFullscreen(boolean showing, boolean animated) {
|
|
if (this.showingInFullscreen != showing) {
|
|
this.showingInFullscreen = showing;
|
|
checkScale = true;
|
|
updateAttachState(animated);
|
|
}
|
|
}
|
|
|
|
public void setFullscreenMode(boolean fullscreenMode, boolean animated) {
|
|
if (isFullscreenMode != fullscreenMode) {
|
|
isFullscreenMode = fullscreenMode;
|
|
updateAttachState((primaryView != null || tabletGridView != null) && animated);
|
|
}
|
|
}
|
|
|
|
public void updateAttachState(boolean animated) {
|
|
if (forceDetached) {
|
|
return;
|
|
}
|
|
if (participant == null && (primaryView != null || secondaryView != null || tabletGridView != null)) {
|
|
if (primaryView != null) {
|
|
participant = primaryView.getParticipant();
|
|
} else if (tabletGridView != null) {
|
|
participant = tabletGridView.getParticipant();
|
|
} else {
|
|
participant = secondaryView.getVideoParticipant();
|
|
}
|
|
}
|
|
boolean forceRequestLayout = false;
|
|
if (attached && !showingInFullscreen) {
|
|
boolean needDetach = VoIPService.getSharedInstance() == null;
|
|
if (GroupCallActivity.paused || participant == null || (secondaryView == null && (!ChatObject.Call.videoIsActive(participant.participant, participant.presentation, call) || !call.canStreamVideo && participant != call.videoNotAvailableParticipant))) {
|
|
needDetach = true;
|
|
}
|
|
if (needDetach || (primaryView == null && secondaryView == null && tabletGridView == null) && !showingAsScrimView && !animateToScrimView) {
|
|
attached = false;
|
|
|
|
saveThumb();
|
|
|
|
if (textureView.currentAnimation == null && needDetach) {
|
|
GroupCallMiniTextureView viewToRemove = this;
|
|
parentContainer.detach(viewToRemove);
|
|
animate().scaleX(0.5f).scaleY(0.5f).alpha(0).setListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
viewToRemove.setScaleX(1f);
|
|
viewToRemove.setScaleY(1f);
|
|
viewToRemove.setAlpha(1f);
|
|
parentContainer.removeView(viewToRemove);
|
|
release();
|
|
}
|
|
}).setDuration(150).start();
|
|
} else {
|
|
if (parentContainer.inLayout) {
|
|
View viewToRemove = this;
|
|
AndroidUtilities.runOnUIThread(() -> parentContainer.removeView(viewToRemove));
|
|
} else {
|
|
parentContainer.removeView(this);
|
|
}
|
|
parentContainer.detach(this);
|
|
release();
|
|
}
|
|
|
|
if (participant.participant.self) {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().setLocalSink(null, participant.presentation);
|
|
}
|
|
} else {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().removeRemoteSink(participant.participant, participant.presentation);
|
|
}
|
|
}
|
|
|
|
invalidate();
|
|
|
|
if (noVideoStubAnimator != null) {
|
|
noVideoStubAnimator.removeAllListeners();
|
|
noVideoStubAnimator.cancel();
|
|
}
|
|
}
|
|
} else if (!attached) {
|
|
if (VoIPService.getSharedInstance() == null) {
|
|
return;
|
|
}
|
|
if (primaryView != null || secondaryView != null || tabletGridView != null || showingInFullscreen) {
|
|
if (primaryView != null) {
|
|
participant = primaryView.getParticipant();
|
|
} else if (secondaryView != null) {
|
|
participant = secondaryView.getVideoParticipant();
|
|
} else if (tabletGridView != null) {
|
|
participant = tabletGridView.getParticipant();
|
|
}
|
|
|
|
boolean videoActive;
|
|
if (participant.participant.self) {
|
|
videoActive = VoIPService.getSharedInstance() != null && VoIPService.getSharedInstance().getVideoState(participant.presentation) == Instance.VIDEO_STATE_ACTIVE;
|
|
} else {
|
|
videoActive = (call.canStreamVideo || participant == call.videoNotAvailableParticipant) && ChatObject.Call.videoIsActive(participant.participant, participant.presentation, call);
|
|
}
|
|
if (showingInFullscreen || (!VoIPService.getSharedInstance().isFullscreen(participant.participant, participant.presentation) && !VoIPService.getSharedInstance().isFullscreen(participant.participant, participant.presentation) && videoActive)) {
|
|
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
|
for (int i = 0; i < attachedRenderers.size(); i++) {
|
|
if (attachedRenderers.get(i).participant.equals(participant)) {
|
|
throw new RuntimeException("try add two same renderers");
|
|
}
|
|
}
|
|
}
|
|
forceRequestLayout = true;
|
|
attached = true;
|
|
|
|
if (activity.statusIconPool.size() > 0) {
|
|
statusIcon = activity.statusIconPool.remove(activity.statusIconPool.size() - 1);
|
|
} else {
|
|
statusIcon = new GroupCallStatusIcon();
|
|
}
|
|
statusIcon.setCallback(this);
|
|
statusIcon.setImageView(micIconView);
|
|
updateIconColor(false);
|
|
|
|
if (getParent() == null) {
|
|
parentContainer.addView(this, LayoutHelper.createFrame(46, 46, Gravity.LEFT | Gravity.TOP));
|
|
parentContainer.attach(this);
|
|
}
|
|
|
|
checkScale = true;
|
|
animateEnter = false;
|
|
animate().setListener(null).cancel();
|
|
if (textureView.currentAnimation == null && ((secondaryView != null && primaryView == null)) && !hasImage()) {
|
|
setScaleX(0.5f);
|
|
setScaleY(0.5f);
|
|
setAlpha(0);
|
|
animateEnter = true;
|
|
invalidate();
|
|
animate().scaleX(1f).scaleY(1f).alpha(1f).setListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
animateEnter = false;
|
|
invalidate();
|
|
}
|
|
}).setDuration(100).start();
|
|
invalidate();
|
|
} else {
|
|
setScaleY(1f);
|
|
setScaleX(1f);
|
|
setAlpha(1f);
|
|
}
|
|
animated = false;
|
|
|
|
loadThumb();
|
|
screencastIcon.setVisibility(participant.presentation ? VISIBLE : GONE);
|
|
}
|
|
}
|
|
}
|
|
if (participant == call.videoNotAvailableParticipant) {
|
|
if (nameView.getVisibility() != INVISIBLE) {
|
|
nameView.setVisibility(INVISIBLE);
|
|
micIconView.setVisibility(INVISIBLE);
|
|
}
|
|
} else {
|
|
if (nameView.getVisibility() != VISIBLE) {
|
|
nameView.setVisibility(VISIBLE);
|
|
micIconView.setVisibility(VISIBLE);
|
|
}
|
|
}
|
|
|
|
if (attached) {
|
|
int size;
|
|
float spanCount = 1f;
|
|
boolean useSpanSize = false;
|
|
int gridItemsCount = 0;
|
|
|
|
boolean useTablet = GroupCallActivity.isTabletMode && (!parentContainer.inFullscreenMode || (secondaryView == null && primaryView == null));
|
|
if (showingInFullscreen) {
|
|
size = LayoutHelper.MATCH_PARENT;
|
|
} else if (secondaryView != null && primaryView == null && !parentContainer.inFullscreenMode) {
|
|
size = 0;
|
|
} else if (showingAsScrimView) {
|
|
size = LayoutHelper.MATCH_PARENT;
|
|
} else if (secondaryView != null && primaryView == null) {
|
|
size = AndroidUtilities.dp(80);
|
|
} else if (tabletGridView != null && useTablet) {
|
|
if (tabletGridView != null) {
|
|
useSpanSize = true;
|
|
size = LayoutHelper.MATCH_PARENT;
|
|
spanCount = tabletGridView.spanCount;
|
|
gridItemsCount = tabletGridView.gridAdapter.getItemCount();
|
|
} else {
|
|
size = AndroidUtilities.dp(46);
|
|
}
|
|
} else if (primaryView != null && secondaryView == null || !isFullscreenMode) {
|
|
if (primaryView != null) {
|
|
useSpanSize = true;
|
|
size = LayoutHelper.MATCH_PARENT;
|
|
spanCount = primaryView.spanCount;
|
|
} else {
|
|
size = AndroidUtilities.dp(46);
|
|
}
|
|
} else if (primaryView != null) {
|
|
size = AndroidUtilities.dp(80);
|
|
} else {
|
|
size = 0;
|
|
}
|
|
MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
|
|
if (size != 0 && (layoutParams.height != size || forceRequestLayout || this.useSpanSize != useSpanSize || (useSpanSize && this.spanCount != spanCount || this.gridItemsCount != gridItemsCount))) {
|
|
layoutParams.height = size;
|
|
layoutParams.width = useSpanSize ? LayoutHelper.MATCH_PARENT : size;
|
|
this.useSpanSize = useSpanSize;
|
|
this.spanCount = spanCount;
|
|
checkScale = true;
|
|
if (animated) {
|
|
textureView.animateToLayout();
|
|
updateNextLayoutAnimated = true;
|
|
} else {
|
|
textureView.requestLayout();
|
|
}
|
|
AndroidUtilities.runOnUIThread(this::requestLayout);
|
|
parentContainer.requestLayout();
|
|
invalidate();
|
|
}
|
|
|
|
if (participant.participant.self && !participant.presentation && VoIPService.getSharedInstance() != null) {
|
|
textureView.renderer.setMirror(VoIPService.getSharedInstance().isFrontFaceCamera());
|
|
textureView.renderer.setRotateTextureWitchScreen(true);
|
|
textureView.renderer.setUseCameraRotation(true);
|
|
} else {
|
|
textureView.renderer.setMirror(false);
|
|
textureView.renderer.setRotateTextureWitchScreen(true);
|
|
textureView.renderer.setUseCameraRotation(false);
|
|
}
|
|
textureView.updateRotation();
|
|
|
|
if (participant.participant.self) {
|
|
textureView.renderer.setMaxTextureSize(720);
|
|
} else {
|
|
textureView.renderer.setMaxTextureSize(0);
|
|
}
|
|
|
|
boolean hasVideoLocal = true;
|
|
|
|
if (!ChatObject.Call.videoIsActive(participant.participant, participant.presentation, call) || !call.canStreamVideo && participant != call.videoNotAvailableParticipant) {
|
|
noVideoStubLayout.avatarImageReceiver.setCurrentAccount(currentAccount);
|
|
int peerId = MessageObject.getPeerId(participant.participant.peer);
|
|
ImageLocation imageLocation;
|
|
ImageLocation thumbLocation;
|
|
Object parentObject;
|
|
if (peerId > 0) {
|
|
TLRPC.User currentUser = AccountInstance.getInstance(currentAccount).getMessagesController().getUser(peerId);
|
|
noVideoStubLayout.avatarDrawable.setInfo(currentUser);
|
|
imageLocation = ImageLocation.getForUser(currentUser, ImageLocation.TYPE_BIG);
|
|
thumbLocation = ImageLocation.getForUser(currentUser, ImageLocation.TYPE_SMALL);
|
|
parentObject = currentUser;
|
|
} else {
|
|
TLRPC.Chat currentChat = AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().getChat(-peerId);
|
|
noVideoStubLayout.avatarDrawable.setInfo(currentChat);
|
|
imageLocation = ImageLocation.getForChat(currentChat, ImageLocation.TYPE_BIG);
|
|
thumbLocation = ImageLocation.getForChat(currentChat, ImageLocation.TYPE_SMALL);
|
|
parentObject = currentChat;
|
|
}
|
|
|
|
Drawable thumb = noVideoStubLayout.avatarDrawable;
|
|
if (thumbLocation != null) {
|
|
BitmapDrawable drawable = ImageLoader.getInstance().getImageFromMemory(thumbLocation.location, null, "50_50");
|
|
if (drawable != null) {
|
|
thumb = drawable;
|
|
}
|
|
}
|
|
noVideoStubLayout.avatarImageReceiver.setImage(imageLocation, null, thumb, null, parentObject, 0);
|
|
noVideoStubLayout.backgroundImageReceiver.setImage(imageLocation, "50_50_b", new ColorDrawable(Theme.getColor(Theme.key_voipgroup_listViewBackground)), null, parentObject, 0);
|
|
hasVideoLocal = false;
|
|
}
|
|
|
|
boolean skipNoStubTransition = animated && secondaryView != null && !showingInFullscreen && !hasVideoLocal;
|
|
|
|
if (hasVideoLocal != hasVideo && !skipNoStubTransition) {
|
|
hasVideo = hasVideoLocal;
|
|
|
|
if (noVideoStubAnimator != null) {
|
|
noVideoStubAnimator.removeAllListeners();
|
|
noVideoStubAnimator.cancel();
|
|
}
|
|
if (animated) {
|
|
if (!hasVideo && noVideoStubLayout.getVisibility() != View.VISIBLE) {
|
|
noVideoStubLayout.setVisibility(View.VISIBLE);
|
|
noVideoStubLayout.setAlpha(0);
|
|
}
|
|
noVideoStubAnimator = ValueAnimator.ofFloat(progressToNoVideoStub, hasVideo ? 0 : 1f);
|
|
noVideoStubAnimator.addUpdateListener(valueAnimator1 -> {
|
|
progressToNoVideoStub = (float) valueAnimator1.getAnimatedValue();
|
|
noVideoStubLayout.setAlpha(progressToNoVideoStub);
|
|
textureView.invalidate();
|
|
});
|
|
noVideoStubAnimator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
progressToNoVideoStub = hasVideo ? 0f : 1f;
|
|
noVideoStubLayout.setAlpha(progressToNoVideoStub);
|
|
noVideoStubLayout.setVisibility(hasVideo ? View.GONE : View.VISIBLE);
|
|
textureView.invalidate();
|
|
}
|
|
});
|
|
noVideoStubAnimator.start();
|
|
} else {
|
|
progressToNoVideoStub = hasVideo ? 0f : 1f;
|
|
noVideoStubLayout.setVisibility(hasVideo ? View.GONE : View.VISIBLE);
|
|
noVideoStubLayout.setAlpha(progressToNoVideoStub);
|
|
textureView.invalidate();
|
|
}
|
|
|
|
if (hasVideo) {
|
|
noVideoStubLayout.updateMuteButtonState(false);
|
|
}
|
|
}
|
|
|
|
if (participant.participant.self && VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().setLocalSink(textureView.renderer, participant.presentation);
|
|
}
|
|
|
|
statusIcon.setParticipant(participant.participant, animated);
|
|
if (noVideoStubLayout.getVisibility() == View.VISIBLE) {
|
|
noVideoStubLayout.updateMuteButtonState(true);
|
|
}
|
|
|
|
boolean pausedInternal = false;
|
|
if (participant.participant.video != null && participant.participant.video.paused) {
|
|
pausedInternal = true;
|
|
}
|
|
if (videoIsPaused != pausedInternal) {
|
|
videoIsPaused = pausedInternal;
|
|
textureView.renderer.animate().alpha(videoIsPaused ? 0 : 1f).setDuration(250).start();
|
|
textureView.invalidate();
|
|
}
|
|
|
|
if (GroupCallActivity.paused || !hasVideo) {
|
|
if (participant.participant.self) {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().setLocalSink(null, participant.presentation);
|
|
}
|
|
} else if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().removeRemoteSink(participant.participant, participant.presentation);
|
|
VoIPService.getSharedInstance().removeRemoteSink(participant.participant, participant.presentation);
|
|
}
|
|
if (GroupCallActivity.paused && textureView.renderer.isFirstFrameRendered()) {
|
|
saveThumb();
|
|
textureView.renderer.clearFirstFrame();
|
|
textureView.renderer.setAlpha(0f);
|
|
textureView.blurRenderer.setAlpha(0f);
|
|
}
|
|
} else {
|
|
if (!textureView.renderer.isFirstFrameRendered()) {
|
|
loadThumb();
|
|
}
|
|
if (participant.participant.self) {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().setLocalSink(textureView.renderer, participant.presentation);
|
|
}
|
|
} else if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().addRemoteSink(participant.participant, participant.presentation, textureView.renderer, null);
|
|
VoIPService.getSharedInstance().addRemoteSink(participant.participant, participant.presentation, textureView.renderer, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
updateInfo();
|
|
}
|
|
|
|
private void loadThumb() {
|
|
if (thumb != null) {
|
|
return;
|
|
}
|
|
thumb = call.thumbs.get(participant.presentation ? participant.participant.presentationEndpoint : participant.participant.videoEndpoint);
|
|
textureView.setThumb(thumb);
|
|
|
|
if (thumb == null) {
|
|
int peerId = MessageObject.getPeerId(participant.participant.peer);
|
|
|
|
if (participant.participant.self && participant.presentation) {
|
|
imageReceiver.setImageBitmap(new MotionBackgroundDrawable(0xff212E3A, 0xff2B5B4D, 0xff245863, 0xff274558, true));
|
|
} else {
|
|
if (peerId > 0) {
|
|
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peerId);
|
|
ImageLocation imageLocation = ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL);
|
|
int color = user != null ? AvatarDrawable.getColorForId(user.id) : ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.2f);
|
|
GradientDrawable gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[]{ColorUtils.blendARGB(color, Color.BLACK, 0.2f), ColorUtils.blendARGB(color, Color.BLACK, 0.4f)});
|
|
imageReceiver.setImage(imageLocation, "50_50_b", gradientDrawable, null, user, 0);
|
|
} else {
|
|
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-peerId);
|
|
ImageLocation imageLocation = ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL);
|
|
int color = chat != null ? AvatarDrawable.getColorForId(chat.id) : ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.2f);
|
|
GradientDrawable gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[]{ColorUtils.blendARGB(color, Color.BLACK, 0.2f), ColorUtils.blendARGB(color, Color.BLACK, 0.4f)});
|
|
imageReceiver.setImage(imageLocation, "50_50_b", gradientDrawable, null, chat, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public void updateInfo() {
|
|
if (!attached) {
|
|
return;
|
|
}
|
|
|
|
String name = null;
|
|
|
|
int peerId = MessageObject.getPeerId(participant.participant.peer);
|
|
if (peerId > 0) {
|
|
TLRPC.User currentUser = AccountInstance.getInstance(currentAccount).getMessagesController().getUser(peerId);
|
|
name = UserObject.getUserName(currentUser);
|
|
} else {
|
|
TLRPC.Chat currentChat = AccountInstance.getInstance(currentAccount).getMessagesController().getChat(-peerId);
|
|
if (currentChat != null) {
|
|
name = currentChat.title;
|
|
}
|
|
}
|
|
|
|
nameView.setText(name);
|
|
}
|
|
|
|
public boolean hasImage() {
|
|
return textureView.stubVisibleProgress == 1f;
|
|
}
|
|
|
|
public void updatePosition(ViewGroup listView, ViewGroup tabletGridListView, RecyclerListView fullscreenListView, GroupCallRenderersContainer renderersContainer) {
|
|
if (showingAsScrimView || animateToScrimView || forceDetached) {
|
|
return;
|
|
}
|
|
drawFirst = false;
|
|
float progressToFullscreen = renderersContainer.progressToFullscreenMode;
|
|
if (animateToFullscreen || showingInFullscreen) {
|
|
if (primaryView != null || tabletGridView != null) {
|
|
GroupCallGridCell callUserCell = tabletGridView != null ? tabletGridView : primaryView;
|
|
ViewGroup fromListView = tabletGridView != null ? tabletGridListView : listView;
|
|
float fromX = callUserCell.getX() + fromListView.getX() - getLeft() - renderersContainer.getLeft();
|
|
float fromY = callUserCell.getY() + AndroidUtilities.dp(2) + fromListView.getY() - getTop() - renderersContainer.getTop();
|
|
|
|
float toX = 0;
|
|
float toY = 0;
|
|
|
|
setTranslationX(fromX * (1f - progressToFullscreen) + toX * progressToFullscreen);
|
|
setTranslationY(fromY * (1f - progressToFullscreen) + toY * progressToFullscreen);
|
|
} else {
|
|
setTranslationX(0);
|
|
setTranslationY(0);
|
|
}
|
|
|
|
textureView.setRoundCorners(AndroidUtilities.dp(8));
|
|
|
|
if (secondaryView != null) {
|
|
secondaryView.setAlpha(progressToFullscreen);
|
|
}
|
|
if (!showingInFullscreen && primaryView == null && tabletGridView == null) {
|
|
setAlpha(progressToFullscreen);
|
|
} else if (!animateEnter) {
|
|
setAlpha(1f);
|
|
}
|
|
} else if (secondaryView != null) {
|
|
if (secondaryView.isRemoving(fullscreenListView)) {
|
|
setAlpha(secondaryView.getAlpha());
|
|
} else if (primaryView == null) {
|
|
if (attached && !animateEnter) {
|
|
setAlpha(progressToFullscreen);
|
|
}
|
|
secondaryView.setAlpha(progressToFullscreen);
|
|
progressToFullscreen = 1f;
|
|
} else {
|
|
secondaryView.setAlpha(1f);
|
|
if (attached && !animateEnter) {
|
|
setAlpha(1f);
|
|
}
|
|
}
|
|
|
|
setTranslationX(secondaryView.getX() + fullscreenListView.getX() - getLeft());
|
|
setTranslationY(AndroidUtilities.dp(2) * (1f - progressToFullscreen) + secondaryView.getY() + fullscreenListView.getY() - getTop());
|
|
textureView.setRoundCorners(AndroidUtilities.dp(13) * progressToFullscreen + AndroidUtilities.dp(8) * (1f - progressToFullscreen));
|
|
} else if (primaryView != null || tabletGridView != null) {
|
|
GroupCallGridCell callUserCell;
|
|
ViewGroup fromListView;
|
|
if (tabletGridView != null && primaryView != null) {
|
|
boolean useTablet = GroupCallActivity.isTabletMode && !parentContainer.inFullscreenMode;
|
|
callUserCell = useTablet ? tabletGridView : primaryView;
|
|
fromListView = useTablet ? tabletGridListView : listView;
|
|
} else {
|
|
callUserCell = tabletGridView != null ? tabletGridView : primaryView;
|
|
fromListView = tabletGridView != null ? tabletGridListView : listView;
|
|
}
|
|
setTranslationX(callUserCell.getX() + fromListView.getX() - getLeft() - renderersContainer.getLeft());
|
|
setTranslationY(callUserCell.getY() + AndroidUtilities.dp(2) + fromListView.getY() - getTop() - renderersContainer.getTop());
|
|
textureView.setRoundCorners(AndroidUtilities.dp(8));
|
|
|
|
if (attached && !animateEnter) {
|
|
if (!GroupCallActivity.isTabletMode) {
|
|
drawFirst = true;
|
|
setAlpha((1f - progressToFullscreen) * callUserCell.getAlpha());
|
|
} else if (primaryView != null && tabletGridView == null) {
|
|
setAlpha(progressToFullscreen * callUserCell.getAlpha());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isAttached() {
|
|
return attached;
|
|
}
|
|
|
|
public void release() {
|
|
textureView.renderer.release();
|
|
if (statusIcon != null) {
|
|
activity.statusIconPool.add(statusIcon);
|
|
statusIcon.setCallback(null);
|
|
statusIcon.setImageView(null);
|
|
}
|
|
statusIcon = null;
|
|
}
|
|
|
|
public boolean isFullyVisible() {
|
|
if (showingInFullscreen || animateToFullscreen) {
|
|
return false;
|
|
}
|
|
return attached && textureView.renderer.isFirstFrameRendered() && getAlpha() == 1;
|
|
}
|
|
|
|
public boolean isVisible() {
|
|
if (showingInFullscreen || animateToFullscreen) {
|
|
return false;
|
|
}
|
|
return attached && textureView.renderer.isFirstFrameRendered();
|
|
}
|
|
|
|
@Override
|
|
public void invalidate() {
|
|
super.invalidate();
|
|
if (!invalidateFromChild) {
|
|
textureView.invalidate();
|
|
}
|
|
if (primaryView != null) {
|
|
primaryView.invalidate();
|
|
if (activity.getScrimView() == primaryView) {
|
|
activity.getContainerView().invalidate();
|
|
}
|
|
}
|
|
if (secondaryView != null) {
|
|
secondaryView.invalidate();
|
|
if (secondaryView.getParent() != null) {
|
|
((View) secondaryView.getParent()).invalidate();
|
|
}
|
|
}
|
|
if (getParent() != null) {
|
|
((View) getParent()).invalidate();
|
|
}
|
|
}
|
|
|
|
|
|
public void forceDetach(boolean removeSink) {
|
|
GroupCallMiniTextureView viewToRemove = this;
|
|
forceDetached = true;
|
|
attached = false;
|
|
parentContainer.detach(viewToRemove);
|
|
|
|
if (removeSink) {
|
|
if (participant.participant.self) {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().setLocalSink(null, participant.presentation);
|
|
}
|
|
} else {
|
|
if (VoIPService.getSharedInstance() != null) {
|
|
VoIPService.getSharedInstance().removeRemoteSink(participant.participant, participant.presentation);
|
|
}
|
|
}
|
|
}
|
|
|
|
saveThumb();
|
|
|
|
if (noVideoStubAnimator != null) {
|
|
noVideoStubAnimator.removeAllListeners();
|
|
noVideoStubAnimator.cancel();
|
|
}
|
|
|
|
textureView.renderer.release();
|
|
}
|
|
|
|
public void saveThumb() {
|
|
if (participant != null && textureView.renderer.getMeasuredHeight() != 0 && textureView.renderer.getMeasuredWidth() != 0) {
|
|
getRenderBufferBitmap((bitmap, rotation1) -> {
|
|
if (bitmap != null && bitmap.getPixel(0, 0) != Color.TRANSPARENT) {
|
|
Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(bitmap.getWidth(), bitmap.getHeight()) / 180));
|
|
AndroidUtilities.runOnUIThread(() -> call.thumbs.put(participant.presentation ? participant.participant.presentationEndpoint : participant.participant.videoEndpoint, bitmap));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public void setViews(GroupCallGridCell primaryView, GroupCallFullscreenAdapter.GroupCallUserCell secondaryView, GroupCallGridCell tabletGrid) {
|
|
this.primaryView = primaryView;
|
|
this.secondaryView = secondaryView;
|
|
this.tabletGridView = tabletGrid;
|
|
}
|
|
|
|
public void setAmplitude(double value) {
|
|
statusIcon.setAmplitude(value);
|
|
noVideoStubLayout.setAmplitude(value);
|
|
}
|
|
|
|
public void setZoom(boolean inPinchToZoom, float pinchScale, float pinchCenterX, float pinchCenterY, float pinchTranslationX, float pinchTranslationY) {
|
|
if (this.pinchScale != pinchScale || this.pinchCenterX != pinchCenterX || this.pinchCenterY != pinchCenterY || this.pinchTranslationX != pinchTranslationX || this.pinchTranslationY != pinchTranslationY) {
|
|
this.inPinchToZoom = inPinchToZoom;
|
|
this.pinchScale = pinchScale;
|
|
this.pinchCenterX = pinchCenterX;
|
|
this.pinchCenterY = pinchCenterY;
|
|
this.pinchTranslationX = pinchTranslationX;
|
|
this.pinchTranslationY = pinchTranslationY;
|
|
textureView.invalidate();
|
|
}
|
|
}
|
|
|
|
public void setSwipeToBack(boolean swipeToBack, float swipeToBackDy) {
|
|
if (this.swipeToBack != swipeToBack || this.swipeToBackDy != swipeToBackDy) {
|
|
this.swipeToBack = swipeToBack;
|
|
this.swipeToBackDy = swipeToBackDy;
|
|
textureView.invalidate();
|
|
invalidate();
|
|
}
|
|
}
|
|
|
|
public void runOnFrameRendered(Runnable runnable) {
|
|
if (textureView.renderer.isFirstFrameRendered()) {
|
|
runnable.run();
|
|
} else {
|
|
AndroidUtilities.runOnUIThread(runnable, 250);
|
|
onFirstFrameRunnables.add(runnable);
|
|
}
|
|
}
|
|
|
|
int lastIconColor;
|
|
int animateToColor;
|
|
int lastSpeakingFrameColor;
|
|
ValueAnimator colorAnimator;
|
|
|
|
@Override
|
|
public void onStatusChanged() {
|
|
invalidate();
|
|
updateIconColor(true);
|
|
if (noVideoStubLayout.getVisibility() == View.VISIBLE) {
|
|
noVideoStubLayout.updateMuteButtonState(true);
|
|
}
|
|
}
|
|
|
|
private void updateIconColor(boolean animated) {
|
|
if (statusIcon == null) {
|
|
return;
|
|
}
|
|
int newColor;
|
|
int newSpeakingFrameColor;
|
|
if (statusIcon.isMutedByMe()) {
|
|
newSpeakingFrameColor = newColor = Theme.getColor(Theme.key_voipgroup_mutedByAdminIcon);
|
|
} else if (statusIcon.isSpeaking()) {
|
|
newSpeakingFrameColor = newColor = Theme.getColor(Theme.key_voipgroup_speakingText);
|
|
} else {
|
|
newSpeakingFrameColor = Theme.getColor(Theme.key_voipgroup_speakingText);
|
|
newColor = Color.WHITE;
|
|
}
|
|
|
|
if (animateToColor == newColor) {
|
|
return;
|
|
}
|
|
if (colorAnimator != null) {
|
|
colorAnimator.removeAllListeners();
|
|
colorAnimator.cancel();
|
|
}
|
|
|
|
if (!animated) {
|
|
// micIconView.setColorFilter(new PorterDuffColorFilter(animateToColor = lastIconColor = newColor, PorterDuff.Mode.MULTIPLY));
|
|
speakingPaint.setColor(lastSpeakingFrameColor = newSpeakingFrameColor);
|
|
} else {
|
|
int colorFrom = lastIconColor;
|
|
int colorFromSpeaking = lastSpeakingFrameColor;
|
|
animateToColor = newColor;
|
|
colorAnimator = ValueAnimator.ofFloat(0, 1f);
|
|
colorAnimator.addUpdateListener(valueAnimator -> {
|
|
float v = (float) valueAnimator.getAnimatedValue();
|
|
lastIconColor = ColorUtils.blendARGB(colorFrom, newColor, v);
|
|
lastSpeakingFrameColor = ColorUtils.blendARGB(colorFromSpeaking, newSpeakingFrameColor, v);
|
|
// micIconView.setColorFilter(new PorterDuffColorFilter(lastIconColor, PorterDuff.Mode.MULTIPLY));
|
|
speakingPaint.setColor(lastSpeakingFrameColor);
|
|
});
|
|
colorAnimator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
animateToColor = lastIconColor = newColor;
|
|
lastSpeakingFrameColor = newSpeakingFrameColor;
|
|
// micIconView.setColorFilter(new PorterDuffColorFilter(lastIconColor, PorterDuff.Mode.MULTIPLY));
|
|
speakingPaint.setColor(lastSpeakingFrameColor);
|
|
}
|
|
});
|
|
colorAnimator.start();
|
|
}
|
|
}
|
|
|
|
public void runDelayedAnimations() {
|
|
for (int i = 0; i < onFirstFrameRunnables.size(); i++) {
|
|
onFirstFrameRunnables.get(i).run();
|
|
}
|
|
onFirstFrameRunnables.clear();
|
|
}
|
|
|
|
int collapseSize;
|
|
int fullSize;
|
|
|
|
public void updateSize(int collapseSize) {
|
|
int fullSize = parentContainer.getMeasuredWidth() - AndroidUtilities.dp(6);
|
|
if ((this.collapseSize != collapseSize && collapseSize > 0) || (this.fullSize != fullSize && fullSize > 0)) {
|
|
if (collapseSize != 0) {
|
|
this.collapseSize = collapseSize;
|
|
}
|
|
if (fullSize != 0) {
|
|
this.fullSize = fullSize;
|
|
}
|
|
nameView.setFullLayoutAdditionalWidth(fullSize - collapseSize, 0);
|
|
}
|
|
}
|
|
|
|
private class NoVideoStubLayout extends View {
|
|
|
|
public ImageReceiver avatarImageReceiver = new ImageReceiver();
|
|
public ImageReceiver backgroundImageReceiver = new ImageReceiver();
|
|
AvatarDrawable avatarDrawable = new AvatarDrawable();
|
|
|
|
BlobDrawable tinyWaveDrawable;
|
|
BlobDrawable bigWaveDrawable;
|
|
|
|
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
float amplitude;
|
|
float animateToAmplitude;
|
|
float animateAmplitudeDiff;
|
|
float wavesEnter = 0f;
|
|
float cx, cy;
|
|
float speakingProgress;
|
|
|
|
public NoVideoStubLayout(@NonNull Context context) {
|
|
super(context);
|
|
|
|
tinyWaveDrawable = new BlobDrawable(9);
|
|
bigWaveDrawable = new BlobDrawable(12);
|
|
|
|
tinyWaveDrawable.minRadius = AndroidUtilities.dp(76);
|
|
tinyWaveDrawable.maxRadius = AndroidUtilities.dp(92);
|
|
tinyWaveDrawable.generateBlob();
|
|
|
|
bigWaveDrawable.minRadius = AndroidUtilities.dp(80);
|
|
bigWaveDrawable.maxRadius = AndroidUtilities.dp(95);
|
|
bigWaveDrawable.generateBlob();
|
|
|
|
paint.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_voipgroup_listeningText), Theme.getColor(Theme.key_voipgroup_speakingText), speakingProgress));
|
|
paint.setAlpha((int) (255 * 0.4f));
|
|
|
|
backgroundPaint.setColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.5f)));
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
float size = AndroidUtilities.dp(157);
|
|
cx = getMeasuredWidth() >> 1;
|
|
cy = (getMeasuredHeight() >> 1) + (GroupCallActivity.isLandscapeMode ? 0 : -getMeasuredHeight() * 0.12f);
|
|
avatarImageReceiver.setRoundRadius((int) (size / 2f));
|
|
avatarImageReceiver.setImageCoords(cx - size / 2, cy - size / 2, size, size);
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
super.onDraw(canvas);
|
|
|
|
AndroidUtilities.rectTmp.set(textureView.getX() + textureView.currentClipHorizontal, textureView.getY() + textureView.currentClipVertical, textureView.getX() + textureView.getMeasuredWidth() - textureView.currentClipHorizontal, textureView.getY() + textureView.getMeasuredHeight() + textureView.currentClipVertical);
|
|
backgroundImageReceiver.setImageCoords(AndroidUtilities.rectTmp.left, AndroidUtilities.rectTmp.top, AndroidUtilities.rectTmp.width(), AndroidUtilities.rectTmp.height());
|
|
backgroundImageReceiver.setRoundRadius((int) textureView.roundRadius);
|
|
backgroundImageReceiver.draw(canvas);
|
|
|
|
canvas.drawRoundRect(AndroidUtilities.rectTmp, textureView.roundRadius, textureView.roundRadius, backgroundPaint);
|
|
|
|
if (animateToAmplitude != amplitude) {
|
|
amplitude += animateAmplitudeDiff * 16;
|
|
if (animateAmplitudeDiff > 0) {
|
|
if (amplitude > animateToAmplitude) {
|
|
amplitude = animateToAmplitude;
|
|
}
|
|
} else {
|
|
if (amplitude < animateToAmplitude) {
|
|
amplitude = animateToAmplitude;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (switchProgress != 1f) {
|
|
if (prevState != null) {
|
|
switchProgress += 16 / 220f;
|
|
}
|
|
if (switchProgress >= 1.0f) {
|
|
switchProgress = 1f;
|
|
prevState = null;
|
|
}
|
|
}
|
|
|
|
float scale = 1f + 0.8f * amplitude;
|
|
canvas.save();
|
|
canvas.scale(scale, scale, cx, cy);
|
|
|
|
if (currentState != null) {
|
|
currentState.update((int) (cy - AndroidUtilities.dp(100)), (int) (cx - AndroidUtilities.dp(100)), AndroidUtilities.dp(200), 16, amplitude);
|
|
}
|
|
bigWaveDrawable.update(amplitude, 1f);
|
|
tinyWaveDrawable.update(amplitude, 1f);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
float alpha;
|
|
if (i == 0 && prevState != null) {
|
|
paint.setShader(prevState.shader);
|
|
alpha = 1f - switchProgress;
|
|
} else if (i == 1 && currentState != null) {
|
|
paint.setShader(currentState.shader);
|
|
alpha = switchProgress;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
paint.setAlpha((int) (76 * alpha));
|
|
bigWaveDrawable.draw(cx, cy, canvas, paint);
|
|
tinyWaveDrawable.draw(cx, cy, canvas, paint);
|
|
}
|
|
canvas.restore();
|
|
|
|
scale = 1f + 0.2f * amplitude;
|
|
canvas.save();
|
|
canvas.scale(scale, scale, cx, cy);
|
|
avatarImageReceiver.draw(canvas);
|
|
canvas.restore();
|
|
|
|
invalidate();
|
|
}
|
|
|
|
private GroupCallActivity.WeavingState[] states = new GroupCallActivity.WeavingState[3];
|
|
private GroupCallActivity.WeavingState currentState;
|
|
private GroupCallActivity.WeavingState prevState;
|
|
|
|
int muteButtonState = -1;
|
|
private final static int MUTE_BUTTON_STATE_MUTE = 1;
|
|
private final static int MUTE_BUTTON_STATE_UNMUTE = 0;
|
|
private final static int MUTED_BY_ADMIN = 2;
|
|
float switchProgress = 1f;
|
|
|
|
private void updateMuteButtonState(boolean animated) {
|
|
int newButtonState;
|
|
if (statusIcon.isMutedByMe() || statusIcon.isMutedByAdmin()) {
|
|
newButtonState = MUTED_BY_ADMIN;
|
|
} else if (statusIcon.isSpeaking()) {
|
|
newButtonState = MUTE_BUTTON_STATE_MUTE;
|
|
} else {
|
|
newButtonState = MUTE_BUTTON_STATE_UNMUTE;
|
|
}
|
|
if (newButtonState == muteButtonState) {
|
|
return;
|
|
}
|
|
muteButtonState = newButtonState;
|
|
|
|
if (states[muteButtonState] == null) {
|
|
states[muteButtonState] = new GroupCallActivity.WeavingState(muteButtonState);
|
|
if (muteButtonState == MUTED_BY_ADMIN) {
|
|
states[muteButtonState].shader = new LinearGradient(0, 400, 400, 0, new int[]{Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient3), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient2)}, null, Shader.TileMode.CLAMP);
|
|
} else if (muteButtonState == MUTE_BUTTON_STATE_MUTE) {
|
|
states[muteButtonState].shader = new RadialGradient(200, 200, 200, new int[]{Theme.getColor(Theme.key_voipgroup_muteButton), Theme.getColor(Theme.key_voipgroup_muteButton3)}, null, Shader.TileMode.CLAMP);
|
|
} else {
|
|
states[muteButtonState].shader = new RadialGradient(200, 200, 200, new int[]{Theme.getColor(Theme.key_voipgroup_unmuteButton2), Theme.getColor(Theme.key_voipgroup_unmuteButton)}, null, Shader.TileMode.CLAMP);
|
|
}
|
|
}
|
|
if (states[muteButtonState] != currentState) {
|
|
prevState = currentState;
|
|
currentState = states[muteButtonState];
|
|
if (prevState == null || !animated) {
|
|
switchProgress = 1;
|
|
prevState = null;
|
|
} else {
|
|
switchProgress = 0;
|
|
}
|
|
}
|
|
invalidate();
|
|
}
|
|
|
|
public void setAmplitude(double value) {
|
|
float amplitude = (float) value / 80f;
|
|
if (amplitude > 1f) {
|
|
amplitude = 1f;
|
|
} else if (amplitude < 0) {
|
|
amplitude = 0;
|
|
}
|
|
animateToAmplitude = amplitude;
|
|
animateAmplitudeDiff = (animateToAmplitude - this.amplitude) / 200;
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
avatarImageReceiver.onAttachedToWindow();
|
|
backgroundImageReceiver.onAttachedToWindow();
|
|
}
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
avatarImageReceiver.onDetachedFromWindow();
|
|
backgroundImageReceiver.onDetachedFromWindow();
|
|
}
|
|
}
|
|
|
|
public String getName() {
|
|
int peerId = MessageObject.getPeerId(participant.participant.peer);
|
|
if (peerId > 0) {
|
|
TLRPC.User currentUser = AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().getUser(peerId);
|
|
return UserObject.getUserName(currentUser);
|
|
} else {
|
|
TLRPC.Chat currentChat = AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().getChat(-peerId);
|
|
return currentChat.title;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
imageReceiver.onDetachedFromWindow();
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
imageReceiver.onAttachedToWindow();
|
|
}
|
|
|
|
ValueAnimator flipAnimator;
|
|
boolean flipHalfReached;
|
|
|
|
public void startFlipAnimation() {
|
|
if (flipAnimator != null) {
|
|
return;
|
|
}
|
|
flipHalfReached = false;
|
|
|
|
if (blurredFlippingStub == null) {
|
|
blurredFlippingStub = new ImageView(getContext());
|
|
} else {
|
|
blurredFlippingStub.animate().cancel();
|
|
}
|
|
if (textureView.renderer.isFirstFrameRendered()) {
|
|
Bitmap bitmap = textureView.blurRenderer.getBitmap(100, 100);
|
|
if (bitmap != null) {
|
|
Utilities.blurBitmap(bitmap, 3, 1, bitmap.getWidth(), bitmap.getHeight(), bitmap.getRowBytes());
|
|
Drawable drawable = new BitmapDrawable(bitmap);
|
|
blurredFlippingStub.setBackground(drawable);
|
|
}
|
|
blurredFlippingStub.setAlpha(0f);
|
|
} else {
|
|
blurredFlippingStub.setAlpha(1f);
|
|
}
|
|
|
|
if (blurredFlippingStub.getParent() == null) {
|
|
textureView.addView(blurredFlippingStub);
|
|
}
|
|
((LayoutParams) blurredFlippingStub.getLayoutParams()).gravity = Gravity.CENTER;
|
|
|
|
flipAnimator = ValueAnimator.ofFloat(0, 1f);
|
|
flipAnimator.addUpdateListener(valueAnimator -> {
|
|
float v = (float) valueAnimator.getAnimatedValue();
|
|
float rotation;
|
|
boolean halfReached = false;
|
|
if (v < 0.5f) {
|
|
rotation = v;
|
|
} else {
|
|
halfReached = true;
|
|
rotation = v - 1f;
|
|
}
|
|
|
|
if (halfReached && !flipHalfReached) {
|
|
blurredFlippingStub.setAlpha(1f);
|
|
flipHalfReached = true;
|
|
textureView.renderer.clearImage();
|
|
}
|
|
|
|
rotation *= 180;
|
|
blurredFlippingStub.setRotationY(rotation);
|
|
textureView.renderer.setRotationY(rotation);
|
|
});
|
|
|
|
flipAnimator.addListener(new AnimatorListenerAdapter() {
|
|
@Override
|
|
public void onAnimationEnd(Animator animation) {
|
|
super.onAnimationEnd(animation);
|
|
flipAnimator = null;
|
|
textureView.setRotationY(0);
|
|
|
|
if (!flipHalfReached) {
|
|
textureView.renderer.clearImage();
|
|
//
|
|
}
|
|
}
|
|
});
|
|
flipAnimator.setDuration(400);
|
|
flipAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
|
flipAnimator.start();
|
|
}
|
|
}
|