update to 11.5.3 (5511)

This commit is contained in:
dkaraush 2024-12-06 21:05:26 +04:00
parent fb2e545101
commit 9dcd88b8c1
177 changed files with 12835 additions and 2552 deletions

View file

@ -917,6 +917,8 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Stories_recorder_FfmpegAudioWaveform
int skip = 4;
int barWidth = (int) round((double) duration_in_seconds * sampleRate / count / (1 + skip)); // Assuming you have 'duration' and 'count' defined somewhere
int channels = codecContext->channels;
short peak = 0;
int currentCount = 0;
int index = 0;
@ -937,9 +939,43 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Stories_recorder_FfmpegAudioWaveform
break;
}
int16_t* samples = (int16_t*) frame->data[0];
const int is_planar = av_sample_fmt_is_planar(codecContext->sample_fmt);
const int sample_size = av_get_bytes_per_sample(codecContext->sample_fmt);
for (int i = 0; i < frame->nb_samples; i++) {
short value = samples[i]; // Read the 16-bit PCM sample
int sum = 0;
for (int channel = 0; channel < channels; channel++) {
uint8_t *data;
if (is_planar) {
data = frame->data[channel] + i * sample_size;
} else {
data = frame->data[0] + (i * channels + channel) * sample_size;
}
short sample_value = 0;
switch (codecContext->sample_fmt) {
case AV_SAMPLE_FMT_S16:
case AV_SAMPLE_FMT_S16P:
// Signed 16-bit PCM
sample_value = *(int16_t *)data;
break;
case AV_SAMPLE_FMT_FLT:
case AV_SAMPLE_FMT_FLTP:
// 32-bit float, scale to 16-bit PCM range
sample_value = (short)(*(float *)data * 32767.0f);
break;
case AV_SAMPLE_FMT_U8:
case AV_SAMPLE_FMT_U8P:
// Unsigned 8-bit PCM, scale to 16-bit PCM range
sample_value = (*(uint8_t *)data - 128) * 256;
break;
default:
break;
}
sum += sample_value;
}
short value = sum / channels;
if (currentCount >= barWidth) {
waveformChunkData[index - chunkIndex] = peak;

View file

@ -176,7 +176,7 @@ int open_codec_context(int *stream_idx, AVCodecContext **dec_ctx, AVFormatContex
dec = avcodec_find_decoder(st->codecpar->codec_id);
if (!dec) {
LOGE("failed to find %s codec", av_get_media_type_string(type));
LOGE("failed to find %d codec", st->codecpar->codec_id);
return AVERROR(EINVAL);
}
@ -857,7 +857,7 @@ extern "C" JNIEXPORT int JNICALL Java_org_telegram_ui_Components_AnimatedFileDra
}
extern "C" JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env, jclass clazz, jlong ptr, jobject bitmap, jintArray data, jint stride, jboolean preview, jfloat start_time, jfloat end_time, jboolean loop) {
if (ptr == NULL || bitmap == nullptr) {
if (ptr == NULL) {
return 0;
}
//int64_t time = ConnectionsManager::getInstance(0).getCurrentTimeMonotonicMillis();
@ -946,10 +946,11 @@ extern "C" JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_AnimatedFileDr
}
if (got_frame) {
//LOGD("decoded frame with w = %d, h = %d, format = %d", info->frame->width, info->frame->height, info->frame->format);
if (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_BGRA || info->frame->format == AV_PIX_FMT_YUVJ420P || info->frame->format == AV_PIX_FMT_YUV444P || info->frame->format == AV_PIX_FMT_YUVA420P) {
if (bitmap != nullptr && (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_BGRA || info->frame->format == AV_PIX_FMT_YUVJ420P || info->frame->format == AV_PIX_FMT_YUV444P || info->frame->format == AV_PIX_FMT_YUVA420P)) {
writeFrameToBitmap(env, info, data, bitmap, stride);
}
info->has_decoded_frames = true;
push_time(env, info, data);
av_frame_unref(info->frame);
return 1;
}

Binary file not shown.

View file

@ -20,6 +20,7 @@ import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.Context;
import android.media.MediaCodec;
import android.media.PlaybackParams;
import android.opengl.EGLContext;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.IntDef;
@ -286,6 +287,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
@Override
public Renderer[] createRenderers(
Handler eventHandler,
EGLContext parentContext,
VideoRendererEventListener videoRendererEventListener,
AudioRendererEventListener audioRendererEventListener,
TextOutput textRendererOutput,
@ -293,6 +295,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
ArrayList<Renderer> renderersList = new ArrayList<>();
buildVideoRenderers(
context,
parentContext,
extensionRendererMode,
mediaCodecSelector,
enableDecoderFallback,
@ -348,6 +351,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
*/
protected void buildVideoRenderers(
Context context,
EGLContext parentContext,
@ExtensionRendererMode int extensionRendererMode,
MediaCodecSelector mediaCodecSelector,
boolean enableDecoderFallback,
@ -358,6 +362,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
MediaCodecVideoRenderer videoRenderer =
new MediaCodecVideoRenderer(
context,
parentContext,
getCodecAdapterFactory(),
mediaCodecSelector,
allowedVideoJoiningTimeMs,

View file

@ -23,6 +23,7 @@ import android.content.Context;
import android.media.AudioDeviceInfo;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.opengl.EGLContext;
import android.os.Looper;
import android.os.Process;
import android.view.Surface;
@ -452,6 +453,7 @@ public interface ExoPlayer extends Player {
final class Builder {
/* package */ final Context context;
public EGLContext eglContext;
/* package */ Clock clock;
/* package */ long foregroundModeTimeoutMs;

View file

@ -249,6 +249,7 @@ import java.util.concurrent.TimeoutException;
.get()
.createRenderers(
eventHandler,
builder.eglContext,
componentListener,
componentListener,
componentListener,

View file

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2;
import android.opengl.EGLContext;
import android.os.Handler;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.metadata.MetadataOutput;
@ -36,6 +37,7 @@ public interface RenderersFactory {
*/
Renderer[] createRenderers(
Handler eventHandler,
EGLContext parentContext,
VideoRendererEventListener videoRendererEventListener,
AudioRendererEventListener audioRendererEventListener,
TextOutput textRendererOutput,

View file

@ -28,6 +28,7 @@ import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.opengl.EGLContext;
import android.os.Handler;
import androidx.annotation.CallSuper;
import androidx.annotation.DoNotInline;
@ -418,7 +419,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
MediaCodecInfo codecInfo,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
float codecOperatingRate,
EGLContext parentContext
) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
MediaFormat mediaFormat =

View file

@ -39,6 +39,7 @@ import android.media.MediaCrypto;
import android.media.MediaCryptoException;
import android.media.MediaFormat;
import android.media.metrics.LogSessionId;
import android.opengl.EGLContext;
import android.os.Bundle;
import android.os.SystemClock;
import androidx.annotation.CallSuper;
@ -75,6 +76,8 @@ import com.google.android.exoplayer2.util.NalUnitUtil;
import com.google.android.exoplayer2.util.TimedValueQueue;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -487,7 +490,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
MediaCodecInfo codecInfo,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate);
float codecOperatingRate,
EGLContext context);
protected final void maybeInitCodecOrBypass() throws ExoPlaybackException {
if (codec != null || bypassEnabled || inputFormat == null) {
@ -1099,7 +1103,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
codecInitializingTimestamp = SystemClock.elapsedRealtime();
MediaCodecAdapter.Configuration configuration =
getMediaCodecConfiguration(codecInfo, inputFormat, crypto, codecOperatingRate);
getMediaCodecConfiguration(codecInfo, inputFormat, crypto, codecOperatingRate, this instanceof MediaCodecVideoRenderer ? ((MediaCodecVideoRenderer) this).eglContext : null);
if (Util.SDK_INT >= 31) {
Api31.setLogSessionIdToMediaCodecFormat(configuration, getPlayerId());
}

View file

@ -152,6 +152,7 @@ public final class DownloadHelper {
Renderer[] renderers =
renderersFactory.createRenderers(
Util.createHandlerForCurrentOrMainLooper(),
null,
new VideoRendererEventListener() {},
new AudioRendererEventListener() {},
(cues) -> {},

View file

@ -292,7 +292,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
private @C.NetworkType int networkType;
private long totalElapsedTimeMs;
private long totalBytesTransferred;
private long bitrateEstimate;
private volatile long bitrateEstimate;
private long lastReportedBitrateEstimate;
private boolean networkTypeOverrideSet;
@ -420,7 +420,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
streamCount--;
}
public void onTransfer(long bytes, long duration) {
public synchronized void onTransfer(long bytes, long duration) {
long nowMs = clock.elapsedRealtime();
int sampleElapsedTimeMs = (int) (nowMs - sampleStartTimeMs);
totalElapsedTimeMs += sampleElapsedTimeMs;

View file

@ -90,7 +90,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
/**
* @param handler The {@link Handler} that will be used to call {@link
* SurfaceTexture#updateTexImage()} to update images on the {@link SurfaceTexture}. Note that
* {@link #init(int)} has to be called on the same looper thread as the {@link Handler}'s
* {@link #init(int, EGLContext)} has to be called on the same looper thread as the {@link Handler}'s
* looper.
*/
public EGLSurfaceTexture(Handler handler) {
@ -100,7 +100,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
/**
* @param handler The {@link Handler} that will be used to call {@link
* SurfaceTexture#updateTexImage()} to update images on the {@link SurfaceTexture}. Note that
* {@link #init(int)} has to be called on the same looper thread as the looper of the {@link
* {@link #init(int, EGLContext)} has to be called on the same looper thread as the looper of the {@link
* Handler}.
* @param callback The {@link TextureImageListener} to be called when the texture image on {@link
* SurfaceTexture} has been updated. This callback will be called on the same handler thread
@ -117,10 +117,10 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
*
* @param secureMode The {@link SecureMode} to be used for EGL surface.
*/
public void init(@SecureMode int secureMode) throws GlUtil.GlException {
public void init(@SecureMode int secureMode, EGLContext parentContext) throws GlUtil.GlException {
display = getDefaultDisplay();
EGLConfig config = chooseEGLConfig(display);
context = createEGLContext(display, config, secureMode);
context = createEGLContext(display, config, secureMode, parentContext);
surface = createEGLSurface(display, config, context, secureMode);
generateTextureIds(textureIdHolder);
texture = new SurfaceTexture(textureIdHolder[0]);
@ -164,7 +164,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
}
/**
* Returns the wrapped {@link SurfaceTexture}. This can only be called after {@link #init(int)}.
* Returns the wrapped {@link SurfaceTexture}. This can only be called after {@link #init(int, EGLContext)}.
*/
public SurfaceTexture getSurfaceTexture() {
return Assertions.checkNotNull(texture);
@ -232,7 +232,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
}
private static EGLContext createEGLContext(
EGLDisplay display, EGLConfig config, @SecureMode int secureMode) throws GlUtil.GlException {
EGLDisplay display, EGLConfig config, @SecureMode int secureMode, EGLContext eglContext) throws GlUtil.GlException {
int[] glAttributes;
if (secureMode == SECURE_MODE_NONE) {
glAttributes = new int[] {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
@ -248,7 +248,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
}
EGLContext context =
EGL14.eglCreateContext(
display, config, android.opengl.EGL14.EGL_NO_CONTEXT, glAttributes, 0);
display, config, eglContext == null ? android.opengl.EGL14.EGL_NO_CONTEXT : eglContext, glAttributes, 0);
GlUtil.checkGlException(context != null, "eglCreateContext failed");
return context;
}

View file

@ -34,6 +34,7 @@ import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.opengl.EGLContext;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@ -123,6 +124,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private static boolean deviceNeedsSetOutputSurfaceWorkaround;
private final Context context;
public EGLContext eglContext;
private final VideoFrameReleaseHelper frameReleaseHelper;
private final EventDispatcher eventDispatcher;
private final long allowedJoiningTimeMs;
@ -207,6 +209,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
int maxDroppedFramesToNotify) {
this(
context,
null,
MediaCodecAdapter.Factory.DEFAULT,
mediaCodecSelector,
allowedJoiningTimeMs,
@ -241,6 +244,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
int maxDroppedFramesToNotify) {
this(
context,
null,
MediaCodecAdapter.Factory.DEFAULT,
mediaCodecSelector,
allowedJoiningTimeMs,
@ -269,6 +273,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
*/
public MediaCodecVideoRenderer(
Context context,
EGLContext parentContext,
MediaCodecAdapter.Factory codecAdapterFactory,
MediaCodecSelector mediaCodecSelector,
long allowedJoiningTimeMs,
@ -279,6 +284,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
this(
context,
parentContext,
codecAdapterFactory,
mediaCodecSelector,
allowedJoiningTimeMs,
@ -312,6 +318,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
*/
public MediaCodecVideoRenderer(
Context context,
EGLContext parentContext,
MediaCodecAdapter.Factory codecAdapterFactory,
MediaCodecSelector mediaCodecSelector,
long allowedJoiningTimeMs,
@ -329,6 +336,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.context = context.getApplicationContext();
this.eglContext = parentContext;
frameReleaseHelper = new VideoFrameReleaseHelper(this.context);
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
deviceNeedsNoPostProcessWorkaround = deviceNeedsNoPostProcessWorkaround();
@ -674,7 +682,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} else {
MediaCodecInfo codecInfo = getCodecInfo();
if (codecInfo != null && shouldUsePlaceholderSurface(codecInfo)) {
placeholderSurface = PlaceholderSurface.newInstanceV17(context, codecInfo.secure);
placeholderSurface = PlaceholderSurface.newInstanceV17(context, codecInfo.secure, eglContext);
surface = placeholderSurface;
}
}
@ -739,8 +747,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
MediaCodecInfo codecInfo,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
if (placeholderSurface != null && placeholderSurface.secure != codecInfo.secure) {
float codecOperatingRate,
EGLContext parentContext
) {
if (placeholderSurface != null && (placeholderSurface.secure != codecInfo.secure || placeholderSurface.parentContext != parentContext)) {
// We can't re-use the current DummySurface instance with the new decoder.
releasePlaceholderSurface();
}
@ -759,7 +769,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
throw new IllegalStateException();
}
if (placeholderSurface == null) {
placeholderSurface = PlaceholderSurface.newInstanceV17(context, codecInfo.secure);
placeholderSurface = PlaceholderSurface.newInstanceV17(context, codecInfo.secure, parentContext);
}
surface = placeholderSurface;
}

View file

@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.EGLSurfaceTexture.SECURE_MODE_S
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.EGLContext;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@ -43,6 +44,7 @@ public final class PlaceholderSurface extends Surface {
/** Whether the surface is secure. */
public final boolean secure;
public final EGLContext parentContext;
private static @SecureMode int secureMode;
private static boolean secureModeInitialized;
@ -76,17 +78,18 @@ public final class PlaceholderSurface extends Surface {
* @throws IllegalStateException If a secure surface is requested on a device for which {@link
* #isSecureSupported(Context)} returns {@code false}.
*/
public static PlaceholderSurface newInstanceV17(Context context, boolean secure) {
public static PlaceholderSurface newInstanceV17(Context context, boolean secure, EGLContext parentContext) {
Assertions.checkState(!secure || isSecureSupported(context));
PlaceholderSurfaceThread thread = new PlaceholderSurfaceThread();
return thread.init(secure ? secureMode : SECURE_MODE_NONE);
return thread.init(secure ? secureMode : SECURE_MODE_NONE, parentContext);
}
private PlaceholderSurface(
PlaceholderSurfaceThread thread, SurfaceTexture surfaceTexture, boolean secure) {
PlaceholderSurfaceThread thread, SurfaceTexture surfaceTexture, boolean secure, EGLContext parentContext) {
super(surfaceTexture);
this.thread = thread;
this.secure = secure;
this.parentContext = parentContext;
}
@Override
@ -135,13 +138,13 @@ public final class PlaceholderSurface extends Surface {
super("ExoPlayer:PlaceholderSurface");
}
public PlaceholderSurface init(@SecureMode int secureMode) {
public PlaceholderSurface init(@SecureMode int secureMode, EGLContext parentContext) {
start();
handler = new Handler(getLooper(), /* callback= */ this);
eglSurfaceTexture = new EGLSurfaceTexture(handler);
boolean wasInterrupted = false;
synchronized (this) {
handler.obtainMessage(MSG_INIT, secureMode, 0).sendToTarget();
handler.obtainMessage(MSG_INIT, secureMode, 0, parentContext).sendToTarget();
while (surface == null && initException == null && initError == null) {
try {
wait();
@ -173,7 +176,7 @@ public final class PlaceholderSurface extends Surface {
switch (msg.what) {
case MSG_INIT:
try {
initInternal(/* secureMode= */ msg.arg1);
initInternal(/* secureMode= */ msg.arg1, msg.obj == null ? null : (EGLContext) msg.obj);
} catch (RuntimeException e) {
Log.e(TAG, "Failed to initialize placeholder surface", e);
initException = e;
@ -203,12 +206,12 @@ public final class PlaceholderSurface extends Surface {
}
}
private void initInternal(@SecureMode int secureMode) throws GlUtil.GlException {
private void initInternal(@SecureMode int secureMode, EGLContext parentContext) throws GlUtil.GlException {
Assertions.checkNotNull(eglSurfaceTexture);
eglSurfaceTexture.init(secureMode);
eglSurfaceTexture.init(secureMode, parentContext);
this.surface =
new PlaceholderSurface(
this, eglSurfaceTexture.getSurfaceTexture(), secureMode != SECURE_MODE_NONE);
this, eglSurfaceTexture.getSurfaceTexture(), secureMode != SECURE_MODE_NONE, parentContext);
}
private void releaseInternal() {

View file

@ -4881,6 +4881,10 @@ public class AndroidUtilities {
return -1;
}
public static float distance(float x1, float y1, float x2, float y2) {
return (float) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
public static int lerp(int a, int b, float f) {
return (int) (a + f * (b - a));
}
@ -5861,6 +5865,10 @@ public class AndroidUtilities {
return Math.max(x1, x2) > Math.min(y1, y2) && Math.max(y1, y2) > Math.min(x1, x2);
}
public static boolean intersect1d(float x1, float x2, float y1, float y2) {
return Math.max(x1, x2) > Math.min(y1, y2) && Math.max(y1, y2) > Math.min(x1, x2);
}
public static boolean intersect1dInclusive(int x1, int x2, int y1, int y2) {
return Math.max(x1, x2) >= Math.min(y1, y2) && Math.max(y1, y2) >= Math.min(x1, x2);
}

View file

@ -2271,13 +2271,13 @@ public class LocaleController {
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear && useToday) {
return LocaleController.formatString("TodayAtFormattedWithToday", R.string.TodayAtFormattedWithToday, getInstance().getFormatterDay().format(new Date(date)));
return LocaleController.formatString(R.string.TodayAtFormattedWithToday, getInstance().getFormatterDay().format(new Date(date)));
} else if (dateDay + 1 == day && year == dateYear && useToday) {
return LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().getFormatterDay().format(new Date(date)));
return LocaleController.formatString(R.string.YesterdayAtFormatted, getInstance().getFormatterDay().format(new Date(date)));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().getChatDate().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
return LocaleController.formatString(R.string.formatDateAtTime, getInstance().getChatDate().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
} else {
return LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, getInstance().getChatFullDate().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
return LocaleController.formatString(R.string.formatDateAtTime, getInstance().getChatFullDate().format(new Date(date)), getInstance().getFormatterDay().format(new Date(date)));
}
} catch (Exception e) {
FileLog.e(e);

View file

@ -48,6 +48,9 @@ import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.MediaStore;
@ -5602,24 +5605,30 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private static class VideoConvertRunnable implements Runnable {
private VideoConvertMessage convertMessage;
private final VideoConvertMessage convertMessage;
private final Handler handler;
private VideoConvertRunnable(VideoConvertMessage message) {
convertMessage = message;
private VideoConvertRunnable(VideoConvertMessage message, Handler handler) {
this.convertMessage = message;
this.handler = handler;
}
@Override
public void run() {
MediaController.getInstance().convertVideo(convertMessage);
MediaController.getInstance().convertVideo(convertMessage, handler);
}
public static void runConversion(final VideoConvertMessage obj) {
HandlerThread handlerThread = new HandlerThread("VideoConvertRunnableThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
new Thread(() -> {
try {
VideoConvertRunnable wrapper = new VideoConvertRunnable(obj);
VideoConvertRunnable wrapper = new VideoConvertRunnable(obj, handler);
Thread th = new Thread(wrapper, "VideoConvertRunnable");
th.start();
th.join();
handlerThread.join();
} catch (Exception e) {
FileLog.e(e);
}
@ -5628,7 +5637,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
private boolean convertVideo(final VideoConvertMessage convertMessage) {
private boolean convertVideo(final VideoConvertMessage convertMessage, final Handler handler) {
MessageObject messageObject = convertMessage.messageObject;
VideoEditedInfo info = convertMessage.videoEditedInfo;
if (messageObject == null || info == null) {
@ -5734,7 +5743,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
callback,
info);
convertVideoParams.soundInfos.addAll(info.mixedSoundInfos);
boolean error = videoConvertor.convertVideo(convertVideoParams);
boolean error = videoConvertor.convertVideo(convertVideoParams, handler);
boolean canceled = info.canceled;

View file

@ -6220,7 +6220,9 @@ public class MediaDataController extends BaseController {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
messageObject.generateGameMessageText(null);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
messageObject.generatePaymentSentMessageText(null);
messageObject.generatePaymentSentMessageText(null, false);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
messageObject.generatePaymentSentMessageText(null, true);
}
break;
}
@ -6690,7 +6692,9 @@ public class MediaDataController extends BaseController {
} else if (m.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
m.generateGameMessageText(null);
} else if (m.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
m.generatePaymentSentMessageText(null);
m.generatePaymentSentMessageText(null, false);
} else if (m.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
m.generatePaymentSentMessageText(null, true);
}
}
changed = true;
@ -9648,4 +9652,92 @@ public class MediaDataController extends BaseController {
}
}
}
public static class SearchStickersKey {
public final boolean emojis;
public final String lang_code;
public final String q;
public SearchStickersKey(boolean emojis, String lang_code, String q) {
this.emojis = emojis;
this.lang_code = lang_code;
this.q = q;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SearchStickersKey that = (SearchStickersKey) o;
return emojis == that.emojis && Objects.equals(lang_code, that.lang_code) && Objects.equals(q, that.q);
}
@Override
public int hashCode() {
return Objects.hash(emojis, lang_code, q);
}
}
private static class SearchStickersResult {
public final ArrayList<TLRPC.Document> documents = new ArrayList<>();
public Integer next_offset;
public void apply(TLRPC.TL_messages_foundStickers r) {
documents.addAll(r.stickers);
next_offset = (r.flags & 1) != 0 ? r.next_offset : null;
}
}
private final HashMap<SearchStickersKey, Integer> loadingSearchStickersKeys = new HashMap<>();
private final android.util.LruCache<SearchStickersKey, SearchStickersResult> searchStickerResults = new android.util.LruCache<>(25);
public SearchStickersKey searchStickers(boolean emojis, String lang_code, String q, Utilities.Callback<ArrayList<TLRPC.Document>> whenDone) {
return searchStickers(emojis, lang_code, q, whenDone, false);
}
public SearchStickersKey searchStickers(boolean emojis, String lang_code, String q, Utilities.Callback<ArrayList<TLRPC.Document>> whenDone, boolean next) {
if (whenDone == null) return null;
final SearchStickersKey key = new SearchStickersKey(emojis, lang_code, q);
SearchStickersResult cached = searchStickerResults.get(key);
if ((cached == null || cached.next_offset != null && next) && !loadingSearchStickersKeys.containsKey(key)) {
loadingSearchStickersKeys.put(key, 0);
MediaDataController.getInstance(currentAccount).getEmojiSuggestions(new String[]{lang_code}, q, true, (result, a) -> {
if (!loadingSearchStickersKeys.containsKey(key)) return;
StringBuilder s = new StringBuilder();
for (KeywordResult r : result) {
if (!TextUtils.isEmpty(r.emoji) && !r.emoji.startsWith("animated_")) {
s.append(r.emoji);
}
}
TLRPC.TL_messages_searchStickers req = new TLRPC.TL_messages_searchStickers();
req.emojis = key.emojis;
if (!TextUtils.isEmpty(key.lang_code)) {
req.lang_code.add(key.lang_code);
}
req.emoticon = s.toString();
req.q = key.q;
req.limit = 50;
req.offset = cached == null ? 0 : cached.next_offset;
final int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
loadingSearchStickersKeys.remove(key);
SearchStickersResult finalResult = cached != null ? cached : new SearchStickersResult();
if (res instanceof TLRPC.TL_messages_foundStickers) {
finalResult.apply((TLRPC.TL_messages_foundStickers) res);
}
searchStickerResults.put(key, finalResult);
whenDone.run(finalResult.documents);
}));
loadingSearchStickersKeys.put(key, reqId);
}, false);
} else if (cached != null) {
whenDone.run(cached.documents);
} else {
whenDone.run(new ArrayList<>());
}
return key;
}
public void cancelSearchStickers(SearchStickersKey key) {
if (key == null) return;
final Integer reqId = loadingSearchStickersKeys.remove(key);
if (reqId != null && reqId != 0) {
getConnectionsManager().cancelRequest(reqId, true);
}
}
}

View file

@ -3533,16 +3533,11 @@ public class MessageObject {
return !(replyMessageObject == null || replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear || replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate);
}
public void generatePaymentSentMessageText(TLRPC.User fromUser) {
public void generatePaymentSentMessageText(TLRPC.User fromUser, boolean me) {
if (fromUser == null) {
fromUser = MessagesController.getInstance(currentAccount).getUser(getDialogId());
}
String name;
if (fromUser != null) {
name = UserObject.getFirstName(fromUser);
} else {
name = "";
}
final String name = fromUser != null ? UserObject.getFirstName(fromUser) : "";
String currency;
try {
if (StarsController.currency.equals(messageOwner.action.currency)) {
@ -3555,16 +3550,28 @@ public class MessageObject {
FileLog.e(e);
}
if (replyMessageObject != null && getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaInvoice) {
if (messageOwner.action.recurring_init) {
if (messageOwner.action.subscription_until_date != 0) {
if (me) {
messageText = formatString(R.string.PaymentSuccessfullyPaidMeSubscription, name, currency, getMedia(replyMessageObject).title, LocaleController.formatDateTime(messageOwner.action.subscription_until_date, false));
} else {
messageText = formatString(R.string.PaymentSuccessfullyPaidSubscription, currency, name, getMedia(replyMessageObject).title, LocaleController.formatDateTime(messageOwner.action.subscription_until_date, false));
}
} else if (messageOwner.action.recurring_init && !me) {
messageText = formatString(R.string.PaymentSuccessfullyPaidRecurrent, currency, name, getMedia(replyMessageObject).title);
} else {
messageText = formatString("PaymentSuccessfullyPaid", R.string.PaymentSuccessfullyPaid, currency, name, getMedia(replyMessageObject).title);
messageText = formatString(R.string.PaymentSuccessfullyPaid, currency, name, getMedia(replyMessageObject).title);
}
} else {
if (messageOwner.action.recurring_init) {
if (messageOwner.action.subscription_until_date != 0) {
if (me) {
messageText = formatString(R.string.PaymentSuccessfullyPaidMeNoItemSubscription, name, currency, LocaleController.formatDateTime(messageOwner.action.subscription_until_date, false));
} else {
messageText = formatString(R.string.PaymentSuccessfullyPaidSubscriptionNoItem, currency, name, LocaleController.formatDateTime(messageOwner.action.subscription_until_date, false));
}
} else if (messageOwner.action.recurring_init && !me) {
messageText = formatString(R.string.PaymentSuccessfullyPaidNoItemRecurrent, currency, name);
} else {
messageText = formatString("PaymentSuccessfullyPaidNoItem", R.string.PaymentSuccessfullyPaidNoItem, currency, name);
messageText = formatString(R.string.PaymentSuccessfullyPaidNoItem, currency, name);
}
}
messageText = StarsIntroActivity.replaceStars(messageText);
@ -4414,17 +4421,31 @@ public class MessageObject {
messageText = replaceWithLink(AndroidUtilities.replaceTags(LocaleController.formatPluralStringComma("ActionStarGiveawayPrize", (int) action.stars)), "un1", chat);
} else if (messageOwner.action instanceof TLRPC.TL_messageActionStarGift) {
TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) messageOwner.action;
int stars = 0;
if (action.gift != null) {
stars = (int) action.gift.stars;
}
if (fromObject instanceof TLRPC.User && ((TLRPC.User) fromObject).self && !action.forceIn) {
TLRPC.User user = getUser(users, sUsers, messageOwner.peer_id.user_id);
messageText = replaceWithLink(AndroidUtilities.replaceTags(getString(R.string.ActionGiftOutbound)), "un1", user);
if (action.message != null && !TextUtils.isEmpty(action.message.text)) {
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(action.message.text);
addEntitiesToText(stringBuilder, action.message.entities, isOutOwner(), false, false, false);
messageTextShort = stringBuilder;
} else {
messageTextShort = getString(R.string.ActionStarGift);
}
} else if (fromObject instanceof TLRPC.User && UserObject.isService(((TLRPC.User) fromObject).id)) {
messageText = TextUtils.replace(AndroidUtilities.replaceTags(getString(R.string.ActionGiftInbound)), new String[] {"un1"}, new CharSequence[]{ getString(R.string.StarsTransactionUnknown) });
} else {
messageText = replaceWithLink(AndroidUtilities.replaceTags(getString(R.string.ActionGiftInbound)), "un1", fromObject);
if (action.message != null && !TextUtils.isEmpty(action.message.text)) {
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(action.message.text);
addEntitiesToText(stringBuilder, action.message.entities, isOutOwner(), false, false, false);
messageTextShort = stringBuilder;
} else {
messageTextShort = getString(R.string.ActionStarGift);
}
int stars = 0;
if (action.gift != null) {
stars = (int) action.gift.stars;
}
int i = messageText.toString().indexOf("un2");
if (i != -1) {
@ -4840,8 +4861,11 @@ public class MessageObject {
}
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
TLRPC.User user = getUser(users, sUsers, getDialogId());
generatePaymentSentMessageText(user);
final TLRPC.User user = getUser(users, sUsers, getDialogId());
generatePaymentSentMessageText(user, false);
} else if (messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
final TLRPC.User user = getUser(users, sUsers, getDialogId());
generatePaymentSentMessageText(user, true);
} else if (messageOwner.action instanceof TLRPC.TL_messageActionBotAllowed) {
String domain = ((TLRPC.TL_messageActionBotAllowed) messageOwner.action).domain;
TLRPC.BotApp botApp = ((TLRPC.TL_messageActionBotAllowed) messageOwner.action).app;

View file

@ -639,6 +639,11 @@ public class MessagesController extends BaseController implements NotificationCe
public float starsUsdSellRate1000;
public float starsUsdWithdrawRate1000;
public boolean sponsoredLinksInappAllow;
public Set<String> starrefStartParamPrefixes = new HashSet<>();
public boolean starrefProgramAllowed;
public boolean starrefConnectAllowed;
public int starrefMinCommissionPermille;
public int starrefMaxCommissionPermille;
public long paidReactionsAnonymousTime;
public Boolean paidReactionsAnonymous;
@ -1605,6 +1610,11 @@ public class MessagesController extends BaseController implements NotificationCe
starsUsdSellRate1000 = mainPreferences.getFloat("starsUsdSellRate1000", 2000);
starsUsdWithdrawRate1000 = mainPreferences.getFloat("starsUsdWithdrawRate1000", 1200);
sponsoredLinksInappAllow = mainPreferences.getBoolean("sponsoredLinksInappAllow", false);
starrefProgramAllowed = mainPreferences.getBoolean("starrefProgramAllowed", false);
starrefConnectAllowed = mainPreferences.getBoolean("starrefConnectAllowed", false);
starrefStartParamPrefixes = mainPreferences.getStringSet("starrefStartParamPrefixes", new HashSet<>(Arrays.asList("_tgr_")));
starrefMinCommissionPermille = mainPreferences.getInt("starrefMinCommissionPermille", 1);
starrefMaxCommissionPermille = mainPreferences.getInt("starrefMaxCommissionPermille", 400);
paidReactionsAnonymousTime = mainPreferences.getLong("paidReactionsAnonymousTime", 0);
paidReactionsAnonymous = mainPreferences.contains("paidReactionsAnonymous") && (System.currentTimeMillis() - paidReactionsAnonymousTime) < 1000 * 60 * 60 * 2 ? mainPreferences.getBoolean("paidReactionsAnonymous", false) : null;
scheduleTranscriptionUpdate();
@ -4288,6 +4298,25 @@ public class MessagesController extends BaseController implements NotificationCe
}
break;
}
case "starref_start_param_prefixes": {
HashSet<String> newPrefixes = new HashSet<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value;
for (int b = 0, N2 = array.value.size(); b < N2; b++) {
TLRPC.JSONValue val = array.value.get(b);
if (val instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val;
newPrefixes.add(string.value.toLowerCase());
}
}
}
if (!starrefStartParamPrefixes.equals(newPrefixes)) {
starrefStartParamPrefixes = newPrefixes;
editor.putStringSet("starrefStartParamPrefixes", starrefStartParamPrefixes);
changed = true;
}
break;
}
case "weather_search_username": {
if (value.value instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString str = (TLRPC.TL_jsonString) value.value;
@ -4406,6 +4435,50 @@ public class MessagesController extends BaseController implements NotificationCe
}
break;
}
case "starref_program_allowed": {
if (value.value instanceof TLRPC.TL_jsonBool) {
TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value;
if (bool.value != starrefProgramAllowed) {
starrefProgramAllowed = bool.value;
editor.putBoolean("starrefProgramAllowed", starrefProgramAllowed);
changed = true;
}
}
break;
}
case "starref_connect_allowed": {
if (value.value instanceof TLRPC.TL_jsonBool) {
TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value;
if (bool.value != starrefConnectAllowed) {
starrefConnectAllowed = bool.value;
editor.putBoolean("starrefConnectAllowed", starrefConnectAllowed);
changed = true;
}
}
break;
}
case "starref_min_commission_permille": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != starrefMinCommissionPermille) {
starrefMinCommissionPermille = (int) num.value;
editor.putInt("starrefMinCommissionPermille", starrefMinCommissionPermille);
changed = true;
}
}
break;
}
case "starref_max_commission_permille": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != starrefMaxCommissionPermille) {
starrefMaxCommissionPermille = (int) num.value;
editor.putInt("starrefMaxCommissionPermille", starrefMaxCommissionPermille);
changed = true;
}
}
break;
}
}
}
@ -10765,7 +10838,9 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (msg.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
msg.generateGameMessageText(null);
} else if (msg.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
msg.generatePaymentSentMessageText(null);
msg.generatePaymentSentMessageText(null, false);
} else if (msg.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
msg.generatePaymentSentMessageText(null, true);
}
break;
}
@ -22128,4 +22203,12 @@ public class MessagesController extends BaseController implements NotificationCe
return paidReactionsAnonymous;
}
public boolean shouldShowMoveCaptionHint() {
return getMainSettings().getInt("movecaptionhint", 0) < 24 || BuildVars.DEBUG_PRIVATE_VERSION;
}
public void incrementMoveCaptionHint() {
getMainSettings().edit().putInt("movecaptionhint", getMainSettings().getInt("movecaptionhint", 0) + 1).apply();
}
}

View file

@ -263,6 +263,8 @@ public class NotificationCenter {
public static final int starGiftSoldOut = totalEvents++;
public static final int updateStories = totalEvents++;
public static final int botDownloadsUpdate = totalEvents++;
public static final int channelSuggestedBotsUpdate = totalEvents++;
public static final int channelConnectedBotsUpdate = totalEvents++;
//global
public static final int pushMessagesUpdated = totalEvents++;

View file

@ -1802,7 +1802,7 @@ public class NotificationsController extends BaseController {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
String date = LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000));
return LocaleController.formatString(R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
return messageObject.messageText.toString();
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) {
return messageObject.messageText.toString();
@ -2431,7 +2431,7 @@ public class NotificationsController extends BaseController {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) {
String date = LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().getFormatterYear().format(((long) messageObject.messageOwner.date) * 1000), LocaleController.getInstance().getFormatterDay().format(((long) messageObject.messageOwner.date) * 1000));
msg = LocaleController.formatString(R.string.NotificationUnrecognizedDevice, getUserConfig().getCurrentUser().first_name, date, messageObject.messageOwner.action.title, messageObject.messageOwner.action.address);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
msg = messageObject.messageText.toString();
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionStarGift || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) {
msg = messageObject.messageText.toString();

View file

@ -28,6 +28,11 @@ public class UserNameResolver {
HashMap<String, ArrayList<Consumer<Long>>> resolvingConsumers = new HashMap<>();
public int resolve(String username, Consumer<Long> resolveConsumer) {
return resolve(username, null, resolveConsumer);
}
public int resolve(String username, String referrer, Consumer<Long> resolveConsumer) {
if (TextUtils.isEmpty(referrer)) {
CachedPeer cachedPeer = resolvedCache.get(username);
if (cachedPeer != null) {
if (System.currentTimeMillis() - cachedPeer.time < CACHE_TIME) {
@ -38,6 +43,7 @@ public class UserNameResolver {
resolvedCache.remove(username);
}
}
}
ArrayList<Consumer<Long>> consumers = resolvingConsumers.get(username);
if (consumers != null) {
@ -57,6 +63,10 @@ public class UserNameResolver {
} else {
TLRPC.TL_contacts_resolveUsername resolveUsername = new TLRPC.TL_contacts_resolveUsername();
resolveUsername.username = username;
if (!TextUtils.isEmpty(referrer)) {
resolveUsername.flags |= 1;
resolveUsername.referer = referrer;
}
req = resolveUsername;
}
return ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
@ -65,6 +75,12 @@ public class UserNameResolver {
return;
}
if (error != null) {
if (error != null && error.text != null && "STARREF_EXPIRED".equals(error.text)) {
for (int i = 0; i < finalConsumers.size(); i++) {
finalConsumers.get(i).accept(Long.MAX_VALUE);
}
return;
}
for (int i = 0; i < finalConsumers.size(); i++) {
finalConsumers.get(i).accept(null);
}

View file

@ -11,12 +11,16 @@ package org.telegram.messenger;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.text.TextUtils;
import android.view.View;
import org.telegram.messenger.video.MediaCodecPlayer;
import org.telegram.messenger.video.MediaCodecVideoConvertor;
import org.telegram.messenger.video.VideoPlayerHolderBase;
import org.telegram.tgnet.AbstractSerializedData;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.Components.AnimatedFileDrawable;
@ -25,11 +29,17 @@ import org.telegram.ui.Components.Paint.Views.LinkPreview;
import org.telegram.ui.Components.PhotoFilterView;
import org.telegram.ui.Components.Point;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.VideoPlayer;
import org.telegram.ui.Stories.recorder.CollageLayout;
import org.telegram.ui.Stories.recorder.StoryEntry;
import org.telegram.ui.Stories.recorder.Weather;
import java.io.File;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
public class VideoEditedInfo {
@ -66,6 +76,9 @@ public class VideoEditedInfo {
public boolean isStory;
public StoryEntry.HDRInfo hdrInfo;
public CollageLayout collage;
public ArrayList<Part> collageParts;
public boolean isSticker;
public Bitmap thumb;
@ -83,7 +96,6 @@ public class VideoEditedInfo {
public boolean videoConvertFirstWrite;
public boolean needUpdateProgress = false;
public boolean shouldLimitFps = true;
public boolean tryUseHevc = false;
public boolean fromCamera;
public ArrayList<MediaCodecVideoConvertor.MixedSoundInfo> mixedSoundInfos = new ArrayList<>();
@ -416,7 +428,7 @@ public class VideoEditedInfo {
blurPathBytes = null;
}
SerializedData serializedData = new SerializedData(len);
serializedData.writeInt32(10);
serializedData.writeInt32(11);
serializedData.writeInt64(avatarStartTime);
serializedData.writeInt32(originalBitrate);
if (filterState != null) {
@ -509,6 +521,15 @@ public class VideoEditedInfo {
}
serializedData.writeFloat(volume);
serializedData.writeBool(isSticker);
if (collage != null && collageParts != null && collage.parts.size() > 1 && !collageParts.isEmpty()) {
serializedData.writeInt32(0xdeadbeef);
serializedData.writeString(collage.toString());
for (int i = 0; i < collageParts.size(); ++i) {
collageParts.get(i).serializeToStream(serializedData);
}
} else {
serializedData.writeInt32(TLRPC.TL_null.constructor);
}
filters = Utilities.bytesToHex(serializedData.toByteArray());
serializedData.cleanup();
} else {
@ -642,6 +663,19 @@ public class VideoEditedInfo {
if (version >= 10) {
isSticker = serializedData.readBool(false);
}
if (version >= 11) {
int magic = serializedData.readInt32(false);
if (magic == 0xdeadbeef) {
collage = new CollageLayout(serializedData.readString(false));
collageParts = new ArrayList<>();
for (int i = 0; i < collage.parts.size(); ++i) {
Part part = new Part();
part.part = collage.parts.get(i);
part.readParams(serializedData, false);
collageParts.add(part);
}
}
}
serializedData.cleanup();
}
} else {
@ -676,4 +710,115 @@ public class VideoEditedInfo {
public boolean canAutoPlaySourceVideo() {
return roundVideo;
}
public static class Part extends TLObject {
public int flags;
public boolean isVideo;
public boolean muted;
public String path;
public float volume = 1.0f;
public long offset = 0;
public boolean loop = true;
public float left, right;
public int width, height;
public long duration;
public CollageLayout.Part part;
public Part() {}
public Part(StoryEntry entry) {
isVideo = entry.isVideo;
muted = entry.muted;
path = entry.file.getAbsolutePath();
volume = entry.videoVolume;
loop = entry.videoLoop;
offset = entry.videoOffset;
left = entry.videoLeft;
right = entry.videoRight;
width = entry.width;
height = entry.height;
duration = entry.duration;
}
public static ArrayList<Part> toParts(StoryEntry collageEntry) {
if (collageEntry == null || collageEntry.collageContent == null)
return null;
final ArrayList<Part> parts = new ArrayList<>();
for (int i = 0; i < collageEntry.collageContent.size(); ++i) {
final StoryEntry entry = collageEntry.collageContent.get(i);
Part part = new Part(entry);
part.part = collageEntry.collage.parts.get(i);
parts.add(part);
}
return parts;
}
public static ArrayList<StoryEntry> toStoryEntries(ArrayList<Part> parts) {
if (parts == null) return null;
final ArrayList<StoryEntry> entries = new ArrayList<>();
for (Part part : parts) {
final StoryEntry entry = new StoryEntry();
entry.isVideo = part.isVideo;
entry.muted = part.muted;
entry.file = new File(part.path);
entry.videoVolume = part.volume;
entry.videoLoop = part.loop;
entry.videoOffset = part.offset;
entry.videoLeft = part.left;
entry.videoRight = part.right;
entry.width = part.width;
entry.height = part.height;
entry.duration = part.duration;
entries.add(entry);
}
return entries;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
isVideo = (flags & 1) != 0;
loop = (flags & 2) != 0;
muted = (flags & 4) != 0;
path = stream.readString(exception);
volume = stream.readFloat(exception);
offset = stream.readInt64(exception);
left = stream.readFloat(exception);
right = stream.readFloat(exception);
width = stream.readInt32(exception);
height = stream.readInt32(exception);
duration = stream.readInt64(exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
flags = isVideo ? flags | 1 : flags &~ 1;
flags = loop ? flags | 2 : flags &~ 2;
flags = muted ? flags | 4 : flags &~ 4;
stream.writeInt32(flags);
stream.writeString(path);
stream.writeFloat(volume);
stream.writeInt64(offset);
stream.writeFloat(left);
stream.writeFloat(right);
stream.writeInt32(width);
stream.writeInt32(height);
stream.writeInt64(duration);
}
public FloatBuffer posBuffer;
public FloatBuffer uvBuffer;
// software rendering
public AnimatedFileDrawable animatedFileDrawable;
public float currentFrame;
public float framesPerDraw;
public float msPerFrame;
// hardware rendering
public SurfaceTexture surfaceTexture;
public MediaCodecPlayer player;
}
}

View file

@ -8,6 +8,8 @@
package org.telegram.messenger.camera;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@ -21,6 +23,9 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.RenderEffect;
import android.graphics.RenderNode;
import android.graphics.Shader;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@ -89,7 +94,6 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
@SuppressLint("NewApi")
public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView, CameraController.ErrorCallback {
@ -97,6 +101,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
public boolean WRITE_TO_FILE_IN_BACKGROUND = false;
public boolean isStory;
public boolean recordHevc;
private float scaleX, scaleY;
private Size[] previewSize = new Size[2];
private Size[] pictureSize = new Size[2];
@ -104,7 +109,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private boolean mirror;
private boolean lazy;
private TextureView textureView;
private ImageView blurredStubView;
public ImageView blurredStubView;
private boolean inited;
private CameraViewDelegate delegate;
private int clipTop;
@ -398,10 +403,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
blurredStubView = new ImageView(context);
addView(blurredStubView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER));
blurredStubView.setVisibility(View.GONE);
focusAreaSize = AndroidUtilities.dp(96);
focusAreaSize = dp(96);
outerPaint.setColor(0xffffffff);
outerPaint.setStyle(Paint.Style.STROKE);
outerPaint.setStrokeWidth(AndroidUtilities.dp(2));
outerPaint.setStrokeWidth(dp(2));
innerPaint.setColor(0x7fffffff);
}
@ -671,6 +676,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
FileLog.d("CameraView " + "start create thread");
}
cameraThread = new CameraGLThread(surface);
if (blurTextureView != null) {
cameraThread.setBlurSurfaceTexture(blurTextureView.getSurfaceTexture());
}
checkPreviewMatrix();
}
}
@ -960,9 +968,30 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean result = super.drawChild(canvas, child, drawingTime);
Canvas c = canvas;
if (child == textureView && canvas.isHardwareAccelerated()) {
if (renderNode != null) {
RenderNode node = (RenderNode) renderNode;
node.setPosition(0, 0, getWidth(), getHeight());
c = node.beginRecording();
}
}
boolean result = super.drawChild(c, child, drawingTime);
if (child == textureView && canvas.isHardwareAccelerated()) {
if (renderNode != null) {
RenderNode node = (RenderNode) renderNode;
node.endRecording();
canvas.drawRenderNode(node);
if (blurRenderNode != null) {
RenderNode blurNode = (RenderNode) blurRenderNode;
blurNode.setPosition(0, 0, getWidth(), getHeight());
blurNode.beginRecording().drawRenderNode(node);
blurNode.endRecording();;
}
}
}
if (focusProgress != 1.0f || innerAlpha != 0.0f || outerAlpha != 0.0f) {
int baseRad = AndroidUtilities.dp(30);
int baseRad = dp(30);
long newTime = System.currentTimeMillis();
long dt = newTime - lastDrawTime;
if (dt < 0 || dt > 17) {
@ -1020,6 +1049,51 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
private Object renderNode;
private Object blurRenderNode;
public Object getBlurRenderNode() {
if (renderNode == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
renderNode = new RenderNode("CameraViewRenderNode");
blurRenderNode = new RenderNode("CameraViewRenderNodeBlur");
((RenderNode) blurRenderNode).setRenderEffect(RenderEffect.createBlurEffect(dp(32), dp(32), Shader.TileMode.DECAL));
}
return blurRenderNode;
}
private TextureView blurTextureView;
public TextureView makeBlurTextureView() {
if (blurTextureView == null) {
blurTextureView = new TextureView(getContext());
blurTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
if (cameraThread != null) {
cameraThread.setBlurSurfaceTexture(surface);
}
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
if (cameraThread != null) {
cameraThread.setBlurSurfaceTexture(null);
}
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
});
}
return blurTextureView;
}
@Override
protected void dispatchDraw(Canvas canvas) {
@ -1028,7 +1102,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
super.dispatchDraw(canvas);
if (takePictureProgress != 1f) {
takePictureProgress += 16 / 150f;
takePictureProgress += 16 / 250f;
if (takePictureProgress > 1f) {
takePictureProgress = 1f;
} else {
@ -1038,6 +1112,38 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
private final ArrayList<Runnable> invalidateListeners = new ArrayList<>();
public void listenDraw(Runnable listener) {
invalidateListeners.add(listener);
}
public void unlistenDraw(Runnable listener) {
invalidateListeners.remove(listener);
}
@Override
public void invalidate() {
super.invalidate();
for (Runnable l : invalidateListeners) {
l.run();
}
}
@Override
public void invalidate(Rect dirty) {
super.invalidate(dirty);
for (Runnable l : invalidateListeners) {
l.run();
}
}
@Override
public void invalidate(int l, int t, int r, int b) {
super.invalidate(l, t, r, b);
for (Runnable i : invalidateListeners) {
i.run();
}
}
private int videoWidth;
private int videoHeight;
@ -1048,9 +1154,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return videoHeight;
}
private int[] position = new int[2];
private int[][] cameraTexture = new int[2][1];
private int[] oldCameraTexture = new int[1];
private final int[][] cameraTexture = new int[2][1];
private VideoRecorder videoEncoder;
private volatile float pixelW, pixelH;
@ -1070,6 +1174,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private EGLConfig eglConfig;
private boolean initied;
private SurfaceTexture blurSurfaceTexture;
private EGLContext eglBlurContext;
private EGLSurface eglBlurSurface;
private boolean blurInited;
private int drawBlurProgram;
private int blurVertexMatrixHandle;
private int blurTextureMatrixHandle;
private int blurCameraMatrixHandle;
private int blurPositionHandle;
private int blurTextureHandle;
private int blurPixelHandle;
private final CameraSessionWrapper currentSession[] = new CameraSessionWrapper[2];
private final SurfaceTexture[] cameraSurface = new SurfaceTexture[2];
@ -1088,6 +1205,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private final int DO_DUAL_END = 10;
private final int BLUR_CAMERA1 = 11;
private final int DO_BLUR_TEXTURE = 12;
private int drawProgram;
private int vertexMatrixHandle;
private int textureMatrixHandle;
@ -1111,7 +1230,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private boolean recording;
private boolean needRecord;
private int cameraId[] = new int[] { -1, -1 };
private final int cameraId[] = new int[] { -1, -1 };
private final float[] verticesData = {
-1.0f, -1.0f, 0,
@ -1120,8 +1239,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
1.0f, 1.0f, 0
};
//private InstantCameraView.VideoRecorder videoEncoder;
public CameraGLThread(SurfaceTexture surface) {
super("CameraGLThread");
surfaceTexture = surface;
@ -1214,7 +1331,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
finish();
return false;
}
GL gl = eglContext.getGL();
android.opengl.Matrix.setIdentityM(mSTMatrix[0], 0);
@ -1334,6 +1450,65 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return true;
}
private boolean initBlurGL() {
if (!initied) {
return false;
}
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
eglBlurContext = egl10.eglCreateContext(eglDisplay, eglConfig, eglContext, attrib_list);
if (eglBlurContext == null || eglBlurContext == EGL10.EGL_NO_CONTEXT) {
eglBlurContext = null;
if (BuildVars.LOGS_ENABLED) {
FileLog.e("eglCreateContext (blur) failed " + GLUtils.getEGLErrorString(egl10.eglGetError()));
}
return false;
}
if (blurSurfaceTexture != null) {
eglBlurSurface = egl10.eglCreateWindowSurface(eglDisplay, eglConfig, blurSurfaceTexture, null);
} else {
finishBlur();
return false;
}
if (eglBlurSurface == null || eglBlurSurface == EGL10.EGL_NO_SURFACE) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("createWindowSurface failed " + GLUtils.getEGLErrorString(egl10.eglGetError()));
}
finishBlur();
return false;
}
if (!egl10.eglMakeCurrent(eglDisplay, eglBlurSurface, eglBlurSurface, eglBlurContext)) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError()));
}
finishBlur();
egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
return false;
}
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, AndroidUtilities.readRes(R.raw.camera_blur_vert));
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, AndroidUtilities.readRes(R.raw.camera_blur_frag));
if (vertexShader != 0 && fragmentShader != 0) {
drawBlurProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(drawBlurProgram, vertexShader);
GLES20.glAttachShader(drawBlurProgram, fragmentShader);
GLES20.glLinkProgram(drawBlurProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(drawBlurProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(drawBlurProgram);
drawBlurProgram = 0;
} else {
blurPositionHandle = GLES20.glGetAttribLocation(drawBlurProgram, "aPosition");
blurTextureHandle = GLES20.glGetAttribLocation(drawBlurProgram, "aTextureCoord");
blurVertexMatrixHandle = GLES20.glGetUniformLocation(drawBlurProgram, "uMVPMatrix");
blurTextureMatrixHandle = GLES20.glGetUniformLocation(drawBlurProgram, "uSTMatrix");
blurCameraMatrixHandle = GLES20.glGetUniformLocation(drawBlurProgram, "cameraMatrix");
blurPixelHandle = GLES20.glGetUniformLocation(drawBlurProgram, "pixelWH");
}
}
return true;
}
private void updTex(SurfaceTexture surfaceTexture) {
if (surfaceTexture == cameraSurface[0]) {
if (!ignoreCamera1Upd && System.currentTimeMillis() > camera1AppearedUntil) {
@ -1369,6 +1544,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
}
finishBlur();
if (eglSurface != null) {
egl10.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl10.eglDestroySurface(eglDisplay, eglSurface);
@ -1384,6 +1560,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
public void finishBlur() {
if (eglBlurSurface != null) {
egl10.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl10.eglDestroySurface(eglDisplay, eglBlurSurface);
eglBlurSurface = null;
}
if (eglBlurContext != null) {
egl10.eglDestroyContext(eglDisplay, eglBlurContext);
eglBlurContext = null;
}
blurInited = false;
}
public void setCurrentSession(CameraSessionWrapper session, int i) {
Handler handler = getHandler();
if (handler != null) {
@ -1492,6 +1681,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (crossfade <= 0) {
crossfading = false;
}
int drawnCameraTexture = -1;
for (int a = -1; a < 2; ++a) {
if (a == -1 && !crossfading) {
continue;
@ -1511,6 +1701,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glUseProgram(drawProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, cameraTexture[i][0]);
if (drawnCameraTexture == -1) {
drawnCameraTexture = cameraTexture[i][0];
}
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
@ -1541,14 +1734,14 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glUniform1f(shapeHandle, 0);
GLES20.glUniform1f(crossfadeHandle, 1);
} else if (!crossfading) {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.dp(16));
GLES20.glUniform1f(roundRadiusHandle, dp(16));
GLES20.glUniform1f(scaleHandle, dualScale);
GLES20.glUniform1f(shapeFromHandle, (float) Math.floor(shapeValue));
GLES20.glUniform1f(shapeToHandle, (float) Math.ceil(shapeValue));
GLES20.glUniform1f(shapeHandle, shapeValue - (float) Math.floor(shapeValue));
GLES20.glUniform1f(crossfadeHandle, 0);
} else {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.dp(16));
GLES20.glUniform1f(roundRadiusHandle, dp(16));
GLES20.glUniform1f(scaleHandle, 1f - crossfade);
GLES20.glUniform1f(shapeFromHandle, (float) Math.floor(shapeValue));
GLES20.glUniform1f(shapeToHandle, (float) Math.ceil(shapeValue));
@ -1559,7 +1752,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
} else {
GLES20.glUniform1f(alphaHandle, 1f);
if (crossfading) {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.lerp(AndroidUtilities.dp(12), AndroidUtilities.dp(16), crossfade));
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.lerp(dp(12), dp(16), crossfade));
GLES20.glUniform1f(scaleHandle, 1f);
GLES20.glUniform1f(shapeFromHandle, shapeTo);
GLES20.glUniform1f(shapeToHandle, 2);
@ -1585,6 +1778,42 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
egl10.eglSwapBuffers(eglDisplay, eglSurface);
if (blurSurfaceTexture != null && blurInited) {
boolean drawBlur = true;
if (!eglBlurContext.equals(egl10.eglGetCurrentContext()) || !eglBlurSurface.equals(egl10.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!egl10.eglMakeCurrent(eglDisplay, eglBlurSurface, eglBlurSurface, eglBlurContext)) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("eglMakeCurrent failed " + GLUtils.getEGLErrorString(egl10.eglGetError()));
}
drawBlur = false;
}
}
if (drawBlur && cameraSurface[0] != null) {
GLES20.glUseProgram(drawBlurProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, cameraTexture[0][0]);
GLES20.glVertexAttribPointer(blurPositionHandle, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);
GLES20.glEnableVertexAttribArray(blurPositionHandle);
GLES20.glVertexAttribPointer(blurTextureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(blurTextureHandle);
GLES20.glUniformMatrix4fv(blurCameraMatrixHandle, 1, false, cameraMatrix[0], 0);
GLES20.glUniformMatrix4fv(blurTextureMatrixHandle, 1, false, mSTMatrix[0], 0);
GLES20.glUniformMatrix4fv(blurVertexMatrixHandle, 1, false, mMVPMatrix[0], 0);
GLES20.glUniform2f(blurPixelHandle, pixelW, pixelH);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDisableVertexAttribArray(blurPositionHandle);
GLES20.glDisableVertexAttribArray(blurTextureHandle);
egl10.eglSwapBuffers(eglDisplay, eglBlurSurface);
}
}
synchronized (layoutLock) {
if (!firstFrameRendered && !waitingForCamera1) {
firstFrameRendered = true;
@ -1604,6 +1833,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
@Override
public void run() {
initied = initGL();
if (blurSurfaceTexture != null) {
blurInited = initBlurGL();
}
super.run();
}
@ -1616,6 +1848,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
onDraw(inputMessage.arg1, inputMessage.arg2, inputMessage.obj == updateTexBoth || inputMessage.obj == updateTex1, inputMessage.obj == updateTexBoth || inputMessage.obj == updateTex2);
break;
case DO_SHUTDOWN_MESSAGE:
finishBlur();
finish();
if (recording) {
videoEncoder.stopRecording(inputMessage.arg1);
@ -1808,6 +2041,18 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
requestRender(false, false);
break;
}
case DO_BLUR_TEXTURE: {
if (blurSurfaceTexture != inputMessage.obj) {
finishBlur();
blurSurfaceTexture = null;
}
if (inputMessage.obj != null && blurSurfaceTexture != inputMessage.obj) {
blurSurfaceTexture = (SurfaceTexture) inputMessage.obj;
blurInited = initBlurGL();
}
requestRender(false, false);
break;
}
}
}
@ -1838,16 +2083,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
FileLog.d("CameraView camera scaleX = " + scaleX + " scaleY = " + scaleY);
}
// private final float[] tempVertices = new float[6];
private void applyDualMatrix(Matrix matrix) {
// tempVertices[0] = tempVertices[1] = 0;
// tempVertices[2] = pixelW;
// tempVertices[3] = 0;
// tempVertices[4] = 0;
// tempVertices[5] = pixelH;
// matrix.mapPoints(tempVertices);
// pixelDualW = MathUtils.distance(tempVertices[0], tempVertices[1], tempVertices[2], tempVertices[3]);
// pixelDualH = MathUtils.distance(tempVertices[0], tempVertices[1], tempVertices[4], tempVertices[5]);
getValues(matrix, cameraMatrix[1]);
}
@ -1934,6 +2170,15 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
sendMessage(handler.obtainMessage(DO_STOP_RECORDING), 0);
}
}
public void setBlurSurfaceTexture(SurfaceTexture blurSurfaceTexture) {
Handler handler = getHandler();
if (handler != null) {
sendMessage(handler.obtainMessage(DO_BLUR_TEXTURE, blurSurfaceTexture), 0);
} else {
this.blurSurfaceTexture = blurSurfaceTexture;
}
}
}
private void onFirstFrameRendered(int i) {
@ -2510,14 +2755,14 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glUniform1f(shapeHandle, 0);
GLES20.glUniform1f(crossfadeHandle, 1);
} else if (!crossfading) {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.dp(16));
GLES20.glUniform1f(roundRadiusHandle, dp(16));
GLES20.glUniform1f(scaleHandle, 1f);
GLES20.glUniform1f(shapeFromHandle, (float) Math.floor(shapeValue));
GLES20.glUniform1f(shapeToHandle, (float) Math.ceil(shapeValue));
GLES20.glUniform1f(shapeHandle, shapeValue - (float) Math.floor(shapeValue));
GLES20.glUniform1f(crossfadeHandle, 0);
} else {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.dp(16));
GLES20.glUniform1f(roundRadiusHandle, dp(16));
GLES20.glUniform1f(scaleHandle, 1f - crossfade);
GLES20.glUniform1f(shapeFromHandle, (float) Math.floor(shapeValue));
GLES20.glUniform1f(shapeToHandle, (float) Math.ceil(shapeValue));
@ -2528,7 +2773,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
} else {
GLES20.glUniform1f(alphaHandle, 1f);
if (crossfading) {
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.lerp(AndroidUtilities.dp(12), AndroidUtilities.dp(16), crossfade));
GLES20.glUniform1f(roundRadiusHandle, AndroidUtilities.lerp(dp(12), dp(16), crossfade));
GLES20.glUniform1f(scaleHandle, 1f);
GLES20.glUniform1f(shapeFromHandle, lastShapeTo);
GLES20.glUniform1f(shapeToHandle, 2);
@ -2677,7 +2922,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
audioEncoder.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
audioEncoder.start();
boolean shouldUseHevc = isStory;
boolean shouldUseHevc = recordHevc;
outputMimeType = shouldUseHevc ? "video/hevc" : "video/avc";
try {
if (shouldUseHevc) {

View file

@ -321,103 +321,4 @@ public final class ExtendedDefaultDataSource implements DataSource {
dataSource.addTransferListener(listener);
}
}
private final Cache cache = new Cache() {
@Override
public long getUid() {
return 0;
}
@Override
public void release() {
}
@Override
public NavigableSet<CacheSpan> addListener(String key, Listener listener) {
return null;
}
@Override
public void removeListener(String key, Listener listener) {
}
@Override
public NavigableSet<CacheSpan> getCachedSpans(String key) {
return null;
}
@Override
public Set<String> getKeys() {
return null;
}
@Override
public long getCacheSpace() {
return 0;
}
@Override
public CacheSpan startReadWrite(String key, long position, long length) throws InterruptedException, CacheException {
return null;
}
@Nullable
@Override
public CacheSpan startReadWriteNonBlocking(String key, long position, long length) throws CacheException {
return null;
}
@Override
public File startFile(String key, long position, long length) throws CacheException {
return null;
}
@Override
public void commitFile(File file, long length) throws CacheException {
}
@Override
public void releaseHoleSpan(CacheSpan holeSpan) {
}
@Override
public void removeResource(String key) {
}
@Override
public void removeSpan(CacheSpan span) {
}
@Override
public boolean isCached(String key, long position, long length) {
return false;
}
@Override
public long getCachedLength(String key, long position, long length) {
return 0;
}
@Override
public long getCachedBytes(String key, long position, long length) {
return 0;
}
@Override
public void applyContentMetadataMutations(String key, ContentMetadataMutations mutations) throws CacheException {
}
@Override
public ContentMetadata getContentMetadata(String key) {
return null;
}
};
}

View file

@ -111,6 +111,10 @@ public class InputSurface {
}
}
public EGLContext getContext() {
return mEGLContext;
}
public boolean swapBuffers() {
return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
}

View file

@ -0,0 +1,139 @@
package org.telegram.messenger.video;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;
import java.io.IOException;
import java.nio.ByteBuffer;
public class MediaCodecPlayer {
private final MediaExtractor extractor;
private final MediaCodec codec;
private final Surface outputSurface;
private final int w, h, o;
public MediaCodecPlayer(String videoPath, Surface surface) throws IOException {
this.outputSurface = surface;
this.extractor = new MediaExtractor();
// Set up the extractor to read the video file
extractor.setDataSource(videoPath);
MediaFormat videoFormat = null;
int videoTrackIndex = -1;
// Find the video track
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mimeType = format.getString(MediaFormat.KEY_MIME);
if (mimeType.startsWith("video/")) {
videoTrackIndex = i;
videoFormat = format;
break;
}
}
if (videoTrackIndex == -1 || videoFormat == null) {
throw new IllegalArgumentException("No video track found in file.");
}
extractor.selectTrack(videoTrackIndex);
w = videoFormat.getInteger(MediaFormat.KEY_WIDTH);
h = videoFormat.getInteger(MediaFormat.KEY_HEIGHT);
if (videoFormat.containsKey(MediaFormat.KEY_ROTATION)) {
o = videoFormat.getInteger(MediaFormat.KEY_ROTATION);
} else {
o = 0;
}
codec = MediaCodec.createDecoderByType(videoFormat.getString(MediaFormat.KEY_MIME));
codec.configure(videoFormat, surface, null, 0);
codec.start();
}
public int getWidth() {
return w;
}
public int getOrientedWidth() {
return (o / 90) % 2 == 1 ? h : w;
}
public int getHeight() {
return h;
}
public int getOrientedHeight() {
return (o / 90) % 2 == 1 ? w : h;
}
public int getOrientation() {
return o;
}
private boolean done;
private boolean first = true;
private long lastPositionUs = 0;
public boolean ensure(long ms) {
if (done) return false;
final boolean first = this.first;
this.first = false;
final long us = ms * 1000;
if (!first && us <= lastPositionUs) {
return false;
}
if (extractor.getSampleTime() > us || first && us > 1000 * 1000) {
extractor.seekTo(us, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
}
while (true) {
int inputBufferIndex = codec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex);
if (inputBuffer != null) {
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize > 0) {
long sampleTime = extractor.getSampleTime();
codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, sampleTime, extractor.getSampleFlags());
extractor.advance();
} else {
codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
release();
return false;
}
}
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
if (outputBufferIndex >= 0) {
if (bufferInfo.presentationTimeUs >= us - 16 * 1000) {
lastPositionUs = bufferInfo.presentationTimeUs;
codec.releaseOutputBuffer(outputBufferIndex, true);
return true;
} else {
codec.releaseOutputBuffer(outputBufferIndex, false);
}
}
}
}
public void release() {
if (done) return;
done = true;
if (codec != null) {
codec.stop();
codec.release();
}
if (extractor != null) {
extractor.release();
}
}
}

View file

@ -7,6 +7,9 @@ import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
@ -21,6 +24,7 @@ import org.telegram.messenger.VideoEditedInfo;
import org.telegram.messenger.video.audio_input.AudioInput;
import org.telegram.messenger.video.audio_input.BlankAudioInput;
import org.telegram.messenger.video.audio_input.GeneralAudioInput;
import org.telegram.ui.Stories.recorder.CollageLayout;
import org.telegram.ui.Stories.recorder.StoryEntry;
import java.io.File;
@ -48,12 +52,12 @@ public class MediaCodecVideoConvertor {
private static final int MEDIACODEC_TIMEOUT_INCREASED = 22000;
private String outputMimeType;
public boolean convertVideo(ConvertVideoParams convertVideoParams) {
public boolean convertVideo(ConvertVideoParams convertVideoParams, Handler handler) {
if (convertVideoParams.isSticker) {
return WebmEncoder.convert(convertVideoParams, 0);
}
this.callback = convertVideoParams.callback;
return convertVideoInternal(convertVideoParams, false, 0);
return convertVideoInternal(convertVideoParams, false, 0, handler);
}
public long getLastFrameTimestamp() {
@ -61,9 +65,12 @@ public class MediaCodecVideoConvertor {
}
@TargetApi(18)
private boolean convertVideoInternal(ConvertVideoParams convertVideoParams,
private boolean convertVideoInternal(
ConvertVideoParams convertVideoParams,
boolean increaseTimeout,
int triesCount) {
int triesCount,
Handler handler
) {
String videoPath = convertVideoParams.videoPath;
File cacheFile = convertVideoParams.cacheFile;
int rotationValue = convertVideoParams.rotationValue;
@ -178,7 +185,7 @@ public class MediaCodecVideoConvertor {
inputSurface.makeCurrent();
encoder.start();
outputSurface = new OutputSurface(savedFilterState, videoPath, paintPath, blurPath, mediaEntities, cropState != null && cropState.useMatrix != null ? cropState : null, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, true, gradientTopColor, gradientBottomColor, null, convertVideoParams);
outputSurface = new OutputSurface(inputSurface.getContext(), savedFilterState, videoPath, paintPath, blurPath, mediaEntities, cropState != null && cropState.useMatrix != null ? cropState : null, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, true, gradientTopColor, gradientBottomColor, null, convertVideoParams, handler);
ByteBuffer[] encoderOutputBuffers = null;
ByteBuffer[] encoderInputBuffers = null;
@ -511,7 +518,7 @@ public class MediaCodecVideoConvertor {
}
}
outputSurface = new OutputSurface(savedFilterState, null, paintPath, blurPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false, gradientTopColor, gradientBottomColor, hdrInfo, convertVideoParams);
outputSurface = new OutputSurface(inputSurface.getContext(), savedFilterState, null, paintPath, blurPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false, gradientTopColor, gradientBottomColor, hdrInfo, convertVideoParams, handler);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && hdrInfo != null && hdrInfo.getHDRType() != 0) {
outputSurface.changeFragmentShader(
hdrFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, true, hdrInfo),
@ -956,18 +963,17 @@ public class MediaCodecVideoConvertor {
}
if (repeatWithIncreasedTimeout) {
return convertVideoInternal(convertVideoParams, true, triesCount + 1);
return convertVideoInternal(convertVideoParams, true, triesCount + 1, handler);
}
if (error && canBeBrokenEncoder && triesCount < 3) {
return convertVideoInternal(convertVideoParams, increaseTimeout, triesCount + 1);
return convertVideoInternal(convertVideoParams, increaseTimeout, triesCount + 1, handler);
}
long timeLeft = System.currentTimeMillis() - time;
if (BuildVars.LOGS_ENABLED) {
FileLog.d("compression completed time=" + timeLeft + " needCompress=" + needCompress + " w=" + resultWidth + " h=" + resultHeight + " bitrate=" + bitrate + " file size=" + AndroidUtilities.formatFileSize(cacheFile.length()) + " encoder_name=" + selectedEncoderName);
}
return error;
}
@ -975,7 +981,13 @@ public class MediaCodecVideoConvertor {
if (soundInfos == null) return;
for (int i = 0; i < soundInfos.size(); i++) {
MixedSoundInfo soundInfo = soundInfos.get(i);
GeneralAudioInput secondAudio = new GeneralAudioInput(soundInfo.audioFile);
GeneralAudioInput secondAudio;
try {
secondAudio = new GeneralAudioInput(soundInfo.audioFile);
} catch (Exception e) {
FileLog.e(e);
continue;
}
secondAudio.setVolume(soundInfo.volume);
long startTimeLocal = 0;
if (soundInfo.startTime > 0) {
@ -1444,6 +1456,8 @@ public class MediaCodecVideoConvertor {
boolean isDark;
long wallpaperPeerId;
boolean isSticker;
CollageLayout collage;
ArrayList<VideoEditedInfo.Part> collageParts;
private ConvertVideoParams() {
@ -1496,6 +1510,8 @@ public class MediaCodecVideoConvertor {
params.messageVideoMaskPath = info.messageVideoMaskPath;
params.backgroundPath = info.backgroundPath;
params.isSticker = info.isSticker;
params.collage = info.collage;
params.collageParts = info.collageParts;
return params;
}
}

View file

@ -9,7 +9,13 @@
package org.telegram.messenger.video;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.EGLConfig;
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
import android.opengl.GLES20;
import android.os.Handler;
import android.view.Surface;
import org.telegram.messenger.FileLog;
@ -18,12 +24,9 @@ import org.telegram.messenger.VideoEditedInfo;
import org.telegram.ui.Stories.recorder.StoryEntry;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
@ -39,70 +42,130 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private boolean mFrameAvailable;
private TextureRenderer mTextureRender;
public OutputSurface(MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, String blurPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, MediaController.CropState cropState, int w, int h, int originalW, int originalH, int rotation, float fps, boolean photo, Integer gradientTopColor, Integer gradientBottomColor, StoryEntry.HDRInfo hdrInfo, MediaCodecVideoConvertor.ConvertVideoParams params) {
mTextureRender = new TextureRenderer(savedFilterState, imagePath, paintPath, blurPath, mediaEntities, cropState, w, h, originalW, originalH, rotation, fps, photo, gradientTopColor, gradientBottomColor, hdrInfo, params);
private android.opengl.EGLContext parentContext;
private Handler handler;
public OutputSurface(android.opengl.EGLContext context, MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, String blurPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, MediaController.CropState cropState, int w, int h, int originalW, int originalH, int rotation, float fps, boolean photo, Integer gradientTopColor, Integer gradientBottomColor, StoryEntry.HDRInfo hdrInfo, MediaCodecVideoConvertor.ConvertVideoParams params, Handler handler) {
this.parentContext = context;
this.handler = handler;
final CountDownLatch latch = new CountDownLatch(1);
handler.post(() -> {
setupBackground(context);
latch.countDown();
});
try {
latch.await();
} catch (Exception e) {
FileLog.e(e);
}
mTextureRender = new TextureRenderer(savedFilterState, imagePath, paintPath, blurPath, mediaEntities, cropState, w, h, originalW, originalH, rotation, fps, photo, gradientTopColor, gradientBottomColor, hdrInfo, params, handler, bgEGLContext);
mTextureRender.surfaceCreated();
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
mSurfaceTexture.setOnFrameAvailableListener(this);
mSurface = new Surface(mSurfaceTexture);
}
private void eglSetup(int width, int height) {
mEGL = (EGL10) EGLContext.getEGL();
mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {
throw new RuntimeException("unable to get EGL10 display");
private EGLDisplay bgEGLDisplay;
private EGLContext bgEGLContext;
private void setupBackground(EGLContext ctx) {
bgEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if (bgEGLDisplay == EGL14.EGL_NO_DISPLAY) {
throw new RuntimeException("unable to get EGL14 display");
}
if (!mEGL.eglInitialize(mEGLDisplay, null)) {
mEGLDisplay = null;
throw new RuntimeException("unable to initialize EGL10");
int[] version = new int[2];
if (!EGL14.eglInitialize(bgEGLDisplay, version, 0, version, 1)) {
bgEGLDisplay = null;
throw new RuntimeException("unable to initialize EGL14");
}
int[] attribList = {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL10.EGL_NONE
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, configs.length, numConfigs)) {
throw new RuntimeException("unable to find RGB888+pbuffer EGL config");
if (!EGL14.eglChooseConfig(bgEGLDisplay, attribList, 0, configs, 0, configs.length,
numConfigs, 0)) {
throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
}
int[] attrib_list = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL10.EGL_NONE
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT, attrib_list);
bgEGLContext = EGL14.eglCreateContext(bgEGLDisplay, configs[0], ctx, attrib_list, 0);
checkEglError("eglCreateContext");
if (mEGLContext == null) {
if (bgEGLContext == null) {
throw new RuntimeException("null context");
}
int[] surfaceAttribs = {
EGL10.EGL_WIDTH, width,
EGL10.EGL_HEIGHT, height,
EGL10.EGL_NONE
};
mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs);
checkEglError("eglCreatePbufferSurface");
if (mEGLSurface == null) {
throw new RuntimeException("surface was null");
checkEglError("before makeCurrent");
if (!EGL14.eglMakeCurrent(bgEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, bgEGLContext)) {
throw new RuntimeException("eglMakeCurrent failed");
}
}
// private void eglSetup(int width, int height) {
// mEGL = (EGL10) EGLContext.getEGL();
// mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
//
// if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {
// throw new RuntimeException("unable to get EGL10 display");
// }
//
// if (!mEGL.eglInitialize(mEGLDisplay, null)) {
// mEGLDisplay = null;
// throw new RuntimeException("unable to initialize EGL10");
// }
//
// int[] attribList = {
// EGL10.EGL_RED_SIZE, 8,
// EGL10.EGL_GREEN_SIZE, 8,
// EGL10.EGL_BLUE_SIZE, 8,
// EGL10.EGL_ALPHA_SIZE, 8,
// EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
// EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
// EGL10.EGL_NONE
// };
// EGLConfig[] configs = new EGLConfig[1];
// int[] numConfigs = new int[1];
// if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, configs.length, numConfigs)) {
// throw new RuntimeException("unable to find RGB888+pbuffer EGL config");
// }
// int[] attrib_list = {
// EGL_CONTEXT_CLIENT_VERSION, 2,
// EGL10.EGL_NONE
// };
// mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT, attrib_list);
// checkEglError("eglCreateContext");
// if (mEGLContext == null) {
// throw new RuntimeException("null context");
// }
// int[] surfaceAttribs = {
// EGL10.EGL_WIDTH, width,
// EGL10.EGL_HEIGHT, height,
// EGL10.EGL_NONE
// };
// mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs);
// checkEglError("eglCreatePbufferSurface");
// if (mEGLSurface == null) {
// throw new RuntimeException("surface was null");
// }
// }
public void release() {
if (mEGL != null) {
if (mEGL.eglGetCurrentContext().equals(mEGLContext)) {
mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
}
mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface);
mEGL.eglDestroyContext(mEGLDisplay, mEGLContext);
}
// if (mEGL != null) {
// if (EGL14.eglGetCurrentContext().equals(mEGLContext)) {
// EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
// }
// if (mEGLSurface != null) {
// EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
// }
// if (mEGLContext != null) {
// EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
// }
// }
if (mTextureRender != null) {
mTextureRender.release();
}
@ -116,15 +179,15 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
mSurfaceTexture = null;
}
public void makeCurrent() {
if (mEGL == null) {
throw new RuntimeException("not configured for makeCurrent");
}
checkEglError("before makeCurrent");
if (!mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
throw new RuntimeException("eglMakeCurrent failed");
}
}
// public void makeCurrent() {
// if (mEGL == null) {
// throw new RuntimeException("not configured for makeCurrent");
// }
// checkEglError("before makeCurrent");
// if (!mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
// throw new RuntimeException("eglMakeCurrent failed");
// }
// }
public Surface getSurface() {
return mSurface;
@ -164,8 +227,8 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
private void checkEglError(String msg) {
if (mEGL.eglGetError() != EGL10.EGL_SUCCESS) {
throw new RuntimeException("EGL error encountered (see log)");
if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
throw new RuntimeException("EGL error encountered (see log) at: " + msg);
}
}

View file

@ -11,7 +11,6 @@ package org.telegram.messenger.video;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@ -22,21 +21,24 @@ import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.opengl.EGLContext;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.Build;
import android.os.Handler;
import android.text.Layout;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ReplacementSpan;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.Surface;
import android.view.View;
import android.view.inputmethod.EditorInfo;
@ -51,11 +53,9 @@ import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AnimatedEmojiSpan;
import org.telegram.ui.Components.AnimatedFileDrawable;
@ -68,17 +68,18 @@ import org.telegram.ui.Components.Paint.Views.LinkPreview;
import org.telegram.ui.Components.Paint.Views.LocationMarker;
import org.telegram.ui.Components.Paint.Views.PaintTextOptionsView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.Rect;
import org.telegram.ui.Components.VideoPlayer;
import org.telegram.ui.Stories.recorder.PreviewView;
import org.telegram.ui.Stories.recorder.StoryEntry;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.microedition.khronos.opengles.GL10;
@ -248,6 +249,11 @@ public class TextureRenderer {
private int simpleInputTexCoordHandle;
private int simpleSourceImageHandle;
private int simpleShaderProgramOES;
private int simplePositionHandleOES;
private int simpleInputTexCoordHandleOES;
private int simpleSourceImageHandleOES;
private int blurShaderProgram;
private int blurPositionHandle;
private int blurInputTexCoordHandle;
@ -274,9 +280,14 @@ public class TextureRenderer {
private int imageOrientation;
private boolean blendEnabled;
private boolean isPhoto;
private int[] collageTextures;
private ArrayList<VideoEditedInfo.Part> collageParts;
private boolean isCollage() {
return collageParts != null;
}
private boolean firstFrame = true;
Path path;
Paint xRefPaint;
@ -286,6 +297,8 @@ public class TextureRenderer {
private int[] blurTexture;
private int gradientTopColor, gradientBottomColor;
private final Handler handler;
private final EGLContext parentContext;
public TextureRenderer(
MediaController.SavedFilterState savedFilterState,
@ -302,9 +315,14 @@ public class TextureRenderer {
Integer gradientTopColor,
Integer gradientBottomColor,
StoryEntry.HDRInfo hdrInfo,
MediaCodecVideoConvertor.ConvertVideoParams params
MediaCodecVideoConvertor.ConvertVideoParams params,
Handler handler,
EGLContext parentContext
) {
isPhoto = photo;
collageParts = params.collageParts;
this.handler = handler;
this.parentContext = parentContext;
float[] texData = {
0.f, 0.f,
@ -561,6 +579,11 @@ public class TextureRenderer {
}
public void drawFrame(SurfaceTexture st, long time) {
// if (isCollage()) {
// for (int i = 0; i < collageParts.size(); ++i) {
// stepCollagePart(i, collageParts.get(i), time);
// }
// }
boolean blurred = false;
if (isPhoto) {
drawBackground();
@ -680,6 +703,12 @@ public class TextureRenderer {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
}
if (isCollage()) {
for (int i = 0; i < collageParts.size(); ++i) {
stepCollagePart(i, collageParts.get(i), time);
drawCollagePart(i, collageParts.get(i), time);
}
}
if (isPhoto || paintTexture != null || stickerTexture != null) {
GLES20.glUseProgram(simpleShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
@ -689,7 +718,7 @@ public class TextureRenderer {
GLES20.glVertexAttribPointer(simpleInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(simplePositionHandle);
}
if (imagePathIndex >= 0) {
if (imagePathIndex >= 0 && !isCollage()) {
drawTexture(true, paintTexture[imagePathIndex], -10000, -10000, -10000, -10000, 0, false, useMatrixForImagePath && isPhoto, -1);
}
if (paintPathIndex >= 0) {
@ -1086,7 +1115,7 @@ public class TextureRenderer {
}
}
}
if (filterShaders != null || imagePath != null || paintPath != null || messagePath != null || mediaEntities != null) {
if (filterShaders != null || imagePath != null || paintPath != null || messagePath != null || mediaEntities != null || isCollage()) {
int vertexShader = FilterShaders.loadShader(GLES20.GL_VERTEX_SHADER, FilterShaders.simpleVertexShaderCode);
int fragmentShader = FilterShaders.loadShader(GLES20.GL_FRAGMENT_SHADER, FilterShaders.simpleFragmentShaderCode);
if (vertexShader != 0 && fragmentShader != 0) {
@ -1109,6 +1138,29 @@ public class TextureRenderer {
}
}
}
if (isCollage()) {
int vertexShader = FilterShaders.loadShader(GLES20.GL_VERTEX_SHADER, FilterShaders.simpleVertexShaderCode);
int fragmentShader = FilterShaders.loadShader(GLES20.GL_FRAGMENT_SHADER, "#extension GL_OES_EGL_image_external : require\n" + FilterShaders.simpleFragmentShaderCode.replaceAll("sampler2D", "samplerExternalOES"));
if (vertexShader != 0 && fragmentShader != 0) {
simpleShaderProgramOES = GLES20.glCreateProgram();
GLES20.glAttachShader(simpleShaderProgramOES, vertexShader);
GLES20.glAttachShader(simpleShaderProgramOES, fragmentShader);
GLES20.glBindAttribLocation(simpleShaderProgramOES, 0, "position");
GLES20.glBindAttribLocation(simpleShaderProgramOES, 1, "inputTexCoord");
GLES20.glLinkProgram(simpleShaderProgramOES);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(simpleShaderProgramOES, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(simpleShaderProgramOES);
simpleShaderProgramOES = 0;
} else {
simplePositionHandleOES = GLES20.glGetAttribLocation(simpleShaderProgramOES, "position");
simpleInputTexCoordHandleOES = GLES20.glGetAttribLocation(simpleShaderProgramOES, "inputTexCoord");
simpleSourceImageHandleOES = GLES20.glGetUniformLocation(simpleShaderProgramOES, "sTexture");
}
}
}
if (filterShaders != null) {
filterShaders.create();
@ -1185,6 +1237,17 @@ public class TextureRenderer {
FileLog.e(e);
}
}
if (isCollage()) {
try {
collageTextures = new int[collageParts.size()];
GLES20.glGenTextures(collageTextures.length, collageTextures, 0);
for (int i = 0; i < collageParts.size(); ++i) {
initCollagePart(i, collageParts.get(i));
}
} catch (Exception e) {
FileLog.e(e);
}
}
if (mediaEntities != null || backgroundDrawable != null) {
try {
stickerBitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
@ -1486,6 +1549,230 @@ public class TextureRenderer {
}
}
public static final boolean USE_MEDIACODEC = true;
private void initCollagePart(int i, VideoEditedInfo.Part part) {
AtomicInteger width = new AtomicInteger(part.width);
AtomicInteger height = new AtomicInteger(part.height);
AtomicInteger rotate = new AtomicInteger(0);
if (part.isVideo) {
if (USE_MEDIACODEC) {
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, collageTextures[i]);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
part.surfaceTexture = new SurfaceTexture(collageTextures[i]);
part.surfaceTexture.setDefaultBufferSize(part.width, part.height);
try {
part.player = new MediaCodecPlayer(part.path, new Surface(part.surfaceTexture));
} catch (Exception e) {
FileLog.e(e);
part.player = null;
}
if (part.player != null) {
width.set(part.player.getOrientedWidth());
height.set(part.player.getOrientedHeight());
rotate.set(part.player.getOrientation());
} else {
part.surfaceTexture.release();
part.surfaceTexture = null;
GLES20.glDeleteTextures(1, collageTextures, i);
GLES20.glGenTextures(1, collageTextures, i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, collageTextures[i]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
part.animatedFileDrawable = new AnimatedFileDrawable(new File(part.path), true, 0, 0, null, null, null, 0, UserConfig.selectedAccount, true, 512, 512, null);
if (part.animatedFileDrawable.decoderFailed()) {
throw new RuntimeException("Failed to decode with ffmpeg software codecs");
}
part.framesPerDraw = part.animatedFileDrawable.getFps() / videoFps;
part.msPerFrame = 1000.0f / part.animatedFileDrawable.getFps();
part.currentFrame = 1;
Bitmap bitmap = part.animatedFileDrawable.getNextFrame(false);
if (bitmap != null) {
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
width.set(part.animatedFileDrawable.getIntrinsicWidth());
height.set(part.animatedFileDrawable.getIntrinsicHeight());
rotate.set(part.animatedFileDrawable.getOrientation());
}
}
} else {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, collageTextures[i]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
final BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inMutable = true;
Bitmap bitmap = BitmapFactory.decodeFile(part.path, opts);
final Pair<Integer, Integer> orientation = AndroidUtilities.getImageOrientation(part.path);
if (orientation.first != 0 || orientation.second != 0) {
android.graphics.Matrix matrix = new android.graphics.Matrix();
if (orientation.second != 0)
matrix.postScale(orientation.second == 1 ? -1 : 1, orientation.second == 2 ? -1 : 1);
if (orientation.first != 0)
matrix.postRotate(orientation.first);
bitmap = Bitmaps.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
width.set(bitmap.getWidth());
height.set(bitmap.getHeight());
}
final float[] pos = new float[] {
part.part.l(2.0f) - 1.0f, -(part.part.t(2.0f) - 1.0f),
part.part.r(2.0f) - 1.0f, -(part.part.t(2.0f) - 1.0f),
part.part.l(2.0f) - 1.0f, -(part.part.b(2.0f) - 1.0f),
part.part.r(2.0f) - 1.0f, -(part.part.b(2.0f) - 1.0f)
};
final float partWidth = part.part.w(transformedWidth);
final float partHeight = part.part.h(transformedHeight);
final int W = width.get(), H = height.get();
int r = rotate.get();
final float scale = 1.0f / Math.max(partWidth / W, partHeight / H);
float uvHW = partWidth * scale / W / 2;
float uvHH = partHeight * scale / H / 2;
if ((r / 90) % 2 == 1) {
float x = uvHW;
uvHW = uvHH;
uvHH = x;
}
final float[] uv = new float[] {
0.5f - uvHW, 0.5f - uvHH,
0.5f + uvHW, 0.5f - uvHH,
0.5f - uvHW, 0.5f + uvHH,
0.5f + uvHW, 0.5f + uvHH
};
while (r > 0) {
// left top 0 1
// right top 2 3
// left bottom 4 5
// right bottom 6 7
final float uv0 = uv[0], uv1 = uv[1];
uv[0] = uv[4];
uv[1] = uv[5];
uv[4] = uv[6];
uv[5] = uv[7];
uv[6] = uv[2];
uv[7] = uv[3];
uv[2] = uv0;
uv[3] = uv1;
r -= 90;
}
while (r < 0) {
// left top 0 1
// right top 2 3
// left bottom 4 5
// right bottom 6 7
final float uv0 = uv[0], uv1 = uv[1];
uv[0] = uv[2];
uv[1] = uv[3];
uv[2] = uv[6];
uv[3] = uv[7];
uv[6] = uv[4];
uv[7] = uv[5];
uv[4] = uv0;
uv[5] = uv1;
r += 90;
}
part.posBuffer = floats(pos);
part.uvBuffer = floats(uv);
}
private void destroyCollagePart(int i, VideoEditedInfo.Part part) {
if (part == null) return;
if (part.animatedFileDrawable != null) {
part.animatedFileDrawable.recycle();
part.animatedFileDrawable = null;
}
if (part.player != null) {
part.player.release();
part.player = null;
}
if (part.surfaceTexture != null) {
part.surfaceTexture.release();
part.surfaceTexture = null;
}
}
private FloatBuffer floats(float[] values) {
final FloatBuffer buffer = ByteBuffer.allocateDirect(values.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
buffer.put(values).position(0);
return buffer;
}
private void stepCollagePart(int i, VideoEditedInfo.Part part, long time) {
final long ms = time / 1_000_000L;
final long position = Utilities.clamp(ms - part.offset, (long) (part.right * part.duration), (long) (part.left * part.duration));
if (part.player != null) {
part.player.ensure(position);
part.surfaceTexture.updateTexImage();
} else if (part.animatedFileDrawable != null) {
boolean first = part.animatedFileDrawable.getProgressMs() <= 0;
if (position < part.animatedFileDrawable.getProgressMs() || first && position > 1000) {
part.animatedFileDrawable.seekToSync(position);
}
while (part.animatedFileDrawable.getProgressMs() + part.msPerFrame * 2 < position) {
long before = part.animatedFileDrawable.getProgressMs();
part.animatedFileDrawable.skipNextFrame(false);
long after = part.animatedFileDrawable.getProgressMs();
if (after == before) {
break;
}
}
if (first || position > part.animatedFileDrawable.getProgressMs() - part.msPerFrame / 2) {
Bitmap bitmap = part.animatedFileDrawable.getNextFrame(false);
if (bitmap != null) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, collageTextures[i]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
}
}
}
private void drawCollagePart(int i, VideoEditedInfo.Part part, long time) {
if (part.player != null && part.isVideo) {
GLES20.glUseProgram(simpleShaderProgramOES);
GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, collageTextures[i]);
GLES20.glUniform1i(simpleSourceImageHandleOES, 3);
GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandleOES);
GLES20.glVertexAttribPointer(simpleInputTexCoordHandleOES, 2, GLES20.GL_FLOAT, false, 8, part.uvBuffer);
GLES20.glEnableVertexAttribArray(simplePositionHandleOES);
GLES20.glVertexAttribPointer(simplePositionHandleOES, 2, GLES20.GL_FLOAT, false, 8, part.posBuffer);
} else {
GLES20.glUseProgram(simpleShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, collageTextures[i]);
GLES20.glUniform1i(simpleSourceImageHandle, 2);
GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandle);
GLES20.glVertexAttribPointer(simpleInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, part.uvBuffer);
GLES20.glEnableVertexAttribArray(simplePositionHandle);
GLES20.glVertexAttribPointer(simplePositionHandle, 2, GLES20.GL_FLOAT, false, 8, part.posBuffer);
}
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
private int createProgram(String vertexSource, String fragmentSource, boolean is300) {
if (is300) {
int vertexShader = FilterShaders.loadShader(GLES30.GL_VERTEX_SHADER, vertexSource);
@ -1555,6 +1842,13 @@ public class TextureRenderer {
}
}
}
if (collageParts != null) {
for (VideoEditedInfo.Part part : collageParts) {
for (int i = 0; i < collageParts.size(); ++i) {
destroyCollagePart(i, collageParts.get(i));
}
}
}
}
public void changeFragmentShader(String fragmentExternalShader, String fragmentShader, boolean is300) {

View file

@ -6,7 +6,7 @@ import android.graphics.Paint;
import android.graphics.SurfaceTexture;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.TextureView;
@ -33,7 +33,7 @@ public class VideoPlayerHolderBase {
public float progress;
int lastState;
public long currentPosition;
public volatile long currentPosition;
private int currentAccount;
long playerDuration;
boolean audioDisabled;
@ -41,6 +41,7 @@ public class VideoPlayerHolderBase {
private TextureView textureView;
private SurfaceView surfaceView;
private Surface surface;
public Bitmap playerStubBitmap;
public Paint playerStubPaint;
public long pendingSeekTo;
@ -53,12 +54,22 @@ public class VideoPlayerHolderBase {
public VideoPlayerHolderBase with(SurfaceView surfaceView) {
this.surfaceView = surfaceView;
this.textureView = null;
this.surface = null;
return this;
}
public VideoPlayerHolderBase with(TextureView textureView) {
this.surfaceView = null;
this.textureView = textureView;
this.surface = null;
return this;
}
public VideoPlayerHolderBase with(Surface surface) {
this.surfaceView = null;
this.textureView = null;
this.surface = surface;
return this;
}
@ -76,7 +87,7 @@ public class VideoPlayerHolderBase {
currentPosition = videoPlayer.getCurrentPosition();
playerDuration = videoPlayer.getDuration();
}
if (lastState == ExoPlayer.STATE_READY) {
if (lastState == ExoPlayer.STATE_READY || lastState == ExoPlayer.STATE_BUFFERING) {
dispatchQueue.cancelRunnable(progressRunnable);
dispatchQueue.postRunnable(progressRunnable, 16);
}
@ -107,7 +118,7 @@ public class VideoPlayerHolderBase {
});
}
public void start(boolean paused, Uri uri, long position, boolean audioDisabled, float speed) {
public void start(boolean attach, boolean paused, Uri uri, long position, boolean audioDisabled, float speed) {
startTime = System.currentTimeMillis();
this.audioDisabled = audioDisabled;
this.paused = paused;
@ -127,22 +138,44 @@ public class VideoPlayerHolderBase {
videoPlayer.preparePlayer(uri, "other");
videoPlayer.setWorkerQueue(dispatchQueue);
if (!paused) {
if (surfaceView != null) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
}
videoPlayer.setPlayWhenReady(true);
} else if (attach) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
}
videoPlayer.setPlayWhenReady(false);
}
} else {
FileLog.d("videoplayerholderbase.start(): player already exist");
if (!paused) {
if (surfaceView != null) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
}
videoPlayer.play();
} else if (attach) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
}
videoPlayer.setPlayWhenReady(false);
}
}
if (position > 0) {
@ -154,6 +187,11 @@ public class VideoPlayerHolderBase {
});
}
private boolean allowMultipleInstances;
public void allowMultipleInstances(boolean allow) {
this.allowMultipleInstances = allow;
}
private volatile int triesCount = 3;
private void ensurePlayerCreated(boolean audioDisabled) {
@ -161,10 +199,13 @@ public class VideoPlayerHolderBase {
videoPlayer.releasePlayer(true);
}
videoPlayer = new VideoPlayer(false, audioDisabled);
videoPlayer.allowMultipleInstances = allowMultipleInstances;
videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() {
@Override
public void onStateChanged(boolean playWhenReady, int playbackState) {
lastState = playbackState;
currentPosition = videoPlayer.getCurrentPosition();
playerDuration = videoPlayer.getDuration();
if (playbackState == ExoPlayer.STATE_READY || playbackState == ExoPlayer.STATE_BUFFERING) {
dispatchQueue.cancelRunnable(progressRunnable);
dispatchQueue.postRunnable(progressRunnable);
@ -193,12 +234,19 @@ public class VideoPlayerHolderBase {
videoPlayer.preparePlayer(uri, "other");
videoPlayer.seekTo(positionMs);
});
} else {
AndroidUtilities.runOnUIThread(() -> {
if (onErrorListener != null) {
onErrorListener.run();
onErrorListener = null;
}
});
}
}
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
VideoPlayerHolderBase.this.onVideoSizeChanged(width, height, unappliedRotationDegrees, pixelWidthHeightRatio);
}
@Override
@ -213,7 +261,7 @@ public class VideoPlayerHolderBase {
onReadyListener.run();
onReadyListener = null;
}
}, surfaceView == null ? 16 : 32);
}, surface != null ? 0 : surfaceView == null ? 16 : 32);
}
@Override
@ -229,11 +277,18 @@ public class VideoPlayerHolderBase {
videoPlayer.setIsStory();
}
protected void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
}
private Runnable onReadyListener;
public void setOnReadyListener(Runnable listener) {
onReadyListener = listener;
}
private Runnable onErrorListener;
public void setOnErrorListener(Runnable listener) {
onErrorListener = listener;
}
public boolean release(Runnable whenReleased) {
TLRPC.Document document = this.document;
@ -246,9 +301,11 @@ public class VideoPlayerHolderBase {
}
released = true;
dispatchQueue.cancelRunnable(initRunnable);
dispatchQueue.cancelRunnable(progressRunnable);
initRunnable = null;
dispatchQueue.postRunnable(() -> {
if (videoPlayer != null) {
videoPlayer.setSurface(null);
videoPlayer.setTextureView(null);
videoPlayer.setSurfaceView(null);
videoPlayer.releasePlayer(false);
@ -260,6 +317,7 @@ public class VideoPlayerHolderBase {
AndroidUtilities.runOnUIThread(whenReleased);
}
videoPlayer = null;
dispatchQueue.cancelRunnable(progressRunnable);
});
if (playerStubBitmap != null) {
AndroidUtilities.recycleBitmap(playerStubBitmap);
@ -321,7 +379,9 @@ public class VideoPlayerHolderBase {
paused = false;
dispatchQueue.postRunnable(() -> {
if (videoPlayer != null) {
if (surfaceView != null) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
@ -345,7 +405,9 @@ public class VideoPlayerHolderBase {
paused = false;
dispatchQueue.postRunnable(() -> {
if (videoPlayer != null) {
if (surfaceView != null) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
@ -379,11 +441,14 @@ public class VideoPlayerHolderBase {
videoPlayer.releasePlayer(false);
videoPlayer = null;
ensurePlayerCreated(audioDisabled);
final Uri uri = this.uri == null ? contentUri : this.uri;
FileLog.d("videoplayerholderbase.setAudioEnabled(): repreparePlayer as audio track is enabled back uri=" + uri);
videoPlayer.preparePlayer(uri, "other");
videoPlayer.setWorkerQueue(dispatchQueue);
if (!prepared) {
if (surfaceView != null) {
if (surface != null) {
videoPlayer.setSurface(surface);
} else if (surfaceView != null) {
videoPlayer.setSurfaceView(surfaceView);
} else {
videoPlayer.setTextureView(textureView);
@ -484,6 +549,16 @@ public class VideoPlayerHolderBase {
});
}
public void seekTo(long position, boolean fast, Runnable done) {
dispatchQueue.postRunnable(() -> {
if (videoPlayer == null) {
pendingSeekTo = position;
return;
}
videoPlayer.seekTo(position, fast, done);
});
}
public Uri getCurrentUri() {
return contentUri;
}

View file

@ -383,7 +383,9 @@ public class ConnectionsManager extends BaseController {
}
if ((connectionType & ConnectionTypeDownload) != 0 && VideoPlayer.activePlayers.isEmpty()) {
long ping_time = native_getCurrentPingTime(currentAccount);
DefaultBandwidthMeter.getSingletonInstance(ApplicationLoader.applicationContext).onTransfer(responseSize, Math.max(0, (System.currentTimeMillis() - finalStartRequestTime) - ping_time));
final long size = responseSize;
final long delta = Math.max(0, (System.currentTimeMillis() - finalStartRequestTime) - ping_time);
DefaultBandwidthMeter.getSingletonInstance(ApplicationLoader.applicationContext).onTransfer(size, delta);
}
if (BuildVars.DEBUG_PRIVATE_VERSION && !getUserConfig().isClientActivated() && error != null && error.code == 400 && Objects.equals(error.text, "CONNECTION_NOT_INITED")) {
if (BuildVars.LOGS_ENABLED) {
@ -437,16 +439,16 @@ public class ConnectionsManager extends BaseController {
private void listen(int requestToken, RequestDelegateInternal onComplete, QuickAckDelegate onQuickAck, WriteToSocketDelegate onWriteToSocket) {
requestCallbacks.put(requestToken, new RequestCallbacks(onComplete, onQuickAck, onWriteToSocket));
FileLog.d("{rc} listen(" + currentAccount + ", " + requestToken + "): " + requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} listen(" + currentAccount + ", " + requestToken + "): " + requestCallbacks.size() + " requests' callbacks");
}
private void listenCancel(int requestToken, Runnable onCancelled) {
RequestCallbacks callbacks = requestCallbacks.get(requestToken);
if (callbacks != null) {
callbacks.onCancelled = onCancelled;
FileLog.d("{rc} listenCancel(" + currentAccount + ", " + requestToken + "): " + requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} listenCancel(" + currentAccount + ", " + requestToken + "): " + requestCallbacks.size() + " requests' callbacks");
} else {
FileLog.d("{rc} listenCancel(" + currentAccount + ", " + requestToken + "): callback not found, " + requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} listenCancel(" + currentAccount + ", " + requestToken + "): callback not found, " + requestCallbacks.size() + " requests' callbacks");
}
}
@ -460,13 +462,13 @@ public class ConnectionsManager extends BaseController {
callbacks.onCancelled.run();
}
connectionsManager.requestCallbacks.remove(requestToken);
FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): request to cancel is found " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): request to cancel is found " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
} else {
FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): request to cancel is not found " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): request to cancel is not found " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
}
} else if (callbacks != null) {
connectionsManager.requestCallbacks.remove(requestToken);
FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestClear(" + currentAccount + ", " + requestToken + ", " + cancelled + "): " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
}
}
@ -479,9 +481,9 @@ public class ConnectionsManager extends BaseController {
if (callbacks.onComplete != null) {
callbacks.onComplete.run(response, errorCode, errorText, networkType, timestamp, requestMsgId, dcId);
}
FileLog.d("{rc} onRequestComplete(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestComplete(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
} else {
FileLog.d("{rc} onRequestComplete(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestComplete(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
}
}
@ -493,9 +495,9 @@ public class ConnectionsManager extends BaseController {
if (callbacks.onQuickAck != null) {
callbacks.onQuickAck.run();
}
FileLog.d("{rc} onRequestQuickAck(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestQuickAck(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
} else {
FileLog.d("{rc} onRequestQuickAck(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestQuickAck(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
}
}
@ -507,9 +509,9 @@ public class ConnectionsManager extends BaseController {
if (callbacks.onWriteToSocket != null) {
callbacks.onWriteToSocket.run();
}
FileLog.d("{rc} onRequestWriteToSocket(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestWriteToSocket(" + currentAccount + ", " + requestToken + "): found request " + requestToken + ", " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
} else {
FileLog.d("{rc} onRequestWriteToSocket(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
// FileLog.d("{rc} onRequestWriteToSocket(" + currentAccount + ", " + requestToken + "): not found request " + requestToken + "! " + connectionsManager.requestCallbacks.size() + " requests' callbacks");
}
}

View file

@ -28,6 +28,7 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.tl.TL_bots;
import org.telegram.tgnet.tl.TL_payments;
import org.telegram.tgnet.tl.TL_stars;
import org.telegram.tgnet.tl.TL_stats;
import org.telegram.tgnet.tl.TL_stories;
@ -81,7 +82,7 @@ public class TLRPC {
public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800;
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static final int LAYER = 193;
public static final int LAYER = 195;
public static abstract class EmailVerifyPurpose extends TLObject {
@ -28087,6 +28088,7 @@ public class TLRPC {
public WallPaper wallpaper;
public Peer peer;
public byte[] payload;
public int subscription_until_date;
public static MessageAction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
MessageAction result = null;
@ -28268,6 +28270,9 @@ public class TLRPC {
case TL_messageActionPaymentSent.constructor:
result = new TL_messageActionPaymentSent();
break;
case TL_messageActionPaymentSent_layer193.constructor:
result = new TL_messageActionPaymentSent_layer193();
break;
case TL_messageActionPaymentSent_layer140.constructor:
result = new TL_messageActionPaymentSent_layer140();
break;
@ -28286,6 +28291,9 @@ public class TLRPC {
case TL_messageActionPaymentSentMe.constructor:
result = new TL_messageActionPaymentSentMe();
break;
case TL_messageActionPaymentSentMe_layer193.constructor:
result = new TL_messageActionPaymentSentMe_layer193();
break;
case TL_messageActionGiftPremium.constructor:
result = new TL_messageActionGiftPremium();
break;
@ -29284,6 +29292,39 @@ public class TLRPC {
}
public static class TL_messageActionPaymentSent extends MessageAction {
public static final int constructor = 0xc624b16e;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
recurring_init = (flags & 4) != 0;
recurring_used = (flags & 8) != 0;
currency = stream.readString(exception);
total_amount = stream.readInt64(exception);
if ((flags & 1) != 0) {
invoice_slug = stream.readString(exception);
}
if ((flags & 16) != 0) {
subscription_until_date = stream.readInt32(exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = recurring_init ? (flags | 4) : (flags &~ 4);
flags = recurring_used ? (flags | 8) : (flags &~ 8);
stream.writeInt32(flags);
stream.writeString(currency);
stream.writeInt64(total_amount);
if ((flags & 1) != 0) {
stream.writeString(invoice_slug);
}
if ((flags & 16) != 0) {
stream.writeInt32(subscription_until_date);
}
}
}
public static class TL_messageActionPaymentSent_layer193 extends TL_messageActionPaymentSent {
public static final int constructor = 0x96163f56;
public void readParams(AbstractSerializedData stream, boolean exception) {
@ -29477,7 +29518,7 @@ public class TLRPC {
}
public static class TL_messageActionPaymentSentMe extends MessageAction {
public static final int constructor = 0x8f31b327;
public static final int constructor = 0xffa00ccc;
public int flags;
public byte[] payload;
@ -29485,6 +29526,49 @@ public class TLRPC {
public String shipping_option_id;
public TL_paymentCharge charge;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
recurring_init = (flags & 4) != 0;
recurring_used = (flags & 8) != 0;
currency = stream.readString(exception);
total_amount = stream.readInt64(exception);
payload = stream.readByteArray(exception);
if ((flags & 1) != 0) {
info = TL_paymentRequestedInfo.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 2) != 0) {
shipping_option_id = stream.readString(exception);
}
charge = TL_paymentCharge.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 16) != 0) {
subscription_until_date = stream.readInt32(exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = recurring_init ? (flags | 4) : (flags &~ 4);
flags = recurring_used ? (flags | 8) : (flags &~ 8);
stream.writeInt32(flags);
stream.writeString(currency);
stream.writeInt64(total_amount);
stream.writeByteArray(payload);
if ((flags & 1) != 0) {
info.serializeToStream(stream);
}
if ((flags & 2) != 0) {
stream.writeString(shipping_option_id);
}
charge.serializeToStream(stream);
if ((flags & 16) != 0) {
stream.writeInt32(subscription_until_date);
}
}
}
public static class TL_messageActionPaymentSentMe_layer193 extends TL_messageActionPaymentSentMe {
public static final int constructor = 0x8f31b327;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
recurring_init = (flags & 4) != 0;
@ -54406,6 +54490,7 @@ public class TLRPC {
public long personal_channel_id;
public int personal_channel_message;
public int stargifts_count;
public TL_payments.starRefProgram starref_program;
public static UserFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
UserFull result = null;
@ -54413,6 +54498,9 @@ public class TLRPC {
case TL_userFull.constructor:
result = new TL_userFull();
break;
case TL_userFull_layer194.constructor:
result = new TL_userFull_layer194();
break;
case TL_userFull_layer188.constructor:
result = new TL_userFull_layer188();
break;
@ -54476,6 +54564,226 @@ public class TLRPC {
}
public static class TL_userFull extends UserFull {
public static final int constructor = 0x979d2376;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
blocked = (flags & 1) != 0;
phone_calls_available = (flags & 16) != 0;
phone_calls_private = (flags & 32) != 0;
can_pin_message = (flags & 128) != 0;
has_scheduled = (flags & 4096) != 0;
video_calls_available = (flags & 8192) != 0;
voice_messages_forbidden = (flags & 1048576) != 0;
translations_disabled = (flags & 8388608) != 0;
stories_pinned_available = (flags & 67108864) != 0;
blocked_my_stories_from = (flags & 134217728) != 0;
wallpaper_overridden = (flags & 268435456) != 0;
contact_require_premium = (flags & 536870912) != 0;
read_dates_private = (flags & 1073741824) != 0;
flags2 = stream.readInt32(exception);
sponsored_enabled = (flags2 & 128) != 0;
can_view_revenue = (flags2 & 512) != 0;
bot_can_manage_emoji_status = (flags2 & 1024) != 0;
id = stream.readInt64(exception);
if ((flags & 2) != 0) {
about = stream.readString(exception);
}
settings = PeerSettings.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 2097152) != 0) {
personal_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 4) != 0) {
profile_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 4194304) != 0) {
fallback_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
}
notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 8) != 0) {
bot_info = TL_bots.BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 64) != 0) {
pinned_msg_id = stream.readInt32(exception);
}
common_chats_count = stream.readInt32(exception);
if ((flags & 2048) != 0) {
folder_id = stream.readInt32(exception);
}
if ((flags & 16384) != 0) {
ttl_period = stream.readInt32(exception);
}
if ((flags & 32768) != 0) {
theme_emoticon = stream.readString(exception);
}
if ((flags & 65536) != 0) {
private_forward_name = stream.readString(exception);
}
if ((flags & 131072) != 0) {
bot_group_admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 262144) != 0) {
bot_broadcast_admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 524288) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TL_premiumGiftOption object = TL_premiumGiftOption.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
premium_gifts.add(object);
}
}
if ((flags & 16777216) != 0) {
wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 33554432) != 0) {
stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 1) != 0) {
business_work_hours = TL_businessWorkHours.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 2) != 0) {
business_location = TL_businessLocation.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 4) != 0) {
business_greeting_message = TL_businessGreetingMessage.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 8) != 0) {
business_away_message = TL_businessAwayMessage.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 16) != 0) {
business_intro = TL_businessIntro.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 32) != 0) {
birthday = TL_birthday.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 64) != 0) {
personal_channel_id = stream.readInt64(exception);
personal_channel_message = stream.readInt32(exception);
}
if ((flags2 & 256) != 0) {
stargifts_count = stream.readInt32(exception);
}
if ((flags2 & 2048) != 0) {
starref_program = TL_payments.starRefProgram.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = blocked ? (flags | 1) : (flags &~ 1);
flags = phone_calls_available ? (flags | 16) : (flags &~ 16);
flags = phone_calls_private ? (flags | 32) : (flags &~ 32);
flags = can_pin_message ? (flags | 128) : (flags &~ 128);
flags = has_scheduled ? (flags | 4096) : (flags &~ 4096);
flags = video_calls_available ? (flags | 8192) : (flags &~ 8192);
flags = voice_messages_forbidden ? (flags | 1048576) : (flags &~ 1048576);
flags = translations_disabled ? (flags | 8388608) : (flags &~ 8388608);
flags = stories_pinned_available ? (flags | 67108864) : (flags &~ 67108864);
flags = blocked_my_stories_from ? (flags | 134217728) : (flags &~ 134217728);
flags = wallpaper_overridden ? (flags | 268435456) : (flags &~ 268435456);
flags = contact_require_premium ? (flags | 536870912) : (flags &~ 536870912);
flags = read_dates_private ? (flags | 1073741824) : (flags &~ 1073741824);
stream.writeInt32(flags);
flags2 = sponsored_enabled ? (flags2 | 128) : (flags2 &~ 128);
flags2 = can_view_revenue ? (flags2 | 512) : (flags2 &~ 512);
flags2 = bot_can_manage_emoji_status ? (flags2 | 1024) : (flags2 &~ 1024);
stream.writeInt32(flags2);
stream.writeInt64(id);
if ((flags & 2) != 0) {
stream.writeString(about);
}
settings.serializeToStream(stream);
if ((flags & 2097152) != 0) {
personal_photo.serializeToStream(stream);
}
if ((flags & 4) != 0) {
profile_photo.serializeToStream(stream);
}
if ((flags & 4194304) != 0) {
fallback_photo.serializeToStream(stream);
}
notify_settings.serializeToStream(stream);
if ((flags & 8) != 0) {
bot_info.serializeToStream(stream);
}
if ((flags & 64) != 0) {
stream.writeInt32(pinned_msg_id);
}
stream.writeInt32(common_chats_count);
if ((flags & 2048) != 0) {
stream.writeInt32(folder_id);
}
if ((flags & 16384) != 0) {
stream.writeInt32(ttl_period);
}
if ((flags & 32768) != 0) {
stream.writeString(theme_emoticon);
}
if ((flags & 65536) != 0) {
stream.writeString(private_forward_name);
}
if ((flags & 131072) != 0) {
bot_group_admin_rights.serializeToStream(stream);
}
if ((flags & 262144) != 0) {
bot_broadcast_admin_rights.serializeToStream(stream);
}
if ((flags & 524288) != 0) {
stream.writeInt32(0x1cb5c415);
int count = premium_gifts.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
premium_gifts.get(a).serializeToStream(stream);
}
}
if ((flags & 16777216) != 0) {
wallpaper.serializeToStream(stream);
}
if ((flags & 33554432) != 0) {
stories.serializeToStream(stream);
}
if ((flags2 & 1) != 0) {
business_work_hours.serializeToStream(stream);
}
if ((flags2 & 2) != 0) {
business_location.serializeToStream(stream);
}
if ((flags2 & 4) != 0) {
business_greeting_message.serializeToStream(stream);
}
if ((flags2 & 8) != 0) {
business_away_message.serializeToStream(stream);
}
if ((flags2 & 16) != 0) {
business_intro.serializeToStream(stream);
}
if ((flags2 & 32) != 0) {
birthday.serializeToStream(stream);
}
if ((flags2 & 64) != 0) {
stream.writeInt64(personal_channel_id);
stream.writeInt32(personal_channel_message);
}
if ((flags2 & 256) != 0) {
stream.writeInt32(stargifts_count);
}
if ((flags2 & 2048) != 0) {
starref_program.serializeToStream(stream);
}
}
}
public static class TL_userFull_layer194 extends TL_userFull {
public static final int constructor = 0x1f58e369;
public void readParams(AbstractSerializedData stream, boolean exception) {
@ -62309,9 +62617,11 @@ public class TLRPC {
}
public static class TL_contacts_resolveUsername extends TLObject {
public static final int constructor = 0xf93ccba3;
public static final int constructor = 0x725afbbc;
public int flags;
public String username;
public String referer;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_contacts_resolvedPeer.TLdeserialize(stream, constructor, exception);
@ -62319,7 +62629,11 @@ public class TLRPC {
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeString(username);
if ((flags & 1) != 0) {
stream.writeString(referer);
}
}
}
@ -78248,6 +78562,21 @@ public class TLRPC {
}
public static class TL_updateStarsBalance extends Update {
public static final int constructor = 0x4e80a379;
public TL_stars.StarsAmount balance;
public void readParams(AbstractSerializedData stream, boolean exception) {
balance = TL_stars.StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
balance.serializeToStream(stream);
}
}
public static class TL_updateStarsBalance_layer194 extends TL_updateStarsBalance {
public static final int constructor = 0xfb85198;
public long balance;
@ -83821,13 +84150,13 @@ public class TLRPC {
}
public static class TL_starsRevenueStatus extends TLObject {
public static final int constructor = 0x79342946;
public static final int constructor = 0xfebe5491;
public int flags;
public boolean withdrawal_enabled;
public long current_balance;
public long available_balance;
public long overall_revenue;
public TL_stars.StarsAmount current_balance = new TL_stars.StarsAmount();
public TL_stars.StarsAmount available_balance = new TL_stars.StarsAmount();
public TL_stars.StarsAmount overall_revenue = new TL_stars.StarsAmount();
public int next_withdrawal_at;
public static TL_starsRevenueStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -83846,9 +84175,9 @@ public class TLRPC {
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
withdrawal_enabled = (flags & 1) != 0;
current_balance = stream.readInt64(exception);
available_balance = stream.readInt64(exception);
overall_revenue = stream.readInt64(exception);
current_balance = TL_stars.StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
available_balance = TL_stars.StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
overall_revenue = TL_stars.StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 2) != 0) {
next_withdrawal_at = stream.readInt32(exception);
}
@ -83859,9 +84188,9 @@ public class TLRPC {
stream.writeInt32(constructor);
flags = withdrawal_enabled ? flags | 1 : flags &~ 1;
stream.writeInt32(flags);
stream.writeInt64(current_balance);
stream.writeInt64(available_balance);
stream.writeInt64(overall_revenue);
current_balance.serializeToStream(stream);
available_balance.serializeToStream(stream);
overall_revenue.serializeToStream(stream);
if ((flags & 2) != 0) {
stream.writeInt32(next_withdrawal_at);
}
@ -84143,4 +84472,126 @@ public class TLRPC {
}
}
public static class messages_FoundStickers extends TLObject {
public int flags;
public int next_offset;
public static messages_FoundStickers TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
messages_FoundStickers result = null;
switch (constructor) {
case TL_messages_foundStickers.constructor:
result = new TL_messages_foundStickers();
break;
case TL_messages_foundStickersNotModified.constructor:
result = new TL_messages_foundStickersNotModified();
break;
}
if (result == null && exception) {
throw new RuntimeException(String.format("can't parse magic %x in messages_FoundStickers", constructor));
}
if (result != null) {
result.readParams(stream, exception);
}
return result;
}
}
public static class TL_messages_foundStickers extends messages_FoundStickers {
public static final int constructor = 0x82c9e290;
public long hash;
public ArrayList<Document> stickers = new ArrayList<>();
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
if ((flags & 1) != 0) {
next_offset = stream.readInt32(exception);
}
hash = stream.readInt64(exception);
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int i = 0; i < count; ++i) {
stickers.add(Document.TLdeserialize(stream, stream.readInt32(exception), exception));
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
if ((flags & 1) != 0) {
stream.writeInt32(next_offset);
}
stream.writeInt64(hash);
stream.writeInt32(0x1cb5c415);
stream.writeInt32(stickers.size());
for (int i = 0; i < stickers.size(); ++i) {
stickers.get(i).serializeToStream(stream);
}
}
}
public static class TL_messages_foundStickersNotModified extends messages_FoundStickers {
public static final int constructor = 0x6010c534;
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
if ((flags & 1) != 0) {
next_offset = stream.readInt32(exception);
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
if ((flags & 1) != 0) {
stream.writeInt32(next_offset);
}
}
}
public static class TL_messages_searchStickers extends TLObject {
public static final int constructor = 0x29b1c66a;
public int flags;
public boolean emojis;
public String q;
public String emoticon;
public ArrayList<String> lang_code = new ArrayList<>();
public int offset;
public int limit;
public long hash;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return messages_FoundStickers.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = emojis ? flags | 1 : flags &~ 1;
stream.writeInt32(flags);
stream.writeString(q);
stream.writeString(emoticon);
stream.writeInt32(0x1cb5c415);
stream.writeInt32(lang_code.size());
for (int i = 0; i < lang_code.size(); ++i)
stream.writeString(lang_code.get(i));
stream.writeInt32(offset);
stream.writeInt32(limit);
stream.writeInt64(hash);
}
}
}

View file

@ -1130,7 +1130,50 @@ public class TL_bots {
stream.writeString(file_name);
stream.writeString(url);
}
}
public static class updateStarRefProgram extends TLObject {
public static final int constructor = 0x778b5ab3;
public int flags;
public TLRPC.InputUser bot;
public int commission_permille;
public int duration_months;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_payments.starRefProgram.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
bot.serializeToStream(stream);
stream.writeInt32(commission_permille);
if ((flags & 1) != 0) {
stream.writeInt32(duration_months);
}
}
}
public static class getAdminedBots extends TLObject {
public static final int constructor = 0xb0711d83;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
TLRPC.Vector vector = new TLRPC.Vector();
int size = stream.readInt32(exception);
for (int a = 0; a < size; a++) {
vector.objects.add(TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception));
}
return vector;
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
}
}
}

View file

@ -0,0 +1,383 @@
package org.telegram.tgnet.tl;
import org.telegram.tgnet.AbstractSerializedData;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import java.util.ArrayList;
public class TL_payments {
public static class connectedBotStarRef extends TLObject {
public static final int constructor = 0x19a13f71;
public int flags;
public boolean revoked;
public String url;
public int date;
public long bot_id;
public int commission_permille;
public int duration_months;
public long participants;
public long revenue;
public static connectedBotStarRef TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (connectedBotStarRef.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_payments.connectedBotStarRef", constructor));
} else {
return null;
}
}
connectedBotStarRef result = new connectedBotStarRef();
result.readParams(stream, exception);
return result;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
revoked = (flags & 2) != 0;
url = stream.readString(exception);
date = stream.readInt32(exception);
bot_id = stream.readInt64(exception);
commission_permille = stream.readInt32(exception);
if ((flags & 1) != 0) {
duration_months = stream.readInt32(exception);
}
participants = stream.readInt64(exception);
revenue = stream.readInt64(exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = revoked ? flags | 2 : flags &~ 2;
stream.writeInt32(flags);
stream.writeString(url);
stream.writeInt32(date);
stream.writeInt64(bot_id);
stream.writeInt32(commission_permille);
if ((flags & 1) != 0) {
stream.writeInt32(duration_months);
}
stream.writeInt64(participants);
stream.writeInt64(revenue);
}
}
public static class connectedStarRefBots extends TLObject {
public static final int constructor = 0x98d5ea1d;
public int count;
public ArrayList<connectedBotStarRef> connected_bots = new ArrayList<>();
public ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
public static connectedStarRefBots TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (connectedStarRefBots.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_payments.connectedStarRefBots", constructor));
} else {
return null;
}
}
connectedStarRefBots result = new connectedStarRefBots();
result.readParams(stream, exception);
return result;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
count = stream.readInt32(exception);
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int i = 0; i < count; ++i) {
connected_bots.add(connectedBotStarRef.TLdeserialize(stream, stream.readInt32(exception), exception));
}
magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
count = stream.readInt32(exception);
for (int i = 0; i < count; ++i) {
users.add(TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception));
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(count);
stream.writeInt32(0x1cb5c415);
int count = connected_bots.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
connected_bots.get(i).serializeToStream(stream);
}
stream.writeInt32(0x1cb5c415);
count = users.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
users.get(i).serializeToStream(stream);
}
}
}
public static class suggestedStarRefBots extends TLObject {
public static final int constructor = 0xb4d5d859;
public int flags;
public int count;
public ArrayList<starRefProgram> suggested_bots = new ArrayList<>();
public ArrayList<TLRPC.User> users = new ArrayList<>();
public String next_offset;
public static suggestedStarRefBots TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (suggestedStarRefBots.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_payments.suggestedStarRefBots", constructor));
} else {
return null;
}
}
suggestedStarRefBots result = new suggestedStarRefBots();
result.readParams(stream, exception);
return result;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
count = stream.readInt32(exception);
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int i = 0; i < count; ++i) {
suggested_bots.add(starRefProgram.TLdeserialize(stream, stream.readInt32(exception), exception));
}
magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
count = stream.readInt32(exception);
for (int i = 0; i < count; ++i) {
users.add(TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception));
}
if ((flags & 1) != 0) {
next_offset = stream.readString(exception);
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(count);
stream.writeInt32(0x1cb5c415);
int count = suggested_bots.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
suggested_bots.get(i).serializeToStream(stream);
}
stream.writeInt32(0x1cb5c415);
count = users.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
users.get(i).serializeToStream(stream);
}
if ((flags & 1) != 0) {
stream.writeString(next_offset);
}
}
}
public static class starRefProgram extends TLObject {
public static final int constructor = 0xdd0c66f2;
public int flags;
public long bot_id;
public int commission_permille;
public int duration_months;
public int end_date;
public TL_stars.StarsAmount daily_revenue_per_user = new TL_stars.StarsAmount(0);
public static starRefProgram TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (starRefProgram.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_payments.starRefProgram", constructor));
} else {
return null;
}
}
starRefProgram result = new starRefProgram();
result.readParams(stream, exception);
return result;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
bot_id = stream.readInt64(exception);
commission_permille = stream.readInt32(exception);
if ((flags & 1) != 0) {
duration_months = stream.readInt32(exception);
}
if ((flags & 2) != 0) {
end_date = stream.readInt32(exception);
}
if ((flags & 4) != 0) {
daily_revenue_per_user = TL_stars.StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeInt64(bot_id);
stream.writeInt32(commission_permille);
if ((flags & 1) != 0) {
stream.writeInt32(duration_months);
}
if ((flags & 2) != 0) {
stream.writeInt32(end_date);
}
if ((flags & 4) != 0) {
daily_revenue_per_user.serializeToStream(stream);
}
}
}
public static class connectStarRefBot extends TLObject {
public static final int constructor = 0x7ed5348a;
public TLRPC.InputPeer peer;
public TLRPC.InputUser bot;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return connectedStarRefBots.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
peer.serializeToStream(stream);
bot.serializeToStream(stream);
}
}
public static class getSuggestedStarRefBots extends TLObject {
public static final int constructor = 0xd6b48f7;
public int flags;
public boolean order_by_revenue;
public boolean order_by_date;
public TLRPC.InputPeer peer;
public String offset;
public int limit;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return suggestedStarRefBots.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = order_by_revenue ? flags | 1 : flags &~ 1;
flags = order_by_date ? flags | 2 : flags &~ 2;
stream.writeInt32(flags);
peer.serializeToStream(stream);
stream.writeString(offset);
stream.writeInt32(limit);
}
}
public static class getConnectedStarRefBots extends TLObject {
public static final int constructor = 0x5869a553;
public int flags;
public TLRPC.InputPeer peer;
public int offset_date;
public String offset_link;
public int limit;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return connectedStarRefBots.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
peer.serializeToStream(stream);
if ((flags & 4) != 0) {
stream.writeInt32(offset_date);
stream.writeString(offset_link);
}
stream.writeInt32(limit);
}
}
public static class getConnectedStarRefBot extends TLObject {
public static final int constructor = 0xb7d998f0;
public TLRPC.InputPeer peer;
public TLRPC.InputUser bot;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return connectedStarRefBots.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
peer.serializeToStream(stream);
bot.serializeToStream(stream);
}
}
public static class editConnectedStarRefBot extends TLObject {
public static final int constructor = 0xe4fca4a3;
public int flags;
public boolean revoked;
public TLRPC.InputPeer peer;
public String link;
@Override
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return connectedStarRefBots.TLdeserialize(stream, constructor, exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = revoked ? flags | 1 : flags &~ 1;
stream.writeInt32(flags);
peer.serializeToStream(stream);
stream.writeString(link);
}
}
}

View file

@ -782,7 +782,7 @@ public class TL_stars {
public boolean subscription;
public boolean floodskip;
public String id;
public long stars;
public StarsAmount stars = new StarsAmount(0);
public int date;
public StarsTransactionPeer peer;
public String title;
@ -797,6 +797,9 @@ public class TL_stars {
public int giveaway_post_id;
public StarGift stargift;
public int floodskip_number;
public int starref_commission_permille;
public TLRPC.Peer starref_peer;
public StarsAmount starref_amount;
public TLRPC.Peer sent_by; //custom
public TLRPC.Peer received_by; //custom
@ -822,6 +825,9 @@ public class TL_stars {
case TL_starsTransaction_layer191.constructor:
result = new TL_starsTransaction_layer191();
break;
case TL_starsTransaction_layer194.constructor:
result = new TL_starsTransaction_layer194();
break;
case TL_starsTransaction.constructor:
result = new TL_starsTransaction();
break;
@ -844,7 +850,7 @@ public class TL_stars {
flags = stream.readInt32(exception);
refund = (flags & 8) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -862,7 +868,7 @@ public class TL_stars {
stream.writeInt32(constructor);
flags = refund ? flags | 8 : flags &~ 8;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -886,7 +892,7 @@ public class TL_stars {
pending = (flags & 16) != 0;
failed = (flags & 64) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -910,7 +916,7 @@ public class TL_stars {
flags = pending ? flags | 16 : flags &~ 16;
flags = failed ? flags | 64 : flags &~ 64;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -929,7 +935,185 @@ public class TL_stars {
}
}
public static class StarsAmount extends TLObject {
public static final int constructor = 0xbbb6b4a3;
public long amount;
public int nanos;
public static StarsAmount TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (StarsAmount.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in StarsAmount", constructor));
} else {
return null;
}
}
StarsAmount result = new StarsAmount();
result.readParams(stream, exception);
return result;
}
public StarsAmount() {}
public StarsAmount(long stars) {
this.amount = stars;
this.nanos = 0;
}
public void readParams(AbstractSerializedData stream, boolean exception) {
amount = stream.readInt64(exception);
nanos = stream.readInt32(exception);
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(amount);
stream.writeInt32(nanos);
}
public boolean equals(TL_stars.StarsAmount amount) {
if (amount == null) return false;
return this.amount == amount.amount && this.nanos == amount.nanos;
}
}
public static class TL_starsTransaction extends StarsTransaction {
public static final int constructor = 0x64dfc926;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
refund = (flags & 8) != 0;
pending = (flags & 16) != 0;
failed = (flags & 64) != 0;
gift = (flags & 1024) != 0;
reaction = (flags & 2048) != 0;
subscription = (flags & 4096) != 0;
floodskip = (flags & 32768) != 0;
id = stream.readString(exception);
stars = StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
title = stream.readString(exception);
}
if ((flags & 2) != 0) {
description = stream.readString(exception);
}
if ((flags & 4) != 0) {
photo = TLRPC.WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 32) != 0) {
transaction_date = stream.readInt32(exception);
transaction_url = stream.readString(exception);
}
if ((flags & 128) != 0) {
bot_payload = stream.readByteArray(exception);
}
if ((flags & 256) != 0) {
msg_id = stream.readInt32(exception);
}
if ((flags & 512) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TLRPC.MessageMedia object = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
extended_media.add(object);
}
}
if ((flags & 4096) != 0) {
subscription_period = stream.readInt32(exception);
}
if ((flags & 8192) != 0) {
giveaway_post_id = stream.readInt32(exception);
}
if ((flags & 16384) != 0) {
stargift = StarGift.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 32768) != 0) {
floodskip_number = stream.readInt32(exception);
}
if ((flags & 65536) != 0) {
starref_commission_permille = stream.readInt32(exception);
}
if ((flags & 131072) != 0) {
starref_peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
starref_amount = StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = refund ? flags | 8 : flags &~ 8;
flags = pending ? flags | 16 : flags &~ 16;
flags = failed ? flags | 64 : flags &~ 64;
flags = gift ? flags | 1024 : flags &~ 1024;
flags = reaction ? flags | 2048 : flags &~ 2048;
flags = subscription ? flags | 4096 : flags &~ 4096;
flags = floodskip ? flags | 32768 : flags &~ 32768;
stream.writeInt32(flags);
stars.serializeToStream(stream);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
stream.writeString(title);
}
if ((flags & 2) != 0) {
stream.writeString(description);
}
if ((flags & 4) != 0) {
photo.serializeToStream(stream);
}
if ((flags & 32) != 0) {
stream.writeInt32(transaction_date);
stream.writeString(transaction_url);
}
if ((flags & 128) != 0) {
stream.writeByteArray(bot_payload);
}
if ((flags & 256) != 0) {
stream.writeInt32(msg_id);
}
if ((flags & 512) != 0) {
stream.writeInt32(0x1cb5c415);
int count = extended_media.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
extended_media.get(i).serializeToStream(stream);
}
}
if ((flags & 4096) != 0) {
stream.writeInt32(subscription_period);
}
if ((flags & 8192) != 0) {
stream.writeInt32(giveaway_post_id);
}
if ((flags & 16384) != 0) {
stargift.serializeToStream(stream);
}
if ((flags & 32768) != 0) {
stream.writeInt32(floodskip_number);
}
if ((flags & 65536) != 0) {
stream.writeInt32(starref_commission_permille);
}
if ((flags & 131072) != 0) {
starref_peer.serializeToStream(stream);
starref_amount.serializeToStream(stream);
}
}
}
public static class TL_starsTransaction_layer194 extends TL_starsTransaction {
public static final int constructor = 0x35d4f276;
public void readParams(AbstractSerializedData stream, boolean exception) {
@ -942,7 +1126,7 @@ public class TL_stars {
subscription = (flags & 4096) != 0;
floodskip = (flags & 32768) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -1005,7 +1189,7 @@ public class TL_stars {
flags = subscription ? flags | 4096 : flags &~ 4096;
flags = floodskip ? flags | 32768 : flags &~ 32768;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -1062,7 +1246,7 @@ public class TL_stars {
reaction = (flags & 2048) != 0;
subscription = (flags & 4096) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -1121,7 +1305,7 @@ public class TL_stars {
flags = reaction ? flags | 2048 : flags &~ 2048;
flags = subscription ? flags | 4096 : flags &~ 4096;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -1175,7 +1359,7 @@ public class TL_stars {
reaction = (flags & 2048) != 0;
subscription = (flags & 4096) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -1231,7 +1415,7 @@ public class TL_stars {
flags = reaction ? flags | 2048 : flags &~ 2048;
flags = subscription ? flags | 4096 : flags &~ 4096;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -1282,7 +1466,7 @@ public class TL_stars {
reaction = (flags & 2048) != 0;
subscription = (flags & 4096) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -1335,7 +1519,7 @@ public class TL_stars {
flags = reaction ? flags | 2048 : flags &~ 2048;
flags = subscription ? flags | 4096 : flags &~ 4096;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -1381,7 +1565,7 @@ public class TL_stars {
failed = (flags & 64) != 0;
gift = (flags & 1024) != 0;
id = stream.readString(exception);
stars = stream.readInt64(exception);
stars = new StarsAmount(stream.readInt64(exception));
date = stream.readInt32(exception);
peer = StarsTransactionPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 1) != 0) {
@ -1429,7 +1613,7 @@ public class TL_stars {
flags = failed ? flags | 64 : flags &~ 64;
flags = gift ? flags | 1024 : flags &~ 1024;
stream.writeInt32(flags);
stream.writeInt64(stars);
stream.writeInt64(stars.amount);
stream.writeInt32(date);
peer.serializeToStream(stream);
if ((flags & 1) != 0) {
@ -1462,11 +1646,10 @@ public class TL_stars {
}
}
public static class TL_payments_starsStatus extends TLObject {
public static final int constructor = 0xbbfa316c;
public static class StarsStatus extends TLObject {
public int flags;
public long balance;
public StarsAmount balance = new StarsAmount(0);
public ArrayList<StarsSubscription> subscriptions = new ArrayList<>();
public String subscriptions_next_offset;
public long subscriptions_missing_balance;
@ -1475,22 +1658,32 @@ public class TL_stars {
public ArrayList<TLRPC.Chat> chats = new ArrayList<>();
public ArrayList<TLRPC.User> users = new ArrayList<>();
public static TL_payments_starsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (TL_payments_starsStatus.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_payments_starsStatus", constructor));
} else {
return null;
public static StarsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
StarsStatus result = null;
switch (constructor) {
case TL_payments_starsStatus_layer194.constructor:
result = new TL_payments_starsStatus_layer194();
break;
case TL_payments_starsStatus.constructor:
result = new TL_payments_starsStatus();
break;
}
if (result == null && exception) {
throw new RuntimeException(String.format("can't parse magic %x in StarsStatus", constructor));
}
TL_payments_starsStatus result = new TL_payments_starsStatus();
if (result != null) {
result.readParams(stream, exception);
}
return result;
}
}
public static class TL_payments_starsStatus extends StarsStatus {
public static final int constructor = 0x6c9ce8ed;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
balance = stream.readInt64(exception);
balance = StarsAmount.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 2) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
@ -1569,7 +1762,131 @@ public class TL_stars {
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeInt64(balance);
balance.serializeToStream(stream);
if ((flags & 2) != 0) {
stream.writeInt32(0x1cb5c415);
int count = subscriptions.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
subscriptions.get(i).serializeToStream(stream);
}
}
if ((flags & 4) != 0) {
stream.writeString(subscriptions_next_offset);
}
if ((flags & 16) != 0) {
stream.writeInt64(subscriptions_missing_balance);
}
stream.writeInt32(0x1cb5c415);
int count = history.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
history.get(i).serializeToStream(stream);
}
if ((flags & 1) != 0) {
stream.writeString(next_offset);
}
stream.writeInt32(0x1cb5c415);
count = chats.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
chats.get(i).serializeToStream(stream);
}
stream.writeInt32(0x1cb5c415);
count = users.size();
stream.writeInt32(count);
for (int i = 0; i < count; ++i) {
users.get(i).serializeToStream(stream);
}
}
}
public static class TL_payments_starsStatus_layer194 extends TL_payments_starsStatus {
public static final int constructor = 0xbbfa316c;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
balance = new StarsAmount(stream.readInt64(exception));
if ((flags & 2) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
StarsSubscription object = StarsSubscription.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
subscriptions.add(object);
}
}
if ((flags & 4) != 0) {
subscriptions_next_offset = stream.readString(exception);
}
if ((flags & 16) != 0) {
subscriptions_missing_balance = stream.readInt64(exception);
}
if ((flags & 8) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
StarsTransaction object = StarsTransaction.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
history.add(object);
}
}
if ((flags & 1) != 0) {
next_offset = stream.readString(exception);
}
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TLRPC.Chat object = TLRPC.Chat.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
chats.add(object);
}
magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TLRPC.User object = TLRPC.User.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
users.add(object);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeInt64(balance.amount);
if ((flags & 2) != 0) {
stream.writeInt32(0x1cb5c415);
int count = subscriptions.size();
@ -1684,7 +2001,7 @@ public class TL_stars {
public TLRPC.InputPeer peer;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception);
return StarsStatus.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
@ -1703,7 +2020,7 @@ public class TL_stars {
public String offset;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception);
return StarsStatus.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
@ -1934,7 +2251,7 @@ public class TL_stars {
public String offset;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_payments_starsStatus.TLdeserialize(stream, constructor, exception);
return StarsStatus.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {

View file

@ -30,11 +30,11 @@ import org.telegram.ui.Components.RLottieImageView;
public class ActionBarMenuSubItem extends FrameLayout {
private TextView textView;
public TextView textView;
public TextView subtextView;
public RLottieImageView imageView;
private boolean checkViewLeft;
private CheckBox2 checkView;
public boolean checkViewLeft;
public CheckBox2 checkView;
private ImageView rightIcon;
private int textColor;

View file

@ -280,6 +280,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
super(context, R.style.TransparentDialog);
this.resourcesProvider = resourcesProvider;
progressViewStyle = progressStyle;
backgroundColor = getThemedColor(Theme.key_dialogBackground);
final boolean isDark = AndroidUtilities.computePerceivedBrightness(backgroundColor) < 0.721f;
blurredNativeBackground = supportsNativeBlur() && progressViewStyle == ALERT_TYPE_MESSAGE;
@ -293,8 +294,6 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
shadowDrawable.getPadding(backgroundPaddings);
}
withCancelDialog = progressViewStyle == ALERT_TYPE_SPINNER;
progressViewStyle = progressStyle;
}
private long shownAt;

View file

@ -66,6 +66,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.camera.CameraView;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AnimationProperties;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.CubicBezierInterpolator;

View file

@ -16,6 +16,8 @@
package org.telegram.ui.ActionBar;
import static org.telegram.messenger.AndroidUtilities.allGlobalViews;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@ -70,6 +72,8 @@ import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PhotoViewer;
import java.util.ArrayList;
import java.util.Arrays;
@ -1406,11 +1410,70 @@ public final class FloatingToolbar {
}
private static PopupWindow createPopupWindow(ViewGroup content) {
ViewGroup popupContentHolder = new LinearLayout(content.getContext());
ViewGroup popupContentHolder = new LinearLayout(content.getContext()) {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
private boolean isParent(View child, View parent) {
if (child == parent) return true;
if (child.getParent() == null) return false;
if (child.getParent() instanceof View) {
return isParent((View) child.getParent(), parent);
} else if (child.getParent() == parent) {
return true;
} else if (child.getRootView() == parent) {
return true;
}
return false;
}
private final int[] p = new int[2];
private View downRootView = null;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean r = super.dispatchTouchEvent(ev);
if (!r) {
getLocationOnScreen(p);
ev.offsetLocation(p[0], p[1]);
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
final List<View> views = allGlobalViews();
if (views != null && views.size() > 1) {
for (int i = views.size() - 2; i >= 0; --i) {
final View view = views.get(i);
if (isParent(this, view)) continue;
view.getLocationOnScreen(p);
ev.offsetLocation(-p[0], -p[1]);
r = view.dispatchTouchEvent(ev);
if (r) {
downRootView = view;
return true;
}
ev.offsetLocation(p[0], p[1]);
}
}
} else if (downRootView != null) {
View view = downRootView;
view.getLocationOnScreen(p);
ev.offsetLocation(-p[0], -p[1]);
r = view.dispatchTouchEvent(ev);
}
}
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
downRootView = null;
}
return r;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
};
PopupWindow popupWindow = new PopupWindow(popupContentHolder);
popupWindow.setClippingEnabled(false);
popupWindow.setAnimationStyle(0);
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setSplitTouchEnabled(true);
content.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
popupContentHolder.addView(content);
return popupWindow;

View file

@ -5244,6 +5244,41 @@ public class Theme {
return defaultDrawable;
}
public static Drawable createOutlineCircleDrawable(int size, int color, int strokeWidth) {
return new Drawable() {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
paint.setColor(color);
}
@Override
public void draw(@NonNull Canvas canvas) {
final Rect b = getBounds();
canvas.drawCircle(b.centerX(), b.centerY(), size / 2.0f, paint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
@Override
public int getIntrinsicWidth() {
return size + strokeWidth;
}
@Override
public int getIntrinsicHeight() {
return size + strokeWidth;
}
};
}
public static ShapeDrawable createCircleDrawable(int size, int colorTop, int colorBottom) {
OvalShape ovalShape = new OvalShape();
ovalShape.resize(size, size);

View file

@ -570,6 +570,9 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
view = new ProfileSearchCell(mContext);
} else {
DialogCell dialogCell = new DialogCell(parentFragment, mContext, true, false, currentAccount, null);
if (showOpenBotButton()) {
dialogCell.allowBotOpenButton(true, this::onOpenBot);
}
dialogCell.setArchivedPullAnimation(pullForegroundDrawable);
dialogCell.setPreloader(preloader);
dialogCell.setDialogCellDelegate(this);
@ -1540,4 +1543,12 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
}
return 0;
}
protected boolean showOpenBotButton() {
return false;
}
protected void onOpenBot(TLRPC.User user) {
}
}

View file

@ -442,6 +442,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
stickers = null;
stickersMap = null;
notifyDataSetChanged();
visibleByStickersSearch = false;
if (lastReqId != 0) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(lastReqId, true);
lastReqId = 0;
@ -619,6 +620,60 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
}
}
// private String lastSearchForStickersQuery;
// private Runnable searchForStickersRunnable;
// private MediaDataController.SearchStickersKey loadingSearchKey;
// public void loadMoreStickers() {
// searchForStickers(lastSearchForStickersQuery, true);
// }
// private void searchForStickers(final String q, boolean allowNext) {
// if (TextUtils.isEmpty(q)) {
// if (loadingSearchKey != null) {
// MediaDataController.getInstance(currentAccount).cancelSearchStickers(loadingSearchKey);
// loadingSearchKey = null;
// }
// if (searchForStickersRunnable != null) {
// AndroidUtilities.cancelRunOnUIThread(searchForStickersRunnable);
// searchForStickersRunnable = null;
// }
// return;
// }
// if (TextUtils.equals(lastSearchForStickersQuery, q) && (!allowNext || loadingSearchKey == null && (stickers == null || stickers.isEmpty()))) {
// return;
// }
// lastSearchForStickersQuery = q;
// AndroidUtilities.runOnUIThread(searchForStickersRunnable = () -> {
// if (!TextUtils.equals(lastSearchForStickersQuery, q)) {
// return;
// }
// final String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage();
// final String lang_code = newLanguage == null || newLanguage.length == 0 ? "" : newLanguage[0];
// if (loadingSearchKey != null) {
// MediaDataController.getInstance(currentAccount).cancelSearchStickers(loadingSearchKey);
// loadingSearchKey = null;
// }
// loadingSearchKey = MediaDataController.getInstance(currentAccount).searchStickers(false, lang_code, q, stickers -> {
// if (!TextUtils.equals(lastSearchForStickersQuery, q)) {
// return;
// }
// loadingSearchKey = null;
// int oldCount = stickers != null ? stickers.size() : 0;
// if (!stickers.isEmpty()) {
// addStickersToResult(stickers, null);
// }
// int newCount = stickers != null ? stickers.size() : 0;
// if (!visibleByStickersSearch && stickers != null && !stickers.isEmpty()) {
// checkStickerFilesExistAndDownload();
// delegate.needChangePanelVisibility(getItemCountInternal() > 0);
// visibleByStickersSearch = true;
// }
// if (oldCount != newCount) {
// notifyDataSetChanged();
// }
// }, allowNext);
// }, 600);
// }
private void searchForContextBot(final String username, final String query) {
if (foundContextBot != null && foundContextBot.username != null && foundContextBot.username.equals(username) && searchingContextQuery != null && searchingContextQuery.equals(query)) {
return;
@ -835,6 +890,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
searchResultSuggestions = null;
searchResultCommandsHelp = null;
searchResultCommandsUsers = null;
visibleByStickersSearch = false;
delegate.needChangePanelVisibility(!searchResultBotContext.isEmpty() || searchResultBotContextSwitch != null || searchResultBotWebViewSwitch != null);
if (added) {
boolean hasTop = searchResultBotContextSwitch != null || searchResultBotWebViewSwitch != null;
@ -1075,8 +1131,13 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
} else {
username = "";
}
// searchForStickers(null, false);
searchForContextBot(username, query);
} else if (allowStickers && parentFragment != null && parentFragment.getCurrentEncryptedChat() == null && (currentChat == null || ChatObject.canSendStickers(currentChat)) && text.trim().length() >= 2 && text.trim().indexOf(' ') < 0) {
// searchForStickers(text.trim(), false);
searchForContextBot(null, null);
} else {
// searchForStickers(null, false);
searchForContextBot(null, null);
}
if (foundContextBot != null) {

View file

@ -107,7 +107,6 @@ public class CachedStaticLayout {
(e = (!lastLayoutBounds.equals(getLayoutBounds()))) ||
(f = (!emojiLoadedEquals(emojiLoaded = getEmojiLoaded(), lastEmojiLoaded)))
) {
// Log.i("lolkek", "draw \"" + getText() + "\" because " + (renderNode == null ? "first" : a ? "textcolor ["+Integer.toHexString(textColor) + " => "+Integer.toHexString(layout.getPaint().getColor())+"]" : (b ? "linkcolor" : (c ? "textsize" : (d ? "typeface" : (e ? "bounds" : (f ? "emojis" : "???")))))));
textColor = layout.getPaint().getColor();
linkColor = layout.getPaint().linkColor;
textSize = layout.getPaint().getTextSize();

View file

@ -14134,7 +14134,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
canvas.save();
// canvas.translate(button.x * widthForButtons + addX + AndroidUtilities.dp(5), y + (AndroidUtilities.dp(44) - button.title.getLineBottom(button.title.getLineCount() - 1)) / 2);
button.title.ellipsize(Math.max(1, (int) (button.width * widthForButtons) - dp(10))).draw(canvas, button.x * widthForButtons + addX + (button.width * widthForButtons - button.title.getWidth()) / 2f, y + dp(44) / 2f);
button.title.ellipsize(Math.max(1, (int) (button.width * widthForButtons) - dp(15)));
button.title.draw(canvas, button.x * widthForButtons + addX + (button.width * widthForButtons - button.title.getWidth()) / 2f, y + dp(44) / 2f);
canvas.restore();
if (button.button instanceof TLRPC.TL_keyboardButtonWebView) {
Drawable drawable = getThemedDrawable(Theme.key_drawable_botWebView);

View file

@ -87,6 +87,7 @@ import org.telegram.ui.Components.AnimatedEmojiSpan;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BubbleCounterPath;
import org.telegram.ui.Components.ButtonBounce;
import org.telegram.ui.Components.CanvasButton;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.ColoredImageSpan;
@ -104,6 +105,7 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.StaticLayoutEx;
import org.telegram.ui.Components.StatusDrawable;
import org.telegram.ui.Components.SwipeGestureSettingsView;
import org.telegram.ui.Components.Text;
import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.TimerDrawable;
import org.telegram.ui.Components.TypefaceSpan;
@ -205,7 +207,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
private Path thumbPath;
private SpoilerEffect thumbSpoiler = new SpoilerEffect();
private boolean drawForwardIcon;
private boolean drawForwardIcon, drawGiftIcon;
private boolean visibleOnScreen = true;
private boolean updateLayout;
private boolean wasDrawnOnline;
@ -382,6 +384,27 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
private float currentRevealBounceProgress;
private float archiveBackgroundProgress;
private boolean openBot;
private final ButtonBounce openButtonBounce = new ButtonBounce(this);
private final Paint openButtonBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final RectF openButtonRect = new RectF();
private Text openButtonText;
public void setOpenBotButton(boolean show) {
if (openBot == show) return;
if (openButtonText == null) {
openButtonText = new Text(LocaleController.getString(R.string.BotOpen), 14, AndroidUtilities.bold());
}
openBot = show;
openButtonBounce.setPressed(false);
}
private boolean allowBotOpenButton;
private Utilities.Callback<TLRPC.User> onOpenButtonClick;
public DialogCell allowBotOpenButton(boolean allow, Utilities.Callback<TLRPC.User> onOpenClick) {
allowBotOpenButton = allow;
onOpenButtonClick = onOpenClick;
return this;
}
protected boolean overrideSwipeAction = false;
protected int overrideSwipeActionBackgroundColorKey;
protected int overrideSwipeActionRevealBackgroundColorKey;
@ -1032,6 +1055,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
drawVerified = false;
drawPremium = false;
drawForwardIcon = false;
drawGiftIcon = false;
drawScam = 0;
drawPinBackground = false;
thumbsCount = 0;
@ -1045,6 +1069,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
if (!isForumCell()) {
buttonLayout = null;
}
setOpenBotButton(false);
int messageFormatType;
if (Build.VERSION.SDK_INT >= 18) {
@ -1416,9 +1441,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(lastReaction.reaction);
currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex];
if (visibleReaction.emojicon != null) {
messageString = LocaleController.formatString("ReactionInDialog", R.string.ReactionInDialog, visibleReaction.emojicon);
messageString = LocaleController.formatString(R.string.ReactionInDialog, visibleReaction.emojicon);
} else {
String string = LocaleController.formatString("ReactionInDialog", R.string.ReactionInDialog, "**reaction**");
String string = LocaleController.formatString(R.string.ReactionInDialog, "**reaction**");
int i = string.indexOf("**reaction**");
string = string.replace("**reaction**", "d");
@ -1473,6 +1498,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
if (ChatObject.isChannelAndNotMegaGroup(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) {
messageString = "";
showChecks = false;
} else if (message.messageTextShort != null) {
messageString = message.messageTextShort;
} else {
messageString = msgText;
}
@ -1747,6 +1774,22 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
}
if (!drawForwardIcon && message != null && message.messageOwner != null && message.messageOwner.action instanceof TLRPC.TL_messageActionStarGift) {
drawGiftIcon = true;
SpannableStringBuilder builder = new SpannableStringBuilder(messageString);
builder.insert(0, "d ");
ColoredImageSpan coloredImageSpan = new ColoredImageSpan(ContextCompat.getDrawable(getContext(), R.drawable.mini_gift).mutate());
coloredImageSpan.setScale(1.25f, 1.25f);
coloredImageSpan.spaceScaleX = 0.9f;
coloredImageSpan.setAlpha(0.9f);
builder.setSpan(coloredImageSpan, 0, 1, 0);
messageString = builder;
final TLRPC.TL_messageActionStarGift action = (TLRPC.TL_messageActionStarGift) message.messageOwner.action;
if (action.message != null && !TextUtils.isEmpty(action.message.text)) {
currentMessagePaint = Theme.dialogs_messagePaint[paintIndex];
}
}
if (draftMessage != null) {
timeString = LocaleController.stringForMessageListDate(draftMessage.date);
} else if (lastMessageDate != 0) {
@ -2192,6 +2235,27 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
messageNameLeft += w;
}
}
} else if (allowBotOpenButton && UserObject.isBot(user) && user.bot_has_main_app) {
setOpenBotButton(true);
int buttonWidth = (int) (dp(2 * 13) + openButtonText.getCurrentWidth()), p = dp(13);
messageWidth -= buttonWidth;
int y;
if (useForceThreeLines || SharedConfig.useThreeLinesLayout) {
y = dp(40);
} else {
y = isTopic ? dp(33) : dp(36);
}
if (!LocaleController.isRTL) {
openButtonRect.set(getMeasuredWidth() - buttonWidth - dp(13), y, getMeasuredWidth() - dp(13), y + dp(28));
} else {
openButtonRect.set(dp(13), y, dp(13) + buttonWidth, y + dp(28));
messageLeft += buttonWidth + p;
typingLeft += buttonWidth + p;
buttonLeft += buttonWidth + p;
messageNameLeft += buttonWidth + p;
}
drawCount = false;
drawMention = false;
} else {
if (getIsPinned()) {
int w = Theme.dialogs_pinnedDrawable.getIntrinsicWidth() + dp(8);
@ -2553,7 +2617,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
float x1 = layout.getPrimaryHorizontal(spanOffset);
float x2 = layout.getPrimaryHorizontal(spanOffset + 1);
int offset = (int) Math.ceil(Math.min(x1, x2));
if (offset != 0 && !drawForwardIcon) {
if (offset != 0 && !drawForwardIcon && !drawGiftIcon) {
offset += dp(3);
}
for (int i = 0; i < thumbsCount; ++i) {
@ -3278,59 +3342,59 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
if (archiveHidden) {
backgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground, resourcesProvider);
revealBackgroundColor = Theme.getColor(Theme.key_chats_archiveBackground, resourcesProvider);
swipeMessage = LocaleController.getString("UnhideFromTop", swipeMessageStringId = R.string.UnhideFromTop);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.UnhideFromTop);
translationDrawable = Theme.dialogs_unpinArchiveDrawable;
} else {
backgroundColor = Theme.getColor(Theme.key_chats_archiveBackground, resourcesProvider);
revealBackgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground, resourcesProvider);
swipeMessage = LocaleController.getString("HideOnTop", swipeMessageStringId = R.string.HideOnTop);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.HideOnTop);
translationDrawable = Theme.dialogs_pinArchiveDrawable;
}
} else {
if (promoDialog) {
backgroundColor = Theme.getColor(Theme.key_chats_archiveBackground, resourcesProvider);
revealBackgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground, resourcesProvider);
swipeMessage = LocaleController.getString("PsaHide", swipeMessageStringId = R.string.PsaHide);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.PsaHide);
translationDrawable = Theme.dialogs_hidePsaDrawable;
} else if (folderId == 0) {
backgroundColor = Theme.getColor(Theme.key_chats_archiveBackground, resourcesProvider);
revealBackgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground, resourcesProvider);
if (SharedConfig.getChatSwipeAction(currentAccount) == SwipeGestureSettingsView.SWIPE_GESTURE_MUTE) {
if (dialogMuted) {
swipeMessage = LocaleController.getString("SwipeUnmute", swipeMessageStringId = R.string.SwipeUnmute);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeUnmute);
translationDrawable = Theme.dialogs_swipeUnmuteDrawable;
} else {
swipeMessage = LocaleController.getString("SwipeMute", swipeMessageStringId = R.string.SwipeMute);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeMute);
translationDrawable = Theme.dialogs_swipeMuteDrawable;
}
} else if (SharedConfig.getChatSwipeAction(currentAccount) == SwipeGestureSettingsView.SWIPE_GESTURE_DELETE) {
swipeMessage = LocaleController.getString("SwipeDeleteChat", swipeMessageStringId = R.string.SwipeDeleteChat);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeDeleteChat);
backgroundColor = Theme.getColor(Theme.key_dialogSwipeRemove, resourcesProvider);
translationDrawable = Theme.dialogs_swipeDeleteDrawable;
} else if (SharedConfig.getChatSwipeAction(currentAccount) == SwipeGestureSettingsView.SWIPE_GESTURE_READ) {
if (unreadCount > 0 || markUnread) {
swipeMessage = LocaleController.getString("SwipeMarkAsRead", swipeMessageStringId = R.string.SwipeMarkAsRead);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeMarkAsRead);
translationDrawable = Theme.dialogs_swipeReadDrawable;
} else {
swipeMessage = LocaleController.getString("SwipeMarkAsUnread", swipeMessageStringId = R.string.SwipeMarkAsUnread);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeMarkAsUnread);
translationDrawable = Theme.dialogs_swipeUnreadDrawable;
}
} else if (SharedConfig.getChatSwipeAction(currentAccount) == SwipeGestureSettingsView.SWIPE_GESTURE_PIN) {
if (getIsPinned()) {
swipeMessage = LocaleController.getString("SwipeUnpin", swipeMessageStringId = R.string.SwipeUnpin);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipeUnpin);
translationDrawable = Theme.dialogs_swipeUnpinDrawable;
} else {
swipeMessage = LocaleController.getString("SwipePin", swipeMessageStringId = R.string.SwipePin);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.SwipePin);
translationDrawable = Theme.dialogs_swipePinDrawable;
}
} else {
swipeMessage = LocaleController.getString("Archive", swipeMessageStringId = R.string.Archive);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.Archive);
translationDrawable = Theme.dialogs_archiveDrawable;
}
} else {
backgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground, resourcesProvider);
revealBackgroundColor = Theme.getColor(Theme.key_chats_archiveBackground, resourcesProvider);
swipeMessage = LocaleController.getString("Unarchive", swipeMessageStringId = R.string.Unarchive);
swipeMessage = LocaleController.getString(swipeMessageStringId = R.string.Unarchive);
translationDrawable = Theme.dialogs_unarchiveDrawable;
}
}
@ -3945,6 +4009,16 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
Theme.dialogs_reactionsMentionDrawable.draw(canvas);
canvas.restore();
}
} else if (openBot) {
canvas.save();
final float scale = openButtonBounce.getScale(.05f);
canvas.scale(scale, scale, openButtonRect.centerX(), openButtonRect.centerY());
openButtonBackgroundPaint.setColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider));
canvas.drawRoundRect(openButtonRect, openButtonRect.height() / 2.0f, openButtonRect.height() / 2.0f, openButtonBackgroundPaint);
if (openButtonText != null) {
openButtonText.draw(canvas, openButtonRect.left + dp(13), openButtonRect.centerY(), Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider), 1.0f);
}
canvas.restore();
} else if (getIsPinned()) {
Theme.dialogs_pinnedDrawable.setAlpha((int) ((1.0f - reorderIconProgress) * 255));
setDrawableBounds(Theme.dialogs_pinnedDrawable, pinLeft, pinTop);
@ -5337,6 +5411,22 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
return true;
}
if (delegate == null || delegate.canClickButtonInside()) {
if (openBot) {
final boolean hit = openButtonRect.contains(event.getX(), event.getY());
if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) {
openButtonBounce.setPressed(hit);
} else if (openButtonBounce.isPressed() && event.getAction() == MotionEvent.ACTION_UP) {
if (onOpenButtonClick != null) {
onOpenButtonClick.run(user);
}
openButtonBounce.setPressed(false);
return true;
} else if (openButtonBounce.isPressed() && event.getAction() == MotionEvent.ACTION_CANCEL) {
openButtonBounce.setPressed(false);
return true;
}
if (hit) return true;
}
if (lastTopicMessageUnread && canvasButton != null && buttonLayout != null && (dialogsType == DialogsActivity.DIALOGS_TYPE_DEFAULT || dialogsType == DialogsActivity.DIALOGS_TYPE_FOLDER1 || dialogsType == DialogsActivity.DIALOGS_TYPE_FOLDER2) && canvasButton.checkTouchEvent(event)) {
return true;
}

View file

@ -101,7 +101,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
private boolean drawCount;
private int lastUnreadCount;
private int countTop = AndroidUtilities.dp(19);
private int countTop = dp(19);
private int countLeft;
private int countWidth;
private StaticLayout countLayout;
@ -134,7 +134,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
this.resourcesProvider = resourcesProvider;
avatarImage = new ImageReceiver(this);
avatarImage.setRoundRadius(AndroidUtilities.dp(23));
avatarImage.setRoundRadius(dp(23));
avatarDrawable = new AvatarDrawable();
checkBox = new CheckBox2(context, 21, resourcesProvider);
@ -143,7 +143,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
checkBox.setDrawBackgroundAsArc(3);
addView(checkBox);
statusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(20));
statusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, dp(20));
statusDrawable.setCallback(this);
}
@ -319,9 +319,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (checkBox != null) {
checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY));
checkBox.measure(MeasureSpec.makeMeasureSpec(dp(24), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(24), MeasureSpec.EXACTLY));
}
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(60) + (useSeparator ? 1 : 0));
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), dp(60) + (useSeparator ? 1 : 0));
}
@Override
@ -330,8 +330,8 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
return;
}
if (checkBox != null) {
int x = LocaleController.isRTL ? (right - left) - AndroidUtilities.dp(42) : AndroidUtilities.dp(42);
int y = AndroidUtilities.dp(36);
int x = LocaleController.isRTL ? (right - left) - dp(42) : dp(42);
int y = dp(36);
checkBox.layout(x, y, x + checkBox.getMeasuredWidth(), y + checkBox.getMeasuredHeight());
}
if (changed) {
@ -364,40 +364,40 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
drawNameLock = true;
dialog_id = DialogObject.makeEncryptedDialogId(encryptedChat.id);
if (!LocaleController.isRTL) {
nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_lockDrawable.getIntrinsicWidth();
nameLockLeft = dp(AndroidUtilities.leftBaseline);
nameLeft = dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_lockDrawable.getIntrinsicWidth();
} else {
nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - Theme.dialogs_lockDrawable.getIntrinsicWidth();
nameLeft = AndroidUtilities.dp(11);
nameLockLeft = getMeasuredWidth() - dp(AndroidUtilities.leftBaseline + 2) - Theme.dialogs_lockDrawable.getIntrinsicWidth();
nameLeft = dp(11);
}
nameLockTop = AndroidUtilities.dp(22.0f);
nameLockTop = dp(22.0f);
updateStatus(false, null, null, false);
} else if (chat != null) {
dialog_id = -chat.id;
drawCheck = chat.verified;
if (!LocaleController.isRTL) {
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = dp(AndroidUtilities.leftBaseline);
} else {
nameLeft = AndroidUtilities.dp(11);
nameLeft = dp(11);
}
updateStatus(drawCheck, null, chat, false);
} else if (user != null) {
dialog_id = user.id;
if (!LocaleController.isRTL) {
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = dp(AndroidUtilities.leftBaseline);
} else {
nameLeft = AndroidUtilities.dp(11);
nameLeft = dp(11);
}
nameLockTop = AndroidUtilities.dp(21);
nameLockTop = dp(21);
drawCheck = user.verified;
drawPremium = !savedMessages && MessagesController.getInstance(currentAccount).isPremiumUser(user);
updateStatus(drawCheck, user, null, false);
} else if (contact != null) {
dialog_id = 0;
if (!LocaleController.isRTL) {
nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
nameLeft = dp(AndroidUtilities.leftBaseline);
} else {
nameLeft = AndroidUtilities.dp(11);
nameLeft = dp(11);
}
if (actionButton == null) {
actionButton = new CanvasButton(this);
@ -412,9 +412,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
}
}
if (!LocaleController.isRTL) {
statusLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline);
statusLeft = dp(AndroidUtilities.leftBaseline);
} else {
statusLeft = AndroidUtilities.dp(11);
statusLeft = dp(11);
}
if (currentName != null) {
@ -440,7 +440,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
namePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
namePaint.setTypeface(AndroidUtilities.bold());
}
namePaint.setTextSize(AndroidUtilities.dp(16));
namePaint.setTextSize(dp(16));
if (encryptedChat != null) {
namePaint.setColor(Theme.getColor(Theme.key_chats_secretName, resourcesProvider));
} else {
@ -455,25 +455,25 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
int statusWidth;
if (!LocaleController.isRTL) {
statusWidth = nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(14);
statusWidth = nameWidth = getMeasuredWidth() - nameLeft - dp(14);
} else {
statusWidth = nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(AndroidUtilities.leftBaseline);
statusWidth = nameWidth = getMeasuredWidth() - nameLeft - dp(AndroidUtilities.leftBaseline);
}
if (drawNameLock) {
nameWidth -= AndroidUtilities.dp(6) + Theme.dialogs_lockDrawable.getIntrinsicWidth();
nameWidth -= dp(6) + Theme.dialogs_lockDrawable.getIntrinsicWidth();
}
if (contact != null) {
int w = (int) (Theme.dialogs_countTextPaint.measureText(LocaleController.getString(R.string.Invite)) + 1);
actionLayout = new StaticLayout(LocaleController.getString(R.string.Invite), Theme.dialogs_countTextPaint, w, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
if (!LocaleController.isRTL) {
actionLeft = getMeasuredWidth() - w - AndroidUtilities.dp(19) - AndroidUtilities.dp(16);
actionLeft = getMeasuredWidth() - w - dp(19) - dp(16);
} else {
actionLeft = AndroidUtilities.dp(19) + AndroidUtilities.dp(16);
actionLeft = dp(19) + dp(16);
nameLeft += w;
statusLeft += w;
}
nameWidth -= AndroidUtilities.dp(32) + w;
nameWidth -= dp(32) + w;
}
nameWidth -= getPaddingLeft() + getPaddingRight();
@ -485,15 +485,15 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
if (unreadCount != 0) {
lastUnreadCount = unreadCount;
String countString = String.format(Locale.US, "%d", unreadCount);
countWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(countString)));
countWidth = Math.max(dp(12), (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(countString)));
countLayout = new StaticLayout(countString, Theme.dialogs_countTextPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
int w = countWidth + AndroidUtilities.dp(18);
int w = countWidth + dp(18);
nameWidth -= w;
statusWidth -= w;
if (!LocaleController.isRTL) {
countLeft = getMeasuredWidth() - countWidth - AndroidUtilities.dp(19);
countLeft = getMeasuredWidth() - countWidth - dp(19);
} else {
countLeft = AndroidUtilities.dp(19);
countLeft = dp(19);
nameLeft += w;
statusLeft += w;
}
@ -509,9 +509,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
if (nameWidth < 0) {
nameWidth = 0;
}
CharSequence nameStringFinal = TextUtils.ellipsize(nameString, currentNamePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
CharSequence nameStringFinal = TextUtils.ellipsize(nameString, currentNamePaint, nameWidth - dp(12), TextUtils.TruncateAt.END);
if (nameStringFinal != null) {
nameStringFinal = Emoji.replaceEmoji(nameStringFinal, currentNamePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
nameStringFinal = Emoji.replaceEmoji(nameStringFinal, currentNamePaint.getFontMetricsInt(), dp(20), false);
}
nameLayout = new StaticLayout(nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
@ -548,7 +548,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
}
if (savedMessages || UserObject.isReplyUser(user)) {
statusString = null;
nameTop = AndroidUtilities.dp(20);
nameTop = dp(20);
}
} else {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
@ -574,13 +574,13 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
}
}
}
nameTop = AndroidUtilities.dp(19);
nameTop = dp(19);
}
if (customPaints) {
if (statusPaint == null) {
statusPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
}
statusPaint.setTextSize(AndroidUtilities.dp(15));
statusPaint.setTextSize(dp(15));
if (currentStatusPaint == Theme.dialogs_offlinePaint) {
statusPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3, resourcesProvider));
} else if (currentStatusPaint == Theme.dialogs_onlinePaint) {
@ -590,22 +590,22 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
}
if (!TextUtils.isEmpty(statusString)) {
CharSequence statusStringFinal = TextUtils.ellipsize(statusString, currentStatusPaint, statusWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
CharSequence statusStringFinal = TextUtils.ellipsize(statusString, currentStatusPaint, statusWidth - dp(12), TextUtils.TruncateAt.END);
statusLayout = new StaticLayout(statusStringFinal, currentStatusPaint, statusWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
nameTop = AndroidUtilities.dp(9);
nameLockTop -= AndroidUtilities.dp(10);
nameTop = dp(9);
nameLockTop -= dp(10);
} else {
nameTop = AndroidUtilities.dp(20);
nameTop = dp(20);
statusLayout = null;
}
int avatarLeft;
if (LocaleController.isRTL) {
avatarLeft = getMeasuredWidth() - AndroidUtilities.dp(57) - getPaddingRight();
avatarLeft = getMeasuredWidth() - dp(57) - getPaddingRight();
} else {
avatarLeft = AndroidUtilities.dp(11) + getPaddingLeft();
avatarLeft = dp(rectangularAvatar ? 15 : 11) + getPaddingLeft();
}
avatarStoryParams.originalAvatarRect.set(avatarLeft, AndroidUtilities.dp(7), avatarLeft + AndroidUtilities.dp(46), AndroidUtilities.dp(7) + AndroidUtilities.dp(46));
avatarStoryParams.originalAvatarRect.set(avatarLeft, dp(7), avatarLeft + dp(rectangularAvatar ? 42 : 46), dp(7) + dp(46));
double widthpx;
float left;
@ -674,6 +674,11 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
}
}
private boolean rectangularAvatar;
public void setRectangularAvatar(boolean value) {
rectangularAvatar = value;
}
public void update(int mask) {
TLRPC.FileLocation photo = null;
if (user != null) {
@ -712,7 +717,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
avatarImage.setImage(null, null, avatarDrawable, null, null, 0);
}
avatarImage.setRoundRadius(chat != null && chat.forum ? AndroidUtilities.dp(16) : AndroidUtilities.dp(23));
avatarImage.setRoundRadius(rectangularAvatar ? dp(10) : chat != null && chat.forum ? dp(16) : dp(23));
if (mask != 0) {
boolean continueUpdate = false;
if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 && user != null || (mask & MessagesController.UPDATE_MASK_CHAT_AVATAR) != 0 && chat != null) {
@ -794,9 +799,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
dividerPaint = Theme.dividerPaint;
}
if (LocaleController.isRTL) {
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, dividerPaint);
canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, dividerPaint);
} else {
canvas.drawLine(AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, dividerPaint);
canvas.drawLine(dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, dividerPaint);
}
}
@ -814,13 +819,13 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
int x;
if (LocaleController.isRTL) {
if (nameLayout.getLineLeft(0) == 0) {
x = nameLeft - AndroidUtilities.dp(3) - statusDrawable.getIntrinsicWidth();
x = nameLeft - dp(3) - statusDrawable.getIntrinsicWidth();
} else {
float w = nameLayout.getLineWidth(0);
x = (int) (nameLeft + nameWidth - Math.ceil(w) - AndroidUtilities.dp(3) - statusDrawable.getIntrinsicWidth());
x = (int) (nameLeft + nameWidth - Math.ceil(w) - dp(3) - statusDrawable.getIntrinsicWidth());
}
} else {
x = (int) (nameLeft + nameLayout.getLineRight(0) + AndroidUtilities.dp(6));
x = (int) (nameLeft + nameLayout.getLineRight(0) + dp(6));
}
setDrawableBounds(statusDrawable, x, nameTop + (nameLayout.getHeight() - statusDrawable.getIntrinsicHeight()) / 2f);
statusDrawable.draw(canvas);
@ -828,31 +833,31 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
if (statusLayout != null) {
canvas.save();
canvas.translate(statusLeft + sublabelOffsetX, AndroidUtilities.dp(33) + sublabelOffsetY);
canvas.translate(statusLeft + sublabelOffsetX, dp(33) + sublabelOffsetY);
statusLayout.draw(canvas);
canvas.restore();
}
if (countLayout != null) {
int x = countLeft - AndroidUtilities.dp(5.5f);
rect.set(x, countTop, x + countWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23));
int x = countLeft - dp(5.5f);
rect.set(x, countTop, x + countWidth + dp(11), countTop + dp(23));
canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id, 0) ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint);
canvas.save();
canvas.translate(countLeft, countTop + AndroidUtilities.dp(4));
canvas.translate(countLeft, countTop + dp(4));
countLayout.draw(canvas);
canvas.restore();
}
if (actionLayout != null) {
actionButton.setColor(Theme.getColor(Theme.key_chats_unreadCounter), Theme.getColor(Theme.key_chats_unreadCounterText));
AndroidUtilities.rectTmp.set(actionLeft, countTop, actionLeft + actionLayout.getWidth(), countTop + AndroidUtilities.dp(23));
AndroidUtilities.rectTmp.inset(-AndroidUtilities.dp(16), -AndroidUtilities.dp(4));
AndroidUtilities.rectTmp.set(actionLeft, countTop, actionLeft + actionLayout.getWidth(), countTop + dp(23));
AndroidUtilities.rectTmp.inset(-dp(16), -dp(4));
actionButton.setRect(AndroidUtilities.rectTmp);
actionButton.setRounded(true);
actionButton.draw(canvas);
canvas.save();
canvas.translate(actionLeft, countTop + AndroidUtilities.dp(4));
canvas.translate(actionLeft, countTop + dp(4));
actionLayout.draw(canvas);
canvas.restore();
}

View file

@ -94,7 +94,10 @@ public class SlideIntChooseView extends FrameLayout {
if (options == null || whenChanged == null) {
return;
}
final int newValue = (int) Math.round(options.min + stepsCount * progress);
int newValue = (int) Math.round(options.min + stepsCount * progress);
if (minValueAllowed != Integer.MIN_VALUE) {
newValue = Math.max(newValue, minValueAllowed);
}
if (value != newValue) {
value = newValue;
AndroidUtilities.vibrateCursor(seekBarView);
@ -114,6 +117,7 @@ public class SlideIntChooseView extends FrameLayout {
}
private int value;
private int minValueAllowed = Integer.MIN_VALUE;
private Utilities.Callback<Integer> whenChanged;
private Options options;
@ -132,28 +136,23 @@ public class SlideIntChooseView extends FrameLayout {
updateTexts(value, false);
}
public void setMinValueAllowed(int value) {
minValueAllowed = value;
if (this.value < minValueAllowed) {
this.value = minValueAllowed;
}
seekBarView.setMinProgress(Utilities.clamp01((float) (value - options.min) / stepsCount));
updateTexts(this.value, false);
invalidate();
}
public void updateTexts(int value, boolean animated) {
minText.cancelAnimation();
maxText.cancelAnimation();
if (!TextUtils.isEmpty(options.resId)) {
valueText.cancelAnimation();
valueText.setText(LocaleController.formatPluralString(options.resId, value), animated);
minText.setText("" + options.min, animated);
maxText.setText("" + options.max, animated);
} else {
int valueResId;
if (value <= options.min) {
valueResId = options.valueMinStringResId;
} else if (value < options.max) {
valueResId = options.valueStringResId;
} else {
valueResId = options.valueMaxStringResId;
}
valueText.cancelAnimation();
valueText.setText(processText(valueResId, value), animated);
minText.setText(processText(options.minStringResId, options.min), animated);
maxText.setText(processText(options.maxStringResId, options.max), animated);
}
valueText.setText(options.toString.run(0, value), animated);
minText.setText(options.toString.run(-1, options.min), animated);
maxText.setText(options.toString.run(+1, options.max), animated);
maxText.setTextColor(Theme.getColor(value >= options.max ? Theme.key_windowBackgroundWhiteValueText : Theme.key_windowBackgroundWhiteGrayText, resourcesProvider), animated);
setMaxTextEmojiSaturation(value >= options.max ? 1f : 0f, animated);
}
@ -203,14 +202,6 @@ public class SlideIntChooseView extends FrameLayout {
}
}
private CharSequence processText(int resId, int value) {
String string = getString(resId);
string = string.replace("%d", "" + value);
CharSequence cs = AndroidUtilities.replaceTags(string);
cs = ChannelMonetizationLayout.replaceTON(cs, valueText.getPaint());
return cs;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(
@ -232,27 +223,18 @@ public class SlideIntChooseView extends FrameLayout {
public int min;
public int max;
public String resId;
public int minStringResId;
public int valueMinStringResId, valueStringResId, valueMaxStringResId;
public int maxStringResId;
public Utilities.Callback2Return<Integer, Integer, String> toString;
public static Options make(
int style,
int min, int minStringResId,
int valueMinStringResId, int valueStringResId, int valueMaxStringResId,
int max, int maxStringResId
int min, int max,
Utilities.CallbackReturn<Integer, String> toString
) {
Options o = new Options();
o.style = style;
o.min = min;
o.minStringResId = minStringResId;
o.valueMinStringResId = valueMinStringResId;
o.valueStringResId = valueStringResId;
o.valueMaxStringResId = valueMaxStringResId;
o.max = max;
o.maxStringResId = maxStringResId;
o.toString = (type, val) -> toString.run(val);
return o;
}
@ -263,8 +245,8 @@ public class SlideIntChooseView extends FrameLayout {
Options o = new Options();
o.style = style;
o.min = min;
o.resId = resId;
o.max = max;
o.toString = (type, val) -> type == 0 ? LocaleController.formatPluralString(resId, val) : "" + val;
return o;
}
}

View file

@ -6,6 +6,7 @@ import static org.telegram.messenger.AndroidUtilities.makeBlurBitmap;
import static org.telegram.messenger.LocaleController.formatPluralString;
import static org.telegram.messenger.LocaleController.formatString;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.ChatEditActivity.applyNewSpan;
import android.app.Activity;
import android.content.Context;
@ -91,6 +92,8 @@ import org.telegram.ui.Stars.BotStarsActivity;
import org.telegram.ui.Stars.BotStarsController;
import org.telegram.ui.Stars.StarsIntroActivity;
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
import org.telegram.ui.bots.AffiliateProgramFragment;
import org.telegram.ui.bots.ChannelAffiliateProgramsFragment;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@ -125,7 +128,7 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
private int starsBalanceBlockedUntil;
private final LinearLayout starsBalanceLayout;
private final RelativeSizeSpan starsBalanceTitleSizeSpan;
private long starsBalance;
private TL_stars.StarsAmount starsBalance = new TL_stars.StarsAmount(0);
private final AnimatedTextView starsBalanceTitle;
private final AnimatedTextView starsBalanceSubtitle;
private final ButtonWithCounterView starsBalanceButton;
@ -327,16 +330,15 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
@Override
public void afterTextChanged(Editable s) {
if (starsBalanceEditTextIgnore) return;
long balance = starsBalance;
starsBalanceEditTextValue = TextUtils.isEmpty(s) ? 0 : Long.parseLong(s.toString());
if (starsBalanceEditTextValue > balance) {
starsBalanceEditTextValue = balance;
if (starsBalanceEditTextValue > starsBalance.amount) {
starsBalanceEditTextValue = starsBalance.amount;
starsBalanceEditTextIgnore = true;
starsBalanceEditText.setText(Long.toString(starsBalanceEditTextValue));
starsBalanceEditText.setSelection(starsBalanceEditText.getText().length());
starsBalanceEditTextIgnore = false;
}
starsBalanceEditTextAll = starsBalanceEditTextValue == balance;
starsBalanceEditTextAll = starsBalanceEditTextValue == starsBalance.amount;
AndroidUtilities.cancelRunOnUIThread(setStarsBalanceButtonText);
setStarsBalanceButtonText.run();
starsBalanceEditTextAll = false;
@ -380,10 +382,9 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
Drawable starDrawable = getContext().getResources().getDrawable(R.drawable.star_small_inner).mutate();
BulletinFactory.of(fragment).createSimpleBulletin(starDrawable, AndroidUtilities.replaceSingleTag(LocaleController.formatPluralString("BotStarsWithdrawMinLimit", (int) MessagesController.getInstance(currentAccount).starsRevenueWithdrawalMin), () -> {
Bulletin.hideVisible();
long balance = starsBalance;
if (balance < MessagesController.getInstance(currentAccount).starsRevenueWithdrawalMin) {
if (starsBalance.amount < MessagesController.getInstance(currentAccount).starsRevenueWithdrawalMin) {
starsBalanceEditTextAll = true;
starsBalanceEditTextValue = balance;
starsBalanceEditTextValue = starsBalance.amount;
} else {
starsBalanceEditTextAll = false;
starsBalanceEditTextValue = MessagesController.getInstance(currentAccount).starsRevenueWithdrawalMin;
@ -661,29 +662,29 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
balanceSubtitle.setText("" + BillingController.getInstance().formatCurrency(amount, "USD"));
}
private void setStarsBalance(long crypto_amount, int blockedUntil) {
private void setStarsBalance(TL_stars.StarsAmount amount, int blockedUntil) {
if (balanceTitle == null || balanceSubtitle == null)
return;
long amount = (long) (stars_rate * crypto_amount * 100.0);
SpannableStringBuilder ssb = new SpannableStringBuilder(StarsIntroActivity.replaceStarsWithPlain("XTR " + LocaleController.formatNumber(crypto_amount, ' '), 1f));
// long amount = (long) (stars_rate * crypto_amount * 100.0);
SpannableStringBuilder ssb = new SpannableStringBuilder(StarsIntroActivity.replaceStarsWithPlain(TextUtils.concat("XTR ", StarsIntroActivity.formatStarsAmount(amount, 0.8f, ' ')), 1f));
int index = TextUtils.indexOf(ssb, ".");
if (index >= 0) {
ssb.setSpan(balanceTitleSizeSpan, index, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
starsBalance = crypto_amount;
starsBalance = amount;
starsBalanceTitle.setText(ssb);
starsBalanceSubtitle.setText("" + BillingController.getInstance().formatCurrency(amount, "USD"));
starsBalanceEditTextContainer.setVisibility(crypto_amount > 0 ? VISIBLE : GONE);
starsBalanceSubtitle.setText("" + BillingController.getInstance().formatCurrency((long) (stars_rate * amount.amount * 100.0), "USD"));
starsBalanceEditTextContainer.setVisibility(amount.amount > 0 ? VISIBLE : GONE);
if (starsBalanceEditTextAll) {
starsBalanceEditTextIgnore = true;
starsBalanceEditText.setText(Long.toString(starsBalanceEditTextValue = crypto_amount));
starsBalanceEditText.setText(Long.toString(starsBalanceEditTextValue = amount.amount));
starsBalanceEditText.setSelection(starsBalanceEditText.getText().length());
starsBalanceEditTextIgnore = false;
starsBalanceButton.setEnabled(starsBalanceEditTextValue > 0);
}
if (starsAdsButton != null) {
starsAdsButton.setEnabled(amount > 0);
starsAdsButton.setEnabled(amount.amount > 0);
}
starsBalanceBlockedUntil = blockedUntil;
@ -829,23 +830,23 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
}
availableValue.contains2 = true;
availableValue.crypto_amount2 = balances.available_balance;
availableValue.amount2 = (long) (availableValue.crypto_amount2 * stars_rate * 100.0);
availableValue.amount2 = (long) (availableValue.crypto_amount2.amount * stars_rate * 100.0);
setStarsBalance(availableValue.crypto_amount2, balances.next_withdrawal_at);
availableValue.currency = "USD";
lastWithdrawalValue.contains2 = true;
lastWithdrawalValue.crypto_amount2 = balances.current_balance;
lastWithdrawalValue.amount2 = (long) (lastWithdrawalValue.crypto_amount2 * stars_rate * 100.0);
lastWithdrawalValue.amount2 = (long) (lastWithdrawalValue.crypto_amount2.amount * stars_rate * 100.0);
lastWithdrawalValue.currency = "USD";
lifetimeValue.contains2 = true;
lifetimeValue.crypto_amount2 = balances.overall_revenue;
lifetimeValue.amount2 = (long) (lifetimeValue.crypto_amount2 * stars_rate * 100.0);
lifetimeValue.amount2 = (long) (lifetimeValue.crypto_amount2.amount * stars_rate * 100.0);
lifetimeValue.currency = "USD";
proceedsAvailable = true;
if (starsBalanceButtonsLayout != null) {
starsBalanceButtonsLayout.setVisibility(balances.withdrawal_enabled ? View.VISIBLE : View.GONE);
}
if (starsBalanceButton != null) {
starsBalanceButton.setVisibility(balances.available_balance > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE);
starsBalanceButton.setVisibility(balances.available_balance.amount > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE);
}
if (listView != null && listView.adapter != null) {
@ -899,6 +900,7 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
private final static int CHECK_SWITCHOFF = 1;
private final static int BUTTON_LOAD_MORE_TRANSACTIONS = 2;
private final static int STARS_BALANCE = 3;
private final static int BUTTON_AFFILIATE =4;
private void fillItems(ArrayList<UItem> items, UniversalAdapter adapter) {
int stats_dc = -1;
@ -946,6 +948,10 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
items.add(UItem.asShadow(-6, starsBalanceInfo));
}
}
if (MessagesController.getInstance(currentAccount).starrefConnectAllowed) {
items.add(AffiliateProgramFragment.ColorfulTextCell.Factory.as(BUTTON_AFFILIATE, Theme.getColor(Theme.key_color_green, resourcesProvider), R.drawable.filled_earn_stars, applyNewSpan(getString(R.string.ChannelAffiliateProgramRowTitle)), getString(R.string.ChannelAffiliateProgramRowText)));
items.add(UItem.asShadow(-7, null));
}
if (transactionsLayout.hasTransactions()) {
items.add(UItem.asFullscreenCustom(transactionsLayout, 0));
} else {
@ -970,6 +976,8 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
AndroidUtilities.cancelRunOnUIThread(sendCpmUpdateRunnable);
AndroidUtilities.runOnUIThread(sendCpmUpdateRunnable, 1000);
listView.adapter.update(true);
} else if (item.id == BUTTON_AFFILIATE) {
fragment.presentFragment(new ChannelAffiliateProgramsFragment(dialogId));
}
}
@ -1095,7 +1103,11 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
for (int i = 0; i < 2; ++i) {
final String crypto_currency = i == 0 ? value.crypto_currency : value.crypto_currency2;
final long crypto_amount = i == 0 ? value.crypto_amount : value.crypto_amount2;
// final long crypto_amount = i == 0 ? value.crypto_amount : value.crypto_amount2;
// CharSequence cryptoAmount;
// if (i == 0) {
// cryptoAmount
// }
final long amount = i == 0 ? value.amount : value.amount2;
if (i == 0 && !value.contains1) {
@ -1107,17 +1119,23 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
continue;
}
CharSequence s = crypto_currency + " ";
SpannableStringBuilder s = new SpannableStringBuilder(crypto_currency + " ");
CharSequence finalS;
if ("TON".equalsIgnoreCase(crypto_currency)) {
s += formatter.format(crypto_amount / 1_000_000_000.0);
s = replaceTON(s, cryptoAmountView[i].getPaint(), .87f, true);
s.append(formatter.format(value.crypto_amount / 1_000_000_000.0));
finalS = replaceTON(s, cryptoAmountView[i].getPaint(), .87f, true);
} else if ("XTR".equalsIgnoreCase(crypto_currency)) {
s += LocaleController.formatNumber(crypto_amount, ' ');
s = StarsIntroActivity.replaceStarsWithPlain(s, .8f);
if (i == 0) {
s.append(LocaleController.formatNumber(value.crypto_amount, ' '));
} else {
s += Long.toString(crypto_amount);
s.append(StarsIntroActivity.formatStarsAmount(value.crypto_amount2, .8f, ' '));
}
SpannableStringBuilder cryptoAmount = new SpannableStringBuilder(s);
finalS = StarsIntroActivity.replaceStarsWithPlain(s, .8f);
} else {
s.append(Long.toString(value.crypto_amount));
finalS = s;
}
SpannableStringBuilder cryptoAmount = new SpannableStringBuilder(finalS);
if ("TON".equalsIgnoreCase(crypto_currency)) {
int index = TextUtils.indexOf(cryptoAmount, ".");
if (index >= 0) {
@ -1147,7 +1165,7 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
public boolean contains2;
public String crypto_currency2;
public long crypto_amount2;
public TL_stars.StarsAmount crypto_amount2 = new TL_stars.StarsAmount(0);
public long amount2;
public static ProceedOverview as(String cryptoCurrency, CharSequence text) {
@ -1808,8 +1826,8 @@ public class ChannelMonetizationLayout extends SizeNotifierFrameLayout implement
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
req.offset = starsLastOffset;
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
starsTransactions.addAll(r.history);

View file

@ -12796,7 +12796,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
chatAttachAlert.enableDefaultMode();
chatAttachAlert.init();
chatAttachAlert.getCommentTextView().setText(chatActivityEnterView.getFieldText());
chatAttachAlert.getCommentView().setText(chatActivityEnterView.getFieldText());
chatAttachAlert.parentThemeDelegate = themeDelegate;
showDialog(chatAttachAlert);
}
@ -23462,7 +23462,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
messageObject.generateGameMessageText(null);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
messageObject.generatePaymentSentMessageText(null);
messageObject.generatePaymentSentMessageText(null, false);
}else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
messageObject.generatePaymentSentMessageText(null, true);
}
}
@ -24498,7 +24500,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) {
messageObject.generateGameMessageText(null);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) {
messageObject.generatePaymentSentMessageText(null);
messageObject.generatePaymentSentMessageText(null, false);
} else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSentMe) {
messageObject.generatePaymentSentMessageText(null, true);
}
}
if (old.isWebpage() && messageObject.isWebpage()) {
@ -37153,24 +37157,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (getMessagesController().premiumFeaturesBlocked() || span == null || span.standard) {
return false;
}
long documentId = span.getDocumentId();
TLRPC.Document document = span.document == null ? AnimatedEmojiDrawable.findDocument(currentAccount, documentId) : span.document;
if (document == null) {
return false;
}
Bulletin bulletin = BulletinFactory.of(ChatActivity.this).createContainsEmojiBulletin(document, BulletinFactory.CONTAINS_EMOJI_IN_MESSAGE, set -> {
ArrayList<TLRPC.InputStickerSet> inputSets = new ArrayList<>(1);
inputSets.add(set);
EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets);
final long documentId = span.getDocumentId();
final TLRPC.Document document = span.document == null ? AnimatedEmojiDrawable.findDocument(currentAccount, documentId) : span.document;
if (document == null) return false;
final TLRPC.InputStickerSet inputStickerSet = MessageObject.getInputStickerSet(document);
if (inputStickerSet == null) return false;
final TLRPC.TL_messages_stickerSet cachedSet = MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSet(inputStickerSet, true);
// if (cachedSet == null || cachedSet.set == null) {
// final boolean[] cancelled = new boolean[1];
// final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER);
// progressDialog.showDelayed(200);
// progressDialog.setCanCancel(true);
// progressDialog.setOnCancelListener(d -> cancelled[0] = true);
// MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSet(inputStickerSet, null, false, set -> {
// if (cancelled[0]) return;
// ArrayList<TLRPC.InputStickerSet> inputSets = new ArrayList<>(1);
// inputSets.add(inputStickerSet);
// EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets);
// alert.setCalcMandatoryInsets(isKeyboardVisible());
// showDialog(alert);
// });
// } else {
final ArrayList<TLRPC.InputStickerSet> inputSets = new ArrayList<>(1);
inputSets.add(inputStickerSet);
final EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets);
alert.setPreviewEmoji(document);
alert.setCalcMandatoryInsets(isKeyboardVisible());
showDialog(alert);
});
if (bulletin != null) {
bulletin.show();
// }
// Bulletin bulletin = BulletinFactory.of(ChatActivity.this).createContainsEmojiBulletin(document, BulletinFactory.CONTAINS_EMOJI_IN_MESSAGE, set -> {
// ArrayList<TLRPC.InputStickerSet> inputSets = new ArrayList<>(1);
// inputSets.add(set);
// EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets);
// alert.setCalcMandatoryInsets(isKeyboardVisible());
// showDialog(alert);
// });
// if (bulletin != null) {
// bulletin.show();
// return true;
// }
return true;
}
return false;
}
@Override
public void didPressTopicButton(ChatMessageCell cell) {

View file

@ -11,6 +11,8 @@ package org.telegram.ui;
import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.ChannelMonetizationLayout.replaceTON;
import static org.telegram.ui.Stars.StarsIntroActivity.formatStarsAmount;
import static org.telegram.ui.Stars.StarsIntroActivity.formatStarsAmountShort;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -18,6 +20,7 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Dialog;
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
@ -97,10 +100,13 @@ import org.telegram.ui.Components.RadialProgressView;
import org.telegram.ui.Components.Reactions.ChatCustomReactionsEditActivity;
import org.telegram.ui.Components.Reactions.ReactionsUtils;
import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.Text;
import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Stars.BotStarsActivity;
import org.telegram.ui.Stars.BotStarsController;
import org.telegram.ui.Stars.StarsIntroActivity;
import org.telegram.ui.bots.AffiliateProgramFragment;
import org.telegram.ui.bots.ChannelAffiliateProgramsFragment;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@ -155,6 +161,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private TextCell adminCell;
private TextCell blockCell;
private TextCell logCell;
private TextCell channelAffiliateProgramsCell;
private TextCell statsAndBoosts;
private TextCell setAvatarCell;
private ShadowSectionCell infoSectionCell;
@ -166,6 +173,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private TextCell publicLinkCell;
private TextCell tonBalanceCell;
private TextCell starsBalanceCell;
private TextCell botAffiliateProgramCell;
private TextCell editIntroCell;
private TextCell editCommandsCell;
private TextCell changeBotSettingsCell;
@ -350,6 +358,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
canForum = userId == 0 && (forum || Math.max(info == null ? 0 : info.participants_count, currentChat.participants_count) >= getMessagesController().forumUpgradeParticipantsMin) && (info == null || info.linked_chat_id == 0);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatAvailableReactionsUpdated);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.channelConnectedBotsUpdate);
} else {
avatarDrawable.setInfo(5, currentUser.first_name, null);
isChannel = false;
@ -395,6 +404,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (currentChat != null) {
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatAvailableReactionsUpdated);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.channelConnectedBotsUpdate);
} else {
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad);
if (currentUser.bot) {
@ -1117,6 +1127,14 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
});
}
channelAffiliateProgramsCell = new TextCell(context);
channelAffiliateProgramsCell.setTextAndIcon(ChatEditActivity.applyNewSpan(LocaleController.getString(R.string.ChannelAffiliatePrograms)), R.drawable.menu_feature_premium, false);
channelAffiliateProgramsCell.setBackground(Theme.getSelectorDrawable(false));
channelAffiliateProgramsCell.setOnClickListener(v -> {
presentFragment(new ChannelAffiliateProgramsFragment(-chatId));
});
channelAffiliateProgramsCell.setVisibility(View.GONE);
if (ChatObject.isChannel(currentChat) || currentChat.gigagroup) {
logCell = new TextCell(context);
logCell.setTextAndIcon(LocaleController.getString(R.string.EventLog), R.drawable.msg_log, false);
@ -1158,6 +1176,16 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (logCell != null) {
infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
if (channelAffiliateProgramsCell != null) {
infoContainer.addView(channelAffiliateProgramsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
if (channelAffiliateProgramsCell != null && getMessagesController().starrefConnectAllowed) {
channelAffiliateProgramsCell.setVisibility(View.VISIBLE);
}
if (logCell != null) {
logCell.setNeedDivider(channelAffiliateProgramsCell != null && channelAffiliateProgramsCell.getVisibility() == View.VISIBLE);
}
}
if (currentUser != null) {
@ -1173,6 +1201,21 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
updatePublicLinksCount();
botAffiliateProgramCell = new TextCell(context);
botAffiliateProgramCell.setBackground(Theme.getSelectorDrawable(false));
botAffiliateProgramCell.setTextAndValueAndIcon(applyNewSpan(getString(R.string.AffiliateProgramBot)), "", R.drawable.msg_shareout, true);
infoContainer.addView(botAffiliateProgramCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
botAffiliateProgramCell.setOnClickListener(v -> {
presentFragment(new AffiliateProgramFragment(userId));
});
botAffiliateProgramCell.setDrawLoading(userInfo == null, 45, false);
if (userInfo != null) {
botAffiliateProgramCell.setValue(userInfo.starref_program == null ? getString(R.string.AffiliateProgramBotOff) : String.format(Locale.US, "%.1f%%", userInfo.starref_program.commission_permille / 10.0f), false);
}
if (!getMessagesController().starrefProgramAllowed) {
botAffiliateProgramCell.setVisibility(View.GONE);
}
editIntroCell = new TextCell(context);
editIntroCell.setBackground(Theme.getSelectorDrawable(false));
editIntroCell.setTextAndIcon(getString(R.string.BotEditIntro), R.drawable.msg_log, true);
@ -1284,7 +1327,8 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
loadingStr.setSpan(new LoadingSpan(starsBalanceCell.valueTextView, dp(30)), 0, loadingStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
starsBalanceCell.setTextAndValueAndIcon(getString(R.string.BotBalanceStars), loadingStr, R.drawable.menu_premium_main, false);
} else {
starsBalanceCell.setTextAndValueAndIcon(getString(R.string.BotBalanceStars), c.getBotStarsBalance(userId)<=0?"":StarsIntroActivity.replaceStarsWithPlain("XTR" + LocaleController.formatNumber(c.getBotStarsBalance(userId), ' '), .85f), R.drawable.menu_premium_main, false);
starsBalanceCell.setTextAndValueAndIcon(getString(R.string.BotBalanceStars), c.getBotStarsBalance(userId).amount <= 0?"":StarsIntroActivity.replaceStarsWithPlain(TextUtils.concat("XTR", formatStarsAmountShort(c.getBotStarsBalance(userId), .85f, ' ')), .85f), R.drawable.menu_premium_main, false);
}
starsBalanceCell.setVisibility(c.botHasStars(userId) ? View.VISIBLE : View.GONE);
@ -1352,6 +1396,16 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
return fragmentView;
}
public static CharSequence applyNewSpan(String str) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str);
spannableStringBuilder.append(" d");
FilterCreateActivity.NewSpan span = new FilterCreateActivity.NewSpan(false, 10);
span.setTypeface(AndroidUtilities.getTypeface("fonts/num.otf"));
span.setColor(Theme.getColor(Theme.key_premiumGradient1));
spannableStringBuilder.setSpan(span, spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0);
return spannableStringBuilder;
}
private void updatePublicLinksCount() {
if (publicLinkCell == null) {
return;
@ -1475,7 +1529,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (starsBalanceCell != null) {
BotStarsController c = BotStarsController.getInstance(currentAccount);
starsBalanceCell.setVisibility(c.botHasStars(userId) ? View.VISIBLE : View.GONE);
starsBalanceCell.setValue(StarsIntroActivity.replaceStarsWithPlain("XTR" + LocaleController.formatNumber(c.getBotStarsBalance(userId), ' '), .85f), true);
starsBalanceCell.setValue(StarsIntroActivity.replaceStarsWithPlain(TextUtils.concat("XTR", formatStarsAmount(c.getBotStarsBalance(userId), .8f, ' ')), .85f), true);
if (publicLinkCell != null) {
publicLinkCell.setNeedDivider(c.botHasStars(userId) || c.botHasTON(userId));
}
@ -1504,6 +1558,16 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
}
}
}
} else if (id == NotificationCenter.userInfoDidLoad) {
Long uid = (Long) args[0];
if (uid == userId) {
setInfo(getMessagesController().getUserFull(userId));
}
} else if (id == NotificationCenter.channelConnectedBotsUpdate) {
Long did = (Long) args[0];
if (did == -chatId) {
}
}
}
@ -1851,6 +1915,12 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (currentUser == null) {
currentUser = userId == 0 ? null : getMessagesController().getUser(userId);
}
if (botAffiliateProgramCell != null) {
botAffiliateProgramCell.setDrawLoading(userInfo == null, 45, true);
if (userInfo != null) {
botAffiliateProgramCell.setValue(userInfo.starref_program == null ? getString(R.string.AffiliateProgramBotOff) : String.format(Locale.US, "%.1f%%", userInfo.starref_program.commission_permille / 10.0f), false);
}
}
}
}

View file

@ -3401,13 +3401,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton);
boolean showDivider = addNew2Row != -1 || (!(loadingUsers && !firstLoaded) && membersHeaderRow == -1 && !participants.isEmpty());
if (isChannel) {
actionCell.setText(getString("AddSubscriber", R.string.AddSubscriber), null, R.drawable.msg_contact_add, showDivider);
actionCell.setText(getString(R.string.AddSubscriber), null, R.drawable.msg_contact_add, showDivider);
} else {
actionCell.setText(getString("AddMember", R.string.AddMember), null, R.drawable.msg_contact_add, showDivider);
actionCell.setText(getString(R.string.AddMember), null, R.drawable.msg_contact_add, showDivider);
}
}
} else if (position == recentActionsRow) {
actionCell.setText(getString("EventLog", R.string.EventLog), null, R.drawable.msg_log, antiSpamRow > recentActionsRow);
actionCell.setText(getString(R.string.EventLog), null, R.drawable.msg_log, antiSpamRow > recentActionsRow);
} else if (position == addNew2Row) {
actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton);
boolean showDivider = !(loadingUsers && !firstLoaded) && membersHeaderRow == -1 && !participants.isEmpty();

View file

@ -1805,10 +1805,10 @@ public class AlertsCreator {
lastMessageIsJoined = true;
}
if (user != null && user.bot) {
if (user != null && user.bot && user.id != UserObject.VERIFY) {
cell[0] = new CheckBoxCell(context, 1, resourcesProvider);
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
cell[0].setText(LocaleController.getString(R.string.BlockBot), "", false, false);
cell[0].setText(getString(R.string.BlockBot), "", false, false);
cell[0].setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0);
cell[0].setChecked(deleteForAll[0] = true, false);
frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0));
@ -1822,14 +1822,14 @@ public class AlertsCreator {
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
if (deleteChatForAll) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
cell[0].setText(LocaleController.getString(R.string.DeleteChannelForAll), "", false, false);
cell[0].setText(getString(R.string.DeleteChannelForAll), "", false, false);
} else {
cell[0].setText(LocaleController.getString(R.string.DeleteGroupForAll), "", false, false);
cell[0].setText(getString(R.string.DeleteGroupForAll), "", false, false);
}
} else if (clear) {
cell[0].setText(LocaleController.formatString("ClearHistoryOptionAlso", R.string.ClearHistoryOptionAlso, UserObject.getFirstName(user)), "", false, false);
cell[0].setText(LocaleController.formatString(R.string.ClearHistoryOptionAlso, UserObject.getFirstName(user)), "", false, false);
} else {
cell[0].setText(LocaleController.formatString("DeleteMessagesOptionAlso", R.string.DeleteMessagesOptionAlso, UserObject.getFirstName(user)), "", false, false);
cell[0].setText(LocaleController.formatString(R.string.DeleteMessagesOptionAlso, UserObject.getFirstName(user)), "", false, false);
}
cell[0].setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0);
frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0));

View file

@ -667,8 +667,21 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
}
if (force && decodeSingleFrame) {
singleFrameDecoded = false;
// if ((!PRERENDER_FRAME || nextRenderingBitmap2 != null) && nextRenderingBitmap != null) {
// renderingBitmap = nextRenderingBitmap;
// renderingBitmapTime = nextRenderingBitmapTime;
// for (int i = 0; i < backgroundShader.length; i++) {
// renderingShader[i] = nextRenderingShader[i];
// nextRenderingShader[i] = nextRenderingShader2[i];
// nextRenderingShader2[i] = null;
// }
// nextRenderingBitmap = nextRenderingBitmap2;
// nextRenderingBitmapTime = nextRenderingBitmapTime2;
// nextRenderingBitmap2 = null;
// nextRenderingBitmapTime2 = 0;
// }
if (loadFrameTask == null) {
scheduleNextGetFrame();
scheduleNextGetFrame(false, true);
} else {
forceDecodeAfterNextFrame = true;
}
@ -676,28 +689,10 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
}
}
// public void seekToSync(long ms) {
// if (nativePtr != 0) {
// if (renderingBitmap == null) {
// if (!unusedBitmaps.isEmpty()) {
// renderingBitmap = unusedBitmaps.remove(0);
// } else {
// renderingBitmap = Bitmap.createBitmap((int) (metaData[0] * scaleFactor), (int) (metaData[1] * scaleFactor), Bitmap.Config.ARGB_8888);
// }
// }
// if (decodeQueue == null) {
// decodeQueue = new DispatchQueue("decodeQueue" + this);
// }
// decodeQueue.postRunnable(() -> {
// prepareToSeek(nativePtr);
// seekToMs(nativePtr, ms, false);
// getVideoFrame(nativePtr, renderingBitmap, metaData, renderingBitmap.getRowBytes(), false, startTime, endTime, true);
// AndroidUtilities.runOnUIThread(() -> {
// invalidateInternal();
// });
// });
// }
// }
public void seekToSync(long ms) {
if (nativePtr == 0) return;
seekToMs(nativePtr, ms, metaData, true);
}
public void recycle() {
if (!secondParentViews.isEmpty()) {
@ -819,23 +814,32 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
}
private void scheduleNextGetFrame() {
if (loadFrameTask != null || ((!PRERENDER_FRAME || nextRenderingBitmap2 != null) && nextRenderingBitmap != null) || !canLoadFrames() || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded) || parents.size() == 0 && !ignoreNoParent || generatingCache) {
scheduleNextGetFrame(true, false);
}
private void scheduleNextGetFrame(boolean wait, boolean cancel) {
if (loadFrameTask != null && !cancel || ((!PRERENDER_FRAME || nextRenderingBitmap2 != null) && nextRenderingBitmap != null) || !canLoadFrames() || destroyWhenDone || !isRunning && (!decodeSingleFrame || decodeSingleFrame && singleFrameDecoded) || parents.size() == 0 && !ignoreNoParent || generatingCache) {
return;
}
long ms = 0;
if (lastFrameDecodeTime != 0) {
if (wait && lastFrameDecodeTime != 0) {
ms = Math.min(invalidateAfter, Math.max(0, invalidateAfter - (System.currentTimeMillis() - lastFrameDecodeTime)));
}
if (useSharedQueue) {
if (limitFps) {
DispatchQueuePoolBackground.execute(loadFrameTask = loadFrameRunnable);
} else {
if (cancel && loadFrameTask != null) {
executor.remove(loadFrameTask);
}
executor.schedule(loadFrameTask = loadFrameRunnable, ms, TimeUnit.MILLISECONDS);
}
} else {
if (decodeQueue == null) {
decodeQueue = new DispatchQueue("decodeQueue" + this);
}
if (cancel && loadFrameTask != null) {
decodeQueue.cancelRunnable(loadFrameTask);
}
decodeQueue.postRunnable(loadFrameTask = loadFrameRunnable, ms);
}
}
@ -1151,6 +1155,13 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
return backgroundBitmap;
}
public void skipNextFrame(boolean loop) {
if (nativePtr == 0) {
return;
}
getVideoFrame(nativePtr, null, metaData, 0, false, startTime, endTime, loop);
}
public void setLimitFps(boolean limitFps) {
this.limitFps = limitFps;
if (limitFps) {

View file

@ -1,5 +1,7 @@
package org.telegram.ui.Components;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
@ -9,16 +11,19 @@ import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.RenderEffect;
import android.graphics.RenderNode;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.os.Build;
import android.text.TextUtils;
import android.view.View;
@ -29,6 +34,7 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.R;
import org.telegram.messenger.Utilities;
import org.telegram.ui.ActionBar.Theme;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -427,6 +433,37 @@ public class BlurringShader {
private final Object textureLock = new Object();
private int renderNodeBackgroundColor;
private View renderNodeView;
private Object renderNode;
private Object blurRenderNode;
public void setRenderNode(View view, Object renderNode) {
setRenderNode(view, renderNode, 0xFF000000);
}
public void setRenderNode(View view, Object renderNode, int bgColor) {
this.renderNodeView = view;
this.renderNode = renderNode;
this.renderNodeBackgroundColor = bgColor;
if (renderNode != null && Build.VERSION.SDK_INT >= 31) {
RenderNode parent = (RenderNode) renderNode;
RenderNode node = new RenderNode("blurRenderNode");
node.setRenderEffect(RenderEffect.createBlurEffect(dp(35), dp(35), Shader.TileMode.CLAMP));
node.setPosition(0, 0, parent.getWidth(), parent.getHeight());
Canvas renderNodeCanvas = node.beginRecording();
renderNodeCanvas.drawColor(bgColor);
// renderNodeCanvas.translate(dp(32), dp(32));
renderNodeCanvas.drawRenderNode(parent);
node.endRecording();
this.blurRenderNode = node;
} else {
this.blurRenderNode = null;
}
}
public boolean hasRenderNode() {
return this.blurRenderNode != null;
}
public BlurManager(View parentView) {
this.view = parentView;
if (view.isAttachedToWindow()) {
@ -714,6 +751,7 @@ public class BlurringShader {
public RenderNode renderNode;
public final ColorMatrix colorMatrix;
public boolean xfer;
private boolean animateBitmapChange;
private boolean oldPaintSet;
@ -722,6 +760,7 @@ public class BlurringShader {
public Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private final int type;
private Integer bgColor;
public StoryBlurDrawer(@Nullable BlurManager manager, @NonNull View view, int type) {
this(manager, view, type, false);
@ -740,12 +779,14 @@ public class BlurringShader {
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
oldPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.3f);
xfer = true;
} else if (type == BLUR_TYPE_CAPTION_XFER) {
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
oldPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, +.4f);
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.3f);
// AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, 1.4f);
xfer = true;
} else if (type == BLUR_TYPE_CAPTION) {
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.35f);
AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, +.7f);
@ -753,6 +794,7 @@ public class BlurringShader {
} else if (type == BLUR_TYPE_AUDIO_BACKGROUND) {
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.5f);
} else if (type == BLUR_TYPE_AUDIO_WAVEFORM_BACKGROUND) {
bgColor = 0xFF626262;
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.6f);
AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, +.3f);
AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, 1.2f);
@ -770,6 +812,7 @@ public class BlurringShader {
oldPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
AndroidUtilities.adjustBrightnessColorMatrix(colorMatrix, +.4f);
AndroidUtilities.adjustSaturationColorMatrix(colorMatrix, +.45f);
xfer = true;
// AndroidUtilities.multiplyBrightnessColorMatrix(colorMatrix, 1.4f);
} else if (type == BLUR_TYPE_ACTION_BACKGROUND) {
colorMatrix.setSaturation(1.6f);
@ -800,6 +843,68 @@ public class BlurringShader {
});
}
private int getBackgroundColor() {
if (bgColor != null) return bgColor;
return manager.renderNodeBackgroundColor;
}
private final Path clipPath = new Path();
private int clipPathWidth, clipPathHeight;
public void drawRect(Canvas canvas) {
drawRect(canvas, 0, 0, 1.0f);
}
public void drawRect(Canvas canvas, float tx, float ty, float alpha) {
drawRect(canvas, tx, ty, alpha, true);
}
public void drawRect(Canvas canvas, float tx, float ty, float alpha, boolean clip) {
if (manager.hasRenderNode() && Build.VERSION.SDK_INT >= 31) {
if (!canvas.isHardwareAccelerated()) {
canvas.drawColor(getBackgroundColor());
return;
}
final RenderNode node = (RenderNode) manager.blurRenderNode;
if (!node.hasDisplayList()) {
final RenderNode parentNode = (RenderNode) manager.renderNode;
node.setPosition(0, 0, parentNode.getWidth(), parentNode.getHeight());
Canvas renderNodeCanvas = node.beginRecording();
renderNodeCanvas.drawColor(getBackgroundColor());
// renderNodeCanvas.translate(dp(32), dp(32));
renderNodeCanvas.drawRenderNode(parentNode);
node.endRecording();
}
if (!node.hasDisplayList()) {
canvas.drawColor(getBackgroundColor());
} else {
canvas.drawColor(getBackgroundColor());
if (setupMatrix(node.getWidth(), node.getHeight(), true)) {
if (node.hasDisplayList()) {
matrix.postTranslate(-tx, -ty);
paint.setAlpha((int) (0xFF * alpha));
canvas.saveLayer(null, paint);
canvas.concat(matrix);
if (clip) {
if (clipPathWidth != node.getWidth() || clipPathHeight != node.getHeight()) {
clipPath.rewind();
AndroidUtilities.rectTmp.set(0, 0, clipPathWidth = node.getWidth(), clipPathHeight = node.getHeight());
clipPath.addRoundRect(AndroidUtilities.rectTmp, dp(12), dp(12), Path.Direction.CW);
}
canvas.clipPath(clipPath);
}
// canvas.translate(-dp(32), -dp(32));
canvas.drawRenderNode(node);
canvas.restore();
}
}
}
} else {
Paint paint = getPaint(alpha, tx, ty);
if (paint != null) {
canvas.drawPaint(paint);
}
}
}
private boolean customOffset;
private float customOffsetX, customOffsetY;
public StoryBlurDrawer setOffset(float ox, float oy) {
@ -889,7 +994,7 @@ public class BlurringShader {
paint.setShader(bitmapShader);
}
if (!setupMatrix(bitmap.getWidth(), bitmap.getHeight())) {
if (!setupMatrix(bitmap.getWidth(), bitmap.getHeight(), false)) {
return null;
}
matrix.postTranslate(-tx, -ty);
@ -938,11 +1043,13 @@ public class BlurringShader {
paint.setShader(bitmapShader = null);
}
private boolean setupMatrix(int bitmapWidth, int bitmapHeight) {
private final int[] loc1 = new int[2], loc2 = new int[2];
private boolean setupMatrix(int bitmapWidth, int bitmapHeight, boolean renderNode) {
matrix.reset();
final View parentView = manager != null ? (renderNode ? manager.renderNodeView : manager.view) : null;
if (customOffset) {
matrix.postTranslate(-customOffsetX, -customOffsetY);
} else {
} else if (manager != null) {
View view = this.view;
do {
matrix.preScale(1f / view.getScaleX(), 1f / view.getScaleY(), view.getPivotX(), view.getPivotY());
@ -953,25 +1060,33 @@ public class BlurringShader {
} else {
break;
}
} while (view != null && manager != null && !manager.parents.contains(view));
} while (view != null && !manager.parents.contains(view));
if (manager != null && manager.view != view) {
if (parentView != view) {
int index = manager.parents.indexOf(view) + 1;
if (index == 0) {
View child = manager.parents.get(index);
if (child != null) {
view.getLocationOnScreen(loc1);
child.getLocationOnScreen(loc2);
matrix.preTranslate(loc2[0] - loc1[0], loc2[1] - loc1[1]);
}
}
while (index >= 0 && index < manager.parents.size()) {
View child = manager.parents.get(index);
if (child == null) {
continue;
}
matrix.postTranslate(child.getX(), child.getY());
matrix.postScale(1f / child.getScaleX(), 1f / child.getScaleY(), child.getPivotX(), child.getPivotY());
matrix.postRotate(child.getRotation(), child.getPivotX(), child.getPivotY());
matrix.preScale(child.getScaleX(), child.getScaleY(), child.getPivotX(), child.getPivotY());
matrix.preRotate(child.getRotation(), child.getPivotX(), child.getPivotY());
matrix.preTranslate(child.getX(), child.getY());
index++;
}
}
}
if (manager != null && manager.view != null) {
matrix.preScale((float) manager.view.getWidth() / bitmapWidth, (float) manager.view.getHeight() / bitmapHeight);
if (parentView != null) {
matrix.preScale((float) parentView.getWidth() / bitmapWidth, (float) parentView.getHeight() / bitmapHeight);
}
return true;
}
@ -982,6 +1097,7 @@ public class BlurringShader {
float alpha = 1f;
private final Paint dimPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Rect rect = new Rect();
private final Path clipPath = new Path();
@Nullable
private Paint getPaint() {
@ -1012,12 +1128,29 @@ public class BlurringShader {
public void draw(@NonNull Canvas canvas) {
Paint paint = getPaint();
Rect bounds = getBounds();
if (paint != null) {
if (paint != null || manager != null && manager.hasRenderNode()) {
if (base != null) {
canvas.saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 0xFF, Canvas.ALL_SAVE_FLAG);
base.setBounds(bounds);
base.draw(canvas);
if (manager != null && manager.hasRenderNode()) {
canvas.save();
getPadding(rect);
AndroidUtilities.rectTmp.set(
bounds.left + rect.left,
bounds.top + rect.top,
bounds.right - rect.right,
bounds.bottom - rect.bottom
);
clipPath.rewind();
clipPath.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW);
canvas.clipPath(clipPath);
// canvas.translate(Math.max(0, -customOffsetX - offsetX / 2.0f), Math.max(0, -customOffsetY - offsetY / 2.0f));
drawRect(canvas, 0, 0, 1, false);
canvas.restore();
} else {
canvas.drawRect(bounds, paint);
}
canvas.restore();
getPadding(rect);
AndroidUtilities.rectTmp.set(
@ -1031,10 +1164,28 @@ public class BlurringShader {
} else {
if (r > 0) {
AndroidUtilities.rectTmp.set(bounds);
if (manager != null && manager.hasRenderNode()) {
canvas.save();
clipPath.rewind();
clipPath.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW);
canvas.clipPath(clipPath);
// canvas.translate(-customOffsetX - offsetX, -customOffsetY - offsetY);
drawRect(canvas, 0, 0, 1, false);
canvas.restore();
} else {
canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, paint);
}
} else {
if (manager != null && manager.hasRenderNode()) {
canvas.save();
canvas.clipRect(bounds);
// canvas.translate(-customOffsetX - offsetX, -customOffsetY - offsetY);
drawRect(canvas, 0, 0, 1, false);
canvas.restore();
} else {
canvas.drawRect(bounds, paint);
}
}
dimPaint.setColor(0x66000000);
if (r > 0) {
AndroidUtilities.rectTmp.set(bounds);

View file

@ -133,6 +133,15 @@ public class Bulletin {
return null;
}
public Bulletin setImageScale(float scale) {
if (layout instanceof Bulletin.TwoLineLottieLayout) {
View imageView = ((TwoLineLottieLayout) layout).imageView;
imageView.setScaleX(scale);
imageView.setScaleY(scale);
}
return this;
}
public static void hide(@NonNull FrameLayout containerLayout) {
hide(containerLayout, true);
}

View file

@ -33,6 +33,8 @@ import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import androidx.core.graphics.ColorUtils;
import com.google.common.collect.Lists;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
@ -62,6 +64,7 @@ import org.telegram.ui.Stories.recorder.HintView2;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class BulletinFactory {
@ -471,6 +474,10 @@ public final class BulletinFactory {
return createUsersBulletin(users, text, null, null);
}
public Bulletin createUsersBulletin(TLObject user, CharSequence text, CharSequence subtitle) {
return createUsersBulletin(Arrays.asList(user), text, subtitle, null);
}
public Bulletin createUsersBulletin(List<? extends TLObject> users, CharSequence text, CharSequence subtitle) {
return createUsersBulletin(users, text, subtitle, null);
}

View file

@ -1,22 +1,25 @@
package org.telegram.ui.Components;
import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.messenger.AndroidUtilities.dpf2;
import static org.telegram.messenger.AndroidUtilities.lerp;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.ActionBar.Theme.RIPPLE_MASK_CIRCLE_20DP;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.google.android.exoplayer2.util.Util;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
@ -46,36 +49,60 @@ public class CaptionPhotoViewer extends CaptionContainerView {
private final HintView2 hint;
private final Runnable applyCaption;
private final RectF moveButtonBounds = new RectF();
private Drawable moveButtonIcon;
private final AnimatedTextView.AnimatedTextDrawable moveButtonText = new AnimatedTextView.AnimatedTextDrawable();
private final ButtonBounce moveButtonBounce = new ButtonBounce(this);
@Override
protected int getEditTextStyle() {
return EditTextEmoji.STYLE_PHOTOVIEWER;
}
public CaptionPhotoViewer(Context context, FrameLayout rootView, SizeNotifierFrameLayout sizeNotifierFrameLayout, FrameLayout containerView, Theme.ResourcesProvider resourcesProvider, BlurringShader.BlurManager blurManager, Runnable applyCaption) {
public CaptionPhotoViewer(
Context context,
FrameLayout rootView,
SizeNotifierFrameLayout sizeNotifierFrameLayout,
FrameLayout containerView,
Theme.ResourcesProvider resourcesProvider,
BlurringShader.BlurManager blurManager,
Runnable applyCaption
) {
super(context, rootView, sizeNotifierFrameLayout, containerView, resourcesProvider, blurManager);
this.applyCaption = applyCaption;
moveButtonText.setTextSize(dp(14));
moveButtonText.setOverrideFullWidth(AndroidUtilities.displaySize.x);
moveButtonText.setTextColor(0xFFFFFFFF);
if (isAtTop()) {
moveButtonText.setText(getString(R.string.MoveCaptionDown));
moveButtonIcon = context.getResources().getDrawable(R.drawable.menu_link_below);
} else {
moveButtonText.setText(getString(R.string.MoveCaptionUp));
moveButtonIcon = context.getResources().getDrawable(R.drawable.menu_link_above);
}
addPhotoButton = new ImageView(context);
addPhotoButton.setImageResource(R.drawable.filled_add_photo);
addPhotoButton.setScaleType(ImageView.ScaleType.CENTER);
addPhotoButton.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN));
addPhotoButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, RIPPLE_MASK_CIRCLE_20DP, dp(18)));
setAddPhotoVisible(false, false);
addView(addPhotoButton, LayoutHelper.createFrame(44, 44, Gravity.LEFT | Gravity.BOTTOM, 14, 0, 0, 10));
addView(addPhotoButton, LayoutHelper.createFrame(44, 44, Gravity.LEFT | (isAtTop() ? Gravity.TOP : Gravity.BOTTOM), 14, isAtTop() ? 10 : 0, 0, isAtTop() ? 0 : 10));
timerButton = new ImageView(context);
timerButton.setImageDrawable(timerDrawable = new PeriodDrawable());
timerButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR, RIPPLE_MASK_CIRCLE_20DP, dp(18)));
timerButton.setScaleType(ImageView.ScaleType.CENTER);
setTimerVisible(false, false);
addView(timerButton, LayoutHelper.createFrame(44, 44, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 11, 10));
addView(timerButton, LayoutHelper.createFrame(44, 44, Gravity.RIGHT | (isAtTop() ? Gravity.TOP : Gravity.BOTTOM), 0, isAtTop() ? 10 : 0, 11, isAtTop() ? 0 : 10));
hint = new HintView2(context, HintView2.DIRECTION_BOTTOM);
hint = new HintView2(context, isAtTop() ? HintView2.DIRECTION_TOP : HintView2.DIRECTION_BOTTOM);
hint.setRounding(12);
hint.setPadding(dp(12), 0, dp(12), dp(8));
hint.setPadding(dp(12), dp(isAtTop() ? 8 : 0), dp(12), dp(isAtTop() ? 0 : 8));
hint.setJoint(1, -21);
hint.setMultilineText(true);
addView(hint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80, Gravity.RIGHT | Gravity.BOTTOM));
addView(hint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80, Gravity.RIGHT | (isAtTop() ? Gravity.TOP : Gravity.BOTTOM)));
timerButton.setOnClickListener(e -> {
if (timerPopup != null && timerPopup.isShown()) {
@ -87,14 +114,14 @@ public class CaptionPhotoViewer extends CaptionContainerView {
timerPopup = ItemOptions.makeOptions(rootView, new DarkThemeResourceProvider(), timerButton);
timerPopup.setDimAlpha(0);
timerPopup.addText(LocaleController.getString(R.string.TimerPeriodHint), 13, dp(200));
timerPopup.addText(getString(R.string.TimerPeriodHint), 13, dp(200));
timerPopup.addGap();
for (int value : values) {
String text;
if (value == 0) {
text = LocaleController.getString(R.string.TimerPeriodDoNotDelete);
text = getString(R.string.TimerPeriodDoNotDelete);
} else if (value == SHOW_ONCE) {
text = LocaleController.getString(R.string.TimerPeriodOnce);
text = getString(R.string.TimerPeriodOnce);
} else {
text = LocaleController.formatPluralString("Seconds", value);
}
@ -107,6 +134,98 @@ public class CaptionPhotoViewer extends CaptionContainerView {
});
}
// private final AnimatedFloat aboveAnimated = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
//
// @Override
// protected float forceRound() {
// return aboveAnimated.set(isAtTop());
// }
private final AnimatedFloat moveButtonAnimated = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
private final AnimatedFloat moveButtonExpandedAnimated = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
private boolean moveButtonVisible;
private boolean moveButtonExpanded;
public void expandMoveButton() {
AndroidUtilities.cancelRunOnUIThread(collapseMoveButton);
moveButtonExpanded = MessagesController.getInstance(currentAccount).shouldShowMoveCaptionHint();
if (moveButtonExpanded) {
MessagesController.getInstance(currentAccount).incrementMoveCaptionHint();
invalidate();
AndroidUtilities.runOnUIThread(collapseMoveButton, 5000);
}
}
private final Runnable collapseMoveButton = () -> {
if (moveButtonExpanded) {
moveButtonExpanded = false;
invalidate();
}
};
protected void openedKeyboard() {
expandMoveButton();
}
@Override
public void updateKeyboard(int keyboardHeight) {
final boolean wasOpen = super.toKeyboardShow;
super.updateKeyboard(keyboardHeight);
if (!wasOpen && keyboardNotifier.keyboardVisible()) {
openedKeyboard();
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
final float moveButtonAlpha = moveButtonAnimated.set(moveButtonVisible, !showMoveButton());
final float moveButtonExpanded = moveButtonExpandedAnimated.set(this.moveButtonExpanded);
if (moveButtonAlpha > 0.0f) {
float s = moveButtonBounce.getScale(.03f);
if (isAtTop()) {
moveButtonBounds.set(dp(10), bounds.bottom + dp(10), dp(10 + 34) + (moveButtonText.getCurrentWidth() + dp(11)) * moveButtonExpanded, bounds.bottom + dp(10 + 32));
} else {
moveButtonBounds.set(dp(10), bounds.top - dp(32 + 10), dp(10 + 34) + (moveButtonText.getCurrentWidth() + dp(11)) * moveButtonExpanded, bounds.top - dp(10));
}
if (moveButtonAlpha < 1) {
canvas.saveLayerAlpha(moveButtonBounds, (int) (0xFF * moveButtonAlpha), Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
}
canvas.scale(s, s, moveButtonBounds.centerX(), moveButtonBounds.centerY());
canvas.clipRect(moveButtonBounds);
float r = dpf2(8.33f);
if (customBlur()) {
drawBlur(backgroundBlur, canvas, moveButtonBounds, r, false, 0, 0, true, 1.0f);
backgroundPaint.setAlpha((int) (lerp(0, 0x40, moveButtonAlpha)));
canvas.drawRoundRect(moveButtonBounds, r, r, backgroundPaint);
} else {
Paint[] blurPaints = backgroundBlur.getPaints(moveButtonAlpha, 0, 0);
if (blurPaints == null || blurPaints[1] == null) {
backgroundPaint.setAlpha(lerp(0, 0x80, moveButtonAlpha));
canvas.drawRoundRect(moveButtonBounds, r, r, backgroundPaint);
} else {
if (blurPaints[0] != null) {
canvas.drawRoundRect(moveButtonBounds, r, r, blurPaints[0]);
}
if (blurPaints[1] != null) {
canvas.drawRoundRect(moveButtonBounds, r, r, blurPaints[1]);
}
backgroundPaint.setAlpha(lerp(0, 0x33, moveButtonAlpha));
canvas.drawRoundRect(moveButtonBounds, r, r, backgroundPaint);
}
}
moveButtonIcon.setBounds((int) (moveButtonBounds.left + dp(9)), (int) (moveButtonBounds.centerY() - dp(9)), (int) (moveButtonBounds.left + dp(9 + 18)), (int) (moveButtonBounds.centerY() + dp(9)));
moveButtonIcon.draw(canvas);
moveButtonText.setBounds(moveButtonBounds.left + dp(34), moveButtonBounds.top, moveButtonBounds.right, moveButtonBounds.bottom);
moveButtonText.setAlpha((int) (0xFF * moveButtonExpanded));
moveButtonText.draw(canvas);
canvas.restore();
}
}
public void setOnAddPhotoClick(View.OnClickListener listener) {
addPhotoButton.setOnClickListener(listener);
}
@ -193,14 +312,14 @@ public class CaptionPhotoViewer extends CaptionContainerView {
}
CharSequence text;
if (value == 0) {
text = LocaleController.getString(isVideo ? R.string.TimerPeriodVideoKeep : R.string.TimerPeriodPhotoKeep);
text = getString(isVideo ? R.string.TimerPeriodVideoKeep : R.string.TimerPeriodPhotoKeep);
hint.setMaxWidthPx(getMeasuredWidth());
hint.setMultilineText(false);
hint.setInnerPadding(13, 4, 10, 4);
hint.setIconMargin(0);
hint.setIconTranslate(0, -dp(1));
} else if (value == SHOW_ONCE) {
text = LocaleController.getString(isVideo ? R.string.TimerPeriodVideoSetOnce : R.string.TimerPeriodPhotoSetOnce);
text = getString(isVideo ? R.string.TimerPeriodVideoSetOnce : R.string.TimerPeriodPhotoSetOnce);
hint.setMaxWidthPx(getMeasuredWidth());
hint.setMultilineText(false);
hint.setInnerPadding(13, 4, 10, 4);
@ -216,18 +335,22 @@ public class CaptionPhotoViewer extends CaptionContainerView {
} else {
return;
}
hint.setTranslationY(-Math.min(dp(34), getEditTextHeight()) - dp(14));
hint.setTranslationY((-Math.min(dp(34), getEditTextHeight()) - dp(14)) * (isAtTop() ? -1.0f : 1.0f));
hint.setText(text);
final int iconResId = value > 0 ? R.raw.fire_on : R.raw.fire_off;
RLottieDrawable icon = new RLottieDrawable(iconResId, "" + iconResId, dp(34), dp(34));
icon.start();
hint.setIcon(icon);
hint.show();
moveButtonExpanded = false;
AndroidUtilities.cancelRunOnUIThread(collapseMoveButton);
invalidate();
}
@Override
protected void onEditHeightChange(int height) {
hint.setTranslationY(-Math.min(dp(34), height) - dp(10));
hint.setTranslationY((-Math.min(dp(34), height) - dp(10)) * (isAtTop() ? -1.0f : 1.0f));
}
@Override
@ -297,4 +420,47 @@ public class CaptionPhotoViewer extends CaptionContainerView {
protected void setupMentionContainer() {
}
protected boolean showMoveButton() {
return false;
}
public void setShowMoveButtonVisible(boolean visible, boolean animated) {
if (moveButtonVisible == visible && animated) return;
moveButtonVisible = visible;
if (!animated) {
moveButtonAnimated.set(visible, true);
}
invalidate();
}
protected void onMoveButtonClick() {
}
@Override
public int getEditTextHeight() {
return super.getEditTextHeight();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
moveButtonBounce.setPressed(moveButtonBounds.contains(event.getX(), event.getY()));
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (moveButtonBounce.isPressed() && !moveButtonBounds.contains(event.getX(), event.getY())) {
moveButtonBounce.setPressed(false);
}
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
if (moveButtonBounce.isPressed()) {
if (event.getAction() == MotionEvent.ACTION_UP) {
onMoveButtonClick();
moveButtonText.setText(getString(isAtTop() ? R.string.MoveCaptionDown : R.string.MoveCaptionUp), true);
}
moveButtonBounce.setPressed(false);
return true;
}
}
return moveButtonBounce.isPressed() || super.dispatchTouchEvent(event);
}
}

View file

@ -467,7 +467,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou
sendPressed = true;
ArrayList<MessageObject> audios = new ArrayList<>();
audios.add(audioEntry.messageObject);
delegate.didSelectAudio(audios, parentAlert.commentTextView.getText(), false, 0, 0, false);
delegate.didSelectAudio(audios, parentAlert.getCommentView().getText(), false, 0, 0, false);
add = true;
} else if (selectedAudios.indexOfKey(audioEntry.id) >= 0) {
selectedAudios.remove(audioEntry.id);
@ -502,7 +502,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou
for (int a = 0; a < selectedAudiosOrder.size(); a++) {
audios.add(selectedAudiosOrder.get(a).messageObject);
}
delegate.didSelectAudio(audios, parentAlert.commentTextView.getText(), notify, scheduleDate, effectId, invertMedia);
delegate.didSelectAudio(audios, parentAlert.getCommentView().getText(), notify, scheduleDate, effectId, invertMedia);
}
public ArrayList<MessageObject> getSelected() {

View file

@ -704,7 +704,7 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
users.add(prepareContact(object));
}
delegate.didSelectContacts(users, parentAlert.commentTextView.getText().toString(), notify, scheduleDate, effectId, invertMedia);
delegate.didSelectContacts(users, parentAlert.getCommentView().getText().toString(), notify, scheduleDate, effectId, invertMedia);
}
public ArrayList<TLRPC.User> getSelected() {

View file

@ -764,7 +764,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
fmessages.add(selectedMessages.get(hashId));
}
ArrayList<String> files = new ArrayList<>(selectedFilesOrder);
delegate.didSelectFiles(files, parentAlert.commentTextView.getText().toString(), fmessages, notify, scheduleDate, effectId, invertMedia);
delegate.didSelectFiles(files, parentAlert.getCommentView().getText().toString(), fmessages, notify, scheduleDate, effectId, invertMedia);
parentAlert.dismiss(true);
}

View file

@ -10,6 +10,7 @@ package org.telegram.ui.Components;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.messenger.LocaleController.formatPluralString;
import static org.telegram.messenger.LocaleController.getString;
@ -41,6 +42,7 @@ import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Gravity;
@ -203,7 +205,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
private boolean cameraPhotoRecyclerViewIgnoreLayout;
private int itemSize = AndroidUtilities.dp(80);
private int itemSize = dp(80);
private int lastItemSize = itemSize;
private int itemsPerRow = 3;
@ -482,7 +484,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
MessageObject.addEntitiesToText(firstPhotoCaption, entities, false, false, false, false);
}
}
parentAlert.commentTextView.setText(AnimatedEmojiSpan.cloneSpans(firstPhotoCaption, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW));
parentAlert.getCommentView().setText(AnimatedEmojiSpan.cloneSpans(firstPhotoCaption, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW));
}
}
@ -501,7 +503,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (selectedPhotos.isEmpty() && photoEntry != null) {
addToSelectedPhotos(photoEntry, -1);
}
if (parentAlert.checkCaption(parentAlert.commentTextView.getText())) {
if (parentAlert.checkCaption(parentAlert.getCommentView().getText())) {
return;
}
parentAlert.applyCaption();
@ -527,7 +529,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
}
}
parentAlert.delegate.didPressedButton(7, true, notify, scheduleDate, 0, false, forceDocument);
parentAlert.delegate.didPressedButton(7, true, notify, scheduleDate, 0, parentAlert.isCaptionAbove(), forceDocument);
selectedPhotos.clear();
cameraPhotos.clear();
selectedPhotosOrder.clear();
@ -545,6 +547,21 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
return ((ChatActivity) parentAlert.baseFragment).getDialogId();
return super.getDialogId();
}
@Override
public boolean canMoveCaptionAbove() {
return parentAlert != null && parentAlert.baseFragment instanceof ChatActivity;
}
@Override
public boolean isCaptionAbove() {
return parentAlert != null && parentAlert.captionAbove;
}
@Override
public void moveCaptionAbove(boolean above) {
if (parentAlert == null || parentAlert.captionAbove == above) return;
parentAlert.setCaptionAbove(above);
captionItem.setState(!parentAlert.captionAbove, true);
}
};
protected void updateCheckedPhotoIndices() {
@ -686,8 +703,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
dropDown.setTypeface(AndroidUtilities.bold());
dropDownDrawable = context.getResources().getDrawable(R.drawable.ic_arrow_drop_down).mutate();
dropDownDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogTextBlack), PorterDuff.Mode.MULTIPLY));
dropDown.setCompoundDrawablePadding(AndroidUtilities.dp(4));
dropDown.setPadding(0, 0, AndroidUtilities.dp(10), 0);
dropDown.setCompoundDrawablePadding(dp(4));
dropDown.setPadding(0, 0, dp(10), 0);
dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0));
checkCamera(false);
@ -715,7 +732,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
gridView = new RecyclerListView(context, resourcesProvider) {
@Override
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN && e.getY() < parentAlert.scrollOffsetY[0] - AndroidUtilities.dp(80)) {
if (e.getAction() == MotionEvent.ACTION_DOWN && e.getY() < parentAlert.scrollOffsetY[0] - dp(80)) {
return false;
}
return super.onTouchEvent(e);
@ -723,7 +740,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN && e.getY() < parentAlert.scrollOffsetY[0] - AndroidUtilities.dp(80)) {
if (e.getAction() == MotionEvent.ACTION_DOWN && e.getY() < parentAlert.scrollOffsetY[0] - dp(80)) {
return false;
}
return super.onInterceptTouchEvent(e);
@ -772,13 +789,13 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int offset = AndroidUtilities.dp(13) + (parentAlert.selectedMenuItem != null ? AndroidUtilities.dp(parentAlert.selectedMenuItem.getAlpha() * 26) : 0);
int offset = dp(13) + (parentAlert.selectedMenuItem != null ? dp(parentAlert.selectedMenuItem.getAlpha() * 26) : 0);
int backgroundPaddingTop = parentAlert.getBackgroundPaddingTop();
int top = parentAlert.scrollOffsetY[0] - backgroundPaddingTop - offset;
if (top + backgroundPaddingTop < ActionBar.getCurrentActionBarHeight()) {
if (top + backgroundPaddingTop < ActionBar.getCurrentActionBarHeight() + parentAlert.topCommentContainer.getMeasuredHeight() * parentAlert.topCommentContainer.getAlpha()) {
RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.findViewHolderForAdapterPosition(0);
if (holder != null && holder.itemView.getTop() > AndroidUtilities.dp(7)) {
gridView.smoothScrollBy(0, holder.itemView.getTop() - AndroidUtilities.dp(7));
if (holder != null && holder.itemView.getTop() > dp(7)) {
gridView.smoothScrollBy(0, holder.itemView.getTop() - dp(7));
}
}
}
@ -796,7 +813,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
public int calculateDyToMakeVisible(View view, int snapPreference) {
int dy = super.calculateDyToMakeVisible(view, snapPreference);
dy -= (gridView.getPaddingTop() - AndroidUtilities.dp(7));
dy -= (gridView.getPaddingTop() - dp(7));
return dy;
}
@ -815,7 +832,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (position == adapter.itemsCount - 1) {
return layoutManager.getSpanCount();
}
return itemSize + (position % itemsPerRow != itemsPerRow - 1 ? AndroidUtilities.dp(5) : 0);
return itemSize + (position % itemsPerRow != itemsPerRow - 1 ? dp(5) : 0);
}
});
gridView.setLayoutManager(layoutManager);
@ -876,7 +893,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
addToSelectedPhotos(photoEntry, -1);
}
parentAlert.applyCaption();
parentAlert.delegate.didPressedButton(7, true, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(7, true, true, 0, 0, parentAlert.isCaptionAbove(), false);
selectedPhotos.clear();
cameraPhotos.clear();
selectedPhotosOrder.clear();
@ -916,11 +933,11 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
Object o = selectedPhotos.get(selectedPhotosOrder.get(0));
if (o instanceof MediaController.PhotoEntry) {
MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o;
photoEntry1.caption = parentAlert.getCommentTextView().getText();
photoEntry1.caption = parentAlert.getCommentView().getText();
}
if (o instanceof MediaController.SearchImage) {
MediaController.SearchImage photoEntry1 = (MediaController.SearchImage) o;
photoEntry1.caption = parentAlert.getCommentTextView().getText();
photoEntry1.caption = parentAlert.getCommentView().getText();
}
}
if (parentAlert.getAvatarFor() != null) {
@ -960,7 +977,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
PhotoViewer.getInstance().enableStickerMode(null, false, parentAlert.customStickerHandler);
}
if (captionForAllMedia()) {
PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText());
PhotoViewer.getInstance().setCaption(parentAlert.getCommentView().getText());
}
}, hasSpoiler ? 250 : 0);
} else {
@ -968,7 +985,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
openCamera(true);
} else {
if (parentAlert.delegate != null) {
parentAlert.delegate.didPressedButton(0, false, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(0, false, true, 0, 0, parentAlert.isCaptionAbove(), false);
}
}
}
@ -979,7 +996,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
if (position == 0 && selectedAlbumEntry == galleryAlbumEntry) {
if (parentAlert.delegate != null) {
parentAlert.delegate.didPressedButton(0, false, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(0, false, true, 0, 0, parentAlert.isCaptionAbove(), false);
}
return true;
} else if (view instanceof PhotoAttachPhotoCell) {
@ -1060,7 +1077,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
}
super.onDraw(canvas);
canvas.drawCircle(AndroidUtilities.dp(14), getMeasuredHeight() / 2, AndroidUtilities.dp(4), recordPaint);
canvas.drawCircle(dp(14), getMeasuredHeight() / 2, dp(4), recordPaint);
invalidate();
}
};
@ -1071,7 +1088,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
recordTime.setTypeface(AndroidUtilities.bold());
recordTime.setAlpha(0.0f);
recordTime.setTextColor(0xffffffff);
recordTime.setPadding(AndroidUtilities.dp(24), AndroidUtilities.dp(5), AndroidUtilities.dp(10), AndroidUtilities.dp(5));
recordTime.setPadding(dp(24), dp(5), dp(10), dp(5));
container.addView(recordTime, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16, 0, 0));
cameraPanel = new FrameLayout(context) {
@ -1084,22 +1101,22 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
int cx3;
int cy3;
if (getMeasuredWidth() == AndroidUtilities.dp(126)) {
if (getMeasuredWidth() == dp(126)) {
cx = getMeasuredWidth() / 2;
cy = getMeasuredHeight() / 2;
cx3 = cx2 = getMeasuredWidth() / 2;
cy2 = cy + cy / 2 + AndroidUtilities.dp(17);
cy3 = cy / 2 - AndroidUtilities.dp(17);
cy2 = cy + cy / 2 + dp(17);
cy3 = cy / 2 - dp(17);
} else {
cx = getMeasuredWidth() / 2;
cy = getMeasuredHeight() / 2 - AndroidUtilities.dp(13);
cx2 = cx + cx / 2 + AndroidUtilities.dp(17);
cx3 = cx / 2 - AndroidUtilities.dp(17);
cy3 = cy2 = getMeasuredHeight() / 2 - AndroidUtilities.dp(13);
cy = getMeasuredHeight() / 2 - dp(13);
cx2 = cx + cx / 2 + dp(17);
cx3 = cx / 2 - dp(17);
cy3 = cy2 = getMeasuredHeight() / 2 - dp(13);
}
int y = getMeasuredHeight() - tooltipTextView.getMeasuredHeight() - AndroidUtilities.dp(12);
if (getMeasuredWidth() == AndroidUtilities.dp(126)) {
int y = getMeasuredHeight() - tooltipTextView.getMeasuredHeight() - dp(12);
if (getMeasuredWidth() == dp(126)) {
tooltipTextView.layout(cx - tooltipTextView.getMeasuredWidth() / 2, getMeasuredHeight(), cx + tooltipTextView.getMeasuredWidth() / 2, getMeasuredHeight() + tooltipTextView.getMeasuredHeight());
} else {
tooltipTextView.layout(cx - tooltipTextView.getMeasuredWidth() / 2, y, cx + tooltipTextView.getMeasuredWidth() / 2, y + tooltipTextView.getMeasuredHeight());
@ -1124,8 +1141,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
counterTextView.setPivotY(0);
counterTextView.setTypeface(AndroidUtilities.bold());
counterTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.photos_arrow, 0);
counterTextView.setCompoundDrawablePadding(AndroidUtilities.dp(4));
counterTextView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
counterTextView.setCompoundDrawablePadding(dp(4));
counterTextView.setPadding(dp(16), 0, dp(16), 0);
container.addView(counterTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 38, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 100 + 16));
counterTextView.setOnClickListener(v -> {
if (cameraView == null) {
@ -1180,9 +1197,9 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
}
for (int a = 0; a < 2; a++) {
flashModeButton[a].animate().alpha(0f).translationX(AndroidUtilities.dp(30)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
flashModeButton[a].animate().alpha(0f).translationX(dp(30)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
}
switchCameraButton.animate().alpha(0f).translationX(-AndroidUtilities.dp(30)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
switchCameraButton.animate().alpha(0f).translationX(-dp(30)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
tooltipTextView.animate().alpha(0f).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
outputFile = AndroidUtilities.generateVideoPath(parentAlert.baseFragment instanceof ChatActivity && ((ChatActivity) parentAlert.baseFragment).isSecretChat());
AndroidUtilities.updateViewVisibilityAnimated(recordTime, true);
@ -1287,7 +1304,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
if (val2 < 0) {
showZoomControls(true, true);
zoomControlView.setZoom(-val2 / AndroidUtilities.dp(200), true);
zoomControlView.setZoom(-val2 / dp(200), true);
zoomingWas = true;
return false;
}
@ -1346,8 +1363,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
setCameraFlashModeIcon(nextImage, next);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(
ObjectAnimator.ofFloat(currentImage, View.TRANSLATION_Y, 0, AndroidUtilities.dp(48)),
ObjectAnimator.ofFloat(nextImage, View.TRANSLATION_Y, -AndroidUtilities.dp(48), 0),
ObjectAnimator.ofFloat(currentImage, View.TRANSLATION_Y, 0, dp(48)),
ObjectAnimator.ofFloat(nextImage, View.TRANSLATION_Y, -dp(48), 0),
ObjectAnimator.ofFloat(currentImage, View.ALPHA, 1.0f, 0.0f),
ObjectAnimator.ofFloat(nextImage, View.ALPHA, 0.0f, 1.0f));
animatorSet.setDuration(220);
@ -1369,8 +1386,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
tooltipTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
tooltipTextView.setTextColor(0xffffffff);
tooltipTextView.setText(LocaleController.getString(R.string.TapForVideo));
tooltipTextView.setShadowLayer(AndroidUtilities.dp(3.33333f), 0, AndroidUtilities.dp(0.666f), 0x4c000000);
tooltipTextView.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0);
tooltipTextView.setShadowLayer(dp(3.33333f), 0, dp(0.666f), 0x4c000000);
tooltipTextView.setPadding(dp(6), 0, dp(6), 0);
cameraPanel.addView(tooltipTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 16));
cameraPhotoRecyclerView = new RecyclerListView(context, resourcesProvider) {
@ -1386,7 +1403,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraPhotoRecyclerView.setAdapter(cameraAttachAdapter = new PhotoAttachAdapter(context, false));
cameraAttachAdapter.createCache();
cameraPhotoRecyclerView.setClipToPadding(false);
cameraPhotoRecyclerView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0);
cameraPhotoRecyclerView.setPadding(dp(8), 0, dp(8), 0);
cameraPhotoRecyclerView.setItemAnimator(null);
cameraPhotoRecyclerView.setLayoutAnimation(null);
cameraPhotoRecyclerView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER);
@ -1575,7 +1592,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
selectedPhotos.put(-1, photoEntry);
selectedPhotosOrder.add(-1);
parentAlert.delegate.didPressedButton(7, true, false, 0, 0, false, false);
parentAlert.delegate.didPressedButton(7, true, false, 0, 0, parentAlert.isCaptionAbove(), false);
if (!avatarConstructorFragment.finishOnDone) {
if (parentAlert.baseFragment != null) {
parentAlert.baseFragment.removeSelfFromStack();
@ -1807,7 +1824,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
} else {
if (cameraView != null) {
float diff = (newDistance - pinchStartDistance) / AndroidUtilities.dp(100);
float diff = (newDistance - pinchStartDistance) / dp(100);
pinchStartDistance = newDistance;
cameraZoom += diff;
if (cameraZoom < 0.0f) {
@ -2032,7 +2049,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
public void needAddMorePhotos() {
cancelTakingPhotos = false;
if (mediaFromExternalCamera) {
parentAlert.delegate.didPressedButton(0, true, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(0, true, true, 0, 0, parentAlert.isCaptionAbove(), false);
return;
}
if (!cameraOpened) {
@ -2065,7 +2082,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
parentAlert.applyCaption();
closeCamera(false);
parentAlert.delegate.didPressedButton(forceDocument ? 4 : 8, true, notify, scheduleDate, 0, false, forceDocument);
parentAlert.delegate.didPressedButton(forceDocument ? 4 : 8, true, notify, scheduleDate, 0, parentAlert.isCaptionAbove(), forceDocument);
cameraPhotos.clear();
selectedPhotosOrder.clear();
selectedPhotos.clear();
@ -2290,8 +2307,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
counterTextView.setVisibility(View.VISIBLE);
cameraPhotoRecyclerView.setVisibility(View.VISIBLE);
}
if (parentAlert.commentTextView.isKeyboardVisible() && isFocusable()) {
parentAlert.commentTextView.closeKeyboard();
if (parentAlert.getCommentView().isKeyboardVisible() && isFocusable()) {
parentAlert.getCommentView().closeKeyboard();
}
zoomControlView.setVisibility(View.VISIBLE);
zoomControlView.setAlpha(0.0f);
@ -2404,7 +2421,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
Bulletin.Delegate bulletinDelegate = new Bulletin.Delegate() {
@Override
public int getBottomOffset(int tag) {
return AndroidUtilities.dp(126) + parentAlert.getBottomInset();
return dp(126) + parentAlert.getBottomInset();
}
};
@Override
@ -2415,7 +2432,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (Build.VERSION.SDK_INT >= 21) {
super.dispatchDraw(canvas);
} else {
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + AndroidUtilities.dp(8) : 0), getMeasuredHeight());
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + dp(8) : 0), getMeasuredHeight());
if (cameraAnimationInProgress) {
AndroidUtilities.rectTmp.set(animationClipLeft + cameraViewOffsetX * (1f - cameraOpenProgress), animationClipTop + cameraViewOffsetY * (1f - cameraOpenProgress), animationClipRight, Math.min(maxY, animationClipBottom));
} else if (!cameraAnimationInProgress && !cameraOpened) {
@ -2452,7 +2469,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraView.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + AndroidUtilities.dp(8) : 0) + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY(), view.getMeasuredHeight());
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + dp(8) : 0) + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY(), view.getMeasuredHeight());
if (cameraOpened) {
maxY = view.getMeasuredHeight();
} else if (cameraAnimationInProgress) {
@ -2462,7 +2479,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
AndroidUtilities.rectTmp.set(animationClipLeft + cameraViewOffsetX * (1f - cameraOpenProgress), animationClipTop + cameraViewOffsetY * (1f - cameraOpenProgress), animationClipRight, animationClipBottom);
outline.setRect((int) AndroidUtilities.rectTmp.left,(int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, Math.min(maxY, (int) AndroidUtilities.rectTmp.bottom));
} else if (!cameraAnimationInProgress && !cameraOpened) {
int rad = AndroidUtilities.dp(8 * parentAlert.cornerRadius);
int rad = dp(8 * parentAlert.cornerRadius);
outline.setRoundRect((int) cameraViewOffsetX, (int) cameraViewOffsetY, view.getMeasuredWidth() + rad, Math.min(maxY, view.getMeasuredHeight()) + rad, rad);
} else {
outline.setRect(0, 0, view.getMeasuredWidth(), Math.min(maxY, view.getMeasuredHeight()));
@ -2978,7 +2995,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && recordTime != null) {
MarginLayoutParams params = (MarginLayoutParams) recordTime.getLayoutParams();
params.topMargin = (getRootWindowInsets() == null ? AndroidUtilities.dp(16) : getRootWindowInsets().getSystemWindowInsetTop() + AndroidUtilities.dp(2));
params.topMargin = (getRootWindowInsets() == null ? dp(16) : getRootWindowInsets().getSystemWindowInsetTop() + dp(2));
}
if (!deviceHasGoodCamera) {
@ -3001,7 +3018,10 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
left -= getRootWindowInsets().getSystemWindowInsetLeft();
}
float maxY = (Build.VERSION.SDK_INT >= 21 && !parentAlert.inBubbleMode ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
float maxY = (Build.VERSION.SDK_INT >= 21 && !parentAlert.inBubbleMode ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + parentAlert.topCommentContainer.getMeasuredHeight() * parentAlert.topCommentContainer.getAlpha();
if (parentAlert.mentionContainer != null && parentAlert.mentionContainer.isReversed()) {
maxY = Math.max(maxY, parentAlert.mentionContainer.getY() + parentAlert.mentionContainer.clipTop() - parentAlert.currentPanTranslationY);
}
float newCameraViewOffsetY;
if (topLocal < maxY) {
newCameraViewOffsetY = maxY - topLocal;
@ -3026,11 +3046,11 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
int containerHeight = parentAlert.getSheetContainer().getMeasuredHeight();
maxY = (int) (containerHeight - parentAlert.buttonsRecyclerView.getMeasuredHeight() + parentAlert.buttonsRecyclerView.getTranslationY());
if (parentAlert.mentionContainer != null) {
maxY -= parentAlert.mentionContainer.clipBottom() - AndroidUtilities.dp(6);
maxY -= parentAlert.mentionContainer.clipBottom() - dp(6);
}
if (topLocal + child.getMeasuredHeight() > maxY) {
cameraViewOffsetBottomY = Math.min(-AndroidUtilities.dp(5), topLocal - maxY) + child.getMeasuredHeight();
cameraViewOffsetBottomY = Math.min(-dp(5), topLocal - maxY) + child.getMeasuredHeight();
} else {
cameraViewOffsetBottomY = 0;
}
@ -3058,7 +3078,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
}
cameraViewLocation[0] = AndroidUtilities.dp(-400);
cameraViewLocation[0] = dp(-400);
cameraViewLocation[1] = 0;
applyCameraViewPosition();
@ -3196,7 +3216,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
public void onMenuItemClick(int id) {
if (id == caption) {
parentAlert.captionAbove = !parentAlert.captionAbove;
parentAlert.setCaptionAbove(!parentAlert.captionAbove);
captionItem.setState(!parentAlert.captionAbove, true);
return;
}
@ -3213,21 +3233,21 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (parentAlert.editingMessageObject == null && parentAlert.baseFragment instanceof ChatActivity && ((ChatActivity) parentAlert.baseFragment).isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(getContext(), ((ChatActivity) parentAlert.baseFragment).getDialogId(), (notify, scheduleDate) -> {
parentAlert.applyCaption();
parentAlert.delegate.didPressedButton(7, false, notify, scheduleDate, 0, false, false);
parentAlert.delegate.didPressedButton(7, false, notify, scheduleDate, 0, parentAlert.isCaptionAbove(), false);
}, resourcesProvider);
} else {
parentAlert.applyCaption();
parentAlert.delegate.didPressedButton(7, false, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(7, false, true, 0, 0, parentAlert.isCaptionAbove(), false);
}
} else if (id == compress) {
if (parentAlert.editingMessageObject == null && parentAlert.baseFragment instanceof ChatActivity && ((ChatActivity) parentAlert.baseFragment).isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(getContext(), ((ChatActivity) parentAlert.baseFragment).getDialogId(), (notify, scheduleDate) -> {
parentAlert.applyCaption();
parentAlert.delegate.didPressedButton(4, true, notify, scheduleDate, 0, false, false);
parentAlert.delegate.didPressedButton(4, true, notify, scheduleDate, 0, parentAlert.isCaptionAbove(), false);
}, resourcesProvider);
} else {
parentAlert.applyCaption();
parentAlert.delegate.didPressedButton(4, true, true, 0, 0, false, false);
parentAlert.delegate.didPressedButton(4, true, true, 0, 0, parentAlert.isCaptionAbove(), false);
}
} else if (id == spoiler) {
if (parentAlert.getPhotoPreviewLayout() != null) {
@ -3335,7 +3355,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
adapter.notifyDataSetChanged();
cameraAttachAdapter.notifyDataSetChanged();
layoutManager.scrollToPositionWithOffset(0, -gridView.getPaddingTop() + AndroidUtilities.dp(7));
layoutManager.scrollToPositionWithOffset(0, -gridView.getPaddingTop() + dp(7));
}
}
@ -3531,18 +3551,18 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
View child = gridView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.findContainingViewHolder(child);
int top = child.getTop();
int newOffset = AndroidUtilities.dp(7);
if (top >= AndroidUtilities.dp(7) && holder != null && holder.getAdapterPosition() == 0) {
int newOffset = dp(7);
if (top >= dp(7) && holder != null && holder.getAdapterPosition() == 0) {
newOffset = top;
}
progressView.setTranslationY(newOffset + (getMeasuredHeight() - newOffset - AndroidUtilities.dp(50) - progressView.getMeasuredHeight()) / 2);
progressView.setTranslationY(newOffset + (getMeasuredHeight() - newOffset - dp(50) - progressView.getMeasuredHeight()) / 2);
gridView.setTopGlowOffset(newOffset);
return currentItemTop = newOffset;
}
@Override
public int getFirstOffset() {
return getListTopPadding() + AndroidUtilities.dp(56);
return getListTopPadding() + dp(56);
}
@Override
@ -3712,7 +3732,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
Runnable setScrollY = () -> {
int currentItemTop = previousLayout.getCurrentItemTop(),
paddingTop = previousLayout.getListTopPadding();
gridView.scrollBy(0, (currentItemTop > AndroidUtilities.dp(8) ? paddingTop - currentItemTop : paddingTop));
gridView.scrollBy(0, (currentItemTop > dp(8) ? paddingTop - currentItemTop : paddingTop));
};
gridView.post(setScrollY);
}
@ -3886,17 +3906,17 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
LayoutParams layoutParams = (LayoutParams) getLayoutParams();
layoutParams.topMargin = ActionBar.getCurrentActionBarHeight();
itemSize = (availableWidth - AndroidUtilities.dp(6 * 2) - AndroidUtilities.dp(5 * 2)) / itemsPerRow;
itemSize = (availableWidth - dp(6 * 2) - dp(5 * 2)) / itemsPerRow;
if (lastItemSize != itemSize) {
lastItemSize = itemSize;
AndroidUtilities.runOnUIThread(() -> adapter.notifyDataSetChanged());
}
layoutManager.setSpanCount(Math.max(1, itemSize * itemsPerRow + AndroidUtilities.dp(5) * (itemsPerRow - 1)));
layoutManager.setSpanCount(Math.max(1, itemSize * itemsPerRow + dp(5) * (itemsPerRow - 1)));
int rows = (int) Math.ceil((adapter.getItemCount() - 1) / (float) itemsPerRow);
int contentSize = rows * itemSize + (rows - 1) * AndroidUtilities.dp(5);
int newSize = Math.max(0, availableHeight - contentSize - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48 + 12));
int contentSize = rows * itemSize + (rows - 1) * dp(5);
int newSize = Math.max(0, availableHeight - contentSize - ActionBar.getCurrentActionBarHeight() - dp(48 + 12));
if (gridExtraSpace != newSize) {
gridExtraSpace = newSize;
adapter.notifyDataSetChanged();
@ -3907,12 +3927,12 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
} else {
paddingTop = (availableHeight / 5 * 2);
}
paddingTop -= AndroidUtilities.dp(52);
paddingTop -= dp(52);
if (paddingTop < 0) {
paddingTop = 0;
}
if (gridView.getPaddingTop() != paddingTop) {
gridView.setPadding(AndroidUtilities.dp(6), paddingTop, AndroidUtilities.dp(6), AndroidUtilities.dp(48));
gridView.setPadding(dp(6), paddingTop, dp(6), dp(48));
}
dropDown.setTextSize(!AndroidUtilities.isTablet() && AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? 18 : 20);
ignoreLayout = false;
@ -4011,31 +4031,31 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
} else if (view == cameraPanel) {
if (isPortrait) {
cameraPanel.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(126), View.MeasureSpec.EXACTLY));
cameraPanel.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(dp(126), View.MeasureSpec.EXACTLY));
} else {
cameraPanel.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(126), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
cameraPanel.measure(View.MeasureSpec.makeMeasureSpec(dp(126), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
}
return true;
} else if (view == zoomControlView) {
if (isPortrait) {
zoomControlView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), View.MeasureSpec.EXACTLY));
zoomControlView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(dp(50), View.MeasureSpec.EXACTLY));
} else {
zoomControlView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
zoomControlView.measure(View.MeasureSpec.makeMeasureSpec(dp(50), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
}
return true;
} else if (view == cameraPhotoRecyclerView) {
cameraPhotoRecyclerViewIgnoreLayout = true;
if (isPortrait) {
cameraPhotoRecyclerView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), View.MeasureSpec.EXACTLY));
cameraPhotoRecyclerView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(dp(80), View.MeasureSpec.EXACTLY));
if (cameraPhotoLayoutManager.getOrientation() != LinearLayoutManager.HORIZONTAL) {
cameraPhotoRecyclerView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0);
cameraPhotoRecyclerView.setPadding(dp(8), 0, dp(8), 0);
cameraPhotoLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
cameraAttachAdapter.notifyDataSetChanged();
}
} else {
cameraPhotoRecyclerView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
cameraPhotoRecyclerView.measure(View.MeasureSpec.makeMeasureSpec(dp(80), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
if (cameraPhotoLayoutManager.getOrientation() != LinearLayoutManager.VERTICAL) {
cameraPhotoRecyclerView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8));
cameraPhotoRecyclerView.setPadding(0, dp(8), 0, dp(8));
cameraPhotoLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
cameraAttachAdapter.notifyDataSetChanged();
}
@ -4054,30 +4074,30 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (view == cameraPanel) {
if (isPortrait) {
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
cameraPanel.layout(0, bottom - AndroidUtilities.dp(126 + 96), width, bottom - AndroidUtilities.dp(96));
cameraPanel.layout(0, bottom - dp(126 + 96), width, bottom - dp(96));
} else {
cameraPanel.layout(0, bottom - AndroidUtilities.dp(126), width, bottom);
cameraPanel.layout(0, bottom - dp(126), width, bottom);
}
} else {
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
cameraPanel.layout(right - AndroidUtilities.dp(126 + 96), 0, right - AndroidUtilities.dp(96), height);
cameraPanel.layout(right - dp(126 + 96), 0, right - dp(96), height);
} else {
cameraPanel.layout(right - AndroidUtilities.dp(126), 0, right, height);
cameraPanel.layout(right - dp(126), 0, right, height);
}
}
return true;
} else if (view == zoomControlView) {
if (isPortrait) {
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
zoomControlView.layout(0, bottom - AndroidUtilities.dp(126 + 96 + 38 + 50), width, bottom - AndroidUtilities.dp(126 + 96 + 38));
zoomControlView.layout(0, bottom - dp(126 + 96 + 38 + 50), width, bottom - dp(126 + 96 + 38));
} else {
zoomControlView.layout(0, bottom - AndroidUtilities.dp(126 + 50), width, bottom - AndroidUtilities.dp(126));
zoomControlView.layout(0, bottom - dp(126 + 50), width, bottom - dp(126));
}
} else {
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
zoomControlView.layout(right - AndroidUtilities.dp(126 + 96 + 38 + 50), 0, right - AndroidUtilities.dp(126 + 96 + 38), height);
zoomControlView.layout(right - dp(126 + 96 + 38 + 50), 0, right - dp(126 + 96 + 38), height);
} else {
zoomControlView.layout(right - AndroidUtilities.dp(126 + 50), 0, right - AndroidUtilities.dp(126), height);
zoomControlView.layout(right - dp(126 + 50), 0, right - dp(126), height);
}
}
return true;
@ -4086,27 +4106,27 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
int cy;
if (isPortrait) {
cx = (width - counterTextView.getMeasuredWidth()) / 2;
cy = bottom - AndroidUtilities.dp(113 + 16 + 38);
cy = bottom - dp(113 + 16 + 38);
counterTextView.setRotation(0);
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
cy -= AndroidUtilities.dp(96);
cy -= dp(96);
}
} else {
cx = right - AndroidUtilities.dp(113 + 16 + 38);
cx = right - dp(113 + 16 + 38);
cy = height / 2 + counterTextView.getMeasuredWidth() / 2;
counterTextView.setRotation(-90);
if (cameraPhotoRecyclerView.getVisibility() == View.VISIBLE) {
cx -= AndroidUtilities.dp(96);
cx -= dp(96);
}
}
counterTextView.layout(cx, cy, cx + counterTextView.getMeasuredWidth(), cy + counterTextView.getMeasuredHeight());
return true;
} else if (view == cameraPhotoRecyclerView) {
if (isPortrait) {
int cy = height - AndroidUtilities.dp(88);
int cy = height - dp(88);
view.layout(0, cy, view.getMeasuredWidth(), cy + view.getMeasuredHeight());
} else {
int cx = left + width - AndroidUtilities.dp(88);
int cx = left + width - dp(88);
view.layout(cx, 0, cx + view.getMeasuredWidth(), view.getMeasuredHeight());
}
return true;
@ -4197,10 +4217,10 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
position++;
}
if (position == 0) {
int rad = AndroidUtilities.dp(8 * parentAlert.cornerRadius);
int rad = dp(8 * parentAlert.cornerRadius);
outline.setRoundRect(0, 0, view.getMeasuredWidth() + rad, view.getMeasuredHeight() + rad, rad);
} else if (position == itemsPerRow - 1) {
int rad = AndroidUtilities.dp(8 * parentAlert.cornerRadius);
int rad = dp(8 * parentAlert.cornerRadius);
outline.setRoundRect(-rad, 0, view.getMeasuredWidth(), view.getMeasuredHeight() + rad, rad);
} else {
outline.setRect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
@ -4353,7 +4373,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraCell.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int rad = AndroidUtilities.dp(8 * parentAlert.cornerRadius);
int rad = dp(8 * parentAlert.cornerRadius);
outline.setRoundRect(0, 0, view.getMeasuredWidth() + rad, view.getMeasuredHeight() + rad, rad);
}
});

View file

@ -1842,7 +1842,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
ArrayList<Object> objectArrayList = new ArrayList<>(arrayList);
PhotoViewer.getInstance().openPhotoForSelect(objectArrayList, position, type, false, photoViewerProvider, chatActivity);
if (photoLayout.captionForAllMedia()) {
PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText());
PhotoViewer.getInstance().setCaption(parentAlert.getCommentView().getText());
}
}
tapMediaCell = null;

View file

@ -166,7 +166,7 @@ public class DialogsBotsAdapter extends UniversalAdapter {
final TLRPC.User user = popular.bots.get(i);
if (uids.contains(user.id)) continue;
uids.add(user.id);
items.add(UItem.asProfileCell(user).accent());
items.add(UItem.asProfileCell(user).accent().red());
hasAdded = true;
}
if (popular.loading) {

View file

@ -135,6 +135,10 @@ public class EditTextCaption extends EditTextBoldCursor {
allowTextEntitiesIntersection = value;
}
public boolean getAllowTextEntitiesIntersection() {
return allowTextEntitiesIntersection;
}
public void makeSelectedBold() {
TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun();
run.flags |= TextStyleSpan.FLAG_STYLE_BOLD;

View file

@ -149,7 +149,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
parentFragment = fragment;
sizeNotifierLayout = parent;
sizeNotifierLayout.setDelegate(this);
sizeNotifierLayout.addDelegate(this);
editText = new EditTextCaption(context, resourcesProvider) {
@Override
@ -387,8 +387,11 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
}
public void setSizeNotifierLayout(SizeNotifierFrameLayout layout) {
if (sizeNotifierLayout != null) {
sizeNotifierLayout.removeDelegate(this);
}
sizeNotifierLayout = layout;
sizeNotifierLayout.setDelegate(this);
sizeNotifierLayout.addDelegate(this);
}
@Override
@ -477,7 +480,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
emojiView.onDestroy();
}
if (sizeNotifierLayout != null) {
sizeNotifierLayout.setDelegate(null);
sizeNotifierLayout.removeDelegate(this);
}
}

View file

@ -46,7 +46,10 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DocumentObject;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
@ -55,6 +58,7 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
@ -350,6 +354,14 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
}
}
});
listView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (contentView != null && listView.scrollingByUser) {
contentView.hidePreviewEmoji();
}
}
});
final Theme.ResourcesProvider finalResourceProvider = resourceProvider;
RecyclerListView.OnItemClickListener stickersOnItemClickListener;
listView.setOnItemClickListener(stickersOnItemClickListener = (view, position) -> {
@ -559,6 +571,10 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
shown = show;
}
public void setPreviewEmoji(TLRPC.Document document) {
contentView.setPreviewEmoji(document);
}
private class ContentView extends FrameLayout {
public ContentView(Context context) {
super(context);
@ -576,6 +592,39 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
private final AnimatedFloat statusBarT = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
private ImageReceiver previewImageReceiver;
private boolean previewImageVisible;
private final AnimatedFloat previewImageVisibleT = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT);
public void setPreviewEmoji(TLRPC.Document document) {
previewImageReceiver = new ImageReceiver(this);
if (attached) previewImageReceiver.onAttachedToWindow();
previewImageVisible = true;
previewImageVisibleT.set(1.0f, true);
final TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
final SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, true);
previewImageReceiver.setImage(
ImageLocation.getForDocument(document), "140_140",
ImageLocation.getForDocument(thumb, document), "140_140",
svgThumb,
0, null, null, 0
);
previewImageReceiver.setLayerNum(7);
previewImageReceiver.setAllowStartLottieAnimation(true);
previewImageReceiver.setAllowStartAnimation(true);
previewImageReceiver.setAutoRepeat(1);
previewImageReceiver.setAllowDecodeSingleFrame(true);
previewImageReceiver.setParentView(this);
}
public void hidePreviewEmoji() {
if (previewImageVisible) {
previewImageVisible = false;
invalidate();
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
if (!attached) {
@ -586,13 +635,25 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
path.reset();
float y = lastY = getListTop();
float pad = 0;
// if (fromY != null) {
// float wasY = y;
// y = AndroidUtilities.lerp(fromY, y + containerView.getY(), loadT) - containerView.getY();
// pad = y - wasY;
// }
final float statusBarT = this.statusBarT.set(y <= containerView.getPaddingTop());
y = AndroidUtilities.lerp(y, 0, statusBarT);
if (previewImageReceiver != null) {
final float sz = dp(140), p = dp(20);
if (y < sz + p) previewImageVisible = false;
previewImageReceiver.setAlpha(previewImageVisibleT.set(previewImageVisible));
if (previewImageReceiver.getAlpha() > 0.0f) {
final float scale = .6f + .4f * previewImageReceiver.getAlpha();
final float size = sz * scale;
final float cx = getWidth() / 2.0f, cy = y - p - sz / 2.0f;
previewImageReceiver.setImageCoords(cx - size / 2.0f, cy - size / 2.0f, size, size);
previewImageReceiver.draw(canvas);
} else {
previewImageReceiver.onDetachedFromWindow();
previewImageReceiver = null;
}
}
float r = dp((1f - statusBarT) * 14);
AndroidUtilities.rectTmp.set(getPaddingLeft(), y, getWidth() - getPaddingRight(), getBottom() + r);
path.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW);
@ -861,6 +922,9 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
protected void onAttachedToWindow() {
super.onAttachedToWindow();
attached = true;
if (previewImageReceiver != null) {
previewImageReceiver.onAttachedToWindow();
}
}
@Override
@ -875,6 +939,9 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
}
lineDrawables.clear();
AnimatedEmojiSpan.release(this, animatedEmojiDrawables);
if (previewImageReceiver != null) {
previewImageReceiver.onDetachedFromWindow();
}
}
}
@ -1187,6 +1254,9 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N
@Override
public void dismiss() {
if (contentView != null) {
contentView.hidePreviewEmoji();
}
super.dismiss();
if (customEmojiPacks != null) {
customEmojiPacks.recycle();

View file

@ -7740,6 +7740,26 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
next.run();
}, null, SharedConfig.suggestAnimatedEmoji || UserConfig.getInstance(currentAccount).isPremium(), false, true, 25);
},
next -> {
if (ConnectionsManager.getInstance(currentAccount).getConnectionState() != ConnectionsManager.ConnectionStateConnected) {
next.run();
return;
}
final String lang_code = newLanguage == null || newLanguage.length == 0 ? "" : newLanguage[0];
MediaDataController.getInstance(currentAccount).searchStickers(true, lang_code, query, emojis -> {
if (!query.equals(lastSearchEmojiString)) {
return;
}
AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocuments(emojis);
for (TLRPC.Document emoji : emojis) {
MediaDataController.KeywordResult keywordResult = new MediaDataController.KeywordResult();
keywordResult.emoji = "animated_" + emoji.id;
keywordResult.keyword = null;
searchResult.add(keywordResult);
}
next.run();
});
},
next -> {
if (SharedConfig.suggestAnimatedEmoji || UserConfig.getInstance(currentAccount).isPremium()) {
final String q = translitSafe((query + "").toLowerCase());
@ -8714,20 +8734,34 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
}
private void searchStickerSets(Runnable finished) {
final TLRPC.TL_messages_searchStickerSets req = new TLRPC.TL_messages_searchStickerSets();
req.q = query;
reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
final String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage();
final String lang_code = newLanguage == null || newLanguage.length == 0 ? "" : newLanguage[0];
MediaDataController.getInstance(currentAccount).searchStickers(false, lang_code, query, stickers -> {
if (emojiSearchId != lastId) {
return;
}
if (response instanceof TLRPC.TL_messages_foundStickerSets) {
reqId = 0;
TLRPC.TL_messages_foundStickerSets res = (TLRPC.TL_messages_foundStickerSets) response;
serverPacks.addAll(res.sets);
emojiStickersArray.addAll(stickers);
for (TLRPC.Document sticker : stickers) {
emojiStickersMap.put(sticker.id, sticker);
}
emojiStickers.put(emojiStickersArray, searchQuery);
emojiArrays.add(emojiStickersArray);
finished.run();
}));
});
// final TLRPC.TL_messages_searchStickerSets req = new TLRPC.TL_messages_searchStickerSets();
// req.q = query;
// reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
// if (emojiSearchId != lastId) {
// return;
// }
//
// if (response instanceof TLRPC.TL_messages_foundStickerSets) {
// reqId = 0;
// TLRPC.TL_messages_foundStickerSets res = (TLRPC.TL_messages_foundStickerSets) response;
// serverPacks.addAll(res.sets);
// }
// finished.run();
// }));
}
private void searchStickers(Runnable finished) {

View file

@ -5,12 +5,18 @@ import static org.telegram.messenger.LocaleController.getString;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@ -23,6 +29,7 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.ScrollView;
@ -34,10 +41,13 @@ import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLObject;
@ -82,6 +92,19 @@ public class ItemOptions {
private int gravity = Gravity.RIGHT;
private boolean ignoreX;
private int scrimViewPadding;
private int scrimViewRoundRadius;
public ItemOptions setRoundRadius(int r) {
return setRoundRadius(r, 0);
}
public ItemOptions setRoundRadius(int r, int p) {
scrimViewRoundRadius = r;
scrimViewPadding = p;
return this;
}
private ActionBarPopupWindow actionBarPopupWindow;
private final float[] point = new float[2];
@ -91,6 +114,13 @@ public class ItemOptions {
private int dimAlpha;
private boolean drawScrim = true;
private boolean blur;
public ItemOptions setBlur(boolean b) {
this.blur = b;
return this;
}
private View dimView;
private ViewTreeObserver.OnPreDrawListener preDrawListener;
@ -258,6 +288,99 @@ public class ItemOptions {
return this;
}
public ItemOptions addChecked(boolean checked, CharSequence text, Runnable onClickListener) {
if (context == null) {
return this;
}
final int textColorKey = Theme.key_actionBarDefaultSubmenuItem;
final int iconColorKey = Theme.key_actionBarDefaultSubmenuItemIcon;
ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider);
subItem.setPadding(dp(18), 0, dp(18), 0);
subItem.setText(text);
subItem.setChecked(checked);
subItem.setColors(textColor != null ? textColor : Theme.getColor(textColorKey, resourcesProvider), iconColor != null ? iconColor : Theme.getColor(iconColorKey, resourcesProvider));
subItem.setSelectorColor(selectorColor != null ? selectorColor : Theme.multAlpha(Theme.getColor(textColorKey, resourcesProvider), .12f));
subItem.setOnClickListener(view1 -> {
if (onClickListener != null) {
onClickListener.run();
}
dismiss();
});
if (minWidthDp > 0) {
subItem.setMinimumWidth(dp(minWidthDp));
addView(subItem, LayoutHelper.createLinear(minWidthDp, LayoutHelper.WRAP_CONTENT));
} else {
addView(subItem, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
return this;
}
public ItemOptions addChat(TLObject obj, boolean checked, Runnable onClickListener) {
if (context == null) {
return this;
}
final int textColorKey = Theme.key_actionBarDefaultSubmenuItem;
final int iconColorKey = Theme.key_actionBarDefaultSubmenuItemIcon;
ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider);
subItem.setPadding(dp(18), 0, dp(18), 0);
if (obj instanceof TLRPC.Chat) {
TLRPC.Chat chat = (TLRPC.Chat) obj;
subItem.setText(chat == null ? "" : chat.title);
subItem.setSubtext(ChatObject.isChannelAndNotMegaGroup(chat) ? getString(R.string.DiscussChannel) : getString(R.string.AccDescrGroup).toLowerCase());
} else if (obj instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) obj;
subItem.setText(UserObject.getUserName(user));
if (user.id == UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId()) {
subItem.setSubtext(getString(R.string.VoipGroupPersonalAccount));
} else if (UserObject.isBot(user)) {
subItem.setSubtext(getString(R.string.Bot));
}
}
subItem.setClipToPadding(false);
subItem.textView.setPadding(subItem.checkViewLeft ? (subItem.checkView != null ? dp(43) : 0) : dp(43), 0, subItem.checkViewLeft ? dp(43) : (subItem.checkView != null ? dp(43) : 0), 0);
BackupImageView imageView = new BackupImageView(context);
AvatarDrawable avatarDrawable = new AvatarDrawable();
avatarDrawable.setInfo(obj);
imageView.setRoundRadius(dp(34));
imageView.setForUserOrChat(obj, avatarDrawable);
imageView.setScaleX(checked ? 0.84f : 1.0f);
imageView.setScaleY(checked ? 0.84f : 1.0f);
subItem.addView(imageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), -5, 0, -5, 0));
if (checked) {
final float strokeWidth = 2;
View checkView = new View(context);
checkView.setBackground(Theme.createOutlineCircleDrawable(dp(34), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), dp(strokeWidth)));
subItem.addView(checkView, LayoutHelper.createFrame(34 + strokeWidth, 34 + strokeWidth, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), -5 - strokeWidth / 2.0f, 0, -5, 0));
}
subItem.setColors(textColor != null ? textColor : Theme.getColor(textColorKey, resourcesProvider), iconColor != null ? iconColor : Theme.getColor(iconColorKey, resourcesProvider));
subItem.setSelectorColor(selectorColor != null ? selectorColor : Theme.multAlpha(Theme.getColor(textColorKey, resourcesProvider), .12f));
subItem.setOnClickListener(view1 -> {
if (onClickListener != null) {
onClickListener.run();
}
dismiss();
});
if (minWidthDp > 0) {
subItem.setMinimumWidth(dp(minWidthDp));
addView(subItem, LayoutHelper.createLinear(minWidthDp, LayoutHelper.WRAP_CONTENT));
} else {
addView(subItem, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
return this;
}
public ItemOptions add(CharSequence text, CharSequence subtext, Runnable onClickListener) {
if (context == null) {
return this;
@ -502,12 +625,19 @@ public class ItemOptions {
}
private int minWidthDp;
private int fixedWidthDp;
public ItemOptions setMinWidth(int minWidthDp) {
this.minWidthDp = minWidthDp;
return this;
}
public ItemOptions setFixedWidth(int fixedWidthDp) {
this.fixedWidthDp = fixedWidthDp;
return this;
}
public ItemOptions setDimAlpha(int dimAlpha) {
this.dimAlpha = dimAlpha;
return this;
@ -524,6 +654,12 @@ public class ItemOptions {
return this;
}
private boolean allowCenter;
public ItemOptions allowCenter(boolean allow) {
allowCenter = allow;
return this;
}
private boolean forceBottom;
public ItemOptions forceBottom(boolean force) {
forceBottom = force;
@ -631,7 +767,18 @@ public class ItemOptions {
setupSelectors();
if (minWidthDp > 0) {
if (fixedWidthDp > 0) {
for (int j = 0; j < layout.getChildCount() - 1; ++j) {
View child = j == layout.getChildCount() - 1 ? lastLayout : layout.getChildAt(j);
if (child instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) {
ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = (ActionBarPopupWindow.ActionBarPopupWindowLayout) child;
for (int i = 0; i < popupLayout.getItemsCount(); ++i) {
ViewGroup.LayoutParams lp = popupLayout.getItemAt(i).getLayoutParams();
lp.width = dp(fixedWidthDp);
}
}
}
} else if (minWidthDp > 0) {
for (int j = 0; j < layout.getChildCount() - 1; ++j) {
View child = j == layout.getChildCount() - 1 ? lastLayout : layout.getChildAt(j);
if (child instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) {
@ -654,9 +801,18 @@ public class ItemOptions {
if (scrimView != null) {
getPointOnScreen(scrimView, container, point);
y = point[1];
x = point[0];
}
RectF scrimViewBounds = new RectF();
if (scrimView instanceof ScrimView) {
((ScrimView) scrimView).getBounds(scrimViewBounds);
} else {
scrimViewBounds.set(0, 0, scrimView.getMeasuredWidth(), scrimView.getMeasuredHeight());
}
x += scrimViewBounds.left;
y += scrimViewBounds.top;
if (ignoreX) {
point[0] = 0;
x = point[0] = 0;
}
if (dimAlpha > 0) {
@ -668,7 +824,11 @@ public class ItemOptions {
container.getViewTreeObserver().addOnPreDrawListener(preDrawListener);
container.addView(dimView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
dimView.setAlpha(0);
dimView.animate().alpha(1f).setDuration(150);
dimView.animate().alpha(1f).setUpdateListener(anm -> {
if (dimView != null && (scrimViewRoundRadius > 0 || scrimViewPadding > 0)) {
dimView.invalidate();
}
}).setDuration(150);
}
layout.measure(View.MeasureSpec.makeMeasureSpec(container.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(container.getMeasuredHeight(), View.MeasureSpec.AT_MOST));
@ -710,23 +870,28 @@ public class ItemOptions {
int X;
if (scrimView != null) {
if (gravity == Gravity.RIGHT) {
X = (int) (point[0] + scrimView.getMeasuredWidth() - layout.getMeasuredWidth() + container.getX());
X = (int) (container.getX() + x + scrimViewBounds.width() - layout.getMeasuredWidth());
} else if (gravity == Gravity.CENTER_HORIZONTAL) {
X = (int) (container.getX() + x + scrimViewBounds.width() / 2.0f - layout.getMeasuredWidth() / 2.0f);
} else {
X = (int) (container.getX() + point[0]);
X = (int) (container.getX() + x);
}
} else {
X = (container.getWidth() - layout.getMeasuredWidth()) / 2; // at the center
}
int Y;
if (forceBottom) {
Y = (int) (Math.min(y + scrimView.getMeasuredHeight(), AndroidUtilities.displaySize.y) - layout.getMeasuredHeight() + container.getY());
Y = (int) (Math.min(y + scrimViewBounds.height(), AndroidUtilities.displaySize.y) - layout.getMeasuredHeight() + container.getY());
} else if (scrimView != null) {
if (forceTop || y + layout.getMeasuredHeight() + dp(16) > AndroidUtilities.displaySize.y - AndroidUtilities.navigationBarHeight) {
if (forceTop || y + scrimViewBounds.height() + layout.getMeasuredHeight() + dp(16) > AndroidUtilities.displaySize.y - AndroidUtilities.navigationBarHeight) {
// put above scrimView
y -= scrimView.getMeasuredHeight();
y -= scrimViewBounds.height();
y -= layout.getMeasuredHeight();
if (allowCenter && Math.max(0, y + scrimViewBounds.height()) + layout.getMeasuredHeight() > point[1] + scrimViewBounds.top && scrimViewBounds.height() == scrimView.getHeight()) {
y = (container.getHeight() - layout.getMeasuredHeight()) / 2f - scrimViewBounds.height() - container.getY();
}
Y = (int) (y + scrimView.getMeasuredHeight() + container.getY()); // under scrimView
}
Y = (int) (y + scrimViewBounds.height() + container.getY()); // under scrimView
} else {
Y = (container.getHeight() - layout.getMeasuredHeight()) / 2; // at the center
}
@ -906,9 +1071,15 @@ public class ItemOptions {
private final Bitmap cachedBitmap;
private final Paint cachedBitmapPaint;
private Bitmap blurBitmap;
private Paint blurPaint;
private final float clipTop;
private final int dim;
private final Path clipPath = new Path();
private final RectF bounds = new RectF();
public DimView(Context context) {
super(context);
@ -929,12 +1100,28 @@ public class ItemOptions {
cachedBitmapPaint = null;
cachedBitmap = null;
}
if (blur) {
blurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
AndroidUtilities.makeGlobalBlurBitmap(b -> {
blurBitmap = b;
}, 12.0f);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (blurBitmap != null) {
canvas.save();
final float scale = Math.max((float) getWidth() / blurBitmap.getWidth(), (float) getHeight() / blurBitmap.getHeight());
canvas.scale(scale, scale);
canvas.drawBitmap(blurBitmap, 0, 0, blurPaint);
canvas.restore();
} else {
canvas.drawColor(dim);
}
if (!drawScrim) {
} else if (cachedBitmap != null && scrimView.getParent() instanceof View) {
@ -962,6 +1149,12 @@ public class ItemOptions {
}
scrimViewBackground.draw(canvas);
}
if (scrimViewPadding > 0 || scrimViewRoundRadius > 0) {
clipPath.rewind();
AndroidUtilities.rectTmp.set(-viewAdditionalOffsets.left + scrimViewPadding * getAlpha(), -viewAdditionalOffsets.top + scrimViewPadding * getAlpha(), -viewAdditionalOffsets.left + cachedBitmap.getWidth() - scrimViewPadding * getAlpha(), -viewAdditionalOffsets.top + cachedBitmap.getHeight() - scrimViewPadding * getAlpha());
clipPath.addRoundRect(AndroidUtilities.rectTmp, scrimViewRoundRadius * getAlpha(), scrimViewRoundRadius * getAlpha(), Path.Direction.CW);
canvas.clipPath(clipPath);
}
canvas.drawBitmap(cachedBitmap, -viewAdditionalOffsets.left, -viewAdditionalOffsets.top, cachedBitmapPaint);
canvas.restore();
} else if (scrimView != null && scrimView.getParent() instanceof View) {
@ -989,9 +1182,38 @@ public class ItemOptions {
}
scrimViewBackground.draw(canvas);
}
if (scrimViewPadding > 0 || scrimViewRoundRadius > 0) {
clipPath.rewind();
if (scrimView instanceof ScrimView) {
((ScrimView) scrimView).getBounds(bounds);
} else {
bounds.set(0, 0, getWidth(), getHeight());
}
AndroidUtilities.rectTmp.set(-viewAdditionalOffsets.left + bounds.left + scrimViewPadding * getAlpha(), -viewAdditionalOffsets.top + bounds.top + scrimViewPadding * getAlpha(), -viewAdditionalOffsets.left + bounds.right - scrimViewPadding * getAlpha(), -viewAdditionalOffsets.top + bounds.bottom - scrimViewPadding * getAlpha());
clipPath.addRoundRect(AndroidUtilities.rectTmp, scrimViewRoundRadius * getAlpha(), scrimViewRoundRadius * getAlpha(), Path.Direction.CW);
canvas.clipPath(clipPath);
}
if (scrimView instanceof ScrimView) {
((ScrimView) scrimView).drawScrim(canvas, getAlpha());
} else {
scrimView.draw(canvas);
}
canvas.restore();
}
}
}
public static interface ScrimView {
default void drawScrim(Canvas canvas, float progress) {
if (this instanceof View) {
((View) this).draw(canvas);
}
}
default void getBounds(RectF bounds) {
if (this instanceof View) {
View view = (View) this;
bounds.set(0, 0, view.getWidth(), view.getHeight());
}
}
}
}

View file

@ -91,6 +91,12 @@ public class LayoutHelper {
return new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity);
}
public static FrameLayout.LayoutParams createFrame(float width, float height, int gravity, float leftMargin, float topMargin, float rightMargin, float bottomMargin) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity);
layoutParams.setMargins(AndroidUtilities.dp(leftMargin), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(rightMargin), AndroidUtilities.dp(bottomMargin));
return layoutParams;
}
public static FrameLayout.LayoutParams createFrameRelatively(float width, float height, int gravity, float startMargin, float topMargin, float endMargin, float bottomMargin) {
final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), getAbsoluteGravity(gravity));
layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? endMargin : startMargin);

View file

@ -288,10 +288,12 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
}
public void setReversed(boolean reversed) {
if (reversed != isReversed()) {
scrollToFirst = true;
linearLayoutManager.setReverseLayout(reversed);
adapter.setIsReversed(reversed);
}
}
public boolean isReversed() {
return listView.getLayoutManager() == linearLayoutManager && linearLayoutManager.getReverseLayout();
@ -328,6 +330,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
boolean reversed = isReversed();
boolean topPadding = (adapter.isStickers() || adapter.isBotContext()) && adapter.isMediaLayout() && adapter.getBotContextSwitch() == null && adapter.getBotWebViewSwitch() == null;
containerPadding = AndroidUtilities.dp(2 + (topPadding ? 2 : 0));
canvas.save();
float r = AndroidUtilities.dp(6);
float wasContainerTop = containerTop;
@ -338,6 +341,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
rect.set(0, (int) (containerTop = 0), getMeasuredWidth(), (int) (containerBottom = top));
r = Math.min(r, Math.abs(getMeasuredHeight() - containerBottom));
if (r > 0) {
canvas.clipRect(0, 0, getWidth(), getHeight());
rect.top -= (int) r;
}
} else {
@ -351,6 +355,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
rect.set(0, (int) (containerTop = top), getMeasuredWidth(), (int) (containerBottom = getMeasuredHeight()));
r = Math.min(r, Math.abs(containerTop));
if (r > 0) {
canvas.clipRect(0, 0, getWidth(), getHeight());
rect.bottom += (int) r;
}
}
@ -383,7 +388,6 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
} else {
drawRoundRect(canvas, rect, r);
}
canvas.save();
canvas.clipRect(rect);
super.dispatchDraw(canvas);
canvas.restore();
@ -719,6 +723,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
}
int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem;
if (visibleItemCount > 0 && lastVisibleItem > adapter.getLastItemCount() - 5) {
// adapter.loadMoreStickers();
adapter.searchForContextBotForNextOffset();
}

View file

@ -80,7 +80,7 @@ public class GLIconTextureView extends TextureView implements TextureView.Surfac
super(context);
this.type = type;
animationsCount = type == Icon3D.TYPE_COIN ? 1 : 5;
animationsCount = type == Icon3D.TYPE_COIN || type == Icon3D.TYPE_DEAL ? 1 : 5;
setOpaque(false);
setRenderer(new GLIconRenderer(context, style, type));
initialize(context);
@ -638,7 +638,7 @@ public class GLIconTextureView extends TextureView implements TextureView.Surfac
private void pullAnimation() {
int i = Math.abs(Utilities.random.nextInt() % 4);
animatorSet = new AnimatorSet();
if (i == 0 && type != Icon3D.TYPE_COIN) {
if (i == 0 && type != Icon3D.TYPE_COIN && type != Icon3D.TYPE_DEAL) {
int a = 48;
ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleY, a);
@ -655,7 +655,7 @@ public class GLIconTextureView extends TextureView implements TextureView.Surfac
animatorSet.playTogether(v1, v2);
} else {
int dg = 485;
if (type == Icon3D.TYPE_COIN) {
if (type == Icon3D.TYPE_COIN || type == Icon3D.TYPE_DEAL) {
dg = 360;
}
int a = dg;

View file

@ -84,6 +84,7 @@ public class Icon3D {
public static final int TYPE_STAR = 0;
public static final int TYPE_COIN = 1;
public static final int TYPE_GOLDEN_STAR = 2;
public static final int TYPE_DEAL = 3;
private static final String[] starModel = new String[] {
"models/star.binobj"
@ -94,12 +95,20 @@ public class Icon3D {
"models/coin_logo.binobj",
"models/coin_stars.binobj"
};
private static final String[] dealModel = new String[] {
"models/coin_outer.binobj",
"models/coin_inner.binobj",
"models/deal_logo.binobj",
"models/coin_stars.binobj"
};
public Icon3D(Context context, int type) {
this.type = type;
String[] modelPaths;
if (type == TYPE_COIN) {
modelPaths = coinModel;
} else if (type == TYPE_DEAL) {
modelPaths = dealModel;
} else if (type == TYPE_STAR || type == TYPE_GOLDEN_STAR) {
modelPaths = starModel;
} else {

View file

@ -217,7 +217,7 @@ public class SelectorUserCell extends BaseCell {
}
}
private String buildCountDownTime(long diff) {
public static String buildCountDownTime(long diff) {
long oneHourMs = 3600 * 1000;
long oneMinuteMs = 60 * 1000;
long oneSecondMs = 1000;

View file

@ -55,6 +55,7 @@ public class SeekBarView extends FrameLayout {
private AnimatedFloat animatedThumbX = new AnimatedFloat(this, 0, 80, CubicBezierInterpolator.EASE_OUT);
private int thumbDX;
private float progressToSet = -100;
private float minProgress = -1;
private boolean pressed, pressedDelayed;
public SeekBarViewDelegate delegate;
private boolean reportChanges;
@ -186,6 +187,14 @@ public class SeekBarView extends FrameLayout {
reportChanges = value;
}
public void setMinProgress(float progress) {
minProgress = progress;
if (getProgress() < minProgress) {
setProgress(minProgress, false);
}
invalidate();
}
public void setDelegate(SeekBarViewDelegate seekBarViewDelegate) {
delegate = seekBarViewDelegate;
}
@ -205,8 +214,8 @@ public class SeekBarView extends FrameLayout {
int additionWidth = (getMeasuredHeight() - thumbSize) / 2;
if (!(thumbX - additionWidth <= ev.getX() && ev.getX() <= thumbX + thumbSize + additionWidth)) {
thumbX = (int) ev.getX() - thumbSize / 2;
if (thumbX < 0) {
thumbX = 0;
if (thumbX < minThumbX()) {
thumbX = minThumbX();
} else if (thumbX > getMeasuredWidth() - selectorWidth) {
thumbX = getMeasuredWidth() - selectorWidth;
}
@ -250,8 +259,8 @@ public class SeekBarView extends FrameLayout {
if (ev.getY() >= 0 && ev.getY() <= getMeasuredHeight()) {
if (!(thumbX - additionWidth <= ev.getX() && ev.getX() <= thumbX + thumbSize + additionWidth)) {
thumbX = (int) ev.getX() - thumbSize / 2;
if (thumbX < 0) {
thumbX = 0;
if (thumbX < minThumbX()) {
thumbX = minThumbX();
} else if (thumbX > getMeasuredWidth() - selectorWidth) {
thumbX = getMeasuredWidth() - selectorWidth;
}
@ -270,8 +279,8 @@ public class SeekBarView extends FrameLayout {
} else {
if (pressed) {
thumbX = (int) (ev.getX() - thumbDX);
if (thumbX < 0) {
thumbX = 0;
if (thumbX < minThumbX()) {
thumbX = minThumbX();
} else if (thumbX > getMeasuredWidth() - selectorWidth) {
thumbX = getMeasuredWidth() - selectorWidth;
}
@ -298,6 +307,10 @@ public class SeekBarView extends FrameLayout {
return false;
}
private int minThumbX() {
return Math.max((int) (minProgress * (getMeasuredWidth() - selectorWidth)), 0);
}
public void setLineWidth(int dp) {
lineWidthDp = dp;
}
@ -351,8 +364,8 @@ public class SeekBarView extends FrameLayout {
transitionProgress = 0f;
}
thumbX = newThumbX;
if (thumbX < 0) {
thumbX = 0;
if (thumbX < minThumbX()) {
thumbX = minThumbX();
} else if (thumbX > getMeasuredWidth() - selectorWidth) {
thumbX = getMeasuredWidth() - selectorWidth;
}
@ -412,8 +425,18 @@ public class SeekBarView extends FrameLayout {
canvas.drawRect(thumbX + selectorWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), getMeasuredWidth() / 2, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), outerPaint1);
}
} else {
rect.set(left, top, selectorWidth / 2 + thumbX, bottom);
if (minProgress >= 0) {
rect.set(left + minProgress * (right - left), top, left + thumbX, bottom);
drawProgressBar(canvas, rect, outerPaint1);
int wasAlpha = outerPaint1.getAlpha();
rect.set(left, top, left + minProgress * (right - left), bottom);
outerPaint1.setAlpha((int) (0.50f * wasAlpha));
drawProgressBar(canvas, rect, outerPaint1);
outerPaint1.setAlpha(wasAlpha);
} else {
rect.set(left, top, left + thumbX, bottom);
drawProgressBar(canvas, rect, outerPaint1);
}
}
if (hoverDrawable != null) {

View file

@ -72,6 +72,7 @@ public class SizeNotifierFrameLayout extends FrameLayout {
protected int keyboardHeight;
private int bottomClip;
protected SizeNotifierFrameLayoutDelegate delegate;
protected final ArrayList<SizeNotifierFrameLayoutDelegate> delegates = new ArrayList<>();
private boolean occupyStatusBar = true;
private WallpaperParallaxEffect parallaxEffect;
private float translationX;
@ -409,6 +410,13 @@ public class SizeNotifierFrameLayout extends FrameLayout {
public void setDelegate(SizeNotifierFrameLayoutDelegate delegate) {
this.delegate = delegate;
}
public void addDelegate(SizeNotifierFrameLayoutDelegate delegate) {
this.delegates.add(delegate);
}
public void removeDelegate(SizeNotifierFrameLayoutDelegate delegate) {
this.delegates.remove(delegate);
}
public void setOccupyStatusBar(boolean value) {
occupyStatusBar = value;
@ -452,13 +460,16 @@ public class SizeNotifierFrameLayout extends FrameLayout {
if (parallaxEffect != null) {
parallaxScale = parallaxEffect.getScale(getMeasuredWidth(), getMeasuredHeight());
}
if (delegate != null) {
if (delegate != null || !delegates.isEmpty()) {
keyboardHeight = measureKeyboardHeight();
final boolean isWidthGreater = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y;
post(() -> {
if (delegate != null) {
delegate.onSizeChanged(keyboardHeight, isWidthGreater);
}
for (int i = 0; i < delegates.size(); ++i) {
delegates.get(i).onSizeChanged(keyboardHeight, isWidthGreater);
}
});
}
}

View file

@ -69,13 +69,16 @@ public class SizeNotifierFrameLayoutPhoto extends SizeNotifierFrameLayout {
@Override
public void notifyHeightChanged() {
if (super.delegate != null) {
if (super.delegate != null || !super.delegates.isEmpty()) {
keyboardHeight = measureKeyboardHeight();
final boolean isWidthGreater = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y;
post(() -> {
if (delegate != null) {
delegate.onSizeChanged(keyboardHeight, isWidthGreater);
}
for (int i = 0; i < super.delegates.size(); ++i) {
super.delegates.get(i).onSizeChanged(keyboardHeight, isWidthGreater);
}
});
}
}

View file

@ -47,6 +47,7 @@ public class SlideChooseView extends View {
private Drawable[] leftDrawables;
private int selectedIndex;
private int minIndex = Integer.MIN_VALUE;
private float selectedIndexTouch;
private AnimatedFloat selectedIndexAnimatedHolder = new AnimatedFloat(this, 120, CubicBezierInterpolator.DEFAULT);
private AnimatedFloat movingAnimatedHolder = new AnimatedFloat(this, 150, CubicBezierInterpolator.DEFAULT);
@ -118,6 +119,19 @@ public class SlideChooseView extends View {
requestLayout();
}
public void setMinAllowedIndex(int index) {
if (index != -1 && optionsStr != null) {
index = Math.min(index, optionsStr.length - 1);
}
if (minIndex != index) {
minIndex = index;
if (selectedIndex < index) {
selectedIndex = index;
}
invalidate();
}
}
public void setDashedFrom(int from) {
dashedFrom = from;
}
@ -131,6 +145,9 @@ public class SlideChooseView extends View {
if (isClose) {
indexTouch = Math.round(indexTouch);
}
if (minIndex != Integer.MIN_VALUE) {
indexTouch = Math.max(indexTouch, minIndex);
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
xTouchDown = x;
yTouchDown = y;
@ -210,7 +227,7 @@ public class SlideChooseView extends View {
int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2;
float t = Math.max(0, 1f - Math.abs(a - selectedIndexAnimated));
float ut = MathUtils.clamp(selectedIndexAnimated - a + 1f, 0, 1);
int color = ColorUtils.blendARGB(getThemedColor(Theme.key_switchTrack), getThemedColor(Theme.key_switchTrackChecked), ut);
int color = ColorUtils.blendARGB(getThemedColor(Theme.key_switchTrack), Theme.multAlpha(getThemedColor(Theme.key_switchTrackChecked), minIndex != Integer.MIN_VALUE && a <= minIndex ? .50f : 1.0f), ut);
paint.setColor(color);
linePaint.setColor(color);
canvas.drawCircle(cx, cy, AndroidUtilities.lerp(circleSize / 2, AndroidUtilities.dp(6), t), paint);

View file

@ -40,6 +40,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
@ -48,6 +49,7 @@ import org.telegram.ui.ContentPreviewViewer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
public class SuggestEmojiView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
@ -488,6 +490,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter.
return lastLang;
}
private MediaDataController.SearchStickersKey loadingKey;
private void searchKeywords(String query) {
if (query == null) {
return;
@ -501,6 +504,10 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter.
return;
}
final int id = ++lastQueryId;
if (loadingKey != null) {
MediaDataController.getInstance(currentAccount).cancelSearchStickers(loadingKey);
loadingKey = null;
}
String[] lang = detectKeyboardLangThrottleFirstWithDelay();
if (lastLang == null || !Arrays.equals(lang, lastLang)) {
@ -513,11 +520,22 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter.
searchRunnable = null;
}
searchRunnable = () -> {
final HashSet<String> addedToResult = new HashSet<>();
final ArrayList<MediaDataController.KeywordResult> result = new ArrayList<>();
// Runnable localSearch = () -> {
MediaDataController.getInstance(currentAccount).getEmojiSuggestions(lang, query, true, (param, alias) -> {
if (id == lastQueryId) {
if (id != lastQueryId) return;
lastQueryType = 1;
lastQuery = query;
if (param != null && !param.isEmpty()) {
if (param != null) {
for (MediaDataController.KeywordResult r : param) {
if (!addedToResult.contains(r.emoji)) {
addedToResult.add(r.emoji);
result.add(r);
}
}
}
if (!result.isEmpty()) {
clear = false;
forceClose = false;
createListView();
@ -539,8 +557,29 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter.
clear = true;
forceClose();
}
}
}, SharedConfig.suggestAnimatedEmoji && UserConfig.getInstance(currentAccount).isPremium());
// };
// Runnable serverSearch = () -> {
// if (ConnectionsManager.getInstance(currentAccount).getConnectionState() != ConnectionsManager.ConnectionStateConnected) {
// localSearch.run();
// return;
// }
// loadingKey = MediaDataController.getInstance(currentAccount).searchStickers(true, query, lang == null ? "" : lang[0], emojis -> {
// if (id != lastQueryId) return;
// AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocuments(emojis);
// for (TLRPC.Document doc : emojis) {
// final String emoji = "animated_" + doc.id;
// if (!addedToResult.contains(emoji)) {
// MediaDataController.KeywordResult keywordResult = new MediaDataController.KeywordResult();
// keywordResult.emoji = emoji;
// addedToResult.add(emoji);
// result.add(keywordResult);
// }
// }
// localSearch.run();
// });
// };
// serverSearch.run();
};
if (keywordResults == null || keywordResults.isEmpty()) {
AndroidUtilities.runOnUIThread(searchRunnable, 600);

View file

@ -26,7 +26,7 @@ public class Text {
private final TextPaint paint;
private StaticLayout layout;
private float width, left;
private float maxWidth = 999999;
private float maxWidth = 9999;
public Text(CharSequence text, TextPaint paint) {
this.paint = paint;
@ -52,10 +52,10 @@ public class Text {
public void setText(CharSequence text) {
layout = new StaticLayout(AndroidUtilities.replaceNewLines(text), paint, (int) Math.max(maxWidth, 1), Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
width = 0;
left = 0;
left = layout.getWidth();
for (int i = 0; i < layout.getLineCount(); ++i) {
width = Math.max(width, layout.getLineWidth(i));
left = Math.max(left, layout.getLineLeft(i));
left = Math.min(left, layout.getLineLeft(i));
}
}
@ -118,7 +118,7 @@ public class Text {
if (!doNotSave) {
canvas.save();
}
canvas.translate(x - left, cy - layout.getHeight() / 2f);
canvas.translate(x, cy - layout.getHeight() / 2f);
draw(canvas);
if (!doNotSave) {
canvas.restore();
@ -133,7 +133,7 @@ public class Text {
if (!doNotSave) {
canvas.save();
}
canvas.translate(x - left, cy - layout.getHeight() / 2f);
canvas.translate(x, cy - layout.getHeight() / 2f);
draw(canvas);
if (!doNotSave) {
canvas.restore();
@ -163,11 +163,14 @@ public class Text {
if (!doNotSave && ellipsizeWidth >= 0 && width > ellipsizeWidth) {
canvas.saveLayerAlpha(0, -vertPad, ellipsizeWidth - 1, layout.getHeight() + vertPad, 0xFF, Canvas.ALL_SAVE_FLAG);
}
canvas.save();
canvas.translate(-left, 0);
if (hackClipBounds) {
canvas.drawText(layout.getText().toString(), 0, -paint.getFontMetricsInt().ascent, paint);
} else {
layout.draw(canvas);
}
canvas.restore();
if (!doNotSave && ellipsizeWidth >= 0 && width > ellipsizeWidth) {
if (ellipsizeGradient == null) {
ellipsizeGradient = new LinearGradient(0, 0, dp(8), 0, new int[] { 0x00ffffff, 0xffffffff }, new float[] {0, 1}, Shader.TileMode.CLAMP);
@ -178,9 +181,9 @@ public class Text {
}
canvas.save();
ellipsizeMatrix.reset();
ellipsizeMatrix.postTranslate(ellipsizeWidth - left - dp(8), 0);
ellipsizeMatrix.postTranslate(ellipsizeWidth - dp(8), 0);
ellipsizeGradient.setLocalMatrix(ellipsizeMatrix);
canvas.drawRect(ellipsizeWidth - left - dp(8), 0, ellipsizeWidth - left, layout.getHeight(), ellipsizePaint);
canvas.drawRect(ellipsizeWidth - dp(8), 0, ellipsizeWidth, layout.getHeight(), ellipsizePaint);
canvas.restore();
canvas.restore();
}

View file

@ -294,23 +294,29 @@ public class UItem extends AdapterWithDiffUtils.Item {
item.texts = choices;
item.intValue = chosen;
item.intCallback = whenChose;
item.longValue = -1;
return item;
}
public static UItem asIntSlideView(
int style,
int minStringResId, int min,
int valueMinStringResId, int valueStringResId, int valueMaxStringResId, int value,
int maxStringResId, int max,
int min, int value, int max,
Utilities.CallbackReturn<Integer, String> toString,
Utilities.Callback<Integer> whenChose
) {
UItem item = new UItem(UniversalAdapter.VIEW_TYPE_INTSLIDE, false);
item.intValue = value;
item.intCallback = whenChose;
item.object = SlideIntChooseView.Options.make(style, min, minStringResId, valueMinStringResId, valueStringResId, valueMaxStringResId, max, maxStringResId);
item.object = SlideIntChooseView.Options.make(style, min, max, toString);
item.longValue = -1;
return item;
}
public UItem setMinSliderValue(int value) {
this.longValue = value;
return this;
}
public static UItem asQuickReply(QuickRepliesController.QuickReply quickReply) {
UItem item = new UItem(UniversalAdapter.VIEW_TYPE_QUICK_REPLY, false);
item.object = quickReply;

View file

@ -754,6 +754,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
case VIEW_TYPE_SLIDE:
SlideChooseView slideView = (SlideChooseView) holder.itemView;
slideView.setOptions(item.intValue, item.texts);
slideView.setMinAllowedIndex((int) item.longValue);
slideView.setCallback(index -> {
if (item.intCallback != null) {
item.intCallback.run(index);
@ -763,6 +764,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
case VIEW_TYPE_INTSLIDE:
SlideIntChooseView slideIntChooseView = (SlideIntChooseView) holder.itemView;
slideIntChooseView.set(item.intValue, (SlideIntChooseView.Options) item.object, item.intCallback);
slideIntChooseView.setMinValueAllowed((int) item.longValue);
break;
case VIEW_TYPE_QUICK_REPLY:
QuickRepliesActivity.QuickReplyView replyView = (QuickRepliesActivity.QuickReplyView) holder.itemView;
@ -843,7 +845,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
ProfileSearchCell profileCell = (ProfileSearchCell) holder.itemView;
Object object = item.object;
CharSequence s = "";
if (item.accent && object instanceof TLRPC.User && ((TLRPC.User) object).bot_active_users != 0) { // show bot dau
if (item.accent && object instanceof TLRPC.User && ((TLRPC.User) object).bot_active_users != 0) { // show bot mau
TLRPC.User user = (TLRPC.User) object;
if (user.bot_active_users != 0) {
s = LocaleController.formatPluralStringSpaced("BotUsers", user.bot_active_users);
@ -883,6 +885,7 @@ public class UniversalAdapter extends AdapterWithDiffUtils {
// add status text
title = UserObject.getUserName(user);
}
profileCell.setRectangularAvatar(item.red);
profileCell.setData(object, null, title, s, false, false);
profileCell.useSeparator = divider;
break;

View file

@ -20,6 +20,7 @@ import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.net.Uri;
import android.opengl.EGLContext;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@ -214,6 +215,16 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis
}
}
private Looper looper;
public void setLooper(Looper looper) {
this.looper = looper;
}
private EGLContext eglParentContext;
public void setEGLContext(EGLContext ctx) {
eglParentContext = ctx;
}
private void ensurePlayerCreated() {
DefaultLoadControl loadControl;
if (isStory) {
@ -247,9 +258,16 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis
factory = new DefaultRenderersFactory(ApplicationLoader.applicationContext);
}
factory.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER);
player = new ExoPlayer.Builder(ApplicationLoader.applicationContext).setRenderersFactory(factory)
ExoPlayer.Builder builder = new ExoPlayer.Builder(ApplicationLoader.applicationContext).setRenderersFactory(factory)
.setTrackSelector(trackSelector)
.setLoadControl(loadControl).build();
.setLoadControl(loadControl);
if (looper != null) {
builder.setLooper(looper);
}
if (eglParentContext != null) {
builder.eglContext = eglParentContext;
}
player = builder.build();
player.addAnalyticsListener(this);
player.addListener(this);

View file

@ -4422,6 +4422,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
protected void onArchiveSettingsClick() {
presentFragment(new ArchiveSettingsActivity());
}
@Override
protected boolean showOpenBotButton() {
return initialDialogsType == DIALOGS_TYPE_DEFAULT;
}
@Override
protected void onOpenBot(TLRPC.User bot) {
MessagesController.getInstance(currentAccount).openApp(bot, 0);
}
};
viewPage.dialogsAdapter.setRecyclerListView(viewPage.listView);
viewPage.dialogsAdapter.setForceShowEmptyCell(afterSignup);
@ -5490,7 +5499,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
c.loadInsufficientSubscriptions();
return false;
} else {
long starsNeeded = -c.balance;
long starsNeeded = -c.balance.amount;
for (int i = 0; i < c.insufficientSubscriptions.size(); ++i) {
final TL_stars.StarsSubscription sub = c.insufficientSubscriptions.get(i);
final long did = DialogObject.getPeerDialogId(sub.peer);
@ -5820,7 +5829,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
updateDialogsHint();
}).show();
});
dialogsHintCell.setText(StarsIntroActivity.replaceStarsWithPlain(formatPluralStringComma("StarsSubscriptionExpiredHintTitle2", (int) (starsNeeded - c.balance <= 0 ? starsNeeded : starsNeeded - c.balance), starsNeededName), .72f), LocaleController.getString(R.string.StarsSubscriptionExpiredHintText));
dialogsHintCell.setText(StarsIntroActivity.replaceStarsWithPlain(formatPluralStringComma("StarsSubscriptionExpiredHintTitle2", (int) (starsNeeded - c.balance.amount <= 0 ? starsNeeded : starsNeeded - c.balance.amount), starsNeededName), .72f), LocaleController.getString(R.string.StarsSubscriptionExpiredHintText));
dialogsHintCell.setOnCloseListener(v -> {
MessagesController.getInstance(currentAccount).removeSuggestion(0, "STARS_SUBSCRIPTION_LOW_BALANCE");
ChangeBounds transition = new ChangeBounds();
@ -8618,7 +8627,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
previewMenu[0].addView(muteItem);
}
if (dialogId != UserObject.VERIFY) {
ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true);
deleteItem.setIconColor(getThemedColor(Theme.key_text_RedRegular));
deleteItem.setTextColor(getThemedColor(Theme.key_text_RedBold));
@ -8630,7 +8638,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
finishPreviewFragment();
});
previewMenu[0].addView(deleteItem);
}
if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) {
if (searchString != null) {
@ -9612,11 +9619,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
canPinCount++;
}
canClearHistoryCount++;
if (dialog.id != UserObject.VERIFY) {
canDeleteCount++;
}
}
}
if (deleteItem != null) {
if (canDeleteCount != count) {
deleteItem.setVisibility(View.GONE);

View file

@ -14,6 +14,7 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Editable;
@ -2067,6 +2068,10 @@ public class FilterCreateActivity extends BaseFragment {
}
}
public void setTypeface(Typeface typeface) {
textPaint.setTypeface(typeface);
}
public NewSpan(float textSize) {
this.outline = false;
textPaint.setTypeface(AndroidUtilities.bold());
@ -2078,9 +2083,18 @@ public class FilterCreateActivity extends BaseFragment {
this.color = color;
}
private CharSequence text = "NEW";
public void setText(CharSequence text) {
this.text = text;
if (layout != null) {
layout = null;
makeLayout();
}
}
public StaticLayout makeLayout() {
if (layout == null) {
layout = new StaticLayout("NEW"/*LocaleController.getString(R.string.New)*/, textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
layout = new StaticLayout(text, textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
width = layout.getLineWidth(0);
height = layout.getHeight();
}

View file

@ -1,6 +1,5 @@
package org.telegram.ui;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;

View file

@ -92,6 +92,11 @@ public abstract class GradientHeaderActivity extends BaseFragment {
public int statusBarHeight;
private int firstViewHeight;
private final Paint headerBgPaint = new Paint();
private int minusHeaderHeight;
public void setMinusHeaderHeight(int h) {
minusHeaderHeight = h;
}
public boolean whiteBackground;
@ -118,7 +123,7 @@ public abstract class GradientHeaderActivity extends BaseFragment {
} else {
int h = AndroidUtilities.dp(140) + statusBarHeight;
if (backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24) > h) {
h = backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24);
h = Math.max(h, backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24) - minusHeaderHeight);
}
firstViewHeight = h;
}

View file

@ -2109,6 +2109,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
Uri data = intent.getData();
if (data != null) {
String username = null;
String referrer = null;
String login = null;
String group = null;
String sticker = null;
@ -2383,6 +2384,24 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
botUser = data.getQueryParameter("start");
botChat = data.getQueryParameter("startgroup");
if (!TextUtils.isEmpty(username)) {
referrer = data.getQueryParameter("ref");
if (TextUtils.isEmpty(referrer) && !TextUtils.isEmpty(botUser)) {
for (String prefix : MessagesController.getInstance(intentAccount[0]).starrefStartParamPrefixes) {
if (botUser.startsWith(prefix)) {
referrer = botUser.substring(prefix.length());
break;
}
}
} else if (TextUtils.isEmpty(referrer) && !TextUtils.isEmpty(startApp)) {
for (String prefix : MessagesController.getInstance(intentAccount[0]).starrefStartParamPrefixes) {
if (startApp.startsWith(prefix)) {
referrer = startApp.substring(prefix.length());
break;
}
}
}
}
botChannel = data.getQueryParameter("startchannel");
botChatAdminParams = data.getQueryParameter("admin");
game = data.getQueryParameter("game");
@ -2492,6 +2511,24 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
commentId = null;
}
}
if (!TextUtils.isEmpty(username)) {
referrer = data.getQueryParameter("ref");
if (TextUtils.isEmpty(referrer) && !TextUtils.isEmpty(botUser)) {
for (String prefix : MessagesController.getInstance(intentAccount[0]).starrefStartParamPrefixes) {
if (botUser.startsWith(prefix)) {
referrer = botUser.substring(prefix.length());
break;
}
}
} else if (TextUtils.isEmpty(referrer) && !TextUtils.isEmpty(startApp)) {
for (String prefix : MessagesController.getInstance(intentAccount[0]).starrefStartParamPrefixes) {
if (startApp.startsWith(prefix)) {
referrer = startApp.substring(prefix.length());
break;
}
}
}
}
} else if (url.startsWith("tg:invoice") || url.startsWith("tg://invoice")) {
url = url.replace("tg:invoice", "tg://invoice");
data = Uri.parse(url);
@ -2860,7 +2897,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (message != null && message.startsWith("@")) {
message = " " + message;
}
runLinkRequest(intentAccount[0], username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, startApp, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
runLinkRequest(intentAccount[0], username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, startApp, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
} else {
try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) {
if (cursor != null) {
@ -3881,9 +3918,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
final boolean forceNotInternalForApps,
final int storyId,
final boolean isBoost,
final String chatLinkSlug, boolean botCompact, boolean botFullscreen, boolean openedTelegram, boolean openProfile, boolean forceRequest) {
final String chatLinkSlug, boolean botCompact, boolean botFullscreen, boolean openedTelegram, boolean openProfile, boolean forceRequest, String referrer) {
if (state == 0 && ChatActivity.SCROLL_DEBUG_DELAY && progress != null) {
Runnable runnable = () -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
Runnable runnable = () -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
progress.init();
progress.onCancel(() -> AndroidUtilities.cancelRunOnUIThread(runnable));
AndroidUtilities.runOnUIThread(runnable, 7500);
@ -3893,7 +3930,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (account != intentAccount) {
switchToAccount(account, true);
}
runLinkRequest(account, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
runLinkRequest(account, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
}).show();
return;
} else if (code != null) {
@ -4047,7 +4084,20 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (progress != null) {
progress.init();
}
MessagesController.getInstance(intentAccount).getUserNameResolver().resolve(username, (peerId) -> {
MessagesController.getInstance(intentAccount).getUserNameResolver().resolve(username, referrer, (peerId) -> {
if (peerId != null && peerId == Long.MAX_VALUE) {
try {
dismissLoading.run();
} catch (Exception e) {
FileLog.e(e);
}
new AlertDialog.Builder(this, null)
.setTitle(LocaleController.getString(R.string.AffiliateLinkExpiredTitle))
.setMessage(LocaleController.getString(R.string.AffiliateLinkExpiredText))
.setNegativeButton(LocaleController.getString(R.string.OK), null)
.show();
return;
}
if (!LaunchActivity.this.isFinishing()) {
boolean hideProgressDialog = true;
if (storyId != 0 && peerId != null) {
@ -4088,7 +4138,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> {
if (error1 != null) {
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest));
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer));
} else if (response1 instanceof TLRPC.TL_attachMenuBotsBot) {
TLRPC.TL_attachMenuBotsBot bot = (TLRPC.TL_attachMenuBotsBot) response1;
TLRPC.TL_attachMenuBot attachBot = bot.bot;
@ -4109,7 +4159,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, botAttachable, true, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, botAttachable, true, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
}, null, progress != null ? progress::end : null);
} else if (attachBot.request_write_access || forceNotInternalForApps) {
AtomicBoolean allowWrite = new AtomicBoolean(true);
@ -4129,15 +4179,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
});
} else {
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
}
}
}));
} else {
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, user, dismissLoading, false, false, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer);
}
return;
}
@ -5198,7 +5248,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
final boolean isBoost,
final String chatLinkSlug,
TLRPC.User user,
Runnable dismissLoading, boolean botAttachable, boolean ignoreInactive, boolean botCompact, boolean botFullscreen, boolean openedTelegram, boolean openProfile, boolean forceRequest) {
Runnable dismissLoading, boolean botAttachable, boolean ignoreInactive, boolean botCompact, boolean botFullscreen, boolean openedTelegram, boolean openProfile, boolean forceRequest, String referrer) {
TLRPC.TL_messages_getBotApp getBotApp = new TLRPC.TL_messages_getBotApp();
TLRPC.TL_inputBotAppShortName app = new TLRPC.TL_inputBotAppShortName();
@ -5210,7 +5260,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
progress.end();
}
if (error1 != null) {
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest));
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, text, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, videochat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId, isBoost, chatLinkSlug, botCompact, botFullscreen, openedTelegram, openProfile, forceRequest, referrer));
} else {
TLRPC.TL_messages_botApp botApp = (TLRPC.TL_messages_botApp) response1;
AndroidUtilities.runOnUIThread(() -> {
@ -5977,7 +6027,6 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
arrayList.add(videoPath);
SendMessagesHelper.prepareSendingDocuments(accountInstance, arrayList, arrayList, null, captionToSend, null, did, replyToMsg, replyToMsg, null, null, null, notify, scheduleDate, null, null, 0, 0, false);
}
}
if (photoPathsArray != null && !photosEditorOpened) {
if (sendingText != null && sendingText.length() <= 1024 && photoPathsArray.size() == 1) {
photoPathsArray.get(0).caption = sendingText;
@ -5985,6 +6034,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, replyToMsg, replyToMsg, null, null, false, false, null, notify, scheduleDate, 0, false, null, null, 0, 0, false);
}
}
if (documentsPathsArray != null || documentsUrisArray != null) {
if (sendingText != null && sendingText.length() <= 1024 && ((documentsPathsArray != null ? documentsPathsArray.size() : 0) + (documentsUrisArray != null ? documentsUrisArray.size() : 0)) == 1) {
captionToSend = sendingText;

View file

@ -82,6 +82,7 @@ import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Pair;
import android.util.Property;
import android.util.Range;
@ -238,7 +239,6 @@ import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.Components.LinkSpanDrawable;
import org.telegram.ui.Components.LoadingDrawable;
import org.telegram.ui.Components.MediaActivity;
import org.telegram.ui.Components.OptionsSpeedIconDrawable;
import org.telegram.ui.Components.OtherDocumentPlaceholderDrawable;
import org.telegram.ui.Components.Paint.Views.LPhotoPaintView;
import org.telegram.ui.Components.Paint.Views.MaskPaintView;
@ -282,6 +282,7 @@ import org.telegram.ui.Components.VideoTimelinePlayView;
import org.telegram.ui.Components.ViewHelper;
import org.telegram.ui.Components.spoilers.SpoilersTextView;
import org.telegram.ui.Stories.DarkThemeResourceProvider;
import org.telegram.ui.Stories.recorder.CaptionContainerView;
import org.telegram.ui.Stories.recorder.KeyboardNotifier;
import org.telegram.ui.Stories.recorder.StoryEntry;
@ -664,7 +665,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private String getOf() {
lng = LocaleController.getInstance().getCurrentLocaleInfo().shortName;
String text = getString("Of"); // %1$d of %2$d
String text = getString(R.string.Of); // %1$d of %2$d
text = text.replace("%1$d", "");
text = text.replace("%2$d", "");
return text;
@ -802,7 +803,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private WindowManager.LayoutParams windowLayoutParams;
private FrameLayoutDrawer containerView;
private PhotoViewerWebView photoViewerWebView;
private FrameLayout windowView;
public FrameLayout windowView;
private ClippingImageView animatingImageView;
private FrameLayout bottomLayout;
private View navigationBar;
@ -835,6 +836,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private CheckBox checkImageView;
private CounterView photosCounterView;
private FrameLayout pickerView;
private FrameLayout topBulletinUnderCaption;
private FrameLayout bottomBulletinUnderCaption;
private ImageView pickerViewSendButton;
private PickerBottomLayoutViewer editorDoneLayout;
private TextView resetButton;
@ -890,8 +893,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private TextView adButtonTextView;
private CaptionScrollView captionScrollView;
private CaptionPhotoViewer captionEdit;
private CaptionPhotoViewer topCaptionEdit;
private float shiftDp = -8;
private FrameLayout captionEditContainer;
private FrameLayout topCaptionEditContainer;
private FrameLayout captionContainer;
private ChatAttachAlert parentAlert;
// private PhotoViewerCaptionEnterView captionEditText;
@ -2834,6 +2839,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
default boolean forceAllInGroup() {
return false;
}
default boolean isCaptionAbove() {
return false;
}
default boolean canMoveCaptionAbove() {
return false;
}
default void moveCaptionAbove(boolean above) {}
}
private class FrameLayoutDrawer extends SizeNotifierFrameLayoutPhoto {
@ -2929,7 +2942,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
height = heightSize;
}
paintingOverlay.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
} else if (captionEdit.editText.isPopupView(child)) {
} else if (captionEdit.editText.isPopupView(child) || topCaptionEdit.editText.isPopupView(child)) {
int inputFieldHeight = 0;
if (inBubbleMode) {
child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - inputFieldHeight, MeasureSpec.EXACTLY));
@ -2958,6 +2971,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
final int height = heightSize - topMargin - bottomMargin;
((MarginLayoutParams) captionScrollView.getLayoutParams()).bottomMargin = bottomMargin;
child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
} else if (child == topCaptionEditContainer || child == topBulletinUnderCaption) {
final int topMargin = (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - topMargin, MeasureSpec.EXACTLY);
child.measure(widthMeasureSpec, heightSpec);
} else if (child == topCaptionEdit.mentionContainer) {
final int topMargin = (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - topMargin, MeasureSpec.EXACTLY);
child.measure(widthMeasureSpec, heightSpec);
} else {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
}
@ -3028,14 +3049,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
if (child == captionEdit.mentionContainer) {
childTop -= captionEdit.getEditTextHeight();
} else if (captionEdit.editText.isPopupView(child)) {
} else if (child == topCaptionEdit.mentionContainer) {
childTop += actionBar.getMeasuredHeight();
} else if (captionEdit.editText.isPopupView(child) || topCaptionEdit.editText.isPopupView(child)) {
childTop = (_b - t) - height + (!inBubbleMode && !AndroidUtilities.isInMultiwindow ? AndroidUtilities.navigationBarHeight : 0);
// if (AndroidUtilities.isInMultiwindow) {
// childTop = captionEditText.getTop() - child.getMeasuredHeight() + dp(1);
// } else {
// childTop = captionEditText.getBottom();
// }
} else if (child == selectedPhotosListView) {
childTop = actionBar.getMeasuredHeight() + dp(5);
} else if (child == muteItem) {
@ -3058,6 +3075,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} else if (child == captionEditContainer) {
childTop = (b - t) - height - (lp.bottomMargin);
childTop -= pickerView.getHeight();
} else if (child == topCaptionEditContainer || child == topBulletinUnderCaption) {
childTop = actionBar.getMeasuredHeight();
} else if (child == bottomBulletinUnderCaption) {
childTop = (b - t) - height - (lp.bottomMargin);
childTop -= pickerView.getHeight();
} else if (child == videoAvatarTooltip) {
childTop -= pickerView.getHeight() + dp(31);
}
@ -3133,14 +3155,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (child == leftPaintingOverlay || child == rightPaintingOverlay) {
return false;
}
if (child != navigationBar && (captionEdit == null || !captionEdit.editText.isPopupView(child))) {
canvas.save();
// canvas.clipRect(0, 0, getWidth(), getHeight());
}
// if (child != navigationBar && (captionEdit == null || !captionEdit.editText.isPopupView(child))) {
// canvas.save();
//// canvas.clipRect(0, 0, getWidth(), getHeight());
// }
boolean result = this.drawChildInternal(canvas, child, drawingTime);
if (child != navigationBar && (captionEdit == null || !captionEdit.editText.isPopupView(child))) {
canvas.restore();
}
// if (child != navigationBar && (captionEdit == null || !captionEdit.editText.isPopupView(child))) {
// canvas.restore();
// }
return result;
}
@ -3179,10 +3201,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
public int getBottomOffset(int tag) {
int offset = 0;
if (editing) {
if (captionEdit != null && captionEdit.getVisibility() == VISIBLE) {
if (captionEdit != null) {
offset += captionEdit.keyboardNotifier.getKeyboardHeight();
if (captionEdit.getVisibility() == VISIBLE && !(placeProvider != null && placeProvider.isCaptionAbove())) {
offset += captionEdit.getEditTextHeight() + dp(12);
}
if (pickerView != null && pickerView.getVisibility() == VISIBLE) {
}
if (pickerView != null && pickerView.getVisibility() == VISIBLE && (captionEdit == null || !captionEdit.keyboardNotifier.keyboardVisible())) {
offset += pickerView.getHeight();
}
} else {
@ -3195,6 +3220,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
return offset;
}
@Override
public int getTopOffset(int tag) {
final int topMargin = (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
return topMargin + (int) (topCaptionEdit.getAlpha() * topCaptionEdit.getEditTextHeight());
}
});
}
@ -5938,7 +5969,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
public void setTranslationY(float translationY) {
super.setTranslationY(translationY);
if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != GONE) {
videoTimelineViewContainer.setTranslationY(translationY - Math.max(0, captionEdit.getEditTextHeight() - dp(46)));
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
if (captionEditContainer != null) {
captionEditContainer.setTranslationY(translationY);
@ -5955,7 +5986,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
videoTimelineViewContainer.setAlpha(alpha);
}
if (captionEdit != null && captionEdit.getVisibility() != GONE) {
captionEdit.setAlpha(alpha);
captionEdit.setAlpha(alpha * captionEditAlpha[0]);
}
if (topCaptionEdit != null && topCaptionEdit.getVisibility() != GONE) {
topCaptionEdit.setAlpha(alpha * topCaptionEditAlpha[0]);
}
}
@ -6200,7 +6234,35 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
@Override
protected void drawBlur(BlurringShader.StoryBlurDrawer blur, Canvas canvas, RectF rect, float r, boolean text, float ox, float oy, boolean thisView) {
public void updateKeyboard(int keyboardHeight) {
super.updateKeyboard(keyboardHeight);
final Bulletin bulletin = Bulletin.getVisibleBulletin();
if (bulletin != null) {
bulletin.updatePosition();
}
updateMoveCaptionButton();
if (bottomBulletinUnderCaption != null) {
bottomBulletinUnderCaption.animate()
.translationY(-Math.max(0, keyboardHeight - pickerView.getHeight()))
.setDuration(AdjustPanLayoutHelper.keyboardDuration)
.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator)
.start();
}
}
@Override
public void setText(CharSequence text) {
super.setText(text);
updateMoveCaptionButton();
}
private void updateMoveCaptionButton() {
final boolean show = (placeProvider != null && placeProvider.canMoveCaptionAbove()) && (captionEdit.keyboardNotifier.keyboardVisible() || !isCurrentVideo && !TextUtils.isEmpty(getCaptionView().getText()));
setShowMoveButtonVisible(show, true);
}
@Override
protected void drawBlur(BlurringShader.StoryBlurDrawer blur, Canvas canvas, RectF rect, float r, boolean text, float ox, float oy, boolean thisView, float alpha) {
canvas.save();
path.rewind();
path.addRoundRect(rect, r, r, Path.Direction.CW);
@ -6210,7 +6272,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
} else {
canvas.translate(ox, oy);
}
drawCaptionBlur(canvas, blur, text ? 0xFF787878 : 0xFF262626, thisView ? (text ? 0 : 0x33000000) : 0x44000000, false, !text, !text && thisView);
drawCaptionBlur(canvas, blur, Theme.multAlpha(text ? 0xFF787878 : 0xFF262626, alpha), Theme.multAlpha(thisView ? (text ? 0 : 0x33000000) : 0x44000000, alpha), false, !text, !text && thisView);
canvas.restore();
}
@ -6238,6 +6300,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
mentionContainer.getAdapter().setNeedBotContext(false);
}
@Override
public void updateMentionsLayoutPosition() {
if (mentionContainer != null) {
mentionContainer.setTranslationY(-getEditTextHeight() - keyboardNotifier.getKeyboardHeight());
}
}
@Override
protected void onUpdateShowKeyboard(float keyboardT) {
super.onUpdateShowKeyboard(keyboardT);
@ -6252,6 +6321,29 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
super.invalidate();
}
@Override
protected boolean showMoveButton() {
return placeProvider != null && placeProvider.canMoveCaptionAbove();
}
@Override
protected boolean isAtTop() {
return false;
}
@Override
protected void onMoveButtonClick() {
toggleCaptionAbove();
}
@Override
protected void openedKeyboard() {
expandMoveButton();
if (topCaptionEdit != null) {
topCaptionEdit.expandMoveButton();
}
}
};
captionEdit.setOnTimerChange(seconds -> {
Object object1 = imagesArrLocals.get(currentIndex);
@ -6263,13 +6355,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (seconds != 0 && !placeProvider.isPhotoChecked(currentIndex)) {
setPhotoChecked();
}
topCaptionEdit.setTimer(seconds);
});
captionEdit.setAccount(currentAccount);
captionEdit.setOnHeightUpdate(height -> {
if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) {
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)));
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
muteItem.setTranslationY(-Math.max(0, height - dp(46)) * captionEdit.getAlpha());
if (captionEdit.mentionContainer != null) {
captionEdit.mentionContainer.setTranslationY(-height);
}
muteItem.setTranslationY(-Math.max(0, height - dp(46)));
});
captionEdit.setOnAddPhotoClick(v -> {
if (placeProvider == null || isCaptionOpen()) {
@ -6279,6 +6375,125 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
closePhoto(true, false);
});
topCaptionEdit = new CaptionPhotoViewer(activityContext, windowView, containerView, containerView, resourcesProvider, blurManager, this::applyCaption) {
private final Path path = new Path();
@Override
protected boolean customBlur() {
return true;
}
@Override
protected boolean ignoreTouches(float x, float y) {
return !keyboardShown && currentEditMode != EDIT_MODE_NONE;
}
@Override
protected void drawBlur(BlurringShader.StoryBlurDrawer blur, Canvas canvas, RectF rect, float r, boolean text, float ox, float oy, boolean thisView, float alpha) {
canvas.save();
path.rewind();
path.addRoundRect(rect, r, r, Path.Direction.CW);
canvas.clipPath(path);
if (thisView) {
canvas.translate(-getX() - topCaptionEditContainer.getX() + ox, -getY() - topCaptionEditContainer.getY() + oy);
} else {
canvas.translate(ox, oy);
}
drawCaptionBlur(canvas, blur, Theme.multAlpha(text ? 0xFF787878 : 0xFF262626, alpha), Theme.multAlpha(thisView ? (text ? 0 : 0x33000000) : 0x44000000, alpha), false, !text, !text && thisView);
canvas.restore();
}
@Override
protected boolean captionLimitToast() {
if (limitBulletin != null && Bulletin.getVisibleBulletin() == limitBulletin) {
return false;
}
return showCaptionLimitBulletin(containerView);
}
@Override
public void invalidate() {
if (SharedConfig.photoViewerBlur && (animationInProgress == 1 || animationInProgress == 2 || animationInProgress == 3)) {
return;
}
super.invalidate();
}
@Override
protected void setupMentionContainer() {
mentionContainer.setReversed(true);
mentionContainer.getAdapter().setAllowStickers(false);
mentionContainer.getAdapter().setAllowBots(false);
mentionContainer.getAdapter().setAllowChats(false);
mentionContainer.getAdapter().setSearchInDailogs(true);
if (parentChatActivity != null) {
mentionContainer.getAdapter().setChatInfo(parentChatActivity.chatInfo);
mentionContainer.getAdapter().setNeedUsernames(parentChatActivity.currentChat != null);
} else {
mentionContainer.getAdapter().setChatInfo(null);
mentionContainer.getAdapter().setNeedUsernames(false);
}
mentionContainer.getAdapter().setNeedBotContext(false);
mentionContainer.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP));
}
@Override
public void updateMentionsLayoutPosition() {
if (mentionContainer != null) {
mentionContainer.setTranslationY(getEditTextHeight());
}
}
@Override
protected boolean showMoveButton() {
return placeProvider != null && placeProvider.canMoveCaptionAbove();
}
@Override
protected boolean isAtTop() {
return true;
}
@Override
protected void onMoveButtonClick() {
toggleCaptionAbove();
}
@Override
protected void openedKeyboard() {
expandMoveButton();
if (captionEdit != null) {
captionEdit.expandMoveButton();
}
}
};
topCaptionEdit.setShowMoveButtonVisible(true, false);
topCaptionEdit.setOnTimerChange(seconds -> {
Object object1 = imagesArrLocals.get(currentIndex);
if (object1 instanceof MediaController.PhotoEntry) {
((MediaController.PhotoEntry) object1).ttl = seconds;
} else if (object1 instanceof MediaController.SearchImage) {
((MediaController.SearchImage) object1).ttl = seconds;
}
if (seconds != 0 && !placeProvider.isPhotoChecked(currentIndex)) {
setPhotoChecked();
}
captionEdit.setTimer(seconds);
});
topCaptionEdit.setAccount(currentAccount);
topCaptionEdit.setOnHeightUpdate(height -> {
if (topCaptionEdit.mentionContainer != null) {
topCaptionEdit.mentionContainer.setTranslationY(height);
}
});
topCaptionEdit.setOnAddPhotoClick(v -> {
if (placeProvider == null || isCaptionOpen()) {
return;
}
placeProvider.needAddMorePhotos();
closePhoto(true, false);
});
stickerMakerBackgroundView = new StickerMakerBackgroundView(activityContext) {
@Override
public void setAlpha(float alpha) {
@ -6512,6 +6727,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
captionEditContainer.addView(captionEdit, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.BOTTOM));
containerView.addView(captionEditContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.BOTTOM, 0, 8, 0, 0));
topCaptionEditContainer = new FrameLayout(parentActivity);
topCaptionEditContainer.addView(topCaptionEdit, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP));
containerView.addView(topCaptionEditContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 8, 0, 0));
topBulletinUnderCaption = new FrameLayout(parentActivity);
containerView.addView(topBulletinUnderCaption, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.FILL_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0));
bottomBulletinUnderCaption = new FrameLayout(parentActivity);
containerView.addView(bottomBulletinUnderCaption, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 0));
videoAvatarTooltip = new TextView(parentActivity);
videoAvatarTooltip.setSingleLine(true);
videoAvatarTooltip.setVisibility(View.GONE);
@ -7541,9 +7766,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
private boolean isCaptionOpen() {
final CaptionContainerView captionView = getCaptionView();
return (
captionEdit != null &&
(captionEdit.keyboardNotifier.keyboardVisible() || captionEdit.editText.isPopupShowing())
captionView != null &&
(captionView.keyboardNotifier.keyboardVisible() || captionView.editText.isPopupShowing())
);
}
@ -9020,11 +9246,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (currentIndex < 0 || currentIndex >= imagesArrLocals.size() || !isCaptionOpen()) {
return;
}
Object object = imagesArrLocals.get(currentIndex);
if (apply) {
applyCaption();
}
captionEdit.onBackPressed();
getCaptionView().onBackPressed();
}
private CaptionContainerView getCaptionView() {
return placeProvider != null && placeProvider.isCaptionAbove() ? topCaptionEdit : captionEdit;
}
private CharSequence applyCaption() {
@ -9033,7 +9262,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
Object object = imagesArrLocals.get(currentIndex);
CharSequence caption = captionEdit.getText();
CharSequence caption = getCaptionView().getText();
CharSequence[] result = new CharSequence[] { caption };
if (hasCaptionForAllMedia && !TextUtils.equals(captionForAllMedia, caption) && placeProvider.getPhotoIndex(currentIndex) != 0 && placeProvider.getSelectedCount() > 0) {
@ -9212,6 +9441,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (captionEdit != null) {
captionEdit.updateColors(resourcesProvider);
}
if (topCaptionEdit != null) {
topCaptionEdit.updateColors(resourcesProvider);
}
if (videoTimelineView != null) {
videoTimelineView.invalidate();
}
@ -10117,11 +10349,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
caption = ((MediaController.SearchImage) object).caption;
}
if (TextUtils.isEmpty(caption)) {
captionEdit.setText("");
getCaptionView().setText("");
} else {
captionEdit.setText(AnimatedEmojiSpan.cloneSpans(caption, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW));
getCaptionView().setText(AnimatedEmojiSpan.cloneSpans(caption, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW));
}
captionEdit.editText.getEditText().setAllowTextEntitiesIntersection(supportsSendingNewEntities());
getCaptionView().editText.getEditText().setAllowTextEntitiesIntersection(supportsSendingNewEntities());
}
public void showAlertDialog(AlertDialog.Builder builder) {
@ -11184,7 +11416,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
imageMoveAnimation = null;
final int fromEditMode = currentEditMode;
currentEditMode = mode;
captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
getCaptionView().keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -11415,7 +11647,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
imageMoveAnimation = null;
currentEditMode = mode;
captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
getCaptionView().keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -11599,7 +11831,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
photoFilterView.init();
imageMoveAnimation = null;
currentEditMode = mode;
captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
getCaptionView().keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -12034,7 +12266,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
paintingOverlay.hideEntities();
imageMoveAnimation = null;
currentEditMode = EDIT_MODE_PAINT;
captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
getCaptionView().keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -12078,10 +12310,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
animatorSet.setDuration(200);
animatorSet.start();
if (!show && isCaptionOpen()) {
closeCaptionEnter(true);
if (captionEdit.editText.isPopupShowing()) {
captionEdit.editText.hidePopup(true);
}
if (topCaptionEdit.editText.isPopupShowing()) {
topCaptionEdit.editText.hidePopup(true);
}
captionEdit.editText.closeKeyboard();
topCaptionEdit.editText.closeKeyboard();
}
}
@ -12772,7 +13009,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
totalImagesCount = 0;
totalImagesCountMerge = 0;
currentEditMode = EDIT_MODE_NONE;
captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
getCaptionView().keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -12892,6 +13129,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
tuneItem.setVisibility(View.GONE);
tuneItem.setTag(null);
captionEdit.setTimerVisible(false, false);
captionEdit.setShowMoveButtonVisible(false, false);
topCaptionEdit.setTimerVisible(false, false);
rotateItem.setVisibility(View.GONE);
mirrorItem.setVisibility(View.GONE);
@ -13115,6 +13354,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
updateActionBarTitlePadding();
}
captionEdit.setAddPhotoVisible(sendPhotoType != SELECT_TYPE_NO_SELECT && (sendPhotoType == 2 || sendPhotoType == 5) && placeProvider.canCaptureMorePhotos(), false);
topCaptionEdit.setAddPhotoVisible(sendPhotoType != SELECT_TYPE_NO_SELECT && (sendPhotoType == 2 || sendPhotoType == 5) && placeProvider.canCaptureMorePhotos(), false);
menuItem.setVisibility(View.GONE);
imagesArrLocals.addAll(photos);
Object obj = imagesArrLocals.get(index);
@ -13161,6 +13401,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
captionEdit.mentionContainer.getAdapter().setNeedUsernames(parentChatActivity.currentChat != null);
captionEdit.mentionContainer.getAdapter().setNeedBotContext(false);
}
if (parentChatActivity != null && topCaptionEdit.mentionContainer != null) {
topCaptionEdit.mentionContainer.getAdapter().setChatInfo(parentChatActivity.chatInfo);
topCaptionEdit.mentionContainer.getAdapter().setNeedUsernames(parentChatActivity.currentChat != null);
topCaptionEdit.mentionContainer.getAdapter().setNeedBotContext(false);
}
// if (parentChatActivity != null) {
// mentionsAdapter.setChatInfo(parentChatActivity.chatInfo);
// mentionsAdapter.setNeedUsernames(parentChatActivity.currentChat != null);
@ -13268,21 +13513,19 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
playerAutoStarted = true;
onActionClick(false);
} else if (!imagesArrLocals.isEmpty()) {
Object entry = imagesArrLocals.get(index);
CharSequence caption = null;
TLRPC.User user = parentChatActivity != null ? parentChatActivity.getCurrentUser() : null;
final Object entry = imagesArrLocals.get(index);
final TLRPC.User user = parentChatActivity != null ? parentChatActivity.getCurrentUser() : null;
boolean allowTimeItem = !isDocumentsPicker && parentChatActivity != null && !parentChatActivity.isSecretChat() && !parentChatActivity.isInScheduleMode() && user != null && !user.bot && !UserObject.isUserSelf(user) && !parentChatActivity.isEditingMessageMedia();
if (placeProvider != null && placeProvider.getEditingMessageObject() != null) {
allowTimeItem = false;
}
if (entry instanceof TLRPC.BotInlineResult) {
allowTimeItem = false;
} else if (entry instanceof MediaController.PhotoEntry) {
} else if (allowTimeItem && entry instanceof MediaController.SearchImage) {
allowTimeItem = ((MediaController.SearchImage) entry).type == 0;
}
captionEdit.setTimerVisible(allowTimeItem, true);
topCaptionEdit.setTimerVisible(allowTimeItem, true);
}
checkFullscreenButton();
}
@ -13890,6 +14133,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
PorterDuffColorFilter filter = new PorterDuffColorFilter(getThemedColor(Theme.key_chat_editMediaButton), PorterDuff.Mode.MULTIPLY);
captionEdit.setIsVideo(isVideo);
captionEdit.setTimer(ttl);
topCaptionEdit.setIsVideo(isVideo);
topCaptionEdit.setTimer(ttl);
paintItem.setColorFilter(isPainted ? filter : null);
cropItem.setColorFilter(isCropped ? filter : null);
tuneItem.setColorFilter(isFiltered ? filter : null);
@ -14213,43 +14458,63 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
eraseBtn.setTag(show ? 1 : null);
}
private ObjectAnimator captionAnimator;
private void showEditCaption(boolean show, boolean animated) {
final boolean top = placeProvider != null && placeProvider.isCaptionAbove();
showEditCaption(captionEdit, show && !top, animated, captionEditAlpha);
showEditCaption(topCaptionEdit, show && top, animated, topCaptionEditAlpha);
}
private final float[] captionEditAlpha = new float[] { 1.0f };
private final float[] topCaptionEditAlpha = new float[] { 1.0f };
private void showEditCaption(View view, boolean show, boolean animated, float[] alphaHolder) {
final float tr = dp(placeProvider != null && placeProvider.canMoveCaptionAbove() ? 175 : 58) * (view == topCaptionEdit ? -1.0f : 1.0f);
if (!animated) {
captionEdit.animate().setListener(null).cancel();
captionEdit.setVisibility(show ? View.VISIBLE : View.GONE);
captionEdit.setTranslationY(0);
captionEdit.setAlpha(pickerView.getAlpha());
view.animate().setListener(null).cancel();
view.setVisibility(show ? View.VISIBLE : View.GONE);
view.setTranslationY(show ? 0 : tr);
view.setAlpha(pickerView.getAlpha() * (alphaHolder[0] = show ? 1.0f : 0.0f));
} else {
if (show && captionEdit.getTag() == null) {
if (captionEdit.getVisibility() != View.VISIBLE) {
captionEdit.setVisibility(View.VISIBLE);
captionEdit.setAlpha(pickerView.getAlpha());
captionEdit.setTranslationY(dp(58));
if (show && view.getTag() == null) {
if (view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
view.setAlpha(pickerView.getAlpha());
view.setTranslationY(tr);
}
if (captionAnimator != null) {
captionAnimator.removeAllListeners();
captionAnimator.cancel();
view.animate()
.translationY(0)
.setUpdateListener(v -> {
view.setAlpha(pickerView.getAlpha() * (alphaHolder[0] = v.getAnimatedFraction()));
if (view == captionEdit) {
if (videoTimelineViewContainer != null) {
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
captionAnimator = ObjectAnimator.ofFloat(captionEdit, View.TRANSLATION_Y, captionEdit.getTranslationY(), 0);
captionAnimator.setDuration(220);
captionAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
captionAnimator.start();
} else if (!show && captionEdit.getTag() != null) {
if (captionAnimator != null) {
captionAnimator.removeAllListeners();
captionAnimator.cancel();
muteItem.setTranslationY(-Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
captionAnimator = ObjectAnimator.ofFloat(captionEdit, View.TRANSLATION_Y, captionEdit.getTranslationY(), dp(58));
captionAnimator.addListener(new HideViewAfterAnimation(captionEdit));
captionAnimator.setDuration(220);
captionAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
captionAnimator.start();
invalidateBlur();
})
.setDuration(420)
.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT)
.start();
} else if (!show && view.getTag() != null) {
view.animate()
.translationY(tr)
.setUpdateListener(v -> {
view.setAlpha(pickerView.getAlpha() * (alphaHolder[0] = (1.0f - v.getAnimatedFraction())));
if (view == captionEdit) {
if (videoTimelineViewContainer != null) {
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
muteItem.setTranslationY(-Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
invalidateBlur();
})
.setDuration(420)
.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT)
.withEndAction(() -> view.setVisibility(View.GONE))
.start();
}
}
captionEdit.setTag(show ? 1 : null);
view.setTag(show ? 1 : null);
}
private ObjectAnimator videoTimelineAnimator;
@ -14289,7 +14554,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
}
if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) {
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)));
videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46)) * captionEdit.getAlpha());
}
videoTimelineViewContainer.setTag(show ? 1 : null);
}
@ -14689,6 +14954,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (dialogId == 0 && currentMessageObject != null)
dialogId = currentMessageObject.getDialogId();
captionEdit.setDialogId(dialogId);
if (topCaptionEdit != null) {
topCaptionEdit.setDialogId(dialogId);
}
}
}
@ -14703,11 +14971,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
final CharSequence caption = AnimatedEmojiSpan.cloneSpans(_caption, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW);
showEditCaption(editing, animated);
if (editing || sendPhotoType == SELECT_TYPE_AVATAR) {
captionEdit.setText(caption);
getCaptionView().setText(caption);
captionTextViewSwitcher.setVisibility(View.GONE);
return;
} else {
captionEdit.setVisibility(View.GONE);
topCaptionEdit.setVisibility(View.GONE);
}
if (needCaptionLayout) {
if (captionTextViewSwitcher.getParent() != pickerView) {
@ -15206,7 +15475,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
public int getSelectionLength() {
return captionEdit.editText != null ? captionEdit.getSelectionLength() : 0;
return getCaptionView().editText != null ? getCaptionView().getSelectionLength() : 0;
}
private void setIndexToPaintingOverlay(int index, PaintingOverlay paintingOverlay) {
@ -16647,7 +16916,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
maskPaintView = null;
}
currentEditMode = EDIT_MODE_NONE;
captionEdit.keyboardNotifier.ignore(false);
getCaptionView().keyboardNotifier.ignore(false);
if (paintKeyboardNotifier != null) {
paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT);
}
@ -17373,7 +17642,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
return true;
}
if (captionEdit.editText.isPopupShowing() || captionEdit.editText.isKeyboardVisible()) {
if (getCaptionView().editText.isPopupShowing() || getCaptionView().editText.isKeyboardVisible()) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
closeCaptionEnter(true);
}
@ -20867,6 +21136,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (captionEdit != null) {
captionEdit.invalidateBlur();
}
if (topCaptionEdit != null) {
topCaptionEdit.invalidateBlur();
}
if (cutOutBtn != null) {
cutOutBtn.invalidateBlur();
}
@ -21442,4 +21714,43 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
videoItem.toggleSubMenu();
}
}
private void toggleCaptionAbove() {
if (placeProvider == null) return;
if (!placeProvider.canMoveCaptionAbove()) return;
final CaptionContainerView fromView = getCaptionView();
placeProvider.moveCaptionAbove(!placeProvider.isCaptionAbove());
showEditCaption(true, true);
final CaptionContainerView toView = getCaptionView();
final boolean above = placeProvider.isCaptionAbove();
if (fromView != toView) {
fromView.editText.hidePopup(true);
toView.setText(AnimatedEmojiSpan.cloneSpans(fromView.getText()));
toView.editText.getEditText().setAllowTextEntitiesIntersection(fromView.editText.getEditText().getAllowTextEntitiesIntersection());
if (fromView.editText.getEditText().isFocused()) {
toView.editText.getEditText().requestFocus();
toView.editText.getEditText().setSelection(
fromView.editText.getEditText().getSelectionStart(),
fromView.editText.getEditText().getSelectionEnd()
);
}
if (fromView.mentionContainer != null) {
AndroidUtilities.removeFromParent(fromView.mentionContainer);
fromView.mentionContainer = null;
}
}
if (MessagesController.getInstance(currentAccount).shouldShowMoveCaptionHint()) {
MessagesController.getInstance(currentAccount).incrementMoveCaptionHint();
BulletinFactory.of(above ? bottomBulletinUnderCaption : topBulletinUnderCaption, new DarkThemeResourceProvider())
.createSimpleBulletin(
above ? R.raw.caption_up : R.raw.caption_down,
getString(above ? R.string.MovedCaptionUp : R.string.MovedCaptionDown),
getString(above ? R.string.MovedCaptionUpText : R.string.MovedCaptionDownText)
)
.setImageScale(.8f)
.show(!above);
}
}
}

View file

@ -14,6 +14,8 @@ import static org.telegram.messenger.ContactsController.PRIVACY_RULES_TYPE_ADDED
import static org.telegram.messenger.LocaleController.formatPluralString;
import static org.telegram.messenger.LocaleController.formatString;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.Stars.StarsIntroActivity.formatStarsAmountShort;
import static org.telegram.ui.bots.AffiliateProgramFragment.percents;
import android.Manifest;
import android.animation.Animator;
@ -161,6 +163,8 @@ import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_bots;
import org.telegram.tgnet.tl.TL_fragment;
import org.telegram.tgnet.tl.TL_payments;
import org.telegram.tgnet.tl.TL_stars;
import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
@ -269,10 +273,12 @@ import org.telegram.ui.Stories.StoryViewer;
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
import org.telegram.ui.Stories.recorder.DualCameraView;
import org.telegram.ui.Stories.recorder.StoryRecorder;
import org.telegram.ui.bots.AffiliateProgramFragment;
import org.telegram.ui.bots.BotBiometry;
import org.telegram.ui.bots.BotDownloads;
import org.telegram.ui.bots.BotLocation;
import org.telegram.ui.bots.BotWebViewAttachedSheet;
import org.telegram.ui.bots.ChannelAffiliateProgramsFragment;
import org.telegram.ui.bots.SetupEmojiStatusSheet;
import java.io.BufferedInputStream;
@ -593,6 +599,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
private int notificationsSimpleRow;
private int infoStartRow, infoEndRow;
private int infoSectionRow;
private int affiliateRow;
private int infoAffiliateRow;
private int sendMessageRow;
private int reportRow;
private int reportReactionRow;
@ -3713,7 +3721,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
return;
}
listView.stopScroll();
if (position == notificationsSimpleRow) {
if (position == affiliateRow) {
TLRPC.User user = getMessagesController().getUser(userId);
if (userInfo != null && userInfo.starref_program != null) {
final long selfId = getUserConfig().getClientUserId();
BotStarsController.getInstance(currentAccount).getConnectedBot(getContext(), selfId, userId, connectedBot -> {
if (connectedBot == null) {
ChannelAffiliateProgramsFragment.showConnectAffiliateAlert(context, currentAccount, userInfo.starref_program, getUserConfig().getClientUserId(), resourcesProvider, false);
} else {
ChannelAffiliateProgramsFragment.showShareAffiliateAlert(context, currentAccount, connectedBot, selfId, resourcesProvider);
}
});
} else if (user != null && user.bot_can_edit) {
presentFragment(new AffiliateProgramFragment(userId));
}
} else if (position == notificationsSimpleRow) {
boolean muted = getMessagesController().isDialogMuted(did, topicId);
getNotificationsController().muteDialog(did, topicId, !muted);
BulletinFactory.createMuteBulletin(ProfileActivity.this, !muted, null).show();
@ -4239,7 +4261,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
PersistColorPalette.getInstance(currentAccount).cleanup();
SharedPreferences prefs = getMessagesController().getMainSettings();
editor = prefs.edit();
editor.remove("peerColors").remove("profilePeerColors").remove("boostingappearance").remove("bizbothint");
editor.remove("peerColors").remove("profilePeerColors").remove("boostingappearance").remove("bizbothint").remove("movecaptionhint");
for (String key : prefs.getAll().keySet()) {
if (key.contains("show_gift_for_") || key.contains("bdayhint_") || key.contains("bdayanim_")) {
editor.remove(key);
@ -8755,6 +8777,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
bizLocationRow = -1;
bizHoursRow = -1;
infoSectionRow = -1;
affiliateRow = -1;
infoAffiliateRow = -1;
secretSettingsSectionRow = -1;
bottomPaddingRow = -1;
addToGroupButtonRow = -1;
@ -8940,6 +8964,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
infoEndRow = rowCount - 1;
infoSectionRow = rowCount++;
if (isBot && userInfo != null && userInfo.starref_program != null && (userInfo.starref_program.flags & 2) == 0 && getMessagesController().starrefConnectAllowed) {
affiliateRow = rowCount++;
infoAffiliateRow = rowCount++;
}
if (isBot) {
if (botLocation == null && getContext() != null) botLocation = BotLocation.get(getContext(), currentAccount, userId);
if (botBiometry == null && getContext() != null) botBiometry = BotBiometry.get(getContext(), currentAccount, userId);
@ -8981,7 +9010,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (userInfo != null && userInfo.can_view_revenue && BotStarsController.getInstance(currentAccount).getTONBalance(userId) > 0) {
botTonBalanceRow = rowCount++;
}
if (BotStarsController.getInstance(currentAccount).getBotStarsBalance(userId) > 0 || BotStarsController.getInstance(currentAccount).hasTransactions(userId)) {
if (BotStarsController.getInstance(currentAccount).getBotStarsBalance(userId).amount > 0 || BotStarsController.getInstance(currentAccount).hasTransactions(userId)) {
botStarsBalanceRow = rowCount++;
}
}
@ -9060,7 +9089,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (
chatInfo != null &&
chatInfo.can_view_stars_revenue && (
BotStarsController.getInstance(currentAccount).getBotStarsBalance(did) > 0 ||
BotStarsController.getInstance(currentAccount).getBotStarsBalance(did).amount > 0 ||
BotStarsController.getInstance(currentAccount).hasTransactions(did)
) ||
chatInfo != null &&
@ -10875,7 +10904,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
VIEW_TYPE_CHANNEL = 23,
VIEW_TYPE_STARS_TEXT_CELL = 24,
VIEW_TYPE_BOT_APP = 25,
VIEW_TYPE_SHADOW_TEXT = 26;
VIEW_TYPE_SHADOW_TEXT = 26,
VIEW_TYPE_COLORFUL_TEXT = 27;
private Context mContext;
@ -10968,6 +10998,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
view = new TextInfoPrivacyCell(mContext, resourcesProvider);
break;
}
case VIEW_TYPE_COLORFUL_TEXT: {
view = new AffiliateProgramFragment.ColorfulTextCell(mContext, resourcesProvider);
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
break;
}
case VIEW_TYPE_USER: {
view = new UserCell(mContext, addMemberRow == -1 ? 9 : 6, 0, true, resourcesProvider);
view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite));
@ -11441,8 +11476,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
} else if (position == settingsRow) {
textCell.setTextAndIcon(LocaleController.getString(R.string.ChannelAdminSettings), R.drawable.msg_customize, position != membersSectionRow - 1);
} else if (position == channelBalanceRow) {
long stars_balance = BotStarsController.getInstance(currentAccount).getBotStarsBalance(-chatId);
long ton_balance = BotStarsController.getInstance(currentAccount).getTONBalance(-chatId);
final TL_stars.StarsAmount stars_balance = BotStarsController.getInstance(currentAccount).getBotStarsBalance(-chatId);
final long ton_balance = BotStarsController.getInstance(currentAccount).getTONBalance(-chatId);
SpannableStringBuilder ssb = new SpannableStringBuilder();
if (ton_balance > 0) {
if (ton_balance / 1_000_000_000.0 > 1000.0) {
@ -11457,16 +11492,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
ssb.append("TON ").append(formatterTON.format(ton_balance / 1_000_000_000.0));
}
}
if (stars_balance > 0) {
if (stars_balance.amount > 0) {
if (ssb.length() > 0) ssb.append(" ");
ssb.append("XTR ").append(AndroidUtilities.formatWholeNumber((int) stars_balance, 0));
ssb.append("XTR ").append(formatStarsAmountShort(stars_balance));
}
textCell.setTextAndValueAndIcon(getString(R.string.ChannelStars), ChannelMonetizationLayout.replaceTON(StarsIntroActivity.replaceStarsWithPlain(ssb, .7f), textCell.getTextView().getPaint()), R.drawable.menu_feature_paid, true);
} else if (position == botStarsBalanceRow) {
long stars_balance = BotStarsController.getInstance(currentAccount).getBotStarsBalance(userId);
final TL_stars.StarsAmount stars_balance = BotStarsController.getInstance(currentAccount).getBotStarsBalance(userId);
SpannableStringBuilder ssb = new SpannableStringBuilder();
if (stars_balance > 0) {
ssb.append("XTR ").append(AndroidUtilities.formatWholeNumber((int) stars_balance, 0));
if (stars_balance.amount > 0) {
ssb.append("XTR ").append(formatStarsAmountShort(stars_balance));
}
textCell.setTextAndValueAndIcon(getString(R.string.BotBalanceStars), ChannelMonetizationLayout.replaceTON(StarsIntroActivity.replaceStarsWithPlain(ssb, .7f), textCell.getTextView().getPaint()), R.drawable.menu_premium_main, true);
} else if (position == botTonBalanceRow) {
@ -11563,7 +11598,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
textCell.setImageLeft(23);
} else if (position == starsRow) {
StarsController c = StarsController.getInstance(currentAccount);
long balance = c.getBalance();
long balance = c.getBalance().amount;
textCell.setTextAndValueAndIcon(LocaleController.getString(R.string.MenuTelegramStars), c.balanceAvailable() && balance > 0 ? LocaleController.formatNumber((int) balance, ',') : "", new AnimatedEmojiDrawable.WrapSizeDrawable(PremiumGradient.getInstance().goldenStarMenuDrawable, dp(24), dp(24)), true);
textCell.setImageLeft(23);
} else if (position == businessRow) {
@ -11668,6 +11703,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
cell.setFixedSize(14);
cell.setText(null);
}
} else if (position == infoAffiliateRow) {
final TLRPC.User botUser = getMessagesController().getUser(userId);
if (botUser != null && botUser.bot && botUser.bot_can_edit) {
cell.setFixedSize(0);
cell.setText(formatString(R.string.ProfileBotAffiliateProgramInfoOwner, UserObject.getUserName(botUser), percents(userInfo != null && userInfo.starref_program != null ? userInfo.starref_program.commission_permille : 0)));
} else {
cell.setFixedSize(0);
cell.setText(formatString(R.string.ProfileBotAffiliateProgramInfo, UserObject.getUserName(botUser), percents(userInfo != null && userInfo.starref_program != null ? userInfo.starref_program.commission_permille : 0)));
}
}
if (position == infoSectionRow && lastSectionRow == -1 && secretSettingsSectionRow == -1 && sharedMediaRow == -1 && membersSectionRow == -1 || position == secretSettingsSectionRow || position == lastSectionRow || position == membersSectionRow && lastSectionRow == -1 && sharedMediaRow == -1) {
cell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, getThemedColor(Theme.key_windowBackgroundGrayShadow)));
@ -11676,6 +11720,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
break;
}
case VIEW_TYPE_COLORFUL_TEXT: {
AffiliateProgramFragment.ColorfulTextCell cell = (AffiliateProgramFragment.ColorfulTextCell) holder.itemView;
cell.set(getThemedColor(Theme.key_color_green), R.drawable.filled_affiliate, getString(R.string.ProfileBotAffiliateProgram), null);
cell.setPercent(userInfo != null && userInfo.starref_program != null ? percents(userInfo.starref_program.commission_permille) : null);
break;
}
case VIEW_TYPE_USER:
UserCell userCell = (UserCell) holder.itemView;
TLRPC.ChatParticipant part;
@ -11897,7 +11947,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
int type = holder.getItemViewType();
return type != VIEW_TYPE_HEADER && type != VIEW_TYPE_DIVIDER && type != VIEW_TYPE_SHADOW &&
type != VIEW_TYPE_EMPTY && type != VIEW_TYPE_BOTTOM_PADDING && type != VIEW_TYPE_SHARED_MEDIA &&
type != 9 && type != 10; // These are legacy ones, left for compatibility
type != 9 && type != 10 && type != VIEW_TYPE_BOT_APP; // These are legacy ones, left for compatibility
}
@Override
@ -11966,8 +12016,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
return VIEW_TYPE_CHANNEL;
} else if (position == botAppRow) {
return VIEW_TYPE_BOT_APP;
} else if (position == infoSectionRow) {
} else if (position == infoSectionRow || position == infoAffiliateRow) {
return VIEW_TYPE_SHADOW_TEXT;
} else if (position == affiliateRow) {
return VIEW_TYPE_COLORFUL_TEXT;
}
return 0;
}
@ -13231,6 +13283,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
put(++pointer, reportDividerRow, sparseIntArray);
put(++pointer, notificationsRow, sparseIntArray);
put(++pointer, infoSectionRow, sparseIntArray);
put(++pointer, affiliateRow, sparseIntArray);
put(++pointer, infoAffiliateRow, sparseIntArray);
put(++pointer, sendMessageRow, sparseIntArray);
put(++pointer, reportRow, sparseIntArray);
put(++pointer, reportReactionRow, sparseIntArray);

View file

@ -1900,6 +1900,20 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati
next.run();
});
};
final Utilities.Callback<Runnable> serverSearch = next -> {
if (ConnectionsManager.getInstance(currentAccount).getConnectionState() != ConnectionsManager.ConnectionStateConnected) {
next.run();
return;
}
final String lang_code = newLanguage == null || newLanguage.length == 0 ? "" : newLanguage[0];
MediaDataController.getInstance(currentAccount).searchStickers(true, lang_code, query, documents -> {
AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocuments(documents);
for (TLRPC.Document doc : documents) {
documentIds.add(doc.id);
}
next.run();
});
};
final Utilities.Callback<Runnable> searchEmojiSuggestions = next -> {
if (queryFullyConsistsOfEmojis) {
ArrayList<TLRPC.TL_messages_stickerSet> stickerSets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJIPACKS);
@ -2059,7 +2073,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati
next.run();
};
Utilities.doCallbacks(searchCategories, searchByKeywords, searchEmojiSuggestions, searchAvatarConstructor, searchFromSets, applySearch);
Utilities.doCallbacks(searchCategories, searchByKeywords, serverSearch, searchEmojiSuggestions, searchAvatarConstructor, searchFromSets, applySearch);
}
}, delay ? 425 : 0);
if (searchBox != null) {

View file

@ -5,6 +5,7 @@ import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.messenger.LocaleController.formatString;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.ChannelMonetizationLayout.replaceTON;
import static org.telegram.ui.ChatEditActivity.applyNewSpan;
import android.app.Activity;
import android.content.Context;
@ -75,6 +76,8 @@ import org.telegram.ui.StatisticActivity;
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
import org.telegram.ui.TwoStepVerificationActivity;
import org.telegram.ui.TwoStepVerificationSetupActivity;
import org.telegram.ui.bots.AffiliateProgramFragment;
import org.telegram.ui.bots.ChannelAffiliateProgramsFragment;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@ -439,6 +442,7 @@ public class BotStarsActivity extends BaseFragment implements NotificationCenter
}
private final int BALANCE = 1;
private final int BUTTON_AFFILIATE = 2;
private CharSequence titleInfo;
private CharSequence proceedsInfo;
@ -455,15 +459,24 @@ public class BotStarsActivity extends BaseFragment implements NotificationCenter
items.add(UItem.asBlackHeader(getString(R.string.BotStarsOverview)));
TLRPC.TL_payments_starsRevenueStats stats = s.getStarsRevenueStats(bot_id);
if (stats != null && stats.status != null) {
availableValue.crypto_amount = stats.status.available_balance;
availableValue.contains1 = false;
availableValue.contains2 = true;
availableValue.crypto_amount2 = stats.status.available_balance;
availableValue.crypto_currency2 = "XTR";
availableValue.currency = "USD";
availableValue.amount = (long) (stats.status.available_balance * rate * 100.0);
totalValue.crypto_amount = stats.status.current_balance;
availableValue.amount2 = (long) (stats.status.available_balance.amount * rate * 100.0);
totalValue.contains1 = false;
totalValue.contains2 = true;
totalValue.crypto_amount2 = stats.status.current_balance;
totalValue.crypto_currency2 = "XTR";
totalValue.amount2 = (long) (stats.status.current_balance.amount * rate * 100.0);
totalValue.currency = "USD";
totalValue.amount = (long) (stats.status.current_balance * rate * 100.0);
totalProceedsValue.crypto_amount = stats.status.overall_revenue;
totalProceedsValue.contains1 = false;
totalProceedsValue.contains2 = true;
totalProceedsValue.crypto_amount2 = stats.status.overall_revenue;
totalProceedsValue.crypto_currency2 = "XTR";
totalProceedsValue.amount2 = (long) (stats.status.overall_revenue.amount * rate * 100.0);
totalProceedsValue.currency = "USD";
totalProceedsValue.amount = (long) (stats.status.overall_revenue * rate * 100.0);
setStarsBalance(stats.status.available_balance, stats.status.next_withdrawal_at);
balanceButtonsLayout.setVisibility(stats.status.withdrawal_enabled ? View.VISIBLE : View.GONE);
@ -475,6 +488,10 @@ public class BotStarsActivity extends BaseFragment implements NotificationCenter
items.add(UItem.asBlackHeader(getString(R.string.BotStarsAvailableBalance)));
items.add(UItem.asCustom(BALANCE, balanceLayout));
items.add(UItem.asShadow(-3, withdrawInfo));
if (getMessagesController().starrefConnectAllowed) {
items.add(AffiliateProgramFragment.ColorfulTextCell.Factory.as(BUTTON_AFFILIATE, Theme.getColor(Theme.key_color_green, resourceProvider), R.drawable.filled_earn_stars, applyNewSpan(getString(R.string.BotAffiliateProgramRowTitle)), getString(R.string.BotAffiliateProgramRowText)));
items.add(UItem.asShadow(-4, null));
}
items.add(UItem.asFullscreenCustom(transactionsLayout, 0));
} else if (type == TYPE_TON) {
TL_stats.TL_broadcastRevenueStats stats = s.getTONRevenueStats(bot_id, true);
@ -600,14 +617,16 @@ public class BotStarsActivity extends BaseFragment implements NotificationCenter
StarsIntroActivity.showTransactionSheet(getContext(), true, bot_id, currentAccount, t, getResourceProvider());
} else if (item.object instanceof TL_stats.BroadcastRevenueTransaction) {
ChannelMonetizationLayout.showTransactionSheet(getContext(), currentAccount, (TL_stats.BroadcastRevenueTransaction) item.object, bot_id, resourceProvider);
} else if (item.id == BUTTON_AFFILIATE) {
presentFragment(new ChannelAffiliateProgramsFragment(bot_id));
}
}
private void setStarsBalance(long crypto_amount, int blockedUntil) {
private void setStarsBalance(TL_stars.StarsAmount crypto_amount, int blockedUntil) {
if (balanceTitle == null || balanceSubtitle == null)
return;
long amount = (long) (rate * crypto_amount * 100.0);
SpannableStringBuilder ssb = new SpannableStringBuilder(StarsIntroActivity.replaceStarsWithPlain("XTR " + LocaleController.formatNumber(crypto_amount, ' '), 1f));
long amount = (long) (rate * crypto_amount.amount * 100.0);
SpannableStringBuilder ssb = new SpannableStringBuilder(StarsIntroActivity.replaceStarsWithPlain(TextUtils.concat("XTR ", StarsIntroActivity.formatStarsAmount(crypto_amount, 0.8f, ' ')), 1f));
int index = TextUtils.indexOf(ssb, ".");
if (index >= 0) {
ssb.setSpan(balanceTitleSizeSpan, index, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@ -617,7 +636,7 @@ public class BotStarsActivity extends BaseFragment implements NotificationCenter
balanceEditTextContainer.setVisibility(amount > 0 ? View.VISIBLE : View.GONE);
if (balanceEditTextAll) {
balanceEditTextIgnore = true;
balanceEditText.setText(Long.toString(balanceEditTextValue = crypto_amount));
balanceEditText.setText(Long.toString(balanceEditTextValue = crypto_amount.amount));
balanceEditText.setSelection(balanceEditText.getText().length());
balanceEditTextIgnore = false;

View file

@ -2,6 +2,9 @@ package org.telegram.ui.Stars;
import static org.telegram.messenger.LocaleController.getString;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
@ -9,10 +12,15 @@ import org.telegram.messenger.DialogObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_bots;
import org.telegram.tgnet.tl.TL_payments;
import org.telegram.tgnet.tl.TL_stars;
import org.telegram.tgnet.tl.TL_stats;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChannelMonetizationLayout;
@ -54,9 +62,9 @@ public class BotStarsController {
private final HashMap<Long, Long> lastLoadedTonStats = new HashMap<>();
private final HashMap<Long, TL_stats.TL_broadcastRevenueStats> tonStats = new HashMap<>();
public long getBotStarsBalance(long did) {
public TL_stars.StarsAmount getBotStarsBalance(long did) {
TLRPC.TL_payments_starsRevenueStats botStats = getStarsRevenueStats(did);
return botStats == null ? 0 : botStats.status.current_balance;
return botStats == null ? new TL_stars.StarsAmount(0) : botStats.status.current_balance;
}
public long getTONBalance(long did) {
@ -66,7 +74,7 @@ public class BotStarsController {
public long getAvailableBalance(long did) {
TLRPC.TL_payments_starsRevenueStats botStats = getStarsRevenueStats(did);
return botStats == null ? 0 : botStats.status.available_balance;
return botStats == null ? 0 : botStats.status.available_balance.amount;
}
public boolean isStarsBalanceAvailable(long did) {
@ -83,7 +91,7 @@ public class BotStarsController {
public boolean botHasStars(long did) {
TLRPC.TL_payments_starsRevenueStats stats = getStarsRevenueStats(did);
return stats != null && stats.status != null && (stats.status.available_balance > 0 || stats.status.overall_revenue > 0 || stats.status.current_balance > 0);
return stats != null && stats.status != null && (stats.status.available_balance.amount > 0 || stats.status.overall_revenue.amount > 0 || stats.status.current_balance.amount > 0);
}
public boolean botHasTON(long did) {
@ -238,8 +246,8 @@ public class BotStarsController {
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
state.loading[type] = false;
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
@ -273,4 +281,350 @@ public class BotStarsController {
return !state.transactions[type].isEmpty();
}
private final HashMap<Long, ChannelConnectedBots> connectedBots = new HashMap<>();
public static class ChannelConnectedBots {
public final int currentAccount;
public final long dialogId;
public int count;
public boolean endReached;
public final ArrayList<TL_payments.connectedBotStarRef> bots = new ArrayList<>();
public long lastRequestTime;
public ChannelConnectedBots(int currentAccount, long dialogId) {
this.currentAccount = currentAccount;
this.dialogId = dialogId;
check();
}
public void clear() {
count = 0;
error = false;
endReached = false;
}
public void check() {
if ((System.currentTimeMillis() - lastRequestTime) > 1000 * 60 * 15) {
clear();
cancel();
load();
}
}
public void cancel() {
if (reqId != 0) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true);
reqId = 0;
}
loading = false;
}
public boolean isLoading() {
return loading;
}
private boolean loading = false;
private boolean error = false;
private int reqId;
public void load() {
if (loading || error || endReached) return;
lastRequestTime = System.currentTimeMillis();
TL_payments.getConnectedStarRefBots req = new TL_payments.getConnectedStarRefBots();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
req.limit = 20;
if (!bots.isEmpty()) {
TL_payments.connectedBotStarRef bot = bots.get(bots.size() - 1);
req.flags |= 4;
req.offset_date = bot.date;
req.offset_link = bot.url;
}
reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
reqId = 0;
if (res instanceof TL_payments.connectedStarRefBots) {
TL_payments.connectedStarRefBots r = (TL_payments.connectedStarRefBots) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
if (count <= 0) {
bots.clear();
}
count = r.count;
bots.addAll(r.connected_bots);
endReached = r.connected_bots.isEmpty() || bots.size() >= count;
} else {
error = true;
endReached = true;
}
loading = false;
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.channelConnectedBotsUpdate, dialogId);
}));
}
public void apply(TL_payments.connectedStarRefBots res) {
MessagesController.getInstance(currentAccount).putUsers(res.users, false);
clear();
bots.clear();
cancel();
count = res.count;
bots.addAll(res.connected_bots);
endReached = res.connected_bots.isEmpty() || bots.size() >= count;
error = false;
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.channelConnectedBotsUpdate, dialogId);
load();
}
public void applyEdit(TL_payments.connectedStarRefBots res) {
MessagesController.getInstance(currentAccount).putUsers(res.users, false);
for (int a = 0; a < res.connected_bots.size(); ++a) {
TL_payments.connectedBotStarRef bot = res.connected_bots.get(a);
for (int i = 0; i < bots.size(); ++i) {
if (bots.get(i).bot_id == bot.bot_id) {
if (bot.revoked) {
bots.remove(i);
count = Math.max(count - 1, 0);
} else {
bots.set(i, bot);
}
break;
}
}
}
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.channelConnectedBotsUpdate, dialogId);
load();
}
}
public ChannelConnectedBots getChannelConnectedBots(long dialogId) {
ChannelConnectedBots bots = connectedBots.get(dialogId);
if (bots == null) {
connectedBots.put(dialogId, bots = new ChannelConnectedBots(currentAccount, dialogId));
}
return bots;
}
public boolean channelHasConnectedBots(long dialogId) {
final ChannelConnectedBots bots = getChannelConnectedBots(dialogId);
return bots != null && bots.count > 0;
}
private final HashMap<Long, ChannelSuggestedBots> suggestedBots = new HashMap<>();
public static class ChannelSuggestedBots {
public final int currentAccount;
public final long dialogId;
public int count;
public boolean endReached;
public final ArrayList<TL_payments.starRefProgram> bots = new ArrayList<>();
public long lastRequestTime;
public ChannelSuggestedBots(int currentAccount, long dialogId) {
this.currentAccount = currentAccount;
this.dialogId = dialogId;
check();
}
public void clear() {
count = 0;
endReached = false;
error = false;
lastRequestTime = 0;
lastOffset = null;
}
public void check() {
if ((System.currentTimeMillis() - lastRequestTime) > 1000 * 60 * 15) {
clear();
cancel();
load();
}
}
public void cancel() {
if (reqId != 0) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true);
reqId = 0;
}
loading = false;
}
public boolean isLoading() {
return loading;
}
public int getCount() {
return Math.max(count, bots.size());
}
public enum Sort {
BY_PROFITABILITY,
BY_REVENUE,
BY_DATE
};
private Sort sorting = Sort.BY_PROFITABILITY;
public void setSort(Sort sort) {
if (sorting != sort) {
sorting = sort;
reload();
}
}
public Sort getSort() {
return sorting;
}
private boolean loading = false;
private boolean error = false;
private String lastOffset = null;
private int reqId;
public void load() {
if (loading || error || endReached) return;
lastRequestTime = System.currentTimeMillis();
TL_payments.getSuggestedStarRefBots req = new TL_payments.getSuggestedStarRefBots();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
req.limit = 20;
req.order_by_date = sorting == Sort.BY_DATE;
req.order_by_revenue = sorting == Sort.BY_REVENUE;
if (!TextUtils.isEmpty(lastOffset)) {
req.offset = lastOffset;
} else {
req.offset = "";
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
if (res instanceof TL_payments.suggestedStarRefBots) {
TL_payments.suggestedStarRefBots r = (TL_payments.suggestedStarRefBots) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
if (count <= 0) {
bots.clear();
}
count = r.count;
bots.addAll(r.suggested_bots);
lastOffset = r.next_offset;
endReached = r.suggested_bots.isEmpty() || bots.size() >= count;
} else {
error = true;
endReached = true;
}
loading = false;
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.channelSuggestedBotsUpdate, dialogId);
}));
}
public void remove(long did) {
for (int i = 0; i < bots.size(); ++i) {
if (bots.get(i).bot_id == did) {
bots.remove(i);
count--;
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.channelSuggestedBotsUpdate, dialogId);
break;
}
}
}
public void reload() {
clear();
cancel();
load();
}
}
public ChannelSuggestedBots getChannelSuggestedBots(long dialogId) {
ChannelSuggestedBots bots = suggestedBots.get(dialogId);
if (bots == null) {
suggestedBots.put(dialogId, bots = new ChannelSuggestedBots(currentAccount, dialogId));
}
return bots;
}
public boolean channelHasSuggestedBots(long dialogId) {
final ChannelConnectedBots bots = getChannelConnectedBots(dialogId);
return bots != null && bots.count > 0;
}
private boolean loadingAdminedBots;
public ArrayList<TLRPC.User> adminedBots;
private boolean loadingAdminedChannels;
public ArrayList<TLRPC.Chat> adminedChannels;
public void loadAdmined() {
if (!loadingAdminedBots || adminedBots != null) {
loadingAdminedBots = true;
TL_bots.getAdminedBots req1 = new TL_bots.getAdminedBots();
ConnectionsManager.getInstance(currentAccount).sendRequest(req1, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
adminedBots = new ArrayList<>();
loadingAdminedBots = false;
if (res instanceof TLRPC.Vector) {
TLRPC.Vector vector = (TLRPC.Vector) res;
for (int i = 0; i < vector.objects.size(); ++i) {
adminedBots.add((TLRPC.User) vector.objects.get(i));
}
MessagesController.getInstance(currentAccount).putUsers(adminedBots, false);
}
}));
}
if (!loadingAdminedChannels || adminedChannels != null) {
loadingAdminedChannels = true;
TLRPC.TL_channels_getAdminedPublicChannels req2 = new TLRPC.TL_channels_getAdminedPublicChannels();
ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
adminedChannels = new ArrayList<>();
loadingAdminedBots = false;
if (res instanceof TLRPC.messages_Chats) {
TLRPC.messages_Chats chats = (TLRPC.messages_Chats) res;
MessagesController.getInstance(currentAccount).putChats(chats.chats, false);
adminedChannels.addAll(chats.chats);
}
}));
}
}
public ArrayList<TLObject> getAdmined() {
loadAdmined();
ArrayList<TLObject> list = new ArrayList<>();
if (adminedBots != null) {
list.addAll(adminedBots);
}
if (adminedChannels != null) {
list.addAll(adminedChannels);
}
return list;
}
public void getConnectedBot(Context context, long dialogId, long botId, Utilities.Callback<TL_payments.connectedBotStarRef> whenDone) {
if (whenDone == null) return;
ChannelConnectedBots bots = connectedBots.get(dialogId);
if (bots != null) {
for (int i = 0; i < bots.bots.size(); ++i) {
if (!bots.bots.get(i).revoked && bots.bots.get(i).bot_id == botId) {
whenDone.run(bots.bots.get(i));
return;
}
}
}
final AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER);
TL_payments.getConnectedStarRefBot req = new TL_payments.getConnectedStarRefBot();
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId);
int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
progressDialog.dismiss();
if (res instanceof TL_payments.connectedStarRefBots) {
TL_payments.connectedStarRefBots r = (TL_payments.connectedStarRefBots) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
for (int i = 0; i < r.connected_bots.size(); ++i) {
if (r.connected_bots.get(i).bot_id == botId && !r.connected_bots.get(i).revoked) {
whenDone.run(r.connected_bots.get(i));
return;
}
}
}
whenDone.run(null);
}));
progressDialog.setCanCancel(true);
progressDialog.setOnCancelListener(d -> {
ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true);
});
progressDialog.showDelayed(200);
}
}

View file

@ -7,12 +7,12 @@ import static org.telegram.messenger.LocaleController.getString;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.LongSparseArray;
import android.view.Gravity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.billingclient.api.BillingClient;
@ -105,22 +105,23 @@ public class StarsController {
private long lastBalanceLoaded;
private boolean balanceLoading, balanceLoaded;
public long balance;
@NonNull
public TL_stars.StarsAmount balance = new TL_stars.StarsAmount(0);
public long minus;
public long getBalance() {
public TL_stars.StarsAmount getBalance() {
return getBalance(null);
}
public long getBalance(boolean withMinus) {
return getBalance(withMinus, null);
return getBalance(withMinus, null).amount;
}
public long getBalance(Runnable loaded) {
public TL_stars.StarsAmount getBalance(Runnable loaded) {
return getBalance(true, loaded);
}
public long getBalance(boolean withMinus, Runnable loaded) {
public TL_stars.StarsAmount getBalance(boolean withMinus, Runnable loaded) {
if ((!balanceLoaded || System.currentTimeMillis() - lastBalanceLoaded > 1000 * 60) && !balanceLoading) {
balanceLoading = true;
TL_stars.TL_payments_getStarsStatus req = new TL_stars.TL_payments_getStarsStatus();
@ -130,15 +131,15 @@ public class StarsController {
boolean updatedSubscriptions = false;
boolean updatedBalance = !balanceLoaded;
lastBalanceLoaded = System.currentTimeMillis();
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
if (transactions[ALL_TRANSACTIONS].isEmpty()) {
for (TL_stars.StarsTransaction t : r.history) {
transactions[ALL_TRANSACTIONS].add(t);
transactions[t.stars > 0 ? INCOMING_TRANSACTIONS : OUTGOING_TRANSACTIONS].add(t);
transactions[t.stars.amount > 0 ? INCOMING_TRANSACTIONS : OUTGOING_TRANSACTIONS].add(t);
}
for (int i = 0; i < 3; ++i) {
transactionsExist[i] = !transactions[i].isEmpty() || transactionsExist[i];
@ -159,7 +160,7 @@ public class StarsController {
updatedSubscriptions = true;
}
if (this.balance != r.balance) {
if (this.balance.amount != r.balance.amount) {
updatedBalance = true;
}
this.balance = r.balance;
@ -182,7 +183,13 @@ public class StarsController {
}
}));
}
return Math.max(0, balance - (withMinus ? minus : 0));
if (withMinus && minus > 0) {
TL_stars.StarsAmount stars = new TL_stars.StarsAmount();
stars.amount = Math.max(0, balance.amount - minus);
stars.nanos = balance.nanos;
return stars;
}
return balance;
}
public void invalidateBalance() {
@ -191,8 +198,8 @@ public class StarsController {
balanceLoaded = true;
}
public void updateBalance(long balance) {
if (this.balance != balance) {
public void updateBalance(TL_stars.StarsAmount balance) {
if (!this.balance.equals(balance)) {
this.balance = balance;
this.minus = 0;
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.starBalanceUpdated);
@ -528,8 +535,8 @@ public class StarsController {
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
loading[type] = false;
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
@ -588,8 +595,8 @@ public class StarsController {
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
subscriptionsLoading = false;
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
@ -620,8 +627,8 @@ public class StarsController {
req.offset = "";
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
insufficientSubscriptionsLoading = false;
if (res instanceof TL_stars.TL_payments_starsStatus) {
TL_stars.TL_payments_starsStatus r = (TL_stars.TL_payments_starsStatus) res;
if (res instanceof TL_stars.StarsStatus) {
TL_stars.StarsStatus r = (TL_stars.StarsStatus) res;
MessagesController.getInstance(currentAccount).putUsers(r.users, false);
MessagesController.getInstance(currentAccount).putChats(r.chats, false);
insufficientSubscriptions.addAll(r.subscriptions);
@ -660,7 +667,7 @@ public class StarsController {
}
private void showStarsTopupInternal(Activity activity, long amount, String purpose) {
if (getBalance() >= amount || amount <= 0) {
if (getBalance().amount >= amount || amount <= 0) {
BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
if (lastFragment == null) return;
BulletinFactory.of(lastFragment).createSimpleBulletin(R.raw.stars_topup, getString(R.string.StarsTopupLinkEnough), getString(R.string.StarsTopupLinkTopupAnyway), () -> {
@ -1206,7 +1213,7 @@ public class StarsController {
final int subscription_period = form.invoice.subscription_period;
final boolean[] allDone = new boolean[] { false };
StarsIntroActivity.openConfirmPurchaseSheet(context, resourcesProvider, currentAccount, messageObject, dialogId, product, stars, form.photo, subscription_period, whenDone -> {
if (balance < stars) {
if (balance.amount < stars) {
if (!MessagesController.getInstance(currentAccount).starsPurchaseAvailable()) {
paymentFormOpened = false;
if (whenDone != null) {
@ -1282,7 +1289,7 @@ public class StarsController {
final boolean[] allDone = new boolean[] { false };
StarsIntroActivity.openStarsChannelInviteSheet(context, resourcesProvider, currentAccount, chatInvite, whenDone -> {
if (balance < stars) {
if (balance.amount < stars) {
if (!MessagesController.getInstance(currentAccount).starsPurchaseAvailable()) {
paymentFormOpened = false;
if (whenDone != null) {

View file

@ -6,7 +6,9 @@ import static org.telegram.messenger.LocaleController.formatPluralStringComma;
import static org.telegram.messenger.LocaleController.formatPluralStringSpaced;
import static org.telegram.messenger.LocaleController.formatString;
import static org.telegram.messenger.LocaleController.getString;
import static org.telegram.ui.ChatEditActivity.applyNewSpan;
import static org.telegram.ui.Stars.StarsIntroActivity.StarsTransactionView.getPlatformDrawable;
import static org.telegram.ui.bots.AffiliateProgramFragment.percents;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -34,6 +36,7 @@ import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.style.ClickableSpan;
import android.text.style.ImageSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ReplacementSpan;
import android.util.TypedValue;
import android.view.Gravity;
@ -84,6 +87,7 @@ import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_payments;
import org.telegram.tgnet.tl.TL_stars;
import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.ActionBar.ActionBar;
@ -135,10 +139,14 @@ import org.telegram.ui.GradientHeaderActivity;
import org.telegram.ui.ImageReceiverSpan;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PhotoViewer;
import org.telegram.ui.PremiumFeatureCell;
import org.telegram.ui.ProfileActivity;
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
import org.telegram.ui.Stories.recorder.HintView2;
import org.telegram.ui.bots.AffiliateProgramFragment;
import org.telegram.ui.bots.ChannelAffiliateProgramsFragment;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@ -350,10 +358,10 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(starBalanceIcon);
sb.append(LocaleController.formatNumber(s.getBalance(), ','));
sb.append(formatStarsAmount(s.getBalance(), 0.66f, ' '));
starBalanceTextView.setText(sb);
buyButton.setText(LocaleController.getString(s.getBalance() > 0 ? R.string.StarsBuyMore : R.string.StarsBuy), true);
buyButton.setText(LocaleController.getString(s.getBalance().amount > 0 ? R.string.StarsBuyMore : R.string.StarsBuy), true);
}
@Override
@ -579,6 +587,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
private final int BUTTON_EXPAND = -1;
private final int BUTTON_GIFT = -2;
private final int BUTTON_SUBSCRIPTIONS_EXPAND = -3;
private final int BUTTON_AFFILIATE = -4;
public void fillItems(ArrayList<UItem> items, UniversalAdapter adapter) {
if (getContext() == null) {
@ -594,40 +603,12 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
giftButton.setVisibility(getMessagesController().starsGiftsEnabled ? View.VISIBLE : View.GONE);
}
// items.add(UItem.asAnimatedHeader(-99, getString(R.string.TelegramStarsChoose)));
//
// int stars = 1;
// ArrayList<TL_stars.TL_starsTopupOption> options = c.getOptions();
// if (options != null && !options.isEmpty()) {
// int hidden = 0;
// for (int id = 0; id < options.size(); ++id) {
// TL_stars.TL_starsTopupOption option = options.get(id);
// if (option.extended && !expanded) {
// hidden++;
// continue;
// }
// items.add(StarTierView.Factory.asStarTier(id, stars++, option));
// }
// if (!expanded && hidden > 0) {
// items.add(ExpandView.Factory.asExpand(BUTTON_EXPAND, getString(expanded ? R.string.NotifyLessOptions : R.string.NotifyMoreOptions), !expanded).accent());
// }
// } else {
// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER));
// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER));
// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER));
// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER));
// items.add(UItem.asFlicker(FlickerLoadingView.STAR_TIER));
// }
//
// items.add(UItem.asShadow(AndroidUtilities.replaceSingleTag(getString(R.string.StarsTOS), () -> {
// Browser.openUrl(getContext(), getString(R.string.StarsTOSLink));
// })));
items.add(UItem.asShadow(null));
//
// if (getMessagesController().starsGiftsEnabled) {
// items.add(UItem.asButton(BUTTON_GIFT, R.drawable.menu_stars_gift, getString(R.string.TelegramStarsGift)).accent());
// items.add(UItem.asShadow(null));
// }
if (getMessagesController().starrefConnectAllowed) {
items.add(AffiliateProgramFragment.ColorfulTextCell.Factory.as(BUTTON_AFFILIATE, getThemedColor(Theme.key_color_green), R.drawable.filled_earn_stars, applyNewSpan(getString(R.string.UserAffiliateProgramRowTitle)), getString(R.string.UserAffiliateProgramRowText)));
items.add(UItem.asShadow(null));
}
if (c.hasSubscriptions()) {
items.add(UItem.asHeader(getString(R.string.StarMySubscriptions)));
@ -659,6 +640,8 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
} else if (item.id == BUTTON_SUBSCRIPTIONS_EXPAND) {
StarsController.getInstance(currentAccount).loadSubscriptions();
adapter.update(true);
} else if (item.id == BUTTON_AFFILIATE) {
presentFragment(new ChannelAffiliateProgramsFragment(getUserConfig().getClientUserId()));
} else if (item.instanceOf(StarTierView.Factory.class)) {
if (item.object instanceof TL_stars.TL_starsTopupOption) {
StarsController.getInstance(currentAccount).buy(getParentActivity(), (TL_stars.TL_starsTopupOption) item.object, (success, error) -> {
@ -751,7 +734,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
StarsController c = StarsController.getInstance(currentAccount);
amountTextView.cancelAnimation();
long balance = StarsController.getInstance(currentAccount).getBalance();
long balance = StarsController.getInstance(currentAccount).getBalance().amount;
if (balance > lastBalance && lastBalance != -1) {
bounce();
}
@ -1414,6 +1397,8 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
public void set(TL_stars.StarsTransaction transaction, boolean bot, boolean divider) {
long did = DialogObject.getPeerDialogId(transaction.peer.peer);
final boolean affiliate_to_bot = (transaction.flags & 131072) != 0;
final boolean affiliate_to_channel = !affiliate_to_bot && (transaction.flags & 65536) != 0;
threeLines = did != 0 || transaction.subscription || transaction.floodskip || transaction.stargift != null || transaction.gift && transaction.peer instanceof TL_stars.TL_starsTransactionPeerFragment;
titleTextViewParams.bottomMargin = threeLines ? 0 : dp(4.33f);
subtitleTextView.setVisibility(threeLines ? View.VISIBLE : View.GONE);
@ -1465,9 +1450,9 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
setGiftImage(span.imageReceiver, transaction.stargift, 16);
titleTextView.setText(username);
if (transaction.refund) {
subtitleTextView.setText(TextUtils.concat(spanString, " ", LocaleController.getString(transaction.stars > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted)));
subtitleTextView.setText(TextUtils.concat(spanString, " ", LocaleController.getString(transaction.stars.amount > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted)));
} else {
subtitleTextView.setText(TextUtils.concat(spanString, " ", LocaleController.getString(transaction.stars > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent)));
subtitleTextView.setText(TextUtils.concat(spanString, " ", LocaleController.getString(transaction.stars.amount > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent)));
}
} else if (transaction.subscription) {
titleTextView.setText(username);
@ -1479,6 +1464,10 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
subtitleTextView.setVisibility(VISIBLE);
subtitleTextView.setText(String.format(Locale.US, "%s subscription fee", period));
}
} else if (affiliate_to_channel) {
titleTextView.setText(username);
subtitleTextView.setVisibility(deleted ? GONE : VISIBLE);
subtitleTextView.setText(LocaleController.formatString(R.string.StarTransactionCommission, percents(transaction.starref_commission_permille)));
} else if (transaction.gift) {
titleTextView.setText(username);
subtitleTextView.setVisibility(deleted ? GONE : VISIBLE);
@ -1570,14 +1559,14 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
imageView.setImageDrawable(null);
}
if (transaction.stars > 0) {
if (transaction.stars.amount > 0) {
amountTextView.setVisibility(View.VISIBLE);
amountTextView.setTextColor(Theme.getColor(Theme.key_color_green));
amountTextView.setText(TextUtils.concat("+", LocaleController.formatNumber(transaction.stars, ' '), " ", star));
} else if (transaction.stars < 0) {
amountTextView.setText(TextUtils.concat("+", formatStarsAmount(transaction.stars), " ", star));
} else if (transaction.stars.amount < 0) {
amountTextView.setVisibility(View.VISIBLE);
amountTextView.setTextColor(Theme.getColor(Theme.key_color_red));
amountTextView.setText(TextUtils.concat("-", LocaleController.formatNumber(-transaction.stars, ' '), " ", star));
amountTextView.setText(TextUtils.concat(formatStarsAmount(transaction.stars), " ", star));
} else {
amountTextView.setVisibility(View.GONE);
}
@ -2262,7 +2251,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
@Override
public void show() {
long balance = StarsController.getInstance(currentAccount).getBalance();
long balance = StarsController.getInstance(currentAccount).getBalance().amount;
BaseFragment lastFragment = LaunchActivity.getLastFragment();
if (lastFragment instanceof ChatActivity) {
ChatActivity chatActivity = (ChatActivity) lastFragment;
@ -2419,7 +2408,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
if (adapter != null) {
adapter.update(true);
}
long balance = StarsController.getInstance(currentAccount).getBalance();
long balance = StarsController.getInstance(currentAccount).getBalance().amount;
headerView.titleView.setText(formatPluralStringComma("StarsNeededTitle", (int) (starsNeeded - balance)));
if (actionBar != null) {
actionBar.setTitle(getTitle());
@ -2436,7 +2425,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
@Override
public void show() {
long balance = StarsController.getInstance(currentAccount).getBalance();
long balance = StarsController.getInstance(currentAccount).getBalance().amount;
if (balance >= starsNeeded) {
if (whenPurchased != null) {
whenPurchased.run();
@ -2506,7 +2495,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
this.starsNeeded = starsNeeded;
headerView = new HeaderView(context, currentAccount, resourcesProvider);
long balance = StarsController.getInstance(currentAccount).getBalance();
long balance = StarsController.getInstance(currentAccount).getBalance().amount;
headerView.titleView.setText(formatPluralString("StarsNeededTitle", (int) Math.max(0, starsNeeded - balance)));
String stringRes;
if (type == TYPE_SUBSCRIPTION_BUY) {
@ -3074,11 +3063,16 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
if (!t.extended_media.isEmpty()) {
return getString(R.string.StarMediaPurchase);
}
final boolean affiliate_to_bot = (t.flags & 131072) != 0;
final boolean affiliate_to_channel = !affiliate_to_bot && (t.flags & 65536) != 0;
if (affiliate_to_channel) {
return LocaleController.formatString(R.string.StarTransactionCommission, percents(t.starref_commission_permille));
}
if (t.stargift != null) {
if (t.refund) {
return LocaleController.getString(t.stars > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted);
return LocaleController.getString(t.stars.amount > 0 ? R.string.Gift2TransactionRefundedSent : R.string.Gift2TransactionRefundedConverted);
} else {
return LocaleController.getString(t.stars > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent);
return LocaleController.getString(t.stars.amount > 0 ? R.string.Gift2TransactionConverted : R.string.Gift2TransactionSent);
}
}
if (t.subscription) {
@ -3130,7 +3124,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
t.peer = new TL_stars.TL_starsTransactionPeer();
t.peer.peer = action.boost_peer;
t.date = date;
t.stars = action.stars;
t.stars = new TL_stars.StarsAmount(action.stars);
t.id = action.transaction_id;
t.gift = true;
t.flags |= 8192;
@ -3148,7 +3142,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
t.peer = new TL_stars.TL_starsTransactionPeer();
t.peer.peer = sent_by;
t.date = date;
t.stars = action.stars;
t.stars = new TL_stars.StarsAmount(action.stars);
t.id = action.transaction_id;
t.gift = true;
t.sent_by = sent_by;
@ -3164,7 +3158,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
t.peer = new TL_stars.TL_starsTransactionPeer();
t.peer.peer = action.peer;
t.date = date;
t.stars = action.total_amount;
t.stars = new TL_stars.StarsAmount(action.total_amount);
t.id = action.charge.id;
t.refund = true;
return showTransactionSheet(context, false, 0, currentAccount, t, resourcesProvider);
@ -3178,7 +3172,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
t.peer = new TL_stars.TL_starsTransactionPeer();
t.peer.peer = MessagesController.getInstance(currentAccount).getPeer(receipt.bot_id);
t.date = receipt.date;
t.stars = -receipt.total_amount;
t.stars = new TL_stars.StarsAmount(-receipt.total_amount);
t.id = receipt.transaction_id;
return showTransactionSheet(context, bot, 0, currentAccount, t, resourcesProvider);
}
@ -3283,6 +3277,8 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
return null;
final boolean giveaway = (transaction.flags & 8192) != 0;
final boolean affiliate_to_bot = (transaction.flags & 131072) != 0;
final boolean affiliate_to_channel = !affiliate_to_bot && (transaction.flags & 65536) != 0;
BottomSheet.Builder b = new BottomSheet.Builder(context, false, resourcesProvider);
BottomSheet[] sheet = new BottomSheet[1];
@ -3298,7 +3294,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
setGiftImage(imageView.getImageReceiver(), transaction.stargift, 160);
linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10));
} else if (giveaway || transaction.gift) {
setGiftImage(imageView, imageView.getImageReceiver(), transaction.stars);
setGiftImage(imageView, imageView.getImageReceiver(), transaction.stars.amount);
linearLayout.addView(imageView, LayoutHelper.createLinear(160, 160, Gravity.CENTER, 0, -8, 0, 10));
} else if (!transaction.extended_media.isEmpty()) {
imageView.setRoundRadius(dp(30));
@ -3374,7 +3370,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
imageView.setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(transaction.photo)), "100_100", null, 0, null);
} else {
imageView.setRoundRadius(dp(50));
final long did = transaction.subscription && bot ? dialogId : DialogObject.getPeerDialogId(transaction.peer.peer);
final long did = affiliate_to_channel ? DialogObject.getPeerDialogId(transaction.starref_peer) : transaction.subscription && bot ? dialogId : DialogObject.getPeerDialogId(transaction.peer.peer);
AvatarDrawable avatarDrawable = new AvatarDrawable();
if (did >= 0) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did);
@ -3420,8 +3416,8 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
textView.setTypeface(AndroidUtilities.bold());
textView.setGravity(Gravity.CENTER);
textView.setTextColor(Theme.getColor(transaction.stars >= 0 ? Theme.key_color_green : Theme.key_color_red, resourcesProvider));
textView.setText(replaceStarsWithPlain((transaction.stars >= 0 ? "+" : "-") + LocaleController.formatNumber((int) Math.abs(transaction.stars), ' ') + " ⭐️", .8f));
textView.setTextColor(Theme.getColor(transaction.stars.amount >= 0 ? Theme.key_color_green : Theme.key_color_red, resourcesProvider));
textView.setText(replaceStarsWithPlain(TextUtils.concat((transaction.stars.amount >= 0 ? "+" : ""), formatStarsAmount(transaction.stars), " ⭐️"), .8f));
SpannableStringBuilder s = new SpannableStringBuilder(textView.getText());
if (transaction.refund) {
appendStatus(s, textView, getString(R.string.StarsRefunded));
@ -3442,7 +3438,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
if (self) {
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
textView.setText(replaceStarsWithPlain(LocaleController.formatNumber((int) Math.abs(transaction.stars), ' ') + " ⭐️", .8f));
textView.setText(replaceStarsWithPlain(TextUtils.concat(formatStarsAmount(transaction.stars), " ⭐️"), .8f));
}
textView = new LinkSpanDrawable.LinksTextView(context);
@ -3477,7 +3473,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
if (!transaction.refund) {
final long did = DialogObject.getPeerDialogId(transaction.peer.peer);
final TLRPC.User didUser = MessagesController.getInstance(currentAccount).getUser(did);
if (transaction.stars > 0) { // converted
if (transaction.stars.amount > 0) { // converted
tableView.addRowUser(getString(R.string.StarGiveawayPrizeFrom), currentAccount, did, () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
@ -3531,7 +3527,49 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
}
} else if (transaction.peer instanceof TL_stars.TL_starsTransactionPeer) {
final long did = DialogObject.getPeerDialogId(transaction.peer.peer);
if (giveaway) {
if (affiliate_to_bot) {
final long botId = dialogId;
final long channelId = DialogObject.getPeerDialogId(transaction.starref_peer);
final long referredUserId = did;
tableView.addRowLink(getString(R.string.StarAffiliateReason), getString(R.string.StarAffiliateReasonProgram), () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
if (lastFragment != null) {
lastFragment.presentFragment(new AffiliateProgramFragment(botId));
}
});
tableView.addRowUser(getString(R.string.StarAffiliate), currentAccount, channelId, () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
if (lastFragment != null) {
lastFragment.presentFragment(ProfileActivity.of(channelId));
}
});
tableView.addRowUser(getString(R.string.StarAffiliateReferredUser), currentAccount, referredUserId, () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
if (lastFragment != null) {
lastFragment.presentFragment(ProfileActivity.of(referredUserId));
}
});
tableView.addRow(getString(R.string.StarAffiliateCommission), percents(transaction.starref_commission_permille));
} else if (affiliate_to_channel) {
final long botId = did;
final long channelId = dialogId;
tableView.addRowLink(getString(R.string.StarAffiliateReason), getString(R.string.StarAffiliateReasonProgram), () -> {
BotStarsController.getInstance(currentAccount).getConnectedBot(context, dialogId, botId, connectedBot -> {
sheet[0].dismiss();
ChannelAffiliateProgramsFragment.showShareAffiliateAlert(context, currentAccount, connectedBot, dialogId, resourcesProvider);
});
});
tableView.addRowUser(getString(R.string.StarAffiliateMiniApp), currentAccount, botId, () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
if (lastFragment != null) {
lastFragment.presentFragment(ProfileActivity.of(botId));
}
});
} else if (giveaway) {
tableView.addRowUser(getString(R.string.StarGiveawayPrizeFrom), currentAccount, did, () -> {
sheet[0].dismiss();
final BaseFragment lastFragment = LaunchActivity.getSafeLastFragment();
@ -3564,7 +3602,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
}
}
});
tableView.addRow(getString(R.string.StarGiveawayGift), formatPluralStringComma("Stars", (int) transaction.stars));
tableView.addRow(getString(R.string.StarGiveawayGift), formatStarsAmountString(transaction.stars));
} else if (transaction.subscription && !bot) {
tableView.addRowUser(getString(R.string.StarSubscriptionTo), currentAccount, did, () -> {
sheet[0].dismiss();
@ -3916,12 +3954,12 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
if (did >= 0) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did);
deleted = user == null || UserObject.isDeleted(user);
username = UserObject.getPublicUsername(user);
username = UserObject.getUserName(user);
avatarSpan.setUser(user);
} else {
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-did);
deleted = chat == null;
username = ChatObject.getPublicUsername(chat);
username = chat != null ? chat.title : "";
avatarSpan.setChat(chat);
}
SpannableStringBuilder ssb = new SpannableStringBuilder("x " + username);
@ -4006,7 +4044,7 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
lastFragment.presentFragment(ChatActivity.of(did));
}));
};
if (c.balance < subscription.pricing.amount) {
if (c.balance.amount < subscription.pricing.amount) {
new StarsNeededSheet(context, resourcesProvider, subscription.pricing.amount, business ? StarsNeededSheet.TYPE_BIZ_SUBSCRIPTION_KEEP : did < 0 ? StarsNeededSheet.TYPE_SUBSCRIPTION_KEEP : StarsNeededSheet.TYPE_BOT_SUBSCRIPTION_KEEP, peerName, refulfill).show();
} else {
refulfill.run();
@ -5160,4 +5198,84 @@ public class StarsIntroActivity extends GradientHeaderActivity implements Notifi
rowTextView.setText(gift.availability_remains <= 0 ? formatPluralStringComma("Gift2Availability2ValueNone", gift.availability_total) : formatPluralStringComma("Gift2Availability4Value", gift.availability_remains, LocaleController.formatNumber(gift.availability_total, ',')));
}
}
private static DecimalFormat floatFormat;
public static CharSequence formatStarsAmount(TL_stars.StarsAmount starsAmount) {
return formatStarsAmount(starsAmount, 0.777f, ',');
}
public static CharSequence formatStarsAmount(TL_stars.StarsAmount starsAmount, float relativeSize, char symbol) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
final long amount = starsAmount.amount + (starsAmount.nanos < 0 && starsAmount.amount > 0 ? -1 : (starsAmount.nanos > 0 && starsAmount.amount < 0 ? +1 : 0));
final boolean negative = amount < 0;
if (starsAmount.nanos != 0) {
ssb.append((negative ? "-" : "") + LocaleController.formatNumber(Math.abs(amount), symbol));
if (floatFormat == null) floatFormat = new DecimalFormat("0.################");
String str = floatFormat.format((starsAmount.nanos < 0 ? 1e9 + starsAmount.nanos : starsAmount.nanos) / 1e9d);
int index;
if ((index = str.indexOf(".")) >= 0) {
int fromIndex = ssb.length();
ssb.append(str.substring(index));
ssb.setSpan(new RelativeSizeSpan(relativeSize), fromIndex + 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
ssb.append((negative ? "-" : "") + LocaleController.formatNumber(Math.abs(amount), ' '));
}
return ssb;
}
public static CharSequence formatStarsAmountShort(TL_stars.StarsAmount starsAmount) {
return formatStarsAmountShort(starsAmount, 0.777f, ' ');
}
public static CharSequence formatStarsAmountShort(TL_stars.StarsAmount starsAmount, float relativeSize, char symbol) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
final long amount = starsAmount.amount + (starsAmount.nanos < 0 && starsAmount.amount > 0 ? -1 : (starsAmount.nanos > 0 && starsAmount.amount < 0 ? +1 : 0));
final boolean negative = amount < 0;
if (Math.abs(amount) <= 1000 && starsAmount.nanos != 0) {
ssb.append((negative ? "-" : "") + LocaleController.formatNumber(Math.abs(amount), symbol));
if (floatFormat == null) floatFormat = new DecimalFormat("0.################");
String str = floatFormat.format((starsAmount.nanos < 0 ? 1e9 + starsAmount.nanos : starsAmount.nanos) / 1e9d);
int index;
if ((index = str.indexOf(".")) >= 0) {
int fromIndex = ssb.length();
String part = str.substring(index);
if (part.length() > 1) {
ssb.append(part.substring(0, Math.min(part.length(), 3)));
ssb.setSpan(new RelativeSizeSpan(relativeSize), fromIndex + 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
} else if (starsAmount.amount <= 1000) {
ssb.append((negative ? "-" : "") + LocaleController.formatNumber(Math.abs(amount), symbol));
} else {
ssb.append((negative ? "-" : "") + AndroidUtilities.formatWholeNumber((int) Math.abs(amount), 0));
}
return ssb;
}
public static CharSequence formatStarsAmountString(TL_stars.StarsAmount starsAmount) {
return formatStarsAmountString(starsAmount, 0.777f, ',');
}
public static CharSequence formatStarsAmountString(TL_stars.StarsAmount starsAmount, float relativeSize, char symbol) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
final long amount = starsAmount.amount + (starsAmount.nanos < 0 && starsAmount.amount > 0 ? -1 : (starsAmount.nanos > 0 && starsAmount.amount < 0 ? +1 : 0));
final boolean negative = amount < 0;
if (starsAmount.nanos != 0) {
ssb.append((negative ? "-" : "") + LocaleController.formatNumber(Math.abs(amount), symbol));
if (floatFormat == null) floatFormat = new DecimalFormat("0.################");
String str = floatFormat.format((starsAmount.nanos < 0 ? 1e9 + starsAmount.nanos : starsAmount.nanos) / 1e9d);
int index;
if ((index = str.indexOf(".")) >= 0) {
int fromIndex = ssb.length();
ssb.append(str.substring(index));
ssb.setSpan(new RelativeSizeSpan(relativeSize), fromIndex + 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
ssb.append(" ").append(getString(R.string.StarsNano));
} else {
ssb.append(formatPluralStringComma("Stars", (int) starsAmount.amount));
}
return ssb;
}
}

View file

@ -345,7 +345,7 @@ public class StarsReactionsSheet extends BottomSheet {
});
};
if (starsController.balanceAvailable() && starsController.getBalance() < totalStars) {
if (starsController.balanceAvailable() && starsController.getBalance().amount < totalStars) {
new StarsIntroActivity.StarsNeededSheet(context, resourcesProvider, totalStars, StarsIntroActivity.StarsNeededSheet.TYPE_REACTIONS, chat == null ? "" : chat.title, send).show();
} else {
send.run();

View file

@ -491,6 +491,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
}
}
} else if (id == NotificationCenter.boostByChannelCreated) {
if (getParentLayout() == null) return;
TLRPC.Chat chat = (TLRPC.Chat) args[0];
boolean isGiveaway = (boolean) args[1];
List<BaseFragment> fragmentStack = getParentLayout().getFragmentStack();

Some files were not shown because too many files have changed in this diff Show more