diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 8cf939ec2a..c37af2f6e8 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -10,12 +10,12 @@ repositories { } } -def verName = "10.10.1" -def verCode = 1169 +def verName = "10.12.0" +def verCode = 1171 -def officialVer = "10.10.1" -def officialCode = 4583 +def officialVer = "10.12.0" +def officialCode = 4710 def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json") @@ -306,6 +306,7 @@ dependencies { implementation 'com.google.guava:guava:31.1-android' implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1' + implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8' compileOnly 'org.yaml:snakeyaml:1.29' implementation 'org.yaml:snakeyaml:1.29' diff --git a/TMessagesProj/jni/lottie.cpp b/TMessagesProj/jni/lottie.cpp index 039beb5e2c..46a1fcf059 100644 --- a/TMessagesProj/jni/lottie.cpp +++ b/TMessagesProj/jni/lottie.cpp @@ -182,9 +182,34 @@ JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_getFramesCount(J delete info; return 0; } - long frameCount = info->animation->totalFrame(); + long framesCount = info->animation->totalFrame(); delete info; - return (jlong) frameCount; + return (jlong) framesCount; +} + +JNIEXPORT jdouble Java_org_telegram_ui_Components_RLottieDrawable_getDuration(JNIEnv *env, jclass clazz, jstring src, jstring json) { + auto info = new LottieInfo(); + char const *srcString = env->GetStringUTFChars(src, nullptr); + info->path = srcString; + if (json != nullptr) { + char const *jsonString = env->GetStringUTFChars(json, nullptr); + if (jsonString) { + info->animation = rlottie::Animation::loadFromData(jsonString, info->path, nullptr, FitzModifier::None); + env->ReleaseStringUTFChars(json, jsonString); + } + } else { + info->animation = rlottie::Animation::loadFromFile(info->path, nullptr, FitzModifier::None); + } + if (srcString) { + env->ReleaseStringUTFChars(src, srcString); + } + if (info->animation == nullptr) { + delete info; + return 0; + } + double duration = info->animation->duration(); + delete info; + return (jdouble) duration; } JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_createWithJson(JNIEnv *env, jclass clazz, jstring json, jstring name, jintArray data, jintArray colorReplacement) { diff --git a/TMessagesProj/jni/webm_encoder.c b/TMessagesProj/jni/webm_encoder.c index 99a0c27554..67f32f5faa 100644 --- a/TMessagesProj/jni/webm_encoder.c +++ b/TMessagesProj/jni/webm_encoder.c @@ -70,8 +70,9 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_video_WebmEncoder_createEnco ctx->codec_ctx->time_base = (AVRational){ 1, fps }; ctx->codec_ctx->framerate = (AVRational){ fps, 1 }; ctx->codec_ctx->bit_rate = bitrate; - ctx->codec_ctx->gop_size = 10; - ctx->codec_ctx->max_b_frames = 1; + ctx->codec_ctx->rc_min_rate = bitrate / 8; + ctx->codec_ctx->rc_max_rate = bitrate; +// ctx->codec_ctx->rc_buffer_size = 2 * bitrate; if (ctx->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { ctx->codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -185,6 +186,9 @@ JNIEXPORT jboolean JNICALL Java_org_telegram_messenger_video_WebmEncoder_writeFr pkt.stream_index = ctx->video_stream->index; ret = av_interleaved_write_frame(ctx->fmt_ctx, &pkt); + if (ret < 0) { + LOGE("vp9: failed to av_interleaved_write_frame %d", ret); + } av_packet_unref(&pkt); } @@ -200,13 +204,16 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_video_WebmEncoder_stop( return; } - avcodec_send_frame(ctx->codec_ctx, NULL); + int ret; + ret = avcodec_send_frame(ctx->codec_ctx, NULL); + if (ret < 0) { + LOGE("vp9: failed to avcodec_send_frame %d", ret); + } AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; - int ret; while (1) { ret = avcodec_receive_packet(ctx->codec_ctx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { @@ -220,10 +227,16 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_video_WebmEncoder_stop( pkt.stream_index = ctx->video_stream->index; ret = av_interleaved_write_frame(ctx->fmt_ctx, &pkt); + if (ret < 0) { + LOGE("vp9: failed to av_interleaved_write_frame %d", ret); + } av_packet_unref(&pkt); } - av_write_trailer(ctx->fmt_ctx); + ret = av_write_trailer(ctx->fmt_ctx); + if (ret < 0) { + LOGE("vp9: failed to av_write_trailer %d", ret); + } if (ctx->frame) { av_frame_free(&ctx->frame); diff --git a/TMessagesProj/src/main/assets/models/coin_border.png b/TMessagesProj/src/main/assets/models/coin_border.png index d5ea95fb1e..d68e1299f3 100644 Binary files a/TMessagesProj/src/main/assets/models/coin_border.png and b/TMessagesProj/src/main/assets/models/coin_border.png differ diff --git a/TMessagesProj/src/main/assets/models/coin_stars.binobj b/TMessagesProj/src/main/assets/models/coin_stars.binobj new file mode 100644 index 0000000000..61a5627210 Binary files /dev/null and b/TMessagesProj/src/main/assets/models/coin_stars.binobj differ diff --git a/TMessagesProj/src/main/assets/shaders/fragment3.glsl b/TMessagesProj/src/main/assets/shaders/fragment3.glsl index 3717c78fb1..b17813e66d 100644 --- a/TMessagesProj/src/main/assets/shaders/fragment3.glsl +++ b/TMessagesProj/src/main/assets/shaders/fragment3.glsl @@ -27,102 +27,82 @@ uniform float time; uniform mat4 world; void main() { - vec3 vLightPosition2 = vec3(-400, 40, 400); - vec3 vLightPosition3 = vec3(0, 200, 400); - vec3 vLightPosition4 = vec3(0, 0, 100); - vec3 vLightPositionNormal = vec3(100, -200, 400); - - vec3 vNormalW = normalize(vec3(world * vec4(vNormal, 0.0))); - vec3 vTextureNormal = normalize(texture2D(u_NormalMap, vUV + vec2(-f_xOffset, f_xOffset)).xyz * 2.0 - 1.0); - vec3 finalNormal = normalize(vNormalW + vTextureNormal); - - vec3 color = texture2D(u_Texture, vUV).xyz; - vec3 viewDirectionW = normalize(cameraPosition - modelViewVertex); - - float border = 0.0; - if (modelIndex == 0) { - border = 1.0; - } else if (modelIndex == 2) { - border = texture2D(u_Texture, vUV).a; - } - - float modelDiffuse = 0.1; - if (!night && modelIndex != 1) { - modelDiffuse = 0.01; - } - float diffuse = max(dot(vNormalW, viewDirectionW), (1.0 - modelDiffuse)); - vec2 uv = vUV; if (modelIndex == 2) { uv *= 2.0; uv = fract(uv); - if (vUV.x > .5) { - uv.x = 1.0 - uv.x; - } } - float mixValue = clamp(distance(uv.xy, vec2(0.0)), 0.0, 1.0); - vec4 gradientColorFinal = vec4(mix(gradientColor1, gradientColor2, mixValue), 1.0); - - float modelNormalSpec = normalSpec, modelSpec1 = 0.0, modelSpec2 = 0.05; + uv.x = 1.0 - uv.x; - float darken = 1. - length(modelViewVertex - vec3(30., -75., 50.)) / 200.; - - if (border > 0.) { - modelNormalSpec += border; - modelSpec1 += border; - modelSpec2 += border; + float diagonal = ((uv.x + uv.y) / 2.0 - .15) / .6; + vec3 baseColor; + if (modelIndex == 0) { + baseColor = mix( + vec3(0.95686, 0.47451, 0.93725), + vec3(0.46274, 0.49411, 0.9960), + diagonal + ); + } else if (modelIndex == 3) { + baseColor = mix( + vec3(0.95686, 0.47451, 0.93725), + vec3(0.46274, 0.49411, 0.9960), + diagonal + ); + baseColor = mix(baseColor, vec3(1.0), .3); + } else if (modelIndex == 1) { + baseColor = mix( + vec3(0.67059, 0.25490, 0.80000), + vec3(0.39608, 0.18824, 0.98039), + diagonal + ); + } else { + baseColor = mix( + vec3(0.91373, 0.62353, 0.99608), + vec3(0.67451, 0.58824, 1.00000), + clamp((uv.y - .2) / .6, 0.0, 1.0) + ); + + baseColor = mix(baseColor, vec3(1.0), .1 + .45 * texture2D(u_Texture, vUV).a); + if (night) { + baseColor = mix(baseColor, vec3(.0), .06); + } } + vec3 pos = modelViewVertex / 100.0 + .5; + vec3 norm = normalize(vec3(world * vec4(vNormal, 0.0))); - vec3 angleW = normalize(viewDirectionW + vLightPosition2); - float specComp2 = max(0., dot(finalNormal, angleW)); - specComp2 = pow(specComp2, max(1., 128.)) * modelSpec1; + vec3 flecksLightPos = vec3(.5, .5, .5); + vec3 flecksLightDir = normalize(flecksLightPos - pos); + vec3 flecksReflectDir = reflect(-flecksLightDir, norm); + float flecksSpec = pow(max(dot(normalize(vec3(0.0) - pos), flecksReflectDir), 0.0), 8.0); + vec3 flecksNormal = normalize(texture2D(u_NormalMap, uv * 1.3 + vec2(.02, .06) * time).xyz * 2.0 - 1.0); + float flecks = max(flecksNormal.x, flecksNormal.y) * flecksSpec; + norm += flecksSpec * flecksNormal; + norm = normalize(norm); - angleW = normalize(viewDirectionW + vLightPosition4); - float specComp3 = max(0., dot(finalNormal, angleW)); - specComp3 = pow(specComp3, max(1., 30.)) * modelSpec2; + vec3 lightPos = vec3(-3., -3., 20.); + vec3 lightDir = normalize(lightPos - pos); + float diffuse = max(dot(norm, lightDir), 0.0); - angleW = normalize(viewDirectionW + vLightPositionNormal); - float normalSpecComp = max(0., dot(finalNormal, angleW)); - normalSpecComp = pow(normalSpecComp, max(1., 128.)) * modelNormalSpec; + float spec = 0.0; - angleW = normalize(viewDirectionW + vLightPosition2); - float normalSpecComp2 = max(0., dot(finalNormal, angleW)); - normalSpecComp2 = pow(normalSpecComp2, max(1., 128.)) * modelNormalSpec; + lightPos = vec3(-3., -3., .5); + spec += 2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0); - vec4 normalSpecFinal = vec4(normalSpecColor, 0.0) * normalSpecComp2; - vec4 specFinal = vec4(color, 0.0) * (specComp2 + specComp3); + lightPos = vec3(-3., .5, 30.); + spec += (modelIndex == 1 ? 1.5 : 0.5) * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 32.0); -// float snap = fract((-gl_FragCoord.x / resolution.x + gl_FragCoord.y / resolution.y) / 20.0 + .2 * time) > .9 ? 1. : 0.; +// lightPos = vec3(3., .5, .5); +// spec += pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 32.0); - vec4 fragColor = gradientColorFinal + specFinal; - vec4 backgroundColor = texture2D(u_BackgroundTexture, vec2(gradientPosition.x + (gl_FragCoord.x / resolution.x) * gradientPosition.y, gradientPosition.z + (1.0 - (gl_FragCoord.y / resolution.y)) * gradientPosition.w)); - vec4 color4 = mix(backgroundColor, fragColor, diffuse); - if (night) { - angleW = normalize(viewDirectionW + vLightPosition2); - float normalSpecComp = max(0., dot(finalNormal, angleW)); - normalSpecComp = pow(normalSpecComp, max(1., 128.)); - if (normalSpecComp > .2 && modelIndex != 0) { - color4.rgb += vec3(.5) * max(0., vTextureNormal.x) * normalSpecComp; - } - if (modelIndex == 1) { - color4.rgb *= .9; - } else { - color4.rgb += vec3(1.0) * .17; - } - } else { - if (modelIndex == 1) { - if (darken > .5) { - color4.rgb *= vec3(0.78039, 0.77254, 0.95294); - } else { - color4.rgb *= vec3(0.83921, 0.83529, 0.96862); - } - } else { - if (darken > .5) { - color4.rgb *= vec3(.945098, .94117, 1.0); - color4.rgb += vec3(.06) * border; - } - } + if (modelIndex != 0) { + spec *= .25; } - gl_FragColor = color4 * f_alpha; + + vec3 color = baseColor; + color *= .94 + .22 * diffuse; + color = mix(color, vec3(1.0), spec); +// color = mix(color, vec3(1.0), 0.35 * flecks); + + gl_FragColor = vec4(color, 1.0); } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 7ad20b296f..844ad8be9c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -207,7 +207,13 @@ import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; import java.util.Map; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; @@ -284,9 +290,11 @@ public class AndroidUtilities { public static final RectF rectTmp = new RectF(); public static final Rect rectTmp2 = new Rect(); + public static final int[] pointTmp2 = new int[2]; public static Pattern WEB_URL = null; public static Pattern BAD_CHARS_PATTERN = null; + public static Pattern LONG_BAD_CHARS_PATTERN = null; public static Pattern BAD_CHARS_MESSAGE_PATTERN = null; public static Pattern BAD_CHARS_MESSAGE_LONG_PATTERN = null; private static Pattern singleTagPatter = null; @@ -295,6 +303,7 @@ public class AndroidUtilities { try { final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; BAD_CHARS_PATTERN = Pattern.compile("[\u2500-\u25ff]"); + LONG_BAD_CHARS_PATTERN = Pattern.compile("[\u4e00-\u9fff]"); BAD_CHARS_MESSAGE_LONG_PATTERN = Pattern.compile("[\u0300-\u036f\u2066-\u2067]+"); BAD_CHARS_MESSAGE_PATTERN = Pattern.compile("[\u2066-\u2067]+"); final Pattern IP_ADDRESS = Pattern.compile( @@ -584,9 +593,13 @@ public void onClick(@NonNull View view) { } public static CharSequence replaceArrows(CharSequence text, boolean link) { + return replaceArrows(text, link, dp(8f / 3f), 0); + } + + public static CharSequence replaceArrows(CharSequence text, boolean link, float translateX, float translateY) { ColoredImageSpan span = new ColoredImageSpan(R.drawable.msg_mini_forumarrow, DynamicDrawableSpan.ALIGN_BOTTOM); span.setScale(.88f, .88f); - span.translate(-dp(8f / 3f), 0); + span.translate(-translateX, translateY); span.spaceScaleX = .8f; if (link) { span.useLinkPaintColor = link; @@ -600,6 +613,23 @@ public static CharSequence replaceArrows(CharSequence text, boolean link) { rightArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); text = AndroidUtilities.replaceMultipleCharSequence(">", text, rightArrow); + span = new ColoredImageSpan(R.drawable.msg_mini_forumarrow, DynamicDrawableSpan.ALIGN_BOTTOM); + span.setScale(.88f, .88f); + span.translate(translateX, translateY); + span.rotate(180f); + span.spaceScaleX = .8f; + if (link) { + span.useLinkPaintColor = link; + } + +// SpannableString leftArrow = new SpannableString("< "); +// leftArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); +// text = AndroidUtilities.replaceMultipleCharSequence("< ", text, leftArrow); + + SpannableString leftArrow = new SpannableString("<"); + leftArrow.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + text = AndroidUtilities.replaceMultipleCharSequence("<", text, leftArrow); + return text; } @@ -1009,10 +1039,51 @@ public static boolean addLinks(Spannable text, int mask) { return addLinks(text, mask, false); } + @Deprecated // use addLinksSafe public static boolean addLinks(Spannable text, int mask, boolean internalOnly) { return addLinks(text, mask, internalOnly, true); } + public static boolean addLinksSafe(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) { + SpannableStringBuilder newText = new SpannableStringBuilder(text); + ExecutorService executor = Executors.newSingleThreadExecutor(); + Callable task = () -> { + try { + return addLinks(newText, mask, internalOnly, removeOldReplacements); + } catch (Exception e) { + FileLog.e(e); + return false; + } + }; + boolean success = false; + Future future = null; + try { + future = executor.submit(task); + success = future.get(200, TimeUnit.MILLISECONDS); + } catch (TimeoutException ex) { + if (future != null) { + future.cancel(true); + } + } catch (Exception ex) { + FileLog.e(ex); + } finally { + executor.shutdownNow(); + } + if (success && text != null) { + URLSpan[] oldSpans = text.getSpans(0, text.length(), URLSpan.class); + for (int i = 0; i < oldSpans.length; ++i) { + text.removeSpan(oldSpans[i]); + } + URLSpan[] newSpans = newText.getSpans(0, newText.length(), URLSpan.class); + for (int i = 0; i < newSpans.length; ++i) { + text.setSpan(newSpans[i], newText.getSpanStart(newSpans[i]), newText.getSpanEnd(newSpans[i]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return true; + } + return false; + } + + @Deprecated // use addLinksSafe public static boolean addLinks(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) { if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) { return false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java index 92e45c3232..2da02d7510 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java @@ -51,11 +51,7 @@ public int read(int offset, int readLength) { debugCanceledCount++; if (!debugReportSend && debugCanceledCount > 200) { debugReportSend = true; - if (BuildVars.DEBUG_PRIVATE_VERSION) { - throw new RuntimeException("infinity stream reading!!!"); - } else { - FileLog.e(new RuntimeException("infinity stream reading!!!")); - } + FileLog.e(new RuntimeException("infinity stream reading!!!")); } return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java index e1a0f78a08..6f17d23880 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AuthTokensHelper.java @@ -120,4 +120,9 @@ public static void addLogOutToken(TLRPC.TL_auth_loggedOut response) { preferences.edit().putString("log_out_token_" + count, Utilities.bytesToHex(data.toByteArray())).putInt("count", count + 1).apply(); BackupAgent.requestBackup(ApplicationLoader.applicationContext); } + + public static void clearLogInTokens() { + ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens_login", Context.MODE_PRIVATE).edit().clear().apply(); + ApplicationLoader.applicationContext.getSharedPreferences("saved_tokens", Context.MODE_PRIVATE).edit().clear().apply(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 5f60ebd07d..52f98fe264 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -1594,6 +1594,51 @@ public static boolean isActionBanned(TLRPC.Chat chat, int action) { return chat != null && (getBannedRight(chat.banned_rights, action) || getBannedRight(chat.default_banned_rights, action)); } + public static boolean canUserDoAdminAction(TLRPC.TL_chatAdminRights admin_rights, int action) { + if (admin_rights != null) { + boolean value; + switch (action) { + case ACTION_PIN: + value = admin_rights.pin_messages; + break; + case ACTION_MANAGE_TOPICS: + value = admin_rights.manage_topics; + break; + case ACTION_CHANGE_INFO: + value = admin_rights.change_info; + break; + case ACTION_INVITE: + value = admin_rights.invite_users; + break; + case ACTION_ADD_ADMINS: + value = admin_rights.add_admins; + break; + case ACTION_POST: + value = admin_rights.post_messages; + break; + case ACTION_EDIT_MESSAGES: + value = admin_rights.edit_messages; + break; + case ACTION_DELETE_MESSAGES: + value = admin_rights.delete_messages; + break; + case ACTION_BLOCK_USERS: + value = admin_rights.ban_users; + break; + case ACTION_MANAGE_CALLS: + value = admin_rights.manage_call; + break; + default: + value = false; + break; + } + if (value) { + return true; + } + } + return false; + } + public static boolean canUserDoAdminAction(TLRPC.Chat chat, int action) { if (chat == null) { return false; @@ -1645,6 +1690,43 @@ public static boolean canUserDoAdminAction(TLRPC.Chat chat, int action) { return false; } + public static boolean canUserDoAction(TLRPC.Chat chat, TLRPC.ChannelParticipant participant, int action) { + if (chat == null) { + return true; + } + if (participant == null) { + return false; + } + if (canUserDoAdminAction(participant.admin_rights, action)) { + return true; + } + if (getBannedRight(participant.banned_rights, action)) { + return false; + } + if (isBannableAction(action)) { + if (participant.admin_rights != null && !isAdminAction(action)) { + return true; + } + if (chat.default_banned_rights == null && ( + chat instanceof TLRPC.TL_chat_layer92 || + chat instanceof TLRPC.TL_chat_old || + chat instanceof TLRPC.TL_chat_old2 || + chat instanceof TLRPC.TL_channel_layer92 || + chat instanceof TLRPC.TL_channel_layer77 || + chat instanceof TLRPC.TL_channel_layer72 || + chat instanceof TLRPC.TL_channel_layer67 || + chat instanceof TLRPC.TL_channel_layer48 || + chat instanceof TLRPC.TL_channel_old)) { + return true; + } + if (chat.default_banned_rights == null || getBannedRight(chat.default_banned_rights, action)) { + return false; + } + return true; + } + return false; + } + public static boolean canUserDoAction(TLRPC.Chat chat, int action) { if (chat == null) { return true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java index fc12553cd0..875e2beaaf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java @@ -233,9 +233,9 @@ public RemoteViews getViewAt(int position) { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -297,7 +297,7 @@ public RemoteViews getViewAt(int position) { } else { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.type == MessageObject.TYPE_MUSIC) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 896da5e1c7..b8d3ff521b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1497,6 +1497,13 @@ public static int migrate(MessagesStorage messagesStorage, int version) throws E version = 152; } + if (version == 152) { + database.executeFast("ALTER TABLE profile_stories ADD COLUMN pin INTEGER default 0;").stepThis().dispose(); + + database.executeFast("PRAGMA user_version = 153").stepThis().dispose(); + version = 153; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java index 189740c2e7..9110e17fd2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DocumentObject.java @@ -45,25 +45,40 @@ public ThemeDocument(TLRPC.ThemeSettings settings) { } } + public static boolean containsPhotoSizeType(ArrayList sizes, String type) { + if (type == null) + return false; + for (int a = 0, N = sizes.size(); a < N; a++) { + TLRPC.PhotoSize photoSize = sizes.get(a); + if (type.equalsIgnoreCase(photoSize.type)) + return true; + } + return false; + } + public static SvgHelper.SvgDrawable getSvgThumb(ArrayList sizes, int colorKey, float alpha) { - int w = 0; - int h = 0; + return getSvgThumb(sizes, colorKey, alpha, false); + } + + public static SvgHelper.SvgDrawable getSvgThumb(ArrayList sizes, int colorKey, float alpha, boolean usePhotoSize) { + int w = 512; + int h = 512; TLRPC.TL_photoPathSize photoPathSize = null; for (int a = 0, N = sizes.size(); a < N; a++) { TLRPC.PhotoSize photoSize = sizes.get(a); if (photoSize instanceof TLRPC.TL_photoPathSize) { photoPathSize = (TLRPC.TL_photoPathSize) photoSize; - } else if (photoSize instanceof TLRPC.TL_photoSize) { + } else if (photoSize instanceof TLRPC.TL_photoSize && usePhotoSize) { w = photoSize.w; h = photoSize.h; } - if (photoPathSize != null && w != 0 && h != 0) { - SvgHelper.SvgDrawable pathThumb = SvgHelper.getDrawableByPath(photoPathSize.svgPath, w, h); - if (pathThumb != null) { - pathThumb.setupGradient(colorKey, alpha, false); - } - return pathThumb; + } + if (photoPathSize != null && w != 0 && h != 0) { + SvgHelper.SvgDrawable pathThumb = SvgHelper.getDrawableByPath(photoPathSize.svgPath, w, h); + if (pathThumb != null) { + pathThumb.setupGradient(colorKey, alpha, false); } + return pathThumb; } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index 068ba989d6..fe2c59d912 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -40,6 +40,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Locale; +import java.util.Objects; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.helpers.remote.EmojiHelper; @@ -856,6 +857,14 @@ public void updateDrawState(TextPaint ds) { } super.updateDrawState(ds); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EmojiSpan emojiSpan = (EmojiSpan) o; + return Float.compare(scale, emojiSpan.scale) == 0 && size == emojiSpan.size && Objects.equals(emoji, emojiSpan.emoji); + } } public static void addRecentEmoji(String code) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 989bd8b109..7933a856b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -869,6 +869,9 @@ public boolean start(final FileLoadOperationStream stream, final long streamOffs startDownloadRequest(-1); nextPartWasPreloaded = false; } + if (notLoadedBytesRanges != null) { + notifyStreamListeners(); + } }); } else if (alreadyStarted) { Utilities.stageQueue.postRunnable(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 671f27f68c..97160df9a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -93,7 +93,7 @@ public static String getKeyForParentObject(Object parentObject) { } else if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; long channelId = messageObject.getChannelId(); - return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled; + return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled + "_" + messageObject.getQuickReplyId(); } else if (parentObject instanceof TLRPC.Message) { TLRPC.Message message = (TLRPC.Message) parentObject; long channelId = message.peer_id != null ? message.peer_id.channel_id : 0; @@ -212,6 +212,11 @@ public void requestReference(Object parentObject, Object... args) { locationKey = "file_" + req.id.id; location = new TLRPC.TL_inputDocumentFileLocation(); location.id = req.id.id; + } else if (args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) args[0]; + locationKey = "file_" + req.sticker.document.id; + location = new TLRPC.TL_inputDocumentFileLocation(); + location.id = req.sticker.document.id; } else if (args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) args[0]; locationKey = "file_" + req.id.id; @@ -392,6 +397,12 @@ private void requestReferenceFromServer(Object parentObject, String locationKey, req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); req.id.add(messageObject.getRealId()); getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); + } else if (messageObject.isQuickReply()) { + TLRPC.TL_messages_getQuickReplyMessages req = new TLRPC.TL_messages_getQuickReplyMessages(); + req.shortcut_id = messageObject.getQuickReplyId(); + req.flags |= 1; + req.id.add(messageObject.getRealId()); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (channelId != 0) { TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); @@ -649,6 +660,15 @@ private boolean onUpdateObjectReference(Requester requester, byte[] file_referen req.id.file_reference = file_reference; getConnectionsManager().sendRequest(req, (response, error) -> { + }); + } else if (requester.args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) requester.args[0]; + if (fromCache && isSameReference(req.sticker.document.file_reference, file_reference)) { + return false; + } + req.sticker.document.file_reference = file_reference; + getConnectionsManager().sendRequest(req, (response, error) -> { + }); } else if (requester.args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) requester.args[0]; @@ -728,6 +748,9 @@ private void sendErrorToObject(Object[] args, int reason) { } else if (args[0] instanceof TLRPC.TL_messages_saveRecentSticker) { TLRPC.TL_messages_saveRecentSticker req = (TLRPC.TL_messages_saveRecentSticker) args[0]; //do nothing + } else if (args[0] instanceof TLRPC.TL_stickers_addStickerToSet) { + TLRPC.TL_stickers_addStickerToSet req = (TLRPC.TL_stickers_addStickerToSet) args[0]; + //do nothing } else if (args[0] instanceof TLRPC.TL_messages_faveSticker) { TLRPC.TL_messages_faveSticker req = (TLRPC.TL_messages_faveSticker) args[0]; //do nothing @@ -790,11 +813,10 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject continue; } if (error != null && BuildVars.LOGS_ENABLED) { - if (requester.args[1] instanceof FileLoadOperation) { + if (requester.args.length > 1 && requester.args[1] instanceof FileLoadOperation) { FileLoadOperation operation = (FileLoadOperation) requester.args[1]; FileLog.e("debug_loading: " + operation.getCacheFileFinal().getName() + " can't update file reference: " + error.code + " " + error.text); } - } if (requester.location instanceof TLRPC.TL_inputFileLocation || requester.location instanceof TLRPC.TL_inputPeerPhotoFileLocation) { locationReplacement = new TLRPC.InputFileLocation[1]; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 056e235b51..4950198f39 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -3453,6 +3453,8 @@ public void loadImageForImageReceiver(ImageReceiver imageReceiver, List whenFound) { + if (whenFound == null) + return; + if (name == null) { + whenFound.run(null); + return; + } + getMessagesStorage().getStorageQueue().postRunnable(() -> { + TLRPC.TL_messages_stickerSet cachedSet = getCachedStickerSetInternal(name.toLowerCase(), 0); + AndroidUtilities.runOnUIThread(() -> { + putStickerSet(cachedSet, false); + whenFound.run(cachedSet); + }); + }); } public TLRPC.TL_messages_stickerSet getStickerSetByEmojiOrName(String emoji) { @@ -1312,6 +1329,42 @@ public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputSti return null; } + public void putStickerSet(TLRPC.TL_messages_stickerSet set) { + putStickerSet(set, true); + } + + public void putStickerSet(TLRPC.TL_messages_stickerSet set, boolean notify) { + if (set == null || set.set == null) return; + stickerSetsById.put(set.set.id, set); + if (!TextUtils.isEmpty(set.set.short_name)) { + stickerSetsByName.put(set.set.short_name.toLowerCase(), set); + } + for (int i = 0; i < stickerSets.length; ++i) { + ArrayList sets = stickerSets[i]; + if (sets != null) { + for (int j = 0; j < sets.size(); ++j) { + TLRPC.TL_messages_stickerSet setB = sets.get(j); + if (setB != null && setB.set != null && setB.set.id == set.set.id) { + sets.set(j, set); + } + } + } + } + if (groupStickerSets.containsKey(set.set.id)) { + groupStickerSets.put(set.set.id, set); + } + saveStickerSetIntoCache(set); + int type = TYPE_IMAGE; + if (set.set.masks) { + type = TYPE_MASK; + } else if (set.set.emojis) { + type = TYPE_EMOJIPACKS; + } + if (notify) { + getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true); + } + } + private boolean cleanedupStickerSetCache; private void cleanupStickerSetCache() { if (cleanedupStickerSetCache) { @@ -2023,8 +2076,11 @@ public void calcNewHash(int type) { } public void storeTempStickerSet(TLRPC.TL_messages_stickerSet set) { + if (set == null || set.set == null) return; stickerSetsById.put(set.set.id, set); - stickerSetsByName.put(set.set.short_name, set); + if (set.set.short_name != null) { + stickerSetsByName.put(set.set.short_name.toLowerCase(), set); + } } public void addNewStickerSet(TLRPC.TL_messages_stickerSet set) { @@ -3209,7 +3265,9 @@ public void toggleStickerSet(Context context, TLObject stickerSetObject, int tog stickerSets[type].add(finalCurrentIndex, messages_stickerSet); stickerSetsById.put(stickerSet.id, messages_stickerSet); installedStickerSetsById.put(stickerSet.id, messages_stickerSet); - stickerSetsByName.put(stickerSet.short_name, messages_stickerSet); + if (stickerSet.short_name != null) { + stickerSetsByName.put(stickerSet.short_name.toLowerCase(), messages_stickerSet); + } removingStickerSetsUndos.remove(stickerSet.id); loadHash[type] = calcStickersHash(stickerSets[type]); @@ -5940,7 +5998,7 @@ public void loadReplyMessagesForMessages(ArrayList messages, long object.applyTimestampsHighlightForReplyMsg(); object.messageOwner.reply_to = new TLRPC.TL_messageReplyHeader(); object.messageOwner.reply_to.flags |= 16; - object.messageOwner.reply_to.reply_to_msg_id = messageObject.getId(); + object.messageOwner.reply_to.reply_to_msg_id = messageObject.getRealId(); } } } @@ -5974,14 +6032,14 @@ public void loadReplyMessagesForMessages(ArrayList messages, long if (messageObject == null) { continue; } - if (!messageObject.isReplyToStory() && messageObject.isReply() && messageObject.getId() > 0) { + if (!messageObject.isReplyToStory() && messageObject.isReply() && messageObject.getRealId() > 0) { if (messageObject.messageOwner.reply_to.reply_to_peer_id != null) { continue; } int reply_to_id = messageObject.messageOwner.reply_to.reply_to_msg_id; for (int j = 0; j < messages.size(); ++j) { if (a == j) continue; - if (messages.get(j) != null && messages.get(j).getId() == reply_to_id) { + if (messages.get(j) != null && messages.get(j).getRealId() == reply_to_id) { messageObject.replyMessageObject = messages.get(j); messageObject.applyTimestampsHighlightForReplyMsg(); if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { @@ -6017,7 +6075,7 @@ public void loadReplyMessagesForMessages(ArrayList messages, long long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer); messageObject.messageOwner.media.storyItem = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.media.storyItem); } - } else if (messageObject.getId() > 0 && messageObject.isReplyToStory()) { + } else if (messageObject.getRealId() > 0 && messageObject.isReplyToStory()) { if (messageObject.messageOwner.replyStory == null) { long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer); if (messagesWithUnknownStories == null) { @@ -6033,7 +6091,7 @@ public void loadReplyMessagesForMessages(ArrayList messages, long long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer); messageObject.messageOwner.replyStory = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.replyStory); } - } else if (messageObject.getId() > 0 && messageObject.isReply()) { + } else if (messageObject.getRealId() > 0 && messageObject.isReply()) { int messageId = messageObject.messageOwner.reply_to.reply_to_msg_id; if (messageId == threadMessageId) { continue; @@ -6993,7 +7051,7 @@ public ArrayList getEntities(CharSequence[] message, boolea } if (spannable instanceof Spannable) { - AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS, false, false); + AndroidUtilities.addLinksSafe((Spannable) spannable, Linkify.WEB_URLS, false, false); URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class); if (spansUrl != null && spansUrl.length > 0) { if (entities == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 4311ffa026..81ecfa97cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -168,6 +168,7 @@ public class MessageObject { public String customName; public boolean reactionsChanged; public boolean isReactionPush; + public boolean isStoryReactionPush; public boolean isStoryPush, isStoryMentionPush, isStoryPushHidden; public boolean putInDownloadsStore; public boolean isDownloadingFile; @@ -208,22 +209,21 @@ public class MessageObject { public boolean isRestrictedMessage; public long loadedFileSize; public boolean forceExpired; + public long actionDeleteGroupEventId = -1; public boolean isSpoilersRevealed = NekoConfig.showSpoilersDirectly.Bool(); public boolean isMediaSpoilersRevealed; public boolean isMediaSpoilersRevealedInSharedMedia; public boolean revealingMediaSpoilers; public byte[] sponsoredId; - public int sponsoredChannelPost; - public TLRPC.ChatInvite sponsoredChatInvite; - public String sponsoredChatInviteHash; - public boolean sponsoredShowPeerPhoto; + public String sponsoredTitle, sponsoredUrl; public boolean sponsoredRecommended; + public TLRPC.Photo sponsoredPhoto; public String sponsoredInfo, sponsoredAdditionalInfo; - public TLRPC.TL_sponsoredWebPage sponsoredWebPage; - public TLRPC.BotApp sponsoredBotApp; public String sponsoredButtonText; + public TLRPC.TL_peerColor sponsoredColor; public boolean sponsoredCanReport; + public boolean replyTextEllipsized; public boolean replyTextRevealed; public int overrideLinkColor = -1; @@ -233,8 +233,6 @@ public class MessageObject { public TLRPC.TL_forumTopic replyToForumTopic; // used only for reply message in view all messages - public String botStartParam; - public boolean animateComments; public boolean loadingCancelled; @@ -265,7 +263,7 @@ public int getChatMode() { return 0; } - public ArrayList checkedVotes; + public ArrayList checkedVotes; public CharSequence editingMessage; public ArrayList editingMessageEntities; @@ -618,6 +616,7 @@ public static class SendAnimationData { public float currentX; public float currentY; public float timeAlpha; + public float progress; } public static class VCardData { @@ -1488,7 +1487,7 @@ public void reset() { backgroundChangeBounds = false; } } - + public boolean contains(int messageId) { if (messages == null) { return false; @@ -1958,6 +1957,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL new_participant = action.new_participant; } messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; long peerId = MessageObject.getPeerId(prev_participant.peer); TLObject whoUser; if (peerId > 0) { @@ -2025,7 +2025,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL } if (o.delete_messages != n.delete_messages) { rights.append('\n').append(n.delete_messages ? '+' : '-').append(' '); - rights.append(LocaleController.getString("EventLogPromotedDeleteMessages", R.string.EventLogPromotedDeleteMessages)); + rights.append(LocaleController.getString(R.string.EventLogPromotedDeleteMessages)); } if (o.add_admins != n.add_admins) { rights.append('\n').append(n.add_admins ? '+' : '-').append(' '); @@ -2060,6 +2060,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDefaultBannedRights) { TLRPC.TL_channelAdminLogEventActionDefaultBannedRights bannedRights = (TLRPC.TL_channelAdminLogEventActionDefaultBannedRights) event.action; messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; TLRPC.TL_chatBannedRights o = bannedRights.prev_banned_rights; TLRPC.TL_chatBannedRights n = bannedRights.new_banned_rights; @@ -2137,6 +2138,7 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) { TLRPC.TL_channelAdminLogEventActionParticipantToggleBan action = (TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) event.action; messageOwner = new TLRPC.TL_message(); + messageOwner.realId = -1; long peerId = getPeerId(action.prev_participant.peer); TLObject whoUser; if (peerId > 0) { @@ -2323,9 +2325,9 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { message = ((TLRPC.TL_channelAdminLogEventActionDeleteMessage) event.action).message; if (fromUser != null && fromUser.id == MessagesController.getInstance(currentAccount).telegramAntispamUserId) { - messageText = LocaleController.getString("EventLogDeletedMessages", R.string.EventLogDeletedMessages).replace("un1", UserObject.getUserName(fromUser)); + messageText = LocaleController.getString(R.string.EventLogDeletedMessages).replace("un1", UserObject.getUserName(fromUser)); } else { - messageText = replaceWithLink(LocaleController.getString("EventLogDeletedMessages", R.string.EventLogDeletedMessages), "un1", fromUser); + messageText = replaceWithLink(LocaleController.getString(R.string.EventLogDeletedMessages), "un1", fromUser); } } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeLinkedChat) { long newChatId = ((TLRPC.TL_channelAdminLogEventActionChangeLinkedChat) event.action).new_value; @@ -3007,9 +3009,8 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL message.out = false; message.realId = message.id; message.id = mid[0]++; - message.flags &= ~TLRPC.MESSAGE_FLAG_REPLY; - message.reply_to = null; message.flags = message.flags & ~TLRPC.MESSAGE_FLAG_EDITED; + message.dialog_id = -chat.id; MessageObject messageObject = new MessageObject(currentAccount, message, null, null, true, true, eventId); messageObject.currentEvent = event; if (messageObject.contentType >= 0) { @@ -3033,6 +3034,9 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL messageObject.generateLinkDescription(); } } + if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { + return; + } if (contentType >= 0) { createDateArray(currentAccount, event, messageObjects, messagesByDays, addToEnd); if (addToEnd) { @@ -5352,13 +5356,13 @@ public void generateThumbs(boolean update) { } } } - } else if (sponsoredWebPage != null && sponsoredWebPage.photo != null) { + } else if (sponsoredPhoto != null) { if (!update || photoThumbs == null) { - photoThumbs = new ArrayList<>(sponsoredWebPage.photo.sizes); + photoThumbs = new ArrayList<>(sponsoredPhoto.sizes); } else if (!photoThumbs.isEmpty()) { - updatePhotoSizeLocations(photoThumbs, sponsoredWebPage.photo.sizes); + updatePhotoSizeLocations(photoThumbs, sponsoredPhoto.sizes); } - photoThumbsObject = sponsoredWebPage.photo; + photoThumbsObject = sponsoredPhoto; if (strippedThumb == null) { createStrippedThumb(); } @@ -5609,7 +5613,7 @@ public void generateLinkDescription() { if (!TextUtils.isEmpty(linkDescription)) { if (containsUrls(linkDescription)) { try { - AndroidUtilities.addLinks((Spannable) linkDescription, Linkify.WEB_URLS); + AndroidUtilities.addLinksSafe((Spannable) linkDescription, Linkify.WEB_URLS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -5739,7 +5743,7 @@ public void generateCaption() { if (useManualParse) { if (containsUrls(caption)) { try { - AndroidUtilities.addLinks((Spannable) caption, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + AndroidUtilities.addLinksSafe((Spannable) caption, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -5957,13 +5961,13 @@ public static void addLinks(boolean isOut, CharSequence messageText, boolean bot if (messageText instanceof Spannable && containsUrls(messageText)) { if (messageText.length() < 1000) { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly); + AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly, false); } catch (Exception e) { FileLog.e(e); } } else { try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.WEB_URLS, internalOnly); + AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS, internalOnly, false); } catch (Exception e) { FileLog.e(e); } @@ -8355,6 +8359,39 @@ public static String findAnimatedEmojiEmoticon(TLRPC.Document document, String f return fallback; } + + public static ArrayList findStickerEmoticons(TLRPC.Document document, Integer currentAccountForFull) { + if (document == null) { + return null; + } + ArrayList emojis = new ArrayList<>(); + for (int a = 0, N = document.attributes.size(); a < N; a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeCustomEmoji || + attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (currentAccountForFull != null) { + TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccountForFull).getStickerSet(attribute.stickerset, true); + if (set != null && set.packs != null) { + for (int p = 0; p < set.packs.size(); ++p) { + TLRPC.TL_stickerPack pack = set.packs.get(p); + if (pack.documents.contains(document.id) && Emoji.getEmojiDrawable(pack.emoticon) != null) { + emojis.add(pack.emoticon); + } + } + } + if (!emojis.isEmpty()) { + return emojis; + } + } + if (!TextUtils.isEmpty(attribute.alt) && Emoji.getEmojiDrawable(attribute.alt) != null) { + emojis.add(attribute.alt); + return emojis; + } + } + } + return null; + } + public static boolean isAnimatedEmoji(TLRPC.Document document) { if (document == null) { return false; @@ -9719,7 +9756,12 @@ public boolean selectReaction(ReactionsLayoutInBubble.VisibleReaction visibleRea } } } + if (newReaction == null) { + int maxChatReactions = MessagesController.getInstance(currentAccount).getChatMaxUniqReactions(getDialogId()); + if (messageOwner.reactions.results.size() + 1 > maxChatReactions) { + return false; + } newReaction = new TLRPC.TL_reactionCount(); newReaction.reaction = visibleReaction.toTLReaction(); messageOwner.reactions.results.add(newReaction); @@ -9880,7 +9922,7 @@ public static CharSequence channelSpan() { public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer) { return peerNameWithIcon(currentAccount, peer, !(peer instanceof TLRPC.TL_peerUser)); } - + public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer, boolean anotherChat) { if (peer instanceof TLRPC.TL_peerUser) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peer.user_id); @@ -10001,7 +10043,7 @@ public boolean hasLinkMediaToMakeSmall() { return hasLinkPreview && !isGiveawayOrGiveawayResults() && webpage != null && (webpage.photo != null || isVideoDocument(webpage.document)) && !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && - !(isSponsored() && sponsoredWebPage == null && sponsoredChannelPost == 0) && // drawInstantViewType = 1 + !isSponsored() && // drawInstantViewType = 1 !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java index 6bc5456c47..fb149152a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java @@ -354,7 +354,7 @@ public boolean hasLink(CharSequence text, String url) { try { Spannable spanned = SpannableString.valueOf(text); try { - AndroidUtilities.addLinks(spanned, Linkify.WEB_URLS); + AndroidUtilities.addLinksSafe(spanned, Linkify.WEB_URLS, false, true); } catch (Exception e2) { FileLog.e(e2); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 6bf5e441ba..490e1a7d49 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -10,6 +10,7 @@ import static org.telegram.messenger.NotificationsController.TYPE_CHANNEL; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; import android.Manifest; import android.app.Activity; @@ -61,6 +62,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.QuickRepliesController; +import org.telegram.ui.ChannelMonetizationLayout; import org.telegram.ui.ChatActivity; import org.telegram.ui.ChatReactionsEditActivity; import org.telegram.ui.ChatRightsEditActivity; @@ -70,13 +72,17 @@ import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.MotionBackgroundDrawable; +import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftToUsersBottomSheet; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.SwipeGestureSettingsView; import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.DialogsActivity; import org.telegram.ui.EditWidgetActivity; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.NotificationsSettingsActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; import org.telegram.ui.SecretMediaViewer; @@ -527,6 +533,7 @@ protected boolean useCache(Integer arguments) { public boolean saveGifsWithStickers; private String installReferer; public Set pendingSuggestions; + public Set dismissedSuggestions; public Set exportUri; public Set exportGroupUri; public Set exportPrivateUri; @@ -619,6 +626,11 @@ protected boolean useCache(Integer arguments) { public int businessChatLinksLimit; public boolean channelRevenueWithdrawalEnabled; public boolean newNoncontactPeersRequirePremiumWithoutOwnpremium; + public int reactionsUniqMax; + public String premiumManageSubscriptionUrl; + public boolean androidDisableRoundCamera2; + public int storiesPinnedToTopCountMax; + public boolean showAnnualPerMonth = false; public int savedDialogsPinnedLimitDefault; public int savedDialogsPinnedLimitPremium; @@ -782,6 +794,14 @@ public int getChatReactionsCount() { return getUserConfig().isPremium() ? reactionsInChatMax : 1; } + public int getChatMaxUniqReactions(long dialogId) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId); + if (chatFull != null && (chatFull instanceof TLRPC.TL_chatFull ? (chatFull.flags & 1048576) != 0 : (chatFull.flags2 & 8192) != 0)) { + return chatFull.reactions_limit; + } + return reactionsUniqMax; + } + public boolean isPremiumUser(TLRPC.User currentUser) { if (NekoConfig.localPremium.Bool()) { return true; @@ -1507,6 +1527,7 @@ public MessagesController(int num) { roundVideoBitrate = mainPreferences.getInt("roundVideoBitrate", 1000); roundAudioBitrate = mainPreferences.getInt("roundAudioBitrate", 64); pendingSuggestions = mainPreferences.getStringSet("pendingSuggestions", null); + dismissedSuggestions = mainPreferences.getStringSet("dismissedSuggestions", null); channelsLimitDefault = mainPreferences.getInt("channelsLimitDefault", 500); channelsLimitPremium = mainPreferences.getInt("channelsLimitPremium", 2 * channelsLimitDefault); savedGifsLimitDefault = mainPreferences.getInt("savedGifsLimitDefault", 200); @@ -1618,6 +1639,11 @@ public MessagesController(int num) { businessChatLinksLimit = mainPreferences.getInt("businessChatLinksLimit", 100); channelRevenueWithdrawalEnabled = mainPreferences.getBoolean("channelRevenueWithdrawalEnabled", false); newNoncontactPeersRequirePremiumWithoutOwnpremium = mainPreferences.getBoolean("newNoncontactPeersRequirePremiumWithoutOwnpremium", false); + reactionsUniqMax = mainPreferences.getInt("reactionsUniqMax", 11); + premiumManageSubscriptionUrl = mainPreferences.getString("premiumManageSubscriptionUrl", ApplicationLoader.isStandaloneBuild() ? "https://t.me/premiumbot?start=status" : "https://play.google.com/store/account/subscriptions?sku=telegram_premium&package=org.telegram.messenger"); + androidDisableRoundCamera2 = mainPreferences.getBoolean("androidDisableRoundCamera2", false); + storiesPinnedToTopCountMax = mainPreferences.getInt("storiesPinnedToTopCountMax", 3); + showAnnualPerMonth = mainPreferences.getBoolean("showAnnualPerMonth", false); scheduleTranscriptionUpdate(); // BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID); if (mainPreferences.contains("dcDomainName2")) { @@ -1644,6 +1670,11 @@ public MessagesController(int num) { } else { pendingSuggestions = new HashSet<>(); } + if (dismissedSuggestions != null) { + dismissedSuggestions = new HashSet<>(dismissedSuggestions); + } else { + dismissedSuggestions = new HashSet<>(); + } exportUri = mainPreferences.getStringSet("exportUri2", null); if (exportUri != null) { @@ -2390,11 +2421,14 @@ public void removeFilter(DialogFilter filter) { getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); } + private Runnable loadAppConfigRunnable = this::loadAppConfig; + public void loadAppConfig() { loadAppConfig(false); } public void loadAppConfig(boolean force) { + AndroidUtilities.cancelRunOnUIThread(loadAppConfigRunnable); if (force) { appConfigFetcher.forceRequest(currentAccount, 0); } @@ -2402,6 +2436,8 @@ public void loadAppConfig(boolean force) { if (config != null && config.config instanceof TLRPC.TL_jsonObject) { applyAppConfig((TLRPC.TL_jsonObject) config.config); } + AndroidUtilities.cancelRunOnUIThread(loadAppConfigRunnable); + AndroidUtilities.runOnUIThread(loadAppConfigRunnable, 4 * 60 * 1000 + 10); })); } @@ -3091,6 +3127,26 @@ private void applyAppConfig(TLRPC.TL_jsonObject object) { } break; } + case "dismissed_suggestions": { + HashSet newSuggestions = 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; + newSuggestions.add(string.value); + } + } + } + if (!dismissedSuggestions.equals(newSuggestions)) { + dismissedSuggestions = newSuggestions; + editor.putStringSet("dismissedSuggestions", dismissedSuggestions); + getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); + changed = true; + } + break; + } case "emojies_sounds": { try { HashMap newEmojies = new HashMap<>(); @@ -4083,6 +4139,61 @@ private void applyAppConfig(TLRPC.TL_jsonObject object) { } break; } + case "reactions_uniq_max": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != reactionsUniqMax) { + reactionsUniqMax = (int) num.value; + editor.putInt("reactionsUniqMax", reactionsUniqMax); + changed = true; + } + } + break; + } + case "premium_manage_subscription_url": { + if (value.value instanceof TLRPC.TL_jsonString) { + TLRPC.TL_jsonString str = (TLRPC.TL_jsonString) value.value; + if (!TextUtils.equals(str.value, premiumManageSubscriptionUrl)) { + premiumManageSubscriptionUrl = str.value; + editor.putString("premiumManageSubscriptionUrl", premiumManageSubscriptionUrl); + changed = true; + } + } + break; + } + case "android_disable_round_camera2": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != androidDisableRoundCamera2) { + androidDisableRoundCamera2 = bool.value; + editor.putBoolean("androidDisableRoundCamera2", androidDisableRoundCamera2); + changed = true; + } + } + break; + } + case "stories_pinned_to_top_count_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (num.value != storiesPinnedToTopCountMax) { + storiesPinnedToTopCountMax = (int) num.value; + editor.putInt("storiesPinnedToTopCountMax", storiesPinnedToTopCountMax); + changed = true; + } + } + break; + } + case "show_annual_per_month": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != showAnnualPerMonth) { + showAnnualPerMonth = bool.value; + editor.putBoolean("showAnnualPerMonth", showAnnualPerMonth); + changed = true; + } + } + break; + } } } @@ -4614,7 +4725,8 @@ private void resetAppConfig() { channelRevenueWithdrawalEnabled = false; collectDeviceStats = false; smsjobsStickyNotificationEnabled = false; - mainPreferences.edit().remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").apply(); + showAnnualPerMonth = false; + mainPreferences.edit().remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").apply(); } private boolean savePremiumFeaturesPreviewOrder(String key, SparseIntArray array, SharedPreferences.Editor editor, ArrayList value) { @@ -4665,9 +4777,11 @@ public void removeSuggestion(long did, String suggestion) { return; } if (did == 0) { - if (pendingSuggestions.remove(suggestion)) { + if (pendingSuggestions.remove(suggestion) || !dismissedSuggestions.contains(suggestion)) { + dismissedSuggestions.add(suggestion); SharedPreferences.Editor editor = mainPreferences.edit(); editor.putStringSet("pendingSuggestions", pendingSuggestions); + editor.putStringSet("dismissedSuggestions", dismissedSuggestions); editor.commit(); getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); } else { @@ -4933,7 +5047,9 @@ public TLRPC.InputPeer getInputPeer(TLRPC.Peer peer) { public TLRPC.InputPeer getInputPeer(long id) { TLRPC.InputPeer inputPeer; - if (id < 0) { + if (id == getUserConfig().getClientUserId()) { + inputPeer = new TLRPC.TL_inputPeerSelf(); + } else if (id < 0) { TLRPC.Chat chat = getChat(-id); if (ChatObject.isChannel(chat)) { inputPeer = new TLRPC.TL_inputPeerChannel(); @@ -4974,6 +5090,16 @@ public static TLRPC.InputPeer getInputPeer(TLRPC.User user) { return inputPeer; } + public static TLRPC.InputPeer getInputPeer(TLObject userOrChat) { + if (userOrChat instanceof TLRPC.User) { + return getInputPeer((TLRPC.User) userOrChat); + } else if (userOrChat instanceof TLRPC.Chat) { + return getInputPeer((TLRPC.Chat) userOrChat); + } else { + return null; + } + } + public TLRPC.Peer getPeer(long id) { TLRPC.Peer inputPeer; if (id < 0) { @@ -7412,6 +7538,10 @@ public void blockPeer(long id) { } public void setParticipantBannedRole(long chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.TL_chatBannedRights rights, boolean isChannel, BaseFragment parentFragment) { + setParticipantBannedRole(chatId, user, chat, rights, isChannel, parentFragment, null); + } + + public void setParticipantBannedRole(long chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.TL_chatBannedRights rights, boolean isChannel, BaseFragment parentFragment, Runnable whenDone) { if (user == null && chat == null || rights == null) { return; } @@ -7427,6 +7557,9 @@ public void setParticipantBannedRole(long chatId, TLRPC.User user, TLRPC.Chat ch if (error == null) { processUpdates((TLRPC.Updates) response, false); AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000); + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, parentFragment, req, isChannel)); } @@ -10954,7 +11087,7 @@ public void loadGlobalNotificationsSettings() { editor1.commit(); } - loadingNotificationSettings = 3; + loadingNotificationSettings = 4; for (int a = 0; a < 3; a++) { TLRPC.TL_account_getNotifySettings req = new TLRPC.TL_account_getNotifySettings(); if (a == 0) { @@ -11023,7 +11156,7 @@ public void loadGlobalNotificationsSettings() { } } getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.android_sound, editor, 0, 0, type, false); - editor.commit(); + editor.apply(); if (loadingNotificationSettings == 0) { getUserConfig().notificationsSettingsLoaded = true; getUserConfig().saveConfig(false); @@ -11031,12 +11164,57 @@ public void loadGlobalNotificationsSettings() { } })); } + + getConnectionsManager().sendRequest(new TLRPC.TL_account_getReactionsNotifySettings(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + loadingNotificationSettings--; + if (res instanceof TLRPC.TL_reactionsNotifySettings) { + TLRPC.TL_reactionsNotifySettings notify_settings = (TLRPC.TL_reactionsNotifySettings) res; + SharedPreferences.Editor editor = notificationsPreferences.edit(); + editor.putBoolean("EnableReactionsMessages", notify_settings.messages_notify_from != null); + if (notify_settings.messages_notify_from != null) { + editor.putBoolean("EnableReactionsMessagesContacts", notify_settings.messages_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsStories", notify_settings.stories_notify_from != null); + if (notify_settings.stories_notify_from != null) { + editor.putBoolean("EnableReactionsStoriesContacts", notify_settings.stories_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsPreview", notify_settings.show_previews); + getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.sound, editor, 0, 0, TYPE_REACTIONS_MESSAGES, false); + editor.apply(); + } + if (loadingNotificationSettings == 0) { + getUserConfig().notificationsSettingsLoaded = true; + getUserConfig().saveConfig(false); + } + })); } if (!getUserConfig().notificationsSignUpSettingsLoaded) { loadSignUpNotificationsSettings(); } } + public void reloadReactionsNotifySettings() { + getConnectionsManager().sendRequest(new TLRPC.TL_account_getReactionsNotifySettings(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_reactionsNotifySettings) { + TLRPC.TL_reactionsNotifySettings notify_settings = (TLRPC.TL_reactionsNotifySettings) res; + SharedPreferences.Editor editor = notificationsPreferences.edit(); + editor.putBoolean("EnableReactionsMessages", notify_settings.messages_notify_from != null); + if (notify_settings.messages_notify_from != null) { + editor.putBoolean("EnableReactionsMessagesContacts", notify_settings.messages_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsStories", notify_settings.stories_notify_from != null); + if (notify_settings.stories_notify_from != null) { + editor.putBoolean("EnableReactionsStoriesContacts", notify_settings.stories_notify_from instanceof TLRPC.TL_reactionNotificationsFromContacts); + } + editor.putBoolean("EnableReactionsPreview", notify_settings.show_previews); + getNotificationsController().getNotificationsSettingsFacade().applySoundSettings(notify_settings.sound, editor, 0, 0, TYPE_REACTIONS_MESSAGES, false); + editor.apply(); + + getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); + } + })); + } + public void loadSignUpNotificationsSettings() { if (!loadingNotificationSignUpSettings) { loadingNotificationSignUpSettings = true; @@ -13844,6 +14022,10 @@ public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer) { } public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean forceDelete, boolean revoke) { + deleteParticipantFromChat(chatId, peer, forceDelete, revoke, null); + } + + public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean forceDelete, boolean revoke, Runnable whenDone) { if (peer == null) { return; } @@ -13886,7 +14068,6 @@ public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean TLRPC.TL_messages_deleteChat req = new TLRPC.TL_messages_deleteChat(); req.chat_id = chatId; getConnectionsManager().sendRequest(req, (response, error) -> { - }); return; } @@ -13908,6 +14089,9 @@ public void deleteParticipantFromChat(long chatId, TLRPC.InputPeer peer, boolean if (isChannel && !self) { AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000); } + if (whenDone != null) { + AndroidUtilities.runOnUIThread(whenDone); + } }, ConnectionsManager.RequestFlagInvokeAfter); } @@ -14700,6 +14884,7 @@ protected void getChannelDifference(long channelId, int newDialogType, long task long[] ids = corrected.valueAt(a); getSendMessagesHelper().processSentMessage((int) ids[1]); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, (int) ids[1], newId, null, ids[0], 0L, -1, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, (int) ids[1], newId, null, ids[0], 0L, -1, false); } }); } @@ -14956,6 +15141,7 @@ public void getDifference(int pts, int date, int qts, boolean slice) { long[] ids = corrected.valueAt(a); getSendMessagesHelper().processSentMessage((int) ids[1]); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, (int) ids[1], newId, null, ids[0], 0L, -1, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, (int) ids[1], newId, null, ids[0], 0L, -1, false); } }); } @@ -17765,6 +17951,41 @@ public boolean processUpdateArray(ArrayList updates, ArrayList messageObjects = new ArrayList(); + MessageObject message = new MessageObject(currentAccount, msg, false, false); + message.isStoryReactionPush = true; + message.localType = 1; + if (user != null) { + message.localUserName = UserObject.getFirstName(user); + } + messageObjects.add(message); + getNotificationsController().processNewMessages(messageObjects, true, false, null); + } else if (baseUpdate instanceof TLRPC.TL_updateBroadcastRevenueTransactions) { + TLRPC.TL_updateBroadcastRevenueTransactions update = (TLRPC.TL_updateBroadcastRevenueTransactions) baseUpdate; + if (ChannelMonetizationLayout.instance != null) { + ChannelMonetizationLayout.instance.setupBalances(update.balances); + ChannelMonetizationLayout.instance.reloadTransactions(); + } } else if (baseUpdate instanceof TLRPC.TL_updateUser) { TLRPC.TL_updateUser update = (TLRPC.TL_updateUser) baseUpdate; TLRPC.User currentUser = getUser(update.user_id); @@ -17804,7 +18025,7 @@ public boolean processUpdateArray(ArrayList updates, ArrayList reactions, Utilities.Callback onError, Runnable onSuccess) { + public void setCustomChatReactions(long chatId, int type, List reactions, int reactionsCount, Utilities.Callback onError, Runnable onSuccess) { TLRPC.TL_messages_setChatAvailableReactions req = new TLRPC.TL_messages_setChatAvailableReactions(); req.peer = getInputPeer(-chatId); if (type == ChatReactionsEditActivity.SELECT_TYPE_NONE || reactions.isEmpty()) { @@ -20158,6 +20375,8 @@ public void setCustomChatReactions(long chatId, int type, List r req.available_reactions = someReactions; someReactions.reactions.addAll(reactions); } + req.flags |= 1; + req.reactions_limit = reactionsCount; getConnectionsManager().sendRequest(req, (response, error) -> { if (response != null) { processUpdates((TLRPC.Updates) response, false); @@ -20186,6 +20405,17 @@ public void setCustomChatReactions(long chatId, int type, List r }); } }); + + TLRPC.ChatFull chatFull = getChatFull(chatId); + if (chatFull != null) { + if (chatFull instanceof TLRPC.TL_channelFull) { + chatFull.flags2 |= 8192; + } else { + chatFull.flags |= 1048576; + } + chatFull.reactions_limit = reactionsCount; + getMessagesStorage().updateChatInfo(chatFull, false); + } } public void setChatReactions(long chatId, int type, List reactions) { @@ -20290,6 +20520,24 @@ public boolean isInChatCached(TLRPC.Chat chat, TLRPC.User user) { return false; } + public void getChannelParticipant(TLRPC.Chat chat, TLRPC.User user, Utilities.Callback callback) { + if (chat == null || user == null) { + if (callback != null) { + callback.run(null); + } + return; + } + TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); + req.channel = getInputChannel(chat.id); + req.participant = getInputPeer(user); + getConnectionsManager().sendRequest(req, (res, err) -> { + if (callback != null) { + TLRPC.ChannelParticipant participant = res instanceof TLRPC.TL_channels_channelParticipant ? ((TLRPC.TL_channels_channelParticipant) res).participant : null; + callback.run(participant); + } + }); + } + public void checkIsInChat(boolean tryCacheFirst, TLRPC.Chat chat, TLRPC.User user, IsInChatCheckedCallback callback) { if (chat == null || user == null) { if (callback != null) { @@ -20713,9 +20961,16 @@ public static boolean hasRecommendations(int currentAccount, long chatId) { } private HashMap cachedChannelRecommendations; + public ChannelRecommendations getCachedChannelRecommendations(long chatId) { + if (cachedChannelRecommendations == null) { + return null; + } + return cachedChannelRecommendations.get(chatId); + } + public ChannelRecommendations getChannelRecommendations(long chatId) { TLRPC.InputChannel inputChannel = getInputChannel(chatId); - if (inputChannel == null) { + if (inputChannel == null && chatId != 0) { return null; } if (cachedChannelRecommendations == null) { @@ -20731,7 +20986,10 @@ public ChannelRecommendations getChannelRecommendations(long chatId) { } cachedChannelRecommendations.put(chatId, null); TLRPC.TL_channels_getChannelRecommendations req = new TLRPC.TL_channels_getChannelRecommendations(); - req.channel = inputChannel; + if (chatId != 0) { + req.flags |= 1; + req.channel = inputChannel; + } getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.messages_Chats) { ArrayList chats = ((TLRPC.messages_Chats) res).chats; @@ -21224,4 +21482,22 @@ private void requestIsUserPremiumBlocked() { } })); } + + public void disableAds(boolean send) { + TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return; + userFull.sponsored_enabled = false; + getMessagesStorage().updateUserInfo(userFull, false); + if (send) { + TLRPC.TL_account_toggleSponsoredMessages req = new TLRPC.TL_account_toggleSponsoredMessages(); + req.enabled = false; + getConnectionsManager().sendRequest(req, null); + } + } + + public boolean isSponsoredDisabled() { + TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return false; + return !userFull.sponsored_enabled; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 40846ba4e7..585653f68f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -105,7 +105,7 @@ public class MessagesStorage extends BaseController { private static SparseArray Instance = new SparseArray(); private static final Object lockObject = new Object(); - public final static int LAST_DB_VERSION = 152; + public final static int LAST_DB_VERSION = 153; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -699,7 +699,7 @@ public static void createTables(SQLiteDatabase database) throws SQLiteException database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose(); - database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, seen INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); + database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, type INTEGER, seen INTEGER, pin INTEGER, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB, type INTEGER);").stepThis().dispose(); @@ -1313,6 +1313,16 @@ public void deleteAllStoryPushMessages() { }); } + public void deleteAllStoryReactionPushMessages() { + storageQueue.postRunnable(() -> { + try { + database.executeFast("DELETE FROM unread_push_messages WHERE is_reaction = 2").stepThis().dispose(); + } catch (Exception e) { + checkSQLException(e); + } + }); + } + public void putPushMessage(MessageObject message) { storageQueue.postRunnable(() -> { try { @@ -1351,7 +1361,7 @@ public void putPushMessage(MessageObject message) { } state.bindInteger(9, flags); state.bindLong(10, MessageObject.getTopicId(currentAccount, message.messageOwner, false)); - state.bindInteger(11, message.isReactionPush ? 1 : 0); + state.bindInteger(11, (message.isReactionPush ? 1 : 0) + (message.isStoryReactionPush ? 1 : 0)); state.step(); data.reuse(); @@ -3739,7 +3749,9 @@ public void loadUnreadMessages() { } MessageObject messageObject = new MessageObject(currentAccount, message, messageText, name, userName, (flags & 1) != 0, (flags & 2) != 0, (message.flags & 0x80000000) != 0, false); - messageObject.isReactionPush = cursor.intValue(10) != 0; + final int is_reaction = cursor.intValue(10); + messageObject.isReactionPush = is_reaction == 1; + messageObject.isStoryReactionPush = is_reaction == 2; pushMessages.add(messageObject); addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, null); } @@ -5197,7 +5209,7 @@ public TLRPC.Message getMessageWithCustomParamsOnlyInternal(int messageId, long TLRPC.Message message = new TLRPC.TL_message(); SQLiteCursor cursor = null; try { - cursor = database.queryFinalized("SELECT custom_params FROM messages_v2 WHERE mid = " + messageId + " AND uid = " + dialogId); + cursor = database.queryFinalized("SELECT custom_params FROM messages_v2 WHERE mid = ? AND uid = ?", messageId, dialogId); boolean read = false; if (cursor.next()) { MessageCustomParamsHelper.readLocalParams(message, cursor.byteBufferValue(0)); @@ -5206,7 +5218,7 @@ public TLRPC.Message getMessageWithCustomParamsOnlyInternal(int messageId, long cursor.dispose(); cursor = null; if (!read) { - cursor = database.queryFinalized("SELECT custom_params FROM messages_topics WHERE mid = " + messageId + " AND uid = " + dialogId); + cursor = database.queryFinalized("SELECT custom_params FROM messages_topics WHERE mid = ? AND uid = ?", messageId, dialogId); if (cursor.next()) { MessageCustomParamsHelper.readLocalParams(message, cursor.byteBufferValue(0)); read = true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index eb2ea110a1..5114bdcb19 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -708,6 +708,9 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.messagePlayingDidSeek) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject == null) { + return; + } long progress = Math.round(messageObject.audioPlayerDuration * (float) args[1]) * 1000L; updatePlaybackState(progress); if (remoteControlClient != null && Build.VERSION.SDK_INT >= 18) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index a1fd78a2f0..b1392b274e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -44,6 +44,7 @@ public class NotificationCenter { public static final int loadingMessagesFailed = totalEvents++; public static final int messageReceivedByAck = totalEvents++; public static final int messageReceivedByServer = totalEvents++; + public static final int messageReceivedByServer2 = totalEvents++; public static final int messageSendError = totalEvents++; public static final int forceImportContactsStart = totalEvents++; public static final int contactsDidLoad = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java index c5d763be4e..d3016505f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java @@ -27,6 +27,8 @@ public void onReceive(Context context, Intent intent) { int date = intent.getIntExtra("messageDate", 0); if (intent.hasExtra("story") && intent.getBooleanExtra("story", false)) { NotificationsController.getInstance(currentAccount).processIgnoreStories(); + } else if (intent.hasExtra("storyReaction") && intent.getBooleanExtra("storyReaction", false)) { + NotificationsController.getInstance(currentAccount).processIgnoreStoryReactions(); } else if (dialogId == 0) { MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dismissDate", date).commit(); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 207daf6a19..83eb95d890 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -256,7 +256,11 @@ public static void checkOtherNotificationsChannel() { } NotificationChannel notificationChannel = systemNotificationManager.getNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); if (notificationChannel != null && notificationChannel.getImportance() == NotificationManager.IMPORTANCE_NONE) { - systemNotificationManager.deleteNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); + try { + systemNotificationManager.deleteNotificationChannel(OTHER_NOTIFICATIONS_CHANNEL); + } catch (Exception e) { + FileLog.e(e); + } OTHER_NOTIFICATIONS_CHANNEL = null; notificationChannel = null; } @@ -322,7 +326,7 @@ public void muteUntil(long did, long topicId, int selectedTimeInSeconds) { SharedPreferences.Editor editor = preferences.edit(); long flags; boolean override = topicId != 0; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); String sharedPrefKey = NotificationsController.getSharedPrefKey(did, topicId); if (selectedTimeInSeconds == Integer.MAX_VALUE) { @@ -567,6 +571,8 @@ public void removeDeletedMessagesFromNotifications(LongSparseArray { + boolean changed = false; + for (int i = 0; i < pushMessages.size(); ++i) { + MessageObject msgObject = pushMessages.get(i); + if (msgObject.isStoryReactionPush && Math.abs(msgObject.getId()) == storyId) { + pushMessages.remove(i); + SparseArray msgs = pushMessagesDict.get(msgObject.getDialogId()); + if (msgs != null) msgs.remove(msgObject.getId()); + if (msgs != null && msgs.size() <= 0) pushMessagesDict.remove(msgObject.getDialogId()); + ArrayList ids = new ArrayList<>(); + ids.add(msgObject.getId()); + getMessagesStorage().deletePushMessages(msgObject.getDialogId(), ids); + i--; + changed = true; + } + } + if (changed) { + showOrUpdateNotification(false); + } + }); + } + public void processDeleteStory(long dialogId, int storyId) { notificationsQueue.postRunnable(() -> { boolean changed = false; @@ -779,6 +810,27 @@ public void processIgnoreStories() { }); } + public void processIgnoreStoryReactions() { + notificationsQueue.postRunnable(() -> { + boolean changed = false; + for (int i = 0; i < pushMessages.size(); ++i) { + MessageObject msg = pushMessages.get(i); + if (msg != null && msg.isStoryReactionPush) { + pushMessages.remove(i); + i--; + SparseArray arr = pushMessagesDict.get(msg.getDialogId()); + if (arr != null) arr.remove(msg.getId()); + if (arr != null && arr.size() <= 0) pushMessagesDict.remove(msg.getDialogId()); + changed = true; + } + } + getMessagesStorage().deleteAllStoryReactionPushMessages(); + if (changed) { + showOrUpdateNotification(false); + } + }); + } + public void processIgnoreStories(long dialogId) { notificationsQueue.postRunnable(() -> { boolean changed = !storyPushMessages.isEmpty(); @@ -791,6 +843,10 @@ public void processIgnoreStories(long dialogId) { }); } + public void processReadStories() { + + } + public void processReadMessages(LongSparseIntArray inbox, long dialogId, int maxDate, int maxId, boolean isPopup) { ArrayList popupArrayRemove = new ArrayList<>(0); notificationsQueue.postRunnable(() -> { @@ -800,13 +856,15 @@ public void processReadMessages(LongSparseIntArray inbox, long dialogId, int max int messageId = inbox.get(key); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == key && messageObject.getId() <= messageId) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == key && messageObject.getId() <= messageId && !messageObject.isStoryReactionPush) { if (isPersonalMessage(messageObject)) { personalCount--; } popupArrayRemove.add(messageObject); long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -828,7 +886,7 @@ public void processReadMessages(LongSparseIntArray inbox, long dialogId, int max if (dialogId != 0 && (maxId != 0 || maxDate != 0)) { for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialogId) { + if (messageObject.getDialogId() == dialogId && !messageObject.isStoryReactionPush) { boolean remove = false; if (maxDate != 0) { if (messageObject.messageOwner.date <= maxDate) { @@ -850,7 +908,9 @@ public void processReadMessages(LongSparseIntArray inbox, long dialogId, int max personalCount--; } long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -882,6 +942,7 @@ public void processReadMessages(LongSparseIntArray inbox, long dialogId, int max } private int addToPopupMessages(ArrayList popupArrayAdd, MessageObject messageObject, long dialogId, boolean isChannel, SharedPreferences preferences) { + if (messageObject.isStoryReactionPush) return 0; int popup = 0; if (!DialogObject.isEncryptedDialog(dialogId)) { if (preferences.getBoolean("custom_" + dialogId, false)) { @@ -921,7 +982,9 @@ public void processEditedMessages(LongSparseArray> edit for (int b = 0, N2 = messages.size(); b < N2; b++) { MessageObject messageObject = messages.get(b); long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -931,7 +994,7 @@ public void processEditedMessages(LongSparseArray> edit break; } MessageObject oldMessage = sparseArray.get(messageObject.getId()); - if (oldMessage != null && oldMessage.isReactionPush) { + if (oldMessage != null && (oldMessage.isReactionPush || oldMessage.isStoryReactionPush)) { oldMessage = null; } if (oldMessage != null) { @@ -1027,7 +1090,9 @@ public void processNewMessages(ArrayList messageObjects, boolean isChannel = false; } long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -1067,7 +1132,7 @@ public void processNewMessages(ArrayList messageObjects, boolean long originalDialogId = dialogId; long topicId = MessageObject.getTopicId(currentAccount, messageObject.messageOwner, getMessagesController().isForum(messageObject)); - if (dialogId == openedDialogId && ApplicationLoader.isScreenOn) { + if (dialogId == openedDialogId && ApplicationLoader.isScreenOn && !messageObject.isStoryReactionPush) { if (!isFcm) { playInChatSound(); } @@ -1092,7 +1157,7 @@ public void processNewMessages(ArrayList messageObjects, boolean } else { int notifyOverride = getNotifyOverride(preferences, dialogId, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialogId, isChannel); + value = isGlobalNotificationsEnabled(dialogId, isChannel, messageObject.isReactionPush, messageObject.isStoryReactionPush); /*if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { FileLog.d("global notify settings for " + dialog_id + " = " + value); }*/ @@ -1173,7 +1238,7 @@ public void processNewMessages(ArrayList messageObjects, boolean int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId); boolean canAddValue; if (notifyOverride == -1) { - canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel); + canAddValue = isGlobalNotificationsEnabled(dialog_id, isChannel, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { canAddValue = notifyOverride != 2; } @@ -1268,7 +1333,7 @@ public void processDialogsUpdateRead(LongSparseIntArray dialogsToUpdate) { if (!forum) { int notifyOverride = getNotifyOverride(preferences, dialogId, 0); if (notifyOverride == -1) { - canAddValue = isGlobalNotificationsEnabled(dialogId); + canAddValue = isGlobalNotificationsEnabled(dialogId, false, false); } else { canAddValue = notifyOverride != 2; } @@ -1308,7 +1373,7 @@ public void processDialogsUpdateRead(LongSparseIntArray dialogsToUpdate) { pushDialogsOverrideMention.remove(dialogId); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == dialogId) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == dialogId && !messageObject.isStoryReactionPush) { if (isPersonalMessage(messageObject)) { personalCount--; } @@ -1422,7 +1487,7 @@ public void processLoadedUnreadMessages(LongSparseArray dialogs, ArrayL } else { int notifyOverride = getNotifyOverride(preferences, dialog_id, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id); + value = isGlobalNotificationsEnabled(dialog_id, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { value = notifyOverride != 2; } @@ -1452,7 +1517,7 @@ public void processLoadedUnreadMessages(LongSparseArray dialogs, ArrayL } else { int notifyOverride = getNotifyOverride(preferences, dialog_id, 0); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id); + value = isGlobalNotificationsEnabled(dialog_id, false, false); } else { value = notifyOverride != 2; } @@ -1495,7 +1560,7 @@ public void processLoadedUnreadMessages(LongSparseArray dialogs, ArrayL } else { int notifyOverride = getNotifyOverride(preferences, dialogId, topicId); if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialogId); + value = isGlobalNotificationsEnabled(dialogId, messageObject.isReactionPush, messageObject.isStoryReactionPush); } else { value = notifyOverride != 2; } @@ -1506,7 +1571,9 @@ public void processLoadedUnreadMessages(LongSparseArray dialogs, ArrayL } if (mid != 0) { long did; - if (messageObject.messageOwner.peer_id.channel_id != 0) { + if (messageObject.isStoryReactionPush) { + did = messageObject.getDialogId(); + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { did = -messageObject.messageOwner.peer_id.channel_id; } else { did = 0; @@ -1953,9 +2020,9 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2025,9 +2092,9 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2097,9 +2164,9 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - return LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, name, mediaPoll.poll.question.text); } else { - return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question); + return LocaleController.formatString("NotificationActionPinnedPollUser", R.string.NotificationActionPinnedPollUser, name, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2439,9 +2506,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationMessageQuiz2", R.string.NotificationMessageQuiz2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageQuiz2", R.string.NotificationMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("NotificationMessageMap", R.string.NotificationMessageMap, name); @@ -2662,9 +2729,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedQuiz2", R.string.NotificationActionPinnedQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2734,9 +2801,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedQuizChannel2", R.string.NotificationActionPinnedQuizChannel2, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question.text); } } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { @@ -2808,9 +2875,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("ChannelMessageQuiz2", R.string.ChannelMessageQuiz2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("ChannelMessageQuiz2", R.string.ChannelMessageQuiz2, name, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question); + msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; @@ -2881,9 +2948,9 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { - msg = LocaleController.formatString("NotificationMessageGroupQuiz2", R.string.NotificationMessageGroupQuiz2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageGroupQuiz2", R.string.NotificationMessageGroupQuiz2, name, chat.title, mediaPoll.poll.question.text); } else { - msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question); + msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question.text); } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { msg = LocaleController.formatString("NotificationMessageGroupGame", R.string.NotificationMessageGroupGame, name, chat.title, messageObject.messageOwner.media.game.title); @@ -2959,7 +3026,7 @@ private void scheduleNotificationRepeat() { private boolean isPersonalMessage(MessageObject messageObject) { return messageObject.messageOwner.peer_id != null && messageObject.messageOwner.peer_id.chat_id == 0 && messageObject.messageOwner.peer_id.channel_id == 0 - && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); + && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) || messageObject.isStoryReactionPush; } private int getNotifyOverride(SharedPreferences preferences, long dialog_id, long topicId) { @@ -3180,6 +3247,8 @@ public void deleteNotificationChannelGlobalInternal(int type, int what) { key = "groups"; } else if (type == TYPE_STORIES) { key = "stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = "reactions"; } else { key = "private"; } @@ -3205,6 +3274,8 @@ public void deleteNotificationChannelGlobalInternal(int type, int what) { key = "groups_ia"; } else if (type == TYPE_STORIES) { key = "stories_ia"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = "reactions_ia"; } else { key = "private_ia"; } @@ -3228,6 +3299,8 @@ public void deleteNotificationChannelGlobalInternal(int type, int what) { overwriteKey = "overwrite_group"; } else if (type == TYPE_STORIES) { overwriteKey = "overwrite_stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + overwriteKey = "overwrite_reactions"; } else { overwriteKey = "overwrite_private"; } @@ -3353,7 +3426,7 @@ private String createNotificationShortcut(NotificationCompat.Builder builder, lo protected void ensureGroupsCreated() { SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); if (groupsCreated == null) { - groupsCreated = preferences.getBoolean("groupsCreated4", false); + groupsCreated = preferences.getBoolean("groupsCreated5", false); } if (!groupsCreated) { try { @@ -3374,7 +3447,12 @@ protected void ensureGroupsCreated() { editor = getAccountInstance().getNotificationsSettings().edit(); } editor.remove("priority_channel").remove("vibrate_channel").remove("ChannelSoundPath").remove("ChannelSound"); - } else if (id.contains("_groups_")) { + } else if (id.contains("_reactions_")) { + if (editor == null) { + editor = getAccountInstance().getNotificationsSettings().edit(); + } + editor.remove("priority_react").remove("vibrate_react").remove("ReactionSoundPath").remove("ReactionSound"); + } else if (id.contains("_groups_")) { if (editor == null) { editor = getAccountInstance().getNotificationsSettings().edit(); } @@ -3404,7 +3482,7 @@ protected void ensureGroupsCreated() { } catch (Exception e) { FileLog.e(e); } - preferences.edit().putBoolean("groupsCreated4", true).commit(); + preferences.edit().putBoolean("groupsCreated5", true).commit(); groupsCreated = true; } if (!channelGroupsCreated) { @@ -3413,6 +3491,7 @@ protected void ensureGroupsCreated() { String groupsId = "groups" + currentAccount; String privateId = "private" + currentAccount; String storiesId = "stories" + currentAccount; + String reactionsId = "reactions" + currentAccount; String otherId = "other" + currentAccount; for (int a = 0, N = list.size(); a < N; a++) { String id = list.get(a).getId(); @@ -3422,17 +3501,19 @@ protected void ensureGroupsCreated() { groupsId = null; } else if (storiesId != null && storiesId.equals(id)) { storiesId = null; + } else if (reactionsId != null && reactionsId.equals(id)) { + reactionsId = null; } else if (privateId != null && privateId.equals(id)) { privateId = null; } else if (otherId != null && otherId.equals(id)) { otherId = null; } - if (channelsId == null && storiesId == null && groupsId == null && privateId == null && otherId == null) { + if (channelsId == null && storiesId == null && reactionsId == null && groupsId == null && privateId == null && otherId == null) { break; } } - if (channelsId != null || groupsId != null || storiesId != null || privateId != null || otherId != null) { + if (channelsId != null || groupsId != null || reactionsId != null || storiesId != null || privateId != null || otherId != null) { TLRPC.User user = getMessagesController().getUser(getUserConfig().getClientUserId()); if (user == null) { getUserConfig().getCurrentUser(); @@ -3452,7 +3533,10 @@ protected void ensureGroupsCreated() { channelGroups.add(new NotificationChannelGroup(groupsId, LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups) + userName)); } if (storiesId != null) { - channelGroups.add(new NotificationChannelGroup(storiesId, LocaleController.getString("NotificationsStories", R.string.NotificationsStories) + userName)); + channelGroups.add(new NotificationChannelGroup(storiesId, LocaleController.getString(R.string.NotificationsStories) + userName)); + } + if (reactionsId != null) { + channelGroups.add(new NotificationChannelGroup(reactionsId, LocaleController.getString(R.string.NotificationsReactions) + userName)); } if (privateId != null) { channelGroups.add(new NotificationChannelGroup(privateId, LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats) + userName)); @@ -3490,6 +3574,9 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ } else if (type == TYPE_STORIES) { groupId = "stories" + currentAccount; overwriteKey = "overwrite_stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + groupId = "reactions" + currentAccount; + overwriteKey = "overwrite_reactions"; } else { groupId = "private" + currentAccount; overwriteKey = "overwrite_private"; @@ -3515,6 +3602,8 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ key = isInApp ? "groups_ia" : "groups"; } else if (type == TYPE_STORIES) { key = isInApp ? "stories_ia" : "stories"; + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + key = isInApp ? "reactions_ia" : "reactions"; } else { key = isInApp ? "private_ia" : "private"; } @@ -3573,6 +3662,9 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ if (!isInApp) { if (type == TYPE_STORIES) { editor.putBoolean("EnableAllStories", false); + } else if (type == TYPE_REACTIONS_MESSAGES) { + editor.putBoolean("EnableReactionsMessages", true); + editor.putBoolean("EnableReactionsStories", true); } else { editor.putInt(getGlobalNotificationsKey(type), Integer.MAX_VALUE); } @@ -3603,6 +3695,9 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ if (isDefault) { if (type == TYPE_STORIES) { editor.putBoolean("EnableAllStories", true); + } else if (type == TYPE_REACTIONS_MESSAGES) { + editor.putBoolean("EnableReactionsMessages", true); + editor.putBoolean("EnableReactionsStories", true); } else { editor.putInt(getGlobalNotificationsKey(type), 0); } @@ -3612,6 +3707,8 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ editor.putInt("priority_group", priority); } else if (type == TYPE_STORIES) { editor.putInt("priority_stories", priority); + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + editor.putInt("priority_react", priority); } else { editor.putInt("priority_messages", priority); } @@ -3640,6 +3737,8 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ editor.putInt("vibrate_group", vibrate ? 0 : 2); } else if (type == TYPE_STORIES) { editor.putInt("vibrate_stories", vibrate ? 0 : 2); + } else if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + editor.putInt("vibrate_react", vibrate ? 0 : 2); } else { editor.putInt("vibrate_messages", vibrate ? 0 : 2); } @@ -3662,6 +3761,8 @@ private String validateChannelId(long dialogId, long topicId, String name, long[ editor.putInt("GroupLed", channelLedColor); } else if (type == TYPE_STORIES) { editor.putInt("StoriesLed", channelLedColor); + } else if (type == TYPE_REACTIONS_STORIES || type == TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionsLed", channelLedColor); } else { editor.putInt("MessagesLed", channelLedColor); } @@ -3879,7 +3980,7 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { int notifyOverride = getNotifyOverride(preferences, override_dialog_id, topicId); boolean value; if (notifyOverride == -1) { - value = isGlobalNotificationsEnabled(dialog_id, isChannel); + value = isGlobalNotificationsEnabled(dialog_id, isChannel, lastMessageObject.isReactionPush, lastMessageObject.isReactionPush); } else { value = notifyOverride != 2; } @@ -3909,6 +4010,9 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { } else { name = chatName; } + if (lastMessageObject != null && (lastMessageObject.isReactionPush || lastMessageObject.isStoryReactionPush) && !preferences.getBoolean("EnableReactionsPreview", true)) { + name = LocaleController.getString("NotificationHiddenName", R.string.NotificationHiddenName); + } String detailText; if (UserConfig.getActivatedAccountsCount() > 1) { @@ -4064,7 +4168,19 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { } boolean vibrateOnlyIfSilent = false; - if (chatId != 0) { + if (lastMessageObject != null && (lastMessageObject.isReactionPush || lastMessageObject.isStoryReactionPush)) { + long soundDocumentId = preferences.getLong("ReactionSoundDocId", 0); + if (soundDocumentId != 0) { + isInternalSoundFile = true; + soundPath = getMediaDataController().ringtoneDataStore.getSoundPath(soundDocumentId); + } else { + soundPath = preferences.getString("ReactionSoundPath", defaultPath); + } + vibrate = preferences.getInt("vibrate_react", 0); + importance = preferences.getInt("priority_react", 1); + ledColor = preferences.getInt("ReactionsLed", 0xff0000ff); + chatType = lastMessageObject.isStoryReactionPush ? TYPE_REACTIONS_STORIES : TYPE_REACTIONS_MESSAGES; + } else if (chatId != 0) { if (isChannel) { long soundDocumentId = preferences.getLong("ChannelSoundDocId", 0); if (soundDocumentId != 0) { @@ -4159,7 +4275,9 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - if (lastMessageObject.isStoryPush) { + if (lastMessageObject.isStoryReactionPush) { + intent.putExtra("storyId", Math.abs(lastMessageObject.getId())); + } else if (lastMessageObject.isStoryPush) { long[] peerIds = new long[storyPushMessages.size()]; for (int i = 0; i < storyPushMessages.size(); ++i) { peerIds[i] = storyPushMessages.get(i).dialogId; @@ -4222,6 +4340,9 @@ private void showOrUpdateNotification(boolean notifyAboutLast) { if (lastMessageObject.isStoryPush) { dismissIntent.putExtra("story", true); } + if (lastMessageObject.isStoryReactionPush) { + dismissIntent.putExtra("storyReaction", true); + } mBuilder.setDeleteIntent(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 1, dismissIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)); } catch (Throwable e) { FileLog.e(e); @@ -4405,6 +4526,8 @@ private void resetNotificationSound(NotificationCompat.Builder notificationBuild editor.putString("GlobalSound", ringtoneName); } else if (chatType == TYPE_STORIES) { editor.putString("StoriesSound", ringtoneName); + } else if (chatType == TYPE_REACTIONS_MESSAGES || chatType == TYPE_REACTIONS_STORIES) { + editor.putString("ReactionSound", ringtoneName); } if (chatType == TYPE_CHANNEL) { editor.putString("ChannelSoundPath", newSound); @@ -4414,6 +4537,8 @@ private void resetNotificationSound(NotificationCompat.Builder notificationBuild editor.putString("GlobalSoundPath", newSound); } else if (chatType == TYPE_STORIES) { editor.putString("StoriesSoundPath", newSound); + } else if (chatType == TYPE_REACTIONS_MESSAGES || chatType == TYPE_REACTIONS_STORIES) { + editor.putString("ReactionSound", newSound); } getNotificationsController().deleteNotificationChannelGlobalInternal(chatType, -1); } else { @@ -4590,7 +4715,7 @@ void call() { photoPath = user.photo.photo_small; } } else if (!DialogObject.isEncryptedDialog(dialogId)) { - canReply = (lastMessageObject != null && !lastMessageObject.isReactionPush) && dialogId != 777000; + canReply = (lastMessageObject != null && !lastMessageObject.isReactionPush && !lastMessageObject.isStoryReactionPush) && dialogId != 777000; if (DialogObject.isUserDialog(dialogId)) { user = getMessagesController().getUser(dialogId); if (user == null) { @@ -4668,6 +4793,11 @@ void call() { name = LocaleController.getString("SecretChatName", R.string.SecretChatName); photoPath = null; } + if (lastMessageObject != null && lastMessageObject.isStoryReactionPush && !preferences.getBoolean("EnableReactionsPreview", true)) { + canReply = false; + name = LocaleController.getString("NotificationHiddenChatName", R.string.NotificationHiddenChatName); + photoPath = null; + } if (waitingForPasscode) { if (DialogObject.isChatDialog(dialogId)) { @@ -5030,7 +5160,9 @@ void call() { intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addCategory(Intent.CATEGORY_LAUNCHER); - if (dialogKey.story) { + if (lastMessageObject != null && lastMessageObject.isStoryReactionPush) { + intent.putExtra("storyId", Math.abs(lastMessageObject.getId())); + } else if (dialogKey.story) { long[] peerIds = new long[storyPushMessages.size()]; for (int i = 0; i < storyPushMessages.size(); ++i) { peerIds[i] = storyPushMessages.get(i).dialogId; @@ -5134,7 +5266,7 @@ void call() { if (wearReplyAction != null) { builder.addAction(wearReplyAction); } - if (!waitingForPasscode && !dialogKey.story) { + if (!waitingForPasscode && !dialogKey.story && (lastMessageObject == null || !lastMessageObject.isStoryReactionPush)) { builder.addAction(readAction); } if (sortedDialogs.size() == 1 && !TextUtils.isEmpty(summary) && !dialogKey.story) { @@ -5461,7 +5593,7 @@ public void setDialogNotificationsSettings(long dialog_id, long topicId, int set SharedPreferences.Editor editor = preferences.edit(); TLRPC.Dialog dialog = MessagesController.getInstance(UserConfig.selectedAccount).dialogs_dict.get(dialog_id); if (setting == SETTING_MUTE_UNMUTE) { - boolean defaultEnabled = isGlobalNotificationsEnabled(dialog_id); + boolean defaultEnabled = isGlobalNotificationsEnabled(dialog_id, false, false); if (defaultEnabled) { editor.remove("notify2_" + NotificationsController.getSharedPrefKey(dialog_id, topicId)); } else { @@ -5579,9 +5711,36 @@ public void updateServerNotificationsSettings(long dialogId, long topicId, boole public final static int TYPE_PRIVATE = 1; public final static int TYPE_CHANNEL = 2; public final static int TYPE_STORIES = 3; + public final static int TYPE_REACTIONS_MESSAGES = 4; + public final static int TYPE_REACTIONS_STORIES = 5; public void updateServerNotificationsSettings(int type) { SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); + if (type == TYPE_REACTIONS_MESSAGES || type == TYPE_REACTIONS_STORIES) { + TLRPC.TL_account_setReactionsNotifySettings req = new TLRPC.TL_account_setReactionsNotifySettings(); + req.settings = new TLRPC.TL_reactionsNotifySettings(); + if (preferences.getBoolean("EnableReactionsMessages", true)) { + req.settings.flags |= 1; + if (preferences.getBoolean("EnableReactionsMessagesContacts", false)) { + req.settings.messages_notify_from = new TLRPC.TL_reactionNotificationsFromContacts(); + } else { + req.settings.messages_notify_from = new TLRPC.TL_reactionNotificationsFromAll(); + } + } + if (preferences.getBoolean("EnableReactionsStories", true)) { + req.settings.flags |= 2; + if (preferences.getBoolean("EnableReactionsStoriesContacts", false)) { + req.settings.stories_notify_from = new TLRPC.TL_reactionNotificationsFromContacts(); + } else { + req.settings.stories_notify_from = new TLRPC.TL_reactionNotificationsFromAll(); + } + } + req.settings.show_previews = preferences.getBoolean("EnableReactionsPreview", true); + req.settings.sound = getInputSound(preferences, "ReactionSound", "ReactionSoundDocId", "ReactionSoundPath"); + getConnectionsManager().sendRequest(req, (response, error) -> { }); + return; + } + TLRPC.TL_account_updateNotifySettings req = new TLRPC.TL_account_updateNotifySettings(); req.settings = new TLRPC.TL_inputPeerNotifySettings(); req.settings.flags = 5; @@ -5642,13 +5801,17 @@ private TLRPC.NotificationSound getInputSound(SharedPreferences preferences, Str } } - public boolean isGlobalNotificationsEnabled(long dialogId) { - return isGlobalNotificationsEnabled(dialogId, null); + public boolean isGlobalNotificationsEnabled(long dialogId, boolean isReaction, boolean isStoryReaction) { + return isGlobalNotificationsEnabled(dialogId, null, isReaction, isStoryReaction); } - public boolean isGlobalNotificationsEnabled(long dialogId, Boolean forceChannel) { + public boolean isGlobalNotificationsEnabled(long dialogId, Boolean forceChannel, boolean isReaction, boolean isStoryReaction) { int type; - if (DialogObject.isChatDialog(dialogId)) { + if (isReaction) { + type = TYPE_REACTIONS_MESSAGES; + } else if (isStoryReaction) { + type = TYPE_REACTIONS_STORIES; + } else if (DialogObject.isChatDialog(dialogId)) { if (forceChannel != null) { if (forceChannel) { type = TYPE_CHANNEL; @@ -5670,6 +5833,12 @@ public boolean isGlobalNotificationsEnabled(long dialogId, Boolean forceChannel) } public boolean isGlobalNotificationsEnabled(int type) { + if (type == TYPE_REACTIONS_MESSAGES) { + return getAccountInstance().getNotificationsSettings().getBoolean("EnableReactionsMessages", true); + } + if (type == TYPE_REACTIONS_STORIES) { + return getAccountInstance().getNotificationsSettings().getBoolean("EnableReactionsStories", true); + } if (type == TYPE_STORIES) { return getAccountInstance().getNotificationsSettings().getBoolean("EnableAllStories", true); } @@ -5697,7 +5866,7 @@ public void muteDialog(long dialog_id, long topicId, boolean mute) { if (mute) { NotificationsController.getInstance(currentAccount).muteUntil(dialog_id, topicId, Integer.MAX_VALUE); } else { - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id, false, false); boolean override = topicId != 0; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences.Editor editor = preferences.edit(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java index 04d171f738..6507ffec18 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsSettingsFacade.java @@ -1,6 +1,8 @@ package org.telegram.messenger; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_STORIES; import android.content.SharedPreferences; @@ -208,6 +210,10 @@ public void applySoundSettings(TLRPC.NotificationSound settings, SharedPreferenc soundPref = "GlobalSound"; soundDocPref = "GlobalSoundDocId"; soundPathPref = "GlobalSoundPath"; + } else if (globalType == TYPE_REACTIONS_MESSAGES || globalType == TYPE_REACTIONS_STORIES) { + soundPref = "ReactionSound"; + soundDocPref = "ReactionSoundDocId"; + soundPathPref = "ReactionSoundPath"; } else { soundPref = "ChannelSound"; soundDocPref = "ChannelSoundDocId"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index f92bbc3561..d8edef4578 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -373,6 +373,8 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon int msg_id; if (custom.has("msg_id")) { msg_id = custom.getInt("msg_id"); + } else if (custom.has("story_id")) { + msg_id = custom.getInt("story_id"); } else { msg_id = 0; } @@ -1199,6 +1201,9 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon } if (messageText != null) { TLRPC.TL_message messageOwner = new TLRPC.TL_message(); + if (loc_key.startsWith("REACT_STORY") && msg_id > 0) { + msg_id = -msg_id; + } messageOwner.id = msg_id; messageOwner.random_id = random_id; messageOwner.message = message1 != null ? message1 : messageText; @@ -1243,7 +1248,8 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon messageObject.messageOwner.reply_to.forum_topic = true; messageObject.messageOwner.reply_to.reply_to_top_id = topicId; } - messageObject.isReactionPush = loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_"); + messageObject.isStoryReactionPush = loc_key.startsWith("REACT_STORY"); + messageObject.isReactionPush = !messageObject.isStoryReactionPush && (loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_")); messageObject.isStoryPush = loc_key.equals("STORY_NOTEXT") || loc_key.equals("STORY_HIDDEN_AUTHOR"); messageObject.isStoryMentionPush = loc_key.equals("MESSAGE_STORY_MENTION"); messageObject.isStoryPushHidden = loc_key.equals("STORY_HIDDEN_AUTHOR"); @@ -1288,107 +1294,117 @@ public static void processRemoteMessage(@PushType int pushType, String data, lon private static String getReactedText(String loc_key, Object[] args) { switch (loc_key) { + case "REACT_HIDDEN": { + return LocaleController.formatString(R.string.PushReactHidden, args); + } case "REACT_TEXT": { - return LocaleController.formatString("PushReactText", R.string.PushReactText, args); + return LocaleController.formatString(R.string.PushReactText, args); } case "REACT_NOTEXT": { - return LocaleController.formatString("PushReactNoText", R.string.PushReactNoText, args); + return LocaleController.formatString(R.string.PushReactNoText, args); } case "REACT_PHOTO": { - return LocaleController.formatString("PushReactPhoto", R.string.PushReactPhoto, args); + return LocaleController.formatString(R.string.PushReactPhoto, args); } case "REACT_VIDEO": { - return LocaleController.formatString("PushReactVideo", R.string.PushReactVideo, args); + return LocaleController.formatString(R.string.PushReactVideo, args); } case "REACT_ROUND": { - return LocaleController.formatString("PushReactRound", R.string.PushReactRound, args); + return LocaleController.formatString(R.string.PushReactRound, args); } case "REACT_DOC": { - return LocaleController.formatString("PushReactDoc", R.string.PushReactDoc, args); + return LocaleController.formatString(R.string.PushReactDoc, args); } case "REACT_STICKER": { - return LocaleController.formatString("PushReactSticker", R.string.PushReactSticker, args); + return LocaleController.formatString(R.string.PushReactSticker, args); } case "REACT_AUDIO": { - return LocaleController.formatString("PushReactAudio", R.string.PushReactAudio, args); + return LocaleController.formatString(R.string.PushReactAudio, args); } case "REACT_CONTACT": { - return LocaleController.formatString("PushReactContect", R.string.PushReactContect, args); + return LocaleController.formatString(R.string.PushReactContect, args); } case "REACT_GEO": { - return LocaleController.formatString("PushReactGeo", R.string.PushReactGeo, args); + return LocaleController.formatString(R.string.PushReactGeo, args); } case "REACT_GEOLIVE": { - return LocaleController.formatString("PushReactGeoLocation", R.string.PushReactGeoLocation, args); + return LocaleController.formatString(R.string.PushReactGeoLocation, args); } case "REACT_POLL": { - return LocaleController.formatString("PushReactPoll", R.string.PushReactPoll, args); + return LocaleController.formatString(R.string.PushReactPoll, args); } case "REACT_QUIZ": { - return LocaleController.formatString("PushReactQuiz", R.string.PushReactQuiz, args); + return LocaleController.formatString(R.string.PushReactQuiz, args); } case "REACT_GAME": { - return LocaleController.formatString("PushReactGame", R.string.PushReactGame, args); + return LocaleController.formatString(R.string.PushReactGame, args); } case "REACT_INVOICE": { - return LocaleController.formatString("PushReactInvoice", R.string.PushReactInvoice, args); + return LocaleController.formatString(R.string.PushReactInvoice, args); } case "REACT_GIF": { - return LocaleController.formatString("PushReactGif", R.string.PushReactGif, args); + return LocaleController.formatString(R.string.PushReactGif, args); } case "REACT_GIVEAWAY": { - return LocaleController.formatString("NotificationReactGiveaway", R.string.NotificationReactGiveaway, args); + return LocaleController.formatString(R.string.NotificationReactGiveaway, args); } case "CHAT_REACT_GIVEAWAY": { - return LocaleController.formatString("NotificationChatReactGiveaway", R.string.NotificationChatReactGiveaway, args); + return LocaleController.formatString(R.string.NotificationChatReactGiveaway, args); } case "CHAT_REACT_TEXT": { - return LocaleController.formatString("PushChatReactText", R.string.PushChatReactText, args); + return LocaleController.formatString(R.string.PushChatReactText, args); } case "CHAT_REACT_NOTEXT": { - return LocaleController.formatString("PushChatReactNotext", R.string.PushChatReactNotext, args); + return LocaleController.formatString(R.string.PushChatReactNotext, args); } case "CHAT_REACT_PHOTO": { - return LocaleController.formatString("PushChatReactPhoto", R.string.PushChatReactPhoto, args); + return LocaleController.formatString(R.string.PushChatReactPhoto, args); } case "CHAT_REACT_VIDEO": { - return LocaleController.formatString("PushChatReactVideo", R.string.PushChatReactVideo, args); + return LocaleController.formatString(R.string.PushChatReactVideo, args); } case "CHAT_REACT_ROUND": { - return LocaleController.formatString("PushChatReactRound", R.string.PushChatReactRound, args); + return LocaleController.formatString(R.string.PushChatReactRound, args); } case "CHAT_REACT_DOC": { - return LocaleController.formatString("PushChatReactDoc", R.string.PushChatReactDoc, args); + return LocaleController.formatString(R.string.PushChatReactDoc, args); } case "CHAT_REACT_STICKER": { - return LocaleController.formatString("PushChatReactSticker", R.string.PushChatReactSticker, args); + return LocaleController.formatString(R.string.PushChatReactSticker, args); } case "CHAT_REACT_AUDIO": { - return LocaleController.formatString("PushChatReactAudio", R.string.PushChatReactAudio, args); + return LocaleController.formatString(R.string.PushChatReactAudio, args); } case "CHAT_REACT_CONTACT": { - return LocaleController.formatString("PushChatReactContact", R.string.PushChatReactContact, args); + return LocaleController.formatString(R.string.PushChatReactContact, args); } case "CHAT_REACT_GEO": { - return LocaleController.formatString("PushChatReactGeo", R.string.PushChatReactGeo, args); + return LocaleController.formatString(R.string.PushChatReactGeo, args); } case "CHAT_REACT_GEOLIVE": { - return LocaleController.formatString("PushChatReactGeoLive", R.string.PushChatReactGeoLive, args); + return LocaleController.formatString(R.string.PushChatReactGeoLive, args); } case "CHAT_REACT_POLL": { - return LocaleController.formatString("PushChatReactPoll", R.string.PushChatReactPoll, args); + return LocaleController.formatString(R.string.PushChatReactPoll, args); } case "CHAT_REACT_QUIZ": { - return LocaleController.formatString("PushChatReactQuiz", R.string.PushChatReactQuiz, args); + return LocaleController.formatString(R.string.PushChatReactQuiz, args); } case "CHAT_REACT_GAME": { - return LocaleController.formatString("PushChatReactGame", R.string.PushChatReactGame, args); + return LocaleController.formatString(R.string.PushChatReactGame, args); } case "CHAT_REACT_INVOICE": { - return LocaleController.formatString("PushChatReactInvoice", R.string.PushChatReactInvoice, args); + return LocaleController.formatString(R.string.PushChatReactInvoice, args); } case "CHAT_REACT_GIF": { - return LocaleController.formatString("PushChatReactGif", R.string.PushChatReactGif, args); + return LocaleController.formatString(R.string.PushChatReactGif, args); + } + /* stories */ + case "REACT_STORY": { + return LocaleController.formatString(R.string.PushReactStory, args); + } + case "REACT_STORY_HIDDEN": { + return LocaleController.formatString(R.string.PushReactStoryHidden, args); } } return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 60f66d2935..68d550df20 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -763,6 +763,7 @@ protected void performSendEncryptedRequest(TLRPC.DecryptedMessage req, TLRPC.Mes AndroidUtilities.runOnUIThread(() -> { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); getSendMessagesHelper().processSentMessage(newMsgObj.id); getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index c040130750..cb1390b94b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -961,7 +961,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else if (message.type == 1) { if (media.file == null) { media.file = file; - if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { + if (media.thumb == null && message.photoSize != null && message.photoSize.location != null && (message.obj == null || message.obj.videoEditedInfo == null || !message.obj.videoEditedInfo.isSticker)) { performSendDelayedMessage(message); } else { performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, null, message.scheduled); @@ -2326,6 +2326,7 @@ public int sendMessage(ArrayList messages, final long peer, boole newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getMediaDataController().increasePeerRaiting(peer); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L, existFlags, scheduleDate != 0); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, message.id, message, peer, 0L, existFlags, scheduleDate != 0); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduleDate != 0); }); @@ -2752,7 +2753,7 @@ public void editMessage(MessageObject messageObject, TLRPC.TL_photo photo, Video delayedMessage.originalPath = originalPath; delayedMessage.type = 2; delayedMessage.obj = messageObject; - if (!document.thumbs.isEmpty()) { + if (!document.thumbs.isEmpty() && (videoEditedInfo == null || !videoEditedInfo.isSticker)) { TLRPC.PhotoSize photoSize = document.thumbs.get(0); if (!(photoSize instanceof TLRPC.TL_photoStrippedSize)) { delayedMessage.photoSize = photoSize; @@ -2970,7 +2971,7 @@ public byte[] isSendingVote(MessageObject messageObject) { return waitingForVote.get(key); } - public int sendVote(final MessageObject messageObject, final ArrayList answers, final Runnable finishRunnable) { + public int sendVote(final MessageObject messageObject, final ArrayList answers, final Runnable finishRunnable) { if (messageObject == null) { return 0; } @@ -2985,7 +2986,7 @@ public int sendVote(final MessageObject messageObject, final ArrayList { int mode = scheduled ? ChatActivity.MODE_SCHEDULED : 0; if (newMsgObj.quick_reply_shortcut_id != 0 || newMsgObj.quick_reply_shortcut != null) { @@ -5874,6 +5880,7 @@ protected void performSendMessageRequestMulti(final TLRPC.TL_messages_sendMultiM AndroidUtilities.runOnUIThread(() -> { getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); @@ -6201,6 +6208,7 @@ protected void performSendMessageRequest(final TLObject req, final MessageObject }); } else { getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); getMessagesStorage().getStorageQueue().postRunnable(() -> { int mode = scheduled ? ChatActivity.MODE_SCHEDULED : 0; if (newMsgObj.quick_reply_shortcut_id != 0 || newMsgObj.quick_reply_shortcut != null) { @@ -6211,6 +6219,7 @@ protected void performSendMessageRequest(final TLObject req, final MessageObject AndroidUtilities.runOnUIThread(() -> { getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer2, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); @@ -6423,7 +6432,7 @@ private void updateMediaPaths(MessageObject newMsgObj, TLRPC.Message sentMessage newMsg.media.document.size = sentMessage.media.document.size; newMsg.media.document.mime_type = sentMessage.media.document.mime_type; - if ((sentMessage.flags & TLRPC.MESSAGE_FLAG_FWD) == 0 && MessageObject.isOut(sentMessage) && !MessageObject.isQuickReply(sentMessage)) { + if ((sentMessage.flags & TLRPC.MESSAGE_FLAG_FWD) == 0 && (MessageObject.isOut(sentMessage) || sentMessage.dialog_id == getUserConfig().getClientUserId()) && !MessageObject.isQuickReply(sentMessage)) { if (MessageObject.isNewGifDocument(sentMessage.media.document)) { boolean save; if (MessageObject.isDocumentHasAttachedStickers(sentMessage.media.document)) { @@ -8194,7 +8203,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, ArrayLis TLRPC.PhotoSize size = null; if (thumb != null) { int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight()); - size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); + size = ImageLoader.scaleAndSaveImage(null, thumb, videoEditedInfo != null && videoEditedInfo.isSticker ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.JPEG, false, side, side, side > 90 ? 80 : 55, isEncrypted, 0, 0, false); if (size != null && size.location != null) { thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index f15b7e11c3..1e8bfce7f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -294,7 +294,7 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static boolean forceDisableTabletMode; public static boolean updateStickersOrderOnSend = true; public static boolean bigCameraForRound; - public static boolean useCamera2; + public static Boolean useCamera2Force; public static boolean useSurfaceInStories; public static boolean photoViewerBlur = true; public static boolean payByInvoice; @@ -1546,7 +1546,7 @@ public static void loadConfig() { updateStickersOrderOnSend = preferences.getBoolean("updateStickersOrderOnSend", true); dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0); bigCameraForRound = preferences.getBoolean("bigCameraForRound", false); - useCamera2 = preferences.getBoolean("useCamera2", BuildVars.DEBUG_VERSION); + useCamera2Force = !preferences.contains("useCamera2Force") ? null : preferences.getBoolean("useCamera2Force", false); useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30); payByInvoice = preferences.getBoolean("payByInvoice", false); photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); @@ -2833,10 +2833,14 @@ public static void toggleRoundCamera() { .apply(); } - public static void toggleUseCamera2() { + public static boolean isUsingCamera2(int currentAccount) { + return useCamera2Force == null ? !MessagesController.getInstance(currentAccount).androidDisableRoundCamera2 : useCamera2Force; + } + + public static void toggleUseCamera2(int currentAccount) { ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) .edit() - .putBoolean("useCamera2", useCamera2 = !useCamera2) + .putBoolean("useCamera2", useCamera2Force = !isUsingCamera2(currentAccount)) .apply(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java index 4eb0e135fc..8d46520325 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java @@ -100,6 +100,7 @@ public static boolean isTranslatable(MessageObject messageObject) { messageObject != null && messageObject.messageOwner != null && !messageObject.isOutOwner() && !messageObject.isRestrictedMessage && + !messageObject.isSponsored() && ( messageObject.type == MessageObject.TYPE_TEXT || messageObject.type == MessageObject.TYPE_VIDEO || @@ -511,7 +512,10 @@ private void checkTranslation(MessageObject messageObject, boolean onScreen, boo final MessageObject finalMessageObject = messageObject; if (finalMessageObject.messageOwner.translatedText == null || !language.equals(finalMessageObject.messageOwner.translatedToLanguage)) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messageTranslating, finalMessageObject); - pushToTranslate(finalMessageObject, language, (text, lang) -> { + pushToTranslate(finalMessageObject, language, (id, text, lang) -> { + if (finalMessageObject.getId() != id) { + FileLog.e("wtf, asked to translate " + finalMessageObject.getId() + " but got " + id + "!"); + } finalMessageObject.messageOwner.translatedToLanguage = lang; finalMessageObject.messageOwner.translatedText = text; if (keepReply) { @@ -680,7 +684,7 @@ private static class PendingTranslation { Runnable runnable; ArrayList messageIds = new ArrayList<>(); ArrayList messageTexts = new ArrayList<>(); - ArrayList> callbacks = new ArrayList<>(); + ArrayList> callbacks = new ArrayList<>(); String language; int delay = GROUPING_TRANSLATIONS_TIMEOUT; @@ -692,9 +696,9 @@ private static class PendingTranslation { private void pushToTranslate( MessageObject message, String language, - Utilities.Callback2 callback + Utilities.Callback3 callback ) { - if (message == null || callback == null) { + if (message == null || message.getId() < 0 || callback == null) { return; } @@ -744,6 +748,7 @@ private void pushToTranslate( source.text = message.messageOwner.message; source.entities = message.messageOwner.entities; } + FileLog.d("pending translation +" + message.getId() + " message"); pendingTranslation.messageTexts.add(source); pendingTranslation.callbacks.add(callback); pendingTranslation.language = language; @@ -768,7 +773,7 @@ private void pushToTranslate( final int reqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { final ArrayList ids; - final ArrayList> callbacks; + final ArrayList> callbacks; final ArrayList texts; synchronized (TranslateController.this) { ids = pendingTranslation1.messageIds; @@ -779,14 +784,14 @@ private void pushToTranslate( ArrayList translated = ((TLRPC.TL_messages_translateResult) res).result; final int count = Math.min(callbacks.size(), translated.size()); for (int i = 0; i < count; ++i) { - callbacks.get(i).run(TranslateAlert2.preprocess(texts.get(i), translated.get(i)), pendingTranslation1.language); + callbacks.get(i).run(ids.get(i), TranslateAlert2.preprocess(texts.get(i), translated.get(i)), pendingTranslation1.language); } } else if (err != null && "TO_LANG_INVALID".equals(err.text)) { toggleTranslatingDialog(dialogId, false); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.getString("TranslationFailedAlert2", R.string.TranslationFailedAlert2)); } else { for (int i = 0; i < callbacks.size(); ++i) { - callbacks.get(i).run(null, pendingTranslation1.language); + callbacks.get(i).run(ids.get(i), null, pendingTranslation1.language); } } synchronized (TranslateController.this) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 2f3cb2cef5..9c0bada5cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -165,7 +165,7 @@ public void saveConfig(boolean withFile) { editor.putBoolean("syncContacts", syncContacts); editor.putBoolean("suggestContacts", suggestContacts); editor.putBoolean("hasSecureData", hasSecureData); - editor.putBoolean("notificationsSettingsLoaded3", notificationsSettingsLoaded); + editor.putBoolean("notificationsSettingsLoaded4", notificationsSettingsLoaded); editor.putBoolean("notificationsSignUpSettingsLoaded", notificationsSignUpSettingsLoaded); editor.putLong("autoDownloadConfigLoadTime", autoDownloadConfigLoadTime); editor.putBoolean("hasValidDialogLoadIds", hasValidDialogLoadIds); @@ -311,7 +311,7 @@ private void checkPremiumSelf(TLRPC.User oldUser, TLRPC.User newUser) { syncContacts = preferences.getBoolean("syncContacts", true); suggestContacts = preferences.getBoolean("suggestContacts", true); hasSecureData = preferences.getBoolean("hasSecureData", false); - notificationsSettingsLoaded = preferences.getBoolean("notificationsSettingsLoaded3", false); + notificationsSettingsLoaded = preferences.getBoolean("notificationsSettingsLoaded4", false); notificationsSignUpSettingsLoaded = preferences.getBoolean("notificationsSignUpSettingsLoaded", false); autoDownloadConfigLoadTime = preferences.getLong("autoDownloadConfigLoadTime", 0); hasValidDialogLoadIds = preferences.contains("2dialogsLoadOffsetId") || preferences.getBoolean("hasValidDialogLoadIds", false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index d19a3bd0dd..31946922e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -582,6 +582,10 @@ public static interface Callback5Return { public ReturnType run(T arg, T2 arg2, T3 arg3, T4 arg4, T5 arg5); } + public static interface IndexedConsumer { + void accept(T t, int index); + } + public static Value getOrDefault(HashMap map, Key key, Value defaultValue) { Value v = map.get(key); if (v == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java index af68fe0eaa..a1e39af6e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java @@ -153,6 +153,7 @@ public static class MediaEntity { public float textViewHeight; public float textViewX; public float textViewY; + public boolean customTextView; public TLRPC.Document document; public Object parentObject; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java index 8f41c63353..c5abe177c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -326,7 +326,7 @@ public static void openUrl(final Context context, Uri uri, final boolean allowCu String token = "autologin_token=" + URLEncoder.encode(AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().autologinToken, "UTF-8"); String url = uri.toString(); int idx = url.indexOf("://"); - String path = idx >= 0 ? url.substring(idx + 3) : url; + String path = idx >= 0 && idx <= 5 && !url.substring(0, idx).contains(".") ? url.substring(idx + 3) : url; String fragment = uri.getEncodedFragment(); String finalPath = fragment == null ? path : path.substring(0, path.indexOf("#" + fragment)); if (finalPath.indexOf('?') >= 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java index 395655f06d..bc37ca6d8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/Camera2Session.java @@ -21,6 +21,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.util.Log; +import android.util.Range; import android.util.Size; import android.util.SizeF; import android.view.Surface; @@ -475,6 +476,11 @@ private void updateCaptureRequest() { captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, isFront ? CameraMetadata.CONTROL_SCENE_MODE_NIGHT_PORTRAIT : CameraMetadata.CONTROL_SCENE_MODE_NIGHT); } + if (recordingVideo) { + captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range(30, 60)); + captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + } + if (sensorSize != null && Math.abs(currentZoom - 1f) >= 0.01f) { final int centerX = sensorSize.width() / 2; final int centerY = sensorSize.height() / 2; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java index b022e74c8c..8237aa8e58 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -42,8 +42,6 @@ import android.os.Message; import android.os.VibrationEffect; import android.os.Vibrator; -import android.text.TextUtils; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.Surface; @@ -55,9 +53,6 @@ import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; - -import com.google.zxing.common.detector.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -66,9 +61,9 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.video.MP4Builder; import org.telegram.messenger.video.MediaCodecVideoConvertor; @@ -124,7 +119,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private int focusAreaSize; private Drawable thumbDrawable; - private final boolean useCamera2 = false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2; + private final boolean useCamera2 = false && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.isUsingCamera2(UserConfig.selectedAccount); private final CameraSessionWrapper[] cameraSession = new CameraSessionWrapper[2]; private CameraSessionWrapper cameraSessionRecording; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java index 59198173ba..c0f4007cb8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java @@ -292,9 +292,12 @@ private DataSource getEncryptedFileDataSource() { return encryptedFileDataSource; } + private FileStreamLoadOperation streamLoadOperation; private DataSource getStreamDataSource() { - FileStreamLoadOperation streamLoadOperation = new FileStreamLoadOperation(); - addListenersToDataSource(streamLoadOperation); + if (streamLoadOperation == null) { + streamLoadOperation = new FileStreamLoadOperation(); + addListenersToDataSource(streamLoadOperation); + } return streamLoadOperation; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java index 6b5b5f0791..9708476cda 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java @@ -53,7 +53,7 @@ public class MediaCodecVideoConvertor { public boolean convertVideo(ConvertVideoParams convertVideoParams) { if (convertVideoParams.isSticker) { - return WebmEncoder.convert(convertVideoParams); + return WebmEncoder.convert(convertVideoParams, 0); } this.callback = convertVideoParams.callback; return convertVideoInternal(convertVideoParams, false, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java index 3dce8ec352..7ff253b8f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/WebmEncoder.java @@ -15,6 +15,7 @@ import android.opengl.GLUtils; import android.os.Build; import android.text.Layout; +import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; @@ -70,10 +71,12 @@ private static native boolean writeFrame( public static native void stop(long ptr); - public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params) { + public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params, int triesLeft) { final int W = params.resultWidth; final int H = params.resultHeight; + final long maxFileSize = 255 * 1024; + final long ptr = createEncoder(params.cacheFile.getAbsolutePath(), W, H, params.framerate, params.bitrate); if (ptr == 0) { return true; @@ -102,7 +105,7 @@ public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params } if (params.callback != null) { - params.callback.didWriteData(params.cacheFile.length(), (float) frame / framesCount); + params.callback.didWriteData(Math.min(maxFileSize, params.cacheFile.length()), (float) frame / framesCount); } if (frame % 3 == 0 && params.callback != null) { @@ -119,11 +122,20 @@ public static boolean convert(MediaCodecVideoConvertor.ConvertVideoParams params } } + long fileSize = params.cacheFile.length(); + if (triesLeft > 0 && fileSize > maxFileSize) { + int oldBitrate = params.bitrate; + params.bitrate *= ((float) maxFileSize / fileSize) * .9f; + params.cacheFile.delete(); + FileLog.d("webm encoded too much, got " + fileSize + ", old bitrate = " + oldBitrate + " new bitrate = " + params.bitrate); + return convert(params, triesLeft - 1); + } + if (params.callback != null) { - params.callback.didWriteData(params.cacheFile.length(), 1f); + params.callback.didWriteData(fileSize, 1f); } - FileLog.d("webm encoded to " + params.cacheFile + " with size=" + params.cacheFile.length()); + FileLog.d("webm encoded to " + params.cacheFile + " with size=" + fileSize + " triesLeft=" + triesLeft); return error; } @@ -139,11 +151,17 @@ public static class FrameDrawer { private final Paint clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); + private final Path clipPath; + public FrameDrawer(MediaCodecVideoConvertor.ConvertVideoParams params) { this.W = params.resultWidth; this.H = params.resultHeight; this.fps = params.framerate; + clipPath = new Path(); + RectF bounds = new RectF(0, 0, W, H); + clipPath.addRoundRect(bounds, W * .125f, H * .125f, Path.Direction.CW); + photo = BitmapFactory.decodeFile(params.videoPath); mediaEntities.addAll(params.mediaEntities); @@ -165,6 +183,8 @@ public FrameDrawer(MediaCodecVideoConvertor.ConvertVideoParams params) { public void draw(Canvas canvas, int frame) { canvas.drawPaint(clearPaint); + canvas.save(); + canvas.clipPath(clipPath); if (photo != null) { canvas.drawBitmap(photo, 0, 0, null); } @@ -173,6 +193,7 @@ public void draw(Canvas canvas, int frame) { VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); drawEntity(canvas, entity, entity.color, time); } + canvas.restore(); } private void drawEntity(Canvas canvas, VideoEditedInfo.MediaEntity entity, int textColor, long time) { @@ -231,7 +252,7 @@ private void initTextEntity(VideoEditedInfo.MediaEntity entity) { editText.setTypeface(typeface); } editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, entity.fontSize); - SpannableString text = new SpannableString(entity.text); + CharSequence text = new SpannableString(entity.text); for (VideoEditedInfo.EmojiEntity e : entity.entities) { if (e.documentAbsolutePath == null) { continue; @@ -267,17 +288,19 @@ public void draw(@NonNull Canvas canvas, CharSequence charSequence, int start, i initStickerEntity(e.entity); } }; - text.setSpan(span, e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ((Spannable) text).setSpan(span, e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - editText.setText(Emoji.replaceEmoji(text, editText.getPaint().getFontMetricsInt(), (int) (editText.getTextSize() * .8f), false)); - editText.setTextColor(entity.color); - CharSequence text2 = editText.getText(); - if (text2 instanceof Spanned) { - Emoji.EmojiSpan[] spans = ((Spanned) text2).getSpans(0, text2.length(), Emoji.EmojiSpan.class); - for (int i = 0; i < spans.length; ++i) { - spans[i].scale = .85f; + text = Emoji.replaceEmoji(text, editText.getPaint().getFontMetricsInt(), (int) (editText.getTextSize() * .8f), false); + if (text instanceof Spanned) { + Emoji.EmojiSpan[] spans = ((Spanned) text).getSpans(0, text.length(), Emoji.EmojiSpan.class); + if (spans != null) { + for (int i = 0; i < spans.length; ++i) { + spans[i].scale = .85f; + } } } + editText.setText(text); + editText.setTextColor(entity.color); int gravity; @@ -365,11 +388,11 @@ private void initStickerEntity(VideoEditedInfo.MediaEntity entity) { entity.bitmap = Bitmap.createBitmap(entity.W, entity.H, Bitmap.Config.ARGB_8888); entity.metadata = new int[3]; entity.ptr = RLottieDrawable.create(entity.text, null, entity.W, entity.H, entity.metadata, false, null, false, 0); - entity.framesPerDraw = entity.metadata[1] / fps; + entity.framesPerDraw = (float) entity.metadata[1] / fps; } else if ((entity.subType & 4) != 0) { entity.looped = false; entity.animatedFileDrawable = new AnimatedFileDrawable(new File(entity.text), true, 0, 0, null, null, null, 0, UserConfig.selectedAccount, true, 512, 512, null); - entity.framesPerDraw = entity.animatedFileDrawable.getFps() / fps; + entity.framesPerDraw = (float) entity.animatedFileDrawable.getFps() / fps; entity.currentFrame = 1; entity.animatedFileDrawable.getNextFrame(true); if (entity.type == VideoEditedInfo.MediaEntity.TYPE_ROUND) { @@ -445,12 +468,12 @@ private void setupMatrix(VideoEditedInfo.MediaEntity entity) { if (bitmap != null) { entity.matrix.postScale(1f / bitmap.getWidth(), 1f / bitmap.getHeight()); } - if ((entity.subType & 2) != 0) { + if (entity.type != VideoEditedInfo.MediaEntity.TYPE_TEXT && (entity.subType & 2) != 0) { entity.matrix.postScale(-1, 1, .5f, .5f); } entity.matrix.postScale(entity.width * W, entity.height * H); entity.matrix.postTranslate(entity.x * W, entity.y * H); - entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width) * W, (entity.x + entity.height) * H); + entity.matrix.postRotate((float) (-entity.rotation / Math.PI * 180), (entity.x + entity.width / 2f) * W, (entity.y + entity.height / 2f) * H); } Path path; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index c5e76fa78f..c0f23685c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -83,7 +83,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 = 177; + public static final int LAYER = 179; public static abstract class EmailVerifyPurpose extends TLObject { @@ -2825,35 +2825,61 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_pollAnswer extends TLObject { + public static class PollAnswer extends TLObject { public static final int constructor = 0x6ca9c2e9; - public String text; + public TL_textWithEntities text = new TL_textWithEntities(); public byte[] option; public String translatedText; // custom - public static TL_pollAnswer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_pollAnswer.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_pollAnswer", constructor)); - } else { - return null; - } + public static PollAnswer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + PollAnswer result = null; + switch (constructor) { + case TL_pollAnswer.constructor: + result = new TL_pollAnswer(); + break; + case TL_pollAnswer_layer178.constructor: + result = new TL_pollAnswer_layer178(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in JSONValue", constructor)); + } + if (result != null) { + result.readParams(stream, exception); } - TL_pollAnswer result = new TL_pollAnswer(); - result.readParams(stream, exception); return result; } + } + + public static class TL_pollAnswer extends PollAnswer { + public static final int constructor = 0xff16e2ca; public void readParams(AbstractSerializedData stream, boolean exception) { - text = stream.readString(exception); + text = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), exception); option = stream.readByteArray(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeString(text); + text.serializeToStream(stream); + stream.writeByteArray(option); + } + } + + public static class TL_pollAnswer_layer178 extends TL_pollAnswer { + public static final int constructor = 0x6ca9c2e9; + + public void readParams(AbstractSerializedData stream, boolean exception) { + text = new TL_textWithEntities(); + text.text = stream.readString(exception); + option = stream.readByteArray(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(text == null ? "" : text.text); stream.writeByteArray(option); } } @@ -6846,6 +6872,7 @@ public static abstract class auth_SentCodeType extends TLObject { public int push_timeout; public int reset_available_period; public int reset_pending_date; + public String beginning; public boolean verifiedFirebase; //custom public static auth_SentCodeType TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -6878,6 +6905,12 @@ public static auth_SentCodeType TLdeserialize(AbstractSerializedData stream, int case 0xe57b1432: result = new TL_auth_sentCodeTypeFirebaseSms(); break; + case 0xa416ac81: + result = new TL_auth_sentCodeTypeSmsWord(); + break; + case 0xb37794af: + result = new TL_auth_sentCodeTypeSmsPhrase(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in auth_SentCodeType", constructor)); @@ -7061,6 +7094,44 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_auth_sentCodeTypeSmsWord extends auth_SentCodeType { + public static final int constructor = 0xa416ac81; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + beginning = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(beginning); + } + } + } + + public static class TL_auth_sentCodeTypeSmsPhrase extends auth_SentCodeType { + public static final int constructor = 0xb37794af; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + beginning = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(beginning); + } + } + } + public static abstract class messages_StickerSetInstallResult extends TLObject { public ArrayList sets = new ArrayList<>(); @@ -11560,9 +11631,6 @@ public static messages_SponsoredMessages TLdeserialize(AbstractSerializedData st case 0xc9ee1d87: result = new TL_messages_sponsoredMessages(); break; - case 0x65a4c7d5: - result = new TL_messages_sponsoredMessagesLayer147(); - break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in messages_SponsoredMessages", constructor)); @@ -11583,80 +11651,6 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_messages_sponsoredMessagesLayer147 extends messages_SponsoredMessages { - public static final int constructor = 0xc9ee1d87; - - public void readParams(AbstractSerializedData stream, boolean 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++) { - TL_sponsoredMessage object = TL_sponsoredMessage.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - messages.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++) { - Chat object = 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++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = messages.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - messages.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - public static class TL_messages_sponsoredMessages extends messages_SponsoredMessages { public static final int constructor = 0xc9ee1d87; @@ -12026,6 +12020,9 @@ public static WebPageAttribute TLdeserialize(AbstractSerializedData stream, int case TL_webPageAttributeStory.constructor: result = new TL_webPageAttributeStory(); break; + case TL_webPageAttributeStickerSet.constructor: + result = new TL_webPageAttributeStickerSet(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in contacts_Contacts", constructor)); @@ -12064,6 +12061,49 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_webPageAttributeStickerSet extends WebPageAttribute { + public final static int constructor = 0x50cc03d3; + + public Peer peer; + public boolean emojis; + public boolean text_color; + public ArrayList stickers = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + emojis = (flags & 1) != 0; + text_color = (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++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stickers.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = emojis ? (flags | 1) : (flags &~ 1); + flags = text_color ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt32(0x1cb5c415); + int count = stickers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stickers.get(a).serializeToStream(stream); + } + } + } + public static class TL_webPageAttributeStory_layer162 extends TL_webPageAttributeStory { public static final int constructor = 0x939a4671; @@ -12807,6 +12847,7 @@ public static abstract class ChatFull extends TLObject { public boolean view_forum_as_messages; public boolean restricted_sponsored; public ChatReactions available_reactions; + public int reactions_limit; public TL_stories.PeerStories stories; public WallPaper wallpaper; public int boosts_applied; @@ -12822,9 +12863,15 @@ public static ChatFull TLdeserialize(AbstractSerializedData stream, int construc case TL_chatFull.constructor: result = new TL_chatFull(); break; + case TL_chatFull_layer177.constructor: + result = new TL_chatFull_layer177(); + break; case TL_channelFull.constructor: result = new TL_channelFull(); break; + case TL_channelFull_layer177.constructor: + result = new TL_channelFull_layer177(); + break; case TL_channelFull_layer176.constructor: result = new TL_channelFull_layer176(); break; @@ -15005,6 +15052,143 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_chatFull extends ChatFull { + public static final int constructor = 0x2633421b; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_set_username = (flags & 128) != 0; + has_scheduled = (flags & 256) != 0; + id = stream.readInt64(exception); + about = stream.readString(exception); + participants = ChatParticipants.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8192) != 0) { + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), 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++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + } + if ((flags & 64) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16384) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 65536) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 131072) != 0) { + requests_pending = stream.readInt32(exception); + } + if ((flags & 131072) != 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++) { + recent_requesters.add(stream.readInt64(exception)); + } + } + if ((flags & 262144) != 0) { + available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 1048576) != 0) { + reactions_limit = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_set_username ? (flags | 128) : (flags &~ 128); + flags = has_scheduled ? (flags | 256) : (flags &~ 256); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeString(about); + participants.serializeToStream(stream); + if ((flags & 4) != 0) { + chat_photo.serializeToStream(stream); + } + notify_settings.serializeToStream(stream); + if ((flags & 8192) != 0) { + exported_invite.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + } + if ((flags & 64) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 4096) != 0) { + call.serializeToStream(stream); + } + if ((flags & 16384) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 32768) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } + if ((flags & 65536) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 131072) != 0) { + stream.writeInt32(requests_pending); + } + if ((flags & 131072) != 0) { + stream.writeInt32(0x1cb5c415); + int count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } + if ((flags & 262144) != 0) { + available_reactions.serializeToStream(stream); + } + if ((flags & 1048576) != 0) { + stream.writeInt32(reactions_limit); + } + } + } + + public static class TL_chatFull_layer177 extends TL_chatFull { public static final int constructor = 0xc9d31138; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -15282,7 +15466,7 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_channelFull extends ChatFull { - public static final int constructor = 0x44c054a7; + public static final int constructor = 0xbbab348d; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15424,6 +15608,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 1073741824) != 0) { available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 8192) != 0) { + reactions_limit = stream.readInt32(exception); + } if ((flags2 & 16) != 0) { stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } @@ -15563,6 +15750,9 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 1073741824) != 0) { available_reactions.serializeToStream(stream); } + if ((flags2 & 8192) != 0) { + stream.writeInt32(reactions_limit); + } if ((flags2 & 16) != 0) { stories.serializeToStream(stream); } @@ -15582,8 +15772,8 @@ public void serializeToStream(AbstractSerializedData stream) { } - public static class TL_channelFull_layer176 extends TL_channelFull { - public static final int constructor = 0x680b773c; + public static class TL_channelFull_layer177 extends TL_channelFull { + public static final int constructor = 0x44c054a7; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15602,6 +15792,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { translations_disabled = (flags2 & 8) != 0; stories_pinned_available = (flags2 & 32) != 0; view_forum_as_messages = (flags2 & 64) != 0; + restricted_sponsored = (flags2 & 2048) != 0; + can_view_revenue = (flags2 & 4096) != 0; id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -15757,6 +15949,8 @@ public void serializeToStream(AbstractSerializedData stream) { flags2 = translations_disabled ? (flags2 | 8) : (flags2 &~ 8); flags2 = stories_pinned_available ? (flags2 | 32) : (flags2 &~ 32); flags2 = view_forum_as_messages ? (flags2 | 64) : (flags2 &~ 64); + flags2 = restricted_sponsored ? (flags2 | 2048) : (flags2 &~ 2048); + flags2 = can_view_revenue ? (flags2 | 4096) : (flags2 &~ 4096); stream.writeInt32(flags2); stream.writeInt64(id); stream.writeString(about); @@ -15878,8 +16072,9 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_channelFull_layer173 extends ChatFull { - public static final int constructor = 0xf2bcb6f; + + public static class TL_channelFull_layer176 extends TL_channelFull { + public static final int constructor = 0x680b773c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16025,6 +16220,15 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags2 & 128) != 0) { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 256) != 0) { + boosts_applied = stream.readInt32(exception); + } + if ((flags2 & 512) != 0) { + boosts_unrestrict = stream.readInt32(exception); + } + if ((flags2 & 1024) != 0) { + emojiset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -16153,11 +16357,20 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags2 & 128) != 0) { wallpaper.serializeToStream(stream); } + if ((flags2 & 256) != 0) { + stream.writeInt32(boosts_applied); + } + if ((flags2 & 512) != 0) { + stream.writeInt32(boosts_unrestrict); + } + if ((flags2 & 1024) != 0) { + emojiset.serializeToStream(stream); + } } } - public static class TL_channelFull_layer167 extends TL_channelFull { - public static final int constructor = 0x723027bd; + public static class TL_channelFull_layer173 extends ChatFull { + public static final int constructor = 0xf2bcb6f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16300,6 +16513,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags2 & 16) != 0) { stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 128) != 0) { + wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -16425,11 +16641,14 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags2 & 16) != 0) { stories.serializeToStream(stream); } + if ((flags2 & 128) != 0) { + wallpaper.serializeToStream(stream); + } } } - public static class TL_channelFull_layer162 extends TL_channelFull { - public static final int constructor = 0xf2355507; + public static class TL_channelFull_layer167 extends TL_channelFull { + public static final int constructor = 0x723027bd; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16446,6 +16665,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { antispam = (flags2 & 2) != 0; participants_hidden = (flags2 & 4) != 0; translations_disabled = (flags2 & 8) != 0; + stories_pinned_available = (flags2 & 32) != 0; + view_forum_as_messages = (flags2 & 64) != 0; id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -16567,6 +16788,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 1073741824) != 0) { available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags2 & 16) != 0) { + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -16584,6 +16808,8 @@ public void serializeToStream(AbstractSerializedData stream) { flags2 = antispam ? (flags2 | 2) : (flags2 &~ 2); flags2 = participants_hidden ? (flags2 | 4) : (flags2 &~ 4); flags2 = translations_disabled ? (flags2 | 8) : (flags2 &~ 8); + flags2 = stories_pinned_available ? (flags2 | 32) : (flags2 &~ 32); + flags2 = view_forum_as_messages ? (flags2 | 64) : (flags2 &~ 64); stream.writeInt32(flags2); stream.writeInt64(id); stream.writeString(about); @@ -16687,11 +16913,14 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 1073741824) != 0) { available_reactions.serializeToStream(stream); } + if ((flags2 & 16) != 0) { + stories.serializeToStream(stream); + } } } - public static class TL_channelFull_layer144 extends ChatFull { - public static final int constructor = 0xea68a619; + public static class TL_channelFull_layer162 extends TL_channelFull { + public static final int constructor = 0xf2355507; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16705,6 +16934,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { blocked = (flags & 4194304) != 0; flags2 = stream.readInt32(exception); can_delete_channel = (flags2 & 1) != 0; + antispam = (flags2 & 2) != 0; + participants_hidden = (flags2 & 4) != 0; + translations_disabled = (flags2 & 8) != 0; id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -16824,17 +17056,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { default_send_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 1073741824) != 0) { - 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++) { - available_reactions_legacy.add(stream.readString(exception)); - } + available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -16850,6 +17072,9 @@ public void serializeToStream(AbstractSerializedData stream) { flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); flags2 = can_delete_channel ? (flags2 | 1) : (flags2 &~ 1); + flags2 = antispam ? (flags2 | 2) : (flags2 &~ 2); + flags2 = participants_hidden ? (flags2 | 4) : (flags2 &~ 4); + flags2 = translations_disabled ? (flags2 | 8) : (flags2 &~ 8); stream.writeInt32(flags2); stream.writeInt64(id); stream.writeString(about); @@ -16951,18 +17176,13 @@ public void serializeToStream(AbstractSerializedData stream) { default_send_as.serializeToStream(stream); } if ((flags & 1073741824) != 0) { - stream.writeInt32(0x1cb5c415); - count = available_reactions_legacy.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeString(available_reactions_legacy.get(a)); - } + available_reactions.serializeToStream(stream); } } } - public static class TL_channelFull_layer139 extends ChatFull { - public static final int constructor = 0xe13c3d20; + public static class TL_channelFull_layer144 extends ChatFull { + public static final int constructor = 0xea68a619; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16974,6 +17194,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { has_scheduled = (flags & 524288) != 0; can_view_stats = (flags & 1048576) != 0; blocked = (flags & 4194304) != 0; + flags2 = stream.readInt32(exception); + can_delete_channel = (flags2 & 1) != 0; id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -17118,6 +17340,8 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); + flags2 = can_delete_channel ? (flags2 | 1) : (flags2 &~ 1); + stream.writeInt32(flags2); stream.writeInt64(id); stream.writeString(about); if ((flags & 1) != 0) { @@ -17228,9 +17452,8 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_channelFull_layer131 extends TL_channelFull { - public static final int constructor = 0x548c3f93; - + public static class TL_channelFull_layer139 extends ChatFull { + public static final int constructor = 0xe13c3d20; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -17265,7 +17488,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 8388608) != 0) { - exported_invite = (TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -17338,6 +17561,41 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 67108864) != 0) { groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 134217728) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 268435456) != 0) { + requests_pending = stream.readInt32(exception); + } + if ((flags & 268435456) != 0) { + 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++) { + recent_requesters.add(stream.readInt64(exception)); + } + } + if ((flags & 536870912) != 0) { + default_send_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 1073741824) != 0) { + 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++) { + available_reactions_legacy.add(stream.readString(exception)); + } + } } public void serializeToStream(AbstractSerializedData stream) { @@ -17433,11 +17691,36 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 67108864) != 0) { groupcall_default_join_as.serializeToStream(stream); } + if ((flags & 134217728) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(requests_pending); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(0x1cb5c415); + count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } + if ((flags & 536870912) != 0) { + default_send_as.serializeToStream(stream); + } + if ((flags & 1073741824) != 0) { + stream.writeInt32(0x1cb5c415); + count = available_reactions_legacy.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(available_reactions_legacy.get(a)); + } + } } } - public static class TL_channelFull_layer122 extends TL_channelFull { - public static final int constructor = 0xef3a6acd; + public static class TL_channelFull_layer131 extends TL_channelFull { + public static final int constructor = 0x548c3f93; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17450,7 +17733,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { has_scheduled = (flags & 524288) != 0; can_view_stats = (flags & 1048576) != 0; blocked = (flags & 4194304) != 0; - id = stream.readInt32(exception); + id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { participants_count = stream.readInt32(exception); @@ -17472,9 +17755,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { unread_count = stream.readInt32(exception); chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); - ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - if (invite instanceof TL_chatInviteExported) { - exported_invite = (TL_chatInviteExported) invite; + if ((flags & 8388608) != 0) { + exported_invite = (TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -17492,7 +17774,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { bot_info.add(object); } if ((flags & 16) != 0) { - migrated_from_chat_id = stream.readInt32(exception); + migrated_from_chat_id = stream.readInt64(exception); } if ((flags & 16) != 0) { migrated_from_max_id = stream.readInt32(exception); @@ -17510,7 +17792,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { folder_id = stream.readInt32(exception); } if ((flags & 16384) != 0) { - linked_chat_id = stream.readInt32(exception); + linked_chat_id = stream.readInt64(exception); } if ((flags & 32768) != 0) { location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -17528,6 +17810,25 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 2097152) != 0) { call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 16777216) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 33554432) != 0) { + 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++) { + pending_suggestions.add(stream.readString(exception)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -17541,7 +17842,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); - stream.writeInt32((int) id); + stream.writeInt64(id); stream.writeString(about); if ((flags & 1) != 0) { stream.writeInt32(participants_count); @@ -17563,10 +17864,8 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(unread_count); chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - if (exported_invite != null) { + if ((flags & 8388608) != 0) { exported_invite.serializeToStream(stream); - } else { - new TLRPC.TL_chatInviteEmpty_layer122().serializeToStream(stream); } stream.writeInt32(0x1cb5c415); int count = bot_info.size(); @@ -17575,7 +17874,7 @@ public void serializeToStream(AbstractSerializedData stream) { bot_info.get(a).serializeToStream(stream); } if ((flags & 16) != 0) { - stream.writeInt32((int) migrated_from_chat_id); + stream.writeInt64(migrated_from_chat_id); } if ((flags & 16) != 0) { stream.writeInt32(migrated_from_max_id); @@ -17593,7 +17892,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(folder_id); } if ((flags & 16384) != 0) { - stream.writeInt32((int) linked_chat_id); + stream.writeInt64(linked_chat_id); } if ((flags & 32768) != 0) { location.serializeToStream(stream); @@ -17611,11 +17910,25 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2097152) != 0) { call.serializeToStream(stream); } + if ((flags & 16777216) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 33554432) != 0) { + stream.writeInt32(0x1cb5c415); + count = pending_suggestions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(pending_suggestions.get(a)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } } } - public static class TL_channelFull_layer121 extends TL_channelFull { - public static final int constructor = 0xf0e6672a; + public static class TL_channelFull_layer122 extends TL_channelFull { + public static final int constructor = 0xef3a6acd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17703,6 +18016,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { stats_dc = stream.readInt32(exception); } pts = stream.readInt32(exception); + if ((flags & 2097152) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -17738,7 +18054,11 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(unread_count); chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - exported_invite.serializeToStream(stream); + if (exported_invite != null) { + exported_invite.serializeToStream(stream); + } else { + new TLRPC.TL_chatInviteEmpty_layer122().serializeToStream(stream); + } stream.writeInt32(0x1cb5c415); int count = bot_info.size(); stream.writeInt32(count); @@ -17779,11 +18099,14 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(stats_dc); } stream.writeInt32(pts); + if ((flags & 2097152) != 0) { + call.serializeToStream(stream); + } } } - public static class TL_channelFull_layer103 extends TL_channelFull { - public static final int constructor = 0x10916653; + public static class TL_channelFull_layer121 extends TL_channelFull { + public static final int constructor = 0xf0e6672a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17792,8 +18115,10 @@ public void readParams(AbstractSerializedData stream, boolean exception) { can_set_username = (flags & 64) != 0; can_set_stickers = (flags & 128) != 0; hidden_prehistory = (flags & 1024) != 0; - can_view_stats = (flags & 4096) != 0; can_set_location = (flags & 65536) != 0; + has_scheduled = (flags & 524288) != 0; + can_view_stats = (flags & 1048576) != 0; + blocked = (flags & 4194304) != 0; id = stream.readInt32(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -17859,6 +18184,15 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 32768) != 0) { location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 131072) != 0) { + slowmode_seconds = stream.readInt32(exception); + } + if ((flags & 262144) != 0) { + slowmode_next_send_date = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + stats_dc = stream.readInt32(exception); + } pts = stream.readInt32(exception); } @@ -17868,8 +18202,10 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_set_username ? (flags | 64) : (flags &~ 64); flags = can_set_stickers ? (flags | 128) : (flags &~ 128); flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); - flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); flags = can_set_location ? (flags | 65536) : (flags &~ 65536); + flags = has_scheduled ? (flags | 524288) : (flags &~ 524288); + flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); + flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); stream.writeInt32((int) id); stream.writeString(about); @@ -17924,12 +18260,167 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 32768) != 0) { location.serializeToStream(stream); } + if ((flags & 131072) != 0) { + stream.writeInt32(slowmode_seconds); + } + if ((flags & 262144) != 0) { + stream.writeInt32(slowmode_next_send_date); + } + if ((flags & 4096) != 0) { + stream.writeInt32(stats_dc); + } stream.writeInt32(pts); } } - public static class TL_channelFull_layer101 extends TL_channelFull { - public static final int constructor = 0x9882e516; + public static class TL_channelFull_layer103 extends TL_channelFull { + public static final int constructor = 0x10916653; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_view_participants = (flags & 8) != 0; + can_set_username = (flags & 64) != 0; + can_set_stickers = (flags & 128) != 0; + hidden_prehistory = (flags & 1024) != 0; + can_view_stats = (flags & 4096) != 0; + can_set_location = (flags & 65536) != 0; + id = stream.readInt32(exception); + about = stream.readString(exception); + if ((flags & 1) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + admins_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + kicked_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + banned_count = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + online_count = stream.readInt32(exception); + } + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + if (invite instanceof TL_chatInviteExported) { + exported_invite = (TL_chatInviteExported) invite; + } + 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++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + if ((flags & 16) != 0) { + migrated_from_chat_id = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + migrated_from_max_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 512) != 0) { + available_min_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 16384) != 0) { + linked_chat_id = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + pts = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_view_participants ? (flags | 8) : (flags &~ 8); + flags = can_set_username ? (flags | 64) : (flags &~ 64); + flags = can_set_stickers ? (flags | 128) : (flags &~ 128); + flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); + flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + flags = can_set_location ? (flags | 65536) : (flags &~ 65536); + stream.writeInt32(flags); + stream.writeInt32((int) id); + stream.writeString(about); + if ((flags & 1) != 0) { + stream.writeInt32(participants_count); + } + if ((flags & 2) != 0) { + stream.writeInt32(admins_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(kicked_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(banned_count); + } + if ((flags & 8192) != 0) { + stream.writeInt32(online_count); + } + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + chat_photo.serializeToStream(stream); + notify_settings.serializeToStream(stream); + exported_invite.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32((int) migrated_from_chat_id); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_max_id); + } + if ((flags & 32) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 256) != 0) { + stickerset.serializeToStream(stream); + } + if ((flags & 512) != 0) { + stream.writeInt32(available_min_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 16384) != 0) { + stream.writeInt32((int) linked_chat_id); + } + if ((flags & 32768) != 0) { + location.serializeToStream(stream); + } + stream.writeInt32(pts); + } + } + + public static class TL_channelFull_layer101 extends TL_channelFull { + public static final int constructor = 0x9882e516; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19585,6 +20076,7 @@ public static class TL_codeSettings extends TLObject { public boolean allow_app_hash; public boolean allow_missed_call; public boolean allow_firebase; + public boolean unknown_number; public ArrayList logout_tokens = new ArrayList<>(); public String token; public boolean app_sandbox; @@ -19609,6 +20101,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { allow_app_hash = (flags & 16) != 0; allow_missed_call = (flags & 32) != 0; allow_firebase = (flags & 128) != 0; + unknown_number = (flags & 512) != 0; if ((flags & 64) != 0) { int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -19640,6 +20133,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = allow_missed_call ? (flags | 32) : (flags &~ 32); flags = allow_firebase ? (flags | 128) : (flags &~ 128); flags = app_sandbox ? (flags | 256) : (flags &~ 256); + flags = unknown_number ? (flags | 512) : (flags &~ 512); stream.writeInt32(flags); if ((flags & 64) != 0) { stream.writeInt32(0x1cb5c415); @@ -31033,6 +31527,7 @@ public static abstract class Document extends TLObject { public ArrayList attributes = new ArrayList<>(); public String file_name_fixed; //custom public String localPath; //custom + public String localThumbPath; public static Document TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Document result = null; @@ -35062,6 +35557,12 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case TL_updateDeleteQuickReplyMessages.constructor: result = new TL_updateDeleteQuickReplyMessages(); break; + case TL_updateNewStoryReaction.constructor: + result = new TL_updateNewStoryReaction(); + break; + case TL_updateBroadcastRevenueTransactions.constructor: + result = new TL_updateBroadcastRevenueTransactions(); + break; } if (result == null && ApplicationLoader.applicationLoaderInstance != null) { result = ApplicationLoader.applicationLoaderInstance.parseTLUpdate(constructor); @@ -40643,8 +41144,8 @@ public static abstract class Poll extends TLObject { public boolean public_voters; public boolean multiple_choice; public boolean quiz; - public String question; - public ArrayList answers = new ArrayList<>(); + public TL_textWithEntities question = new TL_textWithEntities(); + public ArrayList answers = new ArrayList<>(); public int close_period; public int close_date; @@ -40653,13 +41154,16 @@ public static abstract class Poll extends TLObject { public static Poll TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Poll result = null; switch (constructor) { - case 0x86e18161: + case TL_poll.constructor: result = new TL_poll(); break; - case 0xaf746786: + case TL_poll_layer178.constructor: + result = new TL_poll_layer178(); + break; + case TL_poll_toDelete.constructor: result = new TL_poll_toDelete(); break; - case 0xd5529d06: + case TL_poll_layer111.constructor: result = new TL_poll_layer111(); break; } @@ -40672,8 +41176,66 @@ public static Poll TLdeserialize(AbstractSerializedData stream, int constructor, return result; } } - + public static class TL_poll extends Poll { + public static final int constructor = 0x58747131; + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + flags = stream.readInt32(exception); + closed = (flags & 1) != 0; + public_voters = (flags & 2) != 0; + multiple_choice = (flags & 4) != 0; + quiz = (flags & 8) != 0; + question = TL_textWithEntities.TLdeserialize(stream, stream.readInt32(exception), 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++) { + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + answers.add(object); + } + if ((flags & 16) != 0) { + close_period = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + close_date = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + flags = closed ? (flags | 1) : (flags &~ 1); + flags = public_voters ? (flags | 2) : (flags &~ 2); + flags = multiple_choice ? (flags | 4) : (flags &~ 4); + flags = quiz ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + question.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = answers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + answers.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(close_period); + } + if ((flags & 32) != 0) { + stream.writeInt32(close_date); + } + } + } + + public static class TL_poll_layer178 extends TL_poll { public static final int constructor = 0x86e18161; @@ -40684,7 +41246,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = new TL_textWithEntities(); + question.text = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40694,7 +41257,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40716,7 +41279,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -40743,7 +41306,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = new TL_textWithEntities(); + question.text = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40753,7 +41317,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40772,7 +41336,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -40796,7 +41360,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public_voters = (flags & 2) != 0; multiple_choice = (flags & 4) != 0; quiz = (flags & 8) != 0; - question = stream.readString(exception); + question = new TL_textWithEntities(); + question.text = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -40806,7 +41371,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_pollAnswer object = TL_pollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); + PollAnswer object = PollAnswer.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -40822,7 +41387,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = multiple_choice ? (flags | 4) : (flags &~ 4); flags = quiz ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); - stream.writeString(question); + stream.writeString(question == null ? "" : question.text); stream.writeInt32(0x1cb5c415); int count = answers.size(); stream.writeInt32(count); @@ -41877,67 +42442,22 @@ public static ChannelMessagesFilter TLdeserialize(AbstractSerializedData stream, } } - public static class TL_sponsoredWebPage extends TLObject { - public static final int constructor = 0x3db8ec63; - - public int flags; - public String url; - public String site_name; - public Photo photo; - - public static TL_sponsoredWebPage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_sponsoredWebPage.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_sponsoredWebPage", constructor)); - } else { - return null; - } - } - TL_sponsoredWebPage result = new TL_sponsoredWebPage(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - url = stream.readString(exception); - site_name = stream.readString(exception); - if ((flags & 1) != 0) { - photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeString(url); - stream.writeString(site_name); - if ((flags & 1) != 0) { - photo.serializeToStream(stream); - } - } - } - public static class TL_sponsoredMessage extends TLObject { - public static final int constructor = 0xed5383f7; + public static final int constructor = 0xbdedf566; public int flags; public boolean recommended; - public boolean show_peer_photo; public boolean can_report; public byte[] random_id; - public Peer from_id; - public ChatInvite chat_invite; - public String chat_invite_hash; - public int channel_post; - public String start_param; - public BotApp app; - public TL_sponsoredWebPage webpage; + public String url; + public String title; public String message; + public Photo photo; public ArrayList entities = new ArrayList<>(); public String button_text; public String sponsor_info; public String additional_info; + public TL_peerColor color; public static TL_sponsoredMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_sponsoredMessage.constructor != constructor) { @@ -41955,30 +42475,10 @@ public static TL_sponsoredMessage TLdeserialize(AbstractSerializedData stream, i public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); recommended = (flags & 32) != 0; - show_peer_photo = (flags & 64) != 0; can_report = (flags & 4096) != 0; random_id = stream.readByteArray(exception); - if ((flags & 8) != 0) { - from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 16) != 0) { - chat_invite = ChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 16) != 0) { - chat_invite_hash = stream.readString(exception); - } - if ((flags & 4) != 0) { - channel_post = stream.readInt32(exception); - } - if ((flags & 1) != 0) { - start_param = stream.readString(exception); - } - if ((flags & 512) != 0) { - webpage = TL_sponsoredWebPage.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 1024) != 0) { - app = BotApp.TLdeserialize(stream, stream.readInt32(exception), exception); - } + url = stream.readString(exception); + title = stream.readString(exception); message = stream.readString(exception); if ((flags & 2) != 0) { int magic = stream.readInt32(exception); @@ -41997,9 +42497,13 @@ public void readParams(AbstractSerializedData stream, boolean exception) { entities.add(object); } } - if ((flags & 2048) != 0) { - button_text = stream.readString(exception); + if ((flags & 64) != 0) { + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 8192) != 0) { + color = TL_peerColor.TLdeserialize(stream, stream.readInt32(exception), exception); } + button_text = stream.readString(exception); if ((flags & 128) != 0) { sponsor_info = stream.readString(exception); } @@ -42011,31 +42515,11 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = recommended ? (flags | 32) : (flags &~ 32); - flags = show_peer_photo ? (flags | 64) : (flags &~ 64); flags = can_report ? (flags | 4096) : (flags &~ 4096); stream.writeInt32(flags); stream.writeByteArray(random_id); - if ((flags & 8) != 0) { - from_id.serializeToStream(stream); - } - if ((flags & 16) != 0) { - chat_invite.serializeToStream(stream); - } - if ((flags & 16) != 0) { - stream.writeString(chat_invite_hash); - } - if ((flags & 4) != 0) { - stream.writeInt32(channel_post); - } - if ((flags & 1) != 0) { - stream.writeString(start_param); - } - if ((flags & 512) != 0) { - webpage.serializeToStream(stream); - } - if ((flags & 1024) != 0) { - app.serializeToStream(stream); - } + stream.writeString(url); + stream.writeString(title); stream.writeString(message); if ((flags & 2) != 0) { stream.writeInt32(0x1cb5c415); @@ -42045,9 +42529,13 @@ public void serializeToStream(AbstractSerializedData stream) { entities.get(a).serializeToStream(stream); } } - if ((flags & 2048) != 0) { - stream.writeString(button_text); + if ((flags & 64) != 0) { + photo.serializeToStream(stream); } + if ((flags & 8192) != 0) { + color.serializeToStream(stream); + } + stream.writeString(button_text); if ((flags & 128) != 0) { stream.writeString(sponsor_info); } @@ -45019,7 +45507,7 @@ public static class TL_messages_emojiGroups extends messages_EmojiGroups { public static final int constructor = 0x881fb94b; public int hash; - public ArrayList groups = new ArrayList<>(); + public ArrayList groups = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { hash = stream.readInt32(exception); @@ -45032,7 +45520,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_emojiGroup object = TL_emojiGroup.TLdeserialize(stream, stream.readInt32(exception), exception); + EmojiGroup object = EmojiGroup.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -45052,26 +45540,70 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_emojiGroup extends TLObject { - public static final int constructor = 0x7a9abda9; + public static class EmojiGroup extends TLObject { public String title; public long icon_emoji_id; public ArrayList emoticons = new ArrayList<>(); - public static TL_emojiGroup TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_emojiGroup.constructor != constructor) { + public static EmojiGroup TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + EmojiGroup result = null; + switch (constructor) { + case TL_emojiGroup.constructor: + result = new TL_emojiGroup(); + break; + case TL_emojiGroupGreeting.constructor: + result = new TL_emojiGroupGreeting(); + break; + case TL_emojiGroupPremium.constructor: + result = new TL_emojiGroupPremium(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in EmojiGroup", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_emojiGroup extends EmojiGroup { + public static final int constructor = 0x7a9abda9; + + public void readParams(AbstractSerializedData stream, boolean exception) { + title = stream.readString(exception); + icon_emoji_id = stream.readInt64(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_emojiGroup", constructor)); - } else { - return null; + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + emoticons.add(stream.readString(exception)); } - TL_emojiGroup result = new TL_emojiGroup(); - result.readParams(stream, exception); - return result; } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeInt64(icon_emoji_id); + stream.writeInt32(0x1cb5c415); + int count = emoticons.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(emoticons.get(a)); + } + } + } + + public static class TL_emojiGroupGreeting extends EmojiGroup { + public static final int constructor = 0x80d26cc7; + public void readParams(AbstractSerializedData stream, boolean exception) { title = stream.readString(exception); icon_emoji_id = stream.readInt64(exception); @@ -45101,6 +45633,21 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_emojiGroupPremium extends EmojiGroup { + public static final int constructor = 0x93bcf34; + + public void readParams(AbstractSerializedData stream, boolean exception) { + title = stream.readString(exception); + icon_emoji_id = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(title); + stream.writeInt64(icon_emoji_id); + } + } + public static class TL_emojiKeyword extends EmojiKeyword { public static final int constructor = 0xd5b3b9f9; @@ -52233,6 +52780,7 @@ public static abstract class UserFull extends TLObject { public boolean wallpaper_overridden; public boolean contact_require_premium; public boolean read_dates_private; + public boolean sponsored_enabled; public User user; public String about; public TL_contacts_link_layer101 link; @@ -52347,6 +52895,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { contact_require_premium = (flags & 536870912) != 0; read_dates_private = (flags & 1073741824) != 0; flags2 = stream.readInt32(exception); + sponsored_enabled = (flags2 & 128) != 0; id = stream.readInt64(exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -52450,6 +52999,7 @@ public void serializeToStream(AbstractSerializedData stream) { 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); stream.writeInt32(flags2); stream.writeInt64(id); if ((flags & 2) != 0) { @@ -57147,6 +57697,21 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messages_getEmojiStickerGroups extends TLObject { + public static final int constructor = 0x1dd840f5; + + public int hash; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return messages_EmojiGroups.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(hash); + } + } + public static class TL_messages_getEmojiProfilePhotoGroups extends TLObject { public static final int constructor = 0x21a548f3; @@ -58655,6 +59220,7 @@ public static class TL_messages_searchGlobal extends TLObject { public static final int constructor = 0x4bc6589a; public int flags; + public boolean broadcasts_only; public int folder_id; public String q; public MessagesFilter filter; @@ -58671,6 +59237,7 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = broadcasts_only ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); if ((flags & 1) != 0) { stream.writeInt32(folder_id); @@ -62619,10 +63186,12 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_setChatAvailableReactions extends TLObject { - public static final int constructor = 0xfeb16771; + public static final int constructor = 0x5a150bd4; + public int flags; public InputPeer peer; public ChatReactions available_reactions; + public int reactions_limit; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Updates.TLdeserialize(stream, constructor, exception); @@ -62630,8 +63199,12 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); peer.serializeToStream(stream); available_reactions.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(reactions_limit); + } } } @@ -65885,7 +66458,7 @@ public static class TL_photoPathSize extends PhotoSize { public void readParams(AbstractSerializedData stream, boolean exception) { type = stream.readString(exception); bytes = stream.readByteArray(exception); - w = h = 50; + w = h = 512; svgPath = SvgHelper.doPath(SvgHelper.decompress(bytes)); } @@ -75136,6 +75709,42 @@ public void serializeToStream(AbstractSerializedData stream) { } } } + + public static class TL_updateNewStoryReaction extends Update { + public static final int constructor = 0x1824e40b; + + public int story_id; + public Peer peer; + public Reaction reaction; + + public void readParams(AbstractSerializedData stream, boolean exception) { + story_id = stream.readInt32(exception); + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + reaction = Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(story_id); + peer.serializeToStream(stream); + reaction.serializeToStream(stream); + } + } + + public static class TL_updateBroadcastRevenueTransactions extends Update { + public static final int constructor = 0x5c65d358; + + public TL_broadcastRevenueBalances balances; + + public void readParams(AbstractSerializedData stream, boolean exception) { + balances = TL_broadcastRevenueBalances.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + balances.serializeToStream(stream); + } + } public static class TL_updateSavedDialogPinned extends Update { public static final int constructor = 0xaeaf9e74; @@ -76495,8 +77104,9 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_channels_getChannelRecommendations extends TLObject { - public static int constructor = 0x83b70d97; + public static int constructor = 0x25a71742; + public int flags; public InputChannel channel; @Override @@ -76506,7 +77116,10 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - channel.serializeToStream(stream); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + channel.serializeToStream(stream); + } } } @@ -79547,6 +80160,192 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_account_toggleSponsoredMessages extends TLObject { + public static final int constructor = 0xb9d9a38d; + + public boolean enabled; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeBool(enabled); + } + } + + public static class ReactionNotificationsFrom extends TLObject { + public static ReactionNotificationsFrom TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + ReactionNotificationsFrom result = null; + switch (constructor) { + case TL_reactionNotificationsFromContacts.constructor: + result = new TL_reactionNotificationsFromContacts(); + break; + case TL_reactionNotificationsFromAll.constructor: + result = new TL_reactionNotificationsFromAll(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in ReactionNotificationsFrom", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_reactionNotificationsFromContacts extends ReactionNotificationsFrom { + public static final int constructor = 0xbac3a61a; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_reactionNotificationsFromAll extends ReactionNotificationsFrom { + public static final int constructor = 0x4b9e22a0; + + public void readParams(AbstractSerializedData stream, boolean exception) {} + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_reactionsNotifySettings extends TLObject { + public static final int constructor = 0x56e34970; + + public int flags; + public ReactionNotificationsFrom messages_notify_from; + public ReactionNotificationsFrom stories_notify_from; + public NotificationSound sound; + public boolean show_previews; + + public static TL_reactionsNotifySettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_reactionsNotifySettings.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_reactionsNotifySettings", constructor)); + } else { + return null; + } + } + TL_reactionsNotifySettings result = new TL_reactionsNotifySettings(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + messages_notify_from = ReactionNotificationsFrom.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + stories_notify_from = ReactionNotificationsFrom.TLdeserialize(stream, stream.readInt32(exception), exception); + } + sound = NotificationSound.TLdeserialize(stream, stream.readInt32(exception), exception); + show_previews = stream.readBool(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + messages_notify_from.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stories_notify_from.serializeToStream(stream); + } + sound.serializeToStream(stream); + stream.writeBool(show_previews); + } + } + + public static class TL_account_getReactionsNotifySettings extends TLObject { + public static final int constructor = 0x6dd654c; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_reactionsNotifySettings.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_account_setReactionsNotifySettings extends TLObject { + public static final int constructor = 0x316ce548; + + public TL_reactionsNotifySettings settings; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_reactionsNotifySettings.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + settings.serializeToStream(stream); + } + } + + public static class TL_auth_reportMissingCode extends TLObject { + public static final int constructor = 0xcb9deff6; + + public String phone_number; + public String phone_code_hash; + public String mnc; +// public String mcc; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_number); + stream.writeString(phone_code_hash); + stream.writeString(mnc); +// stream.writeString(mcc); + } + } + + public static class TL_broadcastRevenueBalances extends TLObject { + public static final int constructor = 0x8438f1c6; + + public long current_balance; + public long available_balance; + public long overall_revenue; + + public static TL_broadcastRevenueBalances TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_broadcastRevenueBalances.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_broadcastRevenueBalances", constructor)); + } else { + return null; + } + } + TL_broadcastRevenueBalances result = new TL_broadcastRevenueBalances(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + current_balance = stream.readInt64(exception); + available_balance = stream.readInt64(exception); + overall_revenue = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(current_balance); + stream.writeInt64(available_balance); + stream.writeInt64(overall_revenue); + } + } + // NekoX public static class TL_account_setContentSettings extends TLObject { public static int constructor = 0xb574b16b; @@ -79604,4 +80403,5 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } } + } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java index 2b34ec8fa2..88bd2fecb3 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stats.java @@ -780,13 +780,11 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_broadcastRevenueStats extends TLObject { - public static final int constructor = 0xd07b4bad; + public static final int constructor = 0x5407e297; public StatsGraph top_hours_graph; public StatsGraph revenue_graph; - public long current_balance; - public long available_balance; - public long overall_revenue; + public TLRPC.TL_broadcastRevenueBalances balances; public double usd_rate; public static TL_broadcastRevenueStats TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -807,9 +805,7 @@ public static TL_broadcastRevenueStats TLdeserialize(AbstractSerializedData stre public void readParams(AbstractSerializedData stream, boolean exception) { top_hours_graph = StatsGraph.TLdeserialize(stream, stream.readInt32(exception), exception); revenue_graph = StatsGraph.TLdeserialize(stream, stream.readInt32(exception), exception); - current_balance = stream.readInt64(exception); - available_balance = stream.readInt64(exception); - overall_revenue = stream.readInt64(exception); + balances = TLRPC.TL_broadcastRevenueBalances.TLdeserialize(stream, stream.readInt32(exception), exception); usd_rate = stream.readDouble(exception); } @@ -818,9 +814,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); top_hours_graph.serializeToStream(stream); revenue_graph.serializeToStream(stream); - stream.writeInt64(current_balance); - stream.writeInt64(available_balance); - stream.writeInt64(overall_revenue); + balances.serializeToStream(stream); stream.writeDouble(usd_rate); } } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java index 3fce977ca8..373cdc5da6 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java @@ -736,10 +736,12 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_stories_stories extends TLObject { - public static final int constructor = 0x5dd8c3c8; + public static final int constructor = 0x63c3dd0a; + public int flags; public int count; public ArrayList stories = new ArrayList<>(); + public ArrayList pinned_to_top = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -757,6 +759,7 @@ public static TL_stories_stories TLdeserialize(AbstractSerializedData stream, in } public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); count = stream.readInt32(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -773,6 +776,19 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } stories.add(object); } + if ((flags & 1) != 0) { + 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++) { + pinned_to_top.add(stream.readInt32(exception)); + } + } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -807,6 +823,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeInt32(count); stream.writeInt32(0x1cb5c415); int count = stories.size(); @@ -814,6 +831,14 @@ public void serializeToStream(AbstractSerializedData stream) { for (int a = 0; a < count; a++) { stories.get(a).serializeToStream(stream); } + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + count = pinned_to_top.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(pinned_to_top.get(a)); + } + } stream.writeInt32(0x1cb5c415); count = chats.size(); stream.writeInt32(count); @@ -3345,4 +3370,26 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(limit); } } + + public static class TL_togglePinnedToTop extends TLObject { + public static final int constructor = 0xb297e9b; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index b0271a69c9..0eef53ca5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -55,6 +55,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; import org.telegram.ui.Components.BackButtonMenu; import org.telegram.ui.bots.BotWebViewSheet; import org.telegram.ui.Components.Bulletin; @@ -1633,6 +1634,10 @@ public boolean addFragmentToStack(BaseFragment fragment, int position) { } onFragmentStackChanged("addFragmentToStack " + position); } else { + if (position == INavigationLayout.FORCE_ATTACH_VIEW_AS_FIRST) { + position = 0; + attachViewTo(fragment, position); + } fragmentsStack.add(position, fragment); onFragmentStackChanged("addFragmentToStack"); } @@ -1674,6 +1679,35 @@ private void attachView(BaseFragment fragment) { fragment.attachStoryViewer(containerView); } + private void attachViewTo(BaseFragment fragment, int position) { + View fragmentView = fragment.fragmentView; + if (fragmentView == null) { + fragmentView = fragment.createView(parentActivity); + } else { + ViewGroup parent = (ViewGroup) fragmentView.getParent(); + if (parent != null) { + fragment.onRemoveFromParent(); + parent.removeView(fragmentView); + } + } + if (!fragment.hasOwnBackground && fragmentView.getBackground() == null) { + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } + containerView.addView(fragmentView, Utilities.clamp(position, containerView.getChildCount(), 0), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + if (fragment.actionBar != null && fragment.actionBar.shouldAddToContainer()) { + if (removeActionBarExtraHeight) { + fragment.actionBar.setOccupyStatusBar(false); + } + ViewGroup parent = (ViewGroup) fragment.actionBar.getParent(); + if (parent != null) { + parent.removeView(fragment.actionBar); + } + containerView.addView(fragment.actionBar); + fragment.actionBar.setTitleOverlayText(titleOverlayText, titleOverlayTextId, overlayAction); + } + fragment.attachStoryViewer(containerView); + } + private void closeLastFragmentInternalRemoveOld(BaseFragment fragment) { fragment.finishing = true; fragment.onPause(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index 4f2d456723..7568bb1057 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -79,7 +79,7 @@ public class BottomSheet extends Dialog { protected int currentAccount = UserConfig.selectedAccount; protected ViewGroup containerView; - protected ContainerView container; + public ContainerView container; protected boolean keyboardVisible; protected int keyboardHeight; private WindowInsets lastInsets; @@ -590,25 +590,29 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { l += getLeftInset(); } - if (smoothKeyboardAnimationEnabled && startAnimationRunnable == null && keyboardChanged && !dismissed && containerView.getTop() != t) { + if (smoothKeyboardAnimationEnabled && startAnimationRunnable == null && keyboardChanged && !dismissed && containerView.getTop() != t || smoothContainerViewLayoutUntil > 0 && System.currentTimeMillis() < smoothContainerViewLayoutUntil) { containerView.setTranslationY(containerView.getTop() - t); + onSmoothContainerViewLayout(containerView.getTranslationY()); if (keyboardContentAnimator != null) { keyboardContentAnimator.cancel(); } keyboardContentAnimator = ValueAnimator.ofFloat(containerView.getTranslationY(), 0); keyboardContentAnimator.addUpdateListener(valueAnimator -> { containerView.setTranslationY((Float) valueAnimator.getAnimatedValue()); + onSmoothContainerViewLayout(containerView.getTranslationY()); invalidate(); }); keyboardContentAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { containerView.setTranslationY(0); + onSmoothContainerViewLayout(containerView.getTranslationY()); invalidate(); } }); keyboardContentAnimator.setDuration(AdjustPanLayoutHelper.keyboardDuration).setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); keyboardContentAnimator.start(); + smoothContainerViewLayoutUntil = -1; } containerView.layout(l, t, l + containerView.getMeasuredWidth(), t + containerView.getMeasuredHeight()); } @@ -2232,4 +2236,13 @@ public void setImageReceiverNumLevel(int playingImages, int onShowing) { this.playingImagesLayerNum = playingImages; this.openedLayerNum = onShowing; } + + private long smoothContainerViewLayoutUntil = -1; + public void smoothContainerViewLayout() { + smoothContainerViewLayoutUntil = System.currentTimeMillis() + 80; + } + + protected void onSmoothContainerViewLayout(float ty) { + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java index 41e3ed3dc5..ff542dfd98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java @@ -23,6 +23,7 @@ public interface INavigationLayout { int REBUILD_FLAG_REBUILD_LAST = 1, REBUILD_FLAG_REBUILD_ONLY_LAST = 2; int FORCE_NOT_ATTACH_VIEW = -2; + int FORCE_ATTACH_VIEW_AS_FIRST = -3; boolean presentFragment(NavigationParams params); boolean checkTransitionAnimation(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index b810169ff0..1215ca2493 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -3343,6 +3343,11 @@ public void run() { public static Drawable[] chat_pollHintDrawable = new Drawable[2]; public static Drawable[] chat_psaHelpDrawable = new Drawable[2]; + public static Drawable chat_editDrawable; + + public static Drawable chat_timeHintSentDrawable; + public static Drawable chat_timeHintForwardDrawable; + public static Drawable chat_msgCallUpGreenDrawable; public static Drawable chat_msgCallDownRedDrawable; public static Drawable chat_msgCallDownGreenDrawable; @@ -4141,8 +4146,10 @@ public void run() { public static final int key_premiumGradientBackground4 = colorsCount++; public static final int key_premiumGradientBackgroundOverlay = colorsCount++; public static final int key_premiumStartSmallStarsColor = colorsCount++; - public static final int key_premiumStartGradient1 = colorsCount++; - public static final int key_premiumStartGradient2 = colorsCount++; + public static final int key_premiumStarGradient1 = colorsCount++; + public static final int key_premiumStarGradient2 = colorsCount++; + public static final int key_premiumCoinGradient1 = colorsCount++; + public static final int key_premiumCoinGradient2 = colorsCount++; public static final int key_premiumStartSmallStarsColor2 = colorsCount++; public static final int key_premiumGradientBottomSheet1 = colorsCount++; public static final int key_premiumGradientBottomSheet2 = colorsCount++; @@ -4519,8 +4526,8 @@ public void run() { themeAccentExclusionKeys.add(key_premiumGradientBackground3); themeAccentExclusionKeys.add(key_premiumGradientBackground4); themeAccentExclusionKeys.add(key_premiumStartSmallStarsColor); - themeAccentExclusionKeys.add(key_premiumStartGradient1); - themeAccentExclusionKeys.add(key_premiumStartGradient2); + themeAccentExclusionKeys.add(key_premiumStarGradient1); + themeAccentExclusionKeys.add(key_premiumStarGradient2); themeAccentExclusionKeys.add(key_stories_circle1); themeAccentExclusionKeys.add(key_stories_circle2); themeAccentExclusionKeys.add(key_stories_circle_dialog1); @@ -8676,7 +8683,7 @@ public static void createCommonChatResources() { chat_radialProgress2Paint.setStyle(Paint.Style.STROKE); chat_audioTimePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); chat_livePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - chat_livePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + chat_livePaint.setTypeface(Typeface.DEFAULT_BOLD); chat_audioTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); chat_audioTitlePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_audioPerformerPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -8832,6 +8839,11 @@ public static void createChatResources(Context context, boolean fontsOnly) { chat_psaHelpDrawable[a] = resources.getDrawable(R.drawable.msg_psa).mutate(); } + chat_editDrawable = resources.getDrawable(R.drawable.msg_edit).mutate(); + + chat_timeHintSentDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); + chat_timeHintForwardDrawable = resources.getDrawable(R.drawable.mini_forwarded).mutate(); + calllog_msgCallUpRedDrawable = resources.getDrawable(R.drawable.ic_call_made_green_18dp).mutate(); calllog_msgCallUpGreenDrawable = resources.getDrawable(R.drawable.ic_call_made_green_18dp).mutate(); calllog_msgCallDownRedDrawable = resources.getDrawable(R.drawable.ic_call_received_green_18dp).mutate(); @@ -9007,7 +9019,7 @@ public static void createChatResources(Context context, boolean fontsOnly) { chat_contextResult_titleTextPaint.setTextSize(dp(15)); chat_contextResult_descriptionTextPaint.setTextSize(dp(13)); chat_radialProgressPaint.setStrokeWidth(dp(3)); - chat_radialProgress2Paint.setStrokeWidth(dp(2)); + chat_radialProgress2Paint.setStrokeWidth(dp(2.33f)); chat_commentTextPaint.setTextSize(dp(14)); chat_commentTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java index ae53a33873..b9aa6191d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -3,7 +3,6 @@ import static org.telegram.ui.ActionBar.Theme.*; import android.graphics.Color; -import android.util.Log; import android.util.SparseArray; import androidx.core.graphics.ColorUtils; @@ -762,8 +761,10 @@ public static int[] createDefaultColors() { defaultColors[key_premiumGradientBackground3] = 0xffDB5C9D; defaultColors[key_premiumGradientBackground4] = 0xffF38926; defaultColors[key_premiumGradientBackgroundOverlay] = Color.WHITE; - defaultColors[key_premiumStartGradient1] = 0xffFFFFFF; - defaultColors[key_premiumStartGradient2] = 0xffE3ECFA; + defaultColors[key_premiumStarGradient1] = 0xffFFFFFF; + defaultColors[key_premiumStarGradient2] = 0xffE3ECFA; + defaultColors[key_premiumCoinGradient1] = -15436801; + defaultColors[key_premiumCoinGradient2] = -4167942; defaultColors[key_premiumStartSmallStarsColor] = ColorUtils.setAlphaComponent(Color.WHITE, 90); defaultColors[key_premiumStartSmallStarsColor2] = ColorUtils.setAlphaComponent(Color.WHITE, 90); defaultColors[key_premiumGradientBottomSheet1] = 0xff5B9DE7; @@ -1513,8 +1514,10 @@ public static SparseArray createColorKeysMap() { colorKeysMap.put(key_premiumGradientBackground4, "premiumGradientBackground4"); colorKeysMap.put(key_premiumGradientBackgroundOverlay, "premiumGradientBackgroundOverlay"); colorKeysMap.put(key_premiumStartSmallStarsColor, "premiumStartSmallStarsColor"); - colorKeysMap.put(key_premiumStartGradient1, "premiumStarGradient1"); - colorKeysMap.put(key_premiumStartGradient2, "premiumStarGradient2"); + colorKeysMap.put(key_premiumStarGradient1, "premiumStarGradient1"); + colorKeysMap.put(key_premiumStarGradient2, "premiumStarGradient2"); + colorKeysMap.put(key_premiumCoinGradient1, "premiumCoinGradient1"); + colorKeysMap.put(key_premiumCoinGradient2, "premiumCoinGradient2"); colorKeysMap.put(key_premiumStartSmallStarsColor2, "premiumStartSmallStarsColor2"); colorKeysMap.put(key_premiumGradientBottomSheet1, "premiumGradientBottomSheet1"); colorKeysMap.put(key_premiumGradientBottomSheet2, "premiumGradientBottomSheet2"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 3592beff3b..f22c993855 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -65,15 +65,15 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { - private final int VIEW_TYPE_PROFILE_CELL = 0; - private final int VIEW_TYPE_GRAY_SECTION = 1; - private final int VIEW_TYPE_DIALOG_CELL = 2; - private final int VIEW_TYPE_TOPIC_CELL = 3; - private final int VIEW_TYPE_LOADING = 4; - private final int VIEW_TYPE_HASHTAG_CELL = 5; - private final int VIEW_TYPE_CATEGORY_LIST = 6; - private final int VIEW_TYPE_ADD_BY_PHONE = 7; - private final int VIEW_TYPE_INVITE_CONTACT_CELL = 8; + public final static int VIEW_TYPE_PROFILE_CELL = 0; + public final static int VIEW_TYPE_GRAY_SECTION = 1; + public final int VIEW_TYPE_DIALOG_CELL = 2; + public final int VIEW_TYPE_TOPIC_CELL = 3; + public final int VIEW_TYPE_LOADING = 4; + public final int VIEW_TYPE_HASHTAG_CELL = 5; + public final int VIEW_TYPE_CATEGORY_LIST = 6; + public final int VIEW_TYPE_ADD_BY_PHONE = 7; + public final int VIEW_TYPE_INVITE_CONTACT_CELL = 8; private Context mContext; private Runnable searchRunnable; private Runnable searchRunnable2; @@ -1338,6 +1338,12 @@ public boolean isGlobalSearch(int i) { } i -= contactsCount + 1; } + if (localCount + localServerCount > 0 && (getRecentItemsCount() > 0 || !searchTopics.isEmpty())) { + if (i == 0) { + return false; + } + i--; + } if (i >= 0 && i < localCount) { return false; } @@ -1485,12 +1491,23 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { CharSequence username = null; CharSequence name = null; boolean isRecent = false; + boolean isGlobal = isGlobalSearch(position); String un = null; Object obj = getItem(position); if (obj instanceof TLRPC.User) { user = (TLRPC.User) obj; un = UserObject.getPublicUsername(user); + if (un != null && lastSearchText != null && !un.toLowerCase().contains(lastSearchText.toLowerCase())) { + if (user.usernames != null) { + for (int i = 0; i < user.usernames.size(); ++i) { + TLRPC.TL_username u = user.usernames.get(i); + if (u != null && u.active && u.username.toLowerCase().contains(lastSearchText.toLowerCase())) { + un = u.username; + } + } + } + } } else if (obj instanceof TLRPC.Chat) { chat = MessagesController.getInstance(currentAccount).getChat(((TLRPC.Chat) obj).id); if (chat == null) { @@ -1565,7 +1582,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); name = spannableStringBuilder; } - if (un != null && user == null) { + if (un != null && (user == null || isGlobal)) { if (foundUserName.startsWith("@")) { foundUserName = foundUserName.substring(1); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index efbca65d21..3e0c973d39 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -352,6 +352,7 @@ private void resetItems() { } UserConfig me = UserConfig.getInstance(UserConfig.selectedAccount); boolean showDivider = false; + items.add(new Item(16, LocaleController.getString(R.string.MyProfile), R.drawable.left_status_profile)); if (me != null && me.isPremium()) { if (me.getEmojiStatus() != null) { items.add(new Item(15, LocaleController.getString("ChangeEmojiStatus", R.string.ChangeEmojiStatus), R.drawable.msg_status_edit)); @@ -360,14 +361,11 @@ private void resetItems() { } showDivider = true; } - if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { - items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories)); - showDivider = true; - - if (NaConfig.INSTANCE.getDisableDialogsFloatingButton().Bool()) { - items.add(new Item(nkbtnNewStory, LocaleController.getString("RecorderNewStory", R.string.RecorderNewStory), R.drawable.msg_menu_stories)); - } - } +// if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) { +// items.add(new Item(17, LocaleController.getString(R.string.ProfileStories), R.drawable.msg_menu_stories)); +// showDivider = true; +// } + showDivider = true; if (ApplicationLoader.applicationLoaderInstance != null) { if (ApplicationLoader.applicationLoaderInstance.extendDrawer(items)) { showDivider = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index daff53ebae..f950cf40f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -321,8 +321,9 @@ public int getItemCount() { return 2; } else if (currentMessageObject != null) { return 2 + (currentLiveLocations.isEmpty() ? 1 : currentLiveLocations.size() + 3); - } else if (locationType == 2) { - return 2 + currentLiveLocations.size(); + } else if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + return 2 + currentLiveLocations.size() + (currentInfo != null && currentInfo.period != 0x7FFFFFFF ? 1 : 0); } else { if (searching || !searched || places.isEmpty()) { int count = 6; @@ -368,7 +369,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType emptyCell.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, overScrollHeight)); break; case VIEW_TYPE_SEND_LOCATION: - view = new SendLocationCell(mContext, false, resourcesProvider); + view = new SendLocationCell(mContext, false, false, resourcesProvider); break; case VIEW_TYPE_HEADER: view = new HeaderCell(mContext, resourcesProvider); @@ -384,7 +385,13 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view = new LocationPoweredCell(mContext, resourcesProvider); break; case VIEW_TYPE_LIVE_LOCATION: { - SendLocationCell cell = new SendLocationCell(mContext, true, resourcesProvider); + SendLocationCell cell = new SendLocationCell(mContext, true, false, resourcesProvider); + cell.setDialogId(dialogId); + view = cell; + break; + } + case VIEW_TYPE_DELETE_LIVE_LOCATION: { + SendLocationCell cell = new SendLocationCell(mContext, true, true, resourcesProvider); cell.setDialogId(dialogId); view = cell; break; @@ -428,11 +435,12 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType public static final int VIEW_TYPE_LOADING = 4; public static final int VIEW_TYPE_FOOTER = 5; public static final int VIEW_TYPE_LIVE_LOCATION = 6; - public static final int VIEW_TYPE_SHARING = 7; - public static final int VIEW_TYPE_DIRECTION = 8; - public static final int VIEW_TYPE_SHADOW = 9; - public static final int VIEW_TYPE_EMPTY = 10; - public static final int VIEW_TYPE_STORY_LOCATION = 11; + public static final int VIEW_TYPE_DELETE_LIVE_LOCATION = 7; + public static final int VIEW_TYPE_SHARING = 8; + public static final int VIEW_TYPE_DIRECTION = 9; + public static final int VIEW_TYPE_SHADOW = 10; + public static final int VIEW_TYPE_EMPTY = 11; + public static final int VIEW_TYPE_STORY_LOCATION = 12; @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { @@ -493,6 +501,12 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ((LocationLoadingCell) holder.itemView).setLoading(searching); break; case VIEW_TYPE_LIVE_LOCATION: + SendLocationCell cell2 = (SendLocationCell) holder.itemView; + cell2.setHasLocation(gpsLocation != null); + cell2.useDivider = position + 1 < getItemCount() && getItemViewType(position + 1) == VIEW_TYPE_DELETE_LIVE_LOCATION; + cell2.invalidate(); + break; + case VIEW_TYPE_DELETE_LIVE_LOCATION: ((SendLocationCell) holder.itemView).setHasLocation(gpsLocation != null); break; case VIEW_TYPE_SHARING: @@ -504,7 +518,14 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (currentMessageObject != null && position == 1) { locationCell.setDialog(currentMessageObject, gpsLocation, myLocationDenied); } else { - locationCell.setDialog(currentLiveLocations.get(position - (currentMessageObject != null ? 5 : 2)), gpsLocation); + int index = position - (currentMessageObject != null ? 5 : 2); + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + if (currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + index--; + } + if (index < 0 || index >= currentLiveLocations.size()) + return; + locationCell.setDialog(currentLiveLocations.get(index), gpsLocation); } break; case VIEW_TYPE_EMPTY: @@ -549,9 +570,14 @@ public Object getItem(int i) { } else if (i > 4 && i < places.size() + 4) { return currentLiveLocations.get(i - 5); } - } else if (locationType == 2) { - if (i >= 2) { - return currentLiveLocations.get(i - 2); + } else if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + int start = 2; + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + if (currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + start++; + } + if (i >= start) { + return currentLiveLocations.get(i - start); } return null; } else if (locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { @@ -592,6 +618,10 @@ public int getItemViewType(int position) { if (locationType == LocationActivity.LOCATION_TYPE_GROUP) { return VIEW_TYPE_SEND_LOCATION; } + LocationController.SharingLocationInfo currentInfo = null; + if (locationType == LocationActivity.LOCATION_TYPE_LIVE || locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { + currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + } if (currentMessageObject != null) { if (currentLiveLocations.isEmpty()) { if (position == 2) { @@ -609,8 +639,14 @@ public int getItemViewType(int position) { } return VIEW_TYPE_SHARING; } - if (locationType == 2) { + if (locationType == LocationActivity.LOCATION_TYPE_LIVE) { + if (position == 2 && currentInfo != null && currentInfo.period != 0x7FFFFFFF) { + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } if (position == 1) { + if (currentInfo != null && currentInfo.period == 0x7FFFFFFF) { + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } shareLiveLocationPotistion = position; return VIEW_TYPE_LIVE_LOCATION; } else { @@ -620,9 +656,14 @@ public int getItemViewType(int position) { if (locationType == LocationActivity.LOCATION_TYPE_SEND_WITH_LIVE) { if (position == 1) { return VIEW_TYPE_SEND_LOCATION; - } else if (position == 2) { - shareLiveLocationPotistion = position; - return VIEW_TYPE_LIVE_LOCATION; + } else if (position == LocationActivity.LOCATION_TYPE_LIVE) { + if (currentInfo != null) { + shareLiveLocationPotistion = -1; + return VIEW_TYPE_DELETE_LIVE_LOCATION; + } else { + shareLiveLocationPotistion = position; + return VIEW_TYPE_LIVE_LOCATION; + } } else if (position == 3) { return VIEW_TYPE_SHADOW; } else if (position == 4) { @@ -642,7 +683,7 @@ public int getItemViewType(int position) { return VIEW_TYPE_STORY_LOCATION; } if (this.street != null) { - if (position == 2) { + if (position == LocationActivity.LOCATION_TYPE_LIVE) { return VIEW_TYPE_STORY_LOCATION; } position--; @@ -672,7 +713,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { if (viewType == VIEW_TYPE_LIVE_LOCATION) { return !(LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId) == null && gpsLocation == null); } - return viewType == VIEW_TYPE_SEND_LOCATION || viewType == VIEW_TYPE_LOCATION || viewType == VIEW_TYPE_SHARING || viewType == VIEW_TYPE_STORY_LOCATION; + return viewType == VIEW_TYPE_SEND_LOCATION || viewType == VIEW_TYPE_LOCATION || viewType == VIEW_TYPE_SHARING || viewType == VIEW_TYPE_STORY_LOCATION || viewType == VIEW_TYPE_DELETE_LIVE_LOCATION; } private int getThemedColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index fab75be413..af2b0934ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -65,6 +65,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { private int searchPointer; private ArrayList allUnregistredContacts; private ArrayList unregistredContacts = new ArrayList<>(); + private String lastQuery; public SearchAdapter(Context context, LongSparseArray arg1, LongSparseArray selected, boolean usernameSearch, boolean mutual, boolean chats, boolean bots, boolean self, boolean phones, int searchChannelId) { @@ -133,6 +134,7 @@ public void run() { private void processSearch(final String query) { AndroidUtilities.runOnUIThread(() -> { + lastQuery = query; if (allowUsernameSearch) { searchAdapterHelper.queryServerSearch(query, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, -1, 1); } @@ -260,8 +262,8 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { public int getItemCount() { unregistredContactsHeaderRow = -1; int count = searchResult.size(); - unregistredContactsHeaderRow = count; if (!unregistredContacts.isEmpty()) { + unregistredContactsHeaderRow = count; count += unregistredContacts.size() + 1; } @@ -359,7 +361,18 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { String un = null; boolean self = false; if (object instanceof TLRPC.User) { - un = ((TLRPC.User) object).username; + TLRPC.User user = (TLRPC.User) object; + un = UserObject.getPublicUsername((TLRPC.User) object); + if (un != null && lastQuery != null && !un.toLowerCase().contains(lastQuery.toLowerCase())) { + if (user.usernames != null) { + for (int i = 0; i < user.usernames.size(); ++i) { + TLRPC.TL_username u = user.usernames.get(i); + if (u != null && u.active && u.username.toLowerCase().contains(lastQuery.toLowerCase())) { + un = u.username; + } + } + } + } id = ((TLRPC.User) object).id; self = ((TLRPC.User) object).self; } else if (object instanceof TLRPC.Chat) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java index b2aa61e9e9..88c4ad6dbe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarSpan.java @@ -13,6 +13,7 @@ import androidx.annotation.Nullable; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.MessagesController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AvatarDrawable; @@ -21,17 +22,20 @@ public class AvatarSpan extends ReplacementSpan { private final Paint shadowPaint; private final ImageReceiver imageReceiver; private final AvatarDrawable avatarDrawable; - private final int sz; + private float sz; private final int currentAccount; private View parent; - public AvatarSpan(View parent, int currentAccount, int sz) { + public AvatarSpan(View parent, int currentAccount) { + this(parent, currentAccount, 18); + } + + public AvatarSpan(View parent, int currentAccount, float sz) { this.currentAccount = currentAccount; this.imageReceiver = new ImageReceiver(parent); this.avatarDrawable = new AvatarDrawable(); - imageReceiver.setRoundRadius(dp(sz)); - this.sz = sz; + setSize(sz); this.shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); shadowPaint.setShadowLayer(dp(1), 0, dp(.66f), 0x33000000); @@ -39,6 +43,11 @@ public AvatarSpan(View parent, int currentAccount, int sz) { setParent(parent); } + public void setSize(float sz) { + imageReceiver.setRoundRadius(dp(sz)); + this.sz = sz; + } + public void setParent(View parent) { if (this.parent == parent) return; if (this.parent != null) { @@ -88,6 +97,11 @@ public void setUser(TLRPC.User user) { imageReceiver.setForUserOrChat(user, avatarDrawable); } + public void setName(String name) { + avatarDrawable.setInfo(0, name, null, null, null, null); + imageReceiver.setForUserOrChat(null, avatarDrawable); + } + @Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) { return dp(sz); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java index cc6366e02d..191d4dbc7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/BusinessIntroActivity.java @@ -9,16 +9,9 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.text.Editable; -import android.text.InputFilter; -import android.text.InputType; -import android.text.Spanned; import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -29,10 +22,8 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; @@ -40,26 +31,21 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.EditTextCell; import org.telegram.ui.Cells.TextCell; -import org.telegram.ui.Components.AnimatedColor; import org.telegram.ui.Components.AnimatedFloat; -import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.ChatGreetingsView; import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CrossfadeDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; -import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.SizeNotifierFrameLayout; -import org.telegram.ui.Components.Text; import org.telegram.ui.Components.UItem; import org.telegram.ui.Components.UniversalAdapter; import org.telegram.ui.Components.UniversalFragment; -import org.telegram.ui.Stories.StoryViewer; +import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; import org.telegram.ui.Stories.recorder.KeyboardNotifier; import org.telegram.ui.Stories.recorder.PreviewView; @@ -113,6 +99,9 @@ protected CharSequence getTitle() { private boolean stickerRandom = true; private TLRPC.Document sticker = getMediaDataController().getGreetingsSticker(); + private String inputStickerPath; + private TLRPC.InputDocument inputSticker; + private boolean keyboardVisible; @Override @@ -303,8 +292,10 @@ protected void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asCustom(messageEdit)); if (stickerRandom) { items.add(UItem.asButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), getString(R.string.BusinessIntroStickerRandom))); + } else if (inputStickerPath != null) { + items.add(UItem.asStickerButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), inputStickerPath)); } else { - items.add(UItem.asButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), sticker)); + items.add(UItem.asStickerButton(BUTTON_STICKER, getString(R.string.BusinessIntroSticker), sticker)); } items.add(UItem.asShadow(getString(R.string.BusinessIntroInfo))); if (clearVisible = !isEmpty()) { @@ -319,13 +310,6 @@ public boolean isEmpty() { return TextUtils.isEmpty(titleEdit.getText()) && TextUtils.isEmpty(messageEdit.getText()) && stickerRandom; } - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.userInfoDidLoad) { - setValue(); - } - } - private String currentTitle, currentMessage; private long currentSticker; @@ -347,6 +331,7 @@ private void setValue() { } else { titleEdit.setText(currentTitle = ""); messageEdit.setText(currentMessage = ""); + inputSticker = null; sticker = null; } currentSticker = sticker == null ? 0 : sticker.id; @@ -371,14 +356,16 @@ private void setValue() { @Override protected void onClick(UItem item, View view, int position, float x, float y) { if (item.id == BUTTON_STICKER) { - EmojiBottomSheet sheet = new EmojiBottomSheet(getContext(), true, getResourceProvider()); + EmojiBottomSheet sheet = new EmojiBottomSheet(getContext(), true, getResourceProvider(), true); sheet.whenDocumentSelected((parentObject, document, a) -> { stickerRandom = false; AndroidUtilities.cancelRunOnUIThread(updateRandomStickerRunnable); greetingsView.setSticker(sticker = document); ((TextCell) view).setValueSticker(document); checkDone(true, false); + return true; }); + sheet.whenPlusSelected(this::openCustomStickerEditor); showDialog(sheet); } else if (item.id == BUTTON_REMOVE) { titleEdit.setText(""); @@ -405,7 +392,7 @@ public boolean hasChanges() { return ( !TextUtils.equals(titleEdit.getText().toString(), currentTitle == null ? "" : currentTitle) || !TextUtils.equals(messageEdit.getText().toString(), currentMessage == null ? "" : currentMessage) || - (stickerRandom || sticker == null ? 0 : sticker.id) != currentSticker + (stickerRandom || sticker == null ? 0 : sticker.id) != currentSticker || (!stickerRandom && inputSticker != null) ); } @@ -452,9 +439,13 @@ private void processDone() { req.intro = new TLRPC.TL_inputBusinessIntro(); req.intro.title = titleEdit.getText().toString(); req.intro.description = messageEdit.getText().toString(); - if (!stickerRandom && sticker != null) { + if (!stickerRandom && (sticker != null || inputSticker != null)) { req.intro.flags |= 1; - req.intro.sticker = getMessagesController().getInputDocument(sticker); + if (inputSticker != null) { + req.intro.sticker = inputSticker; + } else { + req.intro.sticker = getMessagesController().getInputDocument(sticker); + } } if (userFull != null) { @@ -482,6 +473,9 @@ private void processDone() { doneButtonDrawable.animateToProgress(0f); BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); } else { + if (inputSticker != null) { + getMessagesController().loadFullUser(getUserConfig().getCurrentUser(), 0, true); + } finishFragment(); } })); @@ -503,4 +497,83 @@ public boolean onBackPressed() { } + private void openCustomStickerEditor() { + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(null); + if (getParentActivity() == null) { + return; + } + createChatAttachView(); + chatAttachAlert.getPhotoLayout().loadGalleryPhotos(); + chatAttachAlert.setMaxSelectedPhotos(1, false); + chatAttachAlert.setOpenWithFrontFaceCamera(true); + chatAttachAlert.enableStickerMode(this::setCustomSticker); + chatAttachAlert.init(); + chatAttachAlert.parentThemeDelegate = null; + if (visibleDialog != null) { + chatAttachAlert.show(); + } else { + showDialog(chatAttachAlert); + } + } + + private ChatAttachAlert chatAttachAlert; + private void createChatAttachView() { + if (getParentActivity() == null || getContext() == null) { + return; + } + if (chatAttachAlert == null) { + chatAttachAlert = new ChatAttachAlert(getParentActivity(), this, false, false, true, resourceProvider) { + @Override + public void dismissInternal() { + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + super.dismissInternal(); + } + + @Override + public void onDismissAnimationStart() { + if (chatAttachAlert != null) { + chatAttachAlert.setFocusable(false); + } + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + } + }; + chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { + @Override + public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate, boolean forceDocument) { + + } + @Override + public void doOnIdle(Runnable runnable) { + NotificationCenter.getInstance(currentAccount).doOnIdle(runnable); + } + }); + } + } + + private void setCustomSticker(String localPath, TLRPC.InputDocument inputDocument) { + chatAttachAlert.dismiss(); + + inputStickerPath = localPath; + inputSticker = inputDocument; + + stickerRandom = false; + AndroidUtilities.cancelRunOnUIThread(updateRandomStickerRunnable); + greetingsView.setSticker(inputStickerPath); + checkDone(true, false); + if (listView != null && listView.adapter != null) { + listView.adapter.update(true); + } + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.userInfoDidLoad) { + setValue(); + } + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java index c7a0792a0d..b7bb7881db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/ChatbotsActivity.java @@ -370,7 +370,7 @@ private void onClick(UItem item, View view, int position, float x, float y) { } } - private void clear() { + private void clear(View view) { selectedBot = null; listView.adapter.update(true); checkDone(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java index cb5bb00af4..f1c722f4e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursActivity.java @@ -1,6 +1,7 @@ package org.telegram.ui.Business; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.formatString; import static org.telegram.messenger.LocaleController.getString; import android.content.Context; @@ -20,6 +21,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.TLObject; @@ -298,8 +300,15 @@ public static ArrayList[] getDaysHours(ArrayList= 24 * 60) { days[prevDay].get(days[prevDay].size() - 1).end = 24 * 60 - 1; } + + int periodEnd = Math.min(m - start - 1, 24 * 60 * 2 - 1); + ArrayList nextDay = days[(7 + i + 1) % 7]; + if (periodEnd >= 24 * 60 && !nextDay.isEmpty() && nextDay.get(0).start < periodEnd - 24 * 60) { + periodEnd = 24 * 60 + nextDay.get(0).start - 1; + } + days[i].clear(); - days[i].add(new Period(0, 24 * 60 - 1)); + days[i].add(new Period(0, periodEnd)); } else { int nextDay = (i + 1) % 7; if (!days[i].isEmpty() && !days[nextDay].isEmpty()) { @@ -333,6 +342,44 @@ public static ArrayList fromDaysHours(ArrayList[] days = OpeningHoursActivity.getDaysHours(business_work_hours.weekly_open); + StringBuilder sb = new StringBuilder(); + if (user != null) { + sb.append(formatString(R.string.BusinessHoursCopyHeader, UserObject.getUserName(user))).append("\n"); + } + for (int i = 0; i < days.length; ++i) { + ArrayList periods = days[i]; + String day = DayOfWeek.values()[i].getDisplayName(TextStyle.FULL, LocaleController.getInstance().getCurrentLocale()); + day = day.substring(0, 1).toUpperCase() + day.substring(1); + sb.append(day).append(": "); + if (OpeningHoursActivity.isFull(periods)) { + sb.append(LocaleController.getString(R.string.BusinessHoursProfileOpen)); + } else if (periods.isEmpty()) { + sb.append(LocaleController.getString(R.string.BusinessHoursProfileClose)); + } else { + for (int j = 0; j < periods.size(); ++j) { + if (j > 0) sb.append(", "); + OpeningHoursActivity.Period p = periods.get(j); + sb.append(OpeningHoursActivity.Period.timeToString(p.start)); + sb.append(" - "); + sb.append(OpeningHoursActivity.Period.timeToString(p.end)); + } + } + sb.append("\n"); + } + TLRPC.TL_timezone timezone = TimezonesController.getInstance(currentAccount).findTimezone(business_work_hours.timezone_id); + Calendar calendar = Calendar.getInstance(); + int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; + int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; + int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; + if (utcOffset != 0 && timezone != null) { + sb.append(formatString(R.string.BusinessHoursCopyFooter, TimezonesController.getInstance(currentAccount).getTimezoneName(timezone, true))); + } + return sb.toString(); + } + private void processDone() { if (doneButtonDrawable.getProgress() > 0f) return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java index dfe41aafed..3885fe90d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/OpeningHoursDayActivity.java @@ -132,7 +132,7 @@ private boolean showAddButton() { if (periods.size() >= maxPeriodsCount) { return false; } - return periods.isEmpty() || is24() || periods.get(periods.size() - 1).end < max - 2; + return periods.isEmpty() || is24() || periods.get(periods.size() - 1).end < Math.min(24 * 60 - 2, max - 2); } private void onClick(UItem item, View view, int position, float x, float y) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java index 04038a42a4..e95133cd2f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Business/ProfileHoursCell.java @@ -204,7 +204,7 @@ public void set(TLRPC.TL_businessWorkHours value, boolean expanded, boolean show TLRPC.TL_timezone timezone = timezonesController.findTimezone(value.timezone_id); Calendar calendar = Calendar.getInstance(); - int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; + int currentUtcOffset = calendar.getTimeZone().getOffset(System.currentTimeMillis()) / 1000; int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; switchText.setVisibility(utcOffset != 0 && !is24x7 ? View.VISIBLE : View.GONE); @@ -287,15 +287,15 @@ public void set(TLRPC.TL_businessWorkHours value, boolean expanded, boolean show TextView textView = k == 0 ? timeText[i][a] : labelTimeText[a]; if (i == 0 && !open_now && k == 1) { int opensPeriodTime = -1; - for (int j = 0; j < weekly_open.size(); ++j) { - TLRPC.TL_businessWeeklyOpen weekly = weekly_open.get(j); + for (int j = 0; j < adapted_weekly_open.size(); ++j) { + TLRPC.TL_businessWeeklyOpen weekly = adapted_weekly_open.get(j); if (nowPeriodTime < weekly.start_minute) { opensPeriodTime = weekly.start_minute; break; } } - if (opensPeriodTime == -1 && !weekly_open.isEmpty()) { - opensPeriodTime = weekly_open.get(0).start_minute; + if (opensPeriodTime == -1 && !adapted_weekly_open.isEmpty()) { + opensPeriodTime = adapted_weekly_open.get(0).start_minute; } if (opensPeriodTime == -1) { textView.setText(getString(R.string.BusinessHoursProfileClose)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 978d0aeffb..a041c89366 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -189,7 +189,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private LinearLayoutManager layoutManager; AlertDialog progressDialog; - private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true, true }; + private boolean[] selected = new boolean[] { true, true, true, true, true, true, true, true, true, true, true }; private long databaseSize = -1; private long cacheSize = -1, cacheEmojiSize = -1, cacheTempSize = -1, cacheCustomEmojiSize = -1; private long documentsSize = -1; @@ -198,6 +198,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe private long musicSize = -1; private long photoSize = -1; private long videoSize = -1; + private long logsSize = -1; private long stickersCacheSize = -1; private long totalSize = -1; private long totalDeviceSize = -1; @@ -289,7 +290,11 @@ public static void calculateTotalSize(Utilities.Callback onDone) { stickersCacheSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 3); long audioSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_AUDIO), 0); long storiesSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES), 0); - final long totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; + long logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + if (!BuildVars.DEBUG_VERSION && logsSize < 1024 * 1024 * 256) { + logsSize = 0; + } + final long totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize + logsSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); if (!canceled) { AndroidUtilities.runOnUIThread(() -> { @@ -394,6 +399,13 @@ public boolean onFragmentCreate() { if (canceled) { return; } + logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + if (!BuildVars.DEBUG_VERSION && logsSize < 1024 * 1024 * 256) { + logsSize = 0; + } + if (canceled) { + return; + } documentsSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), 1); documentsSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), 1); if (canceled) { @@ -423,7 +435,7 @@ public boolean onFragmentCreate() { if (canceled) { return; } - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + storiesSize + stickersCacheSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + logsSize + audioSize + photoSize + documentsSize + musicSize + storiesSize + stickersCacheSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); File path = EnvUtil.getTelegramPath(); @@ -475,13 +487,13 @@ public boolean onFragmentCreate() { private void updateChart() { if (cacheChart != null) { if (!calculating && totalSize > 0) { - CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[10]; + CacheChart.SegmentSize[] segments = new CacheChart.SegmentSize[11]; for (int i = 0; i < itemInners.size(); ++i) { ItemInner item = itemInners.get(i); if (item.viewType == VIEW_TYPE_SECTION) { if (item.index < 0) { if (collapsed) { - segments[9] = CacheChart.SegmentSize.of(item.size, selected[9]); + segments[10] = CacheChart.SegmentSize.of(item.size, selected[10]); } } else { segments[item.index] = CacheChart.SegmentSize.of(item.size, selected[item.index]); @@ -767,19 +779,22 @@ private void updateRows(boolean animated) { if (cacheTempSize > 0) { sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalMiscellaneousCache), 8, cacheTempSize, Theme.key_statisticChartLine_purple)); } + if (logsSize > 0) { + sections.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalLogsCache), 9, logsSize, Theme.key_statisticChartLine_golden)); + } if (!sections.isEmpty()) { Collections.sort(sections, (a, b) -> Long.compare(b.size, a.size)); sections.get(sections.size() - 1).last = true; hasCache = true; if (tempSizes == null) { - tempSizes = new float[10]; + tempSizes = new float[11]; } for (int i = 0; i < tempSizes.length; ++i) { tempSizes[i] = (float) size(i); } if (percents == null) { - percents = new int[10]; + percents = new int[11]; } AndroidUtilities.roundPercents(tempSizes, percents); @@ -793,7 +808,7 @@ private void updateRows(boolean animated) { sum += sections.get(i).size; sumPercents += percents[sections.get(i).index]; } - percents[9] = sumPercents; + percents[10] = sumPercents; itemInners.add(ItemInner.asCheckBox(LocaleController.getString(R.string.LocalOther), -1, sum, Theme.key_statisticChartLine_golden)); if (!collapsed) { itemInners.addAll(sections.subList(MAX_NOT_COLLAPSED, sections.size())); @@ -999,7 +1014,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre long clearedSize = 0; boolean allItemsClear = true; final int[] clearDirI = new int[] { 0 }; - int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0) + (selected[8] ? 1 : 0); + int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0) + (selected[8] ? 1 : 0) + (selected[9] ? 1 : 0); long time = System.currentTimeMillis(); Utilities.Callback updateProgress = t -> { onProgress.run(clearDirI[0] / (float) clearDirCount + (1f / clearDirCount) * MathUtils.clamp(t, 0, 1), false); @@ -1008,7 +1023,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre final long now = System.currentTimeMillis(); onProgress.run(clearDirI[0] / (float) clearDirCount, now - time > 250); }; - for (int a = 0; a < 9; a++) { + for (int a = 0; a < 10; a++) { if (!selected[a]) { allItemsClear = false; continue; @@ -1046,12 +1061,18 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre clearedSize += cacheTempSize; documentsMusicType = 4; type = FileLoader.MEDIA_DIR_CACHE; + } else if (a == 9) { + clearedSize += logsSize; + documentsMusicType = 1; + type = 0; } if (type == -1) { continue; } File file; - if (type == 100) { + if (a == 9) { + file = AndroidUtilities.getLogsDir(); + } else if (type == 100) { file = new File(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), "acache"); } else { file = FileLoader.checkDirectory(type); @@ -1094,7 +1115,9 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre next.run(); } - if (type == FileLoader.MEDIA_DIR_CACHE) { + if (a == 9) { + logsSize = getDirectorySize(AndroidUtilities.getLogsDir(), 1); + } else if (type == FileLoader.MEDIA_DIR_CACHE) { cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 5); cacheTempSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), 4); imagesCleared = true; @@ -1137,7 +1160,7 @@ private void cleanupFoldersInternal(Utilities.Callback2 onProgre } } final boolean imagesClearedFinal = imagesCleared; - totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; + totalSize = lastTotalSizeCalculated = cacheSize + cacheTempSize + logsSize + videoSize + audioSize + photoSize + documentsSize + musicSize + stickersCacheSize + storiesSize; lastTotalSizeCalculatedTime = System.currentTimeMillis(); Arrays.fill(selected, true); @@ -1229,13 +1252,14 @@ private long size(int type) { case 6: return stickersCacheSize; case 7: return cacheSize; case 8: return cacheTempSize; + case 9: return logsSize; default: return 0; } } private int sectionsSelected() { int count = 0; - for (int i = 0; i < 9; ++i) { + for (int i = 0; i < 10; ++i) { if (selected[i] && size(i) > 0) { count++; } @@ -2112,7 +2136,8 @@ public void updateSize() { (selected[5] ? storiesSize : 0) + (selected[6] ? stickersCacheSize : 0) + (selected[7] ? cacheSize : 0) + - (selected[8] ? cacheTempSize : 0) + (selected[8] ? cacheTempSize : 0) + + (selected[9] ? logsSize : 0) ); setSize( isAllSectionsSelected(), @@ -2625,7 +2650,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { final ItemInner item = itemInners.get(position); switch (holder.getItemViewType()) { case VIEW_TYPE_CHART: -// updateChart(); + updateChart(); break; case VIEW_TYPE_CHART_HEADER: if (cacheChartHeader != null && !calculating) { @@ -2712,7 +2737,6 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { headerCell.setTopMargin(itemInners.get(position).headerTopMargin); headerCell.setBottomMargin(itemInners.get(position).headerBottomMargin); break; - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java index e0550c8053..b6e9edd4ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java @@ -114,7 +114,7 @@ public void setObject(TLObject object) { } else { TLRPC.Chat chat = (TLRPC.Chat) object; avatarDrawable.setInfo(chat); - infoTextView.setText(chat.title); + infoTextView.setText(chat == null ? "" : chat.title); imageView.setForUserOrChat(chat, avatarDrawable); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index d55b75dcbc..6d363c05e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -76,6 +76,7 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChannelAdminLogActivity; import org.telegram.ui.ChatBackgroundDrawable; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -89,11 +90,13 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PhotoViewer; +import org.telegram.ui.ProfileActivity; import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.UploadingDotsSpannable; import org.telegram.ui.Stories.recorder.HintView2; @@ -102,6 +105,7 @@ import tw.nekomimi.nekogram.NekoConfig; import xyz.nextalone.nagram.NaConfig; +import java.nio.channels.Channel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -465,6 +469,17 @@ public void setMessageObject(MessageObject messageObject, boolean force) { if (messageObject.type != MessageObject.TYPE_ACTION_WALLPAPER) { wallpaperPreviewDrawable = null; } + if (messageObject.actionDeleteGroupEventId != -1) { + ScaleStateListAnimator.apply(this, .02f, 1.2f); + overriddenMaxWidth = Math.max(dp(250), HintView2.cutInFancyHalf(messageObject.messageText, (TextPaint) getThemedPaint(Theme.key_paint_chatActionText))); + ProfileActivity.ShowDrawable showDrawable = ChannelAdminLogActivity.findDrawable(messageObject.messageText); + if (showDrawable != null) { + showDrawable.setView(this); + } + } else { + ScaleStateListAnimator.reset(this); + overriddenMaxWidth = 0; + } if (messageObject.isStoryMention()) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.media.user_id); avatarDrawable.setInfo(currentAccount, user); @@ -1823,7 +1838,7 @@ public void drawBackground(Canvas canvas, boolean fromParent) { int lineWidth = (int) Math.ceil(textLayout.getLineWidth(a)); if (a != 0) { int diff = prevLineWidth - lineWidth; - if (diff > 0 && diff <= corner + cornerIn) { + if (diff > 0 && diff <= 1.5f * corner + cornerIn) { lineWidth = prevLineWidth; } } @@ -1833,7 +1848,7 @@ public void drawBackground(Canvas canvas, boolean fromParent) { for (int a = count - 2; a >= 0; a--) { int lineWidth = lineWidths.get(a); int diff = prevLineWidth - lineWidth; - if (diff > 0 && diff <= corner + cornerIn) { + if (diff > 0 && diff <= 1.5f * corner + cornerIn) { lineWidth = prevLineWidth; } lineWidths.set(a, lineWidth); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 5040590627..85038777c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -128,6 +128,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.AvatarSpan; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; @@ -145,6 +146,7 @@ import org.telegram.ui.Components.EmptyStubSpan; import org.telegram.ui.Components.FloatSeekBarAccessibilityDelegate; import org.telegram.ui.Components.Forum.MessageTopicButton; +import org.telegram.ui.Components.ForwardBackground; import org.telegram.ui.Components.InfiniteProgress; import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.LinkSpanDrawable; @@ -169,6 +171,7 @@ import org.telegram.ui.Components.SeekBarWaveform; import org.telegram.ui.Components.SlotsDrawable; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.StickerSetLinkIcon; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TimerParticles; import org.telegram.ui.Components.TranscribeButton; @@ -299,23 +302,8 @@ public void setAvatar(MessageObject messageObject) { avatarDrawable.setInfo(currentAccount, currentChat); avatarImage.setForUserOrChat(currentChat, avatarDrawable); } else if (messageObject.isSponsored()) { - if (messageObject.sponsoredWebPage != null) { - avatarDrawable.setInfo(messageObject.sponsoredId[0], messageObject.sponsoredWebPage.site_name, null, null); - TLRPC.Photo photo = messageObject.sponsoredWebPage.photo; - if (photo != null) { - avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(50), false, null, true), photo), "50_50", avatarDrawable, null, null, 0); - } - } else if (messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - avatarDrawable.setInfo(currentAccount, messageObject.sponsoredChatInvite.chat); - avatarImage.setForUserOrChat(messageObject.sponsoredChatInvite.chat, avatarDrawable); - } else { - avatarDrawable.setInfo(currentAccount, messageObject.sponsoredChatInvite); - if (messageObject.sponsoredChatInvite != null) { - TLRPC.Photo photo = messageObject.sponsoredChatInvite.photo; - if (photo != null) { - avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(50), false, null, true), photo), "50_50", avatarDrawable, null, null, 0); - } - } + if (messageObject.sponsoredPhoto != null) { + avatarImage.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(messageObject.sponsoredPhoto.sizes, AndroidUtilities.dp(50), false, null, true), messageObject.sponsoredPhoto), "50_50", avatarDrawable, null, null, 0); } } else { currentPhoto = null; @@ -550,7 +538,7 @@ default void didPressSideButton(ChatMessageCell cell) { default void didPressOther(ChatMessageCell cell, float otherX, float otherY) { } - default void didPressSponsoredClose() { + default void didPressSponsoredClose(ChatMessageCell cell) { } default void didPressSponsoredInfo(ChatMessageCell cell, float x, float y) { @@ -569,7 +557,7 @@ default boolean didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton default void didPressReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction, boolean longpress) { } - default void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { + default void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { } default void didPressInstantButton(ChatMessageCell cell, int type) { @@ -775,12 +763,15 @@ public static class PollButton { private boolean prevChosen; private boolean correct; private StaticLayout title; - private TLRPC.TL_pollAnswer answer; + public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmoji; + private TLRPC.PollAnswer answer; } public static final int INSTANT_BUTTON_TYPE_CONTACT_VIEW = 5; public static final int INSTANT_BUTTON_TYPE_CONTACT_SEND_MESSAGE = 30; public static final int INSTANT_BUTTON_TYPE_CONTACT_ADD = 31; + public static final int INSTANT_BUTTON_TYPE_STICKER_SET = 23; + public static final int INSTANT_BUTTON_TYPE_EMOJI_SET = 24; private static class InstantViewButton { private int type; @@ -857,6 +848,8 @@ public boolean isCellAttachedToWindow() { private Paint onceRadialStrokePaint; private int onceRadialPaintColor; + private StickerSetLinkIcon stickerSetIcons; + private boolean disallowLongPress; private float lastTouchX; private float lastTouchY; @@ -871,6 +864,8 @@ public boolean isCellAttachedToWindow() { private long lastCheckBoxAnimationTime; public int checkBoxTranslation; + private AvatarSpan forwardAvatar; + private ForwardBackground forwardBg; public boolean linkPreviewAbove; private boolean isSmallImage; private boolean drawImageButton; @@ -1034,6 +1029,8 @@ public boolean isCellAttachedToWindow() { private BitmapDrawable currentPhotoObjectThumbStripped; private String currentPhotoFilter; private String currentPhotoFilterThumb; + private Drawable foreverDrawable; + private int foreverDrawableColor = 0xFFFFFFFF; private boolean timePressed; @@ -1322,7 +1319,7 @@ class LoadingDrawableLocation { private float drawTimeY; public StaticLayout timeLayout; public int timeWidth; - private int timeTextWidth; + public int timeTextWidth; public int timeX; public int signWidth; private CharSequence currentTimeString; @@ -1377,6 +1374,7 @@ class LoadingDrawableLocation { public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiReplyStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiDescriptionStack; + public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiPollQuestion; public ButtonBounce replyBounce, contactBounce; public float replyBounceX, replyBounceY; public Drawable replySelector; @@ -2331,7 +2329,7 @@ private boolean checkLinkPreviewMotionEvent(MotionEvent event) { final float left = descriptionLayout.getLineLeft(line); if (left <= checkX && left + descriptionLayout.getLineWidth(line) >= checkX) { - Spannable buffer = (Spannable) currentMessageObject.linkDescription; + Spannable buffer = (Spannable) (currentMessageObject.isSponsored() ? currentMessageObject.messageText : currentMessageObject.linkDescription); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); boolean ignore = false; if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { @@ -2604,9 +2602,9 @@ private boolean checkPollButtonMotionEvent(MotionEvent event) { Toast.makeText(getContext(), LocaleController.getString("MessageScheduledVote", R.string.MessageScheduledVote), Toast.LENGTH_LONG).show(); } else { PollButton button = pollButtons.get(pressedVoteButton); - TLRPC.TL_pollAnswer answer = button.answer; + TLRPC.PollAnswer answer = button.answer; if (pollVoted || pollClosed) { - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(answer); delegate.didPressVoteButtons(this, answers, button.count, button.x + AndroidUtilities.dp(50), button.y + namesOffset); } else { @@ -2626,7 +2624,7 @@ private boolean checkPollButtonMotionEvent(MotionEvent event) { firstCircleLength = true; voteCurrentCircleLength = 360; voteRisingCircleLength = false; - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(answer); delegate.didPressVoteButtons(this, answers, -1, 0, 0); } @@ -2896,7 +2894,7 @@ private boolean checkSponsoredCloseMotionEvent(MotionEvent event) { } else if (event.getAction() == MotionEvent.ACTION_UP) { if (closeSponsoredBounce != null && closeSponsoredBounce.isPressed()) { if (delegate != null) { - delegate.didPressSponsoredClose(); + delegate.didPressSponsoredClose(this); } } if (closeSponsoredBounce != null) { @@ -3007,9 +3005,6 @@ private void resetContactButtonsPressedState() { } private boolean checkDateMotionEvent(MotionEvent event) { - if (!currentMessageObject.isImportedForward()) { - return false; - } int x = (int) event.getX(); int y = (int) event.getY(); @@ -3447,7 +3442,7 @@ public boolean checkSpoilersMotionEvent(MotionEvent event, int n) { } private boolean checkBotButtonMotionEvent(MotionEvent event) { - if (botButtons.isEmpty() || currentMessageObject.eventId != 0) { + if (botButtons.isEmpty()) { return false; } @@ -3736,6 +3731,9 @@ public boolean onTouchEvent(MotionEvent event) { if (viaWidth != 0 && x >= forwardNameX + viaNameWidth + AndroidUtilities.dp(4)) { forwardBotPressed = true; } else { + if (forwardBg != null) { + forwardBg.setPressed(true, x - forwardNameX, y - forwardNameY); + } forwardNamePressed = true; } result = true; @@ -3827,7 +3825,7 @@ public boolean onTouchEvent(MotionEvent event) { id = 0; } delegate.didPressChannelAvatar(this, chat != null ? chat : currentChat, id, lastTouchX, lastTouchY); - } else if (currentMessageObject != null && currentMessageObject.sponsoredChatInvite != null) { + } else if (currentMessageObject != null) { delegate.didPressInstantButton(this, drawInstantViewType); } } @@ -3851,6 +3849,9 @@ public boolean onTouchEvent(MotionEvent event) { } else if (forwardNamePressed) { if (event.getAction() == MotionEvent.ACTION_UP) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (currentForwardChannel != null) { @@ -3867,9 +3868,15 @@ public boolean onTouchEvent(MotionEvent event) { } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (!(x >= forwardNameX && x <= forwardNameX + forwardedNameWidth && y >= forwardNameY && y <= forwardNameY + forwardHeight)) { forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } } } } else if (forwardBotPressed) { @@ -3969,7 +3976,7 @@ public boolean onTouchEvent(MotionEvent event) { playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (pressedSideButton == SIDE_BUTTON_SPONSORED_CLOSE) { - delegate.didPressSponsoredClose(); + delegate.didPressSponsoredClose(this); } else if (pressedSideButton == SIDE_BUTTON_SPONSORED_MORE) { delegate.didPressSponsoredInfo(this, x, y); } else if (pressedSideButton == 3) { @@ -4751,6 +4758,9 @@ protected void onDetachedFromWindow() { ImageLoader.getInstance().removeTestWebFile(currentUrl); addedForTest = false; } + if (stickerSetIcons != null) { + stickerSetIcons.detach(this); + } DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); if (getDelegate() != null && getDelegate().getTextSelectionHelper() != null) { @@ -4877,6 +4887,9 @@ public void onAttachedToWindow() { if (channelRecommendationsCell != null) { channelRecommendationsCell.onAttachedToWindow(); } + if (stickerSetIcons != null) { + stickerSetIcons.attach(this); + } } public void copySpoilerEffect2AttachIndexFrom(ChatMessageCell cell) { @@ -5116,6 +5129,9 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe transChanged = true; } if (messageChanged || dataChanged || groupChanged || pollChanged || widthChanged && messageObject.isPoll() || isPhotoDataChanged(messageObject) || pinnedBottom != bottomNear || pinnedTop != topNear || transChanged) { + if (stickerSetIcons != null) { + stickerSetIcons.readyToDie(); + } wasPinned = isPinned; pinnedBottom = bottomNear; pinnedTop = topNear; @@ -5578,6 +5594,8 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe TLRPC.Document androidThemeDocument = null; TL_stories.StoryItem storyItem = null; TLRPC.ThemeSettings androidThemeSettings = null; + ArrayList stickers = null; + boolean stickersTextColor = false; if (messageObject.isGiveawayOrGiveawayResults()) { hasLinkPreview = true; } @@ -5590,22 +5608,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe drawInstantView = true; hasLinkPreview = true; instantViewButtonText = messageObject.sponsoredButtonText; - if (messageObject.sponsoredBotApp != null) { - drawInstantViewType = 15; - } else if (messageObject.sponsoredWebPage != null) { - drawInstantViewType = 16; - } else if (messageObject.sponsoredChannelPost != 0) { - drawInstantViewType = 12; - } else { - drawInstantViewType = 1; - long id = MessageObject.getPeerId(messageObject.messageOwner.from_id); - if (id > 0) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(id); - if (user != null && user.bot) { - drawInstantViewType = 10; - } - } - } + drawInstantViewType = 1; } else if (messageObject.isGiveawayOrGiveawayResults()) { drawInstantView = true; drawInstantViewType = 19; @@ -5757,6 +5760,25 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } catch (Exception ignore) { } + } else if ("telegram_stickerset".equals(webpageType)) { + TLRPC.TL_webPageAttributeStickerSet attr = null; + for (int i = 0; i < webpage.attributes.size(); ++i) { + if (webpage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStickerSet) { + attr = (TLRPC.TL_webPageAttributeStickerSet) webpage.attributes.get(i); + break; + } + } + drawInstantView = true; + if (attr != null && attr.emojis) { + drawInstantViewType = 24; + } else { + drawInstantViewType = 23; + } + isSmallImage = true; + if (attr != null) { + stickers = attr.stickers; + stickersTextColor = attr.text_color; + } } } else if (siteName != null) { siteName = siteName.toLowerCase(); @@ -5899,27 +5921,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe photo = null; author = null; document = null; - if (messageObject.sponsoredBotApp != null) { - photo = messageObject.sponsoredBotApp.photo; - } else if (messageObject.sponsoredWebPage != null) { - photo = messageObject.sponsoredWebPage.photo; - } else if (messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - peerPhoto = messageObject.sponsoredChatInvite.chat; - currentPhotoLocation = ImageLocation.getForChat(messageObject.sponsoredChatInvite.chat, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForChat(messageObject.sponsoredChatInvite.chat, ImageLocation.TYPE_SMALL); - } else if (messageObject.sponsoredShowPeerPhoto) { - peerPhoto = messageObject.getFromPeerObject(); - if (peerPhoto instanceof TLRPC.User) { - currentPhotoLocation = ImageLocation.getForUser((TLRPC.User) peerPhoto, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForUser((TLRPC.User) peerPhoto, ImageLocation.TYPE_SMALL); - } else if (peerPhoto instanceof TLRPC.Chat) { - currentPhotoLocation = ImageLocation.getForChat((TLRPC.Chat) peerPhoto, ImageLocation.TYPE_BIG); - currentPhotoThumbLocation = ImageLocation.getForChat((TLRPC.Chat) peerPhoto, ImageLocation.TYPE_SMALL); - } - } - if (photo == null && messageObject.sponsoredChatInvite != null) { - photo = messageObject.sponsoredChatInvite.photo; - } + photo = messageObject.sponsoredPhoto; duration = 0; type = null; isSmallImage = photo != null || peerPhoto != null; @@ -5987,9 +5989,9 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe "telegram_user".equals(type) || "telegram_channel".equals(type) || "telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) || "telegram_livestream".equals(type) || "telegram_channel_boost".equals(type) || "telegram_group_boost".equals(type); - smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20 || drawInstantViewType == 22) && document == null && isSmallImageType; + smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20 || drawInstantViewType == 22) && document == null && isSmallImageType || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty(); TLRPC.MessageMedia media = MessageObject.getMedia(messageObject.messageOwner); - if (media != null) { + if (media != null && !(drawInstantViewType == 23 || drawInstantViewType == 24)) { if (media.force_large_media) { smallImage = false; } @@ -5998,7 +6000,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } } linkPreviewAbove = currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.invert_media; - isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null; + isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty(); } else if (hasInvoicePreview) { TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(messageObject.messageOwner); site_name = MessageObject.getMedia(messageObject.messageOwner).title; @@ -6535,7 +6537,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } if (documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC && documentAttachType != DOCUMENT_ATTACH_TYPE_AUDIO && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { - if (currentPhotoObject != null || currentPhotoLocation != null || webDocument != null || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { + if (currentPhotoObject != null || currentPhotoLocation != null || webDocument != null || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME || (drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty()) { drawImageButton = photo != null && !smallImage || type != null && (type.equals("photo") || type.equals("document") && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER || type.equals("gif") || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER); if (isSmallImage) { drawImageButton = false; @@ -6658,7 +6660,21 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe currentPhotoFilter = String.format(Locale.US, "%d_%d", w, h); currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", w, h); - if (webDocument != null) { + if ((drawInstantViewType == 23 || drawInstantViewType == 24) && stickers != null && !stickers.isEmpty()) { + if (stickerSetIcons == null || !stickerSetIcons.equals(stickers)) { + if (stickerSetIcons != null) { + stickerSetIcons.detach(this); + } + stickerSetIcons = new StickerSetLinkIcon(currentAccount, currentMessageObject.isOutOwner(), stickers, stickersTextColor); + if (attachedToWindow) { + stickerSetIcons.attach(this); + } + } + if (stickerSetIcons != null) { + stickerSetIcons.keepAlive(); + } + photoImage.setImageBitmap(stickerSetIcons); + } else if (webDocument != null) { /*TODO*/ photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { @@ -7152,13 +7168,20 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe question = media.poll.translatedQuestion; if (question == null) { messageObject.messageOwner.translated = false; - question = media.poll.question; + question = media.poll.question.text; } } else { - question = media.poll.question; + question = media.poll.question.text; } - titleLayout = new StaticLayout(Emoji.replaceEmoji(question, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false), Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + CharSequence questionText = new SpannableStringBuilder(question); + questionText = Emoji.replaceEmoji(questionText, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false); + if (media.poll.question.entities != null) { + questionText = MessageObject.replaceAnimatedEmoji(questionText, media.poll.question.entities, Theme.chat_audioTitlePaint.getFontMetricsInt(), true); + MessageObject.addEntitiesToText(questionText, media.poll.question.entities, currentMessageObject.isOutOwner(), false, false, false); + } + titleLayout = new StaticLayout(questionText, Theme.chat_audioTitlePaint, maxWidth + AndroidUtilities.dp(2) - getExtraTextX() * 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + animatedEmojiPollQuestion = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, animatedEmojiPollQuestion, titleLayout); boolean titleRtl = false; if (titleLayout != null) { for (int a = 0, N = titleLayout.getLineCount(); a < N; a++) { @@ -7298,17 +7321,26 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe boolean hasDifferent = false; int previousPercent = 0; for (int a = 0, N = media.poll.answers.size(); a < N; a++) { - PollButton button = new PollButton(); - button.answer = media.poll.answers.get(a); + TLRPC.PollAnswer pollAnswer = media.poll.answers.get(a); - String answerText; + String answeredText; if (messageObject.messageOwner.translated) { - answerText = button.answer.translatedText; + answeredText = pollAnswer.translatedText; } else { - answerText = button.answer.text; + answeredText = pollAnswer.text.text; } - button.title = new StaticLayout(Emoji.replaceEmoji(answerText, Theme.chat_audioPerformerPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false), Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + CharSequence answerText = new SpannableStringBuilder(answeredText); + answerText = Emoji.replaceEmoji(answerText, Theme.chat_audioTitlePaint.getFontMetricsInt(), AndroidUtilities.dp(16), false); + if (pollAnswer.text.entities != null) { + answerText = MessageObject.replaceAnimatedEmoji(answerText, pollAnswer.text.entities, Theme.chat_audioPerformerPaint.getFontMetricsInt(), true); + MessageObject.addEntitiesToText(answerText, pollAnswer.text.entities, currentMessageObject.isOutOwner(), false, false, false); + } + + PollButton button = new PollButton(); + button.answer = pollAnswer; + button.title = new StaticLayout(answerText, Theme.chat_audioPerformerPaint, maxWidth - AndroidUtilities.dp(33), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + button.animatedEmoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, button.animatedEmoji, button.title); button.y = height + AndroidUtilities.dp(52); button.height = button.title.getHeight(); pollButtons.add(button); @@ -9034,7 +9066,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe if (!mediaBackground && !currentMessageObject.isOutOwner()) { bl = nearRad; } - if (currentMessageObject.type == MessageObject.TYPE_GEO && MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaVenue) { + if (currentMessageObject.type == MessageObject.TYPE_GEO && (MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaVenue || !locationExpired && MessageObject.getMedia(currentMessageObject) instanceof TLRPC.TL_messageMediaGeoLive)) { br = bl = nearRad; } if (documentAttachType == DOCUMENT_ATTACH_TYPE_STORY) { @@ -9043,6 +9075,10 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe photoImage.setRoundRadius(tl, tr, br, bl); } updateAnimatedEmojis(); + if (stickerSetIcons != null && stickerSetIcons.die()) { + stickerSetIcons.detach(this); + stickerSetIcons = null; + } } if (messageIdChanged) { currentUrl = null; @@ -9275,6 +9311,10 @@ public void invalidate() { if (topicButton != null) { topicButton.resetClick(); } + forwardNamePressed = false; + if (forwardBg != null) { + forwardBg.setPressed(false); + } if (pressedEmoji != null) { // hadLongPress = true; // if (delegate.didPressAnimatedEmoji(this, pressedEmoji)) { @@ -10188,10 +10228,14 @@ public void invalidateDrawable(Drawable drawable) { } private boolean isCurrentLocationTimeExpired(MessageObject messageObject) { - if (MessageObject.getMedia(currentMessageObject.messageOwner).period % 60 == 0) { - return Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date) > MessageObject.getMedia(messageObject.messageOwner).period; + final int period = MessageObject.getMedia(currentMessageObject.messageOwner).period; + final int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + if (period == 0x7fffffff) { + return false; + } else if (period % 60 == 0) { + return Math.abs(currentTime - messageObject.messageOwner.date) > period; } else { - return Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - messageObject.messageOwner.date) > MessageObject.getMedia(messageObject.messageOwner).period - 5; + return Math.abs(currentTime - messageObject.messageOwner.date) > period - 5; } } @@ -10364,52 +10408,56 @@ private void createInstantViewButton() { if (instantViewButtonText != null) { str = instantViewButtonText; } else if (drawInstantViewType == 12) { - str = LocaleController.getString("OpenChannelPost", R.string.OpenChannelPost); + str = LocaleController.getString(R.string.OpenChannelPost); } else if (drawInstantViewType == 1) { - str = LocaleController.getString("OpenChannel", R.string.OpenChannel); + str = LocaleController.getString(R.string.OpenChannel); } else if (drawInstantViewType == 13) { - str = LocaleController.getString("SendMessage", R.string.SendMessage).toUpperCase(); + str = LocaleController.getString(R.string.SendMessage).toUpperCase(); } else if (drawInstantViewType == 10) { - str = LocaleController.getString("OpenBot", R.string.OpenBot); + str = LocaleController.getString(R.string.OpenBot); } else if (drawInstantViewType == 2) { - str = LocaleController.getString("OpenGroup", R.string.OpenGroup); + str = LocaleController.getString(R.string.OpenGroup); } else if (drawInstantViewType == 3) { - str = LocaleController.getString("OpenMessage", R.string.OpenMessage); + str = LocaleController.getString(R.string.OpenMessage); } else if (drawInstantViewType == 5) { - str = LocaleController.getString("ViewContact", R.string.ViewContact); + str = LocaleController.getString(R.string.ViewContact); } else if (drawInstantViewType == 6) { - str = LocaleController.getString("OpenBackground", R.string.OpenBackground); + str = LocaleController.getString(R.string.OpenBackground); } else if (drawInstantViewType == 7) { - str = LocaleController.getString("OpenTheme", R.string.OpenTheme); + str = LocaleController.getString(R.string.OpenTheme); } else if (drawInstantViewType == 8) { if (pollVoted || pollClosed) { - str = LocaleController.getString("PollViewResults", R.string.PollViewResults); + str = LocaleController.getString(R.string.PollViewResults); } else { - str = LocaleController.getString("PollSubmitVotes", R.string.PollSubmitVotes); + str = LocaleController.getString(R.string.PollSubmitVotes); } } else if (drawInstantViewType == 9 || drawInstantViewType == 11) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) MessageObject.getMedia(currentMessageObject.messageOwner).webpage; if (webPage != null && webPage.url.contains("voicechat=")) { - str = LocaleController.getString("VoipGroupJoinAsSpeaker", R.string.VoipGroupJoinAsSpeaker); + str = LocaleController.getString(R.string.VoipGroupJoinAsSpeaker); } else { - str = LocaleController.getString("VoipGroupJoinAsLinstener", R.string.VoipGroupJoinAsLinstener); + str = LocaleController.getString(R.string.VoipGroupJoinAsLinstener); } } else if (drawInstantViewType == 14) { - str = LocaleController.getString("ViewChatList", R.string.ViewChatList).toUpperCase(); + str = LocaleController.getString(R.string.ViewChatList).toUpperCase(); } else if (drawInstantViewType == 15) { str = LocaleController.getString(R.string.BotWebAppInstantViewOpen).toUpperCase(); } else if (drawInstantViewType == 16) { - str = LocaleController.getString("OpenLink").toUpperCase(); + str = LocaleController.getString(R.string.OpenLink).toUpperCase(); } else if (drawInstantViewType == 17) { - str = LocaleController.getString("ViewStory").toUpperCase(); + str = LocaleController.getString(R.string.ViewStory).toUpperCase(); } else if (drawInstantViewType == 18 || drawInstantViewType == 22) { - str = LocaleController.getString("BoostLinkButton", R.string.BoostLinkButton); + str = LocaleController.getString(R.string.BoostLinkButton); } else if (drawInstantViewType == 19) { - str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork); + str = LocaleController.getString(R.string.BoostingHowItWork); } else if (drawInstantViewType == 20) { str = LocaleController.getString(R.string.OpenGift); } else if (drawInstantViewType == 21) { str = LocaleController.getString(R.string.AppUpdate); + } else if (drawInstantViewType == 23) { + str = LocaleController.getString(R.string.OpenStickerSet); + } else if (drawInstantViewType == 24) { + str = LocaleController.getString(R.string.OpenEmojiSet); } else { str = LocaleController.getString(R.string.InstantView); } @@ -12123,6 +12171,7 @@ public void drawLinkPreview(Canvas canvas, float alpha) { linkLine = new ReplyMessageLine(this); } Theme.chat_replyNamePaint.setColor(linkLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, ReplyMessageLine.TYPE_LINK)); + linkLine.setEmojiAlpha(drawInstantViewType == 23 || drawInstantViewType == 24 ? 0.5f : 1f); final boolean drawPhotoImageBefore = drawInstantView && (drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18 && drawInstantViewType != 22) || drawInstantViewType == 6 && imageBackgroundColor != 0; final boolean drawPhotoImageAfter = !drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18 || drawInstantViewType == 22 || isSmallImage; @@ -15048,33 +15097,50 @@ private void setMessageObjectInternal(MessageObject messageObject) { if (messageObject.type == MessageObject.TYPE_STORY || currentForwardUser != null || currentForwardChannel != null || currentForwardName != null) { String forwardedString; CharSequence lastLine; + if (forwardAvatar == null) { + forwardAvatar = new AvatarSpan(this, currentAccount); + forwardAvatar.translate(0, dp(-.33f)); + } + forwardAvatar.setSize((1.23f * ((int) Theme.chat_forwardNamePaint.getTextSize())) / AndroidUtilities.density); if (messageObject.type == MessageObject.TYPE_STORY) { - currentForwardNameString = forwardedString = LocaleController.getString("ForwardedStory", R.string.ForwardedStory); + currentForwardNameString = forwardedString = LocaleController.getString(R.string.ForwardedStory); long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer); if (storyDialogId > 0) { - currentForwardUser = MessagesController.getInstance(currentAccount).getUser(storyDialogId); + forwardAvatar.setUser(currentForwardUser = MessagesController.getInstance(currentAccount).getUser(storyDialogId)); } else { - currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(-storyDialogId); + forwardAvatar.setChat(currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(-storyDialogId)); } + boolean includeAvatar = true; String name = getNameFromDialogId(storyDialogId); if (storyDialogId < 0 && currentForwardChannel == null) { name = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate); + includeAvatar = false; + } + lastLine = new SpannableStringBuilder((includeAvatar ? "A " : "") + name); + ((SpannableStringBuilder) lastLine).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, lastLine.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (includeAvatar) { + ((SpannableStringBuilder) lastLine).setSpan(forwardAvatar, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - lastLine = AndroidUtilities.replaceTags(LocaleController.formatString("ForwardedStoryFrom", R.string.ForwardedStoryFrom, name)); forwardedNameWidth = getMaxNameWidth(); } else { + boolean includeAvatar = true; if (currentForwardChannel != null) { if (currentForwardUser != null) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, UserObject.getUserName(currentForwardUser)); + forwardAvatar.setUser(currentForwardUser); } else if (!TextUtils.isEmpty(messageObject.messageOwner.fwd_from.post_author)) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, messageObject.messageOwner.fwd_from.post_author); + forwardAvatar.setChat(currentForwardChannel); } else { currentForwardNameString = currentForwardChannel.title; + forwardAvatar.setChat(currentForwardChannel); } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardName; + includeAvatar = false; } forwardedNameWidth = getMaxNameWidth(); @@ -15082,17 +15148,8 @@ private void setMessageObjectInternal(MessageObject messageObject) { if (hasPsaHint) { forwardedNameWidth -= AndroidUtilities.dp(36); } - String from = LocaleController.getString("From", R.string.From); - String fromFormattedString = LocaleController.getString("FromFormatted", R.string.FromFormatted); - int idx = fromFormattedString.indexOf("%1$s"); - int fromWidth = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(from + " ")); - CharSequence name = TextUtils.ellipsize(currentForwardNameString.replace('\n', ' '), Theme.chat_replyNamePaint, forwardedNameWidth - fromWidth - viaWidth, TextUtils.TruncateAt.END); - String fromString; - try { - fromString = String.format(fromFormattedString, name); - } catch (Exception e) { - fromString = name.toString(); - } + CharSequence name = TextUtils.ellipsize((includeAvatar ? "A " : "") + currentForwardNameString.replace('\n', ' '), Theme.chat_replyNamePaint, forwardedNameWidth - viaWidth - dp(includeAvatar ? 17.33f : 0), TextUtils.TruncateAt.END); + String fromString = name.toString(); SpannableStringBuilder stringBuilder; if (viaString != null) { @@ -15100,11 +15157,14 @@ private void setMessageObjectInternal(MessageObject messageObject) { viaNameWidth = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(fromString)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), stringBuilder.length() - viaUsername.length() - 1, stringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } else { - stringBuilder = new SpannableStringBuilder(String.format(fromFormattedString, name)); + stringBuilder = new SpannableStringBuilder(fromString); + } + if (includeAvatar && stringBuilder.length() > 1) { + stringBuilder.setSpan(forwardAvatar, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(name, 0, name.length())) / 2; - if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null)) { - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), idx, idx + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + forwardNameCenterX = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(name, 0, name.length())) / 2; + if (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null) { + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } lastLine = stringBuilder; } @@ -15118,6 +15178,10 @@ private void setMessageObjectInternal(MessageObject messageObject) { lastLine = TextUtils.ellipsize(AndroidUtilities.replaceTags(showForwardDate(messageObject, forwardedString)), Theme.chat_forwardNamePaint, forwardedNameWidth, TextUtils.TruncateAt.END); lastLine = Emoji.replaceEmoji(lastLine, Theme.chat_forwardNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); forwardedNameLayout[0] = new StaticLayout(lastLine, Theme.chat_forwardNamePaint, forwardedNameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (forwardBg == null) { + forwardBg = new ForwardBackground(this); + } + forwardBg.set(forwardedNameLayout, !currentMessageObject.isOutOwner() && !(drawNameLayout && nameLayout != null) && pinnedTop); forwardedNameWidth = Math.max((int) Math.ceil(forwardedNameLayout[0].getLineWidth(0)), (int) Math.ceil(forwardedNameLayout[1].getLineWidth(0))); if (hasPsaHint) { forwardedNameWidth += AndroidUtilities.dp(36); @@ -15418,30 +15482,39 @@ protected void onClick() { } if (currentForwardUser != null || currentForwardChannel != null || currentForwardName != null) { + if (forwardAvatar == null) { + forwardAvatar = new AvatarSpan(this, currentAccount); + forwardAvatar.translate(0, dp(-.33f)); + } + forwardAvatar.setSize((1.23f * ((int) Theme.chat_forwardNamePaint.getTextSize())) / AndroidUtilities.density); + boolean includeAvatar = true; if (currentForwardChannel != null) { if (currentForwardUser != null) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, UserObject.getUserName(currentForwardUser)); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardChannel.title; + forwardAvatar.setChat(currentForwardChannel); } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); + forwardAvatar.setUser(currentForwardUser); } else { currentForwardNameString = currentForwardName; + includeAvatar = false; } name = getForwardedMessageText(messageObject); - String from = LocaleController.getString("From", R.string.From); - String fromFormattedString = LocaleController.getString("FromFormatted", R.string.FromFormatted); - int idx = fromFormattedString.indexOf("%1$s"); - int fromWidth = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(from + " ")); CharSequence text = currentForwardNameString == null ? "" : currentForwardNameString.replace('\n', ' '); - CharSequence ellipsizedText = TextUtils.ellipsize(text, Theme.chat_replyNamePaint, maxWidth - fromWidth, TextUtils.TruncateAt.END); - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format(fromFormattedString, ellipsizedText)); - if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null)) { - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), idx, idx + ellipsizedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + CharSequence ellipsizedText = TextUtils.ellipsize((includeAvatar ? "A " : "") + text, Theme.chat_replyNamePaint, maxWidth - dp(includeAvatar ? 17.33f : 0), TextUtils.TruncateAt.END); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(ellipsizedText); + if (includeAvatar && stringBuilder.length() > 1) { + stringBuilder.setSpan(forwardAvatar, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null) { + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, ellipsizedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } stringFinalText = TextUtils.ellipsize(stringBuilder, textPaint, maxWidth, TextUtils.TruncateAt.END); - forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_replyNamePaint.measureText(ellipsizedText, 0, ellipsizedText.length())) / 2; + forwardNameCenterX = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(ellipsizedText, 0, ellipsizedText.length())) / 2; } } CharSequence stringFinalName = name; @@ -15611,19 +15684,7 @@ private String getAuthorName() { } else if (currentChat != null) { return currentChat.title; } else if (currentMessageObject != null && currentMessageObject.isSponsored()) { - if (currentMessageObject.sponsoredBotApp != null) { - return currentMessageObject.sponsoredBotApp.title; - } - if (currentMessageObject.sponsoredWebPage != null) { - return currentMessageObject.sponsoredWebPage.site_name; - } - if (currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.title != null) { - return currentMessageObject.sponsoredChatInvite.title; - } - if (currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null && currentMessageObject.sponsoredChatInvite.chat.title != null) { - return currentMessageObject.sponsoredChatInvite.chat.title; - } - return ""; + return currentMessageObject.sponsoredTitle; } return "DELETED"; } @@ -15651,7 +15712,7 @@ private String getForwardedMessageText(MessageObject messageObject) { } return forwardedString; } else { - return LocaleController.getString("ForwardedMessage", R.string.ForwardedMessage); + return LocaleController.getString(R.string.ForwardedFrom); } } @@ -15792,12 +15853,43 @@ protected boolean isWidthAdaptive() { @Override public int getBoundsLeft() { - return Math.max(0, getBackgroundDrawableLeft() - (needDrawAvatar() ? dp(currentPosition != null ? 73 : (currentMessageObject != null && currentMessageObject.isRepostPreview ? 42 : 63)) : 0) - (currentMessageObject != null && currentMessageObject.isOutOwner() && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0)); + boolean isOut = currentMessageObject != null && currentMessageObject.isOutOwner(); + int avatarWidth = needDrawAvatar() ? dp(currentPosition != null ? 73 : (currentMessageObject != null && currentMessageObject.isRepostPreview ? 42 : 63)) : 0; + int shareButtonWidth = (isOut && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + int buttonMostLeft = Integer.MAX_VALUE; + if (botButtons != null) { + int addX; + if (currentMessageObject != null && currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 1 : 7); + } + for (int i = 0; i < botButtons.size(); ++i) { + BotButton btn = botButtons.get(i); + buttonMostLeft = Math.max(buttonMostLeft, addX + btn.x); + } + } + return Math.max(0, Math.min(buttonMostLeft, getBackgroundDrawableLeft() - avatarWidth - shareButtonWidth)); } @Override public int getBoundsRight() { - return getBackgroundDrawableRight() + (currentMessageObject != null && !currentMessageObject.isOutOwner() && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + boolean isIn = currentMessageObject != null && !currentMessageObject.isOutOwner(); + int shareButtonWidth = (isIn && (checkNeedDrawShareButton(currentMessageObject) || useTranscribeButton) ? dp(48) : 0); + int buttonMostRight = 0; + if (botButtons != null) { + int addX; + if (currentMessageObject != null && currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 1 : 7); + } + for (int i = 0; i < botButtons.size(); ++i) { + BotButton btn = botButtons.get(i); + buttonMostRight = Math.max(buttonMostRight, addX + btn.x + btn.width); + } + } + return Math.max(getBackgroundDrawableRight() + shareButtonWidth, buttonMostRight); } @SuppressLint("WrongCall") @@ -16651,16 +16743,13 @@ public void drawOutboundsContent(Canvas canvas) { currentMessageObject.overrideLinkColor >= 0 || currentMessageObject.isFromUser() && currentUser != null || currentMessageObject.isFromChannel() && currentChat != null || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + currentMessageObject.sponsoredColor != null && currentMessageObject.sponsoredColor.color != -1 ) { int colorId; if (currentMessageObject.overrideLinkColor >= 0) { colorId = currentMessageObject.overrideLinkColor; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = currentMessageObject.sponsoredChatInvite.color; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(currentMessageObject.sponsoredChatInvite.chat); + } else if (currentMessageObject.sponsoredColor != null) { + colorId = currentMessageObject.sponsoredColor.color; } else if (currentMessageObject.isFromUser() && currentUser != null) { colorId = UserObject.getColorId(currentUser); } else { @@ -17245,17 +17334,11 @@ public void drawNamesLayout(Canvas canvas, float alpha) { } else if ( currentMessageObject.overrideLinkColor >= 0 || currentMessageObject.isFromUser() && currentUser != null || - currentMessageObject.isFromChannel() && currentChat != null || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + currentMessageObject.isFromChannel() && currentChat != null ) { int colorId; if (currentMessageObject.overrideLinkColor >= 0) { colorId = currentMessageObject.overrideLinkColor; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = currentMessageObject.sponsoredChatInvite.color; - } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(currentMessageObject.sponsoredChatInvite.chat); } else if (currentMessageObject.isFromUser() && currentUser != null) { colorId = UserObject.getColorId(currentUser); } else { @@ -17480,19 +17563,40 @@ public void drawNamesLayout(Canvas canvas, float alpha) { } else { rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameXLocal - AndroidUtilities.dp(7) + backWidth, forwardNameY + forwardHeight + AndroidUtilities.dp(6)); } - applyServiceShaderMatrix(); int oldAlpha1 = -1, oldAlpha2 = -1; - if (animatingAlpha != 1f || replyForwardAlpha != 1f) { - oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); - getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); - } - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), getThemedPaint(Theme.key_paint_chatActionBackground)); - if (hasGradientService()) { + if (hasReply || forwardBg == null) { + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); if (animatingAlpha != 1f || replyForwardAlpha != 1f) { - oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); - Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); + getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); } - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_actionBackgroundGradientDarkenPaint); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), getThemedPaint(Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_actionBackgroundGradientDarkenPaint); + } + } else { + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX() + forwardNameXLocal, viewTop + forwardNameY); + canvas.save(); + canvas.translate(forwardNameXLocal, forwardNameY); + final float s = forwardBg.bounce.getScale(.02f); + canvas.scale(s, s, forwardBg.cx, forwardBg.cy); + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha1 = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); + getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha1 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawPath(forwardBg.path, getThemedPaint(Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + if (animatingAlpha != 1f || replyForwardAlpha != 1f) { + oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * animatingAlpha * replyForwardAlpha)); + } + canvas.drawPath(forwardBg.path, Theme.chat_actionBackgroundGradientDarkenPaint); + } + canvas.restore(); } if (oldAlpha1 >= 0) { getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha(oldAlpha1); @@ -17501,7 +17605,13 @@ public void drawNamesLayout(Canvas canvas, float alpha) { Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(oldAlpha2); } } else { - forwardNameY = AndroidUtilities.dp(10) + (drawNameLayout ? AndroidUtilities.dp(5) + (int) Theme.chat_namePaint.getTextSize() : 0) + (drawTopic && topicButton != null ? topicButton.height() + AndroidUtilities.dp(7 + (currentMessageObject.type != MessageObject.TYPE_TEXT ? 3 : 0)) : 0); + forwardNameY = AndroidUtilities.dp(7) + (drawNameLayout ? AndroidUtilities.dp(6) + (int) Theme.chat_namePaint.getTextSize() : 0) + (drawTopic && topicButton != null ? topicButton.height() + AndroidUtilities.dp(7 + (currentMessageObject.type != MessageObject.TYPE_TEXT ? 3 : 0)) : 0); + if (!drawNameLayout && (currentMessageObject.type == MessageObject.TYPE_GIF || currentMessageObject.type == MessageObject.TYPE_PHOTO || currentMessageObject.type == MessageObject.TYPE_VIDEO || currentMessageObject.type == MessageObject.TYPE_STORY)) { + forwardNameY += dp(2); + } + if (!drawNameLayout && currentMessageObject.type == MessageObject.TYPE_TEXT && !drawPinnedTop) { + forwardNameY += dp(2); + } forwardHeight = AndroidUtilities.dp(4) + (int) Theme.chat_forwardNamePaint.getTextSize() * 2; Theme.chat_forwardNamePaint.setColor(getThemedColor(hasPsaHint ? Theme.key_chat_inPsaNameText : Theme.key_chat_inForwardedNameText)); if (currentMessageObject.isOutOwner()) { @@ -17537,14 +17647,14 @@ public void drawNamesLayout(Canvas canvas, float alpha) { } if (currentMessageObject.isOutOwner()) { if (currentMessageObject.needDrawForwarded()) { - forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(11) + getExtraTextX(); + forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(10) + getExtraTextX(); forwardNameXLocal += transitionParams.deltaLeft; } else { forwardNameXLocal = transitionParams.animateForwardNameX; } } else { if (currentMessageObject.needDrawForwarded()) { - forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 11 : 17) + getExtraTextX(); + forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 10 : 16) + getExtraTextX(); } else { forwardNameXLocal = transitionParams.animateForwardNameX; } @@ -17570,9 +17680,21 @@ public void drawNamesLayout(Canvas canvas, float alpha) { } } + canvas.save(); + canvas.translate(forwardNameXLocal, forwardNameY); + if (forwardBg != null) { + final float s = forwardBg.bounce.getScale(.02f); + canvas.scale(s, s, forwardBg.cx, forwardBg.cy); + if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO || currentMessageObject.isAnyKindOfSticker()) { + forwardBg.setColor(Theme.multAlpha(Theme.getColor(Theme.key_listSelector, resourcesProvider), 1.35f)); + } else { + forwardBg.setColor(Theme.multAlpha(Theme.chat_forwardNamePaint.getColor(), .15f)); + } + forwardBg.draw(canvas); + } for (int a = 0; a < 2; a++) { canvas.save(); - canvas.translate(forwardNameXLocal - forwardNameOffsetX[a], forwardNameY + (forwardHeight / 2f + 2) * a); + canvas.translate(-forwardNameOffsetX[a], (forwardHeight / 2f + dp(1.33f)) * a); if (animatingAlpha != 1f || replyForwardAlpha != 1f) { int oldAlpha = forwardedNameLayoutLocal[a].getPaint().getAlpha(); forwardedNameLayoutLocal[a].getPaint().setAlpha((int) (oldAlpha * animatingAlpha * replyForwardAlpha)); @@ -17583,6 +17705,7 @@ public void drawNamesLayout(Canvas canvas, float alpha) { } canvas.restore(); } + canvas.restore(); if (clipContent) { canvas.restore(); } @@ -17751,9 +17874,10 @@ public void drawNamesLayout(Canvas canvas, float alpha) { forwardNameX = replyStartX - replyTextOffset + offset + (needReplyImage ? offset + AndroidUtilities.dp(25) : 0); if ((currentPosition == null || currentPosition.minY == 0 && currentPosition.minX == 0) && !(enterTransitionInProgress && !currentMessageObject.isVoice())) { int restoreToCount = -1; - if (getAlpha() * replyForwardAlpha != 1f) { + float _alpha = (transitionParams.ignoreAlpha ? 1f : getAlpha()) * replyForwardAlpha; + if (_alpha != 1f) { AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); - restoreToCount = canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * getAlpha() * replyForwardAlpha), Canvas.ALL_SAVE_FLAG); + restoreToCount = canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * _alpha), Canvas.ALL_SAVE_FLAG); } float leftRad, rightRad, bottomRad = Math.min(4f, SharedConfig.bubbleRadius); @@ -19867,12 +19991,17 @@ public void drawOverlays(Canvas canvas) { StaticLayout docTitleLayout = this.docTitleLayout; StaticLayout infoLayout = this.infoLayout; float alpha = 1f; + boolean forever = false; if (transitionParams.animateLocationIsExpired) { progress = transitionParams.lastDrawLocationExpireProgress; text = transitionParams.lastDrawLocationExpireText; docTitleLayout = transitionParams.lastDrawDocTitleLayout; infoLayout = transitionParams.lastDrawInfoLayout; alpha = 1f - transitionParams.animateChangeProgress; + } else if (MessageObject.getMedia(currentMessageObject.messageOwner).period == 0x7fffffff) { + forever = true; + progress = 1.0f; + text = ""; } else { progress = 1.0f - Math.abs(ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date) / (float) MessageObject.getMedia(currentMessageObject.messageOwner).period; text = LocaleController.formatLocationLeftTime(Math.abs(MessageObject.getMedia(currentMessageObject.messageOwner).period - (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - currentMessageObject.messageOwner.date))); @@ -19903,8 +20032,29 @@ public void drawOverlays(Canvas canvas) { Theme.chat_radialProgress2Paint.setAlpha((int) (255 * alpha)); canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); - float w = Theme.chat_livePaint.measureText(text); - canvas.drawText(text, rect.centerX() - w / 2, cy + AndroidUtilities.dp(4), Theme.chat_livePaint); + if (forever) { + if (foreverDrawable == null) { + foreverDrawable = getContext().getResources().getDrawable(R.drawable.filled_location_forever).mutate(); + } + if (Theme.chat_livePaint.getColor() != foreverDrawableColor) { + foreverDrawable.setColorFilter(new PorterDuffColorFilter(foreverDrawableColor = Theme.chat_livePaint.getColor(), PorterDuff.Mode.SRC_IN)); + } + foreverDrawable.setBounds( + (int) rect.centerX() - foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() - foreverDrawable.getIntrinsicHeight() / 2, + (int) rect.centerX() + foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() + foreverDrawable.getIntrinsicHeight() / 2 + ); + foreverDrawable.draw(canvas); + } else { + float w = Theme.chat_livePaint.measureText(text); + int len = text.length(); + final float s2 = (len > 4 ? .75f : (len > 3 ? .85f : 1f)); + canvas.save(); + canvas.scale(s2, s2, rect.centerX(), rect.centerY()); + canvas.drawText(text, rect.centerX() - w / 2, cy + AndroidUtilities.dp(4), Theme.chat_livePaint); + canvas.restore(); + } if (docTitleLayout != null && infoLayout != null) { canvas.save(); @@ -20077,6 +20227,7 @@ public void drawOverlays(Canvas canvas) { canvas.save(); canvas.translate(x + getExtraTextX(), AndroidUtilities.dp(15) + namesOffset); titleLayout.draw(canvas); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, titleLayout, animatedEmojiPollQuestion, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(1, titleLayout.getPaint().getColor())); canvas.restore(); } int y = (titleLayout != null ? titleLayout.getHeight() : 0) + AndroidUtilities.dp(20) + namesOffset; @@ -20207,6 +20358,7 @@ public void drawOverlays(Canvas canvas) { canvas.save(); canvas.translate(x + AndroidUtilities.dp(35), button.y + namesOffset); button.title.draw(canvas); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, button.title, button.animatedEmoji, 0, null, 0, 0, 0, 1f, getAdaptiveEmojiColorFilter(1, button.title.getPaint().getColor())); int alpha = (int) (animatePollAnswerAlpha ? 255 * Math.min((pollUnvoteInProgress ? 1.0f - pollAnimationProgress : pollAnimationProgress) / 0.3f, 1.0f) : 255); if (pollVoted || pollClosed || animatePollAnswerAlpha) { if (lastPoll.quiz && pollVoted && button.chosen) { @@ -21113,7 +21265,7 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { } if (lastPoll != null) { sb.append(", "); - sb.append(lastPoll.question); + sb.append(lastPoll.question.text); sb.append(", "); String title; if (pollClosed) { @@ -21766,7 +21918,7 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) { } PollButton button = pollButtons.get(buttonIndex); if (delegate != null) { - ArrayList answers = new ArrayList<>(); + ArrayList answers = new ArrayList<>(); answers.add(button.answer); delegate.didPressVoteButtons(ChatMessageCell.this, answers, -1, 0, 0); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java index f9525da009..ecd8ffb81f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java @@ -8,6 +8,9 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -19,14 +22,28 @@ import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -40,20 +57,31 @@ public class CheckBoxCell extends FrameLayout { TYPE_CHECK_BOX_ENTER_PHONE = 2, TYPE_CHECK_BOX_UNKNOWN = 3, TYPE_CHECK_BOX_ROUND = 4, - TYPE_CHECK_BOX_URL = 5; + TYPE_CHECK_BOX_URL = 5, + TYPE_CHECK_BOX_USER_GROUP = 6, + TYPE_CHECK_BOX_USER = 7, + TYPE_CHECK_BOX_ROUND_GROUP = 8; + + public int itemId; private final Theme.ResourcesProvider resourcesProvider; - private final LinkSpanDrawable.LinksTextView textView; + private LinkSpanDrawable.LinksTextView linksTextView; + private AnimatedTextView animatedTextView; + private View textView; private final TextView valueTextView; private final View checkBox; private CheckBoxSquare checkBoxSquare; private CheckBox2 checkBoxRound; private View collapsedArrow; + private CollapseButton collapseButton; + private BackupImageView avatarImageView; + private AvatarDrawable avatarDrawable; private final int currentType; private final int checkBoxSize; private boolean needDivider; private boolean isMultiline; + private boolean textAnimated; public CheckBoxCell(Context context, int type) { this(context, type, 17, null); @@ -64,42 +92,91 @@ public CheckBoxCell(Context context, int type, Theme.ResourcesProvider resources } public CheckBoxCell(Context context, int type, int padding, Theme.ResourcesProvider resourcesProvider) { + this(context, type, padding, false, resourcesProvider); + } + + public CheckBoxCell(Context context, int type, int padding, boolean textAnimated, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.currentType = type; - - textView = new LinkSpanDrawable.LinksTextView(context) { - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - updateCollapseArrowTranslation(); + this.textAnimated = textAnimated; + + if (textAnimated) { + animatedTextView = new AnimatedTextView(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + updateCollapseArrowTranslation(); + } + }; + NotificationCenter.listenEmojiLoading(animatedTextView); + animatedTextView.setEllipsizeByGradient(true); + animatedTextView.setRightPadding(dp(8)); + animatedTextView.getDrawable().setHacks(true, true, false); + animatedTextView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + animatedTextView.setTextSize(dp(16)); + if (type == TYPE_CHECK_BOX_USER) { + animatedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } - - @Override - public void setText(CharSequence text, BufferType type) { - text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), false); - super.setText(text, type); + if (type == TYPE_CHECK_BOX_UNKNOWN) { + animatedTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); + animatedTextView.setPadding(0, 0, 0, dp(3)); + } else { + animatedTextView.setRightPadding(dp(padding)); + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + if (type == TYPE_CHECK_BOX_ENTER_PHONE) { + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + } else { + int offset = isCheckboxRound() ? 56 : 46; + if (type == TYPE_CHECK_BOX_USER) { + offset += 39; + } + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + } } - }; - NotificationCenter.listenEmojiLoading(textView); - textView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); - textView.setEllipsize(TextUtils.TruncateAt.END); - if (type == TYPE_CHECK_BOX_UNKNOWN) { - textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); - textView.setPadding(0, 0, 0, AndroidUtilities.dp(3)); + textView = animatedTextView; } else { - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - if (type == TYPE_CHECK_BOX_ENTER_PHONE) { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + linksTextView = new LinkSpanDrawable.LinksTextView(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + updateCollapseArrowTranslation(); + } + + @Override + public void setText(CharSequence text, BufferType type) { + text = Emoji.replaceEmoji(text, getPaint().getFontMetricsInt(), false); + super.setText(text, type); + } + }; + NotificationCenter.listenEmojiLoading(linksTextView); + linksTextView.setTag(getThemedColor(type == TYPE_CHECK_BOX_DEFAULT || type == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + linksTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + linksTextView.setLines(1); + linksTextView.setMaxLines(1); + linksTextView.setSingleLine(true); + linksTextView.setEllipsize(TextUtils.TruncateAt.END); + if (type == TYPE_CHECK_BOX_USER) { + linksTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + } + if (type == TYPE_CHECK_BOX_UNKNOWN) { + linksTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + addView(linksTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 29, 0, 0, 0)); + linksTextView.setPadding(0, 0, 0, dp(3)); } else { - int offset = type == TYPE_CHECK_BOX_ROUND ? 56 : 46; - addView(textView, LayoutHelper.createFrame(type == TYPE_CHECK_BOX_ROUND ? LayoutHelper.WRAP_CONTENT : LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + linksTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + if (type == TYPE_CHECK_BOX_ENTER_PHONE) { + addView(linksTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 8 : 29), 0, (LocaleController.isRTL ? 29 : 8), 0)); + } else { + int offset = isCheckboxRound() ? 56 : 46; + if (type == TYPE_CHECK_BOX_USER) { + offset += 39; + } + addView(linksTextView, LayoutHelper.createFrame(isCheckboxRound() ? LayoutHelper.WRAP_CONTENT : LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? padding : offset + (padding - 17)), 0, (LocaleController.isRTL ? offset + (padding - 17) : padding), 0)); + } } + textView = linksTextView; } valueTextView = new TextView(context); @@ -112,7 +189,7 @@ public void setText(CharSequence text, BufferType type) { valueTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, padding, 0, padding, 0)); - if (type == TYPE_CHECK_BOX_ROUND) { + if (isCheckboxRound()) { checkBox = checkBoxRound = new CheckBox2(context, 21, resourcesProvider); checkBoxRound.setDrawUnchecked(true); checkBoxRound.setChecked(true, false); @@ -132,18 +209,43 @@ public void setText(CharSequence text, BufferType type) { addView(checkBox, LayoutHelper.createFrame(checkBoxSize, checkBoxSize, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 0 : padding), 16, (LocaleController.isRTL ? padding : 0), 0)); } } + + if (type == TYPE_CHECK_BOX_USER_GROUP) { + collapseButton = new CollapseButton(context, R.drawable.msg_folders_groups); + addView(collapseButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL, padding, 0, padding - 11, 0)); + } else if (type == TYPE_CHECK_BOX_ROUND_GROUP) { + collapseButton = new CollapseButton(context, 0); + addView(collapseButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL, padding, 0, padding - 11, 0)); + } else if (type == TYPE_CHECK_BOX_USER) { + avatarDrawable = new AvatarDrawable(); + avatarImageView = new BackupImageView(context); + avatarImageView.setRoundRadius(dp(17)); + addView(avatarImageView, LayoutHelper.createFrameRelatively(34, 34, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 0, 0)); + } + updateTextColor(); } + public boolean isCheckboxRound() { + return currentType == TYPE_CHECK_BOX_ROUND || currentType == TYPE_CHECK_BOX_ROUND_GROUP || currentType == TYPE_CHECK_BOX_USER_GROUP || currentType == TYPE_CHECK_BOX_USER; + } + public void allowMultiline() { - textView.setLines(3); - textView.setMaxLines(3); - textView.setSingleLine(false); + if (textAnimated) { + return; + } + linksTextView.setLines(3); + linksTextView.setMaxLines(3); + linksTextView.setSingleLine(false); } public void updateTextColor() { - textView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); - textView.setLinkTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextLink : Theme.key_windowBackgroundWhiteLinkText)); + if (textAnimated) { + animatedTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + } else { + linksTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + linksTextView.setLinkTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextLink : Theme.key_windowBackgroundWhiteLinkText)); + } valueTextView.setTextColor(getThemedColor(currentType == TYPE_CHECK_BOX_DEFAULT || currentType == TYPE_CHECK_BOX_URL ? Theme.key_dialogTextBlue : Theme.key_windowBackgroundWhiteValueText)); } @@ -210,9 +312,9 @@ private void updateCollapseArrowTranslation() { float translateX; if (LocaleController.isRTL) { - translateX = textView.getRight() - textWidth - AndroidUtilities.dp(20); + translateX = textView.getRight() - textWidth - dp(20); } else { - translateX = textView.getLeft() + textWidth + AndroidUtilities.dp(4); + translateX = textView.getLeft() + textWidth + dp(4); } collapsedArrow.setTranslationX(translateX); } @@ -221,47 +323,66 @@ private void updateCollapseArrowTranslation() { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); if (currentType == TYPE_CHECK_BOX_UNKNOWN) { - valueTextView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(10), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); - textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(34), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.AT_MOST)); - checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.EXACTLY)); + valueTextView.measure(MeasureSpec.makeMeasureSpec(dp(10), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); + textView.measure(MeasureSpec.makeMeasureSpec(width - dp(34), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.AT_MOST)); + checkBox.measure(MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.EXACTLY)); - setMeasuredDimension(textView.getMeasuredWidth() + AndroidUtilities.dp(29), AndroidUtilities.dp(50)); + setMeasuredDimension(textView.getMeasuredWidth() + dp(29), dp(50)); } else if (isMultiline) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } else { - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(50) + (needDivider ? 1 : 0)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), dp(50) + (needDivider ? 1 : 0)); - int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - AndroidUtilities.dp(currentType == TYPE_CHECK_BOX_ROUND ? 60 : 34); + int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - dp(isCheckboxRound() ? 60 : 34); + if (textAnimated) { + availableWidth += (int) animatedTextView.getRightPadding(); + } + if (currentType == TYPE_CHECK_BOX_USER) { + availableWidth -= dp(34); + } if (valueTextView.getLayoutParams() instanceof MarginLayoutParams) { availableWidth -= ((MarginLayoutParams) valueTextView.getLayoutParams()).rightMargin; } + int takenSpace = 0; valueTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth / 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); + takenSpace += valueTextView.getMeasuredWidth(); + if (collapseButton != null) { + collapseButton.measure(MeasureSpec.makeMeasureSpec(availableWidth / 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); + takenSpace += collapseButton.getMeasuredWidth() - dp(11); + } if (textView.getLayoutParams().width == LayoutHelper.MATCH_PARENT) { - textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - valueTextView.getMeasuredWidth() - AndroidUtilities.dp(8), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - takenSpace - dp(8), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); } else { - textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - valueTextView.getMeasuredWidth() - AndroidUtilities.dp(8), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + textView.measure(MeasureSpec.makeMeasureSpec(availableWidth - (int) Math.abs(textView.getTranslationX()) - takenSpace - dp(8), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + } + if (avatarImageView != null) { + avatarImageView.measure(MeasureSpec.makeMeasureSpec(dp(34), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(34), MeasureSpec.EXACTLY)); } - checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(checkBoxSize), MeasureSpec.EXACTLY)); + checkBox.measure(MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(checkBoxSize), MeasureSpec.EXACTLY)); } if (click1Container != null) { MarginLayoutParams margin = (MarginLayoutParams) click1Container.getLayoutParams(); - click1Container.measure(MeasureSpec.makeMeasureSpec(width - margin.leftMargin - margin.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); + click1Container.measure(MeasureSpec.makeMeasureSpec(width - margin.leftMargin - margin.rightMargin, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); } if (click2Container != null) { - click2Container.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); + click2Container.measure(MeasureSpec.makeMeasureSpec(dp(56), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY)); } if (collapsedArrow != null) { collapsedArrow.measure( - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(16), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(16), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(dp(16), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(16), MeasureSpec.EXACTLY) ); } } public void setTextColor(int color) { - textView.setTextColor(color); + if (textAnimated) { + animatedTextView.setTextColor(color); + } else { + linksTextView.setTextColor(color); + } } public void setText(CharSequence text, String value, boolean checked, boolean divider) { @@ -269,7 +390,12 @@ public void setText(CharSequence text, String value, boolean checked, boolean di } public void setText(CharSequence text, String value, boolean checked, boolean divider, boolean animated) { - textView.setText(text); + if (textAnimated) { + text = Emoji.replaceEmoji(text, animatedTextView.getPaint().getFontMetricsInt(), false); + animatedTextView.setText(text, animated); + } else { + linksTextView.setText(text); + } if (checkBoxRound != null) { checkBoxRound.setChecked(checked, animated); } else { @@ -280,12 +406,35 @@ public void setText(CharSequence text, String value, boolean checked, boolean di setWillNotDraw(!divider); } + public void setUserOrChat(TLObject userOrChat) { + avatarDrawable.setInfo(userOrChat); + avatarImageView.setForUserOrChat(userOrChat, avatarDrawable); + CharSequence name; + if (userOrChat instanceof TLRPC.User) { + name = UserObject.getUserName((TLRPC.User) userOrChat); + } else { + name = ContactsController.formatName(userOrChat); + } + if (userOrChat instanceof TLRPC.User && ((TLRPC.User) userOrChat).id == MessagesController.getInstance(UserConfig.selectedAccount).telegramAntispamUserId) { + name = LocaleController.getString(R.string.ChannelAntiSpamUser); + } + if (textAnimated) { + name = Emoji.replaceEmoji(name, animatedTextView.getPaint().getFontMetricsInt(), false); + animatedTextView.setText(name); + } else { + linksTextView.setText(name); + } + } + public void setPad(int pad) { - int offset = AndroidUtilities.dp(pad * 40 * (LocaleController.isRTL ? -1 : 1)); + int offset = dp(pad * 40 * (LocaleController.isRTL ? -1 : 1)); if (checkBox != null) { checkBox.setTranslationX(offset); } textView.setTranslationX(offset); + if (avatarImageView != null) { + avatarImageView.setTranslationX(offset); + } if (click1Container != null) { click1Container.setTranslationX(offset); } @@ -299,30 +448,33 @@ public void setNeedDivider(boolean needDivider) { } public void setMultiline(boolean value) { + if (textAnimated) { + return; + } isMultiline = value; LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); LayoutParams layoutParams1 = (LayoutParams) checkBox.getLayoutParams(); if (isMultiline) { - textView.setLines(0); - textView.setMaxLines(0); - textView.setSingleLine(false); - textView.setEllipsize(null); + linksTextView.setLines(0); + linksTextView.setMaxLines(0); + linksTextView.setSingleLine(false); + linksTextView.setEllipsize(null); if (currentType != TYPE_CHECK_BOX_URL) { layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP; - layoutParams.topMargin = AndroidUtilities.dp(14); - layoutParams.bottomMargin = AndroidUtilities.dp(10); + layoutParams.topMargin = dp(14); + layoutParams.bottomMargin = dp(10); } } else { - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); - textView.setEllipsize(TextUtils.TruncateAt.END); + linksTextView.setLines(1); + linksTextView.setMaxLines(1); + linksTextView.setSingleLine(true); + linksTextView.setEllipsize(TextUtils.TruncateAt.END); textView.setPadding(0, 0, 0, 0); layoutParams.height = LayoutParams.MATCH_PARENT; layoutParams.topMargin = 0; - layoutParams1.topMargin = AndroidUtilities.dp(15); + layoutParams1.topMargin = dp(15); } textView.setLayoutParams(layoutParams); checkBox.setLayoutParams(layoutParams1); @@ -353,7 +505,11 @@ public boolean isChecked() { } public TextView getTextView() { - return textView; + return linksTextView; + } + + public AnimatedTextView getAnimatedTextView() { + return animatedTextView; } public TextView getValueTextView() { @@ -383,7 +539,10 @@ public void setSquareCheckBoxColor(int uncheckedColor, int checkedColor, int che @Override protected void onDraw(Canvas canvas) { if (needDivider) { - int offset = AndroidUtilities.dp(currentType == TYPE_CHECK_BOX_ROUND ? 60 : 20) + (int) Math.abs(textView.getTranslationX()); + int offset = dp(isCheckboxRound() ? 60 : 20) + (int) Math.abs(textView.getTranslationX()); + if (currentType == TYPE_CHECK_BOX_USER) { + offset += dp(39); + } canvas.drawLine(LocaleController.isRTL ? 0 : offset, getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? offset : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } @@ -407,4 +566,74 @@ public void setIcon(int icon) { public boolean hasIcon() { return checkBoxRound.hasIcon(); } + + public void setCollapseButton(boolean collapsed, CharSequence text, View.OnClickListener onClick) { + if (collapseButton != null) { + collapseButton.set(collapsed, text); + if (onClick != null) { + collapseButton.setOnClickListener(onClick); + } + } + } + + public class CollapseButton extends LinearLayout { + + @Nullable + private ImageView iconView; + private final AnimatedTextView textView; + private final View collapsedArrow; + + @SuppressLint("UseCompatLoadingForDrawables") + public CollapseButton(@NonNull Context context, int iconResId) { + super(context); + + final int color = getThemedColor(Theme.key_windowBackgroundWhiteBlackText); + + if (iconResId != 0) { + iconView = new ImageView(context); + iconView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + iconView.setImageResource(iconResId); + } + + textView = new AnimatedTextView(context, false, true, false); + textView.setTextSize(dp(13)); + textView.setTextColor(color); + textView.setIncludeFontPadding(false); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + + collapsedArrow = new View(context); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.arrow_more).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + collapsedArrow.setBackground(drawable); + + if (LocaleController.isRTL) { + addView(collapsedArrow, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 11, 0, 3, 0)); + addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 16, Gravity.CENTER_VERTICAL, 0, 0, iconView == null ? 11 : 3, 0)); + if (iconView != null) { + addView(iconView, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 0, 0, 11, 0)); + } + } else { + if (iconView != null) { + addView(iconView, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 11, 0, 3, 0)); + } + addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 16, Gravity.CENTER_VERTICAL, iconView == null ? 11 : 0, 0, 3, 0)); + addView(collapsedArrow, LayoutHelper.createLinear(16, 16, Gravity.CENTER_VERTICAL, 0, 0, 11, 0)); + } + + setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_listSelector), 16, 16)); + setClickable(true); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(32), MeasureSpec.EXACTLY)); + } + + public void set(boolean collapsed, CharSequence text) { + textView.cancelAnimation(); + textView.setText(text); + collapsedArrow.animate().cancel(); + collapsedArrow.animate().rotation(collapsed ? 0 : 180).setDuration(340).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java new file mode 100644 index 0000000000..a0b23d26d3 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CollapseTextCell.java @@ -0,0 +1,76 @@ +package org.telegram.ui.Cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class CollapseTextCell extends FrameLayout { + + public final AnimatedTextView textView; + private View collapsedArrow; + private Theme.ResourcesProvider resourcesProvider; + + @SuppressLint("UseCompatLoadingForDrawables") + public CollapseTextCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + textView = new AnimatedTextView(context); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + textView.setTextSize(dp(14)); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + textView.setOnWidthUpdatedListener(this::updateCollapseArrowTranslation); + addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 21, 0, 38, 3)); + + collapsedArrow = new View(context); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.arrow_more).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider), PorterDuff.Mode.MULTIPLY)); + collapsedArrow.setBackground(drawable); + addView(collapsedArrow, LayoutHelper.createFrameRelatively(14, 14, Gravity.START | Gravity.CENTER_VERTICAL, 21, 1, 0, 3)); + } + + public void set(CharSequence text, boolean collapsed) { + textView.setText(text); + collapsedArrow.animate().cancel(); + collapsedArrow.animate().rotation(collapsed ? 0 : 180).setDuration(340).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); + } + + public void setColor(int colorKey) { + int color = Theme.getColor(colorKey, resourcesProvider); + textView.setTextColor(color); + collapsedArrow.getBackground().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(46), MeasureSpec.EXACTLY)); + updateCollapseArrowTranslation(); + } + + private void updateCollapseArrowTranslation() { + float textWidth = textView.getDrawable().getCurrentWidth(); + + float translateX = textWidth + dp(1); + if (LocaleController.isRTL) { + collapsedArrow.setTranslationX(-translateX); + } else { + collapsedArrow.setTranslationX(translateX); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 725dbd15cd..7e405f6368 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -1629,7 +1629,14 @@ public void buildLayout() { messageString = LocaleController.getString("BoostingGiveawayResults", R.string.BoostingGiveawayResults); } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + messageString = new SpannableStringBuilder("\uD83D\uDCCA ").append(questionText); + } else { + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; + } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { @@ -5112,14 +5119,28 @@ public SpannableStringBuilder getMessageStringFormatted(int messageFormatType, S } } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; - String innerMessage; + CharSequence innerMessage; int colorKey = Theme.key_chats_attachMessage; if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text.replace('\n', ' ')); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + innerMessage = new SpannableStringBuilder("\uD83D\uDCCA \u2068").append(questionText).append("\u2069"); + } else { + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); + } } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + if (mediaPoll.poll.question != null && mediaPoll.poll.question.entities != null) { + SpannableStringBuilder questionText = new SpannableStringBuilder(mediaPoll.poll.question.text.replace('\n', ' ')); + MediaDataController.addTextStyleRuns(mediaPoll.poll.question.entities, mediaPoll.poll.question.text, questionText); + MediaDataController.addAnimatedEmojiSpans(mediaPoll.poll.question.entities, questionText, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt()); + innerMessage = new SpannableStringBuilder("\uD83D\uDCCA ").append(questionText); + } else { + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); + } } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -5146,7 +5167,9 @@ public SpannableStringBuilder getMessageStringFormatted(int messageFormatType, S innerMessage = msgText.toString(); colorKey = Theme.key_chats_actionMessage; } - innerMessage = innerMessage.replace('\n', ' '); + if (innerMessage instanceof String) { + innerMessage = ((String) innerMessage).replace('\n', ' '); + } CharSequence message = innerMessage; if (applyThumbs) { message = applyThumbs(innerMessage); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java index f30960e3e5..b02dc7deae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EditTextCell.java @@ -148,8 +148,8 @@ protected void onDraw(Canvas canvas) { } editText.setPadding(dp(21), dp(15), dp((maxLength > 0 ? 42 : 0) + 21), dp(15)); editText.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | (multiline ? InputType.TYPE_TEXT_FLAG_MULTI_LINE : 0) | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - editText.setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | (multiline ? InputType.TYPE_TEXT_FLAG_MULTI_LINE : 0) | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + editText.setRawInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); editText.setHint(hint); editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setCursorSize(dp(19)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java index 7544e76c70..872de319be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java @@ -98,7 +98,7 @@ public void setText(CharSequence text) { rightTextView.setOnClickListener(null); } - public void setText(String left, String right, OnClickListener onClickListener) { + public void setText(CharSequence left, CharSequence right, OnClickListener onClickListener) { textView.setText(left); rightTextView.setText(right, false); rightTextView.setOnClickListener(onClickListener); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index 62fbcea086..70f4a3d915 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -28,19 +28,24 @@ import org.telegram.messenger.LocaleController; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.LayoutHelper; import java.util.ArrayList; public class HeaderCell extends LinearLayout { + public int id; + protected int padding; protected int bottomMargin; private TextView textView; + private AnimatedTextView animatedTextView; private TextView textView2; private int height = 40; private final Theme.ResourcesProvider resourcesProvider; + private boolean animated; public HeaderCell(Context context) { this(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, false, null); @@ -67,23 +72,41 @@ public HeaderCell(Context context, int textColorKey, int padding, int topMargin, } public HeaderCell(Context context, int textColorKey, int padding, int topMargin, int bottomMargin, boolean text2, Theme.ResourcesProvider resourcesProvider) { + this(context, textColorKey, padding, topMargin, bottomMargin, text2, false, resourcesProvider); + } + + public HeaderCell(Context context, int textColorKey, int padding, int topMargin, int bottomMargin, boolean text2, boolean animated, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.padding = padding; this.bottomMargin = bottomMargin; + this.animated = animated; setOrientation(LinearLayout.VERTICAL); setPadding(AndroidUtilities.dp(padding), AndroidUtilities.dp(topMargin), AndroidUtilities.dp(padding), 0); - textView = new TextView(getContext()); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setTextColor(getThemedColor(textColorKey)); - textView.setTag(textColorKey); -// addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + if (animated) { + animatedTextView = new AnimatedTextView(getContext()); + animatedTextView.setTextSize(AndroidUtilities.dp(15)); + animatedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + animatedTextView.setTextColor(getThemedColor(textColorKey)); + animatedTextView.setTag(textColorKey); + animatedTextView.getDrawable().setHacks(true, true, false); +// addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, height - topMargin, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); + addView(animatedTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, height - topMargin)); + } else { + textView = new TextView(getContext()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setMinHeight(AndroidUtilities.dp(height - topMargin)); + textView.setTextColor(getThemedColor(textColorKey)); + textView.setTag(textColorKey); +// addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + } textView2 = new TextView(getContext()); textView2.setTextSize(13); @@ -142,7 +165,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } public void setTextSize(float dip) { - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dip); + if (animated) { + animatedTextView.setTextSize(AndroidUtilities.dp(dip)); + } else { + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dip); + } } public void setTextColor(int color) { @@ -150,8 +177,17 @@ public void setTextColor(int color) { } public void setText(CharSequence text) { - textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setText(text); + setText(text, false); + } + + public void setText(CharSequence text, boolean animate) { + if (this.animated) { + animatedTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + animatedTextView.setText(text, animate); + } else { + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setText(text); + } } public void setText2(CharSequence text) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java index 4de6324284..26f44a0173 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java @@ -8,6 +8,8 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -15,6 +17,7 @@ import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -25,13 +28,16 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Switch; public class NotificationsCheckCell extends FrameLayout { private TextView textView; - private TextView valueTextView; + private AnimatedTextView valueTextView; + private TextView multilineValueTextView; @SuppressWarnings("FieldCanBeLocal") private ImageView imageView; private Switch checkBox; @@ -78,16 +84,26 @@ public NotificationsCheckCell(Context context, int padding, int height, boolean textView.setEllipsize(TextUtils.TruncateAt.END); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 13 + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); - valueTextView = new TextView(context); + valueTextView = new AnimatedTextView(context); + valueTextView.setAnimationProperties(.55f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); - valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + valueTextView.setTextSize(dp(13)); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - valueTextView.setLines(1); - valueTextView.setMaxLines(1); - valueTextView.setSingleLine(true); valueTextView.setPadding(0, 0, 0, 0); - valueTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); + valueTextView.setEllipsizeByGradient(true); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - 9 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); + + multilineValueTextView = new TextView(context); + multilineValueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); + multilineValueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + multilineValueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + multilineValueTextView.setLines(0); + multilineValueTextView.setMaxLines(0); + multilineValueTextView.setSingleLine(false); + multilineValueTextView.setEllipsize(null); + multilineValueTextView.setPadding(0, 0, 0, 0); + multilineValueTextView.setVisibility(View.GONE); + addView(multilineValueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (withImage ? 64 : padding), 38 - (withImage ? 2 : 0) + (currentHeight - 70) / 2, LocaleController.isRTL ? (withImage ? 64 : padding) : 80, 0)); checkBox = new Switch(context, resourcesProvider) { @Override @@ -113,7 +129,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (isMultiline) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } else { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(currentHeight), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(currentHeight), MeasureSpec.EXACTLY)); } } @@ -130,38 +146,46 @@ public void setTextAndValueAndCheck(CharSequence text, CharSequence value, boole } public void setTextAndValueAndIconAndCheck(CharSequence text, CharSequence value, int iconResId, boolean checked, int iconType, boolean multiline, boolean divider) { + setTextAndValueAndIconAndCheck(text, value, iconResId, checked, iconType, multiline, divider, false); + } + + public void setTextAndValueAndIconAndCheck(CharSequence text, CharSequence value, int iconResId, boolean checked, int iconType, boolean multiline, boolean divider, boolean animated) { textView.setText(text); - valueTextView.setText(value); if (imageView != null) { imageView.setImageResource(iconResId); imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogIcon), PorterDuff.Mode.MULTIPLY)); } checkBox.setChecked(checked, iconType, animationsEnabled); - valueTextView.setVisibility(VISIBLE); - needDivider = divider; setMultiline(multiline); + if (isMultiline) { + multilineValueTextView.setText(value); + } else { + valueTextView.setText(value, animated); + } + (isMultiline ? multilineValueTextView : valueTextView).setVisibility(VISIBLE); checkBox.setContentDescription(text); + needDivider = divider; } public void setMultiline(boolean multiline) { isMultiline = multiline; if (multiline) { - valueTextView.setLines(0); - valueTextView.setMaxLines(0); - valueTextView.setSingleLine(false); - valueTextView.setEllipsize(null); - valueTextView.setPadding(0, 0, 0, AndroidUtilities.dp(14)); + multilineValueTextView.setVisibility(View.VISIBLE); + valueTextView.setVisibility(View.GONE); + multilineValueTextView.setPadding(0, 0, 0, dp(14)); } else { - valueTextView.setLines(1); - valueTextView.setMaxLines(1); - valueTextView.setSingleLine(true); - valueTextView.setEllipsize(TextUtils.TruncateAt.END); + multilineValueTextView.setVisibility(View.GONE); + valueTextView.setVisibility(View.VISIBLE); valueTextView.setPadding(0, 0, 0, 0); } } public void setValue(CharSequence value) { - valueTextView.setText(value); + if (isMultiline) { + multilineValueTextView.setText(value); + } else { + valueTextView.setText(value, true); + } } public void setDrawLine(boolean value) { @@ -184,17 +208,17 @@ public boolean isChecked() { protected void onDraw(Canvas canvas) { if (needDivider) { canvas.drawLine( - LocaleController.isRTL ? 0 : AndroidUtilities.dp(imageView != null ? 64 : 20), + LocaleController.isRTL ? 0 : dp(imageView != null ? 64 : 20), getMeasuredHeight() - 1, - getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(imageView != null ? 64 : 20) : 0), + getMeasuredWidth() - (LocaleController.isRTL ? dp(imageView != null ? 64 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint ); } if (drawLine) { - int x = LocaleController.isRTL ? AndroidUtilities.dp(76) : getMeasuredWidth() - AndroidUtilities.dp(76) - 1; - int y = (getMeasuredHeight() - AndroidUtilities.dp(22)) / 2; - canvas.drawRect(x, y, x + 2, y + AndroidUtilities.dp(22), Theme.dividerPaint); + int x = LocaleController.isRTL ? dp(76) : getMeasuredWidth() - dp(76) - 1; + int y = (getMeasuredHeight() - dp(22)) / 2; + canvas.drawRect(x, y, x + 2, y + dp(22), Theme.dividerPaint); } } @@ -208,9 +232,16 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { info.setClassName("android.widget.Switch"); StringBuilder sb = new StringBuilder(); sb.append(textView.getText()); - if (valueTextView != null && !TextUtils.isEmpty(valueTextView.getText())) { - sb.append("\n"); - sb.append(valueTextView.getText()); + if (isMultiline) { + if (multilineValueTextView != null && !TextUtils.isEmpty(multilineValueTextView.getText())) { + sb.append("\n"); + sb.append(multilineValueTextView.getText()); + } + } else { + if (valueTextView != null && !TextUtils.isEmpty(valueTextView.getText())) { + sb.append("\n"); + sb.append(valueTextView.getText()); + } } info.setContentDescription(sb); info.setCheckable(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java index 93c17c673c..40a3e4c5cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -13,6 +13,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; +import android.content.ContentUris; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -23,10 +24,12 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.text.TextUtils; +import android.util.Size; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -44,6 +47,7 @@ import org.telegram.messenger.AndroidUtilities; 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; @@ -60,6 +64,8 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect2; import org.telegram.ui.PhotoViewer; +import java.io.IOException; + public class PhotoAttachPhotoCell extends FrameLayout { private BackupImageView imageView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java index d0f25630e2..1babb32be6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java @@ -8,13 +8,19 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.os.Build; +import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.TypedValue; @@ -27,19 +33,28 @@ import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextCaption; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.SuggestEmojiView; import java.util.ArrayList; -public class PollEditTextCell extends FrameLayout { +public class PollEditTextCell extends FrameLayout implements SuggestEmojiView.AnchorViewDelegate { + + public static final int TYPE_DEFAULT = 0; + public static final int TYPE_EMOJI = 1; private EditTextBoldCursor textView; private ImageView deleteImageView; @@ -51,93 +66,83 @@ public class PollEditTextCell extends FrameLayout { private boolean needDivider; private AnimatorSet checkBoxAnimation; private boolean alwaysShowText2; + private ChatActivityEnterViewAnimatedIconView emojiButton; + private ValueAnimator valueAnimator; public PollEditTextCell(Context context, OnClickListener onDelete) { - this(context, false, onDelete); + this(context, false, TYPE_DEFAULT, onDelete); } - public PollEditTextCell(Context context, boolean caption, OnClickListener onDelete) { - this(context, caption, onDelete, null); + public PollEditTextCell(Context context, boolean caption, int type, OnClickListener onDelete) { + this(context, caption, type, onDelete, null); } - public PollEditTextCell(Context context, boolean caption, OnClickListener onDelete, OnClickListener onChangeIcon) { + public PollEditTextCell(Context context, boolean caption, int type, OnClickListener onDelete, OnClickListener onChangeIcon) { super(context); - if (caption) { - textView = new EditTextCaption(context, null) { - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - InputConnection conn = super.onCreateInputConnection(outAttrs); - if (showNextButton) { - outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; - } - return conn; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - onEditTextDraw(this, canvas); + textView = new EditTextCaption(context, null) { + @Override + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + } + + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + InputConnection conn = super.onCreateInputConnection(outAttrs); + if (showNextButton) { + outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - onFieldTouchUp(this); - } - return super.onTouchEvent(event); - } - - @Override - public ActionMode startActionMode(ActionMode.Callback callback, int type) { - ActionMode actionMode = super.startActionMode(callback, type); - onActionModeStart(this, actionMode); - return actionMode; - } - - @Override - public ActionMode startActionMode(ActionMode.Callback callback) { - ActionMode actionMode = super.startActionMode(callback); - onActionModeStart(this, actionMode); - return actionMode; - } - }; - ((EditTextCaption) textView).setAllowTextEntitiesIntersection(true); - } else { - textView = new EditTextBoldCursor(context) { - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - InputConnection conn = super.onCreateInputConnection(outAttrs); - if (showNextButton) { - outAttrs.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; - } - return conn; + return conn; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + onEditTextDraw(this, canvas); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - onEditTextDraw(this, canvas); + if (event.getAction() == MotionEvent.ACTION_UP) { + onFieldTouchUp(this); } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) { - return false; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - onFieldTouchUp(this); + return super.onTouchEvent(event); + } + + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + if (type == TYPE_EMOJI) { + if (focused && emojiButton.getVisibility() == View.GONE) { + setEmojiButtonVisibility(true); + } else if (!focused && emojiButton.getVisibility() == View.VISIBLE) { + setEmojiButtonVisibility(false); } - return super.onTouchEvent(event); } - }; - } + } + + @Override + public ActionMode startActionMode(ActionMode.Callback callback, int type) { + ActionMode actionMode = super.startActionMode(callback, type); + onActionModeStart(this, actionMode); + return actionMode; + } + + @Override + public ActionMode startActionMode(ActionMode.Callback callback) { + ActionMode actionMode = super.startActionMode(callback); + onActionModeStart(this, actionMode); + return actionMode; + } + }; + ((EditTextCaption) textView).setAllowTextEntitiesIntersection(true); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); textView.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setMaxLines(type == TYPE_EMOJI ? 4 : Integer.MAX_VALUE); // textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setBackgroundDrawable(null); textView.setImeOptions(textView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI); @@ -145,7 +150,8 @@ public boolean onTouchEvent(MotionEvent event) { textView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(10), AndroidUtilities.dp(4), AndroidUtilities.dp(11)); if (onDelete != null) { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 58 : 64, 0, !LocaleController.isRTL ? 58 : 64, 0)); + int endMargin = type == TYPE_EMOJI ? 102: 58; + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? endMargin : 64, 0, !LocaleController.isRTL ? endMargin : 64, 0)); moveImageView = new ImageView(context); moveImageView.setFocusable(false); @@ -194,7 +200,27 @@ public boolean onTouchEvent(MotionEvent event) { iconImageView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); addView(iconImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 8, 2, 8, 0)); } else { - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 19, 0, 19, 0)); + int endMargin = type == TYPE_EMOJI ? 80: 19; + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? endMargin : 19, 0, LocaleController.isRTL ? 19 : endMargin, 0)); + } + + if (type == TYPE_EMOJI) { + emojiButton = new ChatActivityEnterViewAnimatedIconView(context); + emojiButton.setAlpha(0.80f); + emojiButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + int padding = dp(9.5f); + emojiButton.setPadding(padding, padding, padding, padding); + emojiButton.setVisibility(View.GONE); + int endMargin = deleteImageView == null ? 3 : 48; + addView(emojiButton, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), LocaleController.isRTL ? endMargin : 0, 0, LocaleController.isRTL ? 0 : endMargin, 0)); + if (Build.VERSION.SDK_INT >= 21) { + emojiButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + } + emojiButton.setOnClickListener(view -> { + onEmojiButtonClicked(this); + }); + emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); } } @@ -216,6 +242,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (deleteImageView != null) { deleteImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } + if (emojiButton != null) { + emojiButton.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + } if (moveImageView != null) { moveImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } @@ -234,7 +263,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else if (deleteImageView == null) { right = 70; } else { - right = 122; + if (emojiButton != null) { + right = 174; + } else { + right = 122; + } } textView.measure(MeasureSpec.makeMeasureSpec(width - getPaddingLeft() - getPaddingRight() - AndroidUtilities.dp(right), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = textView.getMeasuredHeight(); @@ -357,6 +390,10 @@ public void setTextAndHint(CharSequence text, String hint, boolean divider) { setWillNotDraw(!divider); } + public ChatActivityEnterViewAnimatedIconView getEmojiButton() { + return emojiButton; + } + public void setEnabled(boolean value, ArrayList animators) { setEnabled(value); } @@ -365,6 +402,10 @@ protected void onFieldTouchUp(EditTextBoldCursor editText) { } + protected void onEmojiButtonClicked(PollEditTextCell cell) { + + } + public void setText2(String text) { if (textView2 == null) { return; @@ -376,10 +417,94 @@ public SimpleTextView getTextView2() { return textView2; } + private void setEmojiButtonVisibility(boolean visible) { + if (valueAnimator != null) { + valueAnimator.cancel(); + } + if (visible) { + emojiButton.setVisibility(View.VISIBLE); + emojiButton.setScaleX(0f); + emojiButton.setScaleY(0f); + emojiButton.setAlpha(0f); + } + valueAnimator = ValueAnimator.ofFloat(visible ? 0 : 1, visible ? 1 : 0); + valueAnimator.addUpdateListener(animation -> { + float value = (Float) animation.getAnimatedValue(); + emojiButton.setScaleX(value); + emojiButton.setScaleY(value); + emojiButton.setAlpha(Math.max(value, 0.80f)); + if (textView2 != null && deleteImageView == null && textView2.getVisibility() == View.VISIBLE) { + textView2.setTranslationY(AndroidUtilities.dp(26) * value); + } + }); + valueAnimator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(@NonNull Animator animation) { + + } + + @Override + public void onAnimationEnd(@NonNull Animator animation) { + if (!visible) { + emojiButton.setVisibility(View.GONE); + } else { + emojiButton.setScaleX(1f); + emojiButton.setScaleY(1f); + emojiButton.setAlpha(0.80f); + } + } + + @Override + public void onAnimationCancel(@NonNull Animator animation) { + + } + + @Override + public void onAnimationRepeat(@NonNull Animator animation) { + + } + }); + valueAnimator.setDuration(200L); + valueAnimator.start(); + } + @Override protected void onDraw(Canvas canvas) { if (needDivider && drawDivider()) { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(moveImageView != null ? 63 : 20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(moveImageView != null ? 63 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public BaseFragment getParentFragment() { + return null; + } + + @Override + public void setFieldText(CharSequence text) { + textView.setText(text); + } + + @Override + public void addTextChangedListener(TextWatcher watcher) { + textView.addTextChangedListener(watcher); + } + + @Override + public EditTextBoldCursor getEditField() { + return textView; + } + + @Override + public CharSequence getFieldText() { + if (textView.length() > 0) { + return textView.getText(); + } + return null; + } + + @Override + public Editable getEditText() { + return textView.getText(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java index 91c1560ab9..e4672151e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileChannelCell.java @@ -26,6 +26,7 @@ import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; @@ -54,7 +55,7 @@ public class ProfileChannelCell extends FrameLayout { private final TextView headerView; private final AnimatedTextView subscribersView; - private final DialogCell dialogCell; + public final DialogCell dialogCell; public ProfileChannelCell(BaseFragment fragment) { super(fragment.getContext()); @@ -68,7 +69,7 @@ public ProfileChannelCell(BaseFragment fragment) { headerView = new TextView(context); headerView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); headerView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - headerView.setText("Channel"); + headerView.setText(LocaleController.getString(R.string.ProfileChannel)); headerLayout.addView(headerView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); subscribersView = new ClickableAnimatedTextView(context); @@ -81,6 +82,7 @@ public ProfileChannelCell(BaseFragment fragment) { headerLayout.addView(subscribersView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 17, Gravity.LEFT | Gravity.TOP, 4, 2, 4, 0)); dialogCell = new DialogCell(null, context, false, true, UserConfig.selectedAccount, resourcesProvider); + dialogCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); dialogCell.setDialogCellDelegate(new DialogCell.DialogCellDelegate() { @Override public void onButtonClicked(DialogCell dialogCell) { @@ -150,8 +152,8 @@ public void openHiddenStories() { private final LoadingDrawable loadingDrawable; @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); float loading = loadingAlpha.set(this.loading); if (loading > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java index 6599bce790..78485389bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java @@ -29,6 +29,8 @@ public class RadioColorCell extends FrameLayout { private RadioButton radioButton; private final Theme.ResourcesProvider resourcesProvider; + public int heightDp = 50; + public RadioColorCell(Context context) { this(context, null); } @@ -72,7 +74,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } super.onMeasure( MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (text2View.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(4) + text2View.getMeasuredHeight() : 0), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(heightDp) + (text2View.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(4) + text2View.getMeasuredHeight() : 0), MeasureSpec.EXACTLY) ); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java index f8cfed7e35..92cebb05c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java @@ -185,7 +185,7 @@ public void setUserReaction(TLRPC.User user, TLRPC.Chat chat, TLRPC.Reaction rea dialogId = user.id; titleView.setText(UserObject.getUserName(user)); } else { - dialogId = chat.id; + dialogId = -chat.id; titleView.setText(chat.title); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java index cc099bc8c1..b1691c523b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -8,16 +8,23 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; + +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocationController; @@ -25,7 +32,10 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.Components.ShareLocationDrawable; @@ -39,7 +49,9 @@ public class SendLocationCell extends FrameLayout { private long dialogId; private RectF rect; private boolean live; + private boolean liveDisable; private final Theme.ResourcesProvider resourcesProvider; + public boolean useDivider; private Runnable invalidateRunnable = new Runnable() { @Override @@ -50,49 +62,57 @@ public void run() { } }; - public SendLocationCell(Context context, boolean live, Theme.ResourcesProvider resourcesProvider) { + public SendLocationCell(Context context, boolean live, boolean liveDisable, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.live = live; + this.liveDisable = liveDisable; imageView = new ImageView(context); - setBackground(Theme.AdaptiveRipple.rect()); + addView(imageView, LayoutHelper.createFrame(46, 46, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 13, 0, LocaleController.isRTL ? 13 : 0, 0)); - imageView.setTag(live ? Theme.key_location_sendLiveLocationBackground + Theme.key_location_sendLiveLocationIcon : Theme.key_location_sendLocationBackground + Theme.key_location_sendLocationIcon); - Drawable circle = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground)); + titleTextView = new SimpleTextView(context); + titleTextView.setTextSize(16); + titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 9.33f, LocaleController.isRTL ? 73 : 16, 0)); + + accurateTextView = new SimpleTextView(context); + accurateTextView.setTextSize(14); + accurateTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); + accurateTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(accurateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 33, LocaleController.isRTL ? 73 : 16, 0)); + + updateImage(); + + setWillNotDraw(false); + } + private void updateImage() { + titleTextView.setTag(live ? liveDisable ? Theme.key_text_RedBold : Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText); + titleTextView.setTextColor(getThemedColor(live ? liveDisable ? Theme.key_text_RedBold : Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText)); + + imageView.setTag(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground + Theme.key_location_sendLiveLocationIcon : Theme.key_location_sendLocationBackground + Theme.key_location_sendLocationIcon); + Drawable circle = Theme.createSimpleSelectorCircleDrawable(dp(46), getThemedColor(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground), getThemedColor(live ? liveDisable ? Theme.key_color_red : Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground)); if (live) { rect = new RectF(); - Drawable drawable = new ShareLocationDrawable(context, 4); - drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLiveLocationIcon), PorterDuff.Mode.SRC_IN)); + Drawable drawable = new ShareLocationDrawable(getContext(), liveDisable ? ShareLocationDrawable.TYPE_DISABLE : ShareLocationDrawable.TYPE_ADD); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLiveLocationIcon), PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); - combinedDrawable.setCustomSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + combinedDrawable.setCustomSize(dp(46), dp(46)); imageView.setBackgroundDrawable(combinedDrawable); - AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); - setWillNotDraw(false); + if (!liveDisable) { + AndroidUtilities.cancelRunOnUIThread(invalidateRunnable); + AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); + } } else { Drawable drawable = getResources().getDrawable(R.drawable.pin).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_sendLocationIcon), PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); - combinedDrawable.setCustomSize(AndroidUtilities.dp(42), AndroidUtilities.dp(42)); - combinedDrawable.setIconSize(AndroidUtilities.dp(24), AndroidUtilities.dp(24)); + combinedDrawable.setCustomSize(dp(46), dp(46)); + combinedDrawable.setIconSize(dp(24), dp(24)); imageView.setBackgroundDrawable(combinedDrawable); } - addView(imageView, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 15, 12, LocaleController.isRTL ? 15 : 0, 0)); - - titleTextView = new SimpleTextView(context); - titleTextView.setTextSize(16); - titleTextView.setTag(live ? Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText); - titleTextView.setTextColor(getThemedColor(live ? Theme.key_location_sendLiveLocationText : Theme.key_location_sendLocationText)); - titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 12, LocaleController.isRTL ? 73 : 16, 0)); - - accurateTextView = new SimpleTextView(context); - accurateTextView.setTextSize(14); - accurateTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); - accurateTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(accurateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 16 : 73, 37, LocaleController.isRTL ? 73 : 16, 0)); } private ImageView getImageView() { @@ -113,7 +133,7 @@ public void setHasLocation(boolean value) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(66), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(60), MeasureSpec.EXACTLY)); } @Override @@ -126,6 +146,7 @@ protected void onDetachedFromWindow() { protected void onAttachedToWindow() { super.onAttachedToWindow(); if (rect != null) { + AndroidUtilities.cancelRunOnUIThread(invalidateRunnable); AndroidUtilities.runOnUIThread(invalidateRunnable, 1000); } } @@ -145,41 +166,93 @@ public void setDialogId(long did) { private void checkText() { LocationController.SharingLocationInfo info = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); if (info != null) { - setText(LocaleController.getString("StopLiveLocation", R.string.StopLiveLocation), LocaleController.formatLocationUpdateDate(info.messageObject.messageOwner.edit_date != 0 ? info.messageObject.messageOwner.edit_date : info.messageObject.messageOwner.date)); + if (liveDisable) { + setText(LocaleController.getString(R.string.StopLiveLocation), LocaleController.formatLocationUpdateDate(info.messageObject.messageOwner.edit_date != 0 ? info.messageObject.messageOwner.edit_date : info.messageObject.messageOwner.date)); + } else { + setText(LocaleController.getString(R.string.SharingLiveLocation), LocaleController.getString(R.string.SharingLiveLocationAdd)); + } } else { setText(LocaleController.getString("SendLiveLocation", R.string.SendLiveLocation), LocaleController.getString("SendLiveLocationInfo", R.string.SendLiveLocationInfo)); } } + private final AnimatedFloat progress = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat progressAlpha = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat progressScale = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedTextView.AnimatedTextDrawable textDrawable = new AnimatedTextView.AnimatedTextDrawable(false, true, false); + { + textDrawable.setAnimationProperties(.3f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + textDrawable.setTextSize(dp(12)); + textDrawable.setTypeface(Typeface.DEFAULT_BOLD); + textDrawable.setGravity(Gravity.CENTER); + textDrawable.setCallback(this); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == textDrawable || super.verifyDrawable(who); + } + @Override protected void onDraw(Canvas canvas) { - LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); - if (currentInfo == null) { + if (useDivider) { + Paint dividerPaint = Theme.getThemePaint(Theme.key_paint_divider, resourcesProvider); + if (dividerPaint != null) { + canvas.drawRect(LocaleController.isRTL ? 0 : dp(73), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? dp(73) : 0), getMeasuredHeight(), dividerPaint); + } + } + + if (liveDisable) { return; } + LocationController.SharingLocationInfo currentInfo = LocationController.getInstance(currentAccount).getSharingLocationInfo(dialogId); + float progress = this.progress.get(); + + float alpha; int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (currentInfo.stopTime < currentTime) { + if (currentInfo != null && currentInfo.stopTime >= currentTime && currentInfo.period != 0x7FFFFFFF) { + progress = Math.abs(currentInfo.stopTime - currentTime) / (float) currentInfo.period; + alpha = this.progressAlpha.set(true); + } else { + alpha = this.progressAlpha.set(false); + } + + if (alpha <= 0) { return; } - float progress = Math.abs(currentInfo.stopTime - currentTime) / (float) currentInfo.period; if (LocaleController.isRTL) { - rect.set(AndroidUtilities.dp(13), AndroidUtilities.dp(18), AndroidUtilities.dp(43), AndroidUtilities.dp(48)); + rect.set(dp(13), getMeasuredHeight() / 2f - dp(15), dp(43), getMeasuredHeight() / 2f + dp(15)); } else { - rect.set(getMeasuredWidth() - AndroidUtilities.dp(43), AndroidUtilities.dp(18), getMeasuredWidth() - AndroidUtilities.dp(13), AndroidUtilities.dp(48)); + rect.set(getMeasuredWidth() - dp(43), getMeasuredHeight() / 2f - dp(15), getMeasuredWidth() - dp(13), getMeasuredHeight() / 2f + dp(15)); } + canvas.save(); + final float s = AndroidUtilities.lerp(.6f, 1f, alpha); + canvas.scale(s, s, rect.centerX(), rect.centerY()); + int color = getThemedColor(Theme.key_location_liveLocationProgress); Theme.chat_radialProgress2Paint.setColor(color); - Theme.chat_livePaint.setColor(color); - canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); + int a = Theme.chat_radialProgress2Paint.getAlpha(); + Theme.chat_radialProgress2Paint.setAlpha((int) (.20f * a * alpha)); + canvas.drawArc(rect, -90, 360, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha((int) (a * alpha)); + canvas.drawArc(rect, -90, -360 * this.progress.set(progress), false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha(a); - String text = LocaleController.formatLocationLeftTime(Math.abs(currentInfo.stopTime - currentTime)); - - float size = Theme.chat_livePaint.measureText(text); + if (currentInfo != null) { + textDrawable.setText(LocaleController.formatLocationLeftTime(Math.abs(currentInfo.stopTime - currentTime))); + } + int len = textDrawable.getText().length(); + final float s2 = progressScale.set(len > 4 ? .75f : (len > 3 ? .85f : 1f)); + canvas.scale(s2, s2, rect.centerX(), rect.centerY()); + textDrawable.setTextColor(color); + textDrawable.setAlpha((int) (0xFF * alpha)); + textDrawable.setBounds((int) rect.left, (int) (rect.centerY() - dp(12 + 1)), (int) rect.right, (int) (rect.centerY() + dp(12))); + textDrawable.draw(canvas); - canvas.drawText(text, rect.centerX() - size / 2, AndroidUtilities.dp(37), Theme.chat_livePaint); + canvas.restore(); } private int getThemedColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java index cfaf78e02d..f2875b003c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -19,12 +20,15 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.URLSpanNoUnderline; public class SettingsSuggestionCell extends LinearLayout { public final static int TYPE_PHONE = 0; public final static int TYPE_PASSWORD = 1; + public final static int TYPE_GRACE = 2; private TextView textView; private TextView detailTextView; @@ -49,22 +53,23 @@ public SettingsSuggestionCell(Context context, Theme.ResourcesProvider resources textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0)); - detailTextView = new TextView(context); - detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); - detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + detailTextView = new LinkSpanDrawable.LinksTextView(context, resourcesProvider); + detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); detailTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); detailTextView.setHighlightColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection, resourcesProvider)); detailTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); detailTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(detailTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 21, 8, 21, 0)); + addView(detailTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 21, 14, 21, 0)); LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(HORIZONTAL); - addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 40, 21, 17, 21, 20)); + addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44, 21, 16, 21, 15)); for (int a = 0; a < 2; a++) { TextView textView = new TextView(context); - textView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 4)); + textView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 8)); + ScaleStateListAnimator.apply(textView, 0.02f, 1.5f); textView.setLines(1); textView.setSingleLine(true); textView.setGravity(Gravity.CENTER_HORIZONTAL); @@ -72,8 +77,8 @@ public SettingsSuggestionCell(Context context, Theme.ResourcesProvider resources textView.setGravity(Gravity.CENTER); textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - linearLayout.addView(textView, LayoutHelper.createLinear(0, 40, 0.5f, a == 0 ? 0 : 4, 0, a == 0 ? 4 : 0, 0)); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + linearLayout.addView(textView, LayoutHelper.createLinear(0, 44, 0.5f, a == 0 ? 0 : 4, 0, a == 0 ? 4 : 0, 0)); if (a == 0) { yesButton = textView; yesButton.setOnClickListener(v -> onYesClick(currentType)); @@ -104,12 +109,19 @@ public void setType(int type) { } detailTextView.setText(builder); yesButton.setText(LocaleController.getString("CheckPhoneNumberYes", R.string.CheckPhoneNumberYes)); + noButton.setVisibility(View.VISIBLE); noButton.setText(LocaleController.getString("CheckPhoneNumberNo", R.string.CheckPhoneNumberNo)); } else if (type == TYPE_PASSWORD) { textView.setText(LocaleController.getString("YourPasswordHeader", R.string.YourPasswordHeader)); detailTextView.setText(LocaleController.getString("YourPasswordRemember", R.string.YourPasswordRemember)); yesButton.setText(LocaleController.getString("YourPasswordRememberYes", R.string.YourPasswordRememberYes)); + noButton.setVisibility(View.VISIBLE); noButton.setText(LocaleController.getString("YourPasswordRememberNo", R.string.YourPasswordRememberNo)); + } else if (type == TYPE_GRACE) { + textView.setText(LocaleController.getString(R.string.GraceSuggestionTitle)); + detailTextView.setText(LocaleController.getString(R.string.GraceSuggestionMessage)); + yesButton.setText(LocaleController.getString(R.string.GraceSuggestionButton)); + noButton.setVisibility(View.GONE); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java index f54eeb6023..2ab3062a23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -8,6 +8,7 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -58,6 +59,9 @@ import org.telegram.ui.PhotoViewer; import org.telegram.ui.Stories.StoryWidgetsImageDecorator; import org.telegram.ui.Stories.recorder.DominantColors; +import org.telegram.ui.Stories.recorder.StoryPrivacyBottomSheet; + +import java.util.HashMap; public class SharedPhotoVideoCell2 extends FrameLayout { @@ -77,6 +81,10 @@ public class SharedPhotoVideoCell2 extends FrameLayout { String videoText; boolean drawVideoIcon = true; + private int privacyType; + private Bitmap privacyBitmap; + private Paint privacyPaint; + boolean drawViews; AnimatedFloat viewsAlpha = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); AnimatedTextView.AnimatedTextDrawable viewsText = new AnimatedTextView.AnimatedTextDrawable(false, true, true); @@ -93,6 +101,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { private boolean gradientDrawableLoading; public boolean isStory; + public boolean isStoryPinned; static long lastUpdateDownloadSettingsTime; static boolean lastAutoDownload; @@ -169,7 +178,7 @@ public void setMessageObject(MessageObject messageObject, int parentColumnsCount if (currentMessageObject == null && messageObject == null) { return; } - if (currentMessageObject != null && messageObject != null && currentMessageObject.getId() == messageObject.getId() && oldParentColumsCount == parentColumnsCount) { + if (currentMessageObject != null && messageObject != null && currentMessageObject.getId() == messageObject.getId() && oldParentColumsCount == parentColumnsCount && (privacyType == 100) == isStoryPinned) { return; } currentMessageObject = messageObject; @@ -186,6 +195,8 @@ public void setMessageObject(MessageObject messageObject, int parentColumnsCount showVideoLayout = false; gradientDrawableLoading = false; gradientDrawable = null; + privacyType = -1; + privacyBitmap = null; return; } else { if (attached) { @@ -303,6 +314,35 @@ public void setMessageObject(MessageObject messageObject, int parentColumnsCount imageReceiver.addDecorator(new StoryWidgetsImageDecorator(messageObject.storyItem)); } + if (isStoryPinned) { + setPrivacyType(100, R.drawable.msg_pin_mini); + } else if (isStory && messageObject.storyItem != null) { + if (messageObject.storyItem.parsedPrivacy == null) { + messageObject.storyItem.parsedPrivacy = new StoryPrivacyBottomSheet.StoryPrivacy(currentAccount, messageObject.storyItem.privacy); + } + if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_CONTACTS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_folders_private); + } else if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_CLOSE_FRIENDS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_stories_closefriends); + } else if (messageObject.storyItem.parsedPrivacy.type == StoryPrivacyBottomSheet.TYPE_SELECTED_CONTACTS) { + setPrivacyType(messageObject.storyItem.parsedPrivacy.type, R.drawable.msg_folders_groups); + } else { + setPrivacyType(-1, 0); + } + } else { + setPrivacyType(-1, 0); + } + + invalidate(); + } + + private void setPrivacyType(int type, int resId) { + if (privacyType == type) return; + privacyType = type; + privacyBitmap = null; + if (resId != 0) { + privacyBitmap = sharedResources.getPrivacyBitmap(getContext(), resId); + } invalidate(); } @@ -446,6 +486,7 @@ protected void onDraw(Canvas canvas) { bounds.set(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX2(), imageReceiver.getImageY2()); drawDuration(canvas, bounds, 1f); drawViews(canvas, bounds, 1f); + drawPrivacy(canvas, bounds, 1f); if (checkBoxBase != null && (style == STYLE_CACHE || checkBoxBase.getProgress() != 0)) { canvas.save(); @@ -474,12 +515,16 @@ public void drawDuration(Canvas canvas, RectF bounds, float alpha) { return; } + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + if (alpha < 1) { alpha = (float) Math.pow(alpha, 8); } canvas.save(); canvas.translate(bounds.left, bounds.top); + canvas.scale(scale, scale, 0, bounds.height()); canvas.clipRect(0, 0, bounds.width(), bounds.height()); if (currentParentColumnsCount != 9 && videoInfoLayot == null && videoText != null) { int textWidth = (int) Math.ceil(sharedResources.textPaint.measureText(videoText)); @@ -487,16 +532,9 @@ public void drawDuration(Canvas canvas, RectF bounds, float alpha) { } else if ((currentParentColumnsCount >= 9 || videoText == null) && videoInfoLayot != null) { videoInfoLayot = null; } - int width; - if (videoInfoLayot == null) { - width = dp(8); - } else { - width = dp(4) + videoInfoLayot.getWidth() + dp(4); - } - if (drawVideoIcon) { - width += dp(10); - } - canvas.translate(dp(5), dp(1) + bounds.height() - dp(17) - dp(4)); + final boolean up = viewsOnLeft(fwidth); + int width = dp(8) + (videoInfoLayot != null ? videoInfoLayot.getWidth() : 0) + (drawVideoIcon ? dp(10) : 0); + canvas.translate(dp(5), dp(1) + bounds.height() - dp(17) - dp(4) - (up ? dp(17 + 5) : 0)); AndroidUtilities.rectTmp.set(0, 0, width, dp(17)); int oldAlpha = Theme.chat_timeBackgroundPaint.getAlpha(); Theme.chat_timeBackgroundPaint.setAlpha((int) (oldAlpha * alpha)); @@ -529,11 +567,46 @@ public void updateViews() { } } + public boolean viewsOnLeft(float width) { + if (!isStory || currentParentColumnsCount >= 5) { + return false; + } + final int viewsWidth = dp(18 + 8) + (int) viewsText.getCurrentWidth(); + final int durationWidth = showVideoLayout ? dp(8) + (videoInfoLayot != null ? videoInfoLayot.getWidth() : 0) + (drawVideoIcon ? dp(10) : 0) : 0; + final int padding = viewsWidth > 0 && durationWidth > 0 ? dp(8) : 0; + final int totalWidth = viewsWidth + padding + durationWidth; + return totalWidth > width; + } + + public void drawPrivacy(Canvas canvas, RectF bounds, float alpha) { + if (!isStory || privacyBitmap == null || privacyBitmap.isRecycled()) { + return; + } + + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + + final int sz = dp(17.33f * scale); + canvas.save(); + canvas.translate(bounds.right - sz - dp(5.66f), bounds.top + dp(5.66f)); + if (privacyPaint == null) { + privacyPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + } + privacyPaint.setAlpha((int) (0xFF * alpha)); + AndroidUtilities.rectTmp.set(0, 0, sz, sz); + canvas.drawBitmap(privacyBitmap, null, AndroidUtilities.rectTmp, privacyPaint); + canvas.restore(); + } + public void drawViews(Canvas canvas, RectF bounds, float alpha) { if (!isStory || imageReceiver != null && !imageReceiver.getVisible() || currentParentColumnsCount >= 5) { return; } + final float fwidth = bounds.width() + dp(20) * checkBoxProgress; + final float scale = bounds.width() / fwidth; + final boolean left = viewsOnLeft(fwidth); + float a = viewsAlpha.set(drawViews); alpha *= a; @@ -547,11 +620,12 @@ public void drawViews(Canvas canvas, RectF bounds, float alpha) { canvas.save(); canvas.translate(bounds.left, bounds.top); + canvas.scale(scale, scale, left ? 0 : bounds.width(), bounds.height()); canvas.clipRect(0, 0, bounds.width(), bounds.height()); float width = dp(18 + 8) + viewsText.getCurrentWidth(); - canvas.translate(bounds.width() - dp(5) - width, dp(1) + bounds.height() - dp(17) - dp(4)); + canvas.translate(left ? dp(5) : bounds.width() - dp(5) - width, dp(1) + bounds.height() - dp(17) - dp(4)); AndroidUtilities.rectTmp.set(0, 0, width, dp(17)); int oldAlpha = Theme.chat_timeBackgroundPaint.getAlpha(); Theme.chat_timeBackgroundPaint.setAlpha((int) (oldAlpha * alpha)); @@ -787,6 +861,7 @@ public static class SharedResources { Drawable viewDrawable; Paint highlightPaint = new Paint(); SparseArray imageFilters = new SparseArray<>(); + private final HashMap privacyBitmaps = new HashMap<>(); public SharedResources(Context context, Theme.ResourcesProvider resourcesProvider) { textPaint.setTextSize(dp(12)); @@ -807,6 +882,39 @@ public String getFilterString(int width) { } return str; } + + public void recycleAll() { + for (Bitmap bitmap : privacyBitmaps.values()) { + AndroidUtilities.recycleBitmap(bitmap); + } + privacyBitmaps.clear(); + } + + public Bitmap getPrivacyBitmap(Context context, int resId) { + Bitmap bitmap = privacyBitmaps.get(resId); + if (bitmap != null) { + return bitmap; + } + bitmap = BitmapFactory.decodeResource(context.getResources(), resId); + Bitmap shadowBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(shadowBitmap); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + paint.setColorFilter(new PorterDuffColorFilter(0xFF606060, PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, 0, 0, paint); + Utilities.stackBlurBitmap(shadowBitmap, dp(1)); + Bitmap resultBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + canvas = new Canvas(resultBitmap); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + canvas.drawBitmap(shadowBitmap, 0, 0, paint); + paint.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, 0, 0, paint); + shadowBitmap.recycle(); + bitmap.recycle(); + bitmap = resultBitmap; + privacyBitmaps.put(resId, bitmap); + return bitmap; + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java index 3692f668f5..c5ced57a29 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java @@ -114,7 +114,7 @@ public SharingLiveLocationCell(Context context, boolean distance, int padding, T distanceTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); distanceTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(distanceTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 73, 37, LocaleController.isRTL ? 73 : padding, 0)); + addView(distanceTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 73, 33, LocaleController.isRTL ? 73 : padding, 0)); } else { addView(avatarImageView, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 15, 6, LocaleController.isRTL ? 15 : 0, 0)); addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? padding : 74, 17, LocaleController.isRTL ? 74 : padding, 0)); @@ -385,6 +385,9 @@ public void setDialog(LocationController.SharingLocationInfo info) { } } + private Drawable foreverDrawable; + private int foreverDrawableColor; + @Override protected void onDraw(Canvas canvas) { if (currentInfo == null && liveLocation == null) { @@ -399,11 +402,12 @@ protected void onDraw(Canvas canvas) { stopTime = liveLocation.object.date + liveLocation.object.media.period; period = liveLocation.object.media.period; } + boolean forever = period == 0x7FFFFFFF; int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (stopTime < currentTime) { + if (stopTime < currentTime && !forever) { return; } - float progress = Math.abs(stopTime - currentTime) / (float) period; + float progress = forever ? 1 : Math.abs(stopTime - currentTime) / (float) period; if (LocaleController.isRTL) { rect.set(dp(13), dp(distanceTextView != null ? 18 : 12), dp(43), dp(distanceTextView != null ? 48 : 42)); } else { @@ -419,13 +423,32 @@ protected void onDraw(Canvas canvas) { Theme.chat_radialProgress2Paint.setColor(color); Theme.chat_livePaint.setColor(color); + int a = Theme.chat_radialProgress2Paint.getAlpha(); + Theme.chat_radialProgress2Paint.setAlpha((int) (.20f * a)); + canvas.drawArc(rect, -90, 360, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha((int) (a)); canvas.drawArc(rect, -90, -360 * progress, false, Theme.chat_radialProgress2Paint); + Theme.chat_radialProgress2Paint.setAlpha(a); - String text = LocaleController.formatLocationLeftTime(stopTime - currentTime); - - float size = Theme.chat_livePaint.measureText(text); - - canvas.drawText(text, rect.centerX() - size / 2, dp(distanceTextView != null ? 37 : 31), Theme.chat_livePaint); + if (forever) { + if (foreverDrawable == null) { + foreverDrawable = getContext().getResources().getDrawable(R.drawable.filled_location_forever).mutate(); + } + if (Theme.chat_livePaint.getColor() != foreverDrawableColor) { + foreverDrawable.setColorFilter(new PorterDuffColorFilter(foreverDrawableColor = Theme.chat_livePaint.getColor(), PorterDuff.Mode.SRC_IN)); + } + foreverDrawable.setBounds( + (int) rect.centerX() - foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() - foreverDrawable.getIntrinsicHeight() / 2, + (int) rect.centerX() + foreverDrawable.getIntrinsicWidth() / 2, + (int) rect.centerY() + foreverDrawable.getIntrinsicHeight() / 2 + ); + foreverDrawable.draw(canvas); + } else { + String text = LocaleController.formatLocationLeftTime(stopTime - currentTime); + float size = Theme.chat_livePaint.measureText(text); + canvas.drawText(text, rect.centerX() - size / 2, dp(distanceTextView != null ? 37 : 31), Theme.chat_livePaint); + } } private int getThemedColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java index ad81f6bf5f..4c4a7e8cb2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SlideIntChooseView.java @@ -15,6 +15,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.Build; +import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -22,6 +23,7 @@ import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChannelMonetizationLayout; @@ -92,7 +94,7 @@ public void onSeekBarDrag(boolean stop, float progress) { if (options == null || whenChanged == null) { return; } - final int newValue = (int) (options.min + stepsCount * progress); + final int newValue = (int) Math.round(options.min + stepsCount * progress); if (value != newValue) { value = newValue; AndroidUtilities.vibrateCursor(seekBarView); @@ -132,19 +134,26 @@ public void set( public void updateTexts(int value, boolean animated) { minText.cancelAnimation(); - minText.setText(processText(options.minStringResId, options.min), animated); - int valueResId; - if (value <= options.min) { - valueResId = options.valueMinStringResId; - } else if (value < options.max) { - valueResId = options.valueStringResId; + 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 { - valueResId = options.valueMaxStringResId; + 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.cancelAnimation(); - valueText.setText(processText(valueResId, value), animated); - maxText.cancelAnimation(); - maxText.setText(processText(options.maxStringResId, 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); } @@ -223,6 +232,8 @@ public static class Options { public int min; public int max; + public String resId; + public int minStringResId; public int valueMinStringResId, valueStringResId, valueMaxStringResId; public int maxStringResId; @@ -244,5 +255,17 @@ public static Options make( o.maxStringResId = maxStringResId; return o; } + + public static Options make( + int style, + String resId, int min, int max + ) { + Options o = new Options(); + o.style = style; + o.min = min; + o.resId = resId; + o.max = max; + return o; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java index 1a8ff3f10d..0abd498595 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java @@ -36,6 +36,7 @@ import org.telegram.ui.Components.EmojiTextView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ScaleStateListAnimator; import java.util.List; @@ -91,21 +92,22 @@ public StickerSetNameCell(Context context, boolean emoji, boolean supportRtl, Th lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, emoji ? 5 : 15, 5, emoji ? 15 : 25, 0); } addView(layout, lp); - layout.addView(textView); + layout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 1, Gravity.CENTER_VERTICAL)); editView = new TextView(context); editView.setTextColor(getThemedColor(Theme.key_chat_emojiPanelStickerSetName)); editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11); editView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); editView.setEllipsize(TextUtils.TruncateAt.END); - editView.setPadding(dp(6.33f), 0, dp(6.33f), 0); + editView.setPadding(dp(6), 0, dp(6.33f), 0); editView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(9), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelStickerSetName), .10f), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelStickerSetName), .24f) )); editView.setGravity(Gravity.CENTER); editView.setSingleLine(true); - layout.addView(editView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 5.33f, .66f, 0, 0)); + ScaleStateListAnimator.apply(editView); + layout.addView(editView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_VERTICAL, 5, 1, 0, 0)); editView.setVisibility(View.GONE); urlTextView = new TextView(context); @@ -201,6 +203,10 @@ public void setEdit(View.OnClickListener whenClickedEdit) { editView.setOnClickListener(whenClickedEdit); } + public void setHeaderOnClick(View.OnClickListener listener) { + textView.setOnClickListener(listener); + } + private void updateTextSearchSpan() { if (stickerSetName != null && stickerSetNameSearchLength > 0) { SpannableStringBuilder builder = new SpannableStringBuilder(stickerSetName); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 1afbbb8b86..e52879dcfe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -13,7 +13,9 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; @@ -25,7 +27,12 @@ import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.SimpleTextView; @@ -49,7 +56,7 @@ public class TextCell extends FrameLayout { public final RLottieImageView imageView; private Switch checkBox; private ImageView valueImageView; - private int leftPadding; + public int leftPadding; private boolean needDivider; public int offsetFromImage = 71; public int heightDp = 50; @@ -649,6 +656,25 @@ public void setTextAndSticker(CharSequence text, TLRPC.Document document, boolea setValueSticker(document); } + public void setTextAndSticker(CharSequence text, String localPath, boolean divider) { + imageLeft = 21; + offsetFromImage = getOffsetFromImage(false); + textView.setText(text); + textView.setRightDrawable(null); + valueTextView.setText(valueText = null, false); + valueImageView.setVisibility(GONE); + valueTextView.setVisibility(GONE); + valueSpoilersTextView.setVisibility(GONE); + imageView.setVisibility(GONE); + imageView.setPadding(0, dp(7), 0, 0); + needDivider = divider; + setWillNotDraw(!needDivider); + if (checkBox != null) { + checkBox.setVisibility(GONE); + } + setValueSticker(localPath); + } + public void setValueSticker(TLRPC.Document document) { if (emojiDrawable == null) { emojiDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, dp(30)); @@ -660,6 +686,64 @@ public void setValueSticker(TLRPC.Document document) { invalidate(); } + public void setValueSticker(String path) { + if (emojiDrawable == null) { + emojiDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, dp(30)); + if (attached) { + emojiDrawable.attach(); + } + } + ImageReceiver imageReceiver = new ImageReceiver(this); + if (isAttachedToWindow()) { + imageReceiver.onAttachedToWindow(); + } + addOnAttachStateChangeListener(new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(@NonNull View v) { + imageReceiver.onAttachedToWindow(); + } + + @Override + public void onViewDetachedFromWindow(@NonNull View v) { + imageReceiver.onDetachedFromWindow(); + } + }); + imageReceiver.setImage(path, "30_30", null, null, 0); + emojiDrawable.set(new Drawable() { + @Override + public void draw(@NonNull Canvas canvas) { + imageReceiver.setImageCoords(getBounds()); + imageReceiver.draw(canvas); + } + + @Override + public void setAlpha(int alpha) { + imageReceiver.setAlpha(alpha / (float) 0xFF); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + imageReceiver.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicWidth() { + return dp(30); + } + + @Override + public int getIntrinsicHeight() { + return dp(30); + } + }, true); + invalidate(); + } + protected int getOffsetFromImage(boolean colourful) { return colourful ? 65 : 71; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java index 23d1c06e49..59fb97fdf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java @@ -33,6 +33,7 @@ public class TextCheckCell2 extends FrameLayout { + public int id; private TextView textView; private TextView valueTextView; private Switch checkBox; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index 09d90fbb92..d5d51726d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -33,7 +33,6 @@ public class TextColorCell extends FrameLayout { private TextView textView; private boolean needDivider; private int currentColor; - private float alpha = 1.0f; private static Paint colorPaint; @@ -62,19 +61,6 @@ public TextColorCell(Context context, Theme.ResourcesProvider resourcesProvider) addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 0, 21, 0)); } - @Keep - @Override - public void setAlpha(float value) { - alpha = value; - invalidate(); - } - - @Keep - @Override - public float getAlpha() { - return alpha; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); @@ -106,7 +92,6 @@ protected void onDraw(Canvas canvas) { } if (currentColor != 0) { colorPaint.setColor(currentColor); - colorPaint.setAlpha((int) (255 * alpha)); canvas.drawCircle(LocaleController.isRTL ? AndroidUtilities.dp(33) : getMeasuredWidth() - AndroidUtilities.dp(33), getMeasuredHeight() / 2, AndroidUtilities.dp(10), colorPaint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index 0a93dc2101..c61ad07da6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -765,7 +765,7 @@ public void setFromUItem(int currentAccount, UItem item, boolean divider) { } } - public void setCloseIcon(Runnable onClick) { + public void setCloseIcon(View.OnClickListener onClick) { if (onClick == null) { if (closeView != null) { removeView(closeView); @@ -781,7 +781,7 @@ public void setCloseIcon(Runnable onClick) { closeView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), Theme.RIPPLE_MASK_CIRCLE_AUTO)); addView(closeView, LayoutHelper.createFrame(30, 30, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 0)); } - closeView.setOnClickListener(v -> onClick.run()); + closeView.setOnClickListener(onClick); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 756d706df7..49b600c503 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -8,6 +8,10 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; +import static org.telegram.messenger.MessageObject.replaceWithLink; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -19,6 +23,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; @@ -30,16 +35,20 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; +import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; +import android.text.style.LineHeightSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -50,10 +59,12 @@ import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -61,6 +72,8 @@ import androidx.collection.LongSparseArray; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.ChatListItemAnimator; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.GridLayoutManagerFixed; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerCustom; import androidx.recyclerview.widget.RecyclerView; @@ -73,6 +86,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; @@ -82,6 +96,7 @@ import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; @@ -89,15 +104,19 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.INavigationLayout; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -106,18 +125,23 @@ import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.ChatUnreadCell; import org.telegram.ui.Components.AdminLogFilterAlert; +import org.telegram.ui.Components.AdminLogFilterAlert2; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.ChatScrimPopupContainerLayout; import org.telegram.ui.Components.ClearHistoryAlert; +import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.EmbedBottomSheet; +import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.InviteLinkBottomSheet; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PhonebookShareAlert; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; +import org.telegram.ui.Components.RecyclerAnimationScrollHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayout; @@ -133,6 +157,7 @@ import java.io.FileWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import kotlin.Unit; import tw.nekomimi.nekogram.ui.BottomBuilder; @@ -152,12 +177,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private RecyclerListView chatListView; private UndoView undoView; private LinearLayoutManager chatLayoutManager; + private RecyclerAnimationScrollHelper chatScrollHelper; private ChatActivityAdapter chatAdapter; private TextView bottomOverlayChatText; private ImageView bottomOverlayImage; private FrameLayout bottomOverlayChat; private FrameLayout emptyViewContainer; private ChatAvatarContainer avatarContainer; + private LinearLayout emptyLayoutView; + private ImageView emptyImageView; private TextView emptyView; private ChatActionCell floatingDateView; private ActionBarMenuItem searchItem; @@ -168,11 +196,20 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private boolean scrollingFloatingDate; private int[] mid = new int[]{2}; private boolean searchWas; + private boolean scrollByTouch; + + private float contentPanTranslation; + private float contentPanTranslationT; + private long activityResumeTime; + + + public static int lastStableId = 10; private boolean checkTextureViewPosition; private SizeNotifierFrameLayout contentView; private MessageObject selectedObject; + private TLRPC.ChannelParticipant selectedParticipant; private FrameLayout searchContainer; private ImageView searchCalendarButton; @@ -194,12 +231,16 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private boolean openAnimationEnded; - private LongSparseArray messagesDict = new LongSparseArray<>(); - private HashMap> messagesByDays = new HashMap<>(); + private final LongSparseArray messagesDict = new LongSparseArray<>(); + private final LongSparseArray realMessagesDict = new LongSparseArray<>(); + private final HashMap> messagesByDays = new HashMap<>(); protected ArrayList messages = new ArrayList<>(); + private final ArrayList filteredMessages = new ArrayList<>(); + private final HashSet expandedEvents = new HashSet<>(); private int minDate; private boolean endReached; private boolean loading; + private boolean reloadingLastMessages; private int loadsCount; private ArrayList admins; @@ -207,16 +248,15 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio private String searchQuery = ""; private LongSparseArray selectedAdmins; - private MessageObject scrollToMessage; - - private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(new int[]{ + private final static int[] allowedNotificationsDuringChatListAnimations = new int[]{ NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad - /*, NotificationCenter.botInfoDidLoad*/ - }); + }; + + private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(allowedNotificationsDuringChatListAnimations); private HashMap invitesCache = new HashMap<>(); private HashMap usersMap; @@ -297,7 +337,7 @@ public boolean onFragmentCreate() { Bulletin.addDelegate(this, new Bulletin.Delegate() { @Override public int getBottomOffset(int tag) { - return AndroidUtilities.dp(51); + return dp(51); } }); @@ -321,21 +361,99 @@ private void updateEmptyPlaceholder() { return; } if (!TextUtils.isEmpty(searchQuery)) { - emptyView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(5), AndroidUtilities.dp(8), AndroidUtilities.dp(5)); - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("EventLogEmptyTextSearch", R.string.EventLogEmptyTextSearch, searchQuery))); + emptyImageView.setVisibility(View.GONE); + emptyView.setPadding(dp(8), dp(3), dp(8), dp(3)); + emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.NoLogFound))); } else if (selectedAdmins != null || currentFilter != null) { - emptyView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(5), AndroidUtilities.dp(8), AndroidUtilities.dp(5)); - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmptySearch", R.string.EventLogEmptySearch))); + emptyImageView.setVisibility(View.GONE); + emptyView.setPadding(dp(8), dp(3), dp(8), dp(3)); + emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.NoLogFoundFiltered))); } else { - emptyView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + emptyImageView.setVisibility(View.VISIBLE); + emptyView.setPadding(dp(16), dp(16), dp(16), dp(16)); if (currentChat.megagroup) { - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmpty", R.string.EventLogEmpty))); + emptyView.setText(smallerNewNewLine(AndroidUtilities.replaceTags(getString(R.string.EventLogEmpty2)))); } else { - emptyView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EventLogEmptyChannel", R.string.EventLogEmptyChannel))); + emptyView.setText(smallerNewNewLine(AndroidUtilities.replaceTags(getString(R.string.EventLogEmptyChannel2)))); } } } + private CharSequence smallerNewNewLine(CharSequence cs) { + int index = AndroidUtilities.charSequenceIndexOf(cs, "\n\n"); + if (index >= 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (!(cs instanceof Spannable)) + cs = new SpannableStringBuilder(cs); + ((SpannableStringBuilder) cs).setSpan(new LineHeightSpan.Standard(dp(8)), index + 1, index + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return cs; + } + + public void reloadLastMessages() { + if (reloadingLastMessages) { + return; + } + reloadingLastMessages = true; + TLRPC.TL_channels_getAdminLog req = new TLRPC.TL_channels_getAdminLog(); + req.channel = MessagesController.getInputChannel(currentChat); + req.q = searchQuery; + req.limit = 10; + req.max_id = 0; + req.min_id = 0; + if (currentFilter != null) { + req.flags |= 1; + req.events_filter = currentFilter; + } + if (selectedAdmins != null) { + req.flags |= 2; + for (int a = 0; a < selectedAdmins.size(); a++) { + req.admins.add(MessagesController.getInstance(currentAccount).getInputUser(selectedAdmins.valueAt(a))); + } + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (response != null) { + final TLRPC.TL_channels_adminLogResults res = (TLRPC.TL_channels_adminLogResults) response; + AndroidUtilities.runOnUIThread(() -> { + reloadingLastMessages = false; + chatListItemAnimator.setShouldAnimateEnterFromBottom(false); + saveScrollPosition(false); + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + + ArrayList messages = new ArrayList<>(); + HashMap> messagesByDays = new HashMap<>(); + boolean added = false; + for (int a = 0; a < res.events.size(); a++) { + TLRPC.TL_channelAdminLogEvent event = res.events.get(a); + if (messagesDict.indexOfKey(event.id) >= 0) { + continue; + } + if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin) { + TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin action = (TLRPC.TL_channelAdminLogEventActionParticipantToggleAdmin) event.action; + if (action.prev_participant instanceof TLRPC.TL_channelParticipantCreator && !(action.new_participant instanceof TLRPC.TL_channelParticipantCreator)) { + continue; + } + } + minEventId = Math.min(minEventId, event.id); + MessageObject messageObject = new MessageObject(currentAccount, event, messages, messagesByDays, currentChat, mid, false); + if (messageObject.contentType < 0 || messageObject.currentEvent != null && messageObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) { + continue; + } + if (!messagesDict.containsKey(event.id)) { + added = true; + this.messages.add(0, messageObject); + messagesDict.put(event.id, messageObject); + } + } + if (chatAdapter != null && added) { + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + } + }); + } + }); + } + private void loadMessages(boolean reset) { if (loading) { return; @@ -350,6 +468,8 @@ private void loadMessages(boolean reset) { messagesDict.clear(); messages.clear(); messagesByDays.clear(); + filterDeletedMessages(); + loadsCount = 0; } loading = true; TLRPC.TL_channels_getAdminLog req = new TLRPC.TL_channels_getAdminLog(); @@ -372,12 +492,15 @@ private void loadMessages(boolean reset) { req.admins.add(MessagesController.getInstance(currentAccount).getInputUser(selectedAdmins.valueAt(a))); } } + loadsCount++; updateEmptyPlaceholder(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { final TLRPC.TL_channels_adminLogResults res = (TLRPC.TL_channels_adminLogResults) response; AndroidUtilities.runOnUIThread(() -> { + loadsCount--; chatListItemAnimator.setShouldAnimateEnterFromBottom(false); + saveScrollPosition(false); MessagesController.getInstance(currentAccount).putUsers(res.users, false); MessagesController.getInstance(currentAccount).putChats(res.chats, false); boolean added = false; @@ -402,31 +525,54 @@ private void loadMessages(boolean reset) { messagesDict.put(event.id, messageObject); } int newRowsCount = messages.size() - oldRowsCount; + + ArrayList missingReplies = new ArrayList<>(); + for (int i = oldRowsCount; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg != null && msg.contentType != 0 && msg.getRealId() >= 0) { + realMessagesDict.put(msg.getRealId(), msg); + } + if (msg == null || msg.messageOwner == null || msg.messageOwner.reply_to == null) { + continue; + } + TLRPC.MessageReplyHeader replyTo = msg.messageOwner.reply_to; + if (replyTo.reply_to_peer_id == null) { + MessageObject replyMessage = null; + for (int j = 0; j < messages.size(); ++j) { + if (i == j) continue; + MessageObject msg2 = messages.get(j); + if (msg2.contentType != 1 && msg2.getRealId() == replyTo.reply_to_msg_id) { + replyMessage = msg2; + break; + } + } + if (replyMessage != null) { + msg.replyMessageObject = replyMessage; + } + } + missingReplies.add(msg); + } + if (!missingReplies.isEmpty()) { + MediaDataController.getInstance(currentAccount).loadReplyMessagesForMessages(missingReplies, -currentChat.id, ChatActivity.MODE_DEFAULT, 0, () -> { + saveScrollPosition(false); + chatAdapter.notifyDataSetChanged(); + }, getClassGuid()); + } + filterDeletedMessages(); + loading = false; if (!added) { endReached = true; } AndroidUtilities.updateViewVisibilityAnimated(progressView, false, 0.3f, true); chatListView.setEmptyView(emptyViewContainer); - if (newRowsCount != 0) { - boolean end = false; - if (endReached) { - end = true; - chatAdapter.notifyItemRangeChanged(0, 2); - } - int firstVisPos = chatLayoutManager.findLastVisibleItemPosition(); - View firstVisView = chatLayoutManager.findViewByPosition(firstVisPos); - int top = ((firstVisView == null) ? 0 : firstVisView.getTop()) - chatListView.getPaddingTop(); - if (newRowsCount - (end ? 1 : 0) > 0) { - int insertStart = 1 + (end ? 0 : 1); - chatAdapter.notifyItemChanged(insertStart); - chatAdapter.notifyItemRangeInserted(insertStart, newRowsCount - (end ? 1 : 0)); - } - if (firstVisPos != -1) { - chatLayoutManager.scrollToPositionWithOffset(firstVisPos + newRowsCount - (end ? 1 : 0), top); - } - } else if (endReached) { - chatAdapter.notifyItemRemoved(0); + + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(); + } + + if (searchItem != null) { + searchItem.setVisibility(filteredMessages.isEmpty() && TextUtils.isEmpty(searchQuery) ? View.GONE : View.VISIBLE); } }); } @@ -436,6 +582,172 @@ private void loadMessages(boolean reset) { } } + private final ArrayList filteredMessagesUpdatedPosition = new ArrayList<>(); + private void filterDeletedMessages() { + ArrayList newFilteredMessages = new ArrayList<>(); + + ArrayList currentDeleteGroup = new ArrayList<>(); + filteredMessagesUpdatedPosition.clear(); + for (int i = 0; i < messages.size(); ++i) { + MessageObject message = messages.get(i); + long thisMessageDeletedBy = messageDeletedBy(message); + + if (message.stableId <= 0) { + message.stableId = lastStableId++; + } + + MessageObject nextMessage = i + 1 < messages.size() ? messages.get(i + 1) : null; + long nextMessageDeletedBy = messageDeletedBy(nextMessage); + + if (thisMessageDeletedBy != 0) { + currentDeleteGroup.add(message); + } else { + newFilteredMessages.add(message); + } + if (thisMessageDeletedBy != nextMessageDeletedBy && !currentDeleteGroup.isEmpty()) { + boolean wasKeyboard = message.messageOwner.reply_markup != null && !(message.messageOwner.reply_markup.rows.isEmpty()); + int index = newFilteredMessages.size(); + ArrayList separatedFirstActions = new ArrayList<>(); + for (int j = currentDeleteGroup.size() - 1; j >= 0; j--) { + if (currentDeleteGroup.get(j).contentType == 1) { + separatedFirstActions.add(currentDeleteGroup.remove(j)); + } else { + break; + } + } + if (!currentDeleteGroup.isEmpty()) { + MessageObject lastMessage = currentDeleteGroup.get(currentDeleteGroup.size() - 1); + boolean expandable = TextUtils.isEmpty(searchQuery) && currentDeleteGroup.size() > 3; + if (expandedEvents.contains(lastMessage.eventId) || !expandable) { + for (int k = 0; k < currentDeleteGroup.size(); ++k) { + setupExpandButton(currentDeleteGroup.get(k), 0); + } + newFilteredMessages.addAll(currentDeleteGroup); + } else { + setupExpandButton(lastMessage, currentDeleteGroup.size() - 1); + newFilteredMessages.add(lastMessage); + } + if (wasKeyboard != (lastMessage.messageOwner.reply_markup != null && !(lastMessage.messageOwner.reply_markup.rows.isEmpty()))) { + lastMessage.forceUpdate = true; + chatAdapter.notifyItemChanged(index + (wasKeyboard ? currentDeleteGroup.size() - 1 : 0)); + chatAdapter.notifyItemChanged(index + (wasKeyboard ? currentDeleteGroup.size() - 1 : 0) + 1); + } + newFilteredMessages.add(actionMessagesDeletedBy(message.eventId, message.currentEvent.user_id, currentDeleteGroup, expandedEvents.contains(message.eventId), expandable)); + } + if (!separatedFirstActions.isEmpty()) { + MessageObject lastMessage = separatedFirstActions.get(separatedFirstActions.size() - 1); + newFilteredMessages.addAll(separatedFirstActions); + newFilteredMessages.add(actionMessagesDeletedBy(lastMessage.eventId, lastMessage.currentEvent.user_id, separatedFirstActions, true, false)); + } + currentDeleteGroup.clear(); + } + } + filteredMessages.clear(); + filteredMessages.addAll(newFilteredMessages); + } + + private final LongSparseArray stableIdByEventExpand = new LongSparseArray<>(); + private MessageObject actionMessagesDeletedBy(long eventId, long user_id, ArrayList messages, boolean expanded, boolean expandable) { + MessageObject messageObject = null; + for (int i = 0; i < filteredMessages.size(); ++i) { + MessageObject messageObject1 = filteredMessages.get(i); + if (messageObject1 != null && messageObject1.contentType == 1 && messageObject1.actionDeleteGroupEventId == eventId) { + messageObject = messageObject1; + break; + } + } + if (messageObject == null) { + TLRPC.TL_message msg = new TLRPC.TL_message(); + msg.dialog_id = -currentChat.id; + msg.id = -1; + try { + msg.date = messages.get(0).messageOwner.date; + } catch (Exception e) { + FileLog.e(e); + } + messageObject = new MessageObject(currentAccount, msg, false, false); + } + TLRPC.User user = getMessagesController().getUser(user_id); + messageObject.contentType = 1; + if (expandable && messages.size() > 1) { + messageObject.actionDeleteGroupEventId = eventId; + } else { + messageObject.actionDeleteGroupEventId = -1; + } + String names = TextUtils.join(", ", messages.stream().map(MessageObject::getFromChatId).distinct().map(dialogId -> { + if (dialogId < 0) { + TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + if (chat == null) return null; + return chat.title; + } else { + return UserObject.getForcedFirstName(getMessagesController().getUser(dialogId)); + } + }).filter(s -> s != null).limit(4).toArray()); + SpannableStringBuilder ssb = new SpannableStringBuilder(replaceWithLink(LocaleController.formatPluralString(expandable ? "EventLogDeletedMultipleMessagesToExpand" : "EventLogDeletedMultipleMessages", messages.size(), names), "un1", user)); + if (expandable && messages.size() > 1) { + ProfileActivity.ShowDrawable drawable = findDrawable(messageObject.messageText); + if (drawable == null) { + drawable = new ProfileActivity.ShowDrawable(getString(expanded ? R.string.EventLogDeletedMultipleMessagesHide : R.string.EventLogDeletedMultipleMessagesShow)); + drawable.textDrawable.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + drawable.textDrawable.setTextSize(dp(10)); + drawable.setTextColor(Color.WHITE); + drawable.setBackgroundColor(0x1e000000); + } else { + drawable.textDrawable.setText(getString(expanded ? R.string.EventLogDeletedMultipleMessagesHide : R.string.EventLogDeletedMultipleMessagesShow), false); + } + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + ssb.append(" S"); + ssb.setSpan(new ColoredImageSpan(drawable), ssb.length() - 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + messageObject.messageText = ssb; + MessageObject lastMessage = messages.size() <= 0 ? null : messages.get(messages.size() - 1); + if (lastMessage != null) { + if (!stableIdByEventExpand.containsKey(lastMessage.eventId)) + stableIdByEventExpand.put(lastMessage.eventId, lastStableId++); + messageObject.stableId = stableIdByEventExpand.get(lastMessage.eventId); + } + return messageObject; + } + + public static ProfileActivity.ShowDrawable findDrawable(CharSequence messageText) { + if (messageText instanceof Spannable) { + ColoredImageSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), ColoredImageSpan.class); + for (int i = 0; i < spans.length; ++i) { + if (spans[i] != null && spans[i].drawable instanceof ProfileActivity.ShowDrawable) { + return (ProfileActivity.ShowDrawable) spans[i].drawable; + } + } + } + return null; + } + + private void setupExpandButton(MessageObject msg, int count) { + if (msg == null) { + return; + } + if (count <= 0) { + if (msg.messageOwner.reply_markup != null) { + msg.messageOwner.reply_markup.rows.clear(); + } + } else { + TLRPC.TL_replyInlineMarkup markup = new TLRPC.TL_replyInlineMarkup(); + msg.messageOwner.reply_markup = markup; + TLRPC.TL_keyboardButtonRow row = new TLRPC.TL_keyboardButtonRow(); + markup.rows.add(row); + TLRPC.TL_keyboardButton button = new TLRPC.TL_keyboardButton(); + button.text = LocaleController.formatPluralString("EventLogExpandMore", count); + row.buttons.add(button); + } + msg.measureInlineBotButtons(); + } + + private long messageDeletedBy(MessageObject msg) { + if (msg == null || msg.currentEvent == null || !(msg.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage)) { + return 0; + } + return msg.currentEvent.user_id; + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.emojiLoaded) { @@ -598,15 +910,68 @@ public void onSearchPressed(EditText editText) { //updateSearchButtons(0, 0, 0); } }); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(getString("Search", R.string.Search)); avatarContainer.setEnabled(false); avatarContainer.setTitle(currentChat.title); - avatarContainer.setSubtitle(LocaleController.getString("EventLogAllEvents", R.string.EventLogAllEvents)); + avatarContainer.setSubtitle(getString("EventLogAllEvents", R.string.EventLogAllEvents)); avatarContainer.setChatAvatar(currentChat); fragmentView = new SizeNotifierFrameLayout(context) { + final AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { + + @Override + protected void onTransitionStart(boolean keyboardVisible, int contentHeight) { + wasManualScroll = true; + } + + @Override + protected void onTransitionEnd() { + + } + + @Override + protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { + if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { + return; + } + contentPanTranslation = y; + contentPanTranslationT = progress; + actionBar.setTranslationY(y); + if (emptyViewContainer != null) { + emptyViewContainer.setTranslationY(y / 2); + } + progressView.setTranslationY(y / 2); + contentView.setBackgroundTranslation((int) y); + setFragmentPanTranslationOffset((int) y); +// invalidateChatListViewTopPadding(); +// invalidateMessagesVisiblePart(); + chatListView.invalidate(); +// updateBulletinLayout(); + if (AndroidUtilities.isTablet() && getParentActivity() instanceof LaunchActivity) { + BaseFragment mainFragment = ((LaunchActivity)getParentActivity()).getActionBarLayout().getLastFragment(); + if (mainFragment instanceof DialogsActivity) { + ((DialogsActivity)mainFragment).setPanTranslationOffset(y); + } + } + } + + @Override + protected boolean heightAnimationEnabled() { + INavigationLayout actionBarLayout = getParentLayout(); + if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null) { + return false; + } + if (System.currentTimeMillis() - activityResumeTime < 250) { + return false; + } + if ((ChannelAdminLogActivity.this == actionBarLayout.getLastFragment() && actionBarLayout.isTransitionAnimationInProgress()) || actionBarLayout.isPreviewOpenAnimationInProgress() || isPaused || !openAnimationEnded) { + return false; + } + return true; + } + }; @Override protected void onAttachedToWindow() { @@ -655,7 +1020,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (child == chatListView || child == progressView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); - int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - AndroidUtilities.dp(48 + 2)), MeasureSpec.EXACTLY); + int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(dp(10), heightSize - dp(48 + 2)), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == emptyViewContainer) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); @@ -722,7 +1087,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } if (child == emptyViewContainer) { - childTop -= AndroidUtilities.dp(24) - (actionBar.getVisibility() == VISIBLE ? actionBar.getMeasuredHeight() / 2 : 0); + childTop -= dp(24) - (actionBar.getVisibility() == VISIBLE ? actionBar.getMeasuredHeight() / 2 : 0); } else if (child == actionBar) { childTop -= getPaddingTop(); } else if (child == backgroundView) { @@ -755,16 +1120,39 @@ public boolean dispatchTouchEvent(MotionEvent ev) { contentView.addView(emptyViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); emptyViewContainer.setOnTouchListener((v, event) -> true); - emptyView = new TextView(context); + emptyLayoutView = new LinearLayout(context); + emptyLayoutView.setBackground(Theme.createServiceDrawable(dp(12), emptyView, contentView)); + emptyLayoutView.setOrientation(LinearLayout.VERTICAL); + + emptyImageView = new ImageView(context); + emptyImageView.setScaleType(ImageView.ScaleType.CENTER); + emptyImageView.setImageResource(R.drawable.large_log_actions); + emptyImageView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); + emptyImageView.setVisibility(View.GONE); + emptyLayoutView.addView(emptyImageView, LayoutHelper.createLinear(54, 54, Gravity.CENTER, 16, 20, 16, -4)); + + emptyView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(Math.min(MeasureSpec.getSize(widthMeasureSpec), dp(220)), MeasureSpec.getMode(widthMeasureSpec)), heightMeasureSpec); + } + }; emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(Theme.getColor(Theme.key_chat_serviceText)); - emptyView.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(6), emptyView, contentView)); - emptyView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); - emptyViewContainer.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 16, 0, 16, 0)); + emptyView.setPadding(dp(8), dp(5), dp(8), dp(5)); + emptyLayoutView.addView(emptyView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 0)); + + emptyViewContainer.addView(emptyLayoutView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 0)); chatListView = new RecyclerListView(context) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + applyScrolledPosition(); + super.onLayout(changed, l, t, r, b); + } + @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result = super.drawChild(canvas, child, drawingTime); @@ -772,6 +1160,7 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { ChatMessageCell chatMessageCell = (ChatMessageCell) child; ImageReceiver imageReceiver = chatMessageCell.getAvatarImage(); if (imageReceiver != null) { + boolean updateVisibility = !chatMessageCell.getMessageObject().deleted && chatListView.getChildAdapterPosition(chatMessageCell) != RecyclerView.NO_POSITION; if (chatMessageCell.getMessageObject().deleted) { imageReceiver.setVisible(false, false); return result; @@ -844,8 +1233,8 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { } } } - if (y - AndroidUtilities.dp(48) < top) { - y = top + AndroidUtilities.dp(48); + if (y - dp(48) < top) { + y = top + dp(48); } if (!chatMessageCell.drawPinnedBottom()) { int cellBottom = (int) (chatMessageCell.getY() + chatMessageCell.getMeasuredHeight()); @@ -862,7 +1251,9 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { y -= chatMessageCell.getTranslationY(); } } - imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + if (updateVisibility) { + imageReceiver.setImageY(y - dp(44)); + } if (chatMessageCell.shouldDrawAlphaLayer()) { imageReceiver.setAlpha(chatMessageCell.getAlpha()); canvas.scale( @@ -872,7 +1263,9 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { } else { imageReceiver.setAlpha(1f); } - imageReceiver.setVisible(true, false); + if (updateVisibility) { + imageReceiver.setVisible(true, false); + } imageReceiver.draw(canvas); canvas.restore(); } @@ -883,6 +1276,20 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { chatListView.setOnItemClickListener(new RecyclerListView.OnItemClickListenerExtended() { @Override public void onItemClick(View view, int position, float x, float y) { + if (view instanceof ChatActionCell) { + MessageObject messageObject = ((ChatActionCell) view).getMessageObject(); + if (messageObject != null && messageObject.actionDeleteGroupEventId != -1) { + if (expandedEvents.contains(messageObject.actionDeleteGroupEventId)) { + expandedEvents.remove(messageObject.actionDeleteGroupEventId); + } else { + expandedEvents.add(messageObject.actionDeleteGroupEventId); + } + saveScrollPosition(true); + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + return; + } + } createMenu(view, x, y); } }); @@ -890,15 +1297,15 @@ public void onItemClick(View view, int position, float x, float y) { chatListView.setVerticalScrollBarEnabled(true); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); - chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); - chatListView.setItemAnimator(chatListItemAnimator = new ChatListItemAnimator(null, chatListView, null) { + chatListView.setPadding(0, dp(4), 0, dp(3)); + chatListView.setItemAnimator(chatListItemAnimator = new ChatListItemAnimator(null, chatListView, resourceProvider) { int scrollAnimationIndex = -1; Runnable finishRunnable; public void onAnimationStart() { if (scrollAnimationIndex == -1) { - scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, null, false); + scrollAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollAnimationIndex, allowedNotificationsDuringChatListAnimations, false); } if (finishRunnable != null) { AndroidUtilities.cancelRunOnUIThread(finishRunnable); @@ -936,19 +1343,28 @@ public boolean supportsPredictiveItemAnimations() { @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + scrollByTouch = false; LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(recyclerView.getContext(), LinearSmoothScrollerCustom.POSITION_MIDDLE); linearSmoothScroller.setTargetPosition(position); startSmoothScroll(linearSmoothScroller); } + + @Override + public void scrollToPositionWithOffset(int position, int offset) { + super.scrollToPositionWithOffset(position, offset); + } }; chatLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); chatLayoutManager.setStackFromEnd(true); chatListView.setLayoutManager(chatLayoutManager); + chatScrollHelper = new RecyclerAnimationScrollHelper(chatListView, chatLayoutManager); + chatScrollHelper.setScrollListener(this::updateMessagesVisiblePart); + chatScrollHelper.setAnimationCallback(chatScrollHelperCallback); contentView.addView(chatListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { private float totalDy = 0; - private final int scrollValue = AndroidUtilities.dp(100); + private final int scrollValue = dp(100); @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { @@ -999,11 +1415,11 @@ public void onAnimationEnd(Animator animation) { contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); progressView2 = new View(context); - progressView2.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(18), progressView2, contentView)); + progressView2.setBackground(Theme.createServiceDrawable(dp(18), progressView2, contentView)); progressView.addView(progressView2, LayoutHelper.createFrame(36, 36, Gravity.CENTER)); progressBar = new RadialProgressView(context); - progressBar.setSize(AndroidUtilities.dp(28)); + progressBar.setSize(dp(28)); progressBar.setProgressColor(Theme.getColor(Theme.key_chat_serviceText)); progressView.addView(progressBar, LayoutHelper.createFrame(32, 32, Gravity.CENTER)); @@ -1024,21 +1440,21 @@ public void onDraw(Canvas canvas) { } }; bottomOverlayChat.setWillNotDraw(false); - bottomOverlayChat.setPadding(0, AndroidUtilities.dp(3), 0, 0); + bottomOverlayChat.setPadding(0, dp(3), 0, 0); contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); bottomOverlayChat.setOnClickListener(view -> { if (getParentActivity() == null) { return; } - AdminLogFilterAlert adminLogFilterAlert = new AdminLogFilterAlert(getParentActivity(), currentFilter, selectedAdmins, currentChat.megagroup); + AdminLogFilterAlert2 adminLogFilterAlert = new AdminLogFilterAlert2(this, currentFilter, selectedAdmins, currentChat.megagroup); adminLogFilterAlert.setCurrentAdmins(admins); adminLogFilterAlert.setAdminLogFilterAlertDelegate((filter, admins) -> { currentFilter = filter; selectedAdmins = admins; if (currentFilter != null || selectedAdmins != null) { - avatarContainer.setSubtitle(LocaleController.getString("EventLogSelectedEvents", R.string.EventLogSelectedEvents)); + avatarContainer.setSubtitle(getString("EventLogSelectedEvents", R.string.EventLogSelectedEvents)); } else { - avatarContainer.setSubtitle(LocaleController.getString("EventLogAllEvents", R.string.EventLogAllEvents)); + avatarContainer.setSubtitle(getString("EventLogAllEvents", R.string.EventLogAllEvents)); } loadMessages(true); }); @@ -1049,7 +1465,7 @@ public void onDraw(Canvas canvas) { bottomOverlayChatText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); bottomOverlayChatText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); bottomOverlayChatText.setTextColor(Theme.getColor(Theme.key_chat_fieldOverlayText)); - bottomOverlayChatText.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS).toUpperCase()); + bottomOverlayChatText.setText(getString("SETTINGS", R.string.SETTINGS).toUpperCase()); bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); bottomOverlayImage = new ImageView(context); @@ -1057,16 +1473,16 @@ public void onDraw(Canvas canvas) { bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_fieldOverlayText), PorterDuff.Mode.SRC_IN)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); bottomOverlayChat.addView(bottomOverlayImage, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 3, 0, 0, 0)); - bottomOverlayImage.setContentDescription(LocaleController.getString("BotHelp", R.string.BotHelp)); + bottomOverlayImage.setContentDescription(getString("BotHelp", R.string.BotHelp)); bottomOverlayImage.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); if (currentChat.megagroup) { - builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("EventLogInfoDetail", R.string.EventLogInfoDetail))); + builder.setMessage(AndroidUtilities.replaceTags(getString("EventLogInfoDetail", R.string.EventLogInfoDetail))); } else { - builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("EventLogInfoDetailChannel", R.string.EventLogInfoDetailChannel))); + builder.setMessage(AndroidUtilities.replaceTags(getString("EventLogInfoDetailChannel", R.string.EventLogInfoDetailChannel))); } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - builder.setTitle(LocaleController.getString("EventLogInfoTitle", R.string.EventLogInfoTitle)); + builder.setPositiveButton(getString("OK", R.string.OK), null); + builder.setTitle(getString("EventLogInfoTitle", R.string.EventLogInfoTitle)); showDialog(builder.create()); }); @@ -1084,7 +1500,7 @@ public void onDraw(Canvas canvas) { searchContainer.setFocusable(true); searchContainer.setFocusableInTouchMode(true); searchContainer.setClickable(true); - searchContainer.setPadding(0, AndroidUtilities.dp(3), 0, 0); + searchContainer.setPadding(0, dp(3), 0, 0); contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); /*searchUpButton = new ImageView(context); @@ -1141,7 +1557,7 @@ public void onClick(View view) { chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); undoView = new UndoView(context); - undoView.setAdditionalTranslationY(AndroidUtilities.dp(51)); + undoView.setAdditionalTranslationY(dp(51)); contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); updateEmptyPlaceholder(); @@ -1170,6 +1586,7 @@ private void closeMenu() { private final static int OPTION_CALL = 17; private final static int OPTION_RESTRICT = 33; private final static int OPTION_REPORT_FALSE_POSITIVE = 34; + private final static int OPTION_BAN = 35; private boolean createMenu(View v) { return createMenu(v, 0, 0); @@ -1200,15 +1617,15 @@ private boolean createMenu(View v, float x, float y) { SpannableString arrow = new SpannableString(">"); Drawable arrowDrawable = getContext().getResources().getDrawable(R.drawable.attach_arrow_right).mutate(); arrowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_undo_cancelColor), PorterDuff.Mode.MULTIPLY)); - arrowDrawable.setBounds(0, 0, AndroidUtilities.dp(10), AndroidUtilities.dp(10)); + arrowDrawable.setBounds(0, 0, dp(10), dp(10)); arrow.setSpan(new ImageSpan(arrowDrawable, DynamicDrawableSpan.ALIGN_CENTER), 0, arrow.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableStringBuilder link = new SpannableStringBuilder(); link - .append(LocaleController.getString("EventLogFilterGroupInfo", R.string.EventLogFilterGroupInfo)) + .append(getString("EventLogFilterGroupInfo", R.string.EventLogFilterGroupInfo)) .append(" ") .append(arrow) .append(" ") - .append(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators)); + .append(getString("ChannelAdministrators", R.string.ChannelAdministrators)); link.setSpan(new ClickableSpan() { @Override public void onClick(@NonNull View view) { @@ -1221,14 +1638,14 @@ public void updateDrawState(@NonNull TextPaint ds) { ds.setUnderlineText(false); } }, 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - CharSequence text = LocaleController.getString("ChannelAntiSpamInfo2", R.string.ChannelAntiSpamInfo2); + CharSequence text = getString("ChannelAntiSpamInfo2", R.string.ChannelAntiSpamInfo2); text = AndroidUtilities.replaceCharSequence("%s", text, link); - Bulletin bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, LocaleController.getString("ChannelAntiSpamUser", R.string.ChannelAntiSpamUser), text); + Bulletin bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString("ChannelAntiSpamUser", R.string.ChannelAntiSpamUser), text); bulletin.setDuration(Bulletin.DURATION_PROLONG); bulletin.show(); return true; } - items.add(LocaleController.getString("ReportFalsePositive", R.string.ReportFalsePositive)); + items.add(getString("ReportFalsePositive", R.string.ReportFalsePositive)); icons.add(R.drawable.msg_notspam); options.add(OPTION_REPORT_FALSE_POSITIVE); items.add(null); @@ -1237,10 +1654,11 @@ public void updateDrawState(@NonNull TextPaint ds) { } if (selectedObject.type == MessageObject.TYPE_TEXT || selectedObject.caption != null) { - items.add(LocaleController.getString("Copy", R.string.Copy)); + items.add(getString("Copy", R.string.Copy)); icons.add(R.drawable.msg_copy); options.add(OPTION_COPY); } + if (type == 1) { if (selectedObject.currentEvent != null && selectedObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionChangeStickerSet) { TLRPC.TL_channelAdminLogEventActionChangeStickerSet action = (TLRPC.TL_channelAdminLogEventActionChangeStickerSet) selectedObject.currentEvent.action; @@ -1277,77 +1695,77 @@ public void onAutoDeleteHistory(int ttl, int action) { } } else if (type == 3) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { - items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + items.add(getString("SaveToGIFs", R.string.SaveToGIFs)); icons.add(R.drawable.msg_gif); options.add(OPTION_SAVE_TO_GIFS); } } else if (type == 4) { if (selectedObject.isVideo()) { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (selectedObject.isMusic()) { - items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); + items.add(getString("SaveToMusic", R.string.SaveToMusic)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { - items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); + items.add(getString("SaveToGIFs", R.string.SaveToGIFs)); icons.add(R.drawable.msg_gif); options.add(OPTION_SAVE_TO_GIFS); } - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY); } } else if (type == 5) { - items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); + items.add(getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); icons.add(R.drawable.msg_language); options.add(OPTION_APPLY_FILE); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 10) { - items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); + items.add(getString("ApplyThemeFile", R.string.ApplyThemeFile)); icons.add(R.drawable.msg_theme); options.add(OPTION_APPLY_FILE); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 6) { - items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + items.add(getString("SaveToGallery", R.string.SaveToGallery)); icons.add(R.drawable.msg_gallery); options.add(OPTION_SAVE_TO_GALLERY2); - items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); + items.add(getString("SaveToDownloads", R.string.SaveToDownloads)); icons.add(R.drawable.msg_download); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); - items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); + items.add(getString("ShareFile", R.string.ShareFile)); icons.add(R.drawable.msg_share); options.add(OPTION_SHARE); } else if (type == 7) { if (selectedObject.isMask()) { - items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); + items.add(getString("AddToMasks", R.string.AddToMasks)); } else { - items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); + items.add(getString("AddToStickers", R.string.AddToStickers)); } icons.add(R.drawable.msg_sticker); options.add(OPTION_SAVE_STICKER); @@ -1358,15 +1776,15 @@ public void onAutoDeleteHistory(int ttl, int action) { user = MessagesController.getInstance(currentAccount).getUser(uid); } if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { - items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); + items.add(getString("AddContactTitle", R.string.AddContactTitle)); icons.add(R.drawable.msg_addcontact); options.add(OPTION_ADD_CONTACT); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { - items.add(LocaleController.getString("Copy", R.string.Copy)); + items.add(getString("Copy", R.string.Copy)); icons.add(R.drawable.msg_copy); options.add(OPTION_COPY_PHONE); - items.add(LocaleController.getString("Call", R.string.Call)); + items.add(getString("Call", R.string.Call)); icons.add(R.drawable.msg_calls); options.add(OPTION_CALL); } @@ -1375,12 +1793,12 @@ public void onAutoDeleteHistory(int ttl, int action) { boolean callbackSent = false; Runnable proceed = () -> { - if (options.isEmpty()) { + if (options.isEmpty() || getParentActivity() == null) { return; } ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, getResourceProvider(), 0); - popupLayout.setMinimumWidth(AndroidUtilities.dp(200)); + popupLayout.setMinimumWidth(dp(200)); Rect backgroundPaddings = new Rect(); Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); shadowDrawable.getPadding(backgroundPaddings); @@ -1391,8 +1809,11 @@ public void onAutoDeleteHistory(int ttl, int action) { popupLayout.addView(new ActionBarPopupWindow.GapView(getContext(), getResourceProvider()), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } else { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1, getResourceProvider()); - cell.setMinimumWidth(AndroidUtilities.dp(200)); + cell.setMinimumWidth(dp(200)); cell.setTextAndIcon(items.get(a), icons.get(a)); + if (options.get(a) == OPTION_BAN) { + cell.setColors(getThemedColor(Theme.key_text_RedBold), getThemedColor(Theme.key_text_RedRegular)); + } final Integer option = options.get(a); popupLayout.addView(cell); final int i = a; @@ -1443,17 +1864,17 @@ public void dismiss() { scrimPopupWindow.setClippingEnabled(true); scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); scrimPopupWindow.setFocusable(true); - scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupContainerLayout.measure(View.MeasureSpec.makeMeasureSpec(dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(dp(1000), View.MeasureSpec.AT_MOST)); scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); scrimPopupWindow.getContentView().setFocusableInTouchMode(true); popupLayout.setFitItems(true); - int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - AndroidUtilities.dp(28); - if (popupX < AndroidUtilities.dp(6)) { - popupX = AndroidUtilities.dp(6); - } else if (popupX > chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth()) { - popupX = chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - scrimPopupContainerLayout.getMeasuredWidth(); + int popupX = v.getLeft() + (int) x - scrimPopupContainerLayout.getMeasuredWidth() + backgroundPaddings.left - dp(28); + if (popupX < dp(6)) { + popupX = dp(6); + } else if (popupX > chatListView.getMeasuredWidth() - dp(6) - scrimPopupContainerLayout.getMeasuredWidth()) { + popupX = chatListView.getMeasuredWidth() - dp(6) - scrimPopupContainerLayout.getMeasuredWidth(); } if (AndroidUtilities.isTablet()) { int[] location = new int[2]; @@ -1461,21 +1882,21 @@ public void dismiss() { popupX += location[0]; } int totalHeight = contentView.getHeight(); - int height = scrimPopupContainerLayout.getMeasuredHeight() + AndroidUtilities.dp(48); + int height = scrimPopupContainerLayout.getMeasuredHeight() + dp(48); int keyboardHeight = contentView.measureKeyboardHeight(); - if (keyboardHeight > AndroidUtilities.dp(20)) { + if (keyboardHeight > dp(20)) { totalHeight += keyboardHeight; } int popupY; if (height < totalHeight) { popupY = (int) (chatListView.getY() + v.getTop() + y); - if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { - popupY += AndroidUtilities.dp(240) - height; + if (height - backgroundPaddings.top - backgroundPaddings.bottom > dp(240)) { + popupY += dp(240) - height; } - if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { - popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); - } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { - popupY = totalHeight - height - AndroidUtilities.dp(8); + if (popupY < chatListView.getY() + dp(24)) { + popupY = (int) (chatListView.getY() + dp(24)); + } else if (popupY > totalHeight - height - dp(8)) { + popupY = totalHeight - height - dp(8); } } else { popupY = inBubbleMode ? 0 : AndroidUtilities.statusBarHeight; @@ -1489,20 +1910,27 @@ public void dismiss() { if ( ChatObject.canBlockUsers(currentChat) && - message.currentEvent != null && message.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage && message.currentEvent.user_id == getMessagesController().telegramAntispamUserId && - message.messageOwner != null && message.messageOwner.from_id != null && !UserObject.isUserSelf(getMessagesController().getUser(message.messageOwner.from_id.user_id)) + message.currentEvent != null && message.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage && + message.messageOwner != null && message.messageOwner.from_id != null ) { TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id.user_id); - if (user != null) { + if (user != null && !UserObject.isUserSelf(user)) { callbackSent = true; - getMessagesController().checkIsInChat(true, currentChat, user, (isInChat, rights, rank) -> { - if (isInChat) { - items.add(LocaleController.getString("BanUser", R.string.BanUser)); - icons.add(R.drawable.msg_block2); - options.add(OPTION_RESTRICT); + getMessagesController().getChannelParticipant(currentChat, user, participant -> AndroidUtilities.runOnUIThread(() -> { + selectedParticipant = participant; + if (participant != null) { + if (ChatObject.canUserDoAction(currentChat, participant, ChatObject.ACTION_SEND) || ChatObject.canUserDoAction(currentChat, participant, ChatObject.ACTION_SEND_MEDIA)) { + items.add(getString(R.string.Restrict)); + icons.add(R.drawable.msg_block2); + options.add(OPTION_RESTRICT); + } + + items.add(getString(R.string.Ban)); + icons.add(R.drawable.msg_block); + options.add(OPTION_BAN); } - AndroidUtilities.runOnUIThread(proceed); - }); + proceed.run(); + })); } } if (!callbackSent) { @@ -1635,7 +2063,7 @@ private void processSelectedOption(int option) { switch (option) { case OPTION_COPY: { AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, true)); - BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(LocaleController.getString("MessageCopied", R.string.MessageCopied)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(getString("MessageCopied", R.string.MessageCopied)).show(); break; } case OPTION_SAVE_TO_GALLERY: { @@ -1653,6 +2081,7 @@ private void processSelectedOption(int option) { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } MediaController.saveFile(path, getParentActivity(), selectedObject.type == MessageObject.TYPE_VIDEO ? 1 : 0, null, null); @@ -1696,9 +2125,14 @@ private void processSelectedOption(int option) { scrollToPositionOnRecreate = -1; if (getParentActivity() == null) { selectedObject = null; + selectedParticipant = null; return; } - AlertUtil.showToast(LocaleController.getString("IncorrectTheme", R.string.IncorrectTheme)); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setMessage(getString("IncorrectTheme", R.string.IncorrectTheme)); + builder.setPositiveButton(getString("OK", R.string.OK), null); + showDialog(builder.create()); } } else { if (LocaleController.getInstance().applyLanguageFile(locFile, currentAccount)) { @@ -1706,9 +2140,14 @@ private void processSelectedOption(int option) { } else { if (getParentActivity() == null) { selectedObject = null; + selectedParticipant = null; return; } - AlertUtil.showToast(LocaleController.getString("IncorrectLocalization", R.string.IncorrectLocalization)); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setMessage(getString("IncorrectLocalization", R.string.IncorrectLocalization)); + builder.setPositiveButton(getString("OK", R.string.OK), null); + showDialog(builder.create()); } } } @@ -1738,7 +2177,7 @@ private void processSelectedOption(int option) { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); } try { - getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); + getParentActivity().startActivityForResult(Intent.createChooser(intent, getString("ShareFile", R.string.ShareFile)), 500); } catch (Exception e) { } @@ -1758,6 +2197,7 @@ private void processSelectedOption(int option) { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } MediaController.saveFile(path, getParentActivity(), 0, null, null); @@ -1771,6 +2211,7 @@ private void processSelectedOption(int option) { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; + selectedParticipant = null; return; } String fileName = FileLoader.getDocumentFileName(selectedObject.getDocument()); @@ -1805,7 +2246,7 @@ private void processSelectedOption(int option) { } case OPTION_COPY_PHONE: { AndroidUtilities.addToClipboard(selectedObject.messageOwner.media.phone_number); - BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(LocaleController.getString("PhoneCopied", R.string.PhoneCopied)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createCopyBulletin(getString("PhoneCopied", R.string.PhoneCopied)).show(); break; } case OPTION_CALL: { @@ -1825,18 +2266,47 @@ private void processSelectedOption(int option) { getConnectionsManager().sendRequest(req, (res, err) -> { AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.TL_boolTrue) { - BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, LocaleController.getString("ChannelAntiSpamFalsePositiveReported", R.string.ChannelAntiSpamFalsePositiveReported)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.msg_antispam, getString("ChannelAntiSpamFalsePositiveReported", R.string.ChannelAntiSpamFalsePositiveReported)).show(); } else if (res instanceof TLRPC.TL_boolFalse) { - BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString("UnknownError", R.string.UnknownError)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString("UnknownError", R.string.UnknownError)).show(); } else { - BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString("UnknownError", R.string.UnknownError)).show(); + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString("UnknownError", R.string.UnknownError)).show(); } }); }); break; } case OPTION_RESTRICT: { - getMessagesController().deleteParticipantFromChat(currentChat.id, getMessagesController().getInputPeer(selectedObject.messageOwner.from_id)); + if (selectedParticipant != null) { + TLRPC.User user = getMessagesController().getUser(DialogObject.getPeerDialogId(selectedParticipant.peer)); + if (selectedParticipant.banned_rights == null) { + selectedParticipant.banned_rights = new TLRPC.TL_chatBannedRights(); + } + selectedParticipant.banned_rights.send_plain = true; + selectedParticipant.banned_rights.send_messages = true; + selectedParticipant.banned_rights.send_media = true; + selectedParticipant.banned_rights.send_stickers = true; + selectedParticipant.banned_rights.send_gifs = true; + selectedParticipant.banned_rights.send_games = true; + selectedParticipant.banned_rights.send_inline = true; + selectedParticipant.banned_rights.send_polls = true; + selectedParticipant.banned_rights.send_photos = true; + selectedParticipant.banned_rights.send_videos = true; + selectedParticipant.banned_rights.send_roundvideos = true; + selectedParticipant.banned_rights.send_audios = true; + selectedParticipant.banned_rights.send_voices = true; + selectedParticipant.banned_rights.send_docs = true; + getMessagesController().setParticipantBannedRole(currentChat.id, user, null, selectedParticipant.banned_rights, true, getFragmentForAlert(1), () -> { + BulletinFactory.of(this).createSimpleBulletin(R.raw.ic_ban, AndroidUtilities.replaceTags(LocaleController.formatString(R.string.RestrictedParticipantSending, UserObject.getFirstName(user)))).show(false); + reloadLastMessages(); + }); + } + break; + } + case OPTION_BAN: { + getMessagesController().deleteParticipantFromChat(currentChat.id, getMessagesController().getInputPeer(selectedObject.messageOwner.from_id), false, false, () -> { + reloadLastMessages(); + }); if (currentChat != null && selectedObject.messageOwner.from_id instanceof TLRPC.TL_peerUser && BulletinFactory.canShowBulletin(this)) { TLRPC.User user = getMessagesController().getUser(selectedObject.messageOwner.from_id.user_id); if (user != null) { @@ -1847,6 +2317,7 @@ private void processSelectedOption(int option) { } } selectedObject = null; + selectedParticipant = null; } private int getMessageType(MessageObject messageObject) { @@ -1934,8 +2405,8 @@ private void loadAdmins() { admins.add(0, antispamParticipant); } } - if (visibleDialog instanceof AdminLogFilterAlert) { - ((AdminLogFilterAlert) visibleDialog).setCurrentAdmins(admins); + if (visibleDialog instanceof AdminLogFilterAlert2) { + ((AdminLogFilterAlert2) visibleDialog).setCurrentAdmins(admins); } } })); @@ -2006,9 +2477,9 @@ private void checkScrollForLoad(boolean scroll) { int totalItemCount = chatAdapter.getItemCount(); int checkLoadCount; if (scroll) { - checkLoadCount = 25; - } else { - checkLoadCount = 5; + checkLoadCount = 4; + } else { + checkLoadCount = 1; } if (firstVisibleItem <= checkLoadCount && !loading && !endReached) { loadMessages(false); @@ -2018,7 +2489,7 @@ private void checkScrollForLoad(boolean scroll) { private void moveScrollToLastMessage() { if (chatListView != null && !messages.isEmpty()) { - chatLayoutManager.scrollToPositionWithOffset(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + chatLayoutManager.scrollToPositionWithOffset(filteredMessages.size() - 1, -100000 - chatListView.getPaddingTop()); } } @@ -2080,7 +2551,7 @@ private void updateMessagesVisiblePart() { if (viewBottom > height) { viewBottom = viewTop + height; } - messageCell.setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - AndroidUtilities.dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); + messageCell.setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); MessageObject messageObject = messageCell.getMessageObject(); if (roundVideoContainer != null && messageObject.isRoundVideo() && MediaController.getInstance().isPlayingMessage(messageObject)) { @@ -2198,6 +2669,7 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { public void onResume() { super.onResume(); + activityResumeTime = System.currentTimeMillis(); if (contentView != null) { contentView.onResume(); } @@ -2260,10 +2732,10 @@ private void alertUserOpenError(MessageObject message) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setTitle(getString("AppName", R.string.AppName)); + builder.setPositiveButton(getString("OK", R.string.OK), null); if (message.type == MessageObject.TYPE_VIDEO) { - builder.setMessage(LocaleController.getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); + builder.setMessage(getString("NoPlayerInstalled", R.string.NoPlayerInstalled)); } else { builder.setMessage(LocaleController.formatString("NoHandleAppInstalled", R.string.NoHandleAppInstalled, message.getDocument().mime_type)); } @@ -2295,24 +2767,24 @@ public void showOpenUrlAlert(final String url, boolean ask) { Browser.openUrl(getParentActivity(), url, true); } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("OpenUrlTitle", R.string.OpenUrlTitle)); + builder.setTitle(getString("OpenUrlTitle", R.string.OpenUrlTitle)); builder.setMessage(LocaleController.formatString("OpenUrlAlert2", R.string.OpenUrlAlert2, url)); - builder.setPositiveButton(LocaleController.getString("Open", R.string.Open), (dialogInterface, i) -> Browser.openUrl(getParentActivity(), url, true)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(getString("Open", R.string.Open), (dialogInterface, i) -> Browser.openUrl(getParentActivity(), url, true)); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } } - private void removeMessageObject(MessageObject messageObject) { - int index = messages.indexOf(messageObject); - if (index == -1) { - return; - } - messages.remove(index); - if (chatAdapter != null) { - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + messages.size() - index - 1); - } - } +// private void removeMessageObject(MessageObject messageObject) { +// int index = messages.indexOf(messageObject); +// if (index == -1) { +// return; +// } +// messages.remove(index); +// if (chatAdapter != null) { +// chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + messages.size() - index - 1); +// } +// } public class ChatActivityAdapter extends RecyclerView.Adapter { @@ -2324,18 +2796,26 @@ public class ChatActivityAdapter extends RecyclerView.Adapter { public ChatActivityAdapter(Context context) { mContext = context; + setHasStableIds(true); } + private final ArrayList oldStableIds = new ArrayList<>(); + private final ArrayList stableIds = new ArrayList<>(); + public void updateRows() { + updateRows(true); + } + + public void updateRows(boolean animated) { rowCount = 0; - if (!messages.isEmpty()) { + if (!filteredMessages.isEmpty()) { if (!endReached) { loadingUpRow = rowCount++; } else { loadingUpRow = -1; } messagesStartRow = rowCount; - rowCount += messages.size(); + rowCount += filteredMessages.size(); messagesEndRow = rowCount; } else { loadingUpRow = -1; @@ -2350,8 +2830,20 @@ public int getItemCount() { } @Override - public long getItemId(int i) { - return RecyclerListView.NO_ID; + public long getItemId(int position) { + if (position >= messagesStartRow && position < messagesEndRow) { + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1).stableId; + } else if (position == loadingUpRow) { + return 2; + } + return 5; + } + + public MessageObject getMessageObject(int position) { + if (position >= messagesStartRow && position < messagesEndRow) { + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1); + } + return null; } @Override @@ -2367,6 +2859,23 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + @Override + public boolean shouldShowTopicButton() { + return ChatObject.isForum(currentChat); + } + + @Override + public void didPressTopicButton(ChatMessageCell cell) { + MessageObject message = cell.getMessageObject(); + if (message != null) { + Bundle args = new Bundle(); + args.putLong("chat_id", -message.getDialogId()); + ChatActivity chatActivity = new ChatActivity(args); + ForumUtilities.applyTopic(chatActivity, MessagesStorage.TopicKey.of(message.getDialogId(), MessageObject.getTopicId(currentAccount, message.messageOwner, true))); + presentFragment(chatActivity); + } + } + @Override public boolean canDrawOutboundsContent() { return true; @@ -2387,7 +2896,7 @@ public boolean needPlayMessage(ChatMessageCell cell, MessageObject messageObject MediaController.getInstance().setVoiceMessagesPlaylist(null, false); return result; } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(messages, messageObject, 0); + return MediaController.getInstance().setPlaylist(filteredMessages, messageObject, 0); } return false; } @@ -2489,7 +2998,7 @@ public void didPressUrl(ChatMessageCell cell, final CharacterStyle url, boolean if (url instanceof URLSpanMono) { ((URLSpanMono) url).copyToClipboard(); if (AndroidUtilities.shouldShowClipboardToast()) { - Toast.makeText(getParentActivity(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); + Toast.makeText(getParentActivity(), getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); } } else if (url instanceof URLSpanUserMention) { long peerId = Utilities.parseLong(((URLSpanUserMention) url).getURL()); @@ -2566,7 +3075,21 @@ public void needOpenWebView(MessageObject message, String url, String title, Str @Override public void didPressReplyMessage(ChatMessageCell cell, int id) { - + MessageObject messageObject = cell.getMessageObject(); + MessageObject reply = messageObject.replyMessageObject; + if (reply.getDialogId() == -currentChat.id) { + for (int i = 0; i < filteredMessages.size(); ++i) { + MessageObject msg = filteredMessages.get(i); + if (msg != null && msg.contentType != 1 && msg.getRealId() == reply.getRealId()) { + scrollToMessage(msg, true); + return; + } + } + } + Bundle args = new Bundle(); + args.putLong("chat_id", currentChat.id); + args.putInt("message_id", reply.getRealId()); + presentFragment(new ChatActivity(args)); } @Override @@ -2670,6 +3193,19 @@ public void didPressInstantButton(ChatMessageCell cell, int type) { } } } + + @Override + public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { + MessageObject messageObject = cell.getMessageObject(); + if (expandedEvents.contains(messageObject.eventId)) { + expandedEvents.remove(messageObject.eventId); + } else { + expandedEvents.add(messageObject.eventId); + } + saveScrollPosition(true); + filterDeletedMessages(); + chatAdapter.notifyDataSetChanged(); + } }); chatMessageCell.setAllowAssistant(true); } else if (viewType == 1) { @@ -2767,7 +3303,7 @@ public void needOpenInviteLink(final TLRPC.TL_chatInviteExported invite) { if (finalInvite != null) { showInviteLinkBottomSheet(finalInvite, usersMap); } else { - BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("LinkHashExpired", R.string.LinkHashExpired)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, getString("LinkHashExpired", R.string.LinkHashExpired)).show(); } }); }); @@ -2775,7 +3311,7 @@ public void needOpenInviteLink(final TLRPC.TL_chatInviteExported invite) { } else if (cachedInvite instanceof TLRPC.TL_messages_exportedChatInvite) { showInviteLinkBottomSheet((TLRPC.TL_messages_exportedChatInvite) cachedInvite, usersMap); } else { - BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("LinkHashExpired", R.string.LinkHashExpired)).show(); + BulletinFactory.of(ChannelAdminLogActivity.this).createSimpleBulletin(R.raw.linkbroken, getString("LinkHashExpired", R.string.LinkHashExpired)).show(); } } @@ -2795,10 +3331,6 @@ public void didPressReplyMessage(ChatActionCell cell, int id) { } - @Override - public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { - - } }); } else if (viewType == 2) { view = new ChatUnreadCell(mContext, null); @@ -2813,9 +3345,9 @@ public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; - loadingCell.setProgressVisible(loadsCount > 1); + loadingCell.setProgressVisible(true); } else if (position >= messagesStartRow && position < messagesEndRow) { - MessageObject message = messages.get(messages.size() - (position - messagesStartRow) - 1); + MessageObject message = filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1); View view = holder.itemView; if (view instanceof ChatMessageCell) { @@ -2826,20 +3358,34 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { boolean pinnedBotton; boolean pinnedTop; if (!(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { - MessageObject nextMessage = messages.get(messages.size() - (position + 1 - messagesStartRow) - 1); + MessageObject nextMessage = filteredMessages.get(filteredMessages.size() - (position + 1 - messagesStartRow) - 1); pinnedBotton = nextMessage.isOutOwner() == message.isOutOwner() && (nextMessage.getFromChatId() == message.getFromChatId()) && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; + if (pinnedBotton) { + long topicId = message.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, message.messageOwner, true) : message.replyToForumTopic.id; + long prevTopicId = nextMessage.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, nextMessage.messageOwner, true) : nextMessage.replyToForumTopic.id; + if (topicId != prevTopicId) { + pinnedBotton = false; + } + } } else { pinnedBotton = false; } if (prevType == holder.getItemViewType()) { - MessageObject prevMessage = messages.get(messages.size() - (position - messagesStartRow)); + MessageObject prevMessage = filteredMessages.get(filteredMessages.size() - (position - messagesStartRow)); pinnedTop = !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && (prevMessage.getFromChatId() == message.getFromChatId()) && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; + if (pinnedTop) { + long topicId = message.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, message.messageOwner, true) : message.replyToForumTopic.id; + long prevTopicId = prevMessage.replyToForumTopic == null ? MessageObject.getTopicId(currentAccount, prevMessage.messageOwner, true) : prevMessage.replyToForumTopic.id; + if (topicId != prevTopicId) { + pinnedTop = false; + } + } } else { pinnedTop = false; } messageCell.setMessageObject(message, null, pinnedBotton, pinnedTop); messageCell.setHighlighted(false); - messageCell.setHighlightedText(null); + messageCell.setHighlightedText(searchQuery); } else if (view instanceof ChatActionCell) { ChatActionCell actionCell = (ChatActionCell) view; actionCell.setMessageObject(message); @@ -2851,7 +3397,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { @Override public int getItemViewType(int position) { if (position >= messagesStartRow && position < messagesEndRow) { - return messages.get(messages.size() - (position - messagesStartRow) - 1).contentType; + return filteredMessages.get(filteredMessages.size() - (position - messagesStartRow) - 1).contentType; } return 4; } @@ -2875,7 +3421,7 @@ public boolean onPreDraw() { } if (holder.itemView instanceof ChatMessageCell) { - ((ChatMessageCell) view).setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - AndroidUtilities.dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); + ((ChatMessageCell) view).setVisiblePart(viewTop, viewBottom - viewTop, contentView.getHeightWithKeyboard() - dp(48) - chatListView.getTop(), 0, view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getMeasuredWidth(), contentView.getBackgroundSizeY(), 0, 0); } else if (holder.itemView instanceof ChatActionCell) { if (actionBar != null && contentView != null) { ((ChatActionCell) view).setVisiblePart(view.getY() + actionBar.getMeasuredHeight() - contentView.getBackgroundTranslationY(), contentView.getBackgroundSizeY()); @@ -2898,11 +3444,11 @@ public boolean onPreDraw() { } public void updateRowWithMessageObject(MessageObject messageObject) { - int index = messages.indexOf(messageObject); + int index = filteredMessages.indexOf(messageObject); if (index == -1) { return; } - notifyItemChanged(messagesStartRow + messages.size() - index - 1); + notifyItemChanged(messagesStartRow + filteredMessages.size() - index - 1); } @Override @@ -2917,7 +3463,7 @@ public void notifyDataSetChanged() { @Override public void notifyItemChanged(int position) { - updateRows(); + updateRows(false); try { super.notifyItemChanged(position); } catch (Exception e) { @@ -2927,7 +3473,7 @@ public void notifyItemChanged(int position) { @Override public void notifyItemRangeChanged(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeChanged(positionStart, itemCount); } catch (Exception e) { @@ -2937,7 +3483,7 @@ public void notifyItemRangeChanged(int positionStart, int itemCount) { @Override public void notifyItemInserted(int position) { - updateRows(); + updateRows(false); try { super.notifyItemInserted(position); } catch (Exception e) { @@ -2947,7 +3493,7 @@ public void notifyItemInserted(int position) { @Override public void notifyItemMoved(int fromPosition, int toPosition) { - updateRows(); + updateRows(false); try { super.notifyItemMoved(fromPosition, toPosition); } catch (Exception e) { @@ -2957,7 +3503,7 @@ public void notifyItemMoved(int fromPosition, int toPosition) { @Override public void notifyItemRangeInserted(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeInserted(positionStart, itemCount); } catch (Exception e) { @@ -2967,7 +3513,7 @@ public void notifyItemRangeInserted(int positionStart, int itemCount) { @Override public void notifyItemRemoved(int position) { - updateRows(); + updateRows(false); try { super.notifyItemRemoved(position); } catch (Exception e) { @@ -2977,7 +3523,7 @@ public void notifyItemRemoved(int position) { @Override public void notifyItemRangeRemoved(int positionStart, int itemCount) { - updateRows(); + updateRows(false); try { super.notifyItemRangeRemoved(positionStart, itemCount); } catch (Exception e) { @@ -2999,7 +3545,7 @@ public void permanentLinkReplaced(TLRPC.TL_chatInviteExported oldLink, TLRPC.TL_ @Override public void linkRevoked(TLRPC.TL_chatInviteExported invite) { TLRPC.TL_channelAdminLogEvent event = new TLRPC.TL_channelAdminLogEvent(); - int size = messages.size(); + int size = filteredMessages.size(); invite.revoked = true; TLRPC.TL_channelAdminLogEventActionExportedInviteRevoke revokeAction = new TLRPC.TL_channelAdminLogEventActionExportedInviteRevoke(); revokeAction.invite = invite; @@ -3010,7 +3556,8 @@ public void linkRevoked(TLRPC.TL_chatInviteExported invite) { if (messageObject.contentType < 0) { return; } - int addCount = messages.size() - size; + filterDeletedMessages(); + int addCount = filteredMessages.size() - size; if (addCount > 0) { chatListItemAnimator.setShouldAnimateEnterFromBottom(true); chatAdapter.notifyItemRangeInserted(chatAdapter.messagesEndRow, addCount); @@ -3021,7 +3568,7 @@ public void linkRevoked(TLRPC.TL_chatInviteExported invite) { @Override public void onLinkDeleted(TLRPC.TL_chatInviteExported invite) { - int size = messages.size(); + int size = filteredMessages.size(); int messagesEndRow = chatAdapter.messagesEndRow; TLRPC.TL_channelAdminLogEvent event = new TLRPC.TL_channelAdminLogEvent(); TLRPC.TL_channelAdminLogEventActionExportedInviteDelete deleteAction = new TLRPC.TL_channelAdminLogEventActionExportedInviteDelete(); @@ -3033,7 +3580,8 @@ public void onLinkDeleted(TLRPC.TL_chatInviteExported invite) { if (messageObject.contentType < 0) { return; } - int addCount = messages.size() - size; + filterDeletedMessages(); + int addCount = filteredMessages.size() - size; if (addCount > 0) { chatListItemAnimator.setShouldAnimateEnterFromBottom(true); chatAdapter.notifyItemRangeInserted(chatAdapter.messagesEndRow, addCount); @@ -3056,6 +3604,7 @@ public void onLinkEdited(TLRPC.TL_chatInviteExported invite) { if (messageObject.contentType < 0) { return; } + filterDeletedMessages(); chatAdapter.notifyDataSetChanged(); moveScrollToLastMessage(); } @@ -3277,4 +3826,431 @@ public ArrayList getThemeDescriptions() { return themeDescriptions; } + + public void scrollToMessage(MessageObject object, boolean select) { + wasManualScroll = true; + int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; + int scrollFromIndex = 0; + if (filteredMessages.size() > 0) { + int end = chatLayoutManager.findLastVisibleItemPosition(); + for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { + if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { + MessageObject messageObject = filteredMessages.get(i - chatAdapter.messagesStartRow); + if (messageObject.contentType == 1 || messageObject.getRealId() == 0 || messageObject.isSponsored()) { + continue; + } + scrollFromIndex = i - chatAdapter.messagesStartRow; + boolean scrollDown = messageObject.getRealId() < object.getRealId(); + scrollDirection = scrollDown ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + break; + } + } + } + + chatScrollHelper.setScrollDirection(scrollDirection); + if (object != null) { + int index = filteredMessages.indexOf(object); + if (index != -1) { + if (scrollFromIndex > 0) { + scrollDirection = scrollFromIndex > index ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP; + chatScrollHelper.setScrollDirection(scrollDirection); + } + removeSelectedMessageHighlight(); + if (select) { + highlightMessageId = object.getRealId(); + } + +// chatAdapter.updateRowsSafe(); + int position = chatAdapter.messagesStartRow + filteredMessages.indexOf(object); + + updateVisibleRows(); + boolean found = false; + int offsetY = 0; + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject != null && messageObject.getRealId() == object.getRealId()) { + found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + offsetY = scrollOffsetForQuote(messageObject); + } + } else if (view instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject != null && messageObject.getRealId() == object.getRealId()) { + found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + } + + if (found) { + int yOffset = getScrollOffsetForMessage(view.getHeight()) - offsetY; + int scrollY = (int) (view.getTop() - /*chatListViewPaddingTop - */yOffset); + int maxScrollOffset = chatListView.computeVerticalScrollRange() - chatListView.computeVerticalScrollOffset() - chatListView.computeVerticalScrollExtent(); + if (maxScrollOffset < 0) { + maxScrollOffset = 0; + } + if (scrollY > maxScrollOffset) { + scrollY = maxScrollOffset; + } + if (scrollY != 0) { +// scrollByTouch = false; + chatListView.smoothScrollBy(0, scrollY); + chatListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + } + break; + } + } + if (!found) { + int yOffset = getScrollOffsetForMessage(object); + chatScrollHelperCallback.scrollTo = object; + chatScrollHelperCallback.lastBottom = false; + chatScrollHelperCallback.lastItemOffset = yOffset; +// chatScrollHelperCallback.lastPadding = (int) chatListViewPaddingTop; + chatScrollHelper.setScrollDirection(scrollDirection); + chatScrollHelper.scrollToPosition(chatScrollHelperCallback.position = position, chatScrollHelperCallback.offset = yOffset, chatScrollHelperCallback.bottom = false, true); +// canShowPagedownButton = true; +// updatePagedownButtonVisibility(true); + } + } + } +// returnToMessageId = fromMessageId; +// returnToLoadIndex = loadIndex; +// needSelectFromMessageId = select; + } + + private boolean wasManualScroll; + private MessageObject scrollToMessage; + public int highlightMessageId = Integer.MAX_VALUE; + public boolean showNoQuoteAlert; + public String highlightMessageQuote; + public int highlightMessageQuoteOffset = -1; + private int scrollToMessagePosition = -10000; + private Runnable unselectRunnable; + + private void startMessageUnselect() { + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + } + unselectRunnable = () -> { + highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; + highlightMessageQuoteOffset = -1; + showNoQuoteAlert = false; + updateVisibleRows(); + unselectRunnable = null; + }; + AndroidUtilities.runOnUIThread(unselectRunnable, highlightMessageQuote != null ? 2500 : 1000); + } + + private void removeSelectedMessageHighlight() { + if (highlightMessageQuote != null) { + return; + } + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + unselectRunnable = null; + } + highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; + } + + private void updateVisibleRows() { + updateVisibleRows(false); + } + + private void updateVisibleRows(boolean suppressUpdateMessageObject) { + if (chatListView == null) { + return; + } + int lastVisibleItem = RecyclerView.NO_POSITION; + int top = 0; +// if (!wasManualScroll && unreadMessageObject != null) { +// int n = chatListView.getChildCount(); +// for (int i = 0; i < n; i++) { +// View child = chatListView.getChildAt(i); +// if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == unreadMessageObject) { +// int unreadMessageIndex = messages.indexOf(unreadMessageObject); +// if (unreadMessageIndex >= 0) { +// lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject); +// top = getScrollingOffsetForView(child); +// } +// break; +// } +// } +// } + int count = chatListView.getChildCount(); +// MessageObject editingMessageObject = chatActivityEnterView != null ? chatActivityEnterView.getEditingMessageObject() : null; +// long linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject == null) + continue; + + boolean disableSelection = false; + boolean selected = false; + if (actionBar.isActionModeShowed()) { + highlightMessageQuote = null; +// cell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(messageObject), true); +// int idx = messageObject.getDialogId() == dialog_id ? 0 : 1; +// if (selectedMessagesIds[idx].indexOfKey(messageObject.getId()) >= 0) { +// setCellSelectionBackground(messageObject, cell, idx, true); +// selected = true; +// } else { +// cell.setDrawSelectionBackground(false); +// cell.setChecked(false, false, true); +// } + disableSelection = true; + } else { + cell.setDrawSelectionBackground(false); + cell.setCheckBoxVisible(false, true); + cell.setChecked(false, false, true); + } + +// if ((!cell.getMessageObject().deleted || cell.linkedChatId != linkedChatId) && !suppressUpdateMessageObject) { +// cell.setIsUpdating(true); +// cell.linkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0; +// cell.setMessageObject(cell.getMessageObject(), cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop()); +// cell.setIsUpdating(false); +// } +// if (cell != scrimView) { +// cell.setCheckPressed(!disableSelection, disableSelection && selected); +// } + cell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageObject != null && messageObject.getRealId() == highlightMessageId); + if (highlightMessageId != Integer.MAX_VALUE) { + startMessageUnselect(); + } + if (cell.isHighlighted() && highlightMessageQuote != null) { + if (!cell.setHighlightedText(highlightMessageQuote, true, highlightMessageQuoteOffset) && showNoQuoteAlert) { + showNoQuoteFound(); + } + showNoQuoteAlert = false; + } else if (!TextUtils.isEmpty(searchQuery)) { + cell.setHighlightedText(searchQuery); + } else { + cell.setHighlightedText(null); + } + cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); + } else if (view instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) view; + if (!suppressUpdateMessageObject) { + cell.setMessageObject(cell.getMessageObject()); + } + cell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); + } + } + if (lastVisibleItem != RecyclerView.NO_POSITION) { + chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top); + } + } + + public void showNoQuoteFound() { + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, getString(R.string.QuoteNotFound)).show(true); + } + + + private ChatMessageCell dummyMessageCell; + private int getScrollOffsetForMessage(MessageObject object) { + return getScrollOffsetForMessage(getHeightForMessage(object, !TextUtils.isEmpty(highlightMessageQuote))) - scrollOffsetForQuote(object); + } + private int getScrollOffsetForMessage(int messageHeight) { + return (int) Math.max(-dp(2), (chatListView.getMeasuredHeight() - /*blurredViewBottomOffset - chatListViewPaddingTop - */messageHeight) / 2); + } + + private int scrollOffsetForQuote(MessageObject object) { + if (TextUtils.isEmpty(highlightMessageQuote) || object == null) { + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + return 0; + } + + int offsetY; + CharSequence text; + ArrayList textLayoutBlocks; +// if (object.getGroupId() != 0) { +// MessageObject.GroupedMessages group = getGroup(object.getGroupId()); +// if (dummyMessageCell == null || dummyMessageCell.computedCaptionLayout == null || group == null || group.captionMessage == null) { +// if (dummyMessageCell != null) { +// dummyMessageCell.computedGroupCaptionY = 0; +// dummyMessageCell.computedCaptionLayout = null; +// } +// return 0; +// } +// offsetY = dummyMessageCell.computedGroupCaptionY; +// text = group.captionMessage.caption; +// textLayoutBlocks = dummyMessageCell.computedCaptionLayout.textLayoutBlocks; +// } else + if (!TextUtils.isEmpty(object.caption) && dummyMessageCell != null && dummyMessageCell.captionLayout != null) { + offsetY = (int) dummyMessageCell.captionY; + text = object.caption; + textLayoutBlocks = dummyMessageCell.captionLayout.textLayoutBlocks; + } else { + offsetY = 0; + text = object.messageText; + textLayoutBlocks = object.textLayoutBlocks; + if (dummyMessageCell != null && dummyMessageCell.linkPreviewAbove) { + offsetY += dummyMessageCell.linkPreviewHeight + dp(10); + } + } + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + if (textLayoutBlocks == null || text == null) { + return 0; + } + + int index = MessageObject.findQuoteStart(text.toString(), highlightMessageQuote, highlightMessageQuoteOffset); + if (index < 0) { + return 0; + } + + for (int i = 0; i < textLayoutBlocks.size(); ++i) { + MessageObject.TextLayoutBlock block = textLayoutBlocks.get(i); + StaticLayout layout = block.textLayout; + String layoutText = layout.getText().toString(); + if (index > block.charactersOffset) { + final float y; + if (index - block.charactersOffset > layoutText.length() - 1) { + y = offsetY + (int) (block.textYOffset + block.padTop + block.height); + } else { + y = offsetY + block.textYOffset + block.padTop + layout.getLineTop(layout.getLineForOffset(index - block.charactersOffset)); + } + if (y > AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)) { + return (int) (y - AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)); + } + return 0; + } + } + return 0; + } + + private int getHeightForMessage(MessageObject object, boolean withGroupCaption) { + if (getParentActivity() == null) { + return 0; + } + if (dummyMessageCell == null) { + dummyMessageCell = new ChatMessageCell(getParentActivity()); + } + dummyMessageCell.isChat = currentChat != null; + dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; + return dummyMessageCell.computeHeight(object, null, withGroupCaption); + } + + public boolean isKeyboardVisible() { + return contentView.getKeyboardHeight() > dp(20); + } + + + private int scrollCallbackAnimationIndex; + + private final ChatScrollCallback chatScrollHelperCallback = new ChatScrollCallback(); + public class ChatScrollCallback extends RecyclerAnimationScrollHelper.AnimationCallback { + + private MessageObject scrollTo; + private int position = 0; + private boolean bottom = true; + private int offset = 0; + private int lastItemOffset; + private boolean lastBottom; + private int lastPadding; + + @Override + public void onStartAnimation() { + super.onStartAnimation(); + scrollCallbackAnimationIndex = getNotificationCenter().setAnimationInProgress(scrollCallbackAnimationIndex, allowedNotificationsDuringChatListAnimations); +// if (pinchToZoomHelper.isInOverlayMode()) { +// pinchToZoomHelper.finishZoom(); +// } + } + + @Override + public void onEndAnimation() { + if (scrollTo != null) { +// chatAdapter.updateRowsSafe(); + int lastItemPosition = chatAdapter.messagesStartRow + filteredMessages.indexOf(scrollTo); + if (lastItemPosition >= 0) { + chatLayoutManager.scrollToPositionWithOffset(lastItemPosition, (int) (lastItemOffset + lastPadding/* - chatListViewPaddingTop*/), lastBottom); + } + } else { +// chatAdapter.updateRowsSafe(); + chatLayoutManager.scrollToPositionWithOffset(position, offset, bottom); + } + scrollTo = null; + checkTextureViewPosition = true; + // chatListView.getOnScrollListener().onScrolled(chatListView, 0, chatScrollHelper.getScrollDirection() == RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN ? 1 : -1); + + updateVisibleRows(); + + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().onAnimationFinish(scrollCallbackAnimationIndex)); + } + + @Override + public void recycleView(View view) { + if (view instanceof ChatMessageCell) { + chatMessageCellsCache.add((ChatMessageCell) view); + } + } + } + + private long savedScrollEventId; + private int savedScrollPosition = -1; + private int savedScrollOffset; + public void saveScrollPosition(boolean fromTop) { + if (chatListView != null && chatLayoutManager != null && chatListView.getChildCount() > 0) { + View view = null; + int position = -1; + int top = fromTop ? Integer.MAX_VALUE : Integer.MIN_VALUE; + for (int i = 0; i < chatListView.getChildCount(); i++) { + View child = chatListView.getChildAt(i); + int childPosition = chatListView.getChildAdapterPosition(child); + if (childPosition >= 0 && (fromTop ? child.getTop() < top : child.getTop() > top)) { + view = child; + position = childPosition; + top = child.getTop(); + } + } + if (view != null) { + long eventId = 0; + if (view instanceof ChatMessageCell) { + eventId = ((ChatMessageCell) view).getMessageObject().eventId; + } else if (view instanceof ChatActionCell) { + eventId = ((ChatActionCell) view).getMessageObject().eventId; + } + savedScrollEventId = eventId; + savedScrollPosition = position; + savedScrollOffset = getScrollingOffsetForView(view); + } + } + } + + private int getScrollingOffsetForView(View v) { + return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); + } + + public void applyScrolledPosition() { + if (chatListView != null && chatLayoutManager != null && savedScrollPosition >= 0) { + int adaptedPosition = savedScrollPosition; + if (savedScrollEventId != 0) { + for (int i = 0; i < chatAdapter.getItemCount(); ++i) { + MessageObject msg = chatAdapter.getMessageObject(i); + if (msg != null && msg.eventId == savedScrollEventId) { + adaptedPosition = i; + break; + } + } + } + chatLayoutManager.scrollToPositionWithOffset(adaptedPosition, savedScrollOffset, true); + savedScrollPosition = -1; + savedScrollEventId = 0; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java index 5483884e14..663ffceae5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelColorActivity.java @@ -17,8 +17,10 @@ import android.graphics.BitmapShader; 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.PorterDuffXfermode; import android.graphics.Shader; @@ -39,6 +41,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -50,16 +53,21 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.DialogObject; +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.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ResultCallback; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; @@ -378,6 +386,13 @@ public void onItemClick(int id) { contentView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 68)); listView.setOnItemClickListener((view, position) -> { if (view instanceof EmojiCell) { + if (position == packStickerRow) { + if (chatFull == null) return; + GroupStickersActivity fragment = new GroupStickersActivity(-dialogId); + fragment.setInfo(chatFull); + presentFragment(fragment); + return; + } long selectedEmojiId = 0; if (position == replyEmojiRow) { selectedEmojiId = selectedReplyEmoji; @@ -878,6 +893,9 @@ public void dismiss() { protected int packEmojiRow; protected int packEmojiHintRow; + protected int packStickerRow; + protected int packStickerHintRow; + protected void updateRows() { rowsCount = 0; messagesPreviewRow = rowsCount++; @@ -926,6 +944,14 @@ protected int getEmojiPackInfoStrRes() { return 0; } + protected int getStickerPackStrRes() { + return 0; + } + + protected int getStickerPackInfoStrRes() { + return 0; + } + protected int getEmojiStatusInfoStrRes() { return R.string.ChannelEmojiStatusInfo; } @@ -1097,6 +1123,15 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } else { emojiCell.setEmoji(0, false); } + } else if (position == packStickerRow) { + emojiCell.setText(LocaleController.getString(getStickerPackStrRes())); + emojiCell.setLockLevel(0); + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.stickerset != null) { + emojiCell.setEmoji(getEmojiSetThumb(chatFull.stickerset), false); + } else { + emojiCell.setEmoji(0, false); + } } break; case VIEW_TYPE_SHADOW: @@ -1112,6 +1147,8 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi infoCell.setText(LocaleController.getString(getEmojiStatusInfoStrRes())); } else if (position == packEmojiHintRow) { infoCell.setText(LocaleController.getString(getEmojiPackInfoStrRes())); + } else if (position == packStickerHintRow) { + infoCell.setText(LocaleController.getString(getStickerPackInfoStrRes())); } else if (position == removeProfileColorShadowRow) { infoCell.setText(""); infoCell.setFixedSize(12); @@ -1165,7 +1202,7 @@ public int getItemViewType(int position) { return VIEW_TYPE_COLOR_REPLY_GRID; } else if (position == profileColorGridRow) { return VIEW_TYPE_COLOR_PROFILE_GRID; - } else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow || position == packEmojiRow) { + } else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow || position == packEmojiRow || position == packStickerRow) { return VIEW_TYPE_BUTTON_EMOJI; } else if (position == wallpaperRow || position == removeProfileColorRow) { return VIEW_TYPE_BUTTON; @@ -1230,6 +1267,7 @@ public void updateProfilePreview(boolean animated) { View emojiPicker = findChildAt(profileEmojiRow); View emojiStatusPicker = findChildAt(statusEmojiRow); View packEmojiPicker = findChildAt(packEmojiRow); + View packStatusPicker = findChildAt(packStickerRow); if (profilePreview instanceof ProfilePreview) { ((ProfilePreview) profilePreview).setColor(selectedProfileColor, animated); @@ -1259,6 +1297,14 @@ public void updateProfilePreview(boolean animated) { ((EmojiCell) packEmojiPicker).setEmoji(0, false); } } + if (packStatusPicker instanceof EmojiCell) { + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.stickerset != null) { + ((EmojiCell) packStatusPicker).setEmoji(getEmojiSetThumb(chatFull.stickerset), false); + } else { + ((EmojiCell) packStatusPicker).setEmoji(0, false); + } + } updateRows(); } @@ -1277,6 +1323,20 @@ private long getEmojiSetThumbId(TLRPC.StickerSet emojiSet) { return thumbDocumentId; } + private TLRPC.Document getEmojiSetThumb(TLRPC.StickerSet emojiSet) { + if (emojiSet == null) { + return null; + } + long thumbDocumentId = emojiSet.thumb_document_id; + if (thumbDocumentId == 0) { + TLRPC.TL_messages_stickerSet stickerSet = getMediaDataController().getGroupStickerSetById(emojiSet); + if (!stickerSet.documents.isEmpty()) { + return stickerSet.documents.get(0); + } + } + return null; + } + public View findChildAt(int position) { for (int i = 0; i < listView.getChildCount(); ++i) { View child = listView.getChildAt(i); @@ -1439,6 +1499,18 @@ public void setEmoji(long documentId, boolean animated) { } } + public void setEmoji(TLRPC.Document document, boolean animated) { + if (document == null) { + imageDrawable.set((Drawable) null, animated); + if (offText == null) { + offText = new Text(LocaleController.getString(R.string.ChannelReplyIconOff), 16); + } + } else { + imageDrawable.set(document, animated); + offText = null; + } + } + public void updateColors() { textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java index 50ae26a72f..fc3711facb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelMonetizationLayout.java @@ -92,6 +92,8 @@ public class ChannelMonetizationLayout extends FrameLayout { + public static ChannelMonetizationLayout instance; + private final BaseFragment fragment; private final Theme.ResourcesProvider resourcesProvider; private final int currentAccount; @@ -144,7 +146,7 @@ public ChannelMonetizationLayout( showLearnSheet(); }, resourcesProvider), true); balanceInfo = AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(MessagesController.getInstance(currentAccount).channelRevenueWithdrawalEnabled ? R.string.MonetizationBalanceInfo : R.string.MonetizationBalanceInfoNotAvailable), -1, REPLACING_TAG_TYPE_LINK_NBSP, () -> { - showLearnSheet(); + Browser.openUrl(getContext(), getString(R.string.MonetizationBalanceInfoLink)); }), true); setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); @@ -383,6 +385,7 @@ private void setBalance(long crypto_amount, long amount) { balanceSubtitle.setText("~" + BillingController.getInstance().formatCurrency(amount, "USD")); } + private double usd_rate; private void initLevel() { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); if (chat != null) { @@ -427,23 +430,8 @@ private void initLevel() { impressionsChart.useHourFormat = true; } - availableValue.crypto_amount = stats.available_balance; - availableValue.amount = (long) (availableValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - setBalance(availableValue.crypto_amount, availableValue.amount); - availableValue.currency = "USD"; - lastWithdrawalValue.crypto_amount = stats.current_balance; - lastWithdrawalValue.amount = (long) (lastWithdrawalValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - lastWithdrawalValue.currency = "USD"; - lifetimeValue.crypto_amount = stats.overall_revenue; - lifetimeValue.amount = (long) (lifetimeValue.crypto_amount / 1_000_000_000.0 * stats.usd_rate * 100.0); - lifetimeValue.currency = "USD"; - proceedsAvailable = true; - - balanceButton.setVisibility(stats.available_balance > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE); - - if (listView != null && listView.adapter != null) { - listView.adapter.update(true); - } + usd_rate = stats.usd_rate; + setupBalances(stats.balances); progress.animate().alpha(0).setDuration(380).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).withEndAction(() -> { progress.setVisibility(View.GONE); @@ -453,13 +441,41 @@ private void initLevel() { } }), null, null, 0, stats_dc, ConnectionsManager.ConnectionTypeGeneric, true); } + public void setupBalances(TLRPC.TL_broadcastRevenueBalances balances) { + if (usd_rate == 0) { + return; + } + availableValue.crypto_amount = balances.available_balance; + availableValue.amount = (long) (availableValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + setBalance(availableValue.crypto_amount, availableValue.amount); + availableValue.currency = "USD"; + lastWithdrawalValue.crypto_amount = balances.current_balance; + lastWithdrawalValue.amount = (long) (lastWithdrawalValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + lastWithdrawalValue.currency = "USD"; + lifetimeValue.crypto_amount = balances.overall_revenue; + lifetimeValue.amount = (long) (lifetimeValue.crypto_amount / 1_000_000_000.0 * usd_rate * 100.0); + lifetimeValue.currency = "USD"; + proceedsAvailable = true; + balanceButton.setVisibility(balances.available_balance > 0 || BuildVars.DEBUG_PRIVATE_VERSION ? View.VISIBLE : View.GONE); + + if (listView != null && listView.adapter != null) { + listView.adapter.update(true); + } + } @Override protected void onAttachedToWindow() { + instance = this; super.onAttachedToWindow(); checkLearnSheet(); } + @Override + protected void onDetachedFromWindow() { + instance = null; + super.onDetachedFromWindow(); + } + private void checkLearnSheet() { if (isAttachedToWindow() && proceedsAvailable && MessagesController.getGlobalMainSettings().getBoolean("monetizationadshint", true)) { showLearnSheet(); @@ -553,14 +569,22 @@ private void onClick(UItem item, View view, int position, float x, float y) { } } + public void reloadTransactions() { + if (loadingTransactions) return; + transactions.clear(); + transactionsTotalCount = 0; + loadingTransactions = false; + loadTransactions(); + } + private boolean loadingTransactions = false; private void loadTransactions() { if (loadingTransactions) return; if (transactions.size() >= transactionsTotalCount && transactionsTotalCount != 0) return; -// TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); -// if (chat == null || !chat.creator) { -// return; -// } + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chat == null || !chat.creator) { + return; + } loadingTransactions = true; TL_stats.TL_getBroadcastRevenueTransactions req = new TL_stats.TL_getBroadcastRevenueTransactions(); @@ -620,7 +644,7 @@ public static CharSequence replaceTON(CharSequence text, TextPaint textPaint, fl if (ChannelMonetizationLayout.tonString == null) { ChannelMonetizationLayout.tonString = new HashMap<>(); } - final int key = textPaint.getFontMetricsInt().bottom * (large ? 1 : -1) * (int) (100 * scale); + final int key = textPaint.getFontMetricsInt().bottom * (large ? 1 : -1) * (int) (100 * scale) - (int) (100 * translateY); SpannableString tonString = ChannelMonetizationLayout.tonString.get(key); if (tonString == null) { tonString = new SpannableString("T"); @@ -807,13 +831,13 @@ public void set(TL_stats.BroadcastRevenueTransaction transaction, boolean divide SpannableStringBuilder value = new SpannableStringBuilder(); value.append(type < 0 ? "-" : "+"); + value.append("TON "); value.append(formatter.format((Math.abs(amount) / 1_000_000_000.0))); - value.append(" TON"); int index = TextUtils.indexOf(value, "."); if (index >= 0) { value.setSpan(new RelativeSizeSpan(1.15f), 0, index + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - valueText.setText(value); + valueText.setText(replaceTON(value, valueText.getPaint(), 1.1f, dp(.33f), false)); valueText.setTextColor(Theme.getColor(type < 0 ? Theme.key_text_RedBold : Theme.key_avatar_nameInMessageGreen, resourcesProvider)); setWillNotDraw(!(needDivider = divider)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 9cdb8c8886..6b79e10aab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -169,6 +169,7 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; +import org.telegram.messenger.PushListenerController; import org.telegram.messenger.R; import org.telegram.messenger.SecretChatHelper; import org.telegram.messenger.SendMessagesHelper; @@ -273,6 +274,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.Stack; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @@ -472,6 +474,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private FrameLayout searchGoToBeginningButton; private ImageView searchGoToBeginningButtonArrow; + private HintView2 timeHint; private HintView2 savedMessagesHint; private HintView2 savedMessagesSearchHint; private HintView2 savedMessagesTagHint; @@ -1001,6 +1004,7 @@ public void run() { private boolean openImport; public float chatListViewPaddingTop; + public float paddingTopHeight; public int chatListViewPaddingVisibleOffset; private int contentPaddingTop; @@ -1122,8 +1126,8 @@ public void run() { NotificationCenter.pinnedInfoDidLoad, NotificationCenter.didSetNewWallpapper, NotificationCenter.savedMessagesDialogsUpdate, - NotificationCenter.didApplyNewTheme, - NotificationCenter.messageReceivedByServer + NotificationCenter.didApplyNewTheme +// NotificationCenter.messageReceivedByServer }; private final DialogInterface.OnCancelListener postponedScrollCancelListener = dialog -> { @@ -4866,7 +4870,14 @@ public void onDraw(Canvas c) { } c.translate(0, getMeasuredHeight() - blurredViewBottomOffset - transitionOffset); if (pullingDownDrawable == null) { - pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, themeDelegate); + pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, getTopicId(), themeDelegate); + if (nextChannels != null && !nextChannels.isEmpty()) { + pullingDownDrawable.updateDialog(nextChannels.get(0)); + } else if (isTopic) { + pullingDownDrawable.updateTopic(); + } else { + pullingDownDrawable.updateDialog(); + } pullingDownDrawable.onAttach(); } pullingDownDrawable.setWidth(getMeasuredWidth()); @@ -5897,6 +5908,7 @@ protected void onDetachedFromWindow() { chatListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA_SCALE); chatListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); chatListViewPaddingTop = 0; + paddingTopHeight = 0; invalidateChatListViewTopPadding(); if (MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)) { chatListItemAnimator = new ChatListItemAnimator(this, chatListView, themeDelegate) { @@ -6127,9 +6139,15 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi if (!foundTopView) { scrolled = super.scrollVerticallyBy(dy, recycler, state); } - if (!NekoConfig.disableSwipeToNext.Bool() && dy > 0 && scrolled == 0 && ChatObject.isChannel(currentChat) && chatMode != MODE_SAVED && !currentChat.megagroup && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && reportType < 0) { + if (!NekoConfig.disableSwipeToNext.Bool() && dy > 0 && scrolled == 0 && (ChatObject.isChannel(currentChat) && !currentChat.megagroup || isTopic) && chatMode != MODE_SAVED && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && !chatListView.isFastScrollAnimationRunning() && !chatListView.isMultiselect() && reportType < 0) { if (pullingDownOffset == 0 && pullingDownDrawable != null) { - pullingDownDrawable.updateDialog(); + if (nextChannels != null && !nextChannels.isEmpty()) { + pullingDownDrawable.updateDialog(nextChannels.get(0)); + } else if (isTopic) { + pullingDownDrawable.updateTopic(); + } else { + pullingDownDrawable.updateDialog(); + } } if (pullingDownBackAnimator != null) { pullingDownBackAnimator.removeAllListeners(); @@ -6376,6 +6394,9 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { AndroidUtilities.cancelRunOnUIThread(ChatActivity.this::checkBotMessageHint); AndroidUtilities.runOnUIThread(ChatActivity.this::checkBotMessageHint, 2000); } + if (timeHint != null && timeHint.shown()) { + timeHint.hide(); + } if (chatActivityEnterView != null) { chatActivityEnterView.hideHints(); } @@ -8480,6 +8501,37 @@ private void showBotMessageHint(ChatMessageCell cell, boolean byClick) { }); } + private void showTimeHint(ChatMessageCell cell) { + if (cell == null || cell.timeLayout == null || cell.getMessageObject() == null || + cell.getMessageObject().messageOwner == null || + (chatMode != MODE_DEFAULT && chatMode != MODE_PINNED && chatMode != MODE_SAVED) || + (NekoConfig.hideTimeForSticker.Bool() && cell.getMessageObject().isAnyKindOfSticker()) || + (NaConfig.INSTANCE.getRealHideTimeForSticker().Bool() && cell.getMessageObject().isAnyKindOfSticker()) + ) { + return; + } + if (timeHint != null) { + var hint = timeHint; + hint.setOnHiddenListener(() -> contentView.removeView(hint)); + hint.hide(); + timeHint = null; + } + timeHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM) + .setMultilineText(true) + .setDuration(2000); + + timeHint.setText(MessageHelper.INSTANCE.getTimeHintText(cell.getMessageObject())); + timeHint.setMaxWidthPx(contentView.getMeasuredWidth()); + contentView.addView(timeHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.TOP | Gravity.FILL_HORIZONTAL, 16, 0, 16, 0)); + contentView.post(() -> { + var loc = new int[2]; + cell.getLocationInWindow(loc); + timeHint.setTranslationY(loc[1] - timeHint.getTop() - dp(120) + cell.getTimeY()); + timeHint.setJointPx(0, -dp(16) + loc[0] + cell.timeX + cell.timeWidth - cell.timeTextWidth / 2f + cell.signWidth / 2f); + timeHint.show(); + }); + } + private void hideHints() { if (savedMessagesTagHint != null && savedMessagesTagHint.shown()) { savedMessagesTagHint.hide(); @@ -9536,7 +9588,7 @@ public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction tagSelector.setVisibility(View.VISIBLE); tagSelector.setHint(LocaleController.getString(tagSelector.getSelectedReactions().isEmpty() ? R.string.SavedTagReactionsSelectedAddHint : R.string.SavedTagReactionsSelectedEditHint)); contentView.addView(tagSelector, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 0, 0, 0)); - tagSelector.setMessage(null, null); + tagSelector.setMessage(null, null, true); tagSelector.setTranslationY(-dp(12)); tagSelector.setScaleY(.4f); tagSelector.setScaleX(.4f); @@ -10236,25 +10288,42 @@ private void animateToNextChat() { if (pullingDownDrawable == null) { return; } -// if (getParentLayout().fragmentsStack.size() > 1) { -// BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2); -// if (previousFragment instanceof ChatActivity) { -// getParentLayout().fragmentsStack.remove(getParentLayout().fragmentsStack.size() - 2); -// } -// } - addToPulledDialogsMyself(); - addToPulledDialogs(pullingDownDrawable.nextChat, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); - Bundle bundle = new Bundle(); - bundle.putLong("chat_id", pullingDownDrawable.getChatId()); - bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); - bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); - bundle.putBoolean("pulled", true); - SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); - sharedPreferences.edit().remove("diditem" + pullingDownDrawable.nextDialogId).apply(); - ChatActivity chatActivity = new ChatActivity(bundle); - chatActivity.setPullingDownTransition(true); - replacingChatActivity = true; - presentFragment(chatActivity, true); + if (isTopic) { + if (pullingDownDrawable.getTopic() != null) { + addToPulledTopicsMyself(); + addToPulledDialogs(currentChat, pullingDownDrawable.nextTopic, dialog_id, dialogFolderId, dialogFilterId); + Bundle bundle = new Bundle(); + bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); + bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); + bundle.putBoolean("pulled", true); + ChatActivity chatActivity = ForumUtilities.getChatActivityForTopic(ChatActivity.this, -dialog_id, pullingDownDrawable.getTopic(), 0, bundle); + chatActivity.setPullingDownTransition(true); + replacingChatActivity = true; + presentFragment(chatActivity, true); + } + } else { + addToPulledDialogsMyself(); + addToPulledDialogs(pullingDownDrawable.nextChat, null, pullingDownDrawable.nextDialogId, pullingDownDrawable.dialogFolderId, pullingDownDrawable.dialogFilterId); + Bundle bundle = new Bundle(); + bundle.putLong("chat_id", pullingDownDrawable.getChatId()); + bundle.putInt("dialog_folder_id", pullingDownDrawable.dialogFolderId); + bundle.putInt("dialog_filter_id", pullingDownDrawable.dialogFilterId); + bundle.putBoolean("pulled", true); + SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); + sharedPreferences.edit().remove("diditem" + pullingDownDrawable.nextDialogId).apply(); + ChatActivity chatActivity = new ChatActivity(bundle); + if (nextChannels != null && nextChannels.size() > 1) { + chatActivity.setNextChannels(new ArrayList<>(nextChannels.subList(1, nextChannels.size()))); + } + chatActivity.setPullingDownTransition(true); + replacingChatActivity = true; + presentFragment(chatActivity, true); + } + } + + private ArrayList nextChannels; + public void setNextChannels(ArrayList channels) { + nextChannels = channels; } private void addToPulledDialogsMyself() { @@ -10262,14 +10331,22 @@ private void addToPulledDialogsMyself() { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); - BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, dialog_id, dialogFilterId, dialogFolderId); + BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, null, dialog_id, dialogFilterId, dialogFolderId); } - private void addToPulledDialogs(TLRPC.Chat chat, long dialogId, int folderId, int filterId) { + private void addToPulledDialogs(TLRPC.Chat chat, TLRPC.TL_forumTopic topic, long dialogId, int folderId, int filterId) { if (getParentLayout() == null) { return; } int stackIndex = getParentLayout().getFragmentStack().indexOf(this); - BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, dialogId, folderId, filterId); + BackButtonMenu.addToPulledDialogs(this, stackIndex, chat, null, topic, dialogId, folderId, filterId); + } + + private void addToPulledTopicsMyself() { + if (getParentLayout() == null) { + return; + } + int stackIndex = getParentLayout().getFragmentStack().indexOf(this); + BackButtonMenu.addToPulledDialogs(this, stackIndex, currentChat, currentUser, forumTopic, dialog_id, dialogFilterId, dialogFolderId); } private void setPullingDownTransition(boolean fromPullingDownTransition) { @@ -11074,7 +11151,7 @@ private void updateChatListViewTopPadding() { pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset() - AndroidUtilities.dp(4)); } float oldPadding = chatListViewPaddingTop; - chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH; + chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + (paddingTopHeight = topPanelViewH + pinnedViewH + pendingViewH); chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; @@ -12719,7 +12796,7 @@ public void openAttachMenuForCreatingSticker() { } chatAttachAlert.setMaxSelectedPhotos(1, false); chatAttachAlert.setOpenWithFrontFaceCamera(true); - chatAttachAlert.enableStickerMode(); + chatAttachAlert.enableStickerMode(null); chatAttachAlert.init(); chatAttachAlert.parentThemeDelegate = themeDelegate; if (visibleDialog != null) { @@ -16227,12 +16304,18 @@ protected void dispatchDraw(Canvas canvas) { MessageObject.SendAnimationData data = cell.getMessageObject().sendAnimationData; if (data != null) { canvas.save(); + final int actionBarBottom = actionBar.getVisibility() == VISIBLE ? (int) actionBar.getTranslationY() + actionBar.getMeasuredHeight() + (actionBarSearchTags != null ? actionBarSearchTags.getCurrentHeight() : 0) + (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) : 0; + canvas.clipRect(0, actionBarBottom + paddingTopHeight, getWidth(), getHeight()); ImageReceiver imageReceiver = cell.getPhotoImage(); - canvas.translate(data.currentX, data.currentY); + cell.getLocationInWindow(AndroidUtilities.pointTmp2); + int finalY = AndroidUtilities.pointTmp2[1]; + finalY -= cell.getTranslationY() * (1.0f - data.progress); + finalY += chatActivityEnterView.topViewVisible() * AndroidUtilities.dp(48); + canvas.translate(data.currentX, AndroidUtilities.lerp(data.y, finalY + imageReceiver.getCenterY(), data.progress)); canvas.scale(data.currentScale, data.currentScale); canvas.translate(-imageReceiver.getCenterX(), -imageReceiver.getCenterY()); cell.setTimeAlpha(data.timeAlpha); - animateSendingViews.get(a).draw(canvas); + cell.draw(canvas); canvas.restore(); } } @@ -19853,11 +19936,32 @@ public void didReceivedNotification(int id, int account, final Object... args) { TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = set.access_hash; inputStickerSet.id = set.id; + + final boolean replacing = args.length > 4 ? (boolean) args[4] : false; + + if (visibleDialog instanceof StickersAlert) { + StickersAlert existingAlert = (StickersAlert) visibleDialog; + if (existingAlert.stickerSet != null && existingAlert.stickerSet.set != null && existingAlert.stickerSet.set.id == set.id) { + existingAlert.updateStickerSet(((TLRPC.TL_messages_stickerSet) args[1])); + if (args.length > 2 && args[2] instanceof TLRPC.Document) { + TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; + if (args.length > 3 && args[3] instanceof String) { + stickerDocument.localThumbPath = (String) args[3]; + } + BulletinFactory.of(existingAlert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); + } + return; + } + } + StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate); alert.setOnShowListener(dialog -> { if (args.length > 2 && args[2] instanceof TLRPC.Document) { TLRPC.Document stickerDocument = (TLRPC.Document) args[2]; - BulletinFactory.of((FrameLayout) alert.getContainerView(), resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(); + if (args.length > 3 && args[3] instanceof String) { + stickerDocument.localThumbPath = (String) args[3]; + } + BulletinFactory.of(alert.container, resourceProvider).createEmojiBulletin(stickerDocument, LocaleController.formatString(replacing ? R.string.StickersStickerEditedInSetToast : R.string.StickersStickerAddedToSetToast, set.title)).setDuration(Bulletin.DURATION_LONG).show(true); } }); showDialog(alert); @@ -20375,7 +20479,15 @@ public void didReceivedNotification(int id, int account, final Object... args) { getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, chatMode, 0, null, classGuid); } if (chatAdapter != null) { - chatAdapter.updateRowWithMessageObject(obj, false, false); + ChatMessageCell cell = null; + for (int i = 0; i < chatListView.getChildCount(); ++i) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == obj) { + cell = (ChatMessageCell) child; + break; + } + } + chatAdapter.updateRowWithMessageObject(obj, animateSendingViews.contains(cell), false); } if (chatLayoutManager != null) { if (mediaUpdated && chatLayoutManager.findFirstVisibleItemPosition() == 0) { @@ -22456,9 +22568,10 @@ private void loadSendAsPeers(boolean animatedUpdate) { private int sponsoredMessagesPostsBetween; private boolean sponsoredMessagesAdded; + private Pattern sponsoredUrlPattern; private void addSponsoredMessages(boolean animated) { - if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium()) { + if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium() && getMessagesController().isSponsoredDisabled()) { return; } MessagesController.SponsoredMessagesInfo res = getMessagesController().getSponsoredMessages(dialog_id); @@ -22468,12 +22581,36 @@ private void addSponsoredMessages(boolean animated) { for (int i = 0; i < res.messages.size(); i++) { MessageObject messageObject = res.messages.get(i); messageObject.resetLayout(); - long dialogId = MessageObject.getPeerId(messageObject.messageOwner.from_id); - int messageId = 0; - if (messageObject.sponsoredChannelPost != 0) { - messageId = messageObject.sponsoredChannelPost; + if (messageObject.sponsoredUrl != null) { + try { + if (sponsoredUrlPattern == null) { + sponsoredUrlPattern = Pattern.compile("https://t\\.me/(\\w+)(?:/(\\d+))?"); + } + Matcher matcher = sponsoredUrlPattern.matcher(messageObject.sponsoredUrl); + if (matcher.matches()) { + String username = matcher.group(1); + int postId = 0; + try { + postId = matcher.groupCount() >= 2 ? Integer.parseInt(matcher.group(2)) : 0; + } catch (Exception e2) { + FileLog.e(e2); + } + TLObject obj = getMessagesController().getUserOrChat(username); + long did; + if (obj instanceof TLRPC.User) { + did = ((TLRPC.User) obj).id; + } else if (obj instanceof TLRPC.Chat) { + did = -((TLRPC.Chat) obj).id; + } else { + continue; + } + if (postId < 0) continue; + getMessagesController().ensureMessagesLoaded(did, postId, null); + } + } catch (Exception e) { + FileLog.e(e); + } } - getMessagesController().ensureMessagesLoaded(dialogId, messageId, null); } sponsoredMessagesAdded = true; sponsoredMessagesPostsBetween = res.posts_between != null ? res.posts_between : 0; @@ -23685,7 +23822,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo if (editingMessageObject == obj) { hideFieldPanel(true); } - int index = chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); + int index = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.indexOf(filteredMessagesDict.get(mid)) : messages.indexOf(obj); if (index != -1) { if (obj.scheduled) { scheduledMessagesCount--; @@ -23695,7 +23832,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); } - MessageObject removed = chatAdapter.getMessages().remove(index); + MessageObject removed = chatAdapter != null && chatAdapter.isFiltered && filteredMessagesDict != null ? chatAdapter.filteredMessages.remove(index) : messages.remove(index); if (chatAdapter != null) { if (chatAdapter.isFiltered) { int mindex = messages.indexOf(obj); @@ -23756,7 +23893,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo if (filteredMessagesByDays != null) { dayArr = filteredMessagesByDays.get(obj.dateKeyInt); if (dayArr != null) { - MessageObject mobj = chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; + MessageObject mobj = chatAdapter != null && chatAdapter.isFiltered ? filteredMessagesDict.get(obj.getId()) : obj; dayArr.remove(mobj); if (dayArr.isEmpty()) { filteredMessagesByDays.remove(obj.dateKeyInt); @@ -23808,7 +23945,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); int index = chatAdapter.getMessages().indexOf(messageObject); if (index >= 0) { - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFrozen) { chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, newGroupsSizes.get(groupedMessages.groupId)); } } @@ -23857,7 +23994,7 @@ private void processDeletedMessages(ArrayList markAsDeletedMessages, lo avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } } - if (chatAdapter != null) { + if (chatAdapter != null && !chatAdapter.isFrozen) { int prevHintRow = chatAdapter.hintRow; int prevLoadingUpRow = chatAdapter.loadingUpRow; int prevLoadingDownRow = chatAdapter.loadingDownRow; @@ -24194,6 +24331,8 @@ private void showPollSolution(MessageObject messageObject, TLRPC.PollResults res CharSequence text; if (!results.solution_entities.isEmpty()) { text = new SpannableStringBuilder(results.solution); + text = Emoji.replaceEmoji(text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(13), false); + text = MessageObject.replaceAnimatedEmoji(text, results.solution_entities, Theme.chat_msgBotButtonPaint.getFontMetricsInt()); MessageObject.addEntitiesToText(text, results.solution_entities, false, true, true, false); } else { text = results.solution; @@ -25818,7 +25957,7 @@ public void onAnimationCancel(Animator animation) { pinnedText = String.format("%s - %s", pinnedMessageObject.getMusicAuthor(), pinnedMessageObject.getMusicTitle()); } else if (pinnedMessageObject.type == MessageObject.TYPE_POLL) { TLRPC.TL_messageMediaPoll poll = (TLRPC.TL_messageMediaPoll) pinnedMessageObject.messageOwner.media; - String mess = poll.poll.question; + String mess = poll.poll.question.text; if (mess.length() > 150) { mess = mess.substring(0, 150); } @@ -26266,7 +26405,7 @@ private void updateTopPanel(boolean animated) { getMessagesController().getTranslateController().isDialogTranslatable(getDialogId()) && !getMessagesController().getTranslateController().isTranslateDialogHidden(getDialogId()) : !getMessagesController().premiumFeaturesBlocked() && preferences.getInt("dialog_show_translate_count" + did, 5) <= 0 ); - boolean showBizBot = getUserConfig().isPremium() && preferences.getLong("dialog_botid" + did, 0) != 0; + boolean showBizBot = currentEncryptedChat == null && getUserConfig().isPremium() && preferences.getLong("dialog_botid" + did, 0) != 0; if (showRestartTopic) { shownRestartTopic = true; } @@ -27223,6 +27362,9 @@ public void applyChatLinkMessageMaybe() { } CharSequence message = ChatActivityEnterView.applyMessageEntities(entities, resolvedChatLink.message, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt()); + if (message != null && message.length() > 0 && message.charAt(0) == '@') { + message = TextUtils.concat(" ", message); + } chatActivityEnterView.setFieldText(message, true, true); @@ -27580,19 +27722,15 @@ public void onConfigurationChanged(android.content.res.Configuration newConfig) } } - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages selectedGroup) { - createDeleteMessagesAlert(finalSelectedObject, selectedGroup, 1); - } - - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant) { - createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, loadParticipant, false); + private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup) { + createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, false); } - private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant, boolean hideDimAfter) { + private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, boolean hideDimAfter) { if (finalSelectedObject == null && (selectedMessagesIds[0].size() + selectedMessagesIds[1].size()) == 0) { return; } - AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, (int) getTopicId(), chatMode, loadParticipant, () -> { + AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, (int) getTopicId(), chatMode, null, () -> { hideActionMode(); updatePinnedMessageView(true); }, hideDimAfter ? () -> dimBehindView(false) : null, themeDelegate); @@ -27932,9 +28070,9 @@ public void setAutoDeleteHistory(int time, int action) { try { TLRPC.Poll poll = ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll; StringBuilder pollText = new StringBuilder(); - pollText = new StringBuilder(poll.question).append("\n"); - for (TLRPC.TL_pollAnswer answer : poll.answers) - pollText.append("\n\uD83D\uDD18 ").append(answer.text); + pollText = new StringBuilder(poll.question.text).append("\n"); + for (TLRPC.PollAnswer answer : poll.answers) + pollText.append("\n\uD83D\uDD18 ").append(answer.text == null ? "" : answer.text.text); messageTextToTranslate = pollText.toString(); } catch (Exception e) { } @@ -28277,7 +28415,7 @@ public void setAutoDeleteHistory(int time, int action) { icons.add(R.drawable.msg_sticker); TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - if (getMediaDataController().canAddStickerToFavorites()/* && MessageObject.isStickerHasSet(document)*/) { + if (getMediaDataController().canAddStickerToFavorites()) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.msg_fave); @@ -28317,11 +28455,11 @@ public void setAutoDeleteHistory(int time, int action) { } TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { - //if (MessageObject.isStickerHasSet(document)) { - items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - options.add(OPTION_ADD_STICKER_TO_FAVORITES); - icons.add(R.drawable.msg_fave); - //} + if (getMediaDataController().canAddStickerToFavorites()) { + items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); + options.add(OPTION_ADD_STICKER_TO_FAVORITES); + icons.add(R.drawable.msg_fave); + } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); @@ -28740,7 +28878,7 @@ public void setAutoDeleteHistory(int time, int action) { } boolean showMessageSeen = !isReactionsViewAvailable && !isInScheduleMode() && currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().chatReadMarkExpirePeriod) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count <= getMessagesController().chatReadMarkSizeThreshold && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); boolean showPrivateMessageSeen = !isReactionsViewAvailable && currentChat == null && currentEncryptedChat == null && (currentUser != null && !UserObject.isUserSelf(currentUser) && !UserObject.isReplyUser(currentUser) && !UserObject.isAnonymous(currentUser) && !currentUser.bot && !UserObject.isService(currentUser.id)) && (userInfo == null || !userInfo.read_dates_private) && !isInScheduleMode() && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < getMessagesController().pmReadDateExpirePeriod) && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) && (v instanceof ChatMessageCell); - boolean showSponsorInfo = selectedObject != null && selectedObject.isSponsored() && (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null || selectedObject.sponsoredBotApp != null); + boolean showSponsorInfo = selectedObject != null && selectedObject.isSponsored() && (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)); if (chatMode == MODE_SAVED) { showMessageSeen = false; } @@ -29224,7 +29362,7 @@ public void run() { } if (selectedObject != null && selectedObject.isSponsored()) { - if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredWebPage != null) { + if (selectedObject.sponsoredInfo != null || selectedObject.sponsoredAdditionalInfo != null || selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith("https://" + getMessagesController().linkPrefix)) { LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); @@ -29239,13 +29377,13 @@ public void run() { ArrayList sections = new ArrayList<>(); - if (selectedObject.sponsoredWebPage != null) { + if (selectedObject.sponsoredUrl != null && !selectedObject.sponsoredUrl.startsWith(getMessagesController().linkPrefix)) { TextView textView = new TextView(getParentActivity()); textView.setTextColor(getThemedColor(Theme.key_chat_messageLinkIn)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(10), AndroidUtilities.dp(18), AndroidUtilities.dp(10)); textView.setMaxWidth(AndroidUtilities.dp(300)); - Uri uri = Uri.parse(selectedObject.sponsoredWebPage.url); + Uri uri = Uri.parse(selectedObject.sponsoredUrl); textView.setText(Browser.replaceHostname(uri, IDN.toUnicode(uri.getHost(), IDN.ALLOW_UNASSIGNED))); textView.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, selectedObject.sponsoredAdditionalInfo == null ? 6 : 0)); textView.setOnClickListener(e -> { @@ -29253,13 +29391,13 @@ public void run() { return; } logSponsoredClicked(selectedObject); - Browser.openUrl(getContext(), selectedObject.sponsoredWebPage.url, true, false); + Browser.openUrl(getContext(), selectedObject.sponsoredUrl, true, false); }); textView.setOnLongClickListener(e -> { if (selectedObject == null) { return false; } - if (AndroidUtilities.addToClipboard(selectedObject.sponsoredWebPage.url)) { + if (AndroidUtilities.addToClipboard(selectedObject.sponsoredUrl)) { BulletinFactory.of(Bulletin.BulletinWindow.make(getParentActivity()), themeDelegate).createCopyLinkBulletin().show(); } return true; @@ -29507,7 +29645,7 @@ public void hideMenu() { if (group != null) { messageWithReactions = group.findPrimaryMessageObject(); } - reactionsLayout.setMessage(messageWithReactions, chatInfo); + reactionsLayout.setMessage(messageWithReactions, chatInfo, true); reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { @@ -29531,7 +29669,7 @@ public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, f } } - boolean showNoForwards = noforwards && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED && chatMode != MODE_SAVED; + boolean showNoForwards = (getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards && currentUser != null && currentUser.bot) && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED && chatMode != MODE_SAVED; scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0)); scrimPopupContainerLayout.setPopupWindowLayout(popupLayout); if (showNoForwards) { @@ -30471,7 +30609,7 @@ private void processSelectedOption(int option) { return; } preserveDim = true; - createDeleteMessagesAlert(selectedObject, selectedObjectGroup, 1,true); + createDeleteMessagesAlert(selectedObject, selectedObjectGroup, true); break; } case OPTION_FORWARD: { @@ -31194,8 +31332,7 @@ private void processSelectedOption(int option) { break; } case OPTION_HIDE_SPONSORED_MESSAGE: { - MessageObject message = selectedObject; - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + hideAds(); break; } case OPTION_ABOUT_REVENUE_SHARING_ADS: { @@ -31274,6 +31411,7 @@ public void onPremiumRequired() { BulletinFactory.of(ChatActivity.this) .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) .show(); + getMessagesController().disableAds(false); removeFromSponsored(message); removeMessageWithThanos(message); }, 200); @@ -31299,7 +31437,7 @@ public void onPremiumRequired() { break; } case OPTION_REMOVE_ADS: { - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + hideAds(); break; } case OPTION_SPEED_PROMO: { @@ -31373,6 +31511,19 @@ private int processSelectedOptionLongClick(ActionBarMenuSubItem cell, int option return 0; } + private void hideAds() { + if (getUserConfig().isPremium()) { + BulletinFactory.of(ChatActivity.this) + .createAdReportedBulletin(LocaleController.getString(R.string.AdHidden)) + .show(); + getMessagesController().disableAds(true); + removeFromSponsored(selectedObject); + removeMessageWithThanos(selectedObject); + } else { + showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + } + } + @Override public boolean didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param, TopicsFragment topicsFragment) { if ((messagePreviewParams == null && (!fragment.isQuote || replyingMessageObject == null) || fragment.isQuote && replyingMessageObject == null) && forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { @@ -34039,31 +34190,28 @@ public Float get(MessageObject.SendAnimationData object) { return object.currentX; } }; - Property param3 = new AnimationProperties.FloatProperty("p3") { - @Override - public void setValue(MessageObject.SendAnimationData object, float value) { - object.currentY = value; - if (fragmentView != null) { - fragmentView.invalidate(); - } - } - - @Override - public Float get(MessageObject.SendAnimationData object) { - return object.currentY; - } - }; AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(sendAnimationData, param1, scale, 1.0f), - ObjectAnimator.ofFloat(sendAnimationData, param3, sendAnimationData.y, position[1] + imageReceiver.getCenterY()) + ObjectAnimator.ofFloat(sendAnimationData, new AnimationProperties.FloatProperty("progress") { + @Override + public void setValue(MessageObject.SendAnimationData object, float value) { + object.progress = value; + if (fragmentView != null) { + fragmentView.invalidate(); + } + } + @Override + public Float get(MessageObject.SendAnimationData object) { + return object.progress; + } + }, 0, 1) ); - animatorSet.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); ObjectAnimator o = ObjectAnimator.ofFloat(sendAnimationData, param2, sendAnimationData.x, position[0] + imageReceiver.getCenterX()); - o.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); allAnimators.playTogether(o, animatorSet); - allAnimators.setDuration(ChatListItemAnimator.DEFAULT_DURATION); + allAnimators.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + allAnimators.setDuration(460); allAnimators.addListener(new AnimatorListenerAdapter() { @Override @@ -34417,6 +34565,9 @@ public void notifyDataSetChanged() { @Override public void notifyItemChanged(int position) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("notify item changed " + position); + } if (!fragmentBeginToShow) { chatListView.setItemAnimator(null); } else if (chatListView.getItemAnimator() != chatListItemAnimator) { @@ -35044,6 +35195,10 @@ public void videoTimerReached() { @Override public void didPressTime(ChatMessageCell cell) { + if (!cell.getMessageObject().isImportedForward()) { + showTimeHint(cell); + return; + } createUndoView(); if (undoView == null) { return; @@ -35085,8 +35240,9 @@ public void didPressOther(ChatMessageCell cell, float otherX, float otherY) { } @Override - public void didPressSponsoredClose() { - showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + public void didPressSponsoredClose(ChatMessageCell cell) { + selectedObject = cell.getMessageObject(); + hideAds(); } @Override @@ -35271,7 +35427,7 @@ private void openProfile(TLRPC.User user) { } private void openProfile(TLRPC.User user, boolean expandPhoto) { - if (user != null && user.id != getUserConfig().getClientUserId()) { + if (user != null) { if (user.photo == null || user.photo instanceof TLRPC.TL_userProfilePhotoEmpty) { expandPhoto = false; } @@ -35313,7 +35469,7 @@ private void openChat(ChatMessageCell cell, TLRPC.Chat chat, int postId) { if (avatarContainer != null && postId == 0) { avatarContainer.openProfile(false); } else { - scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, true, 0); + scrollToMessageId(postId, cell.getMessageObject().getId(), true, 0, false, 0); } } else if (currentChat == null || chat.id != currentChat.id || isThreadChat()) { Bundle args = new Bundle(); @@ -35701,7 +35857,7 @@ private void pressedReaction(ChatMessageCell cell, TLRPC.ReactionCount reaction) @Override - public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { + public void didPressVoteButtons(ChatMessageCell cell, ArrayList buttons, int showCount, int x, int y) { if (showCount >= 0 || buttons.isEmpty()) { if (getParentActivity() == null) { return; @@ -36443,111 +36599,98 @@ public void end(boolean replaced) { args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); } - } else { - if (messageObject.isSponsored()) { - logSponsoredClicked(messageObject); - Bundle args = new Bundle(); - if (messageObject.sponsoredBotApp != null) { - TLRPC.TL_messages_getBotApp getBotApp = new TLRPC.TL_messages_getBotApp(); - TLRPC.TL_inputBotAppShortName app = new TLRPC.TL_inputBotAppShortName(); - if (messageObject.messageOwner == null || messageObject.messageOwner.from_id == null) { - return; - } - TLRPC.User bot = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.from_id.user_id); - if (bot == null) { - return; + } else if (type == ChatMessageCell.INSTANT_BUTTON_TYPE_STICKER_SET || type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET) { + final boolean emoji = type == ChatMessageCell.INSTANT_BUTTON_TYPE_EMOJI_SET; + TLRPC.WebPage webPage = null; + if (webPage == null && messageObject.messageOwner != null && messageObject.messageOwner.media != null) { + webPage = messageObject.messageOwner.media.webpage; + } + if (webPage == null || webPage.url == null) return; + Pattern pattern = Pattern.compile("^https?\\:\\/\\/t\\.me\\/add(?:emoji|stickers)\\/(.+)$"); + Matcher m = pattern.matcher(webPage.url); + + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); } - app.bot_id = MessagesController.getInstance(currentAccount).getInputUser(bot); - app.short_name = messageObject.sponsoredBotApp.short_name; - getBotApp.app = app; - ConnectionsManager.getInstance(currentAccount).sendRequest(getBotApp, (response1, error1) -> { -// if (progress != null) { -// progress.end(); -// } - if (error1 != null) { - BulletinFactory.of(ChatActivity.this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(true); - } else { - TLRPC.TL_messages_botApp botApp = (TLRPC.TL_messages_botApp) response1; - AndroidUtilities.runOnUIThread(() -> { -// dismissLoading.run(); - AtomicBoolean allowWrite = new AtomicBoolean(); - Runnable loadBotSheet = () -> { - BotWebViewSheet sheet = new BotWebViewSheet(getContext(), getResourceProvider()); - sheet.setParentActivity(getParentActivity()); - sheet.requestWebView(currentAccount, bot.id, bot.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, ChatActivity.this, botApp.app, allowWrite.get(), messageObject.botStartParam, bot); - showDialog(sheet); - if (botApp.inactive) { - sheet.showJustAddedBulletin(); - } - }; + } + }; - if (botApp.request_write_access) { - AlertsCreator.createBotLaunchAlert(ChatActivity.this, allowWrite, bot, loadBotSheet); - } else { - loadBotSheet.run(); - } - }); - } - }); - } else if (messageObject.sponsoredWebPage != null) { - Browser.openUrl(getContext(), messageObject.sponsoredWebPage.url, true, false); - } else if (messageObject.sponsoredChatInvite != null) { - final TLRPC.TL_messages_checkChatInvite req = new TLRPC.TL_messages_checkChatInvite(); - req.hash = messageObject.sponsoredChatInviteHash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (error == null) { - TLRPC.ChatInvite invite = (TLRPC.ChatInvite) response; - if (invite.chat != null && (!ChatObject.isLeftFromChat(invite.chat) || !invite.chat.kicked && (ChatObject.isPublic(invite.chat) || invite instanceof TLRPC.TL_chatInvitePeek || invite.chat.has_geo))) { - MessagesController.getInstance(currentAccount).putChat(invite.chat, false); - ArrayList chats = new ArrayList<>(); - chats.add(invite.chat); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(null, chats, false, true); - args.putLong("chat_id", invite.chat.id); - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, ChatActivity.this)) { - ChatActivity fragment = new ChatActivity(args); - if (invite instanceof TLRPC.TL_chatInvitePeek) { - fragment.setChatInvite(invite); - } - presentFragment(fragment); - } - } else { - showDialog(new JoinGroupAlert(getContext(), messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate, JoinGroupAlert.ORIGINATION_SPONSORED_CHAT)); - } - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - if (error.text.startsWith("FLOOD_WAIT")) { - builder.setMessage(LocaleController.getString("FloodWait", R.string.FloodWait)); - } else if (error.text.startsWith("INVITE_HASH_EXPIRED")) { - builder.setTitle(LocaleController.getString("ExpiredLink", R.string.ExpiredLink)); - builder.setMessage(LocaleController.getString("InviteExpired", R.string.InviteExpired)); + if (m.matches() && m.groupCount() > 1 && m.group(1) != null) { + String setname = m.group(1); + TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(setname); + if (set == null) { + progressDialogCurrent.init(); + TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); + TLRPC.TL_inputStickerSetShortName input = new TLRPC.TL_inputStickerSetShortName(); + input.short_name = setname; + req.stickerset = input; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + progressDialogCurrent.end(); + if (res instanceof TLRPC.TL_messages_stickerSet) { + MediaDataController.getInstance(currentAccount).putStickerSet((TLRPC.TL_messages_stickerSet) res, false); + + TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); + inputStickerSet.access_hash = ((TLRPC.TL_messages_stickerSet) res).set.access_hash; + inputStickerSet.id = ((TLRPC.TL_messages_stickerSet) res).set.id; + if (emoji) { + ArrayList inputSets = new ArrayList<>(1); + inputSets.add(inputStickerSet); + EmojiPacksAlert alert = new EmojiPacksAlert(ChatActivity.this, getParentActivity(), themeDelegate, inputSets); + alert.setCalcMandatoryInsets(isKeyboardVisible()); + showDialog(alert); } else { - builder.setMessage(LocaleController.getString("JoinToGroupErrorNotExist", R.string.JoinToGroupErrorNotExist)); + StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView, themeDelegate); + alert.setCalcMandatoryInsets(isKeyboardVisible()); + showDialog(alert); } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - } - }), ConnectionsManager.RequestFlagFailOnServerErrors); - } else { - long peerId = MessageObject.getPeerId(messageObject.messageOwner.from_id); - if (peerId == getDialogId() && messageObject.sponsoredChannelPost != 0) { - scrollToMessageId(messageObject.sponsoredChannelPost, 0, true, 0, false, 0); - } else { - if (peerId < 0) { - args.putLong("chat_id", -peerId); } else { - args.putLong("user_id", peerId); - } - if (messageObject.sponsoredChannelPost != 0) { - args.putInt("message_id", messageObject.sponsoredChannelPost); + BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.error, getString(emoji ? R.string.AddEmojiNotFound : R.string.AddStickersNotFound)).show(true); } - if (messageObject.botStartParam != null) { - args.putString("inline_query", messageObject.botStartParam); + })); + progressDialogCurrent.onCancel(() -> ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true)); + return; + } + } + Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, false, progressDialogCurrent); + } else { + if (messageObject.isSponsored()) { + logSponsoredClicked(messageObject); + Bundle args = new Bundle(); + if (messageObject.sponsoredUrl != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); } - if (getMessagesController().checkCanOpenChat(args, ChatActivity.this)) { - presentFragment(new ChatActivity(args)); + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } } - } + }; + Browser.openUrl(getContext(), Uri.parse(messageObject.sponsoredUrl), true, false, false, progressDialogCurrent); } } else { TLRPC.WebPage webPage = messageObject.getStoryMentionWebpage(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index 4b0bad944a..2c30bfac8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.LocaleController.getString; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -248,7 +250,7 @@ public boolean onDeletePhoto(int index) { req.id = new TLRPC.TL_inputPhotoEmpty(); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { avatarImage.setImageDrawable(avatarDrawable); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); if (currentUser != null) { currentUser.photo = null; @@ -604,7 +606,7 @@ public void requestLayout() { linearLayout1.setOrientation(LinearLayout.VERTICAL); - actionBar.setTitle(LocaleController.getString("ChannelEdit", R.string.ChannelEdit)); + actionBar.setTitle(getString("ChannelEdit", R.string.ChannelEdit)); avatarContainer = new LinearLayout(context); avatarContainer.setOrientation(LinearLayout.VERTICAL); @@ -695,11 +697,11 @@ protected void onDraw(Canvas canvas) { nameTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT, false); if (userId != 0) { - nameTextView.setHint(LocaleController.getString(R.string.BotName)); + nameTextView.setHint(getString(R.string.BotName)); } else if (isChannel) { - nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName)); + nameTextView.setHint(getString("EnterChannelName", R.string.EnterChannelName)); } else { - nameTextView.setHint(LocaleController.getString("GroupName", R.string.GroupName)); + nameTextView.setHint(getString("GroupName", R.string.GroupName)); } nameTextView.setEnabled(currentChat != null || ChatObject.canChangeChatInfo(currentChat)); nameTextView.setFocusable(nameTextView.isEnabled()); @@ -753,7 +755,7 @@ protected void onDraw(Canvas canvas) { req.id = new TLRPC.TL_inputPhotoEmpty(); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { avatarImage.setImageDrawable(avatarDrawable); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); if (currentUser != null) { currentUser.photo = null; @@ -802,7 +804,7 @@ protected void onDraw(Canvas canvas) { inputFilters = new InputFilter[1]; inputFilters[0] = new InputFilter.LengthFilter(255); descriptionTextView.setFilters(inputFilters); - descriptionTextView.setHint(LocaleController.getString("DescriptionOptionalPlaceholder", R.string.DescriptionOptionalPlaceholder)); + descriptionTextView.setHint(getString("DescriptionOptionalPlaceholder", R.string.DescriptionOptionalPlaceholder)); descriptionTextView.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); descriptionTextView.setCursorSize(AndroidUtilities.dp(20)); descriptionTextView.setCursorWidth(1.5f); @@ -918,7 +920,7 @@ public void afterTextChanged(Editable editable) { HeaderCell headerCell = new HeaderCell(context, Theme.key_dialogTextBlue2, 23, 15, false); headerCell.setHeight(47); - headerCell.setText(LocaleController.getString("ChatHistory", R.string.ChatHistory)); + headerCell.setText(getString("ChatHistory", R.string.ChatHistory)); linearLayout.addView(headerCell); LinearLayout linearLayoutInviteContainer = new LinearLayout(context); @@ -932,12 +934,12 @@ public void afterTextChanged(Editable editable) { buttons[a].setTag(a); buttons[a].setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (a == 0) { - buttons[a].setTextAndValueAndCheck(LocaleController.getString("ChatHistoryVisible", R.string.ChatHistoryVisible), LocaleController.getString("ChatHistoryVisibleInfo", R.string.ChatHistoryVisibleInfo), true, !historyHidden); + buttons[a].setTextAndValueAndCheck(getString("ChatHistoryVisible", R.string.ChatHistoryVisible), getString("ChatHistoryVisibleInfo", R.string.ChatHistoryVisibleInfo), true, !historyHidden); } else { if (ChatObject.isChannel(currentChat)) { - buttons[a].setTextAndValueAndCheck(LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden), LocaleController.getString("ChatHistoryHiddenInfo", R.string.ChatHistoryHiddenInfo), false, historyHidden); + buttons[a].setTextAndValueAndCheck(getString("ChatHistoryHidden", R.string.ChatHistoryHidden), getString("ChatHistoryHiddenInfo", R.string.ChatHistoryHiddenInfo), false, historyHidden); } else { - buttons[a].setTextAndValueAndCheck(LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden), LocaleController.getString("ChatHistoryHiddenInfo2", R.string.ChatHistoryHiddenInfo2), false, historyHidden); + buttons[a].setTextAndValueAndCheck(getString("ChatHistoryHidden", R.string.ChatHistoryHidden), getString("ChatHistoryHiddenInfo2", R.string.ChatHistoryHiddenInfo2), false, historyHidden); } } linearLayoutInviteContainer.addView(buttons[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -972,7 +974,7 @@ public void afterTextChanged(Editable editable) { if (isChannel) { signCell = new TextCell(context, 23, false, true, null); signCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - signCell.setTextAndCheckAndIcon(LocaleController.getString("ChannelSignMessages", R.string.ChannelSignMessages), signMessages, R.drawable.msg_signed, false); + signCell.setTextAndCheckAndIcon(getString("ChannelSignMessages", R.string.ChannelSignMessages), signMessages, R.drawable.msg_signed, false); typeEditContainer.addView(signCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); signCell.setOnClickListener(v -> { signMessages = !signMessages; @@ -981,14 +983,14 @@ public void afterTextChanged(Editable editable) { } else if (currentChat.creator) { forumsCell = new TextCell(context, 23, false, true, null); forumsCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - forumsCell.setTextAndCheckAndIcon(LocaleController.getString("ChannelTopics", R.string.ChannelTopics), forum, R.drawable.msg_topics, false); + forumsCell.setTextAndCheckAndIcon(getString("ChannelTopics", R.string.ChannelTopics), forum, R.drawable.msg_topics, false); forumsCell.getCheckBox().setIcon(canForum ? 0 : R.drawable.permission_locked); typeEditContainer.addView(forumsCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); forumsCell.setOnClickListener(v -> { if (!canForum) { CharSequence text; if (!(info == null || info.linked_chat_id == 0)) { - text = AndroidUtilities.replaceTags(LocaleController.getString("ChannelTopicsDiscussionForbidden", R.string.ChannelTopicsDiscussionForbidden)); + text = AndroidUtilities.replaceTags(getString("ChannelTopicsDiscussionForbidden", R.string.ChannelTopicsDiscussionForbidden)); } else { text = AndroidUtilities.replaceTags(LocaleController.formatPluralString("ChannelTopicsForbidden", getMessagesController().forumUpgradeParticipantsMin)); } @@ -1009,7 +1011,7 @@ public void afterTextChanged(Editable editable) { ActionBarMenu menu = actionBar.createMenu(); if (currentUser != null || ChatObject.canChangeChatInfo(currentChat) || signCell != null || historyCell != null) { doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); - doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); + doneButton.setContentDescription(getString("Done", R.string.Done)); } if (locationCell != null || signCell != null || historyCell != null || typeCell != null || linkedCell != null || forumsCell != null) { @@ -1021,9 +1023,9 @@ public void afterTextChanged(Editable editable) { settingsSectionCell.setBackground(combinedDrawable); linearLayout1.addView(settingsSectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if (forumsCell != null) { - settingsSectionCell.setText(LocaleController.getString("ForumToggleDescription", R.string.ForumToggleDescription)); + settingsSectionCell.setText(getString("ForumToggleDescription", R.string.ForumToggleDescription)); } else { - settingsSectionCell.setText(LocaleController.getString("ChannelSignMessagesInfo", R.string.ChannelSignMessagesInfo)); + settingsSectionCell.setText(getString("ChannelSignMessagesInfo", R.string.ChannelSignMessagesInfo)); } } @@ -1107,7 +1109,7 @@ public void afterTextChanged(Editable editable) { if (ChatObject.isBoostSupported(currentChat)) { statsAndBoosts = new TextCell(context); - statsAndBoosts.setTextAndIcon(LocaleController.getString("StatisticsAndBoosts", R.string.StatisticsAndBoosts), R.drawable.msg_stats, true); + statsAndBoosts.setTextAndIcon(getString(R.string.StatisticsAndBoosts), R.drawable.msg_stats, true); statsAndBoosts.setBackground(Theme.getSelectorDrawable(false)); statsAndBoosts.setOnClickListener(v -> { presentFragment(StatisticActivity.create(currentChat, false)); @@ -1133,31 +1135,11 @@ public void afterTextChanged(Editable editable) { if (isChannel || currentChat.gigagroup) { infoContainer.addView(blockCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } - if (!isChannel && info != null && info.can_set_stickers) { - stickersContainer = new FrameLayout(context); - stickersContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - linearLayout1.addView(stickersContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - stickersCell = new TextCell(context); - stickersCell.setBackground(Theme.getSelectorDrawable(false)); - stickersCell.setOnClickListener(v -> presentFragment(new ChannelAdminLogActivity(currentChat))); - stickersCell.setPrioritizeTitleOverValue(true); - stickersContainer.addView(stickersCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - stickersCell.setOnClickListener(v -> { - GroupStickersActivity groupStickersActivity = new GroupStickersActivity(currentChat.id); - groupStickersActivity.setInfo(info); - presentFragment(groupStickersActivity); - }); - if (statsAndBoosts != null) { - infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } - } else { - if (statsAndBoosts != null) { - infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } - if (logCell != null) { - infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } + if (statsAndBoosts != null) { + infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + if (logCell != null) { + infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } } @@ -1176,19 +1158,19 @@ public void afterTextChanged(Editable editable) { editIntroCell = new TextCell(context); editIntroCell.setBackground(Theme.getSelectorDrawable(false)); - editIntroCell.setTextAndIcon(LocaleController.getString(R.string.BotEditIntro), R.drawable.msg_log, true); + editIntroCell.setTextAndIcon(getString(R.string.BotEditIntro), R.drawable.msg_log, true); infoContainer.addView(editIntroCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); editIntroCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser) + "-intro")); editCommandsCell = new TextCell(context); editCommandsCell.setBackground(Theme.getSelectorDrawable(false)); - editCommandsCell.setTextAndIcon(LocaleController.getString(R.string.BotEditCommands), R.drawable.msg_media, true); + editCommandsCell.setTextAndIcon(getString(R.string.BotEditCommands), R.drawable.msg_media, true); infoContainer.addView(editCommandsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); editCommandsCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser) + "-commands")); changeBotSettingsCell = new TextCell(context); changeBotSettingsCell.setBackground(Theme.getSelectorDrawable(false)); - changeBotSettingsCell.setTextAndIcon(LocaleController.getString(R.string.BotChangeSettings), R.drawable.msg_bot, true); + changeBotSettingsCell.setTextAndIcon(getString(R.string.BotChangeSettings), R.drawable.msg_bot, true); infoContainer.addView(changeBotSettingsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); changeBotSettingsCell.setOnClickListener(v -> Browser.openUrl(v.getContext(), "https://t.me/BotFather?start=" + getActiveUsername(currentUser))); } @@ -1203,15 +1185,9 @@ public void afterTextChanged(Editable editable) { infoSectionCell = new ShadowSectionCell(context); linearLayout1.addView(infoSectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } - - if (!isChannel && info != null && info.can_set_stickers) { - stickersInfoCell = new TextInfoPrivacyCell(context); - stickersInfoCell.setText(LocaleController.getString(R.string.GroupStickersInfo)); - linearLayout1.addView(stickersInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } } else { botInfoCell = new TextInfoPrivacyCell(context); - String str = LocaleController.getString(R.string.BotManageInfo); + String str = getString(R.string.BotManageInfo); SpannableString span = SpannableString.valueOf(str); int index = str.indexOf("@BotFather"); if (index != -1) { @@ -1242,11 +1218,11 @@ public void updateDrawState(TextPaint ds) { deleteCell.setTextColor(Theme.getColor(Theme.key_text_RedRegular)); deleteCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (currentUser != null) { - deleteCell.setText(LocaleController.getString(R.string.DeleteBot), false); + deleteCell.setText(getString(R.string.DeleteBot), false); } else if (isChannel) { - deleteCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false); + deleteCell.setText(getString("ChannelDelete", R.string.ChannelDelete), false); } else { - deleteCell.setText(LocaleController.getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false); + deleteCell.setText(getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false); } deleteContainer.addView(deleteCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); deleteCell.setOnClickListener(v -> AlertsCreator.createClearOrDeleteDialogAlert(ChatEditActivity.this, false, true, false, currentChat, null, false, true, false, (param) -> { @@ -1300,9 +1276,9 @@ private void updatePublicLinksCount() { } } - publicLinkCell.setTextAndValueAndIcon(LocaleController.getString(R.string.BotPublicLinks), LocaleController.formatString(R.string.BotPublicLinksCount, usernamesActive, currentUser.usernames.size()), R.drawable.msg_link2, true); + publicLinkCell.setTextAndValueAndIcon(getString(R.string.BotPublicLinks), LocaleController.formatString(R.string.BotPublicLinksCount, usernamesActive, currentUser.usernames.size()), R.drawable.msg_link2, true); } else { - publicLinkCell.setTextAndValueAndIcon(LocaleController.getString(R.string.BotPublicLink), "t.me/" + currentUser.username, R.drawable.msg_link2, true); + publicLinkCell.setTextAndValueAndIcon(getString(R.string.BotPublicLink), "t.me/" + currentUser.username, R.drawable.msg_link2, true); } } @@ -1346,9 +1322,9 @@ private void setAvatar() { } if (setAvatarCell != null) { if (hasPhoto || imageUpdater.isUploadingImage()) { - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); } else { - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo), R.drawable.msg_addphoto, true); } if (cameraDrawable == null) { cameraDrawable = new RLottieDrawable(R.raw.camera_outline, "" + R.raw.camera_outline, AndroidUtilities.dp(50), AndroidUtilities.dp(50), false, null); @@ -1481,7 +1457,7 @@ public void didUploadPhoto(final TLRPC.InputFile photo, final TLRPC.InputFile vi showAvatarProgress(false, true); } else { avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, currentUser != null ? currentUser : currentChat); - setAvatarCell.setTextAndIcon(LocaleController.getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); + setAvatarCell.setTextAndIcon(getString("ChatSetNewPhoto", R.string.ChatSetNewPhoto), R.drawable.msg_addphoto, true); if (cameraDrawable == null) { cameraDrawable = new RLottieDrawable(R.raw.camera_outline, "" + R.raw.camera_outline, AndroidUtilities.dp(50), AndroidUtilities.dp(50), false, null); } @@ -1507,10 +1483,10 @@ private boolean checkDiscard() { if (nameTextView != null && !currentUser.first_name.equals(nameTextView.getText().toString()) || descriptionTextView != null && !about.equals(descriptionTextView.getText().toString())) { showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)) - .setMessage(LocaleController.getString(R.string.BotSettingsChangedAlert)) - .setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()) - .setNegativeButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()) + .setTitle(getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)) + .setMessage(getString(R.string.BotSettingsChangedAlert)) + .setPositiveButton(getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()) + .setNegativeButton(getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()) .create()); return false; } @@ -1523,14 +1499,14 @@ private boolean checkDiscard() { descriptionTextView != null && !about.equals(descriptionTextView.getText().toString()) || signMessages != currentChat.signatures || forum != currentChat.forum) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)); + builder.setTitle(getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)); if (isChannel) { - builder.setMessage(LocaleController.getString("ChannelSettingsChangedAlert", R.string.ChannelSettingsChangedAlert)); + builder.setMessage(getString("ChannelSettingsChangedAlert", R.string.ChannelSettingsChangedAlert)); } else { - builder.setMessage(LocaleController.getString("GroupSettingsChangedAlert", R.string.GroupSettingsChangedAlert)); + builder.setMessage(getString("GroupSettingsChangedAlert", R.string.GroupSettingsChangedAlert)); } - builder.setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()); - builder.setNegativeButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()); + builder.setPositiveButton(getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()); + builder.setNegativeButton(getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()); showDialog(builder.create()); return false; } @@ -1814,7 +1790,7 @@ private void updateFields(boolean updateChat, boolean animated) { } if (logCell != null) { - logCell.setVisibility(!currentChat.megagroup || currentChat.gigagroup || info != null ? View.VISIBLE : View.GONE); + logCell.setVisibility(ChatObject.isChannel(currentChat) ? View.VISIBLE : View.GONE); } if (linkedCell != null) { @@ -1823,7 +1799,7 @@ private void updateFields(boolean updateChat, boolean animated) { } else { linkedCell.setVisibility(View.VISIBLE); if (info.linked_chat_id == 0) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), LocaleController.getString("DiscussionInfoShort", R.string.DiscussionInfoShort), R.drawable.msg_discuss, true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), getString("DiscussionInfoShort", R.string.DiscussionInfoShort), R.drawable.msg_discuss, true); } else { TLRPC.Chat chat = getMessagesController().getChat(info.linked_chat_id); if (chat == null) { @@ -1832,15 +1808,15 @@ private void updateFields(boolean updateChat, boolean animated) { String username; if (isChannel) { if (TextUtils.isEmpty(username = ChatObject.getPublicUsername(chat))) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), chat.title, R.drawable.msg_discuss,true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), chat.title, R.drawable.msg_discuss,true); } else { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("Discussion", R.string.Discussion), "@" + username, R.drawable.msg_discuss,true); + linkedCell.setTextAndValueAndIcon(getString("Discussion", R.string.Discussion), "@" + username, R.drawable.msg_discuss,true); } } else { if (TextUtils.isEmpty(username = ChatObject.getPublicUsername(chat))) { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("LinkedChannel", R.string.LinkedChannel), chat.title, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + linkedCell.setTextAndValueAndIcon(getString("LinkedChannel", R.string.LinkedChannel), chat.title, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { - linkedCell.setTextAndValueAndIcon(LocaleController.getString("LinkedChannel", R.string.LinkedChannel), "@" + username, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + linkedCell.setTextAndValueAndIcon(getString("LinkedChannel", R.string.LinkedChannel), "@" + username, R.drawable.msg_channel, forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } } } @@ -1853,9 +1829,9 @@ private void updateFields(boolean updateChat, boolean animated) { locationCell.setVisibility(View.VISIBLE); if (info.location instanceof TLRPC.TL_channelLocation) { TLRPC.TL_channelLocation location = (TLRPC.TL_channelLocation) info.location; - locationCell.setTextAndValue(LocaleController.getString("AttachLocation", R.string.AttachLocation), location.address, animated, true); + locationCell.setTextAndValue(getString("AttachLocation", R.string.AttachLocation), location.address, animated, true); } else { - locationCell.setTextAndValue(LocaleController.getString("AttachLocation", R.string.AttachLocation), "Unknown address", animated, true); + locationCell.setTextAndValue(getString("AttachLocation", R.string.AttachLocation), "Unknown address", animated, true); } } else { locationCell.setVisibility(View.GONE); @@ -1866,30 +1842,30 @@ private void updateFields(boolean updateChat, boolean animated) { if (info != null && info.location instanceof TLRPC.TL_channelLocation) { String link; if (isPrivate) { - link = LocaleController.getString("TypeLocationGroupEdit", R.string.TypeLocationGroupEdit); + link = getString("TypeLocationGroupEdit", R.string.TypeLocationGroupEdit); } else { link = String.format("https://" + getMessagesController().linkPrefix + "/%s", ChatObject.getPublicUsername(currentChat)); } - typeCell.setTextAndValueAndIcon(LocaleController.getString("TypeLocationGroup", R.string.TypeLocationGroup), link, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("TypeLocationGroup", R.string.TypeLocationGroup), link, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { String type; boolean isRestricted = currentChat.noforwards; if (isChannel) { - type = isPrivate ? isRestricted ? LocaleController.getString("TypePrivateRestrictedForwards", R.string.TypePrivateRestrictedForwards) : LocaleController.getString("TypePrivate", R.string.TypePrivate) : LocaleController.getString("TypePublic", R.string.TypePublic); + type = isPrivate ? isRestricted ? getString("TypePrivateRestrictedForwards", R.string.TypePrivateRestrictedForwards) : getString("TypePrivate", R.string.TypePrivate) : getString("TypePublic", R.string.TypePublic); } else { - type = isPrivate ? isRestricted ? LocaleController.getString("TypePrivateGroupRestrictedForwards", R.string.TypePrivateGroupRestrictedForwards) : LocaleController.getString("TypePrivateGroup", R.string.TypePrivateGroup) : LocaleController.getString("TypePublicGroup", R.string.TypePublicGroup); + type = isPrivate ? isRestricted ? getString("TypePrivateGroupRestrictedForwards", R.string.TypePrivateGroupRestrictedForwards) : getString("TypePrivateGroup", R.string.TypePrivateGroup) : getString("TypePublicGroup", R.string.TypePublicGroup); } if (isChannel) { - typeCell.setTextAndValueAndIcon(LocaleController.getString("ChannelType", R.string.ChannelType), type, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("ChannelType", R.string.ChannelType), type, R.drawable.msg_channel, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } else { - typeCell.setTextAndValueAndIcon(LocaleController.getString("GroupType", R.string.GroupType), type, R.drawable.msg_groups, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); + typeCell.setTextAndValueAndIcon(getString("GroupType", R.string.GroupType), type, R.drawable.msg_groups, historyCell != null && historyCell.getVisibility() == View.VISIBLE || linkedCell != null && linkedCell.getVisibility() == View.VISIBLE || forumsCell != null && forumsCell.getVisibility() == View.VISIBLE); } } } if (historyCell != null) { - String type = historyHidden && !forum ? LocaleController.getString("ChatHistoryHidden", R.string.ChatHistoryHidden) : LocaleController.getString("ChatHistoryVisible", R.string.ChatHistoryVisible); - historyCell.setTextAndValueAndIcon(LocaleController.getString("ChatHistoryShort", R.string.ChatHistoryShort), type, animated, R.drawable.msg_discuss, forumsCell != null); + String type = historyHidden && !forum ? getString("ChatHistoryHidden", R.string.ChatHistoryHidden) : getString("ChatHistoryVisible", R.string.ChatHistoryVisible); + historyCell.setTextAndValueAndIcon(getString("ChatHistoryShort", R.string.ChatHistoryShort), type, animated, R.drawable.msg_discuss, forumsCell != null); historyCell.setEnabled(!forum); updateHistoryShow(!forum && isPrivate && (info == null || info.linked_chat_id == 0) && !(info != null && info.location instanceof TLRPC.TL_channelLocation), animated); } @@ -1904,16 +1880,16 @@ private void updateFields(boolean updateChat, boolean animated) { memberRequestsCell.setVisibility(info.requests_pending > 0 ? View.VISIBLE : View.GONE); } if (isChannel) { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelSubscribers", R.string.ChannelSubscribers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(getString("ChannelSubscribers", R.string.ChannelSubscribers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); + blockCell.setTextAndValueAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { if (ChatObject.isChannel(currentChat)) { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); + membersCell.setTextAndValueAndIcon(getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.msg_groups, true); } else { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.msg_groups, memberRequestsCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.msg_groups, memberRequestsCell.getVisibility() == View.VISIBLE); } if (currentChat.gigagroup) { - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + blockCell.setTextAndValueAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.msg_user_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { int count = 0; if (currentChat.default_banned_rights != null) { @@ -1936,35 +1912,35 @@ private void updateFields(boolean updateChat, boolean animated) { } else { count = forum ? 17 : 16; } - blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), String.format("%d/%d", count, forum ? 17 : 16), R.drawable.msg_permissions, true); + blockCell.setTextAndValueAndIcon(getString("ChannelPermissions", R.string.ChannelPermissions), String.format("%d/%d", count, forum ? 17 : 16), animated, R.drawable.msg_permissions, true); } if (memberRequestsCell != null) { - memberRequestsCell.setTextAndValueAndIcon(LocaleController.getString("MemberRequests", R.string.MemberRequests), String.format("%d", info.requests_pending), R.drawable.msg_requests, logCell != null && logCell.getVisibility() == View.VISIBLE); + memberRequestsCell.setTextAndValueAndIcon(getString("MemberRequests", R.string.MemberRequests), String.format("%d", info.requests_pending), R.drawable.msg_requests, logCell != null && logCell.getVisibility() == View.VISIBLE); } } if (ChatObject.hasAdminRights(currentChat)) { - adminCell.setTextAndValueAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? info.admins_count : getAdminCount()), R.drawable.msg_admins, true); + adminCell.setTextAndValueAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? info.admins_count : getAdminCount()), R.drawable.msg_admins, true); } else { if (ChatObject.isChannel(currentChat) && info.participants != null && info.participants.participants != null && info.participants.participants.size() != info.participants_count && realAdminCount == 0) { - adminCell.setTextAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); + adminCell.setTextAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); getRealChannelAdminCount(); } else { - adminCell.setTextAndValueAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? realAdminCount == 0 ? getChannelAdminCount() : realAdminCount : getAdminCount()), R.drawable.msg_admins, true); + adminCell.setTextAndValueAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? realAdminCount == 0 ? getChannelAdminCount() : realAdminCount : getAdminCount()), R.drawable.msg_admins, true); } } } else { if (isChannel) { - membersCell.setTextAndIcon(LocaleController.getString("ChannelSubscribers", R.string.ChannelSubscribers), R.drawable.msg_groups, true); - blockCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndIcon(getString("ChannelSubscribers", R.string.ChannelSubscribers), R.drawable.msg_groups, true); + blockCell.setTextAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { - membersCell.setTextAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), R.drawable.msg_groups, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndIcon(getString("ChannelMembers", R.string.ChannelMembers), R.drawable.msg_groups, logCell != null && logCell.getVisibility() == View.VISIBLE); if (currentChat.gigagroup) { - blockCell.setText(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), logCell != null && logCell.getVisibility() == View.VISIBLE); + blockCell.setTextAndIcon(getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { - blockCell.setTextAndIcon(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), R.drawable.msg_permissions, true); + blockCell.setTextAndIcon(getString("ChannelPermissions", R.string.ChannelPermissions), R.drawable.msg_permissions, true); } } - adminCell.setTextAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); + adminCell.setTextAndIcon(getString("ChannelAdministrators", R.string.ChannelAdministrators), R.drawable.msg_admins, true); } reactionsCell.setVisibility(ChatObject.canChangeChatInfo(currentChat) ? View.VISIBLE : View.GONE); updateReactionsCell(animated); @@ -1972,15 +1948,15 @@ private void updateFields(boolean updateChat, boolean animated) { inviteLinksCell.setVisibility(View.GONE); } else { if (info.invitesCount > 0) { - inviteLinksCell.setTextAndValueAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), Integer.toString(info.invitesCount), R.drawable.msg_link2, true); + inviteLinksCell.setTextAndValueAndIcon(getString("InviteLinks", R.string.InviteLinks), Integer.toString(info.invitesCount), R.drawable.msg_link2, true); } else { - inviteLinksCell.setTextAndValueAndIcon(LocaleController.getString("InviteLinks", R.string.InviteLinks), "1", R.drawable.msg_link2, true); + inviteLinksCell.setTextAndValueAndIcon(getString("InviteLinks", R.string.InviteLinks), "1", R.drawable.msg_link2, true); } } } if (stickersCell != null && info != null) { - stickersCell.setTextAndValue(LocaleController.getString(R.string.GroupStickers), info.stickerset != null ? info.stickerset.title : LocaleController.getString(R.string.Add), false); + stickersCell.setTextAndValueAndIcon(getString(R.string.GroupStickers), info.stickerset != null ? info.stickerset.title : getString(R.string.Add), R.drawable.msg_sticker, false); } if (logCell != null && !ChatObject.hasAdminRights(currentChat)) logCell.setVisibility(View.GONE); @@ -1988,7 +1964,7 @@ private void updateFields(boolean updateChat, boolean animated) { public void updateColorCell() { if (colorCell != null) { - colorCell.set(currentChat, (historyCell != null && historyCell.getVisibility() == View.VISIBLE) || (signCell != null && signCell.getVisibility() == View.VISIBLE) || (forumsCell != null && forumsCell.getVisibility() == View.VISIBLE)); + colorCell.set(currentChat, (historyCell != null && historyCell.getVisibility() == View.VISIBLE) || (signCell != null && signCell.getVisibility() == View.VISIBLE) || (forumsCell != null && forumsCell.getVisibility() == View.VISIBLE) || ChatObject.isMegagroup(currentChat) && ChatObject.hasAdminRights(currentChat)); } } @@ -2069,7 +2045,7 @@ private void updateReactionsCell(boolean animated) { boolean isChannelAndNotMegaGroup = ChatObject.isChannelAndNotMegaGroup(currentChat); String finalString; if (availableReactions == null || availableReactions instanceof TLRPC.TL_chatReactionsNone) { - finalString = LocaleController.getString("ReactionsOff", R.string.ReactionsOff); + finalString = getString("ReactionsOff", R.string.ReactionsOff); } else if (availableReactions instanceof TLRPC.TL_chatReactionsSome) { TLRPC.TL_chatReactionsSome someReactions = (TLRPC.TL_chatReactionsSome) availableReactions; int count = 0; @@ -2086,16 +2062,16 @@ private void updateReactionsCell(boolean animated) { } } if (isChannelAndNotMegaGroup) { - finalString = count == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) : String.valueOf(count); + finalString = count == 0 ? getString("ReactionsOff", R.string.ReactionsOff) : String.valueOf(count); } else { int reacts = Math.min(getMediaDataController().getEnabledReactionsList().size(), count); - finalString = reacts == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) : + finalString = reacts == 0 ? getString("ReactionsOff", R.string.ReactionsOff) : LocaleController.formatString("ReactionsCount", R.string.ReactionsCount, reacts, getMediaDataController().getEnabledReactionsList().size()); } } else { - finalString = LocaleController.getString("ReactionsAll", R.string.ReactionsAll); + finalString = getString("ReactionsAll", R.string.ReactionsAll); } - reactionsCell.setTextAndValueAndIcon(LocaleController.getString("Reactions", R.string.Reactions), finalString, animated, R.drawable.msg_reactions2, true); + reactionsCell.setTextAndValueAndIcon(getString("Reactions", R.string.Reactions), finalString, animated, R.drawable.msg_reactions2, true); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java index 1e51b4788f..5bcc6f13af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java @@ -4,15 +4,19 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; +import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; @@ -29,9 +33,14 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CounterView; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.Forum.ForumUtilities; +import org.telegram.ui.Components.LetterDrawable; +import org.telegram.ui.Components.StaticLayoutEx; import java.util.ArrayList; @@ -58,8 +67,10 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC int layout1Width; int layout2Width; - ImageReceiver imageReceiver = new ImageReceiver(); + private final ImageReceiver imageReceiver; TLRPC.Chat nextChat; + TLRPC.TL_forumTopic nextTopic; + private long lastWidthTopicId = 0L; AnimatorSet showReleaseAnimator; @@ -76,26 +87,34 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC private final View fragmentView; public long lastShowingReleaseTime; + boolean recommendedChannel; boolean drawFolderBackground; + private final boolean isTopic; Runnable onAnimationFinishRunnable; public long nextDialogId; View parentView; + private boolean visibleCounterDrawable = true; CounterView.CounterDrawable counterDrawable = new CounterView.CounterDrawable(null, true, null); int params[] = new int[3]; private final int currentAccount; private final int folderId; private final int filterId; + private final long topicId; private final long currentDialog; private final Theme.ResourcesProvider resourcesProvider; + private AnimatedEmojiDrawable animatedEmojiDrawable; - public ChatPullingDownDrawable(int currentAccount, View fragmentView, long currentDialog, int folderId, int filterId, Theme.ResourcesProvider resourcesProvider) { + public ChatPullingDownDrawable(int currentAccount, View fragmentView, long currentDialog, int folderId, int filterId, long topicId, Theme.ResourcesProvider resourcesProvider) { this.fragmentView = fragmentView; this.currentAccount = currentAccount; this.currentDialog = currentDialog; this.folderId = folderId; this.filterId = filterId; + this.topicId = topicId; + this.isTopic = MessagesController.getInstance(currentAccount).isForum(currentDialog); this.resourcesProvider = resourcesProvider; + this.imageReceiver = new ImageReceiver(fragmentView); arrowPaint.setStrokeWidth(AndroidUtilities.dpf2(2.8f)); arrowPaint.setStrokeCap(Paint.Cap.ROUND); @@ -111,11 +130,37 @@ public ChatPullingDownDrawable(int currentAccount, View fragmentView, long curre xRefPaint.setColor(0xff000000); xRefPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } - updateDialog(); + public void updateDialog(TLRPC.Chat chat) { + if (chat == null) { + updateDialog(); + return; + } + + nextDialogId = -chat.id; + drawFolderBackground = params[0] == 1; + dialogFolderId = params[1]; + dialogFilterId = params[2]; + emptyStub = false; + nextChat = chat; + AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(currentAccount, nextChat); + imageReceiver.setImage(ImageLocation.getForChat(nextChat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, UserConfig.getInstance(0).getCurrentUser(), 0); + MessagesController.getInstance(currentAccount).ensureMessagesLoaded(-chat.id, 0, null); + + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).getDialog(-chat.id); + final int count = dialog == null ? 0 : dialog.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; + + recommendedChannel = true; + nextTopic = null; } public void updateDialog() { + recommendedChannel = false; + nextTopic = null; TLRPC.Dialog dialog = getNextUnreadDialog(currentDialog, folderId, filterId, true, params); if (dialog != null) { nextDialogId = dialog.id; @@ -125,13 +170,15 @@ public void updateDialog() { emptyStub = false; nextChat = MessagesController.getInstance(currentAccount).getChat(-dialog.id); if (nextChat == null) { - MessagesController.getInstance(currentAccount).getChat(dialog.id); + nextChat = MessagesController.getInstance(currentAccount).getChat(dialog.id); } AvatarDrawable avatarDrawable = new AvatarDrawable(); avatarDrawable.setInfo(currentAccount, nextChat); imageReceiver.setImage(ImageLocation.getForChat(nextChat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, UserConfig.getInstance(0).getCurrentUser(), 0); MessagesController.getInstance(currentAccount).ensureMessagesLoaded(dialog.id, 0, null); - counterDrawable.setCount(dialog.unread_count, false); + final int count = dialog.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; } else { nextChat = null; drawFolderBackground = false; @@ -139,28 +186,92 @@ public void updateDialog() { } } + public void updateTopic() { + recommendedChannel = false; + drawFolderBackground = false; + nextChat = null; + nextDialogId = 0; + imageReceiver.clearImage(); + + TLRPC.TL_forumTopic topic = getNextUnreadTopic(-currentDialog); + if (topic != null) { + emptyStub = false; + nextTopic = topic; + Drawable forumIcon; + if (topic.id == 1) { + if (parentView != null && animatedEmojiDrawable != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = null; + forumIcon = ForumUtilities.createGeneralTopicDrawable(fragmentView.getContext(), 1f, getThemedColor(Theme.key_chat_inMenu), false); + imageReceiver.setImageBitmap(forumIcon); + } else if (topic.icon_emoji_id != 0) { + if (animatedEmojiDrawable == null || animatedEmojiDrawable.getDocumentId() != topic.icon_emoji_id) { + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_FORUM_TOPIC_LARGE, currentAccount, topic.icon_emoji_id); + animatedEmojiDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_serviceText), PorterDuff.Mode.SRC_IN)); + } + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.addView(parentView); + } + imageReceiver.setImageBitmap((Bitmap) null); + } else { + if (parentView != null && animatedEmojiDrawable != null) { + animatedEmojiDrawable.removeView(parentView); + } + animatedEmojiDrawable = null; + forumIcon = ForumUtilities.createTopicDrawable(topic, false); + imageReceiver.setImageBitmap(forumIcon); + } + final int count = topic.unread_count; + counterDrawable.setCount(count, false); + visibleCounterDrawable = count > 0; + } else { + nextTopic = null; + emptyStub = true; + } + } + public void setWidth(int width) { - if (width != lastWidth) { + if (width != lastWidth || (isTopic && nextTopic != null && lastWidthTopicId != nextTopic.id)) { circleRadius = AndroidUtilities.dp(56) / 2f; lastWidth = width; - String nameStr = nextChat != null ? nextChat.title : LocaleController.getString("SwipeToGoNextChannelEnd", R.string.SwipeToGoNextChannelEnd); - chatNameWidth = (int) textPaint.measureText(nameStr); + CharSequence nameStr; + if (nextChat != null) { + nameStr = nextChat.title; + } else if (nextTopic != null) { + nameStr = nextTopic.title; + } else if (isTopic) { + String forumName = MessagesController.getInstance(currentAccount).getChat(-currentDialog).title; + nameStr = LocaleController.formatString(R.string.SwipeToGoNextTopicEnd, forumName); + } else { + nameStr = LocaleController.getString(R.string.SwipeToGoNextChannelEnd); + } + chatNameWidth = (int) textPaint.measureText(nameStr, 0, nameStr.length()); chatNameWidth = Math.min(chatNameWidth, lastWidth - AndroidUtilities.dp(60)); - chatNameLayout = new StaticLayout(nameStr, textPaint, chatNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + chatNameLayout = StaticLayoutEx.createStaticLayout(nameStr, textPaint, chatNameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, chatNameWidth, 1); String str1 = null; String str2 = null; - if (drawFolderBackground && dialogFolderId != folderId && dialogFolderId != 0) { - str1 = LocaleController.getString("SwipeToGoNextArchive", R.string.SwipeToGoNextArchive); - str2 = LocaleController.getString("ReleaseToGoNextArchive", R.string.ReleaseToGoNextArchive); + if (recommendedChannel) { + str1 = LocaleController.getString(R.string.SwipeToGoNextRecommendedChannel); + str2 = LocaleController.getString(R.string.ReleaseToGoNextRecommendedChannel); + } else if (isTopic) { + str1 = LocaleController.getString(R.string.SwipeToGoNextUnreadTopic); + str2 = LocaleController.getString(R.string.ReleaseToGoNextUnreadTopic); + } else if (drawFolderBackground && dialogFolderId != folderId && dialogFolderId != 0) { + str1 = LocaleController.getString(R.string.SwipeToGoNextArchive); + str2 = LocaleController.getString(R.string.ReleaseToGoNextArchive); } else if (drawFolderBackground) { - str1 = LocaleController.getString("SwipeToGoNextFolder", R.string.SwipeToGoNextFolder); - str2 = LocaleController.getString("ReleaseToGoNextFolder", R.string.ReleaseToGoNextFolder); + str1 = LocaleController.getString(R.string.SwipeToGoNextFolder); + str2 = LocaleController.getString(R.string.ReleaseToGoNextFolder); } else { - str1 = LocaleController.getString("SwipeToGoNextChannel", R.string.SwipeToGoNextChannel); - str2 = LocaleController.getString("ReleaseToGoNextChannel", R.string.ReleaseToGoNextChannel); + str1 = LocaleController.getString(R.string.SwipeToGoNextChannel); + str2 = LocaleController.getString(R.string.ReleaseToGoNextChannel); } layout1Width = (int) textPaint2.measureText(str1); layout1Width = Math.min(layout1Width, lastWidth - AndroidUtilities.dp(60)); @@ -178,12 +289,20 @@ public void setWidth(int width) { imageReceiver.setRoundRadius((int) (AndroidUtilities.dp(40) / 2f)); counterDrawable.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(100)); + if (isTopic) { + lastWidthTopicId = nextTopic == null ? 0 : nextTopic.id; + } } } public void draw(Canvas canvas, View parent, float progress, float alpha) { - this.parentView = parent; + if (this.parentView != parent) { + this.parentView = parent; + if (animatedEmojiDrawable != null) { + animatedEmojiDrawable.addView(parent); + } + } counterDrawable.setParent(parent); int oldAlpha, oldAlpha1, oldAlpha2, oldAlpha3; float offset = AndroidUtilities.dp(110) * progress; @@ -291,12 +410,21 @@ public void draw(Canvas canvas, View parent, float progress, float alpha) { if (!emptyStub && size > 0) { float top = (-AndroidUtilities.dp(8) - AndroidUtilities.dp2(8) * progress - size) * (1f - swipeToReleaseProgress) + (-offset + AndroidUtilities.dp(4)) * swipeToReleaseProgress + bounceOffset; - imageReceiver.setRoundRadius((int) (size / 2f)); - imageReceiver.setImageCoords(cx - size / 2f, top, size, size); + ImageReceiver finalImageReceiver; + if (animatedEmojiDrawable != null && animatedEmojiDrawable.getImageReceiver() != null) { + finalImageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + finalImageReceiver = imageReceiver; + } + finalImageReceiver.setRoundRadius((int) (size / 2f)); + finalImageReceiver.setImageCoords(cx - size / 2f, top, size, size); + if (isTopic && finalImageReceiver.getDrawable() != null && finalImageReceiver.getDrawable() instanceof CombinedDrawable && ((CombinedDrawable) finalImageReceiver.getDrawable()).getIcon() instanceof LetterDrawable) { + ((LetterDrawable) ((CombinedDrawable) finalImageReceiver.getDrawable()).getIcon()).scale = progress; + } - if (swipeToReleaseProgress > 0) { - canvas.saveLayerAlpha(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX() + imageReceiver.getImageWidth(), imageReceiver.getImageY() + imageReceiver.getImageHeight(), 255, Canvas.ALL_SAVE_FLAG); - imageReceiver.draw(canvas); + if (swipeToReleaseProgress > 0 && visibleCounterDrawable) { + canvas.saveLayerAlpha(finalImageReceiver.getImageX(), finalImageReceiver.getImageY(), finalImageReceiver.getImageX() + finalImageReceiver.getImageWidth(), finalImageReceiver.getImageY() + finalImageReceiver.getImageHeight(), 255, Canvas.ALL_SAVE_FLAG); + finalImageReceiver.draw(canvas); canvas.scale(swipeToReleaseProgress, swipeToReleaseProgress, cx + AndroidUtilities.dp(12) + counterDrawable.getCenterX(), top - AndroidUtilities.dp(6) + AndroidUtilities.dp(14)); canvas.translate(cx + AndroidUtilities.dp(12), top - AndroidUtilities.dp(6)); counterDrawable.updateBackgroundRect(); @@ -310,8 +438,7 @@ public void draw(Canvas canvas, View parent, float progress, float alpha) { counterDrawable.draw(canvas); canvas.restore(); } else { - - imageReceiver.draw(canvas); + finalImageReceiver.draw(canvas); } } @@ -480,12 +607,18 @@ private void drawArrow(Canvas canvas, float cx, float cy, float size) { public void onAttach() { imageReceiver.onAttachedToWindow(); + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.addView(parentView); + } NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces); } public void onDetach() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateInterfaces); imageReceiver.onDetachedFromWindow(); + if (animatedEmojiDrawable != null && parentView != null) { + animatedEmojiDrawable.removeView(parentView); + } lastProgress = 0; lastHapticTime = 0; } @@ -495,7 +628,9 @@ public void didReceivedNotification(int id, int account, Object... args) { if (nextDialogId != 0) { TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(nextDialogId); if (dialog != null) { - counterDrawable.setCount(dialog.unread_count, true); + final int count = dialog.unread_count; + counterDrawable.setCount(count, true); + visibleCounterDrawable = count > 0; if (parentView != null) { parentView.invalidate(); } @@ -572,10 +707,28 @@ public static TLRPC.Dialog getNextUnreadDialog(long currentDialogId, int folderI return null; } + private TLRPC.TL_forumTopic getNextUnreadTopic(long currentDialogId) { + ArrayList topics = MessagesController.getInstance(currentAccount).getTopicsController().getTopics(currentDialogId); + TLRPC.TL_forumTopic nextUnreadTopic = null; + if (topics != null && topics.size() > 1) { + for (int i = 0; i < topics.size(); i++) { + TLRPC.TL_forumTopic topic = topics.get(i); + if (topic.id != topicId && !topic.hidden && topic.unread_count > 0 && (nextUnreadTopic == null || topic.topMessage.date > nextUnreadTopic.topMessage.date)) { + nextUnreadTopic = topic; + } + } + } + return nextUnreadTopic; + } + public long getChatId() { return nextChat.id; } + public TLRPC.TL_forumTopic getTopic() { + return nextTopic; + } + public void drawBottomPanel(Canvas canvas, int top, int bottom, int width) { if (showBottomPanel && progressToBottomPanel != 1f) { progressToBottomPanel += 16f / 150f; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index b35e297aee..5c38fcc7f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -117,6 +117,7 @@ public class ChatRightsEditActivity extends BaseFragment { private TLRPC.TL_chatAdminRights myAdminRights; private TLRPC.TL_chatBannedRights bannedRights; private TLRPC.TL_chatBannedRights defaultBannedRights; + public boolean banning; private String currentBannedRights = ""; private String currentRank; private String initialRank; @@ -616,6 +617,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { } finishFragment(); } else if (currentType == TYPE_BANNED) { + banning = true; bannedRights = new TLRPC.TL_chatBannedRights(); bannedRights.view_messages = true; bannedRights.send_media = true; @@ -2107,6 +2109,9 @@ private void setSendMediaEnabled(boolean enabled) { bannedRights.send_photos = !enabled; bannedRights.send_videos = !enabled; bannedRights.send_stickers = !enabled; + bannedRights.send_gifs = !enabled; + bannedRights.send_games = !enabled; + bannedRights.send_inline = !enabled; bannedRights.send_audios = !enabled; bannedRights.send_docs = !enabled; bannedRights.send_voices = !enabled; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java new file mode 100644 index 0000000000..7433fd5b82 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert2.java @@ -0,0 +1,397 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; + +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.CheckBoxCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; + +public class AdminLogFilterAlert2 extends BottomSheetWithRecyclerListView { + + private UniversalAdapter adapter; + + private TLRPC.TL_channelAdminLogEventsFilter currentFilter = new TLRPC.TL_channelAdminLogEventsFilter(); + private ArrayList currentAdmins; + private LongSparseArray selectedAdmins; + private boolean isMegagroup; + + + private final ButtonWithCounterView actionButton; + private final SelectorBtnCell buttonContainer; + + public AdminLogFilterAlert2(BaseFragment fragment, TLRPC.TL_channelAdminLogEventsFilter filter, LongSparseArray admins, boolean megagroup) { + super(fragment, false, false); + topPadding = 0.6f; + fixNavigationBar(); + setSlidingActionBar(); + setShowHandle(true); + + if (filter != null) { + currentFilter.join = filter.join; + currentFilter.leave = filter.leave; + currentFilter.invite = filter.invite; + currentFilter.ban = filter.ban; + currentFilter.unban = filter.unban; + currentFilter.kick = filter.kick; + currentFilter.unkick = filter.unkick; + currentFilter.promote = filter.promote; + currentFilter.demote = filter.demote; + currentFilter.info = filter.info; + currentFilter.settings = filter.settings; + currentFilter.pinned = filter.pinned; + currentFilter.edit = filter.edit; + currentFilter.delete = filter.delete; + currentFilter.group_call = filter.group_call; + currentFilter.invites = filter.invites; + } else { + currentFilter.join = true; + currentFilter.leave = true; + currentFilter.invite = true; + currentFilter.ban = true; + currentFilter.unban = true; + currentFilter.kick = true; + currentFilter.unkick = true; + currentFilter.promote = true; + currentFilter.demote = true; + currentFilter.info = true; + currentFilter.settings = true; + currentFilter.pinned = true; + currentFilter.edit = true; + currentFilter.delete = true; + currentFilter.group_call = true; + currentFilter.invites = true; + } + if (admins != null) { + selectedAdmins = admins.clone(); + } + isMegagroup = megagroup; + adapter.update(false); + + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDelayAnimations(false); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDurations(350); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.setOnItemClickListener((view, position, x, y) -> { + onClick(adapter.getItem(position - 1), view, x); + }); + + buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, null); + buttonContainer.setClickable(true); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setPadding(dp(10), dp(10), dp(10), dp(10)); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + actionButton = new ButtonWithCounterView(getContext(), resourcesProvider); + actionButton.setText(getString(R.string.EventLogFilterApply), false); + actionButton.setOnClickListener(v -> { + if (currentFilter.join && + currentFilter.leave && + currentFilter.invite && + currentFilter.ban && + currentFilter.unban && + currentFilter.kick && + currentFilter.unkick && + currentFilter.promote && + currentFilter.demote && + currentFilter.info && + currentFilter.settings && + currentFilter.pinned && + currentFilter.edit && + currentFilter.delete && + currentFilter.group_call && + currentFilter.invites) { + currentFilter = null; + } + if (selectedAdmins != null && currentAdmins != null && selectedAdmins.size() >= currentAdmins.size()) { + selectedAdmins = null; + } + delegate.didSelectRights(currentFilter, selectedAdmins); + dismiss(); + }); + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(68)); + } + + @Override + protected CharSequence getTitle() { + return getString(R.string.EventLog); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + return adapter = new UniversalAdapter(listView, getContext(), currentAccount, 0, true, this::fillItems, resourcesProvider); + } + + private final static int FILTER_SECTION_MEMBERS = 2; + private final static int FILTER_NEW_ADMINS = 3; + private final static int FILTER_RESTRICTIONS = 4; + private final static int FILTER_NEW_MEMBERS = 5; + private final static int FILTER_MEMBERS_LEFT = 6; + private final static int FILTER_SECTION_SETTINGS = 7; + private final static int FILTER_INFO = 8; + private final static int FILTER_INVITES = 9; + private final static int FILTER_CALLS = 10; + private final static int FILTER_SECTION_MESSAGES = 11; + private final static int FILTER_DELETE = 12; + private final static int FILTER_EDIT = 13; + private final static int FILTER_PIN = 14; + private final static int BUTTON_ALL_ADMINS = 15; + + private boolean sectionMembersExpanded = false; + private boolean sectionSettingsExpanded = false; + private boolean sectionMessagesExpanded = false; + + private String getGroupCount(int a) { + switch (a) { + case 0: return ( + (currentFilter.promote || currentFilter.demote ? 1 : 0) + + (isMegagroup && (currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban) ? 1 : 0) + + (currentFilter.invite || currentFilter.join ? 1 : 0) + + (currentFilter.leave ? 1 : 0) + + "/" + (isMegagroup ? 4 : 3) + ); + case 1: return ( + (currentFilter.info || currentFilter.settings ? 1 : 0) + + (currentFilter.invites ? 1 : 0) + + (currentFilter.group_call ? 1 : 0) + + "/3" + ); + case 2: + default: return ( + (currentFilter.delete ? 1 : 0) + + (currentFilter.edit ? 1 : 0) + + (currentFilter.pinned ? 1 : 0) + + "/3" + ); + } + } + + private View.OnClickListener getGroupClick(int a) { + return v -> { + saveScrollPosition(); + switch (a) { + case 0: + sectionMembersExpanded = !sectionMembersExpanded; + break; + case 1: + sectionSettingsExpanded = !sectionSettingsExpanded; + break; + case 2: + sectionMessagesExpanded = !sectionMessagesExpanded; + break; + } + adapter.update(true); + applyScrolledPosition(); + }; + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + if (currentFilter == null) return; + items.add(UItem.asHeader(getString(R.string.EventLogFilterByActions))); + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_MEMBERS, getString(R.string.EventLogFilterSectionMembers), getGroupCount(0)).setChecked( + currentFilter.promote || currentFilter.demote || + isMegagroup && (currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban) || + currentFilter.invite || currentFilter.join || + currentFilter.leave + ).setCollapsed(!sectionMembersExpanded).setClickCallback(getGroupClick(0))); + if (sectionMembersExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_NEW_ADMINS, getString(R.string.EventLogFilterSectionAdmin)).pad().setChecked(currentFilter.promote || currentFilter.demote)); + if (isMegagroup) { + items.add(UItem.asRoundCheckbox(FILTER_RESTRICTIONS, getString(R.string.EventLogFilterNewRestrictions)).pad().setChecked(currentFilter.kick || currentFilter.ban || currentFilter.unkick || currentFilter.unban)); + } + items.add(UItem.asRoundCheckbox(FILTER_NEW_MEMBERS, getString(R.string.EventLogFilterNewMembers)).pad().setChecked(currentFilter.invite || currentFilter.join)); + items.add(UItem.asRoundCheckbox(FILTER_MEMBERS_LEFT, getString(R.string.EventLogFilterLeavingMembers2)).pad().setChecked(currentFilter.leave)); + } + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_SETTINGS, getString(isMegagroup ? R.string.EventLogFilterSectionGroupSettings : R.string.EventLogFilterSectionChannelSettings), getGroupCount(1)).setChecked( + currentFilter.info || currentFilter.settings || + currentFilter.invites || + currentFilter.group_call + ).setCollapsed(!sectionSettingsExpanded).setClickCallback(getGroupClick(1))); + if (sectionSettingsExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_INFO, getString(isMegagroup ? R.string.EventLogFilterGroupInfo : R.string.EventLogFilterChannelInfo)).pad().setChecked(currentFilter.info || currentFilter.settings)); + items.add(UItem.asRoundCheckbox(FILTER_INVITES, getString(R.string.EventLogFilterInvites)).pad().setChecked(currentFilter.invites)); + items.add(UItem.asRoundCheckbox(FILTER_CALLS, getString(R.string.EventLogFilterCalls)).pad().setChecked(currentFilter.group_call)); + } + items.add(UItem.asRoundGroupCheckbox(FILTER_SECTION_MESSAGES, getString(R.string.EventLogFilterSectionMessages), getGroupCount(2)).setChecked( + currentFilter.delete || currentFilter.edit || currentFilter.pinned + ).setCollapsed(!sectionMessagesExpanded).setClickCallback(getGroupClick(2))); + if (sectionMessagesExpanded) { + items.add(UItem.asRoundCheckbox(FILTER_DELETE, getString(R.string.EventLogFilterDeletedMessages)).pad().setChecked(currentFilter.delete)); + items.add(UItem.asRoundCheckbox(FILTER_EDIT, getString(R.string.EventLogFilterEditedMessages)).pad().setChecked(currentFilter.edit)); + items.add(UItem.asRoundCheckbox(FILTER_PIN, getString(R.string.EventLogFilterPinnedMessages)).pad().setChecked(currentFilter.pinned)); + } + items.add(UItem.asShadow(null)); + items.add(UItem.asHeader(getString(R.string.EventLogFilterByAdmins))); + items.add(UItem.asRoundCheckbox(BUTTON_ALL_ADMINS, getString(R.string.EventLogFilterByAdminsAll)).setChecked((selectedAdmins == null ? 0 : selectedAdmins.size()) >= (currentAdmins == null ? 0 : currentAdmins.size()))); + if (currentAdmins != null) { + for (int i = 0; i < currentAdmins.size(); ++i) { + TLRPC.ChannelParticipant admin = currentAdmins.get(i); + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + items.add(UItem.asUserCheckbox(-1 - i, user).pad().setChecked(selectedAdmins != null && selectedAdmins.containsKey(did))); + } + } + } + + public void onClick(UItem item, View view, float x) { + if (item == null) return; + if (item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX || item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX) { + saveScrollPosition(); + final boolean clickedGroupExpand = item.viewType == UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX && (LocaleController.isRTL ? x < view.getMeasuredWidth() - dp(60) : x > dp(60)); + CheckBoxCell cell = (CheckBoxCell) view; + if (!clickedGroupExpand) { + cell.setChecked(!cell.isChecked(), true); + } + switch (item.id) { + case FILTER_SECTION_MEMBERS: + if (clickedGroupExpand) { + sectionMembersExpanded = !sectionMembersExpanded; + } else { + currentFilter.promote = currentFilter.demote = currentFilter.invite = currentFilter.join = currentFilter.leave = cell.isChecked(); + if (isMegagroup) { + currentFilter.kick = currentFilter.ban = currentFilter.unkick = currentFilter.unban = cell.isChecked(); + } + } + break; + case FILTER_NEW_ADMINS: + currentFilter.promote = currentFilter.demote = cell.isChecked(); + break; + case FILTER_RESTRICTIONS: + currentFilter.kick = currentFilter.ban = currentFilter.unkick = currentFilter.unban = cell.isChecked(); + break; + case FILTER_NEW_MEMBERS: + currentFilter.invite = currentFilter.join = cell.isChecked(); + break; + case FILTER_MEMBERS_LEFT: + currentFilter.leave = cell.isChecked(); + break; + case FILTER_SECTION_SETTINGS: + if (clickedGroupExpand) { + sectionSettingsExpanded = !sectionSettingsExpanded; + } else { + currentFilter.info = currentFilter.settings = currentFilter.invites = currentFilter.group_call = cell.isChecked(); + } + break; + case FILTER_INFO: + currentFilter.info = currentFilter.settings = cell.isChecked(); + break; + case FILTER_INVITES: + currentFilter.invites = cell.isChecked(); + break; + case FILTER_CALLS: + currentFilter.group_call = cell.isChecked(); + break; + case FILTER_SECTION_MESSAGES: + if (clickedGroupExpand) { + sectionMessagesExpanded = !sectionMessagesExpanded; + } else { + currentFilter.delete = currentFilter.edit = currentFilter.pinned = cell.isChecked(); + } + break; + case FILTER_DELETE: + currentFilter.delete = cell.isChecked(); + break; + case FILTER_EDIT: + currentFilter.edit = cell.isChecked(); + break; + case FILTER_PIN: + currentFilter.pinned = cell.isChecked(); + break; + case BUTTON_ALL_ADMINS: + if (selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + } + selectedAdmins.clear(); + if (cell.isChecked() && currentAdmins != null) { + for (TLRPC.ChannelParticipant admin : currentAdmins) { + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + selectedAdmins.put(did, user); + } + } + break; + } + adapter.update(true); + } + if (item.id < 0) { + CheckBoxCell cell = (CheckBoxCell) view; + int index = (-item.id) - 1; + if (index < 0 || index >= currentAdmins.size()) return; + TLRPC.ChannelParticipant admin = currentAdmins.get(index); + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + if (selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + } + if (selectedAdmins.containsKey(did)) { + selectedAdmins.remove(did); + cell.setChecked(false, true); + } else { + selectedAdmins.put(did, user); + cell.setChecked(true, true); + } + adapter.update(true); + } + } + + public void setCurrentAdmins(ArrayList admins) { + currentAdmins = admins; + if (currentAdmins != null && selectedAdmins == null) { + selectedAdmins = new LongSparseArray<>(); + for (TLRPC.ChannelParticipant admin : currentAdmins) { + final long did = DialogObject.getPeerDialogId(admin.peer); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + selectedAdmins.put(did, user); + } + } + if (adapter != null) { + adapter.update(true); + } + } + + private AdminLogFilterAlertDelegate delegate; + + public interface AdminLogFilterAlertDelegate { + void didSelectRights( + TLRPC.TL_channelAdminLogEventsFilter filter, + LongSparseArray admins + ); + } + + public void setAdminLogFilterAlertDelegate(AdminLogFilterAlertDelegate adminLogFilterAlertDelegate) { + delegate = adminLogFilterAlertDelegate; + } + + @Override + protected void onSmoothContainerViewLayout(float ty) { + super.onSmoothContainerViewLayout(ty); + buttonContainer.setTranslationY(-ty); + } + + @Override + protected boolean canDismissWithSwipe() { + return !recyclerListView.canScrollVertically(-1); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 9754c61c1f..ddefa7ae4c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -9,7 +9,6 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.messenger.LocaleController.formatDateOnline; import static org.telegram.messenger.LocaleController.getString; import android.Manifest; @@ -47,11 +46,9 @@ import android.text.TextWatcher; import android.text.style.URLSpan; import android.util.Base64; -import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -135,8 +132,13 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; import kotlin.Unit; import tw.nekomimi.nekogram.helpers.PasscodeHelper; @@ -1015,7 +1017,7 @@ public static void showCustomNotificationsDialog(BaseFragment parentFragment, lo return; } boolean enabled; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); String[] descriptions = new String[]{ LocaleController.getString("NotificationsTurnOn", R.string.NotificationsTurnOn), @@ -3792,6 +3794,7 @@ public CharSequence getAccessibilityClassName() { if (addPrivacyText != null) { FrameLayout frameLayout = new FrameLayout(context); LinkSpanDrawable.LinksTextView textView = new LinkSpanDrawable.LinksTextView(context); + textView.setPadding(dp(8), 0, dp(8), 0); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider)); textView.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); @@ -3822,7 +3825,7 @@ public CharSequence getAccessibilityClassName() { bottomSheetParams.transitionFromLeft = true; bottomSheetParams.allowNestedScroll = false; fragment.showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), bottomSheetParams); - }), true)); + }), true, dp(8f / 3f), dp(.66f))); }; setText.run(); @@ -5252,6 +5255,8 @@ public static Dialog createColorSelectDialog(Activity parentActivity, final long currentColor = preferences.getInt("GroupLed", 0xff0000ff); } else if (globalType == NotificationsController.TYPE_STORIES) { currentColor = preferences.getInt("StoriesLed", 0xff0000ff); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + currentColor = preferences.getInt("ReactionsLed", 0xff0000ff); } else { currentColor = preferences.getInt("ChannelLed", 0xff0000ff); } @@ -5299,6 +5304,8 @@ public static Dialog createColorSelectDialog(Activity parentActivity, final long editor.putInt("GroupLed", selectedColor[0]); } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("StoriesLed", selectedColor[0]); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionLed", selectedColor[0]); } else { editor.putInt("ChannelLed", selectedColor[0]); } @@ -5320,6 +5327,8 @@ public static Dialog createColorSelectDialog(Activity parentActivity, final long editor.putInt("GroupLed", 0); } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("StoriesLed", 0); + } else if (globalType == NotificationsController.TYPE_REACTIONS_STORIES || globalType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + editor.putInt("ReactionsLed", 0); } else { editor.putInt("ChannelLed", 0); } @@ -5438,6 +5447,8 @@ public static Dialog createVibrationSelectDialog(Activity parentActivity, final NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_CHANNEL); } else if (prefKeyPrefix.equals("vibrate_group")) { NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_GROUP); + } else if (prefKeyPrefix.equals("vibrate_react")) { + NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_REACTIONS_MESSAGES); } else { NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(NotificationsController.TYPE_PRIVATE); } @@ -5455,32 +5466,37 @@ public static Dialog createVibrationSelectDialog(Activity parentActivity, final return builder.create(); } - public static Dialog createLocationUpdateDialog(final Activity parentActivity, TLRPC.User user, final MessagesStorage.IntCallback callback, Theme.ResourcesProvider resourcesProvider) { + public static Dialog createLocationUpdateDialog(final Activity parentActivity, boolean expand, TLRPC.User user, final MessagesStorage.IntCallback callback, Theme.ResourcesProvider resourcesProvider) { final int[] selected = new int[1]; String[] descriptions = new String[]{ - LocaleController.getString("SendLiveLocationFor15m", R.string.SendLiveLocationFor15m), - LocaleController.getString("SendLiveLocationFor1h", R.string.SendLiveLocationFor1h), - LocaleController.getString("SendLiveLocationFor8h", R.string.SendLiveLocationFor8h), + getString(R.string.SendLiveLocationFor15m), + getString(R.string.SendLiveLocationFor1h), + getString(R.string.SendLiveLocationFor8h), + getString(R.string.SendLiveLocationForever) }; final LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(0, 0, 0, dp(4)); TextView titleTextView = new TextView(parentActivity); - if (user != null) { - titleTextView.setText(LocaleController.formatString("LiveLocationAlertPrivate", R.string.LiveLocationAlertPrivate, UserObject.getFirstName(user))); + if (expand) { + titleTextView.setText(LocaleController.getString(R.string.LiveLocationAlertExpandMessage)); + } else if (user != null) { + titleTextView.setText(LocaleController.formatString(R.string.LiveLocationAlertPrivate, UserObject.getFirstName(user))); } else { - titleTextView.setText(LocaleController.getString("LiveLocationAlertGroup", R.string.LiveLocationAlertGroup)); + titleTextView.setText(LocaleController.getString(R.string.LiveLocationAlertGroup)); } int textColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTextBlack) : Theme.getColor(Theme.key_dialogTextBlack); titleTextView.setTextColor(textColor); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); titleTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 0, 24, 8)); + linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, (expand ? 4 : 0), 24, 8)); for (int a = 0; a < descriptions.length; a++) { RadioColorCell cell = new RadioColorCell(parentActivity, resourcesProvider); + cell.heightDp = 42; cell.setPadding(dp(4), 0, dp(4), 0); cell.setTag(a); int color1 = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_radioBackground) : Theme.getColor(Theme.key_radioBackground); @@ -5501,8 +5517,12 @@ public static Dialog createLocationUpdateDialog(final Activity parentActivity, T }); } AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); - int topImageColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTopBackground) : Theme.getColor(Theme.key_dialogTopBackground); - builder.setTopImage(new ShareLocationDrawable(parentActivity, 0), topImageColor); + if (expand) { + builder.setTitle(getString(R.string.LiveLocationAlertExpandTitle)); + } else { + int topImageColor = resourcesProvider != null ? resourcesProvider.getColorOrDefault(Theme.key_dialogTopBackground) : Theme.getColor(Theme.key_dialogTopBackground); + builder.setTopImage(new ShareLocationDrawable(parentActivity, 0), topImageColor); + } builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("ShareFile", R.string.ShareFile), (dialog, which) -> { int time; @@ -5510,8 +5530,10 @@ public static Dialog createLocationUpdateDialog(final Activity parentActivity, T time = 15 * 60; } else if (selected[0] == 1) { time = 60 * 60; - } else { + } else if (selected[0] == 2) { time = 8 * 60 * 60; + } else { + time = 0x7FFFFFFF; } callback.run(time); }); @@ -5742,6 +5764,8 @@ public static Dialog createPrioritySelectDialog(Activity parentActivity, final l selected[0] = preferences.getInt("priority_channel", 1); } else if (globalType == NotificationsController.TYPE_STORIES) { selected[0] = preferences.getInt("priority_stories", 1); + } else if (globalType == NotificationsController.TYPE_REACTIONS_MESSAGES || globalType == NotificationsController.TYPE_REACTIONS_STORIES) { + selected[0] = preferences.getInt("priority_react", 1); } if (selected[0] == 4) { selected[0] = 0; @@ -5814,6 +5838,9 @@ public static Dialog createPrioritySelectDialog(Activity parentActivity, final l } else if (globalType == NotificationsController.TYPE_STORIES) { editor.putInt("priority_stories", option); selected[0] = preferences.getInt("priority_stories", 1); + } else if (globalType == NotificationsController.TYPE_REACTIONS_MESSAGES || globalType == NotificationsController.TYPE_REACTIONS_STORIES) { + editor.putInt("priority_react", option); + selected[0] = preferences.getInt("priority_react", 1); } NotificationsController.getInstance(UserConfig.selectedAccount).deleteNotificationChannelGlobal(globalType); } @@ -6016,7 +6043,7 @@ public interface PaymentAlertDelegate { void didPressedNewCard(); } - public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User user, TLRPC.Chat chat, TLRPC.EncryptedChat encryptedChat, TLRPC.ChatFull chatInfo, long mergeDialogId, MessageObject selectedMessage, SparseArray[] selectedMessages, MessageObject.GroupedMessages selectedGroup, int topicId, int mode, int loadParticipant, Runnable onDelete, Runnable hideDim, Theme.ResourcesProvider resourcesProvider) { + public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User user, TLRPC.Chat chat, TLRPC.EncryptedChat encryptedChat, TLRPC.ChatFull chatInfo, long mergeDialogId, MessageObject selectedMessage, SparseArray[] selectedMessages, MessageObject.GroupedMessages selectedGroup, int topicId, int mode, TLRPC.ChannelParticipant[] channelParticipants, Runnable onDelete, Runnable hideDim, Theme.ResourcesProvider resourcesProvider) { final boolean scheduled = mode == ChatActivity.MODE_SCHEDULED; final boolean isSavedMessages = mode == ChatActivity.MODE_SAVED; final boolean quickReplies = mode == ChatActivity.MODE_QUICK_REPLIES; @@ -6066,9 +6093,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u } final boolean[] checks = getDeleteMenuChecks(); - final boolean[] deleteForAll = {true}; - TLRPC.User actionUser = null; - TLRPC.Chat actionChat = null; + final boolean[] deleteForAll = new boolean[1]; boolean canRevokeInbox = user != null && MessagesController.getInstance(currentAccount).canRevokePmInbox; int revokeTimeLimit; if (user != null) { @@ -6083,20 +6108,16 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u if (chat != null && chat.megagroup && !scheduled && !isSavedMessages) { long linked_channel_id = - MessagesController.getInstance(currentAccount).getChatFull(chat.id).linked_chat_id; boolean canBan = ChatObject.canBlockUsers(chat); + ArrayList messages = new ArrayList<>(); if (selectedMessage != null) { if (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) { - if (selectedMessage.messageOwner.from_id.user_id != 0) { - actionUser = MessagesController.getInstance(currentAccount).getUser(selectedMessage.messageOwner.from_id.user_id); - } else if (selectedMessage.messageOwner.from_id.channel_id != 0) { - actionChat = MessagesController.getInstance(currentAccount).getChat(selectedMessage.messageOwner.from_id.channel_id); - } else if (selectedMessage.messageOwner.from_id.chat_id != 0) { - actionChat = MessagesController.getInstance(currentAccount).getChat(selectedMessage.messageOwner.from_id.chat_id); - } - if (actionChat != null && actionChat.id == -linked_channel_id) { - actionChat = null; + if (selectedGroup != null) { + messages.addAll(selectedGroup.messages); + } else { + messages.add(selectedMessage); } } boolean hasOutgoing = !selectedMessage.isSendError() && selectedMessage.getDialogId() == mergeDialogId && (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && selectedMessage.isOut() && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; @@ -6104,30 +6125,6 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u myMessagesCount++; } } else { - long from_id = -1; - long from_channel_id = -1; - for (int a = 1; a >= 0; a--) { - long channelId = 0; - for (int b = 0; b < selectedMessages[a].size(); b++) { - MessageObject msg = selectedMessages[a].valueAt(b); - if (from_id == -1) { - from_id = msg.getFromChatId(); - } - if (from_id < 0 && from_id == msg.getSenderId() && from_id != linked_channel_id) { - from_channel_id = from_id; - continue; - } - if (from_id < 0 || from_id != msg.getSenderId()) { - if (from_channel_id != msg.getSenderId()) - from_channel_id = 0; - from_id = -2; - break; - } - } - if (from_id == -2) { - break; - } - } for (int a = 1; a >= 0; a--) { for (int b = 0; b < selectedMessages[a].size(); b++) { MessageObject msg = selectedMessages[a].valueAt(b); @@ -6138,82 +6135,98 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u } } } + messages.add(msg); } } - if (from_id != -1) { - actionUser = MessagesController.getInstance(currentAccount).getUser(from_id); - } - if(actionUser == null && from_channel_id != -1) { - actionChat = MessagesController.getInstance(currentAccount).getChat(-from_channel_id); - } } - if ((actionUser != null && actionUser.id != UserConfig.getInstance(currentAccount).getClientUserId()) || (actionChat != null && !ChatObject.hasAdminRights(actionChat))) { - if (loadParticipant == 1 && !chat.creator && actionUser != null) { + + long clientUserId = UserConfig.getInstance(currentAccount).getClientUserId(); + ArrayList actionParticipants = messages + .stream() + .mapToLong(MessageObject::getFromChatId) + .distinct() + .mapToObj(fromId -> { + if (fromId > 0) { + return MessagesController.getInstance(currentAccount).getUser(fromId); + } else { + return MessagesController.getInstance(currentAccount).getChat(-fromId); + } + }) + .filter(Objects::nonNull) + .filter(userOrChat -> { + if (userOrChat instanceof TLRPC.User) { + TLRPC.User user1 = (TLRPC.User) userOrChat; + return user1.id != clientUserId; + } else if (userOrChat instanceof TLRPC.Chat) { + TLRPC.Chat chat1 = (TLRPC.Chat) userOrChat; + return !ChatObject.hasAdminRights(chat1); + } + return false; + }) + .collect(Collectors.toCollection(ArrayList::new)); + + if (!actionParticipants.isEmpty()) { + if (channelParticipants == null) { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(activity, AlertDialog.ALERT_TYPE_SPINNER)}; - TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); - req.channel = MessagesController.getInputChannel(chat); - req.participant = MessagesController.getInputPeer(actionUser); - int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - try { - progressDialog[0].dismiss(); - } catch (Throwable ignore) { + final int participantCount = actionParticipants.size(); + TLRPC.ChannelParticipant[] channelParticipantsLoad = new TLRPC.ChannelParticipant[participantCount]; + int[] requestIds = new int[participantCount]; + int[] responseCounter = new int[1]; + + for (int i = 0; i < participantCount; i++) { + TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); + req.channel = MessagesController.getInputChannel(chat); + req.participant = MessagesController.getInputPeer(actionParticipants.get(i)); + final int index = i; + requestIds[i] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + responseCounter[0]++; + requestIds[index] = 0; + + if (response != null) { + TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; + channelParticipantsLoad[index] = participant.participant; + } - } - progressDialog[0] = null; - int loadType = 2; - if (response != null) { - TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; - if (!(participant.participant instanceof TLRPC.TL_channelParticipantAdmin || participant.participant instanceof TLRPC.TL_channelParticipantCreator)) { - loadType = 0; + if (responseCounter[0] == participantCount) { + try { + progressDialog[0].dismiss(); + } catch (Throwable ignore) { + } + progressDialog[0] = null; + + createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, topicId, mode, channelParticipantsLoad, onDelete, hideDim, resourcesProvider); } - } else if (error != null && "USER_NOT_PARTICIPANT".equals(error.text)) { - loadType = 0; - } - createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, topicId, mode, loadType, onDelete, hideDim, resourcesProvider); - })); + })); + } + AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } - progressDialog[0].setOnCancelListener(dialog -> ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true)); + progressDialog[0].setOnCancelListener(dialog -> { + for (int requestId : requestIds) { + if (requestId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true); + } + } + if (hideDim != null) { + hideDim.run(); + } + }); fragment.showDialog(progressDialog[0]); }, 1000); return; } - FrameLayout frameLayout = new FrameLayout(activity); - int num = 0; - String name = actionUser != null ? ContactsController.formatName(actionUser.first_name, actionUser.last_name) : actionChat.title; - for (int a = 0; a < 4; a++) { - if ((loadParticipant == 2 || !canBan) && a == 0) { - continue; - } - CheckBoxCell cell = new CheckBoxCell(activity, 1, resourcesProvider); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell.setTag(a); - if (a == 0) { - cell.setText(LocaleController.getString("DeleteBanUser", R.string.DeleteBanUser), "", checks[a], false); - } else if (a == 1) { - cell.setText(LocaleController.getString("DeleteReportSpam", R.string.DeleteReportSpam), "", checks[a], false); - } else if (a == 2) { - cell.setText(LocaleController.formatString("DeleteAllFrom", R.string.DeleteAllFrom, name), "", checks[a], false); - } else if (a == 3) { - cell.setText(LocaleController.getString("DoActionsInCommonGroups", R.string.DoActionsInCommonGroups), "", checks[a], false); - } - cell.setPadding(LocaleController.isRTL ? dp(16) : dp(8), 0, LocaleController.isRTL ? dp(8) : dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 48 * num, 0, 0)); - cell.setOnClickListener(v -> { - if (!v.isEnabled()) { - return; - } - CheckBoxCell cell13 = (CheckBoxCell) v; - Integer num1 = (Integer) cell13.getTag(); - checks[num1] = !checks[num1]; - cell13.setChecked(checks[num1], true); + DeleteMessagesBottomSheet deleteMessagesBottomSheet = new DeleteMessagesBottomSheet(fragment, chat, messages, actionParticipants, channelParticipants, mergeDialogId, topicId, mode, onDelete); + deleteMessagesBottomSheet.toggleDefaultChecks(checks); + if (hideDim != null) { + deleteMessagesBottomSheet.setOnHideListener(i -> { + hideDim.run(); }); - num++; } - builder.setView(frameLayout); + deleteMessagesBottomSheet.show(); + return; } else if (!hasNotOut && myMessagesCount > 0 && hasNonDiceMessages) { hasDeleteForAllCheck = true; FrameLayout frameLayout = new FrameLayout(activity); @@ -6233,8 +6246,6 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u }); builder.setView(frameLayout); builder.setCustomViewOffset(9); - } else { - actionUser = null; } } else if (!scheduled && !isSavedMessages && !ChatObject.isChannel(chat) && encryptedChat == null) { if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && (!user.bot || user.support) || chat != null) { @@ -6296,8 +6307,6 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u builder.setCustomViewOffset(9); } } - final TLRPC.User userFinal = actionUser; - final TLRPC.Chat chatFinal = actionChat; DialogInterface.OnClickListener deleteAction = (dialogInterface, i) -> { ArrayList ids = null; @@ -6326,6 +6335,9 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u random_ids.add(selectedMessage.messageOwner.random_id); } } + if (mergeDialogId != 0 && selectedMessage.messageOwner.peer_id != null && selectedMessage.messageOwner.peer_id.chat_id == -mergeDialogId) { + thisDialogId = mergeDialogId; + } MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, thisDialogId, topicId, deleteForAll[0], mode); } else { for (int a = 1; a >= 0; a--) { @@ -6343,44 +6355,10 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u } } } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, thisDialogId, topicId, deleteForAll[0], mode); + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, (a == 1 && mergeDialogId != 0) ? mergeDialogId : thisDialogId, topicId, deleteForAll[0], mode); selectedMessages[a].clear(); } } - if (userFinal != null || chatFinal != null) { - if (checks[0]) { - MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, userFinal, chatFinal, false, false); - } - if (checks[1]) { - TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); - req.channel = MessagesController.getInputChannel(chat); - if (userFinal != null) { - req.participant = MessagesController.getInputPeer(userFinal); - } else { - req.participant = MessagesController.getInputPeer(chatFinal); - } - req.id = ids; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - - }); - } - if (checks[2]) { - MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat, userFinal, chatFinal, 0); - } - if (checks[3] && userFinal != null) { - if (userFinal.contact || userFinal.bot) { - AlertDialog confirm = new AlertDialog.Builder(activity, resourcesProvider) - .setTitle(LocaleController.getString("DoActionsInCommonGroups", R.string.DoActionsInCommonGroups)) - .setMessage(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)) - .setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface_, i_) -> doActionsInCommonGroups(checks, currentAccount, userFinal)) - .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) - .create(); - fragment.showDialog(confirm); - } else { - doActionsInCommonGroups(checks, currentAccount, userFinal); - } - } - } if (onDelete != null) { onDelete.run(); } @@ -6936,11 +6914,7 @@ private static String generateThemeName(Theme.ThemeAccent accent) { public static ActionBarPopupWindow showPopupMenu(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, View anchorView, int offsetX, int offsetY) { Rect rect = new Rect(); ActionBarPopupWindow popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); - if (Build.VERSION.SDK_INT >= 19) { - popupWindow.setAnimationStyle(0); - } else { - popupWindow.setAnimationStyle(R.style.PopupAnimation); - } + popupWindow.setAnimationStyle(R.style.PopupAnimation); popupWindow.setAnimationEnabled(true); @@ -6963,7 +6937,8 @@ public static ActionBarPopupWindow showPopupMenu(ActionBarPopupWindow.ActionBarP popupWindow.showAsDropDown(anchorView, offsetX, offsetY); popupLayout.updateRadialSelectors(); - popupWindow.startAnimation(); +// popupWindow.startAnimation(); + ActionBarPopupWindow.startAnimation(popupLayout); popupLayout.setOnTouchListener((v, event) -> { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { @@ -6982,31 +6957,4 @@ public static ActionBarPopupWindow showPopupMenu(ActionBarPopupWindow.ActionBarP public interface SoundFrequencyDelegate { void didSelectValues(int time, int minute); } - - public static void doActionsInCommonGroups(boolean[] checks, int currentAccount, TLRPC.User userFinal) { - TLRPC.TL_messages_getCommonChats req = new TLRPC.TL_messages_getCommonChats(); - req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userFinal); - if (req.user_id instanceof TLRPC.TL_inputUserEmpty) { - return; - } - req.limit = 100; - req.max_id = 0; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (error != null) { - return; - } - TLRPC.messages_Chats res = (TLRPC.messages_Chats) response; - for (int j=0; j < res.chats.size(); j++) { - TLRPC.Chat chat_ = res.chats.get(j); - boolean canBan = ChatObject.canBlockUsers(chat_); - boolean canDelete = ChatObject.canUserDoAdminAction(chat_, ChatObject.ACTION_DELETE_MESSAGES); - if (canBan && checks[0]) { - MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat_.id, userFinal, null, false, false); - } - if (canDelete && checks[2]) { - MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat_, userFinal, null, 0); - } - } - }); - } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index 8aff260ada..0f0f081874 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -573,7 +573,8 @@ private void initDocument(boolean force) { if ("video/webm".equals(document.mime_type)) { mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER; - thumbDrawable = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, true); + thumbDrawable = svgThumb; } else if ("application/x-tgsticker".equals(document.mime_type)) { String probableCacheKey = (cacheType != 0 ? cacheType + "_" : "") + documentId + "@" + filter; if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW || (cacheType == CACHE_TYPE_KEYBOARD || !ImageLoader.getInstance().hasLottieMemCache(probableCacheKey))) { @@ -586,7 +587,7 @@ private void initDocument(boolean force) { mediaLocation = ImageLocation.getForDocument(document); mediaFilter = filter; } else { - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f, true); if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) { svgThumb.overrideWidthAndHeight(512, 512); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java index b8f95cc97e..a7c9dacbda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiSpan.java @@ -28,6 +28,7 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LiteMode; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -1058,13 +1059,14 @@ protected void onDetachedFromWindow() { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : 0; - if (offset != 0) { + float offsetY = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : 0; + float offsetX = LocaleController.isRTL ? getPaddingRight() : getPaddingLeft(); + if (offsetY != 0 || offsetX != 0) { canvas.save(); - canvas.translate(0, offset); + canvas.translate(offsetX, offsetY); } AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), stack, 0, null, 0, 0, 0, 1f); - if (offset != 0) { + if (offsetY != 0 || offsetX != 0) { canvas.restore(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index 15a350f4a0..7c88af13ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -145,6 +145,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable, private volatile boolean isRunning; private volatile boolean isRecycled; public volatile long nativePtr; + private boolean ptrFail; private DispatchQueue decodeQueue; private float startTime; private float endTime; @@ -356,18 +357,20 @@ public void checkRepeat() { } private int decoderTryCount = 0; + private final int MAX_TRIES = 15; private Runnable loadFrameRunnable = new Runnable() { @Override public void run() { if (!isRecycled) { if (!decoderCreated && nativePtr == 0) { nativePtr = createDecoder(path.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, false); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; } updateScaleFactor(); - decoderCreated = !isWebmSticker || nativePtr != 0 || (decoderTryCount++) > 15; + decoderCreated = !isWebmSticker || nativePtr != 0 || (decoderTryCount++) > MAX_TRIES; } try { if (bitmapsCache != null) { @@ -502,6 +505,7 @@ public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, i } if (createDecoder && !this.precache) { nativePtr = createDecoder(file.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, preview); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; @@ -511,6 +515,7 @@ public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, i } if (this.precache) { nativePtr = createDecoder(file.getAbsolutePath(), metaData, currentAccount, streamFileSize, stream, preview); + ptrFail = nativePtr == 0 && (!isWebmSticker || decoderTryCount > MAX_TRIES); if (nativePtr != 0 && (metaData[0] > 3840 || metaData[1] > 3840)) { destroyDecoder(nativePtr); nativePtr = 0; @@ -1088,7 +1093,11 @@ public long getStartTime() { } public boolean isRecycled() { - return isRecycled || decoderTryCount >= 15; + return isRecycled || decoderTryCount >= MAX_TRIES; + } + + public boolean decoderFailed() { + return decoderCreated && ptrFail; } public Bitmap getNextFrame(boolean loop) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index fd05568263..0fed232e62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -118,9 +118,9 @@ public void setEmojiCacheType(int cacheType) { private boolean toSetTextMoveDown; private long animateDelay = 0; - private long animateDuration = 450; + private long animateDuration = 320; private TimeInterpolator animateInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; - private float moveAmplitude = 1f; + private float moveAmplitude = .3f; private float scaleAmplitude = 0; @@ -152,6 +152,8 @@ public void setOverrideFullWidth(int value) { private Matrix ellipsizeGradientMatrix; private Paint ellipsizePaint; + private boolean includeFontPadding = true; + public AnimatedTextDrawable() { this(false, false, false); } @@ -319,6 +321,10 @@ public void setRightPadding(float rightPadding) { invalidateSelf(); } + public float getRightPadding() { + return this.rightPadding; + } + public void cancelAnimation() { if (animator != null) { animator.cancel(); @@ -551,6 +557,7 @@ private StaticLayout makeLayout(CharSequence textPart, int width) { .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setEllipsize(TextUtils.TruncateAt.END) .setEllipsizedWidth(width) + .setIncludePad(includeFontPadding) .build(); } else { return new StaticLayout( @@ -561,7 +568,7 @@ private StaticLayout makeLayout(CharSequence textPart, int width) { Layout.Alignment.ALIGN_NORMAL, 1, 0, - false, + includeFontPadding, TextUtils.TruncateAt.END, width ); @@ -1072,6 +1079,10 @@ public float isNotEmpty() { public void setOnWidthUpdatedListener(Runnable listener) { widthUpdatedListener = listener; } + + public void setIncludeFontPadding(boolean includeFontPadding) { + this.includeFontPadding = includeFontPadding; + } } private final AnimatedTextDrawable drawable; @@ -1112,8 +1123,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (lastMaxWidth != width && getLayoutParams().width != 0) { drawable.setBounds(getPaddingLeft(), getPaddingTop(), width - getPaddingRight(), height - getPaddingBottom()); - lastMaxWidth = width; - setText(drawable.getText(), false); + drawable.setText(drawable.getText(), false, true); } lastMaxWidth = width; if (adaptWidth && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { @@ -1264,8 +1274,16 @@ public void setRightPadding(float rightPadding) { drawable.setRightPadding(rightPadding); } + public float getRightPadding() { + return drawable.getRightPadding(); + } + private Runnable widthUpdatedListener; public void setOnWidthUpdatedListener(Runnable listener) { drawable.setOnWidthUpdatedListener(listener); } + + public void setIncludeFontPadding(boolean includeFontPadding) { + this.drawable.setIncludeFontPadding(includeFontPadding); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java index 354cfd9e8a..53989d2f25 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java @@ -30,6 +30,7 @@ import org.telegram.ui.ActionBar.INavigationLayout; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.DialogsActivity; import org.telegram.ui.ProfileActivity; import org.telegram.ui.TopicsFragment; @@ -47,6 +48,7 @@ public static class PulledDialog { int stackIndex; TLRPC.Chat chat; TLRPC.User user; + TLRPC.TL_forumTopic topic; long dialogId; int folderId; int filterId; @@ -64,7 +66,6 @@ public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButt } ArrayList dialogs; if (topicId != 0) { - new ArrayList<>(); dialogs = getStackedHistoryForTopic(thisFragment, currentDialogId, topicId); } else { dialogs = getStackedHistoryDialogs(thisFragment, currentDialogId); @@ -86,6 +87,7 @@ public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButt final PulledDialog pDialog = dialogs.get(i); final TLRPC.Chat chat = pDialog.chat; final TLRPC.User user = pDialog.user; + final TLRPC.TL_forumTopic topic = pDialog.topic; FrameLayout cell = new FrameLayout(context); cell.setMinimumWidth(AndroidUtilities.dp(200)); @@ -108,7 +110,19 @@ public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButt avatarDrawable.setScaleSize(.8f); Drawable thumb = avatarDrawable; boolean addDivider = false; - if (chat != null) { + if (topic != null) { + if (topic.id == 1) { + thumb = ForumUtilities.createGeneralTopicDrawable(fragmentView.getContext(), 1f, Theme.getColor(Theme.key_chat_inMenu, resourcesProvider), false); + imageView.setImageDrawable(thumb); + } else if (topic.icon_emoji_id != 0) { + AnimatedEmojiDrawable animatedEmojiDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_FORUM_TOPIC, thisFragment.getCurrentAccount(), topic.icon_emoji_id); + imageView.setAnimatedEmojiDrawable(animatedEmojiDrawable); + } else { + thumb = ForumUtilities.createTopicDrawable(topic, false); + imageView.setImageDrawable(thumb); + } + titleView.setText(topic.title); + } else if (chat != null) { avatarDrawable.setInfo(thisFragment.getCurrentAccount(), chat); if (chat.photo != null && chat.photo.strippedBitmap != null) { thumb = chat.photo.strippedBitmap; @@ -154,17 +168,21 @@ public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButt } if (pDialog.stackIndex >= 0) { Long nextFragmentDialogId = null; + Long nextFragmentTopicId = null; if (parentLayout == null || parentLayout.getFragmentStack() == null || pDialog.stackIndex >= parentLayout.getFragmentStack().size()) { nextFragmentDialogId = null; + nextFragmentTopicId = null; } else { BaseFragment nextFragment = parentLayout.getFragmentStack().get(pDialog.stackIndex); if (nextFragment instanceof ChatActivity) { nextFragmentDialogId = ((ChatActivity) nextFragment).getDialogId(); + nextFragmentTopicId = ((ChatActivity) nextFragment).getTopicId(); } else if (nextFragment instanceof ProfileActivity) { nextFragmentDialogId = ((ProfileActivity) nextFragment).getDialogId(); + nextFragmentTopicId = ((ProfileActivity) nextFragment).getTopicId(); } } - if (nextFragmentDialogId != null && nextFragmentDialogId != pDialog.dialogId) { + if (nextFragmentDialogId != null && nextFragmentDialogId != pDialog.dialogId || topic != null && nextFragmentTopicId != null && topic.id != nextFragmentTopicId) { for (int j = parentLayout.getFragmentStack().size() - 2; j > pDialog.stackIndex; --j) { parentLayout.removeFragmentFromStack(j); } @@ -225,7 +243,14 @@ public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButt private static ArrayList getStackedHistoryForTopic(BaseFragment thisFragment, long currentDialogId, long topicId) { ArrayList dialogs = new ArrayList<>(); - if (thisFragment.getParentLayout().getFragmentStack().size() > 1 && thisFragment.getParentLayout().getFragmentStack().get(thisFragment.getParentLayout().getFragmentStack().size() - 2) instanceof TopicsFragment) { + if (thisFragment == null) { + return dialogs; + } + final INavigationLayout parentLayout = thisFragment.getParentLayout(); + if (parentLayout == null) { + return dialogs; + } + if (parentLayout.getFragmentStack().size() > 1 && parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2) instanceof TopicsFragment) { PulledDialog pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); pulledDialog.stackIndex = 0; @@ -233,18 +258,28 @@ private static ArrayList getStackedHistoryForTopic(BaseFragment th pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); - pulledDialog.stackIndex = thisFragment.getParentLayout().getFragmentStack().size() - 2; + pulledDialog.stackIndex = parentLayout.getFragmentStack().size() - 2; pulledDialog.activity = TopicsFragment.class; pulledDialog.chat = MessagesController.getInstance(thisFragment.getCurrentAccount()).getChat(-currentDialogId); - return dialogs; } else { PulledDialog pulledDialog = new PulledDialog(); dialogs.add(pulledDialog); pulledDialog.stackIndex = -1; pulledDialog.activity = TopicsFragment.class; pulledDialog.chat = MessagesController.getInstance(thisFragment.getCurrentAccount()).getChat(-currentDialogId); - return dialogs; } + List pulledDialogs = parentLayout.getPulledDialogs(); + if (pulledDialogs != null) { + for (int i = 0; i < pulledDialogs.size(); i++) { + PulledDialog pulledDialog = pulledDialogs.get(i); + if (pulledDialog.topic == null || pulledDialog.topic.id == topicId) { + continue; + } + dialogs.add(pulledDialog); + } + } + Collections.sort(dialogs, (d1, d2) -> d2.stackIndex - d1.stackIndex); + return dialogs; } public static void goToPulledDialog(BaseFragment fragment, PulledDialog dialog) { @@ -260,7 +295,12 @@ public static void goToPulledDialog(BaseFragment fragment, PulledDialog dialog) } bundle.putInt("dialog_folder_id", dialog.folderId); bundle.putInt("dialog_filter_id", dialog.filterId); - fragment.presentFragment(new ChatActivity(bundle), true); + if (dialog.topic != null) { + ChatActivity chatActivity = ForumUtilities.getChatActivityForTopic(fragment, dialog.chat.id, dialog.topic, 0, bundle); + fragment.presentFragment(chatActivity, true); + } else { + fragment.presentFragment(new ChatActivity(bundle), true); + } } else if (dialog.activity == ProfileActivity.class) { Bundle bundle = new Bundle(); bundle.putLong("dialog_id", dialog.dialogId); @@ -364,7 +404,7 @@ public static ArrayList getStackedHistoryDialogs(BaseFragment this return dialogs; } - public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, TLRPC.Chat chat, TLRPC.User user, long dialogId, int folderId, int filterId) { + public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, TLRPC.Chat chat, TLRPC.User user, TLRPC.TL_forumTopic topic, long dialogId, int folderId, int filterId) { if (chat == null && user == null) { return; } @@ -380,7 +420,7 @@ public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, } boolean alreadyAdded = false; for (PulledDialog d : parentLayout.getPulledDialogs()) { - if (d.dialogId == dialogId) { + if (topic == null && d.dialogId == dialogId || topic != null && d.topic.id == topic.id) { alreadyAdded = true; break; } @@ -395,6 +435,7 @@ public static void addToPulledDialogs(BaseFragment thisFragment, int stackIndex, d.folderId = folderId; d.chat = chat; d.user = user; + d.topic = topic; parentLayout.getPulledDialogs().add(d); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java index cf4d4f5848..302599f452 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlurredRecyclerView.java @@ -11,6 +11,7 @@ public class BlurredRecyclerView extends RecyclerListView { public int blurTopPadding; public int topPadding; + public int bottomPadding; boolean globalIgnoreLayout; public int additionalClipBottom; @@ -75,6 +76,7 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { @Override public void setPadding(int left, int top, int right, int bottom) { topPadding = top; - super.setPadding(left, topPadding + blurTopPadding, right, bottom); + bottomPadding = bottom; + super.setPadding(left, topPadding + blurTopPadding, right, bottomPadding); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java index 67efd2813b..d5d0f8cd1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -1,7 +1,11 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.view.MotionEvent; import android.view.View; @@ -9,6 +13,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.LinearLayoutManager; @@ -20,17 +25,25 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; public abstract class BottomSheetWithRecyclerListView extends BottomSheet { + public enum ActionBarType { + FADING, + SLIDING + } + private final Drawable headerShadowDrawable; + protected LinearLayoutManager layoutManager; protected RecyclerListView recyclerListView; protected ActionBar actionBar; boolean wasDrawn; protected int contentHeight; private BaseFragment baseFragment; public final boolean hasFixedSize; + public final boolean stackFromEnd; protected boolean clipToActionBar; public NestedSizeNotifierLayout nestedSizeNotifierLayout; @@ -38,6 +51,23 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { boolean showShadow = true; private float shadowAlpha = 1f; + private boolean showHandle = false; + private RectF handleRect = new RectF(); + + private ActionBarType actionBarType = ActionBarType.FADING; + protected int headerTotalHeight = 0; + protected int headerHeight = 0; + protected int headerPaddingTop = 0; + protected int headerPaddingBottom = 0; + protected boolean actionBarIgnoreTouchEvents = false; + protected AnimatedFloat actionBarSlideProgress; + + /* + Take padding-view translationY into account when positioning background. + If set to true requires that changes to its translation invalidate containerView. + */ + protected boolean takeTranslationIntoAccount = false; + public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, boolean hasFixedSize) { this(fragment, needFocus, hasFixedSize, false, fragment == null ? null : fragment.getResourceProvider()); } @@ -46,10 +76,25 @@ public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, this(fragment.getParentActivity(), fragment, needFocus, hasFixedSize, useNested, resourcesProvider); } + public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, boolean hasFixedSize, ActionBarType actionBarType) { + this(fragment.getParentActivity(), fragment, needFocus, hasFixedSize, false, actionBarType, fragment.getResourceProvider()); + } + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, Theme.ResourcesProvider resourcesProvider) { + this(context, fragment, needFocus, hasFixedSize, useNested, ActionBarType.FADING, resourcesProvider); + } + + @SuppressLint("AppCompatCustomView") + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, ActionBarType actionBarType, Theme.ResourcesProvider resourcesProvider) { + this(context, fragment, needFocus, hasFixedSize, useNested, false, actionBarType, resourcesProvider); + } + + @SuppressLint("AppCompatCustomView") + public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, boolean needFocus, boolean hasFixedSize, boolean useNested, boolean stackFromEnd, ActionBarType actionBarType, Theme.ResourcesProvider resourcesProvider) { super(context, needFocus, resourcesProvider); this.baseFragment = fragment; this.hasFixedSize = hasFixedSize; + this.stackFromEnd = stackFromEnd; headerShadowDrawable = ContextCompat.getDrawable(context, R.drawable.header_shadow).mutate(); FrameLayout containerView; if (useNested) { @@ -59,6 +104,9 @@ public BottomSheetWithRecyclerListView(Context context, BaseFragment fragment, b protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { contentHeight = MeasureSpec.getSize(heightMeasureSpec); onPreMeasure(widthMeasureSpec, heightMeasureSpec); + if (stackFromEnd) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY); + } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -96,6 +144,9 @@ public boolean dispatchTouchEvent(MotionEvent event) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { contentHeight = MeasureSpec.getSize(heightMeasureSpec); onPreMeasure(widthMeasureSpec, heightMeasureSpec); + if (stackFromEnd) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY); + } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -127,8 +178,18 @@ public boolean dispatchTouchEvent(MotionEvent event) { } }; } - recyclerListView = new RecyclerListView(context, resourcesProvider); - recyclerListView.setLayoutManager(new LinearLayoutManager(context)); + recyclerListView = new RecyclerListView(context, resourcesProvider) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + applyScrolledPosition(); + super.onLayout(changed, l, t, r, b); + } + }; + layoutManager = new LinearLayoutManager(context); + if (stackFromEnd) { + layoutManager.setStackFromEnd(true); + } + recyclerListView.setLayoutManager(layoutManager); if (nestedSizeNotifierLayout != null) { nestedSizeNotifierLayout.setBottomSheetContainerView(getContainer()); nestedSizeNotifierLayout.setTargetListView(recyclerListView); @@ -156,6 +217,14 @@ public void setTag(Object tag) { super.setTag(tag); updateStatusBar(); } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (actionBarIgnoreTouchEvents) { + return false; + } + return super.dispatchTouchEvent(ev); + } }; actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -185,13 +254,30 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { } }); } + if (actionBarType == ActionBarType.SLIDING) { + setSlidingActionBar(); + } onViewCreated(containerView); updateStatusBar(); } + public void setSlidingActionBar() { + if (hasFixedSize) { + return; + } + actionBarType = ActionBarType.SLIDING; + headerHeight = ActionBar.getCurrentActionBarHeight(); + headerTotalHeight = headerHeight + AndroidUtilities.statusBarHeight; + headerPaddingTop = dp(16); + headerPaddingBottom = dp(-20); + actionBarSlideProgress = new AnimatedFloat(containerView, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + actionBar.backButtonImageView.setPivotX(0.0f); + recyclerListView.setClipToPadding(true); + } + protected void resetAdapter(Context context) { RecyclerListView.SelectionAdapter adapter = createAdapter(recyclerListView); - recyclerListView.setAdapter(new RecyclerListView.SelectionAdapter() { + RecyclerListView.SelectionAdapter wrapperAdapter = new RecyclerListView.SelectionAdapter() { @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { @@ -207,12 +293,22 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int h; if (contentHeight == 0) { - h = AndroidUtilities.dp(300); + h = dp(300); } else { h = (int) (contentHeight * topPadding); } + h -= headerTotalHeight - headerHeight - headerPaddingTop - headerPaddingBottom; + if (h < 1) { + h = 1; + } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + containerView.invalidate(); + } }; return new RecyclerListView.Holder(view); } @@ -238,27 +334,71 @@ public int getItemViewType(int position) { public int getItemCount() { return 1 + adapter.getItemCount(); } - }); + + @Override + public void registerAdapterDataObserver(@NonNull RecyclerView.AdapterDataObserver observer) { + adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + observer.onChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + observer.onItemRangeChanged(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { + observer.onItemRangeChanged(positionStart + 1, itemCount, payload); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + observer.onItemRangeInserted(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + observer.onItemRangeRemoved(positionStart + 1, itemCount); + } + + @Override + public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { + observer.onItemRangeMoved(fromPosition + 1, toPosition + 1, itemCount); + } + }); + } + }; + recyclerListView.setAdapter(wrapperAdapter); } private void postDrawInternal(Canvas canvas, View parentView) { - if (showShadow && shadowAlpha != 1f) { - shadowAlpha += 16 / 150f; - parentView.invalidate(); - } else if (!showShadow && shadowAlpha != 0) { - shadowAlpha -= 16 / 150f; - parentView.invalidate(); - } - shadowAlpha = Utilities.clamp(shadowAlpha, 1f, 0f); - if (actionBar != null && actionBar.getVisibility() == View.VISIBLE && actionBar.getAlpha() != 0 && shadowAlpha != 0) { - headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + headerShadowDrawable.getIntrinsicHeight()); - headerShadowDrawable.setAlpha((int) (255 * actionBar.getAlpha() * shadowAlpha)); - headerShadowDrawable.draw(canvas); - if (headerShadowDrawable.getAlpha() < 255) { + if (actionBarType == ActionBarType.FADING) { + if (showShadow && shadowAlpha != 1f) { + shadowAlpha += 16 / 150f; parentView.invalidate(); + } else if (!showShadow && shadowAlpha != 0) { + shadowAlpha -= 16 / 150f; + parentView.invalidate(); + } + shadowAlpha = Utilities.clamp(shadowAlpha, 1f, 0f); + if (actionBar != null && actionBar.getVisibility() == View.VISIBLE && actionBar.getAlpha() != 0 && shadowAlpha != 0) { + headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + headerShadowDrawable.getIntrinsicHeight()); + headerShadowDrawable.setAlpha((int) (255 * actionBar.getAlpha() * shadowAlpha)); + headerShadowDrawable.draw(canvas); + if (headerShadowDrawable.getAlpha() < 255) { + parentView.invalidate(); + } + } + wasDrawn = true; + } else if (actionBarType == ActionBarType.SLIDING) { + if ((int) (255 * shadowAlpha) != 0) { + headerShadowDrawable.setBounds(backgroundPaddingLeft, actionBar.getBottom() + (int) actionBar.getTranslationY(), parentView.getMeasuredWidth() - backgroundPaddingLeft, actionBar.getBottom() + (int) actionBar.getTranslationY() + headerShadowDrawable.getIntrinsicHeight()); + headerShadowDrawable.setAlpha((int) (255 * shadowAlpha)); + headerShadowDrawable.draw(canvas); } } - wasDrawn = true; } private void preDrawInternal(Canvas canvas, View parent) { @@ -267,14 +407,49 @@ private void preDrawInternal(Canvas canvas, View parent) { int top = -AndroidUtilities.dp(16); if (holder != null) { top = holder.itemView.getBottom() - AndroidUtilities.dp(16); + if (takeTranslationIntoAccount) { + top += (int) holder.itemView.getTranslationY(); + } } - - float progressToFullView = 1f - (top + AndroidUtilities.dp(16)) / (float) AndroidUtilities.dp(56); - if (progressToFullView < 0) { - progressToFullView = 0; + top = top - headerHeight - headerPaddingTop - headerPaddingBottom; + + float handleAlpha = 1.0f; + float progressToFullView = 0.0f; + if (actionBarType == ActionBarType.FADING) { + progressToFullView = 1f - (top + AndroidUtilities.dp(16)) / (float) AndroidUtilities.dp(56); + if (progressToFullView < 0) { + progressToFullView = 0; + } + AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); + } else if (actionBarType == ActionBarType.SLIDING) { + float actionBarY = Math.max(top + dp(8) + headerPaddingTop - AndroidUtilities.statusBarHeight, 0.0f); + float t = actionBarSlideProgress.set(actionBarY == 0.0f ? 1.0f : 0.0f); + progressToFullView = t; + shadowAlpha = t; + handleAlpha = AndroidUtilities.lerp(1.0f, 0.5f, t); + actionBar.backButtonImageView.setAlpha(t); + actionBar.backButtonImageView.setScaleX(t); + actionBar.backButtonImageView.setPivotY(actionBar.backButtonImageView.getMeasuredHeight() / 2f); + actionBar.backButtonImageView.setScaleY(t); + SimpleTextView titleTextView = actionBar.getTitleTextView(); + titleTextView.setTranslationX(AndroidUtilities.lerp(dp(21) - titleTextView.getLeft(), 0.0f, t)); + actionBar.setTranslationY(actionBarY); + top -= AndroidUtilities.lerp(0, headerTotalHeight - headerHeight - headerPaddingTop - headerPaddingBottom + dp(13), t); + actionBar.getBackground().setBounds(0, AndroidUtilities.lerp(actionBar.getHeight(), 0, t), actionBar.getWidth(), actionBar.getHeight()); + + if (t > 0.5f) { + if (actionBarIgnoreTouchEvents) { + actionBarIgnoreTouchEvents = false; + actionBar.setTag(1); + } + } else { + if (!actionBarIgnoreTouchEvents) { + actionBarIgnoreTouchEvents = true; + actionBar.setTag(null); + } + } } - AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); if (needPaddingShadow()) { shadowDrawable.setBounds(0, top, parent.getMeasuredWidth(), parent.getMeasuredHeight()); } else { @@ -282,6 +457,16 @@ private void preDrawInternal(Canvas canvas, View parent) { } shadowDrawable.draw(canvas); + if (showHandle && handleAlpha > 0) { + int w = dp(36); + int y = top + AndroidUtilities.dp(20); + handleRect.set((parent.getMeasuredWidth() - w) / 2.0f, y, (parent.getMeasuredWidth() + w) / 2.0f, y + dp(4)); + int color = getThemedColor(Theme.key_sheet_scrollUp); + Theme.dialogs_onlineCirclePaint.setColor(color); + Theme.dialogs_onlineCirclePaint.setAlpha((int) (Theme.dialogs_onlineCirclePaint.getAlpha() * handleAlpha)); + canvas.drawRoundRect(handleRect, dp(2), dp(2), Theme.dialogs_onlineCirclePaint); + } + onPreDraw(canvas, top, progressToFullView); } } @@ -342,4 +527,49 @@ public void setShowShadow(boolean show) { nestedSizeNotifierLayout.invalidate(); } + public void setShowHandle(boolean showHandle) { + this.showHandle = showHandle; + } + + + private int savedScrollPosition = -1; + private int savedScrollOffset; + public void saveScrollPosition() { + if (recyclerListView != null && layoutManager != null && recyclerListView.getChildCount() > 0) { + View view = null; + int position = -1; + int top = Integer.MAX_VALUE; + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + int childPosition = recyclerListView.getChildAdapterPosition(child); + if (childPosition > 0 && child.getTop() < top) { + view = child; + position = childPosition; + top = child.getTop(); + } + } + if (view != null) { + savedScrollPosition = position; + savedScrollOffset = view.getTop() + containerView.getTop(); + smoothContainerViewLayout(); + } + } + } + + public void applyScrolledPosition() { + this.applyScrolledPosition(false); + } + + public void applyScrolledPosition(boolean ignorePaddingView) { + if (recyclerListView != null && layoutManager != null && savedScrollPosition >= 0) { + int offset = savedScrollOffset - containerView.getTop() - recyclerListView.getPaddingTop(); + RecyclerView.ViewHolder paddingViewHolder = recyclerListView.findViewHolderForAdapterPosition(0); + if (ignorePaddingView && paddingViewHolder != null) { + View view = paddingViewHolder.itemView; + offset -= Math.max(view.getBottom() - recyclerListView.getPaddingTop(), 0); + } + layoutManager.scrollToPositionWithOffset(savedScrollPosition, offset); + savedScrollPosition = -1; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index 02385ca778..4d0cfd78eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -23,14 +23,10 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.method.LinkMovementMethod; -import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.GestureDetector; @@ -627,6 +623,10 @@ default int getBottomOffset(int tag) { return 0; } + default boolean bottomOffsetAnimated() { + return true; + } + default int getLeftPadding() { return 0; } @@ -875,7 +875,7 @@ public void updatePosition() { } public float getBottomOffset() { - if (bulletin != null && bulletin.bottomOffsetSpring != null && bulletin.bottomOffsetSpring.isRunning()) { + if (bulletin != null && (delegate == null || delegate.bottomOffsetAnimated()) && bulletin.bottomOffsetSpring != null && bulletin.bottomOffsetSpring.isRunning()) { return bulletin.lastBottomOffset; } return delegate.getBottomOffset(bulletin != null ? bulletin.tag : 0); @@ -1462,7 +1462,7 @@ private void showTaggedReactionToast(ReactionsLayoutInBubble.VisibleReaction vis reactionsContainerLayout.setBubbleOffset(-AndroidUtilities.dp(80)); reactionsContainerLayout.setHint(LocaleController.getString(R.string.SavedTagReactionsHint)); addView(reactionsContainerLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 92.5f, Gravity.CENTER_HORIZONTAL, 0, 36, 0, 0)); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java index 597a5de315..2a3e8ae3ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -44,6 +44,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; @@ -77,18 +78,19 @@ public static BulletinFactory global() { if (baseFragment == null) { return BulletinFactory.of(Bulletin.BulletinWindow.make(ApplicationLoader.applicationContext), null); } + if (baseFragment.visibleDialog instanceof BottomSheet) { + return BulletinFactory.of(((BottomSheet) baseFragment.visibleDialog).container, baseFragment.getResourceProvider()); + } return BulletinFactory.of(baseFragment); } public void showForError(TLRPC.TL_error error) { - if (BuildVars.DEBUG_VERSION) { - createErrorBulletin(error.code + " " + error.text).show(); - } else { - createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); - } + if (!LaunchActivity.isActive) return; + createErrorBulletin(LocaleController.formatString(R.string.UnknownErrorCode, error.text)).show(); } public static void showError(TLRPC.TL_error error) { + if (!LaunchActivity.isActive) return; global().createErrorBulletin(LocaleController.formatString(R.string.UnknownErrorCode, error.text)).show(); } @@ -238,9 +240,9 @@ public Bulletin createSimpleBulletin(int iconRawId, CharSequence text, int maxLi } text = ssb; } - layout.textView.setText(text); layout.textView.setSingleLine(false); layout.textView.setMaxLines(maxLines); + layout.textView.setText(text); return create(layout, text.length() < 20 ? Bulletin.DURATION_SHORT : Bulletin.DURATION_LONG); } @@ -360,10 +362,27 @@ public Bulletin createUndoBulletin(CharSequence text, Runnable onUndo, Runnable } public Bulletin createUndoBulletin(CharSequence text, boolean textAndIcon, Runnable onUndo, Runnable onAction) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); - layout.textView.setText(text); - layout.textView.setSingleLine(false); - layout.textView.setMaxLines(2); + return this.createUndoBulletin(text, null, textAndIcon, onUndo, onAction); + } + + public Bulletin createUndoBulletin(CharSequence text, CharSequence subtitle, Runnable onUndo, Runnable onAction) { + return this.createUndoBulletin(text, subtitle, true, onUndo, onAction); + } + + public Bulletin createUndoBulletin(CharSequence text, CharSequence subtitle, boolean textAndIcon, Runnable onUndo, Runnable onAction) { + final Bulletin.ButtonLayout layout; + if (!TextUtils.isEmpty(subtitle)) { + final Bulletin.TwoLineLottieLayout twoLineLayout = new Bulletin.TwoLineLottieLayout(getContext(), resourcesProvider); + twoLineLayout.titleTextView.setText(text); + twoLineLayout.subtitleTextView.setText(subtitle); + layout = twoLineLayout; + } else { + final Bulletin.LottieLayout singleLineLayout = new Bulletin.LottieLayout(getContext(), resourcesProvider); + singleLineLayout.textView.setText(text); + singleLineLayout.textView.setSingleLine(false); + singleLineLayout.textView.setMaxLines(2); + layout = singleLineLayout; + } layout.setTimer(); layout.setButton(new Bulletin.UndoButton(getContext(), true, textAndIcon, resourcesProvider).setText(LocaleController.getString("Undo", R.string.Undo)).setUndoAction(onUndo).setDelayedAction(onAction)); return create(layout, Bulletin.DURATION_PROLONG); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java index 49e6efbbff..9ea2454a79 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java @@ -46,7 +46,7 @@ public class CacheChart extends View { private RectF chartBounds = new RectF(); private RectF chartInnerBounds = new RectF(); - private static final int DEFAULT_SECTIONS_COUNT = 10; + private static final int DEFAULT_SECTIONS_COUNT = 11; private static final int[] DEFAULT_COLORS = new int[] { Theme.key_statisticChartLine_lightblue, Theme.key_statisticChartLine_blue, @@ -57,6 +57,7 @@ public class CacheChart extends View { Theme.key_statisticChartLine_orange, Theme.key_statisticChartLine_cyan, Theme.key_statisticChartLine_purple, + Theme.key_statisticChartLine_golden, Theme.key_statisticChartLine_golden }; @@ -70,7 +71,8 @@ public class CacheChart extends View { R.raw.cache_stickers, R.raw.cache_profile_photos, R.raw.cache_other, - R.raw.cache_other + R.raw.cache_other, + R.raw.cache_documents }; private final int sectionsCount; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index b5411c125d..8dc05f062f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -220,7 +220,7 @@ import xyz.nextalone.nagram.helper.Dialogs; import xyz.nextalone.nagram.ui.syntaxhighlight.SyntaxHighlight; -public class ChatActivityEnterView extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { +public class ChatActivityEnterView extends BlurredFrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate, SuggestEmojiView.AnchorViewDelegate { private int commonInputType; private boolean stickersEnabled; @@ -2522,7 +2522,7 @@ public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, C NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.audioRecordTooShort); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateBotMenuButton); @@ -2650,7 +2650,7 @@ public boolean onTouchEvent(MotionEvent event) { frameLayout.setClipChildren(false); textFieldContainer.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 48, 0)); - emojiButton = new ChatActivityEnterViewAnimatedIconView(context, this) { + emojiButton = new ChatActivityEnterViewAnimatedIconView(context) { @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -3195,7 +3195,7 @@ public boolean onTouchEvent(MotionEvent motionEvent) { // }); // } - audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context, this); + audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context); audioVideoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); // audioVideoSendButton.setFocusable(true); // audioVideoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); @@ -6320,6 +6320,10 @@ public boolean isTopViewVisible() { return topView != null && topView.getVisibility() == VISIBLE; } + public float topViewVisible() { + return topViewEnterProgress; + } + public void onAdjustPanTransitionUpdate(float y, float progress, boolean keyboardVisible) { if (botWebViewMenuContainer != null) { botWebViewMenuContainer.setTranslationY(y); @@ -6421,7 +6425,7 @@ public void onDestroy() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.audioRecordTooShort); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateBotMenuButton); @@ -6589,7 +6593,7 @@ public void setDialogId(long id, int account) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.sendingMessagesChanged); currentAccount = account; accountInstance = AccountInstance.getInstance(currentAccount); @@ -6606,7 +6610,7 @@ public void setDialogId(long id, int account) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer2); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged); } @@ -7587,7 +7591,7 @@ public void doneEditingMessage(boolean withMarkdown) { editingMessageObject.editingMessage = withMarkdown ? message[0] : messageEditText.getText().toString(); editingMessageObject.editingMessageEntities = withMarkdown ? entities : new ArrayList<>(); editingMessageObject.editingMessageSearchWebPage = messageWebPageSearch; - if (parentFragment != null && parentFragment.getCurrentChat() != null && !ChatObject.canSendEmbed(parentFragment.getCurrentChat())) { + if (parentFragment != null && parentFragment.getCurrentChat() != null && (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS) && !ChatObject.canSendEmbed(parentFragment.getCurrentChat())) { editingMessageObject.editingMessageSearchWebPage = false; editingMessageObject.messageOwner.flags &=~ 512; editingMessageObject.messageOwner.media = null; @@ -11139,7 +11143,7 @@ public void onClearEmojiRecent() { } @Override - public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { + public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet, boolean edit) { if (trendingStickersAlert != null && !trendingStickersAlert.isDismissed()) { trendingStickersAlert.getLayout().showStickerSet(stickerSet, inputStickerSet); return; @@ -11156,7 +11160,11 @@ public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet.access_hash = stickerSet.access_hash; inputStickerSet.id = stickerSet.id; } - fragment.showDialog(new StickersAlert(parentActivity, fragment, inputStickerSet, null, ChatActivityEnterView.this, resourcesProvider)); + StickersAlert alert = new StickersAlert(parentActivity, fragment, inputStickerSet, null, ChatActivityEnterView.this, resourcesProvider); + fragment.showDialog(alert); + if (edit) { + alert.enableEditMode(); + } } @Override @@ -12247,7 +12255,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (emojiButton != null) { emojiButton.invalidate(); } - } else if (id == NotificationCenter.messageReceivedByServer) { + } else if (id == NotificationCenter.messageReceivedByServer2) { Boolean scheduled = (Boolean) args[6]; if (scheduled) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterViewAnimatedIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterViewAnimatedIconView.java index b705728401..771ad70032 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterViewAnimatedIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterViewAnimatedIconView.java @@ -24,11 +24,11 @@ public class ChatActivityEnterViewAnimatedIconView extends FrameLayout { private AnimatorSet buttonsAnimation; private final ImageView[] buttonViews = new ImageView[2]; - public ChatActivityEnterViewAnimatedIconView(Context context, ChatActivityEnterView parentActivity) { + public ChatActivityEnterViewAnimatedIconView(Context context) { super(context); for (int a = 0; a < 2; a++) { buttonViews[a] = new ImageView(context); - buttonViews[a].setColorFilter(new PorterDuffColorFilter(parentActivity.getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + buttonViews[a].setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); buttonViews[a].setScaleType(ImageView.ScaleType.CENTER_INSIDE); addView(buttonViews[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java index 3f2634c2c8..c6706f944b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -21,6 +21,8 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Outline; @@ -93,6 +95,8 @@ import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -116,13 +120,17 @@ import org.telegram.ui.PassportActivity; import org.telegram.ui.PhotoPickerActivity; import org.telegram.ui.PhotoPickerSearchActivity; +import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; +import org.telegram.ui.Stories.recorder.StoryEntry; import org.telegram.ui.WebAppDisclaimerAlert; import org.telegram.ui.bots.BotWebViewContainer; import org.telegram.ui.bots.BotWebViewMenuContainer; import org.telegram.ui.bots.ChatAttachAlertBotWebViewLayout; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -148,6 +156,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public boolean forUser; public boolean isPhotoPicker; public boolean isStickerMode; + public Utilities.Callback2 customStickerHandler; private int currentLimit; private int codepointCount; @@ -813,6 +822,7 @@ public void onPanTransitionEnd() { protected ActionBarMenuItem doneItem; protected FrameLayout headerView; protected TextView selectedTextView; + protected ActionBarMenuItem optionsItem; protected LinearLayout selectedView; protected ImageView selectedArrowImageView; protected LinearLayout mediaPreviewView; @@ -1359,7 +1369,7 @@ protected boolean heightAnimationEnabled() { if (isDismissed() || !openTransitionFinished) { return false; } - return !commentTextView.isPopupVisible(); + return currentAttachLayout != pollLayout && !commentTextView.isPopupVisible() || currentAttachLayout == pollLayout && !pollLayout.isPopupVisible(); } }; @@ -1437,12 +1447,22 @@ private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) { ignoreLayout = false; } + if (pollLayout != null && keyboardSize <= AndroidUtilities.dp(20) && !pollLayout.isWaitingForKeyboardOpen() && !pollLayout.isPopupShowing() && !pollLayout.isAnimatePopupClosing()) { + ignoreLayout = true; + pollLayout.hideEmojiView(); + ignoreLayout = false; + } + if (keyboardSize <= AndroidUtilities.dp(20)) { int paddingBottom; if (keyboardVisible) { paddingBottom = 0; } else { - paddingBottom = commentTextView.getEmojiPadding(); + if (currentAttachLayout == pollLayout && pollLayout.emojiView != null) { + paddingBottom = pollLayout.getEmojiPadding(); + } else { + paddingBottom = commentTextView.getEmojiPadding(); + } } if (!AndroidUtilities.isInMultiwindow) { heightSize -= paddingBottom; @@ -1462,7 +1482,7 @@ private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) { if (child == null || child.getVisibility() == GONE) { continue; } - if (commentTextView != null && commentTextView.isPopupView(child)) { + if (commentTextView != null && commentTextView.isPopupView(child) || pollLayout != null && child == pollLayout.emojiView) { if (inBubbleMode) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize + getPaddingTop(), MeasureSpec.EXACTLY)); } else if (AndroidUtilities.isInMultiwindow || AndroidUtilities.isTablet()) { @@ -1500,7 +1520,11 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { if (keyboardVisible) { paddingBottom += 0; } else { - paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0; + if (pollLayout != null && currentAttachLayout == pollLayout && pollLayout.emojiView != null) { + paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? pollLayout.getEmojiPadding() : 0; + } else { + paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0; + } } setBottomClip(paddingBottom); @@ -1551,7 +1575,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { childTop = lp.topMargin; } - if (commentTextView != null && commentTextView.isPopupView(child)) { + if (commentTextView != null && commentTextView.isPopupView(child) || pollLayout != null && child == pollLayout.emojiView) { if (AndroidUtilities.isTablet()) { childTop = getMeasuredHeight() - child.getMeasuredHeight(); } else { @@ -2071,6 +2095,68 @@ public void onCaptionChanged(CharSequence text) { }); } + optionsItem = new ActionBarMenuItem(context, null, 0, getThemedColor(Theme.key_dialogTextBlack), false, resourcesProvider); + optionsItem.setLongClickEnabled(false); + optionsItem.setIcon(R.drawable.ic_ab_other); + optionsItem.setContentDescription(LocaleController.getString(R.string.AccDescrMoreOptions)); + optionsItem.setVisibility(View.GONE); + optionsItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + optionsItem.addSubItem(1, R.drawable.msg_addbot, LocaleController.getString(R.string.StickerCreateEmpty)).setOnClickListener(v -> { + optionsItem.toggleSubMenu(); + PhotoViewer.getInstance().setParentActivity(baseFragment, resourcesProvider); + PhotoViewer.getInstance().setParentAlert(this); + PhotoViewer.getInstance().setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); + if (!delegate.needEnterComment()) { + AndroidUtilities.hideKeyboard(baseFragment.getFragmentView().findFocus()); + AndroidUtilities.hideKeyboard(getContainer().findFocus()); + } + File file = StoryEntry.makeCacheFile(currentAccount, "webp"); + int w = AndroidUtilities.displaySize.x, h = AndroidUtilities.displaySize.y; + if (w > 1080 || h > 1080) { + float scale = Math.min(w, h) / 1080f; + w = (int) (w * scale); + h = (int) (h * scale); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + try { + b.compress(Bitmap.CompressFormat.WEBP, 100, new FileOutputStream(file)); + } catch (Throwable e) { + FileLog.e(e); + } + b.recycle(); + + ArrayList arrayList = new ArrayList<>(); + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + arrayList.add(entry); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + @Override + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + sent = true; + if (delegate == null) { + return; + } + entry.editedInfo = videoEditedInfo; + ChatAttachAlertPhotoLayout.selectedPhotosOrder.clear(); + ChatAttachAlertPhotoLayout.selectedPhotos.clear(); + ChatAttachAlertPhotoLayout.selectedPhotosOrder.add(0); + ChatAttachAlertPhotoLayout.selectedPhotos.put(0, entry); + delegate.didPressedButton(7, true, notify, scheduleDate, forceDocument); + } + }, baseFragment instanceof ChatActivity ? (ChatActivity) baseFragment : null); + if (isStickerMode) { + PhotoViewer.getInstance().enableStickerMode(null, true, customStickerHandler); + } + }); + optionsItem.setMenuYOffset(AndroidUtilities.dp(-12)); + optionsItem.setAdditionalXOffset(AndroidUtilities.dp(12)); + optionsItem.setOnClickListener(v -> { + optionsItem.toggleSubMenu(); + }); + headerView = new FrameLayout(context) { @Override public void setAlpha(float alpha) { @@ -2108,7 +2194,7 @@ public boolean onInterceptTouchEvent(MotionEvent event) { selectedTextView = new TextView(context); selectedTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); selectedTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - selectedTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + selectedTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); selectedTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); selectedTextView.setMaxLines(1); selectedTextView.setEllipsize(TextUtils.TruncateAt.END); @@ -2153,12 +2239,15 @@ public boolean onInterceptTouchEvent(MotionEvent event) { containerView.addView(photoLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - containerView.addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 48, 0)); + containerView.addView(headerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 23, 0, 12, 0)); containerView.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); containerView.addView(selectedMenuItem, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.RIGHT)); if (searchItem != null) { containerView.addView(searchItem, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.RIGHT)); } + if (optionsItem != null) { + headerView.addView(optionsItem, LayoutHelper.createFrame(32, 32, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 0, 8)); + } containerView.addView(doneItem, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48, Gravity.TOP | Gravity.RIGHT)); actionBarShadow = new View(context); @@ -4390,7 +4479,7 @@ public void onOpenAnimationEnd() { @Override public void onOpenAnimationStart() { - + sent = false; } @Override @@ -4398,10 +4487,18 @@ public boolean canDismiss() { return true; } + private boolean allowDrawContent = true; + public boolean sent = false; @Override public void setAllowDrawContent(boolean value) { super.setAllowDrawContent(value); currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); + if (allowDrawContent != value) { + allowDrawContent = value; + if (currentAttachLayout == photoLayout && photoLayout != null && !photoLayout.cameraExpanded) { + photoLayout.pauseCamera(!allowDrawContent || sent); + } + } } public void setStories(boolean value) { @@ -4430,7 +4527,7 @@ public void setAvatarPicker(int type, boolean search) { } } - public void enableStickerMode() { + public void enableStickerMode(Utilities.Callback2 customStickerHandler) { selectedTextView.setText(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto)); typeButtonsAvailable = false; buttonsRecyclerView.setVisibility(View.GONE); @@ -4438,6 +4535,11 @@ public void enableStickerMode() { avatarPicker = 1; isPhotoPicker = true; isStickerMode = true; + this.customStickerHandler = customStickerHandler; + if (optionsItem != null) { + selectedTextView.setTranslationY(-AndroidUtilities.dp(8)); + optionsItem.setVisibility(View.VISIBLE); + } } public void enableDefaultMode() { @@ -4447,6 +4549,11 @@ public void enableDefaultMode() { avatarPicker = 0; isPhotoPicker = false; isStickerMode = false; + customStickerHandler = null; + if (optionsItem != null) { + selectedTextView.setTranslationY(0); + optionsItem.setVisibility(View.GONE); + } } public TextView getSelectedTextView() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java index ca222b5b69..e255129556 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java @@ -1249,7 +1249,7 @@ public void openShareLiveLocation() { if (DialogObject.isUserDialog(dialogId)) { user = parentAlert.baseFragment.getMessagesController().getUser(dialogId); } - AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> { + AlertsCreator.createLocationUpdateDialog(getParentActivity(), false, user, param -> { TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); location.geo = new TLRPC.TL_geoPoint(); location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java index 94fb3c53fd..61d1b1ff14 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -168,7 +168,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou private float cameraViewOffsetX; private float cameraViewOffsetY; private float cameraViewOffsetBottomY; - private boolean cameraOpened; + public boolean cameraOpened; private boolean canSaveCameraPreview; private boolean cameraAnimationInProgress; private float cameraOpenProgress; @@ -189,8 +189,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou private boolean takingPhoto; private static boolean mediaFromExternalCamera; private static ArrayList cameraPhotos = new ArrayList<>(); - private static HashMap selectedPhotos = new HashMap<>(); - private static ArrayList selectedPhotosOrder = new ArrayList<>(); + public static HashMap selectedPhotos = new HashMap<>(); + public static ArrayList selectedPhotosOrder = new ArrayList<>(); public static int lastImageId = -1; private boolean cancelTakingPhotos; private boolean checkCameraWhenShown; @@ -368,7 +368,7 @@ private void setCurrentSpoilerVisible(int i, boolean visible) { } } - private PhotoViewer.PhotoViewerProvider photoViewerProvider = new BasePhotoProvider() { + public PhotoViewer.PhotoViewerProvider photoViewerProvider = new BasePhotoProvider() { @Override public void onOpen() { pauseCameraPreview(); @@ -492,6 +492,7 @@ public boolean cancelButtonPressed() { @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + parentAlert.sent = true; MediaController.PhotoEntry photoEntry = getPhotoEntryAtPosition(index); if (photoEntry != null) { photoEntry.editedInfo = videoEditedInfo; @@ -831,7 +832,11 @@ public int getSpanSize(int position) { int type; if (parentAlert.isPhotoPicker && parentAlert.isStickerMode) { type = PhotoViewer.SELECT_TYPE_STICKER; - chatActivity = (ChatActivity) parentAlert.baseFragment; + if (parentAlert.baseFragment instanceof ChatActivity) { + chatActivity = (ChatActivity) parentAlert.baseFragment; + } else { + chatActivity = null; + } } else if (parentAlert.avatarPicker != 0) { chatActivity = null; type = PhotoViewer.SELECT_TYPE_AVATAR; @@ -894,7 +899,7 @@ public int getSpanSize(int position) { PhotoViewer.getInstance().closePhotoAfterSelect = false; } if (parentAlert.isStickerMode) { - PhotoViewer.getInstance().enableStickerMode(null); + PhotoViewer.getInstance().enableStickerMode(null, false, parentAlert.customStickerHandler); } if (captionForAllMedia()) { PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText()); @@ -1095,6 +1100,9 @@ public boolean shutterLongPressed() { if (parentAlert.avatarPicker != 2 && !(parentAlert.baseFragment instanceof ChatActivity) || takingPhoto || parentAlert.destroyed || cameraView == null) { return false; } + if (parentAlert.isStickerMode) { + return false; + } BaseFragment baseFragment = parentAlert.baseFragment; if (baseFragment == null) { baseFragment = LaunchActivity.getLastFragment(); @@ -1917,6 +1925,7 @@ public void needAddMorePhotos() { @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + parentAlert.sent = true; if (cameraPhotos.isEmpty() || parentAlert.destroyed) { return; } @@ -1983,7 +1992,7 @@ public boolean allowCaption() { }, chatActivity); PhotoViewer.getInstance().setAvatarFor(parentAlert.getAvatarFor()); if (parentAlert.isStickerMode) { - PhotoViewer.getInstance().enableStickerMode(null); + PhotoViewer.getInstance().enableStickerMode(null, false, parentAlert.customStickerHandler); PhotoViewer.getInstance().prepareSegmentImage(); } } @@ -2826,6 +2835,9 @@ public float getCameraOpenProgress() { } protected void checkCameraViewPosition() { + if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().stickerMakerView != null && PhotoViewer.getInstance().stickerMakerView.isThanosInProgress) { + return; + } if (Build.VERSION.SDK_INT >= 21) { if (cameraView != null) { cameraView.invalidateOutline(); @@ -3619,18 +3631,36 @@ private void resumeCameraPreview() { } private void onPhotoEditModeChanged(boolean isEditMode) { +// if (needCamera && !noCameraPermissions) { +// if (isEditMode) { +// if (cameraView != null) { +// isCameraFrontfaceBeforeEnteringEditMode = cameraView.isFrontface(); +// hideCamera(true); +// } +// } else { +// afterCameraInitRunnable = () -> { +// pauseCameraPreview(); +// afterCameraInitRunnable = null; +// isCameraFrontfaceBeforeEnteringEditMode = null; +// }; +// showCamera(); +// } +// } + } + + public void pauseCamera(boolean pause) { if (needCamera && !noCameraPermissions) { - if (isEditMode) { + if (pause) { if (cameraView != null) { isCameraFrontfaceBeforeEnteringEditMode = cameraView.isFrontface(); hideCamera(true); } } else { - afterCameraInitRunnable = () -> { - pauseCameraPreview(); - afterCameraInitRunnable = null; - isCameraFrontfaceBeforeEnteringEditMode = null; - }; +// afterCameraInitRunnable = () -> { +// pauseCameraPreview(); +// afterCameraInitRunnable = null; +// isCameraFrontfaceBeforeEnteringEditMode = null; +// }; showCamera(); } } @@ -3912,7 +3942,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } else { galleryAlbumEntry = MediaController.allPhotosAlbumEntry; } - if (selectedAlbumEntry == null) { + if (selectedAlbumEntry == null || parentAlert != null && parentAlert.isStickerMode) { selectedAlbumEntry = galleryAlbumEntry; } else if (shouldLoadAllMedia()) { for (int a = 0; a < MediaController.allMediaAlbums.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java index d2a62b8639..a51a0e5339 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java @@ -1,5 +1,10 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -8,8 +13,11 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; @@ -17,16 +25,24 @@ import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; +import android.widget.FrameLayout; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -38,6 +54,7 @@ import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; import java.util.ArrayList; import java.util.Arrays; @@ -50,18 +67,24 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; -public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout { +public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout implements SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private RecyclerListView listView; private SimpleItemAnimator itemAnimator; private FillLastLinearLayoutManager layoutManager; + private SuggestEmojiView suggestEmojiPanel; private HintView hintView; + public EmojiView emojiView; + private KeyboardNotifier keyboardNotifier; + private boolean waitingForKeyboardOpen; + private boolean destroyed; + private boolean isPremium; - private String[] answers = new String[10]; + private CharSequence[] answers = new CharSequence[10]; private boolean[] answersChecks = new boolean[10]; private int answersCount = 1; - private String questionString; + private CharSequence questionString; private CharSequence solutionString; private boolean anonymousPoll = true; private boolean multipleChoise; @@ -167,15 +190,31 @@ public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHol } } + private final Runnable openKeyboardRunnable = new Runnable() { + @Override + public void run() { + if (currentCell != null) { + EditTextBoldCursor editText = currentCell.getEditField(); + if (!destroyed && editText != null && waitingForKeyboardOpen && !keyboardVisible && !AndroidUtilities.usingHardwareInput && !AndroidUtilities.isInMultiwindow && AndroidUtilities.isTablet()) { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + } + }; + public ChatAttachAlertPollLayout(ChatAttachAlert alert, Context context, Theme.ResourcesProvider resourcesProvider) { super(alert, context, resourcesProvider); updateRows(); - + isPremium = AccountInstance.getInstance(parentAlert.currentAccount).getUserConfig().isPremium(); /*if (quiz != null) { quizPoll = quiz; quizOnly = quizPoll ? 1 : 2; }*/ + parentAlert.sizeNotifierFrameLayout.setDelegate(this); listAdapter = new ListAdapter(context); listView = new RecyclerListView(context) { @@ -255,6 +294,9 @@ protected int[] getChildRectangleOnScreenScrollAmount(View child, Rect rect) { TextCheckCell cell = (TextCheckCell) view; boolean checked; boolean wasChecksBefore = quizPoll; + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } if (position == anonymousRow) { checked = anonymousPoll = !anonymousPoll; } else if (position == multipleRow) { @@ -332,6 +374,28 @@ protected int[] getChildRectangleOnScreenScrollAmount(View child, Rect rect) { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { parentAlert.updateLayout(ChatAttachAlertPollLayout.this, true, dy); + if (suggestEmojiPanel != null && suggestEmojiPanel.isShown()) { + SuggestEmojiView.AnchorViewDelegate emojiDelegate = suggestEmojiPanel.getDelegate(); + if (emojiDelegate instanceof PollEditTextCell) { + PollEditTextCell cell = (PollEditTextCell) emojiDelegate; + RecyclerView.ViewHolder holder = listView.findContainingViewHolder(cell); + if (holder != null) { + int position = holder.getAdapterPosition(); + if (suggestEmojiPanel.getDirection() == SuggestEmojiView.DIRECTION_TO_BOTTOM) { + suggestEmojiPanel.setTranslationY(holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight()); + } else { + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + if (position < layoutManager.findFirstVisibleItemPosition() || position > layoutManager.findLastVisibleItemPosition()) { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } if (dy != 0 && hintView != null) { hintView.hide(); } @@ -359,6 +423,20 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { hintView.setVisibility(View.INVISIBLE); addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + if (isPremium) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + suggestEmojiPanel = new SuggestEmojiView(context, parentAlert.currentAccount, null, resourcesProvider) { + @Override + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + } + }; + suggestEmojiPanel.forbidCopy(); + suggestEmojiPanel.forbidSetAsStatus(); + suggestEmojiPanel.setHorizontalPadding(AndroidUtilities.dp(24)); + addView(suggestEmojiPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 160, Gravity.LEFT | Gravity.TOP)); + } + keyboardNotifier = new KeyboardNotifier(parentAlert.sizeNotifierFrameLayout, null); checkDoneButton(); } @@ -368,10 +446,17 @@ public int needsActionBar() { } @Override - public void onResume() { + public void onPause() { + super.onPause(); if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + if (isPremium) { + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + } } @Override @@ -394,19 +479,47 @@ public void onMenuItemClick(int id) { } return; } + + CharSequence questionText = getFixedString(questionString); + CharSequence[] questionCharSequence = new CharSequence[]{ questionText }; + ArrayList questionEntities = MediaDataController.getInstance(parentAlert.currentAccount).getEntities(questionCharSequence, true); + questionText = questionCharSequence[0]; + for (int a = 0, N = questionEntities.size(); a < N; a++) { + TLRPC.MessageEntity entity = questionEntities.get(a); + if (entity.offset + entity.length > questionText.length()) { + entity.length = questionText.length() - entity.offset; + } + } + TLRPC.TL_messageMediaPoll poll = new TLRPC.TL_messageMediaPoll(); poll.poll = new TLRPC.TL_poll(); poll.poll.multiple_choice = multipleChoise; poll.poll.quiz = quizPoll; poll.poll.public_voters = !anonymousPoll; - poll.poll.question = getFixedString(questionString).toString(); + poll.poll.question = new TLRPC.TL_textWithEntities(); + poll.poll.question.text = questionText.toString(); + poll.poll.question.entities = questionEntities; + SerializedData serializedData = new SerializedData(10); for (int a = 0; a < answers.length; a++) { if (TextUtils.isEmpty(getFixedString(answers[a]))) { continue; } - TLRPC.TL_pollAnswer answer = new TLRPC.TL_pollAnswer(); - answer.text = getFixedString(answers[a]).toString(); + CharSequence answerText = getFixedString(answers[a]); + CharSequence[] answerCharSequence = new CharSequence[]{ answerText }; + ArrayList answerEntities = MediaDataController.getInstance(parentAlert.currentAccount).getEntities(answerCharSequence, true); + answerText = answerCharSequence[0]; + for (int b = 0, N = answerEntities.size(); b < N; b++) { + TLRPC.MessageEntity entity = answerEntities.get(b); + if (entity.offset + entity.length > answerText.length()) { + entity.length = answerText.length() - entity.offset; + } + } + + TLRPC.PollAnswer answer = new TLRPC.TL_pollAnswer(); + answer.text = new TLRPC.TL_textWithEntities(); + answer.text.text = answerText.toString(); + answer.text.entities = answerEntities; answer.option = new byte[1]; answer.option[0] = (byte) (48 + poll.poll.answers.size()); poll.poll.answers.add(answer); @@ -479,7 +592,7 @@ public int getListTopPadding() { @Override public void onPreMeasure(int availableWidth, int availableHeight) { int padding; - if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) { + if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20) || emojiViewVisible || isAnimatePopupClosing) { padding = AndroidUtilities.dp(52); parentAlert.setAllowNestedScroll(false); } else { @@ -521,6 +634,20 @@ public void scrollToTop() { listView.smoothScrollToPosition(1); } + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + if (emojiView != null) { + emojiView.invalidateViews(); + } + if (currentCell != null) { + int color = currentCell.getEditField().getCurrentTextColor(); + currentCell.getEditField().setTextColor(0xffffffff); + currentCell.getEditField().setTextColor(color); + } + } + } + public static CharSequence getFixedString(CharSequence text) { if (TextUtils.isEmpty(text)) { return text; @@ -536,12 +663,14 @@ public static CharSequence getFixedString(CharSequence text) { } private void showQuizHint() { - int count = listView.getChildCount(); for (int a = answerStartRow; a < answerStartRow + answersCount; a++) { RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(a); if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell pollEditTextCell = (PollEditTextCell) holder.itemView; if (pollEditTextCell.getTop() > AndroidUtilities.dp(40)) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } hintView.showForView(pollEditTextCell.getCheckBox(), true); break; } @@ -651,6 +780,18 @@ public void onShow(ChatAttachAlert.AttachAlertLayout previousLayout) { layoutManager.scrollToPositionWithOffset(0, 0); } + @Override + public void onDestroy() { + super.onDestroy(); + destroyed = true; + if (isPremium) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + if (emojiView != null) { + parentAlert.sizeNotifierFrameLayout.removeView(emojiView); + } + } + } + @Override public void onHidden() { parentAlert.doneItem.setVisibility(INVISIBLE); @@ -658,6 +799,10 @@ public void onHidden() { @Override public boolean onBackPressed() { + if (emojiViewVisible) { + hideEmojiPopup(true); + return true; + } if (!checkDiscard()) { return true; } @@ -721,6 +866,11 @@ private void setTextLeft(View cell, int index) { } private void addNewField() { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + resetSuggestEmojiPanel(); listView.setItemAnimator(itemAnimator); answersChecks[answersCount] = false; answersCount++; @@ -734,6 +884,349 @@ private void addNewField() { listAdapter.notifyItemChanged(emptyRow); } + private void updateSuggestEmojiPanelDelegate(RecyclerView.ViewHolder holder) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + if (suggestEmojiPanel != null && holder != null && holder.itemView instanceof PollEditTextCell && suggestEmojiPanel.getDelegate() != holder.itemView) { + suggestEmojiPanel.setDelegate((PollEditTextCell) holder.itemView); + } + } + } + + private void resetSuggestEmojiPanel() { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.setDelegate(null); + suggestEmojiPanel.forceClose(); + } + } + + private int lastSizeChangeValue1; + private boolean lastSizeChangeValue2; + + @Override + public void onSizeChanged(int height, boolean isWidthGreater) { + if (!isPremium) { + return; + } + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (isWidthGreater) { + keyboardHeightLand = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); + } else { + keyboardHeight = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height", keyboardHeight).commit(); + } + } + + if (emojiViewVisible) { + int newHeight = (isWidthGreater ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emojiView.getLayoutParams(); + if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { + layoutParams.width = AndroidUtilities.displaySize.x; + layoutParams.height = newHeight; + emojiView.setLayoutParams(layoutParams); + emojiPadding = layoutParams.height; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + } + + if (lastSizeChangeValue1 == height && lastSizeChangeValue2 == isWidthGreater) { + return; + } + lastSizeChangeValue1 = height; + lastSizeChangeValue2 = isWidthGreater; + + boolean oldValue = keyboardVisible; + if (currentCell != null) { + final EditTextBoldCursor editText = currentCell.getEditField(); + keyboardVisible = editText.isFocused() && keyboardNotifier.keyboardVisible() && height > 0; + } else { + keyboardVisible = false; + } + if (keyboardVisible && emojiViewVisible) { + showEmojiPopup(0); + } + if (emojiPadding != 0 && !keyboardVisible && keyboardVisible != oldValue && !emojiViewVisible) { + emojiPadding = 0; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + + if (keyboardVisible && waitingForKeyboardOpen) { + waitingForKeyboardOpen = false; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + } + } + + public boolean isWaitingForKeyboardOpen() { + return waitingForKeyboardOpen; + } + + public boolean emojiViewVisible, emojiViewWasVisible; + private int emojiPadding; + private int keyboardHeight, keyboardHeightLand; + private boolean keyboardVisible, isAnimatePopupClosing; + private PollEditTextCell currentCell; + + private void onEmojiClicked(PollEditTextCell cell) { + this.currentCell = cell; + if (emojiViewVisible) { + openKeyboardInternal(); + } else { + showEmojiPopup(1); + } + } + + private void openKeyboardInternal() { + keyboardNotifier.awaitKeyboard(); + final EditTextBoldCursor editText = currentCell.getEditField(); + AndroidUtilities.showKeyboard(editText); + showEmojiPopup(AndroidUtilities.usingHardwareInput ? 0 : 2); + + if (!AndroidUtilities.usingHardwareInput && !keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + waitingForKeyboardOpen = true; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + + private void showEmojiPopup(int show) { + if (!isPremium) { + return; + } + if (show == 1) { + boolean emojiWasVisible = emojiView != null && emojiView.getVisibility() == View.VISIBLE; + createEmojiView(); + + emojiView.setVisibility(VISIBLE); + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = true; + View currentView = emojiView; + + if (keyboardHeight <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeight = dp(150); + } else { + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); + } + } + if (keyboardHeightLand <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeightLand = dp(150); + } else { + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); + } + } + int currentHeight = (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) currentView.getLayoutParams(); + layoutParams.height = currentHeight; + currentView.setLayoutParams(layoutParams); + if (!AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() && currentCell != null) { + AndroidUtilities.hideKeyboard(currentCell.getEditField()); + } + + emojiPadding = currentHeight; + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, true); + } + if (!emojiWasVisible && !keyboardVisible) { + ValueAnimator animator = ValueAnimator.ofFloat(emojiPadding, 0); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + emojiView.setTranslationY(0); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } + } else { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, true); + } + if (emojiView != null) { + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(GONE); + } + } + if (show == 0) { + emojiPadding = 0; + } + keyboardNotifier.fire(); + parentAlert.sizeNotifierFrameLayout.requestLayout(); + } + } + + private void hideEmojiPopup(boolean byBackButton) { + if (!isPremium) { + return; + } + if (emojiViewVisible) { + showEmojiPopup(0); + } + if (byBackButton) { + if (emojiView != null && emojiView.getVisibility() == View.VISIBLE) { + int height = emojiView.getMeasuredHeight(); + ValueAnimator animator = ValueAnimator.ofFloat(0, height); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + isAnimatePopupClosing = true; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimatePopupClosing = false; + emojiView.setTranslationY(0); + hideEmojiView(); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } else { + hideEmojiView(); + } + } + } + + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != GONE) { + if (currentCell != null) { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } + } + emojiView.setVisibility(GONE); + } + int wasEmojiPadding = emojiPadding; + emojiPadding = 0; + if (wasEmojiPadding != emojiPadding) { + keyboardNotifier.fire(); + } + } + + public boolean isAnimatePopupClosing() { + return isAnimatePopupClosing; + } + + public boolean isPopupShowing() { + return emojiViewVisible; + } + + public boolean isPopupVisible() { + return emojiView != null && emojiView.getVisibility() == View.VISIBLE; + } + + public int getEmojiPadding() { + return emojiPadding; + } + + private void createEmojiView() { + if (emojiView != null && emojiView.currentAccount != UserConfig.selectedAccount) { + parentAlert.sizeNotifierFrameLayout.removeView(emojiView); + emojiView = null; + } + if (emojiView != null) { + return; + } + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider, false); + emojiView.emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + emojiView.fixBottomTabContainerTranslation = false; + emojiView.allowEmojisForNonPremium(false); + emojiView.setVisibility(GONE); + if (AndroidUtilities.isTablet()) { + emojiView.setForseMultiwindowLayout(true); + } + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { + @Override + public boolean onBackspace() { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return false; + } + editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + return true; + } + + @Override + public void onEmojiSelected(String symbol) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, editText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + editText.setText(editText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onCustomEmojiSelected(long documentId, TLRPC.Document document, String emoticon, boolean isRecent) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + SpannableString spannable = new SpannableString(emoticon); + AnimatedEmojiSpan span; + if (document != null) { + span = new AnimatedEmojiSpan(document, editText.getPaint().getFontMetricsInt()); + } else { + span = new AnimatedEmojiSpan(documentId, editText.getPaint().getFontMetricsInt()); + } + span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; + spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editText.setText(editText.getText().insert(i, spannable)); + int j = i + spannable.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onClearEmojiRecent() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); + builder.setTitle(LocaleController.getString("ClearRecentEmojiTitle", R.string.ClearRecentEmojiTitle)); + builder.setMessage(LocaleController.getString("ClearRecentEmojiText", R.string.ClearRecentEmojiText)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.show(); + } + }); + parentAlert.sizeNotifierFrameLayout.addView(emojiView); + } + + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -855,10 +1348,17 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { @Override public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == 4) { + if (holder.getItemViewType() == 4 || holder.getItemViewType() == 5) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; EditTextBoldCursor editText = editTextCell.getTextView(); if (editText.isFocused()) { + if (isPremium) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + hideEmojiPopup(true); + } + currentCell = null; editText.clearFocus(); AndroidUtilities.hideKeyboard(editText); } @@ -892,10 +1392,36 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view = new TextCell(mContext); break; case 4: { - PollEditTextCell cell = new PollEditTextCell(mContext, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + + @Override + protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { + if (editText.isFocused() && editText.hasSelection()) { + Menu menu = actionMode.getMenu(); + if (menu.findItem(android.R.id.copy) == null) { + return; + } + ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat(), true); + } + } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); } }; cell.createErrorTextView(); @@ -915,8 +1441,22 @@ public void afterTextChanged(Editable s) { if (cell.getTag() != null) { return; } - questionString = s.toString(); RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } + questionString = s; if (holder != null) { setTextLeft(holder.itemView, questionRow); } @@ -930,10 +1470,20 @@ public void afterTextChanged(Editable s) { view = new TextCheckCell(mContext); break; case 7: { - PollEditTextCell cell = new PollEditTextCell(mContext, true, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } } @Override @@ -946,6 +1496,11 @@ protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionM ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat(), true); } } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.createErrorTextView(); cell.addTextWatcher(new TextWatcher() { @@ -964,8 +1519,22 @@ public void afterTextChanged(Editable s) { if (cell.getTag() != null) { return; } + RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } solutionString = s; - RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(solutionRow); if (holder != null) { setTextLeft(holder.itemView, solutionRow); } @@ -990,7 +1559,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { break; } default: { - PollEditTextCell cell = new PollEditTextCell(mContext, v -> { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, v -> { if (v.getTag() != null) { return; } @@ -1016,12 +1585,26 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; editTextCell.getTextView().requestFocus(); + if (isPremium) { + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } } else if (editText.isFocused()) { AndroidUtilities.hideKeyboard(editText); } + if (isPremium) { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } editText.clearFocus(); checkDoneButton(); updateRows(); + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + suggestEmojiPanel.setDelegate(null); + } listAdapter.notifyItemChanged(answerSectionRow); listAdapter.notifyItemChanged(emptyRow); } @@ -1047,6 +1630,16 @@ protected boolean shouldShowCheckBox() { @Override protected void onFieldTouchUp(EditTextBoldCursor editText) { parentAlert.makeFocusable(editText, true); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } } @Override @@ -1086,6 +1679,11 @@ protected boolean isChecked(PollEditTextCell editText) { } return false; } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.addTextWatcher(new TextWatcher() { @Override @@ -1107,7 +1705,25 @@ public void afterTextChanged(Editable s) { if (index < 0 || index >= answers.length) { return; } - answers[index] = s.toString(); + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + float y = holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight(); + if (y > 0) { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_BOTTOM); + suggestEmojiPanel.setTranslationY(y); + } else { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.fireUpdate(); + } + + answers[index] = s; setTextLeft(cell, position); checkDoneButton(); } @@ -1189,7 +1805,7 @@ public void swapElements(int fromIndex, int toIndex) { if (idx1 < 0 || idx2 < 0 || idx1 >= answersCount || idx2 >= answersCount) { return; } - String from = answers[idx1]; + CharSequence from = answers[idx1]; answers[idx1] = answers[idx2]; answers[idx2] = from; boolean temp = answersChecks[idx1]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java index ca8a6bd213..54018f2c3a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -275,6 +275,15 @@ public void setSticker(TLRPC.Document sticker) { }); } + public void setSticker(String stickerPath) { + if (stickerPath == null) { + return; + } + wasDraw = true; + nextStickerToSendView.clearImage(); + stickerToSendView.setImage(ImageLocation.getForPath(stickerPath), "256_256", null, null, 0, null); + } + public void setNextSticker(TLRPC.Document sticker, Runnable whenDone) { if (sticker == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java index 3d136d2ba5..0c9c1bf411 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java @@ -19,13 +19,13 @@ public class ColoredImageSpan extends ReplacementSpan { int drawableColor; - Drawable drawable; + public Drawable drawable; boolean usePaintColor = true; public boolean useLinkPaintColor = false; int colorKey; private int topOffset = 0; - private float translateX, translateY; + private float translateX, translateY, rotate; private float alpha = 1f; private int overrideColor; @@ -102,6 +102,10 @@ public void translate(float tx, float ty) { translateY = ty; } + public void rotate(float r) { + rotate = r; + } + public void setWidth(int width) { sizeWidth = width; } @@ -119,7 +123,7 @@ public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i fm.top = fontMetrics.top; fm.bottom = fontMetrics.bottom; } - return (int) (scaleX * Math.abs(spaceScaleX) * size); + return (int) (Math.abs(scaleX) * Math.abs(spaceScaleX) * size); } if (sizeWidth != 0) return (int) (Math.abs(scaleX) * sizeWidth); @@ -164,6 +168,9 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, if (scaleX != 1f || scaleY != 1f) { canvas.scale(scaleX, scaleY, 0, drawable.getBounds().centerY()); } + if (rotate != 1f) { + canvas.rotate(rotate, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } if (alpha != 1f || paint.getAlpha() != 0xFF) { drawable.setAlpha((int) (alpha * paint.getAlpha())); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java index f7a6cf29c3..f54d5ed23c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java @@ -11,6 +11,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; @@ -25,6 +26,7 @@ public class CombinedDrawable extends Drawable implements Drawable.Callback { private int iconHeight; private int backWidth; private int backHeight; + private boolean center; private int offsetX; private int offsetY; private boolean fullSize; @@ -77,6 +79,10 @@ public void setCustomSize(int width, int height) { backHeight = height; } + public void setCenter(boolean value) { + center = value; + } + public void setIconOffset(int x, int y) { offsetX = x; offsetY = y; @@ -135,6 +141,15 @@ public ConstantState getConstantState() { @Override public void draw(Canvas canvas) { + if (center) { + Rect bounds = getBounds(); + setBounds( + bounds.centerX() - getIntrinsicWidth() / 2, + bounds.centerY() - getIntrinsicHeight() / 2, + bounds.centerX() + getIntrinsicWidth() / 2, + bounds.centerY() + getIntrinsicHeight() / 2 + ); + } if (background != null) { background.setBounds(getBounds()); background.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java index 5923c2337b..c7368dd768 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java @@ -432,10 +432,12 @@ public void reset() { public void reset(boolean force) { areaView.resetAnimator(); - areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), state.getBaseRotation() % 180 != 0, freeform); + areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), state != null && state.getBaseRotation() % 180 != 0, freeform); areaView.setLockedAspectRatio(freeform ? 0.0f : 1.0f); - state.reset(areaView, 0, freeform); - state.mirrored = false; + if (state != null) { + state.reset(areaView, 0, freeform); + state.mirrored = false; + } areaView.getCropRect(initialAreaRect); updateMatrix(force); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java new file mode 100644 index 0000000000..ec49093fd6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DeleteMessagesBottomSheet.java @@ -0,0 +1,1004 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +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.Components.UniversalAdapter.VIEW_TYPE_EXPANDABLE_SWITCH; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_SHADOW_COLLAPSE_BUTTON; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_SWITCH; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX; +import static org.telegram.ui.Components.UniversalAdapter.VIEW_TYPE_USER_CHECKBOX; + +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BotWebViewVibrationEffect; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.stream.Collectors; + +public class DeleteMessagesBottomSheet extends BottomSheetWithRecyclerListView { + private UniversalAdapter adapter; + + private SelectorBtnCell buttonContainer; + private TextView actionButton; + + private TLRPC.Chat inChat; + private boolean isForum; + private ArrayList messages; + private long mergeDialogId; + private int topicId; + private int mode; + private Runnable onDelete; + + private boolean restrict = false; + + private static final int ACTION_REPORT = 0; + private static final int ACTION_DELETE_ALL = 1; + private static final int ACTION_BAN = 2; + private static final int ACTION_APPLY_IN_COMMON_GROUP = 100; + + private Action report; + private Action deleteAll; + private Action banOrRestrict; + private Action applyInCommonGroup; + + private boolean[] banFilter; + private boolean[] restrictFilter; + private boolean canRestrict; + + private TLRPC.TL_chatBannedRights defaultBannedRights; + private TLRPC.TL_chatBannedRights bannedRights; + private ArrayList participantsBannedRights; + private boolean sendMediaCollapsed = true; + + private static final int RIGHT_SEND_MESSAGES = 0; + private static final int RIGHT_SEND_MEDIA = 1; + private static final int RIGHT_ADD_USERS = 2; + private static final int RIGHT_PIN_MESSAGES = 3; + private static final int RIGHT_CHANGE_CHAT_INFO = 4; + private static final int RIGHT_CREATE_TOPICS = 5; + private static final int RIGHT_SEND_PHOTOS = 6; + private static final int RIGHT_SEND_VIDEOS = 7; + private static final int RIGHT_SEND_FILES = 8; + private static final int RIGHT_SEND_MUSIC = 9; + private static final int RIGHT_SEND_VOICE = 10; + private static final int RIGHT_SEND_ROUND = 11; + private static final int RIGHT_SEND_STICKERS = 12; + private static final int RIGHT_SEND_POLLS = 13; + private static final int RIGHT_SEND_LINKS = 14; + + private class Action { + int type; + String title; + + ArrayList options; + boolean[] checks; + boolean[] filter; + boolean collapsed; + int totalCount; + int filteredCount; + int selectedCount; + + Action(int type, ArrayList options) { + this.type = type; + totalCount = options.size(); + selectedCount = 0; + + if (totalCount > 0) { + this.options = options; + checks = new boolean[totalCount]; + collapsed = true; + + updateTitle(); + } + } + + int getCount() { + if (filter != null) { + return filteredCount; + } else { + return totalCount; + } + } + + boolean isPresent() { + return getCount() > 0; + } + + boolean isExpandable() { + return getCount() > 1; + } + + void setFilter(boolean[] filter) { + if (totalCount == 0) { + return; + } + this.filter = filter; + + updateCounters(); + updateTitle(); + } + + void updateCounters() { + selectedCount = 0; + filteredCount = 0; + for (int i = 0; i < totalCount; i++) { + if (filter == null) { + if (checks[i]) { + selectedCount++; + } + } else if (filter[i]) { + filteredCount++; + if (checks[i]) { + selectedCount++; + } + } + } + } + + TLObject first() { + for (int i = 0; i < totalCount; i++) { + if (filter == null || filter[i]) { + return options.get(i); + } + } + return null; + } + + void updateTitle() { + if (totalCount == 0) { + return; + } + + TLObject userOrChat = first(); + String name; + if (userOrChat instanceof TLRPC.User) { + name = UserObject.getUserName((TLRPC.User) userOrChat); + } else { + name = ContactsController.formatName(userOrChat); + } + if (type == ACTION_REPORT) { + title = getString(R.string.DeleteReportSpam); + } else if (type == ACTION_DELETE_ALL) { + title = isExpandable() ? getString(R.string.DeleteAllFromUsers) : formatString(R.string.DeleteAllFrom, name); + } else if (type == ACTION_BAN) { + if (restrict) { + title = isExpandable() ? getString(R.string.DeleteRestrictUsers) : formatString(R.string.DeleteRestrict, name); + } else { + title = isExpandable() ? getString(R.string.DeleteBanUsers) : formatString(R.string.DeleteBan, name); + } + } else if (type == ACTION_APPLY_IN_COMMON_GROUP) { + title = getString(R.string.DoActionsInCommonGroups); + } + } + + void collapseOrExpand() { + collapsed = !collapsed; + adapter.update(true); + } + + void toggleCheck(int index) { + if (filter != null && !filter[index]) { + return; + } + + this.checks[index] = !this.checks[index]; + if (this.checks[index]) { + selectedCount++; + } else { + selectedCount--; + } + adapter.update(true); + } + + void toggleAllChecks() { + boolean value = true; + for (int i = 0; i < totalCount; i++) { + if (checks[i] && (filter == null || filter[i])) { + value = false; + break; + } + } + Arrays.fill(checks, value); + updateCounters(); + adapter.update(true); + } + + void performAction(Utilities.IndexedConsumer action) { + for (int i = 0; i < totalCount; i++) { + if (checks[i] && (filter == null || filter[i])) { + action.accept(options.get(i), i); + } + } + } + + void forEach(Utilities.IndexedConsumer action) { + for (int i = 0; i < totalCount; i++) { + if (filter == null || filter[i]) { + action.accept(options.get(i), i); + } + } + } + + boolean checkOption(TLObject object) { + for (int i = 0; i < totalCount; i++) { + if (object == options.get(i)) { + return checks[i] && (filter == null || filter[i]); + } + } + return false; + } + } + + public DeleteMessagesBottomSheet(BaseFragment fragment, TLRPC.Chat inChat, ArrayList messages, ArrayList actionParticipants, TLRPC.ChannelParticipant[] channelParticipants, long mergeDialogId, int topicId, int mode, Runnable onDelete) { + super(fragment.getContext(), fragment, false, false, false, true, ActionBarType.SLIDING, fragment.getResourceProvider()); + setShowHandle(true); + fixNavigationBar(); + this.takeTranslationIntoAccount = true; + recyclerListView.setPadding(backgroundPaddingLeft, headerTotalHeight, backgroundPaddingLeft, dp(68)); + recyclerListView.setOnItemClickListener((view, position, x, y) -> { + UItem item = adapter.getItem(position - 1); + if (item == null) return; + onClick(item, view, position, x, y); + }); + this.takeTranslationIntoAccount = true; + DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + containerView.invalidate(); + } + }; + itemAnimator.setSupportsChangeAnimations(false); + itemAnimator.setDelayAnimations(false); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDurations(350); + recyclerListView.setItemAnimator(itemAnimator); + + buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, null); + buttonContainer.setClickable(true); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setPadding(dp(10), dp(10), dp(10), dp(10)); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + actionButton = new TextView(getContext()); + actionButton.setLines(1); + actionButton.setSingleLine(true); + actionButton.setGravity(Gravity.CENTER_HORIZONTAL); + actionButton.setEllipsize(TextUtils.TruncateAt.END); + actionButton.setGravity(Gravity.CENTER); + actionButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + actionButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + actionButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + actionButton.setText(getString(R.string.DeleteProceedBtn)); + actionButton.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 6)); + actionButton.setOnClickListener(e -> proceed()); + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + this.inChat = inChat; + this.isForum = ChatObject.isForum(inChat); + this.messages = messages; + this.mergeDialogId = mergeDialogId; + this.topicId = topicId; + this.mode = mode; + this.onDelete = onDelete; + + this.defaultBannedRights = inChat.default_banned_rights; + this.bannedRights = new TLRPC.TL_chatBannedRights(); + if (defaultBannedRights.view_messages) { + bannedRights.view_messages = true; + } + if (defaultBannedRights.send_messages) { + bannedRights.send_messages = true; + } + if (defaultBannedRights.send_media) { + bannedRights.send_media = true; + } + if (defaultBannedRights.send_stickers) { + bannedRights.send_stickers = true; + } + if (defaultBannedRights.send_gifs) { + bannedRights.send_gifs = true; + } + if (defaultBannedRights.send_games) { + bannedRights.send_games = true; + } + if (defaultBannedRights.send_inline) { + bannedRights.send_inline = true; + } + if (defaultBannedRights.embed_links) { + bannedRights.embed_links = true; + } + if (defaultBannedRights.send_polls) { + bannedRights.send_polls = true; + } + if (defaultBannedRights.invite_users) { + bannedRights.invite_users = true; + } + if (defaultBannedRights.change_info) { + bannedRights.change_info = true; + } + if (defaultBannedRights.pin_messages) { + bannedRights.pin_messages = true; + } + if (defaultBannedRights.manage_topics) { + bannedRights.manage_topics = true; + } + if (defaultBannedRights.send_photos) { + bannedRights.send_photos = true; + } + if (defaultBannedRights.send_videos) { + bannedRights.send_videos = true; + } + if (defaultBannedRights.send_audios) { + bannedRights.send_audios = true; + } + if (defaultBannedRights.send_docs) { + bannedRights.send_docs = true; + } + if (defaultBannedRights.send_voices) { + bannedRights.send_voices = true; + } + if (defaultBannedRights.send_roundvideos) { + bannedRights.send_roundvideos = true; + } + if (defaultBannedRights.send_plain) { + bannedRights.send_plain = true; + } + + report = new Action(ACTION_REPORT, actionParticipants); + deleteAll = new Action(ACTION_DELETE_ALL, actionParticipants); + applyInCommonGroup = new Action(ACTION_APPLY_IN_COMMON_GROUP, actionParticipants); + + if (ChatObject.canBlockUsers(inChat)) { + banFilter = new boolean[actionParticipants.size()]; + for (int i = 0; i < actionParticipants.size(); i++) { + TLRPC.ChannelParticipant channelParticipant = i < channelParticipants.length ? channelParticipants[i] : null; + if (!inChat.creator && (channelParticipant instanceof TLRPC.TL_channelParticipantAdmin || channelParticipant instanceof TLRPC.TL_channelParticipantCreator)) { + continue; + } + if (channelParticipant instanceof TLRPC.TL_channelParticipantBanned && channelParticipant.banned_rights != null && isBanned(channelParticipant.banned_rights)) { + continue; + } + + banFilter[i] = true; + } + + restrictFilter = new boolean[actionParticipants.size()]; + if (hasAnyDefaultRights()) { + for (int i = 0; i < actionParticipants.size(); i++) { + TLRPC.ChannelParticipant channelParticipant = i < channelParticipants.length ? channelParticipants[i] : null; + if (actionParticipants.get(i) instanceof TLRPC.Chat) { + continue; + } + if (channelParticipant instanceof TLRPC.TL_channelParticipantBanned && channelParticipant.banned_rights != null && !canBeRestricted(channelParticipant.banned_rights)) { + continue; + } + + if (banFilter[i]) { + restrictFilter[i] = true; + canRestrict = true; + } + } + } + + participantsBannedRights = Arrays.stream(channelParticipants) + .map(channelParticipant -> channelParticipant == null ? null : channelParticipant.banned_rights) + .collect(Collectors.toCollection(ArrayList::new)); + + banOrRestrict = new Action(ACTION_BAN, actionParticipants); + banOrRestrict.setFilter(banFilter); + } else { + banOrRestrict = new Action(ACTION_BAN, new ArrayList<>(0)); + } + + adapter.update(false); + actionBar.setTitle(getTitle()); + } + + public void toggleDefaultChecks(boolean[] checks) { + for (int a = 0; a < 4; a++) { + if (a == 0 && checks[a] && banOrRestrict != null) { + banOrRestrict.toggleAllChecks(); + } + if (a == 1 && checks[a] && report != null) { + report.toggleAllChecks(); + } + if (a == 2 && checks[a] && deleteAll != null) { + deleteAll.toggleAllChecks(); + } + if (a == 3 && checks[a] && applyInCommonGroup != null) { + applyInCommonGroup.toggleAllChecks(); + } + } + } + + private static boolean isBanned(TLRPC.TL_chatBannedRights bannedRights) { + return bannedRights.view_messages; + } + + private boolean hasAnyDefaultRights() { + return !defaultBannedRights.send_messages || + !defaultBannedRights.send_media || + !defaultBannedRights.send_stickers || + !defaultBannedRights.send_gifs || + !defaultBannedRights.send_games || + !defaultBannedRights.send_inline || + !defaultBannedRights.embed_links || + !defaultBannedRights.send_polls || + !defaultBannedRights.change_info || + !defaultBannedRights.invite_users || + !defaultBannedRights.pin_messages || + !defaultBannedRights.manage_topics && isForum || + !defaultBannedRights.send_photos || + !defaultBannedRights.send_videos || + !defaultBannedRights.send_roundvideos || + !defaultBannedRights.send_audios || + !defaultBannedRights.send_voices || + !defaultBannedRights.send_docs || + !defaultBannedRights.send_plain; + } + + public static TLRPC.TL_chatBannedRights bannedRightsOr(TLRPC.TL_chatBannedRights left, TLRPC.TL_chatBannedRights right) { + if (left == null) { + return right; + } + if (right == null) { + return left; + } + + TLRPC.TL_chatBannedRights bannedRights = new TLRPC.TL_chatBannedRights(); + bannedRights.view_messages = left.view_messages || right.view_messages; + bannedRights.send_messages = left.send_messages || right.send_messages; + bannedRights.send_media = left.send_media || right.send_media; + bannedRights.send_stickers = left.send_stickers || right.send_stickers; + bannedRights.send_gifs = left.send_gifs || right.send_gifs; + bannedRights.send_games = left.send_games || right.send_games; + bannedRights.send_inline = left.send_inline || right.send_inline; + bannedRights.embed_links = left.embed_links || right.embed_links; + bannedRights.send_polls = left.send_polls || right.send_polls; + bannedRights.change_info = left.change_info || right.change_info; + bannedRights.invite_users = left.invite_users || right.invite_users; + bannedRights.pin_messages = left.pin_messages || right.pin_messages; + bannedRights.manage_topics = left.manage_topics || right.manage_topics; + bannedRights.send_photos = left.send_photos || right.send_photos; + bannedRights.send_videos = left.send_videos || right.send_videos; + bannedRights.send_roundvideos = left.send_roundvideos || right.send_roundvideos; + bannedRights.send_audios = left.send_audios || right.send_audios; + bannedRights.send_voices = left.send_voices || right.send_voices; + bannedRights.send_docs = left.send_docs || right.send_docs; + bannedRights.send_plain = left.send_plain || right.send_plain; + return bannedRights; + } + + private boolean canBeRestricted(TLRPC.TL_chatBannedRights bannedRights) { + return !bannedRights.send_stickers && !defaultBannedRights.send_stickers || + !bannedRights.send_gifs && !defaultBannedRights.send_gifs || + !bannedRights.send_games && !defaultBannedRights.send_games || + !bannedRights.send_inline && !defaultBannedRights.send_inline || + !bannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.embed_links && !defaultBannedRights.send_plain || + !bannedRights.send_polls && !defaultBannedRights.send_polls || + !bannedRights.change_info && !defaultBannedRights.change_info || + !bannedRights.invite_users && !defaultBannedRights.invite_users || + !bannedRights.pin_messages && !defaultBannedRights.pin_messages || + !bannedRights.manage_topics && !defaultBannedRights.manage_topics && isForum || + !bannedRights.send_photos && !defaultBannedRights.send_photos || + !bannedRights.send_videos && !defaultBannedRights.send_videos || + !bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos || + !bannedRights.send_audios && !defaultBannedRights.send_audios || + !bannedRights.send_voices && !defaultBannedRights.send_voices || + !bannedRights.send_docs && !defaultBannedRights.send_docs || + !bannedRights.send_plain && !defaultBannedRights.send_plain; + } + + @Override + protected CharSequence getTitle() { + return LocaleController.formatPluralString("DeleteOptionsTitle", messages != null ? messages.size() : 0); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter(RecyclerListView listView) { + return adapter = new UniversalAdapter(listView, getContext(), currentAccount, getBaseFragment().getClassGuid(), true, this::fillItems, resourcesProvider); + } + + @Override + public void show() { + super.show(); + Bulletin.hideVisible(); + } + + private int getSendMediaSelectedCount() { + int i = 0; + if (!bannedRights.send_photos && !defaultBannedRights.send_photos) { + i++; + } + if (!bannedRights.send_videos && !defaultBannedRights.send_videos) { + i++; + } + if (!bannedRights.send_stickers && !defaultBannedRights.send_stickers) { + i++; + } + if (!bannedRights.send_audios && !defaultBannedRights.send_audios) { + i++; + } + if (!bannedRights.send_docs && !defaultBannedRights.send_docs) { + i++; + } + if (!bannedRights.send_voices && !defaultBannedRights.send_voices) { + i++; + } + if (!bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos) { + i++; + } + if (!bannedRights.embed_links && !defaultBannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.send_plain) { + i++; + } + if (!bannedRights.send_polls && !defaultBannedRights.send_polls) { + i++; + } + return i; + } + + private boolean allDefaultMediaBanned() { + return defaultBannedRights.send_photos && defaultBannedRights.send_videos && defaultBannedRights.send_stickers + && defaultBannedRights.send_audios && defaultBannedRights.send_docs && defaultBannedRights.send_voices && + defaultBannedRights.send_roundvideos && defaultBannedRights.embed_links && defaultBannedRights.send_polls; + } + + private void fillAction(ArrayList items, Action action) { + if (!action.isPresent()) { + return; + } + + if (!action.isExpandable()) { + items.add(UItem.asRoundCheckbox(action.type, action.title) + .setChecked(action.selectedCount > 0)); + } else { + items.add(UItem.asUserGroupCheckbox(action.type, action.title, String.valueOf(action.selectedCount > 0 ? action.selectedCount : action.getCount())) + .setChecked(action.selectedCount > 0) + .setCollapsed(action.collapsed) + .setClickCallback((v) -> { + saveScrollPosition(); + action.collapseOrExpand(); + applyScrolledPosition(true); + })); + if (!action.collapsed) { + action.forEach((userOrChat, i) -> { + items.add(UItem.asUserCheckbox(action.type << 24 | i, userOrChat) + .setChecked(action.checks[i]) + .setPad(1)); + }); + } + } + } + + private void fillItems(ArrayList items, UniversalAdapter adapter) { + if (messages == null) { + return; + } + + items.add(UItem.asHeader(getString(R.string.DeleteAdditionalActions))); + fillAction(items, report); + fillAction(items, deleteAll); + fillAction(items, applyInCommonGroup); + fillAction(items, banOrRestrict); + + if (banOrRestrict.isPresent()) { + if (restrict) { + items.add(UItem.asShadow(null)); + if (banOrRestrict.isExpandable()) { + items.add(UItem.asAnimatedHeader(0, formatPluralString("UserRestrictionsCanDoUsers", banOrRestrict.selectedCount))); + } else { + items.add(UItem.asAnimatedHeader(0, getString(R.string.UserRestrictionsCanDo))); + } + + items.add(UItem.asSwitch(RIGHT_SEND_MESSAGES, getString(R.string.UserRestrictionsSend)) + .setChecked(!bannedRights.send_plain && !defaultBannedRights.send_plain) + .setLocked(defaultBannedRights.send_plain)); + + int sendMediaCount = getSendMediaSelectedCount(); + items.add(UItem.asExpandableSwitch(RIGHT_SEND_MEDIA, getString(R.string.UserRestrictionsSendMedia), String.format(Locale.US, "%d/9", sendMediaCount)) + .setChecked(sendMediaCount > 0) + .setLocked(allDefaultMediaBanned()) + .setCollapsed(sendMediaCollapsed) + .setClickCallback((v) -> { + if (allDefaultMediaBanned()) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + boolean enabled = !(sendMediaCount > 0); + bannedRights.send_media = !enabled; + bannedRights.send_photos = !enabled; + bannedRights.send_videos = !enabled; + bannedRights.send_stickers = !enabled; + bannedRights.send_gifs = !enabled; + bannedRights.send_inline = !enabled; + bannedRights.send_games = !enabled; + bannedRights.send_audios = !enabled; + bannedRights.send_docs = !enabled; + bannedRights.send_voices = !enabled; + bannedRights.send_roundvideos = !enabled; + bannedRights.embed_links = !enabled; + bannedRights.send_polls = !enabled; + onRestrictionsChanged(); + + adapter.update(true); + })); + if (!sendMediaCollapsed) { + items.add(UItem.asRoundCheckbox(RIGHT_SEND_PHOTOS, getString(R.string.SendMediaPermissionPhotos)) + .setChecked(!bannedRights.send_photos && !defaultBannedRights.send_photos) + .setLocked(defaultBannedRights.send_photos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_VIDEOS, getString(R.string.SendMediaPermissionVideos)) + .setChecked(!bannedRights.send_videos && !defaultBannedRights.send_videos) + .setLocked(defaultBannedRights.send_videos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_FILES, getString(R.string.SendMediaPermissionFiles)) + .setChecked(!bannedRights.send_docs && !defaultBannedRights.send_docs) + .setLocked(defaultBannedRights.send_docs) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_MUSIC, getString(R.string.SendMediaPermissionMusic)) + .setChecked(!bannedRights.send_audios && !defaultBannedRights.send_audios) + .setLocked(defaultBannedRights.send_audios) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_VOICE, getString(R.string.SendMediaPermissionVoice)) + .setChecked(!bannedRights.send_voices && !defaultBannedRights.send_voices) + .setLocked(defaultBannedRights.send_voices) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_ROUND, getString(R.string.SendMediaPermissionRound)) + .setChecked(!bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos) + .setLocked(defaultBannedRights.send_roundvideos) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_STICKERS, getString(R.string.SendMediaPermissionStickersGifs)) + .setChecked(!bannedRights.send_stickers && !defaultBannedRights.send_stickers) + .setLocked(defaultBannedRights.send_stickers) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_POLLS, getString(R.string.SendMediaPolls)) + .setChecked(!bannedRights.send_polls && !defaultBannedRights.send_polls) + .setLocked(defaultBannedRights.send_polls) + .setPad(1)); + items.add(UItem.asRoundCheckbox(RIGHT_SEND_LINKS, getString(R.string.UserRestrictionsEmbedLinks)) + .setChecked(!bannedRights.embed_links && !defaultBannedRights.embed_links && !bannedRights.send_plain && !defaultBannedRights.send_plain) + .setLocked(defaultBannedRights.embed_links) + .setPad(1)); + } + + items.add(UItem.asSwitch(RIGHT_ADD_USERS, getString(R.string.UserRestrictionsInviteUsers)) + .setChecked(!bannedRights.invite_users && !defaultBannedRights.invite_users) + .setLocked(defaultBannedRights.invite_users)); + items.add(UItem.asSwitch(RIGHT_PIN_MESSAGES, getString(R.string.UserRestrictionsPinMessages)) + .setChecked(!bannedRights.pin_messages && !defaultBannedRights.pin_messages) + .setLocked(defaultBannedRights.pin_messages)); + items.add(UItem.asSwitch(RIGHT_CHANGE_CHAT_INFO, getString(R.string.UserRestrictionsChangeInfo)) + .setChecked(!bannedRights.change_info && !defaultBannedRights.change_info) + .setLocked(defaultBannedRights.change_info)); + if (isForum) { + items.add(UItem.asSwitch(RIGHT_CREATE_TOPICS, getString(R.string.CreateTopicsPermission)) + .setChecked(!bannedRights.manage_topics && !defaultBannedRights.manage_topics) + .setLocked(defaultBannedRights.manage_topics)); + } + } + + if (canRestrict) { + items.add(UItem.asShadowCollapseButton(1, getString(getRestrictToggleTextKey())) + .setCollapsed(!restrict) + .accent()); + } + } + } + + private int getRestrictToggleTextKey() { + if (!banOrRestrict.isExpandable()) { + if (restrict) { + return R.string.DeleteToggleBanUser; + } else { + return R.string.DeleteToggleRestrictUser; + } + } else { + if (restrict) { + return R.string.DeleteToggleBanUsers; + } else { + return R.string.DeleteToggleRestrictUsers; + } + } + } + + private void onRestrictionsChanged() { + if (restrict && banOrRestrict.isPresent() && banOrRestrict.selectedCount == 0) { + banOrRestrict.toggleAllChecks(); + } + } + + private float shiftDp = 10.0f; + private void onClick(UItem item, View view, int position, float x, float y) { + if (item.viewType == VIEW_TYPE_USER_CHECKBOX) { + int action = item.id >>> 24; + int index = item.id & 0xffffff; + + if (action == ACTION_REPORT) { + report.toggleCheck(index); + } else if (action == ACTION_DELETE_ALL) { + deleteAll.toggleCheck(index); + } else if (action == ACTION_BAN) { + banOrRestrict.toggleCheck(index); + } else if (action == ACTION_APPLY_IN_COMMON_GROUP) { + applyInCommonGroup.toggleCheck(index); + } + } else if (item.viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || item.viewType == VIEW_TYPE_ROUND_CHECKBOX) { + if (item.id == ACTION_REPORT) { + report.toggleAllChecks(); + } else if (item.id == ACTION_DELETE_ALL) { + deleteAll.toggleAllChecks(); + } else if (item.id == ACTION_BAN) { + banOrRestrict.toggleAllChecks(); + } else if (item.id == ACTION_APPLY_IN_COMMON_GROUP) { + applyInCommonGroup.toggleAllChecks(); + } else if (item.viewType == VIEW_TYPE_ROUND_CHECKBOX) { + if (item.locked) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + + if (item.id == RIGHT_SEND_PHOTOS) { + bannedRights.send_photos = !bannedRights.send_photos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_VIDEOS) { + bannedRights.send_videos = !bannedRights.send_videos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_MUSIC) { + bannedRights.send_audios = !bannedRights.send_audios; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_FILES) { + bannedRights.send_docs = !bannedRights.send_docs; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_ROUND) { + bannedRights.send_roundvideos = !bannedRights.send_roundvideos; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_VOICE) { + bannedRights.send_voices = !bannedRights.send_voices; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_STICKERS) { + bannedRights.send_stickers = bannedRights.send_games = bannedRights.send_gifs = bannedRights.send_inline = !bannedRights.send_stickers; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_LINKS) { + if (bannedRights.send_plain || defaultBannedRights.send_plain) { + for (int i = 0; i < adapter.getItemCount(); i++) { + UItem childItem = adapter.getItem(i); + if (childItem.viewType == VIEW_TYPE_SWITCH && childItem.id == RIGHT_SEND_MESSAGES) { + RecyclerView.ViewHolder holder = recyclerListView.findViewHolderForAdapterPosition(i + 1); + if (holder != null) { + AndroidUtilities.shakeViewSpring(holder.itemView, shiftDp = -shiftDp); + } + break; + } + } + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + return; + } + bannedRights.embed_links = !bannedRights.embed_links; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_POLLS) { + bannedRights.send_polls = !bannedRights.send_polls; + onRestrictionsChanged(); + } + adapter.update(true); + } + } else if (item.viewType == VIEW_TYPE_SWITCH) { + if (item.locked) { + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.UserRestrictionsCantModify)) + .setMessage(LocaleController.getString(R.string.UserRestrictionsCantModifyDisabled)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .create() + .show(); + return; + } + + if (item.id == RIGHT_ADD_USERS) { + bannedRights.invite_users = !bannedRights.invite_users; + onRestrictionsChanged(); + } else if (item.id == RIGHT_PIN_MESSAGES) { + bannedRights.pin_messages = !bannedRights.pin_messages; + onRestrictionsChanged(); + } else if (item.id == RIGHT_CHANGE_CHAT_INFO) { + bannedRights.change_info = !bannedRights.change_info; + onRestrictionsChanged(); + } else if (item.id == RIGHT_CREATE_TOPICS) { + bannedRights.manage_topics = !bannedRights.manage_topics; + onRestrictionsChanged(); + } else if (item.id == RIGHT_SEND_MESSAGES) { + bannedRights.send_plain = !bannedRights.send_plain; + onRestrictionsChanged(); + } + + adapter.update(true); + } else if (item.viewType == VIEW_TYPE_EXPANDABLE_SWITCH) { + sendMediaCollapsed = !sendMediaCollapsed; + saveScrollPosition(); + adapter.update(true); + applyScrolledPosition(true); + } else if (item.viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON) { + restrict = !restrict; + banOrRestrict.setFilter(restrict ? restrictFilter : banFilter); + adapter.update(true); + } + } + + private void performDelete() { + ArrayList supergroupMessageIds = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id != -mergeDialogId || mergeDialogId == 0) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + ArrayList groupMessageIds = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id == -mergeDialogId && mergeDialogId != 0) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + if (!supergroupMessageIds.isEmpty()) { + MessagesController.getInstance(currentAccount).deleteMessages(supergroupMessageIds, null, null, -inChat.id, topicId, false, mode); + } + if (!groupMessageIds.isEmpty()) { + MessagesController.getInstance(currentAccount).deleteMessages(groupMessageIds, null, null, mergeDialogId, topicId, true, mode); + } + + banOrRestrict.performAction((participant, i) -> { + if (restrict) { + TLRPC.TL_chatBannedRights rights = bannedRightsOr(bannedRights, participantsBannedRights.get(i)); + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).setParticipantBannedRole(inChat.id, (TLRPC.User) participant, null, rights, false, getBaseFragment()); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).setParticipantBannedRole(inChat.id, null, (TLRPC.Chat) participant, rights, false, getBaseFragment()); + } + } else { + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(inChat.id, (TLRPC.User) participant, null, false, false); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(inChat.id, null, (TLRPC.Chat) participant, false, false); + } + } + }); + + report.performAction((participant, i) -> { + TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); + req.channel = MessagesController.getInputChannel(inChat); + if (participant instanceof TLRPC.User) { + req.participant = MessagesController.getInputPeer((TLRPC.User) participant); + } else if (participant instanceof TLRPC.Chat) { + req.participant = MessagesController.getInputPeer((TLRPC.Chat) participant); + } + req.id = messages.stream() + .filter(msg -> msg.messageOwner.peer_id != null && msg.messageOwner.peer_id.chat_id != -mergeDialogId) + .filter(msg -> { + if (participant instanceof TLRPC.User) { + return msg.messageOwner.from_id.user_id == ((TLRPC.User) participant).id; + } else if (participant instanceof TLRPC.Chat) { + return msg.messageOwner.from_id.user_id == ((TLRPC.Chat) participant).id; + } + return false; + }) + .map(MessageObject::getId) + .collect(Collectors.toCollection(ArrayList::new)); + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, null); + }); + + deleteAll.performAction((participant, i) -> { + if (participant instanceof TLRPC.User) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(inChat, (TLRPC.User) participant, null, 0); + } else if (participant instanceof TLRPC.Chat) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(inChat, null, (TLRPC.Chat) participant, 0); + } + }); + + applyInCommonGroup.performAction((participant, i) -> { + if (participant instanceof TLRPC.User) { + boolean needBan = banOrRestrict.checkOption(participant); + boolean needDelete = banOrRestrict.checkOption(participant); + if (!needBan && !needDelete) { + return; + } + TLRPC.User userFinal = (TLRPC.User) participant; + TLRPC.TL_messages_getCommonChats req = new TLRPC.TL_messages_getCommonChats(); + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userFinal); + if (req.user_id instanceof TLRPC.TL_inputUserEmpty) { + return; + } + req.limit = 100; + req.max_id = 0; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error != null) { + return; + } + TLRPC.messages_Chats res = (TLRPC.messages_Chats) response; + for (int j=0; j < res.chats.size(); j++) { + TLRPC.Chat chat_ = res.chats.get(j); + boolean canBan = ChatObject.canBlockUsers(chat_); + boolean canDelete = ChatObject.canUserDoAdminAction(chat_, ChatObject.ACTION_DELETE_MESSAGES); + if (canBan && needBan) { + if (restrict) { + TLRPC.TL_chatBannedRights rights = bannedRightsOr(bannedRights, participantsBannedRights.get(i)); + MessagesController.getInstance(currentAccount).setParticipantBannedRole(chat_.id, (TLRPC.User) participant, null, rights, false, getBaseFragment()); + } else { + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat_.id, (TLRPC.User) participant, null, false, false); + } + } + if (canDelete && needDelete) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat_, userFinal, null, 0); + } + } + }); + } + }); + } + + private void proceed() { + dismiss(); + if (onDelete != null) { + onDelete.run(); + } + + String subtitle = ""; + if (report.selectedCount > 0) { + subtitle += formatPluralString("UsersReported", report.selectedCount); + } + if (banOrRestrict.selectedCount > 0) { + if (!TextUtils.isEmpty(subtitle)) { + subtitle += "\n"; + } + if (restrict) { + subtitle += formatPluralString("UsersRestricted", banOrRestrict.selectedCount); + } else { + subtitle += formatPluralString("UsersBanned", banOrRestrict.selectedCount); + } + } + + int icon = banOrRestrict.selectedCount > 0 ? R.raw.ic_admin : R.raw.contact_check; + if (TextUtils.isEmpty(subtitle)) { + BulletinFactory.of(getBaseFragment()).createSimpleBulletin(icon, getString(R.string.MessagesDeleted)).show(); + } else { + BulletinFactory.of(getBaseFragment()).createSimpleBulletin(icon, getString(R.string.MessagesDeleted), subtitle).show(); + } + + performDelete(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java new file mode 100644 index 0000000000..a5d34b0f43 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsChannelsAdapter.java @@ -0,0 +1,409 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.LocaleController.getString; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import org.checkerframework.checker.units.qual.A; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Adapters.DialogsSearchAdapter; +import org.telegram.ui.Cells.GraySectionCell; +import org.telegram.ui.Cells.ProfileSearchCell; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; +import org.telegram.ui.UserInfoActivity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class DialogsChannelsAdapter extends UniversalAdapter { + + private final Context context; + private final int currentAccount; + private final int folderId; + private final Theme.ResourcesProvider resourcesProvider; + + public final ArrayList messages = new ArrayList<>(); + public final ArrayList searchMyChannels = new ArrayList<>(); + public final ArrayList searchRecommendedChannels = new ArrayList<>(); + public final ArrayList searchChannels = new ArrayList<>(); + public boolean expandedSearchChannels; + + public boolean expandedMyChannels; + public final ArrayList myChannels = new ArrayList<>(); + + public DialogsChannelsAdapter(RecyclerListView listView, Context context, int currentAccount, int folderId, Theme.ResourcesProvider resourcesProvider) { + super(listView, context, currentAccount, 0, null, resourcesProvider); + super.fillItems = this::fillItems; + this.context = context; + this.currentAccount = currentAccount; + this.folderId = folderId; + this.resourcesProvider = resourcesProvider; + update(false); + } + + public void updateMyChannels() { + ArrayList channels = new ArrayList<>(); + ArrayList dialogs = MessagesController.getInstance(currentAccount).getAllDialogs(); + for (TLRPC.Dialog d : dialogs) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-d.id); + if (chat == null || !ChatObject.isChannelAndNotMegaGroup(chat) || !ChatObject.isPublic(chat) || ChatObject.isNotInChat(chat)) continue; + channels.add(chat); + if (channels.size() >= 100) + break; + } + myChannels.clear(); + myChannels.addAll(channels); + } + + public void fillItems(ArrayList items, UniversalAdapter adapter) { + if (TextUtils.isEmpty(query)) { + if (myChannels != null && !myChannels.isEmpty()) { + if (myChannels.size() > 5) { + items.add(UItem.asGraySection(getString(R.string.SearchMyChannels), getString(expandedMyChannels ? R.string.ShowLess : R.string.ShowMore), this::toggleExpandedMyChannels)); + } else { + items.add(UItem.asGraySection(getString(R.string.SearchMyChannels))); + } + int count = myChannels.size(); + if (!expandedMyChannels) + count = Math.min(5, count); + for (int i = 0; i < count; ++i) { + items.add(UItem.asProfileCell(myChannels.get(i)).withUsername(true)); + } + } + MessagesController.ChannelRecommendations recommendations = MessagesController.getInstance(currentAccount).getCachedChannelRecommendations(0); + if (recommendations != null) { + ArrayList chats = new ArrayList<>(); + for (TLRPC.Chat chat : recommendations.chats) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + chats.add(chat); + } + if (!chats.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchRecommendedChannels))); + } + for (TLRPC.Chat chat : chats) { + items.add(UItem.asProfileCell(chat)); + } + } else { + items.add(UItem.asFlicker(FlickerLoadingView.GRAY_SECTION)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + items.add(UItem.asFlicker(FlickerLoadingView.PROFILE_SEARCH_CELL)); + } + } else { + ArrayList foundChannels = new ArrayList<>(); + for (TLRPC.Chat chat : searchMyChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + for (TLRPC.Chat chat : searchRecommendedChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + for (TLRPC.Chat chat : searchChannels) { + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat))) + foundChannels.add(chat); + } + if (!foundChannels.isEmpty()) { + if (foundChannels.size() > 5 && !messages.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchChannels), getString(expandedSearchChannels ? R.string.ShowLess : R.string.ShowMore), this::toggleExpandedSearchChannels)); + } else { + items.add(UItem.asGraySection(getString(R.string.SearchChannels))); + } + int count = foundChannels.size(); + if (!expandedSearchChannels && !messages.isEmpty()) + count = Math.min(5, count); + for (int i = 0; i < count; ++i) { + items.add(UItem.asProfileCell(foundChannels.get(i))); + } + } + if (!messages.isEmpty()) { + items.add(UItem.asGraySection(getString(R.string.SearchMessages))); + for (MessageObject message : messages) { + items.add(UItem.asSearchMessage(message)); + } + if (hasMore) { + items.add(UItem.asFlicker(FlickerLoadingView.DIALOG_TYPE)); + } + } + } + } + + public void toggleExpandedSearchChannels(View view) { + expandedSearchChannels = !expandedSearchChannels; + update(true); + if (expandedSearchChannels) { + hideKeyboard(); + } + } + + public void toggleExpandedMyChannels(View view) { + expandedMyChannels = !expandedMyChannels; + update(true); + if (expandedMyChannels) { + hideKeyboard(); + } + } + + protected void hideKeyboard() { + + } + + public TLRPC.Chat getChat(int position) { + UItem item = getItem(position); + return item != null && item.object instanceof TLRPC.Chat ? (TLRPC.Chat) item.object : null; + } + + public Object getObject(int position) { + UItem item = getItem(position); + return item != null ? item.object : null; + } + + public boolean loadingMessages; + public boolean loadingChannels; + + private boolean hasMore; + private int allCount; + private int nextRate; + private int searchChannelsId; + public String query; + private void searchMessages(boolean next) { + loadingMessages = true; + final int searchId = ++searchChannelsId; + TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal(); + req.broadcasts_only = true; + if (folderId != 0) { + req.flags |= 1; + req.folder_id = folderId; + } + req.q = this.query; + req.limit = 25; + req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); + if (next && !messages.isEmpty()) { + MessageObject lastMessage = messages.get(messages.size() - 1); + req.offset_rate = nextRate; + req.offset_id = lastMessage.getId(); + if (lastMessage.messageOwner.peer_id == null) { + req.offset_peer = new TLRPC.TL_inputPeerEmpty(); + } else { + req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(lastMessage.messageOwner.peer_id); + } + } else { + req.offset_rate = 0; + req.offset_id = 0; + req.offset_peer = new TLRPC.TL_inputPeerEmpty(); + } + AndroidUtilities.runOnUIThread(() -> { + if (searchId != searchChannelsId || !TextUtils.equals(req.q, this.query)) return; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (searchId != searchChannelsId || !TextUtils.equals(req.q, this.query)) return; + loadingMessages = false; + if (!next) { + messages.clear(); + } + if (res instanceof TLRPC.messages_Messages) { + TLRPC.messages_Messages response = (TLRPC.messages_Messages) res; + MessagesStorage.getInstance(currentAccount).putUsersAndChats(response.users, response.chats, true, true); + MessagesController.getInstance(currentAccount).putUsers(response.users, false); + MessagesController.getInstance(currentAccount).putChats(response.chats, false); + + for (TLRPC.Message message : response.messages) { + MessageObject messageObject = new MessageObject(currentAccount, message, false, true); + messageObject.setQuery(query); + messages.add(messageObject); + } + + hasMore = response instanceof TLRPC.TL_messages_messagesSlice; + allCount = Math.max(messages.size(), response.count); + nextRate = response.next_rate; + } + update(true); + })); + }, next ? 800 : 0); + + if (!next) { + loadingChannels = true; + TLRPC.TL_contacts_search req2 = new TLRPC.TL_contacts_search(); + req2.limit = 20; + req2.q = this.query; + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (!TextUtils.equals(req2.q, this.query) || TextUtils.isEmpty(this.query)) return; + + loadingChannels = false; + TLRPC.TL_contacts_found response = null; + if (res instanceof TLRPC.TL_contacts_found) { + response = (TLRPC.TL_contacts_found) res; + MessagesStorage.getInstance(currentAccount).putUsersAndChats(response.users, response.chats, true, true); + MessagesController.getInstance(currentAccount).putUsers(response.users, false); + MessagesController.getInstance(currentAccount).putChats(response.chats, false); + } + + HashSet chatIds = new HashSet<>(); + + searchMyChannels.clear(); + if (response != null) { + for (TLRPC.Peer peer : response.my_results) { + if (!(peer instanceof TLRPC.TL_peerChannel)) continue; + TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(peer.channel_id); + if (channel == null) continue; + if (!ChatObject.isChannelAndNotMegaGroup(channel)) + continue; + if (chatIds.contains(channel.id)) + continue; + chatIds.add(channel.id); + searchMyChannels.add(channel); + } + } + + searchRecommendedChannels.clear(); + String q = this.query.toLowerCase(), qT = AndroidUtilities.translitSafe(q); + MessagesController.ChannelRecommendations recommendations = MessagesController.getInstance(currentAccount).getCachedChannelRecommendations(0); + if (recommendations != null && !recommendations.chats.isEmpty()) { + for (TLRPC.Chat chat : recommendations.chats) { + if (chat == null) + continue; + if (!ChatObject.isChannelAndNotMegaGroup(chat)) + continue; + TLRPC.Chat localChat = MessagesController.getInstance(currentAccount).getChat(chat.id); + if (!(ChatObject.isNotInChat(chat) && (localChat == null || ChatObject.isNotInChat(localChat)))) + continue; + String t = chat.title.toLowerCase(), tT = AndroidUtilities.translitSafe(t); + if ( + t.startsWith(q) || t.contains(" " + q) || + tT.startsWith(qT) || tT.contains(" " + qT) + ) { + if (chatIds.contains(chat.id)) + continue; + chatIds.add(chat.id); + searchRecommendedChannels.add(chat); + } + } + } + + searchChannels.clear(); + if (response != null) { + for (TLRPC.Peer peer : response.results) { + if (!(peer instanceof TLRPC.TL_peerChannel)) continue; + TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(peer.channel_id); + if (channel == null) continue; + if (!ChatObject.isChannelAndNotMegaGroup(channel)) + continue; + if (chatIds.contains(channel.id)) + continue; + chatIds.add(channel.id); + searchChannels.add(channel); + } + } + + update(true); + })); + } + } + + private Runnable searchMessagesRunnable = () -> searchMessages(false); + public void search(String query) { + updateMyChannels(); + if (TextUtils.equals(query, this.query)) return; + this.query = query; + AndroidUtilities.cancelRunOnUIThread(searchMessagesRunnable); + if (TextUtils.isEmpty(this.query)) { + messages.clear(); + searchChannels.clear(); + searchRecommendedChannels.clear(); + searchMyChannels.clear(); + update(true); + searchChannelsId++; + loadingMessages = false; + loadingChannels = false; + hasMore = false; + nextRate = 0; + if (listView != null) { + listView.scrollToPosition(0); + } + return; + } + + messages.clear(); + searchChannels.clear(); + searchRecommendedChannels.clear(); + searchMyChannels.clear(); + + AndroidUtilities.runOnUIThread(searchMessagesRunnable, 1000); + loadingMessages = true; + loadingChannels = true; + + update(true); + + if (listView != null) { + listView.scrollToPosition(0); + } + } + + public void searchMore() { + if (!hasMore || loadingMessages || TextUtils.isEmpty(this.query)) { + return; + } + searchMessages(true); + } + + public ArrayList getNextChannels(int position) { + ArrayList channels = new ArrayList<>(); + for (int pos = position + 1; pos < getItemCount(); ++pos) { + TLRPC.Chat chat = getChat(pos); + if (chat == null) continue; + channels.add(chat); + } + return channels; + } + + public void checkBottom() { + if (!hasMore || loadingMessages || TextUtils.isEmpty(this.query) || listView == null) + return; + if (seesLoading()) { + searchMore(); + } + } + + public boolean seesLoading() { + if (listView == null) return false; + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (child instanceof FlickerLoadingView) { + return true; + } + } + return false; + } + + public boolean atTop() { + if (listView == null) return false; + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (listView.getChildAdapterPosition(child) == 0) + return true; + } + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index 1fc5f7b324..86f18ddb8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -8,6 +8,9 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.getWallpaperRotation; + import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; @@ -15,8 +18,12 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.Rect; @@ -390,7 +397,7 @@ private void init() { linePaint = new Paint(); activeLinePaint = new Paint(); errorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - errorPaint.setTextSize(AndroidUtilities.dp(11)); + errorPaint.setTextSize(dp(11)); if (Build.VERSION.SDK_INT >= 26) { setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO); } @@ -409,12 +416,12 @@ public void draw(Canvas canvas) { @Override public int getIntrinsicHeight() { - return AndroidUtilities.dp(cursorSize + 20); + return dp(cursorSize + 20); } @Override public int getIntrinsicWidth() { - return AndroidUtilities.dp(cursorWidth); + return dp(cursorWidth); } }; cursorDrawable.setShape(new RectShape()); @@ -474,7 +481,7 @@ public int getIntrinsicWidth() { } } - cursorSize = AndroidUtilities.dp(24); + cursorSize = dp(24); } @SuppressLint("PrivateApi") @@ -591,10 +598,10 @@ public void setHeaderHintColor(int value) { @Override public void setTextSize(int unit, float size) { if (hintAnimatedDrawable != null) { - hintAnimatedDrawable.setTextSize(AndroidUtilities.dp(size)); + hintAnimatedDrawable.setTextSize(dp(size)); } if (hintAnimatedDrawable2 != null) { - hintAnimatedDrawable2.setTextSize(AndroidUtilities.dp(size)); + hintAnimatedDrawable2.setTextSize(dp(size)); } super.setTextSize(unit, size); } @@ -661,12 +668,12 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setHintText(hint, false, hintLayout.getPaint()); } if (hintLayoutYFix) { - lineY = getExtendedPaddingTop() + getPaddingTop() + (getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() - AndroidUtilities.dp(1); + lineY = getExtendedPaddingTop() + getPaddingTop() + (getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() - dp(1); } else { - lineY = (getMeasuredHeight() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() + AndroidUtilities.dp(6); + lineY = (getMeasuredHeight() - hintLayout.getHeight()) / 2.0f + hintLayout.getHeight() + dp(6); } } else { - lineY = getMeasuredHeight() - AndroidUtilities.dp(2); + lineY = getMeasuredHeight() - dp(2); } lastSize = currentSize; } @@ -706,7 +713,7 @@ public void setHintText(CharSequence text, boolean animated, TextPaint paint) { return; } } - hintLayout = new StaticLayout(text, paint, AndroidUtilities.dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + hintLayout = new StaticLayout(text, paint, dp(1000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); invalidate(); } } @@ -847,7 +854,7 @@ private void drawHint(Canvas canvas) { hintAnimatedDrawable2.setAlpha((int) (Color.alpha(hintColor) * hintAlpha)); hintAnimatedDrawable2.draw(canvas); canvas.restore(); - hintAnimatedDrawable.setRightPadding(hintAnimatedDrawable2.getCurrentWidth() + AndroidUtilities.dp(2) - rightHintOffset); + hintAnimatedDrawable.setRightPadding(hintAnimatedDrawable2.getCurrentWidth() + dp(2) - rightHintOffset); } } else { hintAnimatedDrawable.setRightPadding(0); @@ -866,7 +873,7 @@ private void drawHint(Canvas canvas) { } if (supportRtlHint && LocaleController.isRTL) { float offset = getMeasuredWidth() - hintWidth; - canvas.translate(hintLayoutX = left + getScrollX() + offset, hintLayoutY = lineY - hintLayout.getHeight() - AndroidUtilities.dp(7)); + canvas.translate(hintLayoutX = left + getScrollX() + offset, hintLayoutY = lineY - hintLayout.getHeight() - dp(7)); } else { canvas.translate(hintLayoutX = left + getScrollX(), hintLayoutY = lineY - hintLayout.getHeight() - AndroidUtilities.dp2(7)); } @@ -879,7 +886,7 @@ private void drawHint(Canvas canvas) { canvas.translate(lineLeft * (1.0f - scale), 0); } canvas.scale(scale, scale); - canvas.translate(0, -AndroidUtilities.dp(22) * headerAnimationProgress); + canvas.translate(0, -dp(22) * headerAnimationProgress); getPaint().setColor(ColorUtils.blendARGB(hintColor, headerHintColor, headerAnimationProgress)); } else { getPaint().setColor(hintColor); @@ -906,6 +913,10 @@ private void drawHint(Canvas canvas) { protected void onDraw(Canvas canvas) { drawHint(canvas); + if (ellipsizeByGradient) { + canvas.saveLayerAlpha(getScrollX() + getPaddingLeft() - ellipsizeWidth, 0, getScrollX() + getWidth() - getPaddingRight() + ellipsizeWidth, getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + } + int topPadding = getExtendedPaddingTop(); scrollY = Integer.MAX_VALUE; try { @@ -972,7 +983,7 @@ protected void onDraw(Canvas canvas) { updateCursorPosition(); Rect bounds = gradientDrawable.getBounds(); rect.left = bounds.left; - rect.right = bounds.left + AndroidUtilities.dp(cursorWidth); + rect.right = bounds.left + dp(cursorWidth); rect.bottom = bounds.bottom; rect.top = bounds.top; if (lineSpacingExtra != 0 && line < lineCount - 1) { @@ -1010,7 +1021,7 @@ protected void onDraw(Canvas canvas) { updateCursorPosition(); Rect bounds = gradientDrawable.getBounds(); rect.left = bounds.left; - rect.right = bounds.left + AndroidUtilities.dp(cursorWidth); + rect.right = bounds.left + dp(cursorWidth); rect.bottom = bounds.bottom; rect.top = bounds.top; if (lineSpacingExtra != 0 && line < lineCount - 1) { @@ -1030,11 +1041,11 @@ protected void onDraw(Canvas canvas) { } } if (lineVisible && lineColor != 0) { - int lineWidth = AndroidUtilities.dp(1); + int lineWidth = dp(1); boolean wasLineActive = lineActive; if (!TextUtils.isEmpty(errorText)) { linePaint.setColor(errorLineColor); - lineWidth = AndroidUtilities.dp(2); + lineWidth = dp(2); lineActive = false; } else if (isFocused()) { lineActive = true; @@ -1055,7 +1066,7 @@ protected void onDraw(Canvas canvas) { } int scrollHeight = (getLayout() == null ? 0 : getLayout().getHeight()) - getMeasuredHeight() + getPaddingBottom() + getPaddingTop(); - int bottom = (int) lineY + getScrollY() + Math.min(Math.max(0, scrollHeight - getScrollY()), AndroidUtilities.dp(2)); + int bottom = (int) lineY + getScrollY() + Math.min(Math.max(0, scrollHeight - getScrollY()), dp(2)); int centerX = lastTouchX < 0 ? getMeasuredWidth() / 2 : lastTouchX, maxWidth = Math.max(centerX, getMeasuredWidth() - centerX) * 2; if (lineActiveness < 1f) { @@ -1066,7 +1077,7 @@ protected void onDraw(Canvas canvas) { if (lineActive) { activeLineWidth = maxWidth * lineActivenessT; } - int lineThickness = (int) ((lineActive ? 1 : lineActivenessT) * AndroidUtilities.dp(2)); + int lineThickness = (int) ((lineActive ? 1 : lineActivenessT) * dp(2)); canvas.drawRect( getScrollX() + Math.max(0, centerX - activeLineWidth / 2), bottom - lineThickness, @@ -1076,6 +1087,22 @@ protected void onDraw(Canvas canvas) { ); } } + if (ellipsizeByGradient) { + canvas.save(); + canvas.translate(getScrollX(), 0); + ellipsizePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + ellipsizeMatrix.reset(); + ellipsizeGradient.setLocalMatrix(ellipsizeMatrix); + canvas.drawRect(getPaddingLeft() - ellipsizeWidth, 0, getPaddingLeft(), getHeight(), ellipsizePaint); + + ellipsizeMatrix.reset(); + ellipsizeMatrix.postScale(-1, 1, ellipsizeWidth / 2f, 0); + ellipsizeMatrix.postTranslate(getWidth() - getPaddingRight(), 0); + ellipsizeGradient.setLocalMatrix(ellipsizeMatrix); + canvas.drawRect(getWidth() - getPaddingRight(), 0, getWidth() - getPaddingRight() + ellipsizeWidth, getHeight(), ellipsizePaint); + canvas.restore(); + canvas.restore(); + } /*if (errorLayout != null) { canvas.save(); canvas.translate(getScrollX(), lineY + AndroidUtilities.dp(3)); @@ -1131,7 +1158,7 @@ private int clampHorizontalPosition(final Drawable drawable, float horizontal) { private void updateCursorPosition(int top, int bottom, float horizontal) { final int left = clampHorizontalPosition(gradientDrawable, horizontal); - final int width = AndroidUtilities.dp(cursorWidth); + final int width = dp(cursorWidth); gradientDrawable.setBounds(left, top - mTempRect.top, left + width, bottom + mTempRect.bottom); } @@ -1295,4 +1322,24 @@ public void setOnPremiumMenuLockClickListener(Runnable listener) { public Runnable getOnPremiumMenuLockClickListener() { return onPremiumMenuLockClickListener; } + + public boolean ellipsizeByGradient; + private Paint ellipsizePaint; + private LinearGradient ellipsizeGradient; + private Matrix ellipsizeMatrix; + private int ellipsizeWidth; + public void setEllipsizeByGradient(boolean value) { + if (ellipsizeByGradient = value) { + ellipsizeWidth = dp(12); + ellipsizePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + ellipsizeGradient = new LinearGradient(0, 0, ellipsizeWidth, 0, new int[] {0xFFFFFFFF, 0x00FFFFFF}, new float[] {0.4f, 1}, Shader.TileMode.CLAMP); + ellipsizePaint.setShader(ellipsizeGradient); + ellipsizeMatrix = new Matrix(); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java index 2407f9fbd6..206e2e93e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java @@ -366,12 +366,16 @@ public void updateAnimatedEmoji(boolean force) { } int newTextLength = (getLayout() == null || getLayout().getText() == null) ? 0 : getLayout().getText().length(); if (force || lastLayout != getLayout() || lastTextLength != newTextLength) { - animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.getCacheTypeForEnterView(), this, animatedEmojiDrawables, getLayout()); + animatedEmojiDrawables = AnimatedEmojiSpan.update(emojiCacheType(), this, animatedEmojiDrawables, getLayout()); lastLayout = getLayout(); lastTextLength = newTextLength; } } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.getCacheTypeForEnterView(); + } + private int lastText2Length; private int quoteUpdatesTries; private boolean[] quoteUpdateLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java index f522dad63a..67dcc30d4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java @@ -647,7 +647,7 @@ protected void dispatchDraw(Canvas canvas) { if (drawable == null) { continue; } - drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText))); // drawable.addView(this); ArrayList arrayList = viewsGroupedByLines.get(child.getTop()); if (arrayList == null) { @@ -781,7 +781,7 @@ public void prepareDraw(long time) { drawable.setAlpha(255); AndroidUtilities.rectTmp2.set(imageView.getLeft() + imageView.getPaddingLeft(), imageView.getPaddingTop(), imageView.getRight() - imageView.getPaddingRight(), imageView.getMeasuredHeight() - imageView.getPaddingBottom()); imageView.backgroundThreadDrawHolder[threadIndex].setBounds(AndroidUtilities.rectTmp2); - drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText))); imageView.imageReceiver = drawable.getImageReceiver();; drawInBackgroundViews.add(imageView); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 2afb106874..ac8d08df9c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -426,7 +426,7 @@ default void onClearEmojiRecent() { } - default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { + default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet, boolean edit) { } @@ -623,7 +623,7 @@ public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null) { return; } - delegate.onShowStickerSet(null, set); + delegate.onShowStickerSet(null, set, false); } @Override @@ -652,6 +652,18 @@ public String getQuery(boolean isGif) { } return emojiGridView.getAdapter() == emojiSearchAdapter ? emojiSearchAdapter.lastSearchEmojiString : null; } + + @Override + public void deleteSticker(TLRPC.Document document) { + TLRPC.TL_stickers_removeStickerFromSet req = new TLRPC.TL_stickers_removeStickerFromSet(); + req.sticker = MediaDataController.getInputStickerSetItem(document, "").document; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_messages_stickerSet) { + MediaDataController.getInstance(currentAccount).putStickerSet((TLRPC.TL_messages_stickerSet) response); + MediaDataController.getInstance(currentAccount).replaceStickerSet((TLRPC.TL_messages_stickerSet) response); + } + })); + } }; @Override @@ -864,7 +876,7 @@ protected int getCurrentColor() { box.addView(clear, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); if (type != 1 || allowAnimatedEmoji && UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { - categoriesListView = new StickerCategoriesListView(context, null, StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { + categoriesListView = new StickerCategoriesListView(context, null, type == 0 ? StickerCategoriesListView.CategoriesType.STICKERS : StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { @Override public void selectCategory(int categoryIndex) { super.selectCategory(categoryIndex); @@ -2180,7 +2192,7 @@ public int getSpanSize(int position) { query = stickersSearchGridAdapter.searchQuery; TLRPC.StickerSetCovered pack = stickersSearchGridAdapter.positionsToSets.get(position); if (pack != null) { - delegate.onShowStickerSet(pack.set, null); + delegate.onShowStickerSet(pack.set, null, false); return; } } @@ -4959,6 +4971,13 @@ private SearchField getSearchFieldForType(@Type int type) { } } + public void scrollEmojiToTop() { + try { + emojiTabs.scrollTo(0, 0); + emojiTabs.onTabClick(0); + } catch (Exception ignore) {} + } + private void checkEmojiSearchFieldScroll(boolean isLayout) { if (delegate != null && delegate.isSearchOpened()) { RecyclerView.ViewHolder holder = emojiGridView.findViewHolderForAdapterPosition(0); @@ -6550,6 +6569,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } case 2: { StickerSetNameCell cell = (StickerSetNameCell) holder.itemView; + cell.setHeaderOnClick(null); if (position == groupStickerPackPosition) { int icon; if (groupStickersHidden && groupStickerSet == null) { @@ -6571,9 +6591,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { cell.setText(title, 0); if (set.set.creator && !StickersAlert.DISABLE_STICKER_EDITOR) { cell.setEdit(v -> { - delegate.onShowStickerSet(set.set, null); + delegate.onShowStickerSet(set.set, null, true); }); } + cell.setHeaderOnClick(v -> delegate.onShowStickerSet(set.set, null, false)); } } else if (object == recentStickers) { cell.setText(LocaleController.getString("RecentStickers", R.string.RecentStickers), R.drawable.msg_close, LocaleController.getString(R.string.ClearRecentStickersAlertTitle)); @@ -8617,6 +8638,48 @@ private void addFromSuggestions(Runnable finished) { } } + private void addPremiumStickers(Runnable finished) { + HashMap> allStickers = MediaDataController.getInstance(currentAccount).getAllStickers(); + + HashSet added = new HashSet<>(); + ArrayList stickers = new ArrayList<>(); + for (ArrayList documents : allStickers.values()) { + for (TLRPC.Document document : documents) { + if (!added.contains(document.id) && MessageObject.isPremiumSticker(document)) { + added.add(document.id); + stickers.add(document); + emojiStickersMap.put(document.id, document); + } + } + } + + ArrayList covers = MediaDataController.getInstance(currentAccount).getFeaturedStickerSets(); + for (TLRPC.StickerSetCovered set : covers) { + if (set.cover != null && !added.contains(set.cover.id) && MessageObject.isPremiumSticker(set.cover)) { + added.add(set.cover.id); + stickers.add(set.cover); + emojiStickersMap.put(set.cover.id, set.cover); + } + if (set.covers != null) { + for (TLRPC.Document document : set.covers) { + if (!added.contains(document.id) && MessageObject.isPremiumSticker(document)) { + added.add(document.id); + stickers.add(document); + emojiStickersMap.put(document.id, document); + } + } + } + } + + if (!stickers.isEmpty()) { + emojiStickersArray.addAll(stickers); + emojiStickers.put(emojiStickersArray, searchQuery); + emojiArrays.add(emojiStickersArray); + } + + finished.run(); + } + private void addLocalPacks(Runnable finished) { ArrayList local = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); MessagesController.getInstance(currentAccount).filterPremiumStickers(local); @@ -8735,15 +8798,23 @@ public void run() { stickersSearchField.showProgress(true); - Utilities.raceCallbacks( - this::searchFinish, + if ("premium".equalsIgnoreCase(query)) { + Utilities.raceCallbacks( + this::searchFinish, - this::addFromAllStickers, - this::addFromSuggestions, - this::addLocalPacks, - this::searchStickerSets, - this::searchStickers - ); + this::addPremiumStickers + ); + } else { + Utilities.raceCallbacks( + this::searchFinish, + + this::addFromAllStickers, + this::addFromSuggestions, + this::addLocalPacks, + this::searchStickerSets, + this::searchStickers + ); + } } }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java index ac5ff8975b..70022ea7e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -48,6 +48,8 @@ public class FlickerLoadingView extends View { public static final int CHECKBOX_TYPE = 26; public final static int STORIES_TYPE = 27; public static final int SOTRY_VIEWS_USER_TYPE = 28; + public static final int PROFILE_SEARCH_CELL = 29; + public static final int GRAY_SECTION = 30; private int gradientWidth; private LinearGradient gradient; @@ -440,6 +442,41 @@ protected void onDraw(Canvas canvas) { break; } } + } else if (getViewType() == PROFILE_SEARCH_CELL) { + int k = 0; + while (h <= getMeasuredHeight()) { + int r = AndroidUtilities.dp(23); + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(9) + r), h + (AndroidUtilities.dp(64) >> 1), r, paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(17), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(25)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(68), h + AndroidUtilities.dp(39), paddingLeft + AndroidUtilities.dp(140), h + AndroidUtilities.dp(47)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + h += getCellHeight(getMeasuredWidth()); + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } + } else if (getViewType() == GRAY_SECTION) { + int k = 0; + while (h <= getMeasuredHeight()) { + int cellHeight = getCellHeight(getMeasuredWidth()); + + rectF.set(0, h, getMeasuredWidth(), h + cellHeight); + checkRtl(rectF); + canvas.drawRect(rectF, paint); + + h += cellHeight; + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } } else if (getViewType() == CALL_LOG_TYPE) { int k = 0; while (h <= getMeasuredHeight()) { @@ -869,6 +906,10 @@ private int getCellHeight(int width) { return AndroidUtilities.dp(50) + 1; case SOTRY_VIEWS_USER_TYPE: return AndroidUtilities.dp(58); + case PROFILE_SEARCH_CELL: + return AndroidUtilities.dp(60) + 1; + case GRAY_SECTION: + return AndroidUtilities.dp(32); } return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java index 2bec001782..b7cdb3a6e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java @@ -201,11 +201,20 @@ public static Drawable createSmallTopicDrawable(String text, int color) { } public static void openTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_forumTopic topic, int fromMessageId) { + ChatActivity chatActivity = getChatActivityForTopic(baseFragment, chatId, topic, fromMessageId, new Bundle()); + if (chatActivity != null) { + baseFragment.presentFragment(chatActivity); + } + } + + public static ChatActivity getChatActivityForTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_forumTopic topic, int fromMessageId, Bundle args) { if (baseFragment == null || topic == null) { - return; + return null; } TLRPC.Chat chatLocal = baseFragment.getMessagesController().getChat(chatId); - Bundle args = new Bundle(); + if (args == null) { + args = new Bundle(); + } args.putLong("chat_id", chatId); if (fromMessageId != 0) { @@ -226,7 +235,7 @@ public static void openTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_fo } } if (message == null) { - return; + return null; } ArrayList messageObjects = new ArrayList<>(); messageObjects.add(new MessageObject(baseFragment.getCurrentAccount(), message, false, false)); @@ -234,7 +243,7 @@ public static void openTopic(BaseFragment baseFragment, long chatId, TLRPC.TL_fo if (fromMessageId != 0) { chatActivity.highlightMessageId = fromMessageId; } - baseFragment.presentFragment(chatActivity); + return chatActivity; } public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint, boolean isDialog) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java new file mode 100644 index 0000000000..5a6ba17c2f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardBackground.java @@ -0,0 +1,153 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.StaticLayout; +import android.view.View; +import android.graphics.Rect; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.Theme; + +public class ForwardBackground { + + private final View view; + public final Path path = new Path(); + public final Rect bounds = new Rect(); + public final ButtonBounce bounce; + private final RectF r = new RectF(); + public float cx, cy; + + public ForwardBackground(View view) { + this.view = view; + bounce = new ButtonBounce(view, .8f, 1.4f); + } + + private int rippleDrawableColor; + private Drawable rippleDrawable; + + public void set(StaticLayout[] layout, boolean topLeftRad) { + final int h = dp(4) + (int) Theme.chat_forwardNamePaint.getTextSize() * 2; + + float pinnedR = Math.max(0, Math.min(6, SharedConfig.bubbleRadius) - 1); + float R = Math.min(9, SharedConfig.bubbleRadius); + float joinR = Math.min(3, SharedConfig.bubbleRadius); + + float pad = 4 + R / 9f * 2.66f; + float l = -dp(pad); + float t = -dp(3); + float b = h + dp(5); + + float w1 = layout[0].getLineWidth(0) + dp(pad); + float w2 = layout[1].getLineWidth(0) + dp(pad); + + float D; + + path.rewind(); + + D = 2 * dp(topLeftRad ? pinnedR : SharedConfig.bubbleRadius / 2f); + r.set(l, t, l + D, t + D); + path.arcTo(r, 180, 90); + + float w = w1; + if (Math.abs(w1 - w2) < dp(joinR + R)) { + w = Math.max(w1, w2); + } + + if (Math.abs(w1 - w2) > dp(joinR + R)) { + float d = 2 * dp(joinR); + float hm; + if (w1 < w2) { + hm = t + 0.45f * (b - t); + + D = 2 * dp(R); + r.set(w - D, t, w, t + D); + path.arcTo(r, 270, 90); + + r.set(w1, hm - d, w1 + d, hm); + path.arcTo(r, 180, -90); + + r.set(w2 - (b - hm), hm, w2, b); + path.arcTo(r, 270, 90); + + r.set(w2 - (b - hm), hm, w2, b); + path.arcTo(r, 0, 90); + } else { + hm = t + 0.55f * (b - t); + r.set(w - (hm - t), t, w, hm); + path.arcTo(r, 270, 90); + + D = 2 * dp(R); + r.set(w1 - (hm - t), t, w1, hm); + path.arcTo(r, 0, 90); + + r.set(w2, hm, w2 + d, hm + d); + path.arcTo(r, 270, -90); + + r.set(w2 - D, b - D, w2, b); + path.arcTo(r, 0, 90); + } + } else { + D = 2 * dp(R); + r.set(w - D, t, w, t + D); + path.arcTo(r, 270, 90); + + r.set(w - D, b - D, w, b); + path.arcTo(r, 0, 90); + } + + r.set(l, b - D, l + D, b); + path.arcTo(r, 90, 90); + + path.close(); + + bounds.set((int) l, (int) t, (int) Math.max(w1, w2), (int) b); + } + + public void setColor(int color) { + if (rippleDrawableColor != color) { + if (rippleDrawable == null) { + rippleDrawable = Theme.createSelectorDrawable(color, Theme.RIPPLE_MASK_ALL); + } else { + Theme.setSelectorDrawableColor(rippleDrawable, color, true); + } + rippleDrawableColor = color; + } + } + + public void setPressed(boolean pressed) { + setPressed(pressed, bounds.centerX(), bounds.centerY()); + } + + public void setPressed(boolean pressed, float x, float y) { + bounce.setPressed(pressed); + if (rippleDrawable != null) { + rippleDrawable.setState(pressed ? new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed} : new int[]{}); + } + if (pressed) { + cx = x; + cy = y; + if (rippleDrawable != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setHotspot(x, y); + } + } + view.invalidate(); + } + + public void draw(Canvas canvas) { + canvas.save(); + canvas.clipPath(path); + if (rippleDrawable != null) { + rippleDrawable.setBounds(bounds); + rippleDrawable.draw(canvas); + } + canvas.restore(); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java index 5277b0e4a0..74711bd53b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -51,7 +51,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -178,7 +177,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private Size aspectRatio = SharedConfig.roundCamera16to9 ? new Size(16, 9) : new Size(4, 3); private TextureView textureView; private BackupImageView textureOverlayView; - private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2; + private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.isUsingCamera2(currentAccount); private CameraSession cameraSession; private boolean bothCameras; private Camera2Session[] camera2Sessions = new Camera2Session[2]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java index a04a7dbe14..d8ee2ad2ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java @@ -144,6 +144,13 @@ public ItemOptions addIf(boolean condition, int iconResId, CharSequence text, Ru return add(iconResId, text, Theme.key_actionBarDefaultSubmenuItemIcon, Theme.key_actionBarDefaultSubmenuItem, onClickListener); } + public ItemOptions addIf(boolean condition, int iconResId, Drawable iconDrawable, CharSequence text, Runnable onClickListener) { + if (!condition) { + return this; + } + return add(iconResId, iconDrawable, text, Theme.key_actionBarDefaultSubmenuItemIcon, Theme.key_actionBarDefaultSubmenuItem, onClickListener); + } + public ItemOptions add(CharSequence text, Runnable onClickListener) { return add(0, text, false, onClickListener); } @@ -161,14 +168,18 @@ public ItemOptions add(int iconResId, CharSequence text, int color, Runnable onC } public ItemOptions add(int iconResId, CharSequence text, int iconColorKey, int textColorKey, Runnable onClickListener) { + return add(iconResId, null, text, iconColorKey, textColorKey, onClickListener); + } + + public ItemOptions add(int iconResId, Drawable iconDrawable, CharSequence text, int iconColorKey, int textColorKey, Runnable onClickListener) { if (context == null) { return this; } ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider); subItem.setPadding(dp(18), 0, dp(18 + (LocaleController.isRTL ? 0 : 8)), 0); - if (iconResId != 0) { - subItem.setTextAndIcon(text, iconResId); + if (iconResId != 0 || iconDrawable != null) { + subItem.setTextAndIcon(text, iconResId, iconDrawable); } else { subItem.setText(text); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java index a474b04074..07ce097a05 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java @@ -3,11 +3,15 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.CornerPathEffect; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.SystemClock; import android.text.Layout; @@ -28,6 +32,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.LiteMode; +import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -661,6 +666,7 @@ protected void onDraw(Canvas canvas) { } canvas.restore(); } + super.onDraw(canvas); boolean restore = false; try { Layout layout = getLayout(); @@ -670,7 +676,11 @@ protected void onDraw(Canvas canvas) { restore = true; canvas.translate(getPaddingLeft(), offset); } - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, null, 0, 0, 0, 1f); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); + if (emojiColorFilter == null) { + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, null, 0, 0, 0, 1f, emojiColorFilter); } catch (Exception e) { if (!loggedError) FileLog.e(e, true); loggedError = true; @@ -678,25 +688,30 @@ protected void onDraw(Canvas canvas) { if (restore) { canvas.restore(); } - super.onDraw(canvas); } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + } + + private ColorFilter emojiColorFilter; + @Override public void setText(CharSequence text, TextView.BufferType type) { super.setText(text, type); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, stack, getLayout()); + stack = AnimatedEmojiSpan.update(emojiCacheType(), this, stack, getLayout()); } @Override @@ -704,6 +719,18 @@ protected void onDetachedFromWindow() { super.onDetachedFromWindow(); AnimatedEmojiSpan.release(this, stack); } + + @Override + public void setTextColor(int color) { + super.setTextColor(color); + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } + + @Override + public void setTextColor(ColorStateList colors) { + super.setTextColor(colors); + emojiColorFilter = new PorterDuffColorFilter(getPaint().linkColor, PorterDuff.Mode.SRC_IN); + } } public static class ClickableSmallTextView extends SimpleTextView { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java index e76d2e696b..0e54598e34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -146,6 +146,11 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); getNotificationCenter().removeObserver(this, NotificationCenter.storiesEnabledUpdate); + if (applyBulletin != null) { + Runnable runnable = applyBulletin; + applyBulletin = null; + AndroidUtilities.runOnUIThread(runnable); + } } @Override @@ -438,7 +443,6 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { } } sharedMediaLayout.closeActionMode(false); - sharedMediaLayout.disableScroll(false); if (pin) { sharedMediaLayout.scrollToPage(SharedMediaLayout.TAB_STORIES); } @@ -562,6 +566,10 @@ protected boolean isStoriesView() { return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; } + protected boolean customTabs() { + return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; + } + @Override protected boolean includeStories() { return type == TYPE_STORIES || type == TYPE_ARCHIVED_CHANNEL_STORIES; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java index 56b83596aa..f8880aceed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineTextContainerView.java @@ -26,7 +26,7 @@ public class OutlineTextContainerView extends FrameLayout { new SimpleFloatPropertyCompat("selectionProgress", obj -> obj.selectionProgress, (obj, value) -> { obj.selectionProgress = value; if (!obj.forceUseCenter) { - obj.outlinePaint.setStrokeWidth(obj.strokeWidthRegular + (obj.strokeWidthSelected - obj.strokeWidthRegular) * obj.selectionProgress); + obj.outlinePaint.setStrokeWidth(AndroidUtilities.lerp(obj.strokeWidthRegular, obj.strokeWidthSelected, obj.selectionProgress)); obj.updateColor(); } obj.invalidate(); @@ -50,7 +50,7 @@ public class OutlineTextContainerView extends FrameLayout { private float errorProgress; private float strokeWidthRegular = Math.max(2, AndroidUtilities.dp(0.5f)); - private float strokeWidthSelected = AndroidUtilities.dp(1.5f); + private float strokeWidthSelected = AndroidUtilities.dp(1.6667f); private EditText attachedEditText; private boolean forceUseCenter; @@ -157,7 +157,7 @@ protected void onDraw(Canvas canvas) { rect.set(getPaddingLeft() + AndroidUtilities.dp(PADDING_LEFT - PADDING_TEXT), getPaddingTop(), getWidth() - AndroidUtilities.dp(PADDING_LEFT + PADDING_TEXT) - getPaddingRight(), getPaddingTop() + stroke * 2); canvas.clipRect(rect, Region.Op.DIFFERENCE); rect.set(getPaddingLeft() + stroke, getPaddingTop() + stroke, getWidth() - stroke - getPaddingRight(), getHeight() - stroke - getPaddingBottom()); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), outlinePaint); + canvas.drawRoundRect(rect, AndroidUtilities.dp(8), AndroidUtilities.dp(8), outlinePaint); canvas.restore(); float left = getPaddingLeft() + AndroidUtilities.dp(PADDING_LEFT - PADDING_TEXT), lineY = getPaddingTop() + stroke, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java index 9014622347..0db67b3113 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Input.java @@ -74,7 +74,7 @@ public void setMatrix(Matrix m) { private ValueAnimator fillAnimator; private void fill(Brush brush, boolean registerUndo, Runnable onDone) { - if (!canFill || lastLocation == null) { + if (!canFill || renderView.getPainting().masking || lastLocation == null) { return; } @@ -245,11 +245,13 @@ public void process(MotionEvent event, float scale) { } points[pointsCount] = location; - if ((System.currentTimeMillis() - drawingStart) > 3000) { - detector.clear(); - renderView.getPainting().setHelperShape(null); - } else if (renderView.getCurrentBrush() instanceof Brush.Radial || renderView.getCurrentBrush() instanceof Brush.Elliptical) { - detector.append(location.x, location.y, distance > AndroidUtilities.dp(6) / scale); + if (renderView.getPainting() == null || !renderView.getPainting().masking) { + if ((System.currentTimeMillis() - drawingStart) > 3000) { + detector.clear(); + renderView.getPainting().setHelperShape(null); + } else if (renderView.getCurrentBrush() instanceof Brush.Radial || renderView.getCurrentBrush() instanceof Brush.Elliptical) { + detector.append(location.x, location.y, distance > AndroidUtilities.dp(6) / scale); + } } pointsCount++; realPointsCount++; @@ -337,9 +339,7 @@ public void process(MotionEvent event, float scale) { arrowAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (!renderView.getCurrentBrush().isEraser() || renderView.getUndoStore().canUndo()) { - renderView.getPainting().commitPath(null, renderView.getCurrentColor()); - } + renderView.getPainting().commitPath(null, renderView.getCurrentColor()); arrowAnimator = null; } }); @@ -349,7 +349,7 @@ public void onAnimationEnd(Animator animation) { } } - if (commit && (!renderView.getCurrentBrush().isEraser() || renderView.getUndoStore().canUndo())) { + if (commit) { renderView.getPainting().commitPath(null, renderView.getCurrentColor(), true, () -> { if (switchedBrushByStylusFrom != null) { renderView.selectBrush(switchedBrushByStylusFrom); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java new file mode 100644 index 0000000000..04d9d46e56 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ObjectDetectionEmojis.java @@ -0,0 +1,459 @@ +package org.telegram.ui.Components.Paint; +public class ObjectDetectionEmojis { + private static String[] labelEmojis; + public static String labelToEmoji(int labelId) { + if (labelEmojis == null) { + labelEmojis = new String[] { + "👥", // Team + "🔥", // Bonfire + "📚", // Comics + "🏔", // Himalayan + "🧊", // Iceberg + "🍱", // Bento + null, + "🚰", // Sink + "🧸", // Toy + "🗿", // Statue + "🍔", // Cheeseburger + "🚜", // Tractor + "🛷", // Sled + "🐠", // Aquarium + "🎪", // Circus + null, + "🪑", // Sitting + "🧔", // Beard + "🌉", // Bridge + "🩰", // Tights + "🐦", // Bird + "🚣", // Rafting + "🏞", // Park + null, + "🏭", // Factory + "🎓", // Graduation + "🍶", // Porcelain + "🌿", // Twig + "🌸", // Petal + "🛋", // Cushion + "😎", // Sunglasses + "🏗", // Infrastructure + "🎡", // Ferris wheel + "🐠", // Pomacentridae + "🤿", // Wetsuit + "🐶", // Shetland Sheepdog + "⛵", // Brig + "🎨", // Watercolor Paint + "🏆", // Competition + "🧗", // Cliff + "🏸", // Badminton + "🦁", // Safari + "🚲", // Bicycle + "🏟", // Stadium + null, + "⛵", // Boat + "🙂", // Smile + "🏄", // Surfboard + "🍟", // Fast Food + "🌇", // Sunset + "🌭", // Hot Dog + "🩳", // Shorts + "🚌", // Bus + "🐂", // Bullfighting + "🌌", // Sky + "🐹", // Gerbil + "🪨", // Rock + "👥", // Interaction + "👗", // Dress + "👣", // Toe + null, + "🐻", // Bear + "🍽", // Eating + "🗼", // Tower + "🧱", // Brick + "🗑", // Junk + "👤", // Person + "🏄", // Windsurfing + "👙", // Swimwear + "🎢", // Roller + "🏕", // Camping + "🎠", // Playground + "🚽", // Bathroom + "😆", // Laugh + "🎈", // Balloon + "🎤", // Concert + "👗", // Prom + "🚧", // Construction + "📦", // Product + "🐠", // Reef + "🧺", // Picnic + "🌼", // Wreath + "🛒", // Wheelbarrow + "🥊", // Boxer + "💍", // Necklace + "💎", // Bracelet + "🎰", // Casino + "🚗", // Windshield + "🪜", // Stairs + "💻", // Computer + "🍳", // Cookware and Bakeware + "📽️", // Monochrome + "🪑", // Chair + "🖼", // Poster + "🍷", // Bar + "🚢", // Shipwreck + "🛳", // Pier + "👥", // Community + "🧗", // Caving + "🕳", // Cave + "👔", // Tie + "🛠", // Cabinetry + "🌊", // Underwater + "🤡", // Clown + "🎉", // Nightclub + "🚴", // Cycling + "☄️", // Comet + "🎓", // Mortarboard + "🏟", // Track + "🎄", // Christmas + "⛪", // Church + "🕰", // Clock + "👨", // Dude + "🐄", // Cattle + "🌴", // Jungle + "🖥", // Desk + "🥌", // Curling + "🍲", // Cuisine + "🐱", // Cat + "🧃", // Juice + "🍚", // Couscous + null, // "📸", // Screenshot + "👥", // Crew + "🏙", // Skyline + null, + "🧸", // Stuffed Toy + "🍪", // Cookie + "🟩", // Tile + "🕎", // Hanukkah + "🧶", // Crochet + "🛹", // Skateboarder + "✂️", // Clipper + "💅", // Nail + "🥤", // Cola + "🍴", // Cutlery + "📜", // Menu + null, + "👘", // Sari + "🧸", // Plush + "📱", // Pocket + "🚦", // Neon + "❄️", // Icicle + "🇵🇷", // Pasteles + "⛓", // Chain + "💃", // Dance + "🏜", // Dune + "🎅", // Santa Claus + "🦃", // Thanksgiving + "🤵", // Tuxedo + "👄", // Mouth + "🏜", // Desert + "🦕", // Dinosaur + "👳‍♂️", // Mufti + "🔥", // Fire + "🛏", // Bedroom + "🥽", // Goggles + "🐉", // Dragon + "🛋", // Couch + "🛷", // Sledding + "🧢", // Cap + "📋", // Whiteboard + "🎩", // Hat + "🍨", // Gelato + "🐎", // Cavalier + "🧶", // Beanie + "👕", // Jersey + "🧣", // Scarf + "🏖", // Vacation + "⚽", // Pitch + "🖤", // Blackboard + "🎧", // Deejay + "🏛", // Monument + "🚘", // Bumper + "🛹", // Longboard + "🦢", // Waterfowl + "🍖", // Flesh + "🥅", // Net + "🧁", // Icing + "🐕", // Dalmatian + "🚤", // Speedboat + "🌳", // Trunk + "☕", // Coffee + "⚽", // Soccer + "🧸", // Ragdoll + "🍲", // Food + "🧍", // Standing + "📖", // Fiction + "🍉", // Fruit + "🍜", // Pho + "✨", // Sparkler + "💼", // Presentation + "🌳", // Swing + "🐕", // Cairn Terrier + "🌲", // Forest + "🚩", // Flag + "⛵", // Frigate + "🦶", // Foot + "🧥", // Jacket + null, + "🛏", // Pillow + null, + "🛁", // Bathing + "🗻", // Glacier + "🤸‍♀️", // Gymnastics + "👂", // Ear + "🌸", // Flora + "🐚", // Shell + "👵", // Grandparent + "🏛", // Ruins + "👁️", // Eyelash + "🛏", // Bunk Bed + "⚖️", // Balance + "🎒", // Backpacking + "🐎", // Horse + "✨", // Glitter + "🛸", // Saucer + "💇", // Hair + "🧸", // Miniature + "👥", // Crowd + "🪟", // Curtain + "🌟", // Icon + "🐱", // Pixie-bob + "🐄", // Herd + "🐞", // Insect + "❄️", // Ice + "💍", // Bangle + "🚪", // Flap + "💎", // Jewellery + "🧶", // Knitting + "🏺", // Centrepiece + "🧥", // Outerwear + "❤️", // Love + "💪", // Muscle + "🏍", // Motorcycle + "💰", // Money + "🕌", // Mosque + "🍽", // Tableware + "💃", // Ballroom + "🛶", // Kayak + "🏖", // Leisure + "🧾", // Receipt + "🏞", // Lake + "🚨", // Lighthouse + "🐴", // Bridle + "🧥", // Leather + "📯", // Horn + "⌚", // Strap + "🧱", // Lego + "🤿", // Scuba Diving + "👖", // Leggings + "🏊", // Pool + "🎸", // Musical Instrument + "🎭", // Musical + "🤘", // Metal + "🌕", // Moon + "🧥", // Blazer + "💍", // Marriage + "📱", // Mobile Phone + "🪖", // Militia + "🍽", // Tablecloth + "🎉", // Party + "🌌", // Nebula + "📰", // News + "🗞", // Newspaper + null, + "🎹", // Piano + "🪴", // Plant + "🛂", // Passport + "🐧", // Penguin + "🐕", // Shikoku + "🏰", // Palace + "🏵", // Doily + "🏇", // Polo + "📝", // Paper + "🎶", // Pop Music + "⛵", // Skiff + "🍕", // Pizza + "🐾", // Pet + "🧵", // Quilting + "🐦", // Cage + "🛹", // Skateboard + "🏄", // Surfing + "🏉", // Rugby + "💄", // Lipstick + "🏞", // River + "🏁", // Race + "🚣", // Rowing + "🛣", // Road + "🏃", // Running + "🛋", // Room + "🏠", // Roof + "⭐", // Star + "🏅", // Sports + "👟", // Shoe + "🚤", // Tubing + "🪐", // Space + "😴", // Sleep + "🤲", // Skin + "🏊", // Swimming + "🏫", // School + "🍣", // Sushi + "🛋", // Loveseat + "🦸", // Superman + "😎", // Cool + "⛷", // Skiing + "🚢", // Submarine + "🎵", // Song + "📚", // Class + "🏙", // Skyscraper + "🌋", // Volcano + "📺", // Television + "🐎", // Rein + "💉", // Tattoo + "🚆", // Train + "🚪", // Handrail + "🥤", // Cup + "🚗", // Vehicle + "👜", // Handbag + "💡", // Lampshade + "🎫", // Event + "🍷", // Wine + "🍗", // Wing + "🎡", // Wheel + "🏄", // Wakeboarding + "💻", // Web Page + null, + null, + "🏡", // Ranch + "🎣", // Fishing + "❤️", // Heart + "🌱", // Cotton + "☕", // Cappuccino + "🍞", // Bread + "🏖", // Sand + null, + "🏛", // Museum + "🚁", // Helicopter + "⛰", // Mountain + "🦆", // Duck + "🌱", // Soil + "🐢", // Turtle + "🐊", // Crocodile + "🎶", // Musician + "👟", // Sneakers + "🧶", // Wool + "💍", // Ring + "🎤", // Singer + "🎡", // Carnival + "🏂", // Snowboarding + "🚤", // Waterskiing + "🧱", // Wall + "🚀", // Rocket + "🏠", // Countertop + "🏖", // Beach + "🌈", // Rainbow + "🌿", // Branch + "👨", // Moustache + "🌷", // Garden + "👗", // Gown + "🏞", // Field + "🐶", // Dog + "🦸", // Superhero + "🌸", // Flower + "🍽", // Placemat + "🔊", // Subwoofer + "⛪", // Cathedral + "🏢", // Building + "✈️", // Airplane + "🐾", // Fur + "🐂", // Bull + "🪑", // Bench + "🛕", // Temple + "🦋", // Butterfly + "👠", // Model + "🏃", // Marathon + "🪡", // Needlework + "🍳", // Kitchen + "🏰", // Castle + "🌌", // Aurora + "🐛", // Larva + "🏎", // Racing + null, + "✈️", // Airliner + "🚣", // Dam + "🧵", // Textile + "🤵", // Groom + "🎢", // Fun + "🍲", // Steaming + "🥦", // Vegetable + "🚲", // Unicycle + "👖", // Jeans + "🪴", // Flowerpot + "🗄", // Drawer + "🎂", // Cake + "💺", // Armrest + "✈️", // Aviation + null, + "🌫", // Fog + "🎆", // Fireworks + "🚜", // Farm + "🦭", // Seal + "📚", // Shelf + "💇", // Bangs + "⚡", // Lightning + "🚐", // Van + "🐱", // Sphynx + "🚗", // Tire + "👖", // Denim + "🌾", // Prairie + "🤿", // Snorkeling + "☔", // Umbrella + "🛣", // Asphalt + "⛵", // Sailboat + "🐶", // Basset Hound + "🔳", // Pattern + "🍽", // Supper + "👰", // Veil + "💧", // Waterfall + null, + "🍴", // Lunch + "🚙", // Odometer + "👶", // Baby + "👓", // Glasses + "🚗", // Car + "✈️", // Aircraft + "✋", // Hand + "🐎", // Rodeo + "🏞", // Canyon + "🍽", // Meal + "⚾", // Softball + "🍷", // Alcohol + "👰", // Bride + "🌿", // Swamp + "🥧", // Pie + "🎒", // Bag + "🃏", // Joker + "🦹", // Supervillain + "🪖", // Army + "🛶", // Canoe + "🤳", // Selfie + "🛺", // Rickshaw + "🏚", // Barn + "🏹", // Archery + "🚀", // Aerospace Engineering + null, + "⛈", // Storm + "⛑", // Helmet + }; + } + if (labelId < 0 || labelId >= labelEmojis.length) return null; + return labelEmojis[labelId]; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java index 666c3b1032..0747177f2a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java @@ -59,6 +59,7 @@ public static class PaintingData { private Brush brush; private HashMap brushTextures = new HashMap<>(); private Texture bitmapTexture; + private Texture originalBitmapTexture; private ByteBuffer vertexBuffer; private ByteBuffer textureBuffer; private int reusableFramebuffer; @@ -126,6 +127,13 @@ public Painting(Size sz, Bitmap originalBitmap, int originalRotation, BlurringSh } } + public boolean masking = false; + + public Painting asMask() { + this.masking = true; + return this; + } + public void setDelegate(PaintingDelegate paintingDelegate) { delegate = paintingDelegate; } @@ -167,6 +175,9 @@ public void setBitmap(Bitmap bitmap, Bitmap blurBitmap) { if (bitmapBlurTexture == null) { bitmapBlurTexture = new Texture(blurBitmap); } + if (masking && originalBitmapTexture == null) { + originalBitmapTexture = new Texture(imageBitmap); + } } private boolean helperShown; @@ -855,7 +866,8 @@ private void renderBlitPath(int mask, Path path, float alpha) { brush = this.brush; } - Shader shader = shaders.get(brush.getShaderName(Brush.PAINT_TYPE_BLIT)); + final boolean masking = this.masking && (brush instanceof Brush.Radial || brush instanceof Brush.Eraser); + Shader shader = shaders.get(brush.getShaderName(Brush.PAINT_TYPE_BLIT) + (masking ? "_masking" : "")); if (shader == null) { return; } @@ -875,6 +887,14 @@ private void renderBlitPath(int mask, Path path, float alpha) { GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mask); + if (masking) { + GLES20.glUniform1i(shader.getUniform("otexture"), 2); + GLES20.glUniform1f(shader.getUniform("preview"), 0.4f); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE2); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } + Object lock = null; if (brush instanceof Brush.Blurer) { GLES20.glUniform1i(shader.getUniform("blured"), 2); @@ -886,7 +906,7 @@ private void renderBlitPath(int mask, Path path, float alpha) { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, bluredTexture.texture()); } } - + GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glVertexAttribPointer(0, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); @@ -906,7 +926,7 @@ private void renderBlitPath(int mask, Path path, float alpha) { } private void renderBlit(int texture, float alpha) { - Shader shader = shaders.get("blit"); + Shader shader = shaders.get(masking ? "maskingBlit" : "blit"); if (texture == 0 || shader == null) { return; } @@ -914,11 +934,24 @@ private void renderBlit(int texture, float alpha) { GLES20.glUseProgram(shader.program); GLES20.glUniformMatrix4fv(shader.getUniform("mvpMatrix"), 1, false, FloatBuffer.wrap(renderProjection)); - GLES20.glUniform1i(shader.getUniform("texture"), 0); GLES20.glUniform1f(shader.getUniform("alpha"), alpha); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + if (masking) { + GLES20.glUniform1i(shader.getUniform("texture"), 1); + GLES20.glUniform1i(shader.getUniform("mask"), 0); + GLES20.glUniform1f(shader.getUniform("preview"), 0.4f); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } else { + GLES20.glUniform1i(shader.getUniform("texture"), 0); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture); + } GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); @@ -963,7 +996,7 @@ public PaintingData getPaintingData(RectF rect, boolean undo, boolean onlyBlur, if (shaders == null) { return null; } - Shader shader = shaders.get(undo ? "nonPremultipliedBlit" : "blit"); + Shader shader = shaders.get(undo ? "nonPremultipliedBlit" : (masking ? "maskingBlit" : "blit")); if (shader == null) { return null; } @@ -976,10 +1009,22 @@ public PaintingData getPaintingData(RectF rect, boolean undo, boolean onlyBlur, GLES20.glUniformMatrix4fv(shader.getUniform("mvpMatrix"), 1, false, FloatBuffer.wrap(finalProjection)); - GLES20.glUniform1i(shader.getUniform("texture"), 0); + if (!undo && masking) { + GLES20.glUniform1i(shader.getUniform("texture"), 1); + GLES20.glUniform1i(shader.getUniform("mask"), 0); + GLES20.glUniform1f(shader.getUniform("preview"), 0); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, originalBitmapTexture.texture()); + } else { + GLES20.glUniform1i(shader.getUniform("texture"), 0); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, onlyBlur && bitmapBlurTexture != null ? bitmapBlurTexture.texture() : getTexture()); + } GLES20.glClearColor(0, 0, 0, 0); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); @@ -1160,6 +1205,9 @@ public void cleanResources(boolean recycle) { if (bluredTexture != null) { bluredTexture.cleanResources(true); } + if (originalBitmapTexture != null) { + originalBitmapTexture.cleanResources(true); + } if (shaders != null) { for (Shader shader : shaders.values()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java index 1a19004364..e2de81b3e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java @@ -55,24 +55,47 @@ public class ShaderSet { "precision highp float;" + "varying vec2 varTexcoord;" + "uniform sampler2D texture;" + -// "uniform float alpha;" + "void main (void) {" + " gl_FragColor = texture2D(texture, varTexcoord.st, 0.0);" + -// " gl_FragColor.a *= alpha;" + + " gl_FragColor.rgb *= gl_FragColor.a;" + + "}"; + private static final String PAINT_MASKING_BLIT_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D mask;" + + "uniform float preview;" + + "void main (void) {" + + " gl_FragColor = texture2D(texture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * texture2D(mask, varTexcoord.st, 0.0).a);" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; private static final String PAINT_BLITWITHMASK_FSH = "precision highp float;" + "varying vec2 varTexcoord;" + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + "uniform sampler2D mask;" + "uniform vec4 color;" + "void main (void) {" + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + - " gl_FragColor.rgb = (color.rgb * srcAlpha + dst.rgb * dst.a * (1.0 - srcAlpha)) / outAlpha;" + + " gl_FragColor.rgb = (color.rgb * srcAlpha + dst.rgb * dst.a * (1.0 - srcAlpha));" + " gl_FragColor.a = outAlpha;" + + "}"; + private static final String PAINT_MASKING_BLITWITHMASK_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + + "uniform sampler2D mask;" + + "uniform vec4 color;" + + "uniform float preview;" + + "void main (void) {" + + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + + " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + + " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; private static final String PAINT_COMPOSITEWITHMASK_FSH = @@ -161,6 +184,37 @@ public class ShaderSet { " gl_FragColor.a = outAlpha;" + " gl_FragColor.rgb *= gl_FragColor.a;" + "}"; + private static final String PAINT_MASKING_BLITWITHMASKERASER_FSH = + "precision highp float;" + + "varying vec2 varTexcoord;" + + "uniform sampler2D texture;" + + "uniform sampler2D otexture;" + + "uniform sampler2D mask;" + + "uniform vec4 color;" + + "uniform float preview;" + + "void main (void) {" + + " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + + " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + + " float outAlpha = dst.a * (1. - srcAlpha);" + + " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + + " gl_FragColor.rgb *= gl_FragColor.a;" + + "}"; +// +// +// "precision highp float;" + +// "varying vec2 varTexcoord;" + +// "uniform sampler2D texture;" + +// "uniform sampler2D otexture;" + +// "uniform sampler2D mask;" + +// "uniform vec4 color;" + +// "uniform float preview;" + +// "void main (void) {" + +// " vec4 dst = texture2D(texture, varTexcoord.st, 0.0);" + +// " float srcAlpha = color.a * texture2D(mask, varTexcoord.st, 0.0).a;" + +// " float outAlpha = srcAlpha + dst.a * (1.0 - srcAlpha);" + +// " gl_FragColor = texture2D(otexture, varTexcoord.st, 0.0) * (preview + (1.0 - preview) * outAlpha);" + +// " gl_FragColor.rgb *= gl_FragColor.a;" + +// "}"; private static final String PAINT_COMPOSITEWITHMASKERASER_FSH = "precision highp float;" + "varying vec2 varTexcoord;" + @@ -344,6 +398,13 @@ private static Map> createMap() { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "alpha"}); result.put("blit", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLIT_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "alpha", "preview"}); + result.put("maskingBlit", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_BLITWITHMASK_FSH); @@ -351,6 +412,13 @@ private static Map> createMap() { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "color"}); result.put("blitWithMask", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLITWITHMASK_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "otexture", "texture", "mask", "color", "preview"}); + result.put("blitWithMask_masking", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_COMPOSITEWITHMASK_FSH); @@ -410,6 +478,13 @@ private static Map> createMap() { shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "mask", "color"}); result.put("blitWithMaskEraser", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); + shader.put(VERTEX, PAINT_BLIT_VSH); + shader.put(FRAGMENT, PAINT_MASKING_BLITWITHMASKERASER_FSH); + shader.put(ATTRIBUTES, new String[]{"inPosition", "inTexcoord"}); + shader.put(UNIFORMS, new String[]{"mvpMatrix", "texture", "otexture", "preview", "mask", "color"}); + result.put("blitWithMaskEraser_masking", Collections.unmodifiableMap(shader)); + shader = new HashMap<>(); shader.put(VERTEX, PAINT_BLIT_VSH); shader.put(FRAGMENT, PAINT_COMPOSITEWITHMASKERASER_FSH); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java index 3af3afc32c..a679024517 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Swatch.java @@ -11,4 +11,8 @@ public Swatch(int color, float colorLocation, float brushWeight) { this.colorLocation = colorLocation; this.brushWeight = brushWeight; } + + public Swatch clone() { + return new Swatch(color, colorLocation, brushWeight); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java index 15b35a048a..d584fba2c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntitiesContainerView.java @@ -2,6 +2,7 @@ import android.content.Context; import android.graphics.Canvas; +import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java index 315825bf14..343435bbe9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EntityView.java @@ -190,7 +190,7 @@ private boolean onTouchMove(float x1, float y1, boolean multitouch, float x2, fl scale(d / pd); } double angleDiff = Math.atan2(y1 - y2, x1 - x2) - Math.atan2(previousLocationY - previousLocationY2, previousLocationX - previousLocationX2); - rotate(this.angle + (float) Math.toDegrees(angleDiff) - delegate.getCropRotation()); + rotate(this.angle + (float) Math.toDegrees(angleDiff)); } previousLocationX = x1; @@ -939,7 +939,7 @@ public boolean onTouchEvent(MotionEvent event) { angle = (float) Math.atan2(y - pos[1], x - pos[0]); } - rotate((float) Math.toDegrees(angle) - delegate.getCropRotation()); + rotate((float) Math.toDegrees(angle)); previousLocationX = x; previousLocationY = y; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java index 154fad652e..a419ff1139 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java @@ -1,12 +1,13 @@ package org.telegram.ui.Components.Paint.Views; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -16,18 +17,16 @@ import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.SweepGradient; import android.graphics.drawable.GradientDrawable; -import android.location.Address; -import android.location.Geocoder; import android.os.Build; import android.os.Looper; import android.text.Layout; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.TypedValue; @@ -36,6 +35,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import android.view.WindowManager; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; @@ -49,14 +49,12 @@ import androidx.dynamicanimation.animation.SpringForce; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; @@ -68,7 +66,6 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLRPC; -import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; @@ -78,6 +75,7 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -97,16 +95,11 @@ import org.telegram.ui.Components.Size; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto; -import org.telegram.ui.Components.StickerMasksAlert; import org.telegram.ui.Components.ThanosEffect; import org.telegram.ui.PhotoViewer; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; -import org.telegram.ui.Stories.recorder.PaintView; -import org.telegram.ui.ThemePreviewActivity; -import org.telegram.ui.WallpapersListActivity; import java.io.File; -import java.io.FileOutputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; @@ -247,8 +240,6 @@ public LPhotoPaintView(Context context, Activity activity, int currentAccount, B return -9539985; } else if (key == Theme.key_chat_emojiPanelIcon) { return -9539985; -// } else if (key == Theme.key_chat_emojiPanelIconSelected) { -// return -10177041; } else if (key == Theme.key_windowBackgroundWhiteBlackText) { return -1; } else if (key == Theme.key_featuredStickers_addedIcon) { @@ -269,6 +260,16 @@ public LPhotoPaintView(Context context, Activity activity, int currentAccount, B return 0x2E878787; } else if (key == Theme.key_windowBackgroundGray) { return 0xFF0D0D0D; + } else if (key == Theme.key_fastScrollInactive) { + return -12500671; + } else if (key == Theme.key_fastScrollActive) { + return -13133079; + } else if (key == Theme.key_fastScrollText) { + return 0xffffffff; + } else if (key == Theme.key_windowBackgroundWhite) { + return -15198183; + } else if (key == Theme.key_divider) { + return 0xFF000000; } if (resourcesProvider != null) { @@ -401,7 +402,7 @@ public void onEntityDeselect() { { setWillNotDraw(false); - linePaint.setStrokeWidth(AndroidUtilities.dp(2)); + linePaint.setStrokeWidth(dp(2)); linePaint.setStyle(Paint.Style.STROKE); linePaint.setColor(Color.WHITE); } @@ -523,13 +524,13 @@ public boolean onTouchEvent(MotionEvent event) { addView(selectionContainerView); topLayout = new FrameLayout(context); - topLayout.setPadding(AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12)); - topLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int [] {0xff000000, 0x00000000} )); + topLayout.setPadding(dp(12), dp(12), dp(12), dp(12)); + topLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{0xff000000, 0x00000000})); addView(topLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); undoButton = new ImageView(context); undoButton.setImageResource(R.drawable.photo_undo2); - undoButton.setPadding(AndroidUtilities.dp(3), AndroidUtilities.dp(3), AndroidUtilities.dp(3), AndroidUtilities.dp(3)); + undoButton.setPadding(dp(3), dp(3), dp(3), dp(3)); undoButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); undoButton.setOnClickListener(v -> { if (renderView != null && renderView.getCurrentBrush() instanceof Brush.Shape) { @@ -547,7 +548,7 @@ public boolean onTouchEvent(MotionEvent event) { zoomOutButton = new LinearLayout(context); zoomOutButton.setOrientation(LinearLayout.HORIZONTAL); zoomOutButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - zoomOutButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + zoomOutButton.setPadding(dp(8), 0, dp(8), 0); zoomOutText = new TextView(context); zoomOutText.setTextColor(Color.WHITE); zoomOutText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -565,7 +566,7 @@ public boolean onTouchEvent(MotionEvent event) { undoAllButton = new TextView(context); undoAllButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - undoAllButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + undoAllButton.setPadding(dp(8), 0, dp(8), 0); undoAllButton.setText(LocaleController.getString(R.string.PhotoEditorClearAll)); undoAllButton.setGravity(Gravity.CENTER_VERTICAL); undoAllButton.setTextColor(Color.WHITE); @@ -590,7 +591,7 @@ public boolean onTouchEvent(MotionEvent event) { cancelTextButton = new TextView(context); cancelTextButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); cancelTextButton.setText(LocaleController.getString(R.string.Clear)); - cancelTextButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + cancelTextButton.setPadding(dp(8), 0, dp(8), 0); cancelTextButton.setGravity(Gravity.CENTER_VERTICAL); cancelTextButton.setTextColor(Color.WHITE); cancelTextButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -612,7 +613,7 @@ public boolean onTouchEvent(MotionEvent event) { doneTextButton = new TextView(context); doneTextButton.setBackground(Theme.createSelectorDrawable(0x30ffffff, Theme.RIPPLE_MASK_ROUNDRECT_6DP)); doneTextButton.setText(LocaleController.getString(R.string.Done)); - doneTextButton.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + doneTextButton.setPadding(dp(8), 0, dp(8), 0); doneTextButton.setGravity(Gravity.CENTER_VERTICAL); doneTextButton.setTextColor(Color.WHITE); doneTextButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); @@ -631,7 +632,7 @@ public boolean onTouchEvent(MotionEvent event) { { setWillNotDraw(false); colorPickerRainbowPaint.setStyle(Paint.Style.STROKE); - colorPickerRainbowPaint.setStrokeWidth(AndroidUtilities.dp(2)); + colorPickerRainbowPaint.setStrokeWidth(dp(2)); } private void checkRainbow(float cx, float cy) { @@ -667,12 +668,12 @@ protected void onDraw(Canvas canvas) { ViewGroup barView = getBarView(); AndroidUtilities.rectTmp.set( - AndroidUtilities.lerp(barView.getLeft(), colorsListView.getLeft(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getTop(), colorsListView.getTop(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getRight(), colorsListView.getRight(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getBottom(), colorsListView.getBottom(), toolsTransformProgress) + AndroidUtilities.lerp(barView.getLeft(), colorsListView.getLeft(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getTop(), colorsListView.getTop(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getRight(), colorsListView.getRight(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getBottom(), colorsListView.getBottom(), toolsTransformProgress) ); - final float radius = AndroidUtilities.lerp(AndroidUtilities.dp(32), AndroidUtilities.dp(24), toolsTransformProgress); + final float radius = AndroidUtilities.lerp(dp(32), dp(24), toolsTransformProgress); canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, toolsPaint); if (barView != null && barView.getChildCount() >= 1 && toolsTransformProgress != 1f) { @@ -711,10 +712,10 @@ protected void onDraw(Canvas canvas) { } checkRainbow(cx, cy); - float rad = Math.min(childWidth, childHeight) / 2f - AndroidUtilities.dp(0.5f); + float rad = Math.min(childWidth, childHeight) / 2f - dp(0.5f); if (colorsListView != null && colorsListView.getChildCount() > 0) { View animateToView = colorsListView.getChildAt(0); - rad = AndroidUtilities.lerp(rad, Math.min(animateToView.getWidth() - animateToView.getPaddingLeft() - animateToView.getPaddingRight(), animateToView.getHeight() - animateToView.getPaddingTop() - animateToView.getPaddingBottom()) / 2f - AndroidUtilities.dp(2f), toolsTransformProgress); + rad = AndroidUtilities.lerp(rad, Math.min(animateToView.getWidth() - animateToView.getPaddingLeft() - animateToView.getPaddingRight(), animateToView.getHeight() - animateToView.getPaddingTop() - animateToView.getPaddingBottom()) / 2f - dp(2f), toolsTransformProgress); } AndroidUtilities.rectTmp.set(cx - rad, cy - rad, cx + rad, cy + rad); canvas.drawArc(AndroidUtilities.rectTmp, 0, 360, false, colorPickerRainbowPaint); @@ -724,15 +725,15 @@ protected void onDraw(Canvas canvas) { colorSwatchOutlinePaint.setColor(colorCircle); colorSwatchOutlinePaint.setAlpha((int) (0xFF * child.getAlpha())); - float rad2 = rad - AndroidUtilities.dp(3f); + float rad2 = rad - dp(3f); if (colorsListView != null && colorsListView.getSelectedColorIndex() != 0) { - rad2 = AndroidUtilities.lerp(rad - AndroidUtilities.dp(3f), rad + AndroidUtilities.dp(2), toolsTransformProgress); + rad2 = AndroidUtilities.lerp(rad - dp(3f), rad + dp(2), toolsTransformProgress); } PaintColorsListView.drawColorCircle(canvas, cx, cy, rad2, colorSwatchPaint.getColor()); if (colorsListView != null && colorsListView.getSelectedColorIndex() == 0) { colorSwatchOutlinePaint.setAlpha((int) (colorSwatchOutlinePaint.getAlpha() * toolsTransformProgress * child.getAlpha())); - canvas.drawCircle(cx, cy, rad - (AndroidUtilities.dp(3f) + colorSwatchOutlinePaint.getStrokeWidth()) * (1f - toolsTransformProgress), colorSwatchOutlinePaint); + canvas.drawCircle(cx, cy, rad - (dp(3f) + colorSwatchOutlinePaint.getStrokeWidth()) * (1f - toolsTransformProgress), colorSwatchOutlinePaint); } } @@ -740,19 +741,19 @@ protected void onDraw(Canvas canvas) { } } }; - bottomLayout.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), 0); - bottomLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int [] {0x00000000, 0x80000000} )); + bottomLayout.setPadding(dp(8), dp(8), dp(8), 0); + bottomLayout.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{0x00000000, 0x80000000})); addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44 + 60, Gravity.BOTTOM)); paintToolsView = new PaintToolsView(context, originalBitmap != null); - paintToolsView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + paintToolsView.setPadding(dp(16), 0, dp(16), 0); paintToolsView.setDelegate(this); // paintToolsView.setSelectedIndex(MathUtils.clamp(palette.getCurrentBrush(), 0, Brush.BRUSHES_LIST.size()) + 1); paintToolsView.setSelectedIndex(1); bottomLayout.addView(paintToolsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); textOptionsView = new PaintTextOptionsView(context); - textOptionsView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + textOptionsView.setPadding(dp(16), 0, dp(16), 0); textOptionsView.setVisibility(GONE); textOptionsView.setDelegate(this); textOptionsView.setAlignment(PersistColorPalette.getInstance(currentAccount).getCurrentAlignment()); @@ -784,7 +785,7 @@ protected void onDraw(Canvas canvas) { AndroidUtilities.lerp(yOffset + AndroidUtilities.rectTmp.top, typefaceListView.getTop() - typefaceListView.getTranslationY(), typefaceMenuTransformProgress), AndroidUtilities.lerp(AndroidUtilities.rectTmp.right, typefaceListView.getRight(), typefaceMenuTransformProgress), AndroidUtilities.lerp(yOffset + AndroidUtilities.rectTmp.bottom, typefaceListView.getBottom() - typefaceListView.getTranslationY(), typefaceMenuTransformProgress)); - float rad = AndroidUtilities.dp(AndroidUtilities.lerp(32, 16, typefaceMenuTransformProgress)); + float rad = dp(AndroidUtilities.lerp(32, 16, typefaceMenuTransformProgress)); int alpha = typefaceMenuBackgroundPaint.getAlpha(); typefaceMenuBackgroundPaint.setAlpha((int) (alpha * typefaceMenuTransformProgress)); @@ -809,7 +810,7 @@ protected void onDraw(Canvas canvas) { typefaceMenuOutlinePaint.setStyle(Paint.Style.STROKE); typefaceMenuOutlinePaint.setColor(0x66FFFFFF); - typefaceMenuOutlinePaint.setStrokeWidth(Math.max(2, AndroidUtilities.dp(1))); + typefaceMenuOutlinePaint.setStrokeWidth(Math.max(2, dp(1))); typefaceMenuBackgroundPaint.setColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); @@ -820,14 +821,14 @@ protected void onDraw(Canvas canvas) { public void draw(Canvas c) { ViewGroup barView = getBarView(); AndroidUtilities.rectTmp.set( - AndroidUtilities.lerp(barView.getLeft() - getLeft(), 0, toolsTransformProgress), - AndroidUtilities.lerp(barView.getTop() - getTop(), 0, toolsTransformProgress), - AndroidUtilities.lerp(barView.getRight() - getLeft(), getWidth(), toolsTransformProgress), - AndroidUtilities.lerp(barView.getBottom() - getTop(), getHeight(), toolsTransformProgress) + AndroidUtilities.lerp(barView.getLeft() - getLeft(), 0, toolsTransformProgress), + AndroidUtilities.lerp(barView.getTop() - getTop(), 0, toolsTransformProgress), + AndroidUtilities.lerp(barView.getRight() - getLeft(), getWidth(), toolsTransformProgress), + AndroidUtilities.lerp(barView.getBottom() - getTop(), getHeight(), toolsTransformProgress) ); path.rewind(); - path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(32), AndroidUtilities.dp(32), Path.Direction.CW); + path.addRoundRect(AndroidUtilities.rectTmp, dp(32), dp(32), Path.Direction.CW); c.save(); c.clipPath(path); @@ -846,12 +847,12 @@ public void draw(Canvas c) { setupTabsLayout(context); cancelButton = new PaintCancelView(context); - cancelButton.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + cancelButton.setPadding(dp(8), dp(8), dp(8), dp(8)); cancelButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); bottomLayout.addView(cancelButton, LayoutHelper.createFrame(32, 32, Gravity.BOTTOM | Gravity.LEFT, 12, 0, 0, 4)); doneButton = new PaintDoneView(context); - doneButton.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + doneButton.setPadding(dp(8), dp(8), dp(8), dp(8)); doneButton.setBackground(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); doneButton.setOnClickListener(v -> { if (isColorListShown) { @@ -930,7 +931,7 @@ public void onColorSelected(int color) { weightChooserView.setRenderView(renderView); weightChooserView.setValueOverride(weightDefaultValueOverride); colorSwatch.brushWeight = weightDefaultValueOverride.get(); - weightChooserView.setOnUpdate(()-> { + weightChooserView.setOnUpdate(() -> { setCurrentSwatch(colorSwatch, true); PersistColorPalette.getInstance(currentAccount).setCurrentWeight(colorSwatch.brushWeight); }); @@ -940,7 +941,7 @@ public void onColorSelected(int color) { addView(pipetteContainerLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); colorSwatchOutlinePaint.setStyle(Paint.Style.STROKE); - colorSwatchOutlinePaint.setStrokeWidth(AndroidUtilities.dp(2)); + colorSwatchOutlinePaint.setStrokeWidth(dp(2)); setCurrentSwatch(colorSwatch, true); // onBrushSelected(Brush.BRUSHES_LIST.get(MathUtils.clamp(palette.getCurrentBrush(), 0, Brush.BRUSHES_LIST.size()))); @@ -948,10 +949,18 @@ public void onColorSelected(int color) { updateColors(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - setSystemGestureExclusionRects(Arrays.asList(new Rect(0, (int) (AndroidUtilities.displaySize.y * .35f), AndroidUtilities.dp(100), (int) (AndroidUtilities.displaySize.y * .65)))); + setSystemGestureExclusionRects(Arrays.asList(new Rect(0, (int) (AndroidUtilities.displaySize.y * .35f), dp(100), (int) (AndroidUtilities.displaySize.y * .65)))); } } + private boolean drawShadow; + + public void setDrawShadow(boolean drawShadow) { + this.drawShadow = drawShadow; + invalidate(); + setClipChildren(!drawShadow); + } + private void setNewColor(int color) { int wasColor = colorSwatch.color; colorSwatch.color = color; @@ -1180,10 +1189,29 @@ public void set(float val) { return changed; } + private final AnimatedFloat shadowAlpha = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + private final Paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint clearPaint = new Paint(Paint.ANTI_ALIAS_FLAG); { + clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean restore = false; - if ((child == renderView || child == renderInputView || child == entitiesView || child == selectionContainerView) && currentCropState != null) { + if (child == entitiesView) { + float shadowAlpha = this.shadowAlpha.set(LPhotoPaintView.this.drawShadow); + if (shadowAlpha > 0) { + shadowPaint.setShadowLayer(dp(24 * shadowAlpha), 0, 0, Theme.multAlpha(0x40FFFFFF, shadowAlpha)); + shadowPaint.setColor(0); + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + canvas.translate(entitiesView.getX(), entitiesView.getY()); + canvas.scale(entitiesView.getScaleX(), entitiesView.getScaleY(), entitiesView.getWidth() / 2f, entitiesView.getHeight() / 2f); + canvas.drawRect(0, 0, entitiesView.getWidth(), entitiesView.getHeight(), shadowPaint); + canvas.drawRect(0, 0, entitiesView.getWidth(), entitiesView.getHeight(), clearPaint); + canvas.restore(); + } + } + if ((child == renderView || child == renderInputView || child == entitiesView && entitiesView.getClipChildren() || child == selectionContainerView && selectionContainerView.getClipChildren()) && currentCropState != null) { canvas.save(); int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); @@ -1202,7 +1230,7 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { int w = (int) (vw * currentCropState.cropPw * child.getScaleX() / currentCropState.cropScale); int h = (int) (vh * currentCropState.cropPh * child.getScaleY() / currentCropState.cropScale); float x = (float) Math.ceil((getMeasuredWidth() - w) / 2f) + transformX; - float y = (getMeasuredHeight() - emojiPadding - actionBarHeight2 - AndroidUtilities.dp(48) + getAdditionalBottom() - h) / 2f + AndroidUtilities.dp(8) + status + transformY; + float y = (getMeasuredHeight() - emojiPadding - actionBarHeight2 - dp(48) + getAdditionalBottom() - h) / 2f + dp(8) + status + transformY; canvas.clipRect(Math.max(0, x), Math.max(0, y), Math.min(x + w, getMeasuredWidth()), Math.min(getMeasuredHeight(), y + h)); restore = true; @@ -1223,7 +1251,7 @@ private void setupTabsLayout(Context context) { Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); { - linePaint.setStrokeWidth(AndroidUtilities.dp(2)); + linePaint.setStrokeWidth(dp(2)); linePaint.setStyle(Paint.Style.STROKE); linePaint.setStrokeCap(Paint.Cap.ROUND); @@ -1237,7 +1265,7 @@ protected void onDraw(Canvas canvas) { TextView selectedTab = (TextView) getChildAt(tabsSelectedIndex); TextView newSelectedTab = tabsNewSelectedIndex != -1 ? (TextView) getChildAt(tabsNewSelectedIndex) : null; linePaint.setColor(selectedTab.getCurrentTextColor()); - float y = selectedTab.getY() + selectedTab.getHeight() - selectedTab.getPaddingBottom() + AndroidUtilities.dp(3); + float y = selectedTab.getY() + selectedTab.getHeight() - selectedTab.getPaddingBottom() + dp(3); Layout layout = selectedTab.getLayout(); Layout newLayout = newSelectedTab != null ? newSelectedTab.getLayout() : null; float pr = newLayout == null ? 0 : CubicBezierInterpolator.DEFAULT.getInterpolation(tabsSelectionProgress); @@ -1253,7 +1281,7 @@ protected void onDraw(Canvas canvas) { drawTab = new TextView(context); drawTab.setText(LocaleController.getString(R.string.PhotoEditorDraw).toUpperCase()); drawTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - drawTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + drawTab.setPadding(0, dp(8), 0, dp(8)); drawTab.setTextColor(Color.WHITE); drawTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); drawTab.setGravity(Gravity.CENTER_HORIZONTAL); @@ -1271,7 +1299,7 @@ protected void onDraw(Canvas canvas) { stickerTab = new TextView(context); stickerTab.setText(LocaleController.getString(R.string.PhotoEditorSticker).toUpperCase()); stickerTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - stickerTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + stickerTab.setPadding(0, dp(8), 0, dp(8)); stickerTab.setOnClickListener(v -> openStickersView()); stickerTab.setTextColor(Color.WHITE); stickerTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); @@ -1284,7 +1312,7 @@ protected void onDraw(Canvas canvas) { textTab = new TextView(context); textTab.setText(LocaleController.getString(R.string.PhotoEditorText).toUpperCase()); textTab.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP)); - textTab.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + textTab.setPadding(0, dp(8), 0, dp(8)); textTab.setTextColor(Color.WHITE); textTab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textTab.setGravity(Gravity.CENTER_HORIZONTAL); @@ -1341,13 +1369,13 @@ private void switchTab(int index) { float scale = 0.6f + 0.4f * (1f - pr); view.setScaleX(scale); view.setScaleY(scale); - view.setTranslationY(AndroidUtilities.dp(16) * Math.min(pr, 0.25f) / 0.25f); + view.setTranslationY(dp(16) * Math.min(pr, 0.25f) / 0.25f); view.setAlpha(1f - Math.min(pr, 0.25f) / 0.25f); scale = 0.6f + 0.4f * pr; newView.setScaleX(scale); newView.setScaleY(scale); - newView.setTranslationY(-AndroidUtilities.dp(16) * Math.min(1f - pr, 0.25f) / 0.25f); + newView.setTranslationY(-dp(16) * Math.min(1f - pr, 0.25f) / 0.25f); newView.setAlpha(1f - Math.min(1f - pr, 0.25f) / 0.25f); } }); @@ -1395,7 +1423,7 @@ private void openStickersView() { // detectFaces(); // } // }, 350); - EmojiBottomSheet emojiBottomSheet = new EmojiBottomSheet(getContext(), false, resourcesProvider) { + EmojiBottomSheet emojiBottomSheet = new EmojiBottomSheet(getContext(), false, resourcesProvider, false) { @Override public boolean canShowWidget(Integer id) { return id == WIDGET_PHOTO; @@ -1406,6 +1434,7 @@ public boolean canShowWidget(Integer id) { if (isGif) { stickerView.setScale(1.5f); } + return true; }); emojiBottomSheet.whenWidgetSelected(widget -> { if (widget == EmojiBottomSheet.WIDGET_PHOTO) { @@ -1569,13 +1598,13 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { float bitmapW; float bitmapH; int fullHeight = AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - getAdditionalTop() - getAdditionalBottom(); - int maxHeight = fullHeight - AndroidUtilities.dp(48); + int maxHeight = fullHeight - dp(48); if (bitmapToEdit != null) { bitmapW = bitmapToEdit.getWidth(); bitmapH = bitmapToEdit.getHeight(); } else { bitmapW = width; - bitmapH = height - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48); + bitmapH = height - ActionBar.getCurrentActionBarHeight() - dp(48); } float renderWidth = width; @@ -1605,18 +1634,18 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int keyboardPad = Math.max(getPKeyboardHeight(), emojiPadding); measureChild(overlayLayout, widthMeasureSpec, MeasureSpec.makeMeasureSpec(height - keyboardPad, MeasureSpec.EXACTLY)); - topLayout.setPadding(topLayout.getPaddingLeft(), AndroidUtilities.dp(12) + AndroidUtilities.statusBarHeight, topLayout.getPaddingRight(), topLayout.getPaddingBottom()); + topLayout.setPadding(topLayout.getPaddingLeft(), dp(12) + AndroidUtilities.statusBarHeight, topLayout.getPaddingRight(), topLayout.getPaddingBottom()); measureChild(topLayout, widthMeasureSpec, heightMeasureSpec); ignoreLayout = false; int keyboardSize = 0; - if (!waitingForKeyboardOpen && keyboardSize <= AndroidUtilities.dp(20) && !emojiViewVisible && !isAnimatePopupClosing) { + if (!waitingForKeyboardOpen && keyboardSize <= dp(20) && !emojiViewVisible && !isAnimatePopupClosing) { ignoreLayout = true; hideEmojiView(); ignoreLayout = false; } - if (keyboardSize <= AndroidUtilities.dp(20)) { + if (keyboardSize <= dp(20)) { } else { hideEmojiView(); @@ -1653,7 +1682,7 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto int actionBarHeight2 = actionBarHeight + status; int x = (int) Math.ceil((width - renderView.getMeasuredWidth()) / 2f); - int y = (height - actionBarHeight2 - AndroidUtilities.dp(48) - renderView.getMeasuredHeight()) / 2 + AndroidUtilities.dp(8) + status + (getAdditionalTop() - getAdditionalBottom()) / 2; + int y = (height - actionBarHeight2 - dp(48) - renderView.getMeasuredHeight()) / 2 + dp(8) + status + (getAdditionalTop() - getAdditionalBottom()) / 2; renderView.layout(x, y, x + renderView.getMeasuredWidth(), y + renderView.getMeasuredHeight()); renderInputView.layout(x, y, x + renderInputView.getMeasuredWidth(), y + renderInputView.getMeasuredHeight()); @@ -2014,7 +2043,7 @@ public boolean onTouch(MotionEvent ev) { } float x2 = (ev.getX() - renderView.getTranslationX() - getMeasuredWidth() / 2f) / renderView.getScaleX(); - float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f + AndroidUtilities.dp(32) - (getAdditionalTop() - getAdditionalBottom()) / 2f) / renderView.getScaleY(); + float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f + dp(32) - (getAdditionalTop() - getAdditionalBottom()) / 2f) / renderView.getScaleY(); float rotation = (float) Math.toRadians(-renderView.getRotation()); float x = (float) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + renderView.getMeasuredWidth() / 2f; float y = (float) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + renderView.getMeasuredHeight() / 2f; @@ -2028,12 +2057,12 @@ public boolean onTouch(MotionEvent ev) { @Override public int getAdditionalTop() { - return AndroidUtilities.dp(48); + return dp(48); } @Override public int getAdditionalBottom() { - return AndroidUtilities.dp(24); + return dp(24); } @Override @@ -2270,7 +2299,7 @@ private void showColorList(boolean show) { float scale = 0.6f + 0.4f * (1f - toolsTransformProgress); barView.setScaleX(scale); barView.setScaleY(scale); - barView.setTranslationY(AndroidUtilities.dp(16) * Math.min(toolsTransformProgress, 0.25f) / 0.25f); + barView.setTranslationY(dp(16) * Math.min(toolsTransformProgress, 0.25f) / 0.25f); barView.setAlpha(1f - Math.min(toolsTransformProgress, 0.25f) / 0.25f); colorsListView.setProgress(toolsTransformProgress, show); @@ -2278,13 +2307,13 @@ private void showColorList(boolean show) { doneButton.setProgress(toolsTransformProgress); cancelButton.setProgress(toolsTransformProgress); - tabsLayout.setTranslationY(AndroidUtilities.dp(32) * toolsTransformProgress); + tabsLayout.setTranslationY(dp(32) * toolsTransformProgress); // if (adjustPanLayoutHelper.animationInProgress()) { // moveBottomLayout[0] = false; // } if (moveBottomLayout[0]) { float progress = show ? toolsTransformProgress : 1f - toolsTransformProgress; - bottomLayout.setTranslationY(bottomLayoutTranslationY - AndroidUtilities.dp(40) * progress * (show ? 1 : -1)); + bottomLayout.setTranslationY(bottomLayoutTranslationY - dp(40) * progress * (show ? 1 : -1)); } bottomLayout.invalidate(); @@ -2524,11 +2553,11 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { private void setTextType(int type) { selectedTextType = type; if (currentEntityView instanceof TextPaintView) { - if (type == 0 && colorSwatch.color == Color.WHITE) { - setNewColor(Color.BLACK); - } else if ((type == 1 || type == 2) && colorSwatch.color == Color.BLACK) { - setNewColor(Color.WHITE); - } +// if (type == 0 && colorSwatch.color == Color.WHITE) { +// setNewColor(Color.BLACK); +// } else if ((type == 1 || type == 2) && colorSwatch.color == Color.BLACK) { +// setNewColor(Color.WHITE); +// } ((TextPaintView) currentEntityView).setType(type); } PersistColorPalette.getInstance(currentAccount).setCurrentTextType(type); @@ -2633,7 +2662,7 @@ public void onAddButtonPressed(View btn) { private void showMenuForEntity(final EntityView entityView) { int[] pos = getCenterLocationInWindow(entityView); int x = pos[0]; - int y = pos[1] - AndroidUtilities.dp(32); + int y = pos[1] - dp(32); showPopup(() -> { LinearLayout parent = new LinearLayout(getContext()); @@ -2643,7 +2672,7 @@ private void showMenuForEntity(final EntityView entityView) { deleteView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); deleteView.setBackground(Theme.getSelectorDrawable(false)); deleteView.setGravity(Gravity.CENTER_VERTICAL); - deleteView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(14), 0); + deleteView.setPadding(dp(16), 0, dp(14), 0); deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); deleteView.setTag(0); deleteView.setText(LocaleController.getString("PaintDelete", R.string.PaintDelete)); @@ -2662,7 +2691,7 @@ private void showMenuForEntity(final EntityView entityView) { editView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); editView.setBackground(Theme.getSelectorDrawable(false)); editView.setGravity(Gravity.CENTER_VERTICAL); - editView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + editView.setPadding(dp(16), 0, dp(16), 0); editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); editView.setEllipsize(TextUtils.TruncateAt.END); editView.setTag(1); @@ -2683,7 +2712,7 @@ private void showMenuForEntity(final EntityView entityView) { flipView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); flipView.setGravity(Gravity.CENTER_VERTICAL); flipView.setEllipsize(TextUtils.TruncateAt.END); - flipView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + flipView.setPadding(dp(14), 0, dp(16), 0); flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); flipView.setTag(2); flipView.setText(LocaleController.getString("Flip", R.string.Flip)); @@ -2703,7 +2732,7 @@ private void showMenuForEntity(final EntityView entityView) { duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); duplicateView.setGravity(Gravity.CENTER_VERTICAL); duplicateView.setEllipsize(TextUtils.TruncateAt.END); - duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + duplicateView.setPadding(dp(14), 0, dp(16), 0); duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); duplicateView.setTag(2); duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate)); @@ -2724,7 +2753,7 @@ private void showMenuForEntity(final EntityView entityView) { cutView.setBackgroundDrawable(Theme.getSelectorDrawable(false)); cutView.setGravity(Gravity.CENTER_VERTICAL); cutView.setEllipsize(TextUtils.TruncateAt.END); - cutView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0); + cutView.setPadding(dp(14), 0, dp(16), 0); cutView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); cutView.setTag(5); cutView.setText(LocaleController.getString(photoView.isSegmented() ? R.string.SegmentationUndoCutOut : R.string.SegmentationCutOut)); @@ -2859,7 +2888,7 @@ private void showPopup(Runnable setupRunnable, View parent, int gravity, int x, popupWindow.setOnDismissListener(() -> popupLayout.removeInnerViews()); } - popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST)); + popupLayout.measure(MeasureSpec.makeMeasureSpec(dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(1000), MeasureSpec.AT_MOST)); popupWindow.setFocusable(true); @@ -3057,17 +3086,52 @@ public int[] getCenterLocation(EntityView entityView) { return getCenterLocationInWindow(entityView); } - private int[] pos = new int[2]; + private Matrix matrix = new Matrix(); + private float[] position = new float[2]; + private int[] pos2 = new int[2]; private int[] getCenterLocationInWindow(View view) { - view.getLocationInWindow(pos); - float rotation = (float) Math.toRadians(view.getRotation() + (currentCropState != null ? currentCropState.cropRotate + currentCropState.transformRotation : 0)); - float width = view.getWidth() * view.getScaleX() * entitiesView.getScaleX(); - float height = view.getHeight() * view.getScaleY() * entitiesView.getScaleY(); - float px = (float) (width * Math.cos(rotation) - height * Math.sin(rotation)); - float py = (float) (width * Math.sin(rotation) + height * Math.cos(rotation)); - pos[0] += px / 2; - pos[1] += py / 2; - return pos; + // code taken from android transformFromViewToWindowSpace source code + position[0] = view.getWidth() / 2f; + position[1] = view.getHeight() / 2f; + + view.getMatrix().mapPoints(position); + position[0] += view.getLeft(); + position[1] += view.getTop(); + ViewParent viewParent = view.getParent(); + while (viewParent instanceof View) { + final View nextView = (View) viewParent; + position[0] -= nextView.getScrollX(); + position[1] -= nextView.getScrollY(); + nextView.getMatrix().mapPoints(position); + position[0] += nextView.getLeft(); + position[1] += nextView.getTop(); + viewParent = nextView.getParent(); + } + + pos2[0] = Math.round(position[0]); + pos2[1] = Math.round(position[1]); + + float x2 = (pos2[0] - AndroidUtilities.displaySize.x / 2f); + float y2 = (pos2[1] - AndroidUtilities.displaySize.y / 2f); + float rotation = (float) Math.toRadians(-entitiesView.getRotation()); + pos2[0] = (int) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + AndroidUtilities.displaySize.x / 2; + pos2[1] = (int) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + AndroidUtilities.displaySize.y / 2; + + return pos2; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + boolean r = false; +// if (entitiesView != null && !entitiesView.getClipChildren() && ev.getPointerCount() > 1) { +// MotionEvent transformedEvent = MotionEvent.obtain(ev); +// transformedEvent.offsetLocation(-entitiesView.getLeft(), -entitiesView.getTop()); +// entitiesView.getMatrix().invert(matrix); +// transformedEvent.transform(matrix); +// r = entitiesView.dispatchTouchEvent(transformedEvent) || r; +// transformedEvent.recycle(); +// } + return super.dispatchTouchEvent(ev) || r; } @Override @@ -3155,16 +3219,16 @@ private void showEmojiPopup(int show) { if (keyboardHeight <= 0) { if (AndroidUtilities.isTablet()) { - keyboardHeight = AndroidUtilities.dp(150); + keyboardHeight = dp(150); } else { - keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", AndroidUtilities.dp(200)); + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); } } if (keyboardHeightLand <= 0) { if (AndroidUtilities.isTablet()) { - keyboardHeightLand = AndroidUtilities.dp(150); + keyboardHeightLand = dp(150); } else { - keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", AndroidUtilities.dp(200)); + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); } } int currentHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; @@ -3327,7 +3391,7 @@ private void onWindowSizeChanged() { @Override public void onSizeChanged(int height, boolean isWidthGreater) { - if (height > AndroidUtilities.dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { if (isWidthGreater) { keyboardHeightLand = height; MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java new file mode 100644 index 0000000000..84598eaf71 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/MaskPaintView.java @@ -0,0 +1,462 @@ +package org.telegram.ui.Components.Paint.Views; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Build; +import android.os.Looper; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Animation; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.BubbleActivity; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Paint.Brush; +import org.telegram.ui.Components.Paint.Painting; +import org.telegram.ui.Components.Paint.PersistColorPalette; +import org.telegram.ui.Components.Paint.RenderView; +import org.telegram.ui.Components.Paint.Swatch; +import org.telegram.ui.Components.Paint.UndoStore; +import org.telegram.ui.Components.Size; + +import java.util.ArrayList; + +public class MaskPaintView extends FrameLayout { + + private int currentAccount; + + private UndoStore undoStore; + private DispatchQueue queue; + + private MediaController.CropState currentCropState; + private final RenderView renderView; + private Bitmap bitmapToEdit; + private int orientation; + + private boolean inBubbleMode; + + public final FrameLayout buttonsLayout; + public final TextView cancelButton; + public final TextView doneButton; + + public PaintWeightChooserView weightChooserView; + private PaintWeightChooserView.ValueOverride weightDefaultValueOverride = new PaintWeightChooserView.ValueOverride() { + @Override + public float get() { + Brush brush = renderView.getCurrentBrush(); + if (brush == null) { + return PersistColorPalette.getInstance(currentAccount).getCurrentWeight(); + } + return PersistColorPalette.getInstance(currentAccount).getWeight("-1", brush.getDefaultWeight()); + } + + @Override + public void set(float val) { + PersistColorPalette.getInstance(currentAccount).setWeight("-1", val); + renderView.setBrushSize(val); + } + }; + + public MaskPaintView(Context context, int currentAccount, Bitmap bitmapToEdit, Bitmap bitmap, int orientation, MediaController.CropState cropState) { + super(context); + + this.currentAccount = currentAccount; + + inBubbleMode = context instanceof BubbleActivity; + + undoStore = new UndoStore(); + undoStore.setDelegate(new UndoStore.UndoStoreDelegate() { + @Override + public void historyChanged() { + + } + }); + queue = new DispatchQueue("MaskPaint"); + + this.currentCropState = cropState; + this.bitmapToEdit = bitmapToEdit; + this.orientation = orientation; + renderView = new RenderView(context, new Painting(getPaintingSize(), bitmap, orientation, null).asMask(), bitmapToEdit, null, null); + renderView.setAlpha(0f); + renderView.setDelegate(new RenderView.RenderViewDelegate() { + @Override + public void onBeganDrawing() { + weightChooserView.setViewHidden(true); + } + + @Override + public void onFinishedDrawing(boolean moved) { + undoStore.getDelegate().historyChanged(); + weightChooserView.setViewHidden(false); + onDrawn(); + } + + @Override + public void onFirstDraw() { + renderView.animate().alpha(1f).setDuration(320).setUpdateListener(MaskPaintView.this::onRenderViewAlphaUpdate).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } + + @Override + public boolean shouldDraw() { + return true; + } + + @Override + public void resetBrush() { + + } + }); + renderView.setUndoStore(undoStore); + renderView.setQueue(queue); + renderView.setVisibility(View.INVISIBLE); + renderView.setBrush(new Brush.Radial()); + renderView.setBrushSize(weightDefaultValueOverride.get()); + renderView.setColor(0xFFFF0000); + addView(renderView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + + weightChooserView = new PaintWeightChooserView(context); + weightChooserView.setMinMax(0.05f, 1f); + weightChooserView.setBrushWeight(weightDefaultValueOverride.get()); + weightChooserView.setRenderView(renderView); + weightChooserView.setValueOverride(weightDefaultValueOverride); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setAlpha(0f); + addView(weightChooserView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + buttonsLayout = new FrameLayout(context); + buttonsLayout.setAlpha(0f); + buttonsLayout.setVisibility(View.GONE); + addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44, Gravity.BOTTOM)); + + cancelButton = new TextView(context); + cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + cancelButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + cancelButton.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Color.WHITE, .15f), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + cancelButton.setPadding(dp(28), 0, dp(28), 0); + cancelButton.setText(LocaleController.getString(R.string.Cancel).toUpperCase()); + cancelButton.setTextColor(Color.WHITE); + cancelButton.setGravity(Gravity.CENTER); + buttonsLayout.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 44, Gravity.LEFT, -8, 0, 0, 0)); + + doneButton = new TextView(context); + doneButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + doneButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + doneButton.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_chat_editMediaButton), .15f), Theme.RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE)); + doneButton.setPadding(dp(28), 0, dp(28), 0); + doneButton.setText(LocaleController.getString(R.string.Save).toUpperCase()); + doneButton.setTextColor(Theme.getColor(Theme.key_chat_editMediaButton)); + doneButton.setGravity(Gravity.CENTER); + buttonsLayout.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 44, Gravity.RIGHT, 0, 0, -8, 0)); + } + + protected void onDrawn() { + + } + + protected void onRenderViewAlphaUpdate(ValueAnimator animation) { + + } + + public boolean canUndo() { + return undoStore.canUndo(); + } + public boolean undo() { + if (!undoStore.canUndo()) return false; + undoStore.undo(); + return true; + } + + private Size paintingSize; + private Size getPaintingSize() { + if (paintingSize != null) { + return paintingSize; + } + float width = bitmapToEdit.getWidth(); + float height = bitmapToEdit.getHeight(); + + int maxSide = 1280; + Size size = new Size(width, height); + size.width = maxSide; + size.height = (float) Math.floor(size.width * height / width); + if (size.height > maxSide) { + size.height = maxSide; + size.width = (float) Math.floor(size.height * width / height); + } + paintingSize = size; + return size; + } + + private boolean eraser; + public void setEraser(boolean eraser) { + if (this.eraser == eraser) return; + this.eraser = eraser; + renderView.setBrush(eraser ? new Brush.Eraser() : new Brush.Radial()); + } + + private float panTranslationY, scale, inputTransformX, inputTransformY, transformX, transformY, imageWidth, imageHeight; + + public void setTransform(float scale, float trX, float trY, float rotate, float imageWidth, float imageHeight) { + this.scale = scale; + this.imageWidth = imageWidth; + this.imageHeight = imageHeight; + inputTransformX = trX; + inputTransformY = trY; + transformX = trX; + trY += panTranslationY; + transformY = trY; + for (int a = 0; a < 1; a++) { + View view; + float additionlScale = 1.0f; + if (a == 0) { + view = renderView; + } else continue; + float tx; + float ty; + float rotation = rotate; + if (currentCropState != null) { + additionlScale *= currentCropState.cropScale; + + int w = view.getMeasuredWidth(); + int h = view.getMeasuredHeight(); + if (w == 0 || h == 0) { + return; + } + int tr = currentCropState.transformRotation; + int fw = w, rotatedW = w; + int fh = h, rotatedH = h; + if (tr == 90 || tr == 270) { + int temp = fw; + fw = rotatedW = fh; + fh = rotatedH = temp; + } + fw *= currentCropState.cropPw; + fh *= currentCropState.cropPh; + + float sc = Math.max(imageWidth / fw, imageHeight / fh); + additionlScale *= sc; + + tx = trX + currentCropState.cropPx * rotatedW * scale * sc * currentCropState.cropScale; + ty = trY + currentCropState.cropPy * rotatedH * scale * sc * currentCropState.cropScale; + rotation += currentCropState.cropRotate + tr; + } else { + if (a == 0) { + additionlScale *= baseScale; + } + tx = trX; + ty = trY; + } + float finalScale = scale * additionlScale; + if (Float.isNaN(finalScale)) { + finalScale = 1f; + } + view.setScaleX(finalScale); + view.setScaleY(finalScale); + view.setTranslationX(tx); + view.setTranslationY(ty); + view.setRotation(rotation); + view.invalidate(); + } + invalidate(); + } + + public void init() { + renderView.setVisibility(View.VISIBLE); + buttonsLayout.setVisibility(View.VISIBLE); + buttonsLayout.setTranslationY(dp(18)); + buttonsLayout.animate().alpha(1f).translationY(0).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + weightChooserView.animate().alpha(1f).translationX(0).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + } + + private boolean ignoreLayout; + private float baseScale; + + private ArrayList exclusionRects = new ArrayList<>(); + private Rect exclusionRect = new Rect(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + ignoreLayout = true; + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(width, height); + + float bitmapW; + float bitmapH; + int fullHeight = AndroidUtilities.displaySize.y; + int maxHeight = fullHeight; + if (bitmapToEdit != null) { + bitmapW = bitmapToEdit.getWidth(); + bitmapH = bitmapToEdit.getHeight(); + } else { + bitmapW = width; + bitmapH = height; + } + + float renderWidth = width; + float renderHeight = (float) Math.floor(renderWidth * bitmapH / bitmapW); + if (renderHeight > maxHeight) { + renderHeight = maxHeight; + renderWidth = (float) Math.floor(renderHeight * bitmapW / bitmapH); + } + + renderView.measure(MeasureSpec.makeMeasureSpec((int) renderWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) renderHeight, MeasureSpec.EXACTLY)); + + baseScale = 1f;//renderWidth / paintingSize.width; + measureChild(weightChooserView, widthMeasureSpec, heightMeasureSpec); + measureChild(buttonsLayout, widthMeasureSpec, heightMeasureSpec); + + ignoreLayout = false; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + setSystemGestureExclusionRects(exclusionRects); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int width = right - left; + int height = bottom - top; + + int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); + int actionBarHeight = 0; + int actionBarHeight2 = status; + + int x = (int) Math.ceil((width - renderView.getMeasuredWidth()) / 2f); + int y = (height - renderView.getMeasuredHeight()) / 2; + + renderView.layout(x, y, x + renderView.getMeasuredWidth(), y + renderView.getMeasuredHeight()); + int b = bottom - top; + buttonsLayout.layout(0, b - buttonsLayout.getMeasuredHeight(), buttonsLayout.getMeasuredWidth(), b); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + boolean restore = false; + if ((child == renderView) && currentCropState != null) { + canvas.save(); + + int status = (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0); + int actionBarHeight = ActionBar.getCurrentActionBarHeight(); + int actionBarHeight2 = actionBarHeight + status; + + int vw = child.getMeasuredWidth(); + int vh = child.getMeasuredHeight(); + int tr = currentCropState.transformRotation; + if (tr == 90 || tr == 270) { + int temp = vw; + vw = vh; + vh = temp; + } + + int w = (int) (vw * currentCropState.cropPw * child.getScaleX() / currentCropState.cropScale); + int h = (int) (vh * currentCropState.cropPh * child.getScaleY() / currentCropState.cropScale); + float x = (float) Math.ceil((getMeasuredWidth() - w) / 2f) + transformX; + float y = (getMeasuredHeight() - actionBarHeight2 - dp(48) + getAdditionalBottom() - h) / 2f + dp(8) + status + transformY; + + canvas.clipRect(Math.max(0, x), Math.max(0, y), Math.min(x + w, getMeasuredWidth()), Math.min(getMeasuredHeight(), y + h)); + restore = true; + } + boolean result = super.drawChild(canvas, child, drawingTime); + if (restore) { + canvas.restore(); + } + return result; + } + + public boolean onTouch(MotionEvent ev) { + float x2 = (ev.getX() - renderView.getTranslationX() - getMeasuredWidth() / 2f) / renderView.getScaleX(); + float y2 = (ev.getY() - renderView.getTranslationY() - getMeasuredHeight() / 2f) / renderView.getScaleY(); + float rotation = (float) Math.toRadians(-renderView.getRotation()); + float x = (float) (x2 * Math.cos(rotation) - y2 * Math.sin(rotation)) + renderView.getMeasuredWidth() / 2f; + float y = (float) (x2 * Math.sin(rotation) + y2 * Math.cos(rotation)) + renderView.getMeasuredHeight() / 2f; + + MotionEvent event = MotionEvent.obtain(ev); + event.setLocation(x, y); + renderView.onTouch(event); + event.recycle(); + return true; + } + + public Bitmap getBitmap() { + Bitmap resultBitmap = renderView.getResultBitmap(false, false); + if (orientation != 0) { + int w = resultBitmap.getWidth(), h = resultBitmap.getHeight(); + if (orientation / 90 % 2 != 0) { + w = resultBitmap.getHeight(); + h = resultBitmap.getWidth(); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(b); + canvas.translate(w / 2f, h / 2f); + canvas.rotate(-orientation); + AndroidUtilities.rectTmp.set( + -resultBitmap.getWidth() / 2f, + -resultBitmap.getHeight() / 2f, + resultBitmap.getWidth() / 2f, + resultBitmap.getHeight() / 2f + ); + canvas.drawBitmap(resultBitmap, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + resultBitmap.recycle(); + resultBitmap = b; + } + return resultBitmap; + } + + public RenderView getRenderView() { + return renderView; + } + + public int getAdditionalTop() { + return 0; // AndroidUtilities.dp(48); + } + + public int getAdditionalBottom() { + return 0; // AndroidUtilities.dp(24); + } + + public void shutdown() { + renderView.shutdown(); + queue.postRunnable(() -> { + Looper looper = Looper.myLooper(); + if (looper != null) { + looper.quit(); + } + }); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java index 1292af8ebb..d52c969391 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PaintWeightChooserView.java @@ -95,7 +95,9 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d colorSwatch.brushWeight = weight; } animatedWeight.set(weight, true); - onUpdate.run(); + if (onUpdate != null) { + onUpdate.run(); + } invalidate(); } return isTouchInProgress; @@ -157,6 +159,11 @@ public void setColorSwatch(Swatch colorSwatch) { invalidate(); } + public void setBrushWeight(float brushWeight) { + this.colorSwatch.brushWeight = brushWeight; + invalidate(); + } + public void setDrawCenter(boolean draw) { drawCenter = draw; invalidate(); @@ -264,7 +271,7 @@ protected void onDraw(Canvas canvas) { false ); - if (drawCenter && showProgress != 0f && showPreview) { + if (drawCenter && showProgress != 0f && showPreview && renderView != null) { float cx = getWidth() / 2f, cy = getHeight() / 2f, rad = renderView.brushWeightForSize(weight) * renderView.getCurrentBrush().getScale() * renderView.getCurrentBrush().getPreviewScale(); drawCircleWithShadow(canvas, cx, cy, rad, true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java index 220a685345..98198f7e78 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java @@ -71,7 +71,7 @@ protected void onDraw(Canvas canvas) { private int anchor = -1; private boolean mirrored = false; private final AnimatedFloat mirrorT; - private Size baseSize; + public Size baseSize; private boolean overridenSegmented = false; private int orientation, invert; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java index 9963dec733..3efb21341a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerCutOutBtn.java @@ -21,24 +21,40 @@ @SuppressLint("ViewConstructor") public class StickerCutOutBtn extends ButtonWithCounterView { + private static final int STATE_CUT_OUT = 0; private static final int STATE_UNDO_CAT = 1; private static final int STATE_CANCEL = 2; + private static final int STATE_ERASE = 3; + private static final int STATE_RESTORE = 4; + private static final int STATE_UNDO = 5; + private static final int STATE_OUTLINE = 6; protected final BlurringShader.StoryBlurDrawer blurDrawer; protected final RectF bounds = new RectF(); private int state; private final StickerMakerView stickerMakerView; + private final Theme.ResourcesProvider resourcesProvider; + public StickerCutOutBtn(StickerMakerView stickerMakerView, Context context, Theme.ResourcesProvider resourcesProvider, BlurringShader.BlurManager blurManager) { super(context, false, resourcesProvider); + this.resourcesProvider = resourcesProvider; this.stickerMakerView = stickerMakerView; blurDrawer = new BlurringShader.StoryBlurDrawer(blurManager, this, BlurringShader.StoryBlurDrawer.BLUR_TYPE_BACKGROUND, true); setWillNotDraw(false); setTextColor(Color.WHITE); setFlickeringLoading(true); text.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - setForeground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + disableRippleView(); + setForeground(Theme.createRadSelectorDrawable(Theme.multAlpha(Color.WHITE, .08f), 8, 8)); + setPadding(dp(24), 0, dp(24), 0); + } + + public int rad = 8; + public void setRad(int rad) { + this.rad = rad; + setForeground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), rad, rad)); } @Override @@ -51,7 +67,12 @@ public void setAlpha(float alpha) { @Override protected void onDraw(Canvas canvas) { - bounds.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (wrapContentDynamic) { + float w = text.getCurrentWidth() + getPaddingLeft() + getPaddingRight(); + bounds.set((getMeasuredWidth() - w) / 2f, 0, (getMeasuredWidth() + w) / 2f, getMeasuredHeight()); + } else { + bounds.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + } super.onDraw(canvas); } @@ -69,7 +90,9 @@ public void setCutOutState(boolean animated) { SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_magic_cut); coloredImageSpan.setSize(dp(22)); - coloredImageSpan.setTranslateX(dp(-2)); + coloredImageSpan.setTranslateX(dp(1)); + coloredImageSpan.setTranslateY(dp(2)); + coloredImageSpan.spaceScaleX = 1.2f; cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationCutObject)); setText(cutOutBtnText, animated); @@ -77,12 +100,49 @@ public void setCutOutState(boolean animated) { public void setUndoCutState(boolean animated) { state = STATE_UNDO_CAT; + } + + public void setUndoState(boolean animated) { + state = STATE_UNDO; SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.photo_undo2); coloredImageSpan.setSize(dp(20)); coloredImageSpan.setTranslateX(dp(-3)); cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); - cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationUndoCutOut)); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationUndo)); + setText(cutOutBtnText, animated); + } + + public void setOutlineState(boolean animated) { + state = STATE_OUTLINE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_sticker_stroke); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationOutline)); + setText(cutOutBtnText, animated); + } + + public void setRestoreState(boolean animated) { + state = STATE_RESTORE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_button_restore); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationRestore)); + setText(cutOutBtnText, animated); + } + + public void setEraseState(boolean animated) { + state = STATE_ERASE; + SpannableStringBuilder cutOutBtnText = new SpannableStringBuilder("d"); + ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.media_button_erase); + coloredImageSpan.setSize(dp(20)); + coloredImageSpan.setTranslateX(dp(-3)); + cutOutBtnText.setSpan(coloredImageSpan, 0, 1, 0); + cutOutBtnText.append(" ").append(LocaleController.getString(R.string.SegmentationErase)); setText(cutOutBtnText, animated); } @@ -99,6 +159,10 @@ public boolean isCancelState() { return state == STATE_CANCEL; } + public boolean isUndoCutState() { + return state == STATE_UNDO_CAT; + } + public void clean() { setCutOutState(false); } @@ -106,4 +170,17 @@ public void clean() { public void invalidateBlur() { invalidate(); } + + private boolean wrapContent; + public void wrapContent() { + wrapContent = true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (wrapContent) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec(getPaddingLeft() + (int) text.getCurrentWidth() + getPaddingRight(), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java index fde6b01a39..94fb97ec5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerMakerView.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components.Paint.Views; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; import android.animation.ValueAnimator; import android.annotation.SuppressLint; @@ -21,6 +22,8 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; +import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -34,12 +37,17 @@ import com.google.mlkit.common.MlKitException; import com.google.mlkit.vision.common.InputImage; +import com.google.mlkit.vision.label.ImageLabeling; +import com.google.mlkit.vision.label.defaults.ImageLabelerOptions; import com.google.mlkit.vision.segmentation.subject.Subject; import com.google.mlkit.vision.segmentation.subject.SubjectSegmentation; import com.google.mlkit.vision.segmentation.subject.SubjectSegmenter; import com.google.mlkit.vision.segmentation.subject.SubjectSegmenterOptions; +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.EmuDetector; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; @@ -49,6 +57,7 @@ import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; @@ -60,10 +69,13 @@ import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Paint.ObjectDetectionEmojis; import org.telegram.ui.Components.ThanosEffect; import org.telegram.ui.Stories.DarkThemeResourceProvider; +import org.telegram.ui.Stories.recorder.DownloadButton; import org.telegram.ui.Stories.recorder.StoryEntry; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -75,6 +87,7 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. public int currentAccount = -1; private final AnimatedFloat segmentBorderAlpha = new AnimatedFloat(0, (View) null, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat outlineAlpha = new AnimatedFloat(0, (View) null, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); private final Paint dashPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -87,8 +100,11 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private volatile boolean segmentingLoading; private volatile boolean segmentingLoaded; private SegmentedObject selectedObject; + public float outlineWidth = 2f; + public boolean empty; public SegmentedObject[] objects; private volatile Bitmap sourceBitmap; + public int orientation; private Bitmap filteredBitmap; private boolean isSegmentedState; private final TextView actionTextView; @@ -105,10 +121,15 @@ public class StickerMakerView extends FrameLayout implements NotificationCenter. private AlertDialog loadingDialog; private final Theme.ResourcesProvider resourcesProvider; private StickerCutOutBtn stickerCutOutBtn; + public String detectedEmoji; + + private DownloadButton.PreparingVideoToast loadingToast; private final Matrix imageReceiverMatrix = new Matrix(); private float imageReceiverWidth, imageReceiverHeight; + public PaintWeightChooserView weightChooserView; + public StickerMakerView(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; @@ -121,7 +142,6 @@ public StickerMakerView(Context context, Theme.ResourcesProvider resourcesProvid dashPaint.setAlpha(140); actionTextView = new TextView(context); - actionTextView.setText(LocaleController.getString(R.string.SegmentationTabToCrop)); actionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); actionTextView.setTextColor(Color.WHITE); actionTextView.setAlpha(0f); @@ -133,18 +153,37 @@ public StickerMakerView(Context context, Theme.ResourcesProvider resourcesProvid borderPaint.setStrokeWidth(dp(3)); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeCap(Paint.Cap.ROUND); - borderPaint.setPathEffect(new CornerPathEffect(dp(6))); + borderPaint.setPathEffect(new CornerPathEffect(dp(20))); borderPaint.setMaskFilter(new BlurMaskFilter(dp(4), BlurMaskFilter.Blur.NORMAL)); segmentBorderPaint.setColor(Color.WHITE); segmentBorderPaint.setStrokeWidth(dp(3)); segmentBorderPaint.setStyle(Paint.Style.STROKE); segmentBorderPaint.setStrokeCap(Paint.Cap.ROUND); - segmentBorderPaint.setPathEffect(new CornerPathEffect(dp(6))); + segmentBorderPaint.setPathEffect(new CornerPathEffect(dp(20))); segmentBorderPaint.setMaskFilter(new BlurMaskFilter(dp(4), BlurMaskFilter.Blur.NORMAL)); bgPaint.setColor(0x66000000); setLayerType(LAYER_TYPE_HARDWARE, null); + + weightChooserView = new PaintWeightChooserView(context); + weightChooserView.setAlpha(0f); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setMinMax(.33f, 10); + weightChooserView.setBrushWeight(outlineWidth); + weightChooserView.setValueOverride(new PaintWeightChooserView.ValueOverride() { + @Override + public float get() { + return outlineWidth; + } + @Override + public void set(float val) { + setOutlineWidth(val); + } + }); + weightChooserView.setTranslationX(-dp(18)); + weightChooserView.setAlpha(0f); + addView(weightChooserView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } public void setStickerCutOutBtn(StickerCutOutBtn stickerCutOutBtn) { @@ -182,7 +221,33 @@ public class SegmentedObject { public int orientation; public Bitmap image; + public Bitmap overrideImage; public Bitmap darkMaskImage; + public Bitmap overrideDarkMaskImage; + + public Bitmap getImage() { + if (overrideImage != null) { + return overrideImage; + } + return image; + } + + public Bitmap getDarkMaskImage() { + if (overrideDarkMaskImage != null) { + return overrideDarkMaskImage; + } + return darkMaskImage; + } + + public Bitmap makeDarkMaskImage() { + Bitmap darkMaskImage = Bitmap.createBitmap(getImage().getWidth(), getImage().getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(darkMaskImage); + canvas.drawColor(Color.BLACK); + Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + canvas.drawBitmap(getImage(), 0, 0, maskPaint); + return darkMaskImage; + } public RectF bounds = new RectF(); public RectF rotatedBounds = new RectF(); @@ -193,11 +258,78 @@ public class SegmentedObject { private final Path segmentBorderPath = new Path(); private final Path partSegmentBorderPath = new Path(); - public void drawBorders(Canvas canvas, float progress, float alpha, View parent) { + private int pointsCount; + private float[] points; + private final Paint bordersFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint bordersStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint bordersDiffStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint pointsPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint pointsHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private final boolean USE_POINTS = true; + public void initPoints() { + PathMeasure pathMeasure = new PathMeasure(); + pathMeasure.setPath(segmentBorderPath, true); + final float length = pathMeasure.getLength(); + final float pointRadius = dp(2); + pointsCount = (int) Math.ceil(length / pointRadius); + this.points = new float[pointsCount * 2]; + final float[] pos = new float[2]; + for (int i = 0; i < pointsCount; ++i) { + pathMeasure.getPosTan(((float) i / pointsCount * length) % length, pos, null); + this.points[i * 2] = pos[0]; + this.points[i * 2 + 1] = pos[1]; + } + + bordersFillPaint.setStyle(Paint.Style.FILL); + bordersFillPaint.setColor(Color.WHITE); + bordersFillPaint.setStrokeJoin(Paint.Join.ROUND); + bordersFillPaint.setStrokeCap(Paint.Cap.ROUND); + bordersFillPaint.setPathEffect(new CornerPathEffect(dp(10))); + bordersStrokePaint.setStyle(Paint.Style.STROKE); + bordersStrokePaint.setColor(Color.WHITE); + bordersStrokePaint.setStrokeJoin(Paint.Join.ROUND); + bordersStrokePaint.setStrokeCap(Paint.Cap.ROUND); + bordersStrokePaint.setPathEffect(new CornerPathEffect(dp(10))); + + pointsPaint.setStyle(Paint.Style.STROKE); + pointsPaint.setStrokeWidth(dp(4)); + pointsPaint.setColor(0xFFFFFFFF); + pointsPaint.setStrokeCap(Paint.Cap.ROUND); + pointsPaint.setMaskFilter(new BlurMaskFilter(dp(.33f), BlurMaskFilter.Blur.NORMAL)); + + pointsHighlightPaint.setStyle(Paint.Style.STROKE); + pointsHighlightPaint.setColor(Theme.multAlpha(0xFFFFFFFF, .04f)); + pointsHighlightPaint.setStrokeCap(Paint.Cap.ROUND); + pointsHighlightPaint.setStrokeWidth(dp(20)); + pointsHighlightPaint.setColor(Theme.multAlpha(Color.WHITE, .04f)); + pointsHighlightPaint.setMaskFilter(new BlurMaskFilter(dp(60), BlurMaskFilter.Blur.NORMAL)); + } + + public void drawOutline(Canvas canvas, boolean after, float width, float alpha) { + if (outlineBoundsPath == null) + return; + canvas.save(); + canvas.clipPath(outlineBoundsPath); + if (sourceBitmap != null) { + Paint paint = after ? bordersStrokePaint : bordersFillPaint; + paint.setAlpha((int) (0xFF * alpha)); + paint.setStrokeWidth(dp(width)); + canvas.drawPath(segmentBorderPath, paint); + if (outlineBoundsPath != null && after) { + canvas.clipPath(segmentBorderPath); + paint.setStrokeWidth(dp(2 * width)); + canvas.drawPath(outlineBoundsPath, paint); + } + } + canvas.restore(); + } + + public void drawAnimationBorders(Canvas canvas, float progress, float alpha, View parent) { select.setParent(parent); - if (sourceBitmap == null) return; + if (sourceBitmap == null || alpha <= 0) return; - final float s = AndroidUtilities.lerp(1f, 1.065f, alpha) * AndroidUtilities.lerp(1f, 1.05f, select.set(hover)); + final float s = lerp(1f, 1.065f, alpha) * lerp(1f, 1.05f, select.set(hover)); int w, h; if (orientation / 90 % 2 != 0) { @@ -211,50 +343,87 @@ public void drawBorders(Canvas canvas, float progress, float alpha, View parent) canvas.save(); canvas.scale(s, s, rotatedBounds.centerX() / w * borderImageWidth - borderImageWidth / 2f, rotatedBounds.centerY() / h * borderImageHeight - borderImageHeight / 2f); - bordersPathMeasure.setPath(segmentBorderPath, false); - partSegmentBorderPath.reset(); + if (USE_POINTS && points != null) { + final int fromIndex = (int) (progress * pointsCount); + final int toIndex = fromIndex + Math.min(500, (int) (.6f * pointsCount)); + if (pointsCount > 0) { + for (int i = fromIndex; i <= toIndex; ++i) { + final float ha = (1f - (toIndex - i) / (float) pointsCount); + if (ha > 0) { + pointsHighlightPaint.setAlpha((int) (0xFF * .04f * ha * alpha)); + canvas.drawPoints(points, (i % pointsCount) * 2, 2, pointsHighlightPaint); + } + } + } + } - float length = bordersPathMeasure.getLength(); - if (length == 0) { - return; + if (getImage() != null) { + canvas.save(); + canvas.rotate(orientation); + canvas.scale(1f / w * borderImageWidth, 1f / h * borderImageHeight); + canvas.drawBitmap(getImage(), -sourceBitmap.getWidth() / 2f, -sourceBitmap.getHeight() / 2f, null); + canvas.restore(); } - segmentBorderPaint.setAlpha((int) (0xFF * alpha)); - borderPaint.setAlpha((int) (0x40 * alpha)); - canvas.drawPath(partSegmentBorderPath, borderPaint); - - float toPercent = progress + 0.2f; - float from = length * progress; - float to = length * toPercent; - bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); - if (toPercent > 1) { - from = 0; - to = (toPercent - 1) * length; - partSegmentBorderPath.reset(); + if (USE_POINTS && points != null) { + final int fromIndex = (int) (progress * pointsCount); + final int toIndex = fromIndex + Math.min(500, (int) (.6f * pointsCount)); + if (pointsCount > 0) { + for (int i = fromIndex; i <= toIndex; ++i) { + final float p = (float) (i - fromIndex) / (toIndex - fromIndex); + final float a = Math.min(1, 4f * Math.min(p, 1 - p)); + pointsPaint.setAlpha((int) (0xFF * a * alpha)); + canvas.drawPoints(points, (i % pointsCount) * 2, 2, pointsPaint); + } + } + } else { bordersPathMeasure.setPath(segmentBorderPath, false); + partSegmentBorderPath.reset(); + + float length = bordersPathMeasure.getLength(); + if (length == 0) { + return; + } + + segmentBorderPaint.setAlpha((int) (0xFF * alpha)); + borderPaint.setAlpha((int) (0x40 * alpha)); + canvas.drawPath(partSegmentBorderPath, borderPaint); + + float toPercent = progress + 0.2f; + float from = length * progress; + float to = length * toPercent; bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + if (toPercent > 1) { + from = 0; + to = (toPercent - 1) * length; + partSegmentBorderPath.reset(); + bordersPathMeasure.setPath(segmentBorderPath, false); + bordersPathMeasure.getSegment(from, to, partSegmentBorderPath, true); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + canvas.drawPath(partSegmentBorderPath, segmentBorderPaint); + } } - if (image != null) { - canvas.save(); - canvas.rotate(orientation); - canvas.scale(1f / w * borderImageWidth, 1f / h * borderImageHeight); - canvas.drawBitmap(image, -sourceBitmap.getWidth() / 2f, -sourceBitmap.getHeight() / 2f, null); - canvas.restore(); - } canvas.restore(); } public void recycle() { segmentBorderPath.reset(); + if (overrideImage != null) { + overrideImage.recycle(); + overrideImage = null; + } if (image != null) { image.recycle(); image = null; } + if (overrideDarkMaskImage != null) { + overrideDarkMaskImage.recycle(); + overrideDarkMaskImage = null; + } if (darkMaskImage != null) { darkMaskImage.recycle(); darkMaskImage = null; @@ -262,24 +431,123 @@ public void recycle() { } } + public void setOutlineWidth(float width) { + outlineWidth = width; + if (getParent() instanceof View) { + ((View) getParent()).invalidate(); + } + } + + public void updateOutlinePath(Bitmap newMaskBitmap) { + if (selectedObject == null) return; + selectedObject.overrideImage = createSmoothEdgesSegmentedImage(0, 0, newMaskBitmap, true); + selectedObject.overrideDarkMaskImage = selectedObject.makeDarkMaskImage(); + createSegmentImagePath(selectedObject, containerWidth, containerHeight); + } + + public boolean overriddenPaths() { + if (objects != null) { + for (SegmentedObject obj : objects) { + if (obj != null && obj.overrideImage != null) { + return true; + } + } + } + return false; + } + + public void resetPaths() { + if (objects != null) { + for (SegmentedObject obj : objects) { + if (obj != null && obj.overrideImage != null) { + obj.overrideImage.recycle(); + obj.overrideImage = null; + if (obj.overrideDarkMaskImage != null) { + obj.overrideDarkMaskImage.recycle(); + obj.overrideDarkMaskImage = null; + } + createSegmentImagePath(obj, containerWidth, containerHeight); + } + } + } + } + + public boolean outlineVisible; + public void setOutlineVisible(boolean visible) { + if (outlineVisible == visible) return; + outlineVisible = visible; + weightChooserView.animate().alpha(visible ? 1f : 0f).translationX(visible ? 0 : dp(-18)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(320).start(); + if (getParent() instanceof View) { + ((View) getParent()).invalidate(); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + if (outlineVisible) { + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + } + setSystemGestureExclusionRects(exclusionRects); + } + } + + public void drawOutline(Canvas canvas, boolean after, ViewGroup parent, boolean hide) { + this.outlineAlpha.setParent(parent); + if (!outlineVisible && this.outlineAlpha.get() <= 0) { + return; + } + + final float outlineAlpha = parent == null ? 1f : this.outlineAlpha.set(outlineVisible && !hide); + if (objects != null) { + for (SegmentedObject object : objects) { + if (object != null && object == selectedObject && outlineWidth > 0) { + object.drawOutline(canvas, after, outlineWidth, outlineAlpha); + break; + } + } + } + } + + public boolean setOutlineBounds; + public final Matrix outlineMatrix = new Matrix(); + private Path outlineBoundsPath, outlineBoundsInnerPath; + private final RectF outlineBounds = new RectF(); + public void updateOutlineBounds(boolean set) { + setOutlineBounds = set; + if (set) { + if (outlineBoundsPath == null) { + outlineBoundsPath = new Path(); + } else { + outlineBoundsPath.rewind(); + } + if (outlineBoundsInnerPath == null) { + outlineBoundsInnerPath = new Path(); + AndroidUtilities.rectTmp.set(0, 0, 1, 1); + outlineBoundsInnerPath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.rectTmp.width() * .12f, AndroidUtilities.rectTmp.height() * .12f, Path.Direction.CW); + } + outlineBoundsPath.addPath(outlineBoundsInnerPath, outlineMatrix); + outlineBoundsPath.computeBounds(outlineBounds, true); + } + } public void drawSegmentBorderPath(Canvas canvas, ImageReceiver imageReceiver, Matrix matrix, ViewGroup parent) { segmentBorderAlpha.setParent(parent); - if ((bordersAnimator == null && segmentBorderAlpha.get() <= 0) || parent == null) { + if (bordersAnimator == null && segmentBorderAlpha.get() <= 0 || parent == null) { return; } imageReceiverWidth = imageReceiver.getImageWidth(); imageReceiverHeight = imageReceiver.getImageHeight(); - matrix.invert(imageReceiverMatrix); + imageReceiverMatrix.set(matrix); float progress = (bordersAnimatorValueStart + bordersAnimatorValue) % 1.0f; - float alpha = segmentBorderAlpha.set(bordersAnimator == null ? 0f : 1f); + float alpha = segmentBorderAlpha.set(bordersAnimator != null); canvas.drawColor(Theme.multAlpha(0x50000000, alpha)); if (objects != null) { for (SegmentedObject object : objects) { - object.drawBorders(canvas, progress, alpha, parent); + if (object == null) continue; + object.drawAnimationBorders(canvas, progress, alpha, parent); } } @@ -298,6 +566,7 @@ public void enableClippingMode(Utilities.Callback onClickListen } }); + actionTextView.setText(LocaleController.getString(R.string.SegmentationTabToCrop)); actionTextView.animate().cancel(); actionTextView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(240).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); if (bordersAnimator != null) { @@ -337,26 +606,27 @@ public boolean dispatchTouchEvent(MotionEvent ev) { } public SegmentedObject objectBehind(float tx, float ty) { - float[] p = new float[] { tx, ty }; - imageReceiverMatrix.mapPoints(p); - int w, h; - if (objects[0].orientation / 90 % 2 != 0) { - w = sourceBitmap.getHeight(); - h = sourceBitmap.getWidth(); - } else { - w = sourceBitmap.getWidth(); - h = sourceBitmap.getHeight(); - } + if (sourceBitmap == null) return null; for (int i = 0; i < objects.length; ++i) { + SegmentedObject obj = objects[i]; + if (obj == null) continue; + int w, h; + if (objects[i].orientation / 90 % 2 != 0) { + w = sourceBitmap.getHeight(); + h = sourceBitmap.getWidth(); + } else { + w = sourceBitmap.getWidth(); + h = sourceBitmap.getHeight(); + } AndroidUtilities.rectTmp.set( objects[i].rotatedBounds.left / w * imageReceiverWidth, objects[i].rotatedBounds.top / h * imageReceiverHeight, objects[i].rotatedBounds.right / w * imageReceiverWidth, objects[i].rotatedBounds.bottom / h * imageReceiverHeight ); - AndroidUtilities.rectTmp.offset(-imageReceiverWidth / 2f, -imageReceiverHeight / 2f); - if (AndroidUtilities.rectTmp.contains(p[0], p[1])) { - return objects[i]; + imageReceiverMatrix.mapRect(AndroidUtilities.rectTmp); + if (AndroidUtilities.rectTmp.contains(tx, ty)) { + return obj; } } return null; @@ -374,10 +644,22 @@ public void disableClippingMode() { actionTextView.animate().alpha(0f).scaleX(0.7f).scaleY(0.7f).setDuration(240).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); } + private ArrayList exclusionRects = new ArrayList<>(); + private Rect exclusionRect = new Rect(); + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - actionTextView.setTranslationY(getMeasuredWidth() / 2f + dp(10)); + actionTextView.setTranslationY(-(getMeasuredWidth() / 2f + dp(10))); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + exclusionRects.clear(); + if (outlineVisible) { + exclusionRects.add(exclusionRect); + int h = (int) (getMeasuredHeight() * .3f); + exclusionRect.set(0, (getMeasuredHeight() - h) / 2, dp(20), (getMeasuredHeight() + h) / 2); + } + setSystemGestureExclusionRects(exclusionRects); + } } public boolean isSegmentedState() { @@ -390,7 +672,7 @@ public void setSegmentedState(boolean segmentedState, SegmentedObject selectedOb } public Bitmap getSegmentedDarkMaskImage() { - return isSegmentedState && selectedObject != null ? selectedObject.darkMaskImage : null; + return isSegmentedState && selectedObject != null ? selectedObject.getDarkMaskImage() : null; } public boolean hasSegmentedBitmap() { @@ -415,7 +697,7 @@ public Bitmap getSegmentedImage(Bitmap filteredBitmap, boolean hasFilters, int o if (hasFilters && filteredBitmap != null) { return cutSegmentInFilteredBitmap(filteredBitmap, orientation); } - return selectedObject.image; + return selectedObject.getImage(); } @Nullable @@ -442,15 +724,15 @@ public Bitmap getThanosImage(MediaController.PhotoEntry photoEntry, int orientat if (object.orientation != 0 && photoEntry.isFiltered) { Matrix matrix = new Matrix(); - matrix.postRotate(object.orientation, object.darkMaskImage.getWidth() / 2f, object.darkMaskImage.getHeight() / 2f); + matrix.postRotate(object.orientation, object.getDarkMaskImage().getWidth() / 2f, object.getDarkMaskImage().getHeight() / 2f); if (object.orientation / 90 % 2 != 0) { - float dxy = (object.darkMaskImage.getHeight() - object.darkMaskImage.getWidth()) / 2f; + float dxy = (object.getDarkMaskImage().getHeight() - object.getDarkMaskImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } - matrix.postScale(filteredBitmap.getWidth() / (float) object.darkMaskImage.getHeight(), filteredBitmap.getHeight() / (float) object.darkMaskImage.getWidth()); - canvas.drawBitmap(object.darkMaskImage, matrix, maskPaint); + matrix.postScale(filteredBitmap.getWidth() / (float) object.getDarkMaskImage().getHeight(), filteredBitmap.getHeight() / (float) object.getDarkMaskImage().getWidth()); + canvas.drawBitmap(object.getDarkMaskImage(), matrix, maskPaint); } else { - canvas.drawBitmap(object.darkMaskImage, null, dstRect, maskPaint); + canvas.drawBitmap(object.getDarkMaskImage(), null, dstRect, maskPaint); } if (paintedBitmap != null) { @@ -502,15 +784,20 @@ protected void dispatchDraw(Canvas canvas) { canvas.drawPath(dashPath, dashPaint); } - private Bitmap createSmoothEdgesSegmentedImage(int x, int y, Bitmap inputBitmap) { + private Bitmap createSmoothEdgesSegmentedImage(int x, int y, Bitmap inputBitmap, boolean full) { Bitmap srcBitmap = getSourceBitmap(); - if (inputBitmap == null || srcBitmap == null) { + if (inputBitmap == null || inputBitmap.isRecycled() || srcBitmap == null) { return null; } Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); Bitmap bluredBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bluredBitmap); - canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + if (full) { + canvas.scale((float) bluredBitmap.getWidth() / inputBitmap.getWidth(), (float) bluredBitmap.getHeight() / inputBitmap.getHeight()); + canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + } else { + canvas.drawBitmap(inputBitmap, x, y, bitmapPaint); + } Utilities.stackBlurBitmap(bluredBitmap, 5); Bitmap resultBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888); @@ -524,7 +811,13 @@ private Bitmap createSmoothEdgesSegmentedImage(int x, int y, Bitmap inputBitmap) return segmentedImage; } - public void segmentImage(Bitmap source, int orientation, int containerWidth, int containerHeight) { + public void segmentImage(Bitmap source, int orientation, int containerWidth, int containerHeight, Utilities.Callback whenEmpty) { + if (containerWidth <= 0) { + containerWidth = AndroidUtilities.displaySize.x; + } + if (containerHeight <= 0) { + containerHeight = AndroidUtilities.displaySize.y; + } this.containerWidth = containerWidth; this.containerHeight = containerHeight; if (segmentingLoaded) { @@ -532,6 +825,112 @@ public void segmentImage(Bitmap source, int orientation, int containerWidth, int } if (segmentingLoading || source == null) return; if (Build.VERSION.SDK_INT < 24) return; + sourceBitmap = source; + this.orientation = orientation; + detectedEmoji = null; + segment(source, orientation, subjects -> { + final ArrayList finalObjects = new ArrayList<>(); + + Utilities.themeQueue.postRunnable(() -> { + if (sourceBitmap == null || segmentingLoaded) return; + Matrix matrix = new Matrix(); + matrix.postScale(1f / sourceBitmap.getWidth(), 1f / sourceBitmap.getHeight()); + matrix.postTranslate(-.5f, -.5f); + matrix.postRotate(orientation); + matrix.postTranslate(.5f, .5f); + if (orientation / 90 % 2 != 0) { + matrix.postScale(sourceBitmap.getHeight(), sourceBitmap.getWidth()); + } else { + matrix.postScale(sourceBitmap.getWidth(), sourceBitmap.getHeight()); + } + if (subjects.isEmpty()) { + SegmentedObject o = new SegmentedObject(); + o.bounds.set(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()); + o.rotatedBounds.set(o.bounds); + matrix.mapRect(o.rotatedBounds); + o.orientation = orientation; + o.image = createSmoothEdgesSegmentedImage(0, 0, sourceBitmap, false); + if (o.image == null) { + FileLog.e(new RuntimeException("createSmoothEdgesSegmentedImage failed on empty image")); + return; + } + o.darkMaskImage = o.makeDarkMaskImage(); + createSegmentImagePath(o, this.containerWidth, this.containerHeight); + segmentBorderImageWidth = o.borderImageWidth; + segmentBorderImageHeight = o.borderImageHeight; + + finalObjects.add(o); + AndroidUtilities.runOnUIThread(() -> { + empty = true; + objects = finalObjects.toArray(new SegmentedObject[0]); + whenEmpty.run(o); + }); + selectedObject = o; + segmentingLoaded = true; + segmentingLoading = false; + return; + } else { + for (int i = 0; i < subjects.size(); ++i) { + SubjectMock subject = subjects.get(i); + SegmentedObject o = new SegmentedObject(); + o.bounds.set(subject.startX, subject.startY, subject.startX + subject.width, subject.startY + subject.height); + o.rotatedBounds.set(o.bounds); + matrix.mapRect(o.rotatedBounds); + o.orientation = orientation; + o.image = createSmoothEdgesSegmentedImage(subject.startX, subject.startY, subject.bitmap, false); + if (o.image == null) continue; + o.darkMaskImage = o.makeDarkMaskImage(); + createSegmentImagePath(o, this.containerWidth, this.containerHeight); + segmentBorderImageWidth = o.borderImageWidth; + segmentBorderImageHeight = o.borderImageHeight; + + finalObjects.add(o); + } + } + selectedObject = null; + + segmentingLoaded = true; + segmentingLoading = false; + AndroidUtilities.runOnUIThread(() -> { + empty = false; + objects = finalObjects.toArray(new SegmentedObject[0]); + if (objects.length > 0) { + stickerCutOutBtn.setScaleX(0.3f); + stickerCutOutBtn.setScaleY(0.3f); + stickerCutOutBtn.setAlpha(0f); + stickerCutOutBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(250).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + } + }); + + }); + }, whenEmpty); + } + + private static class SubjectMock { + public Bitmap bitmap; + public int startX, startY, width, height; + public static SubjectMock of(Subject subject) { + SubjectMock m = new SubjectMock(); + m.bitmap = subject.getBitmap(); + m.startX = subject.getStartX(); + m.startY = subject.getStartY(); + m.width = subject.getWidth(); + m.height = subject.getHeight(); + return m; + } + public static SubjectMock mock(Bitmap source) { + SubjectMock m = new SubjectMock(); + m.width = m.height = (int) (Math.min(source.getWidth(), source.getHeight()) * .4f); + m.bitmap = Bitmap.createBitmap(m.width, m.height, Bitmap.Config.ARGB_8888); + new Canvas(m.bitmap).drawRect(0, 0, m.width, m.height, Theme.DEBUG_RED); + m.startX = (source.getWidth() - m.width) / 2; + m.startY = (source.getHeight() - m.height) / 2; + return m; + } + } + + private void segment(Bitmap bitmap, int orientation, Utilities.Callback> whenDone, Utilities.Callback whenEmpty) { + segmentingLoading = true; SubjectSegmenter segmenter = SubjectSegmentation.getClient( new SubjectSegmenterOptions.Builder() .enableMultipleSubjects( @@ -541,85 +940,64 @@ public void segmentImage(Bitmap source, int orientation, int containerWidth, int ) .build() ); - segmentingLoading = true; - sourceBitmap = source; - InputImage inputImage = InputImage.fromBitmap(source, orientation); + if (EmuDetector.with(getContext()).detect()) { + ArrayList list = new ArrayList<>(); + list.add(SubjectMock.mock(sourceBitmap)); + whenDone.run(list); + return; + } + InputImage inputImage = InputImage.fromBitmap(bitmap, orientation); segmenter.process(inputImage) - .addOnSuccessListener(result -> { - if (sourceBitmap == null) return; - final ArrayList finalObjects = new ArrayList<>(); - Utilities.themeQueue.postRunnable(() -> { - if (sourceBitmap == null) return; - List subjects = result.getSubjects(); - Matrix matrix = new Matrix(); - matrix.postScale(1f / sourceBitmap.getWidth(), 1f / sourceBitmap.getHeight()); - matrix.postTranslate(-.5f, -.5f); - matrix.postRotate(orientation); - matrix.postTranslate(.5f, .5f); - if (orientation / 90 % 2 != 0) { - matrix.postScale(sourceBitmap.getHeight(), sourceBitmap.getWidth()); - } else { - matrix.postScale(sourceBitmap.getWidth(), sourceBitmap.getHeight()); - } - for (int i = 0; i < subjects.size(); ++i) { - Subject subject = subjects.get(i); - SegmentedObject o = new SegmentedObject(); - o.bounds.set(subject.getStartX(), subject.getStartY(), subject.getStartX() + subject.getWidth(), subject.getStartY() + subject.getHeight()); - o.rotatedBounds.set(o.bounds); - matrix.mapRect(o.rotatedBounds); - o.orientation = orientation; - o.image = createSmoothEdgesSegmentedImage(subject.getStartX(), subject.getStartY(), subject.getBitmap()); - if (o.image == null) continue; - - o.darkMaskImage = Bitmap.createBitmap(o.image.getWidth(), o.image.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(o.darkMaskImage); - canvas.drawColor(Color.BLACK); - Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); - maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - canvas.drawBitmap(o.image, 0, 0, maskPaint); - - createSegmentImagePath(o, containerWidth, containerHeight); - segmentBorderImageWidth = o.borderImageWidth; - segmentBorderImageHeight = o.borderImageHeight; - - finalObjects.add(o); - } - selectedObject = null; - - segmentingLoaded = true; - segmentingLoading = false; - AndroidUtilities.runOnUIThread(() -> { - objects = finalObjects.toArray(new SegmentedObject[1]); - if (objects.length > 0) { - stickerCutOutBtn.setScaleX(0.3f); - stickerCutOutBtn.setScaleY(0.3f); - stickerCutOutBtn.setAlpha(0f); - stickerCutOutBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(250).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); - } - }); + .addOnSuccessListener(result -> { + ArrayList list = new ArrayList<>(); + for (int i = 0; i < result.getSubjects().size(); ++i) { + list.add(SubjectMock.of(result.getSubjects().get(i))); + } + whenDone.run(list); + }) + .addOnFailureListener(error -> { + segmentingLoading = false; + FileLog.e(error); + if (isWaitingMlKitError(error) && isAttachedToWindow()) { + AndroidUtilities.runOnUIThread(() -> segmentImage(bitmap, orientation, containerWidth, containerHeight, whenEmpty), 2000); + } else { + whenDone.run(new ArrayList<>()); + } + }); - }); - }) - .addOnFailureListener(error -> { - segmentingLoading = false; - FileLog.e(error); - if (isWaitingMlKitError(error) && isAttachedToWindow()) { - AndroidUtilities.runOnUIThread(() -> segmentImage(source, orientation, containerWidth, containerHeight), 2000); - } else { - segmentingLoaded = true; + + if (detectedEmoji == null) { + ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS) + .process(inputImage) + .addOnSuccessListener(labels -> { + if (labels.size() <= 0) { + FileLog.d("objimg: no objects"); + return; } + detectedEmoji = ObjectDetectionEmojis.labelToEmoji(labels.get(0).getIndex()); + FileLog.d("objimg: detected #" + labels.get(0).getIndex() + " " + detectedEmoji + " " + labels.get(0).getText()); + Emoji.getEmojiDrawable(detectedEmoji); // preload + }) + .addOnFailureListener(e -> { }); + } + + // preload emojis + List defaultReactions = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + for (int i = 0; i <= Math.min(defaultReactions.size(), 8); ++i) { + Emoji.getEmojiDrawable(defaultReactions.get(i).reaction); + } } private void createSegmentImagePath(SegmentedObject object, int containerWidth, int containerHeight) { - int imageWidth = object.image.getWidth(); - int imageHeight = object.image.getHeight(); + int imageWidth = object.getImage().getWidth(); + int imageHeight = object.getImage().getHeight(); int maxImageSize = Math.max(imageWidth, imageHeight); - float scaleFactor = maxImageSize / 256f; + float scaleFactor = maxImageSize / (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH ? 512f : 384f); if (object.orientation / 90 % 2 != 0) { - imageWidth = object.image.getHeight(); - imageHeight = object.image.getWidth(); + imageWidth = object.getImage().getHeight(); + imageHeight = object.getImage().getWidth(); } Bitmap bitmap = Bitmap.createBitmap((int) (imageWidth / scaleFactor), (int) (imageHeight / scaleFactor), Bitmap.Config.ARGB_8888); @@ -628,15 +1006,15 @@ private void createSegmentImagePath(SegmentedObject object, int containerWidth, rectF.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); if (object.orientation != 0) { Matrix matrix = new Matrix(); - matrix.postRotate(object.orientation, object.image.getWidth() / 2f, object.image.getHeight() / 2f); + matrix.postRotate(object.orientation, object.getImage().getWidth() / 2f, object.image.getHeight() / 2f); if (object.orientation / 90 % 2 != 0) { - float dxy = (object.image.getHeight() - object.image.getWidth()) / 2f; + float dxy = (object.getImage().getHeight() - object.getImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } matrix.postScale(rectF.width() / imageWidth, rectF.height() / imageHeight); - canvas.drawBitmap(object.image, matrix, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawBitmap(object.getImage(), matrix, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); } else { - canvas.drawBitmap(object.image, null, rectF, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + canvas.drawBitmap(object.getImage(), null, rectF, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); } int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()]; @@ -647,7 +1025,10 @@ private void createSegmentImagePath(SegmentedObject object, int containerWidth, Point leftPoint = null; Point rightPoint = null; - scaleFactor = containerWidth / (float) bitmap.getWidth(); + scaleFactor = Math.min( + containerWidth / (float) bitmap.getWidth(), + containerHeight / (float) bitmap.getHeight() + ); for (int i = 0; i < pixels.length; i++) { int y = i / bitmap.getWidth(); int x = i - y * bitmap.getWidth(); @@ -730,8 +1111,8 @@ private void createSegmentImagePath(SegmentedObject object, int containerWidth, topBottomPointsSet.addAll(bottomPoints); topBottomPointsSet.addAll(topPoints); - List topBottomPointsList = new ArrayList<>(topBottomPointsSet); - List leftRightPointsList = new ArrayList<>(leftRightPointsSet); + List topBottomPointsList = removeUnnecessaryPoints(new ArrayList<>(topBottomPointsSet)); + List leftRightPointsList = removeUnnecessaryPoints(new ArrayList<>(leftRightPointsSet)); Path path1 = new Path(); for (int i = 0; i < leftRightPointsList.size(); i += 2) { @@ -762,9 +1143,38 @@ private void createSegmentImagePath(SegmentedObject object, int containerWidth, object.borderImageWidth = imageWidth * scaleFactor; object.borderImageHeight = imageHeight * scaleFactor; object.segmentBorderPath.offset(-object.borderImageWidth / 2f, -object.borderImageHeight / 2f); + object.initPoints(); + } + + public static List removeUnnecessaryPoints(List points) { + if (points.size() < 3) return points; + + List optimizedPoints = new ArrayList<>(); + optimizedPoints.add(points.get(0)); + + for (int i = 1; i < points.size() - 1; i++) { + Point prev = points.get(i - 1); + Point curr = points.get(i); + Point next = points.get(i + 1); + + if (!isPointOnLine(prev, curr, next)) { + optimizedPoints.add(curr); + } + } + + optimizedPoints.add(points.get(points.size() - 1)); + return optimizedPoints; + } + + private static boolean isPointOnLine(Point a, Point b, Point c) { + int crossProduct = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); + return Math.abs(crossProduct - (-1.0f)) < 0.15f; } public Bitmap cutSegmentInFilteredBitmap(Bitmap filteredBitmap, int orientation) { + if (filteredBitmap == null) { + return null; + } if (selectedObject == null) { return filteredBitmap; } @@ -782,15 +1192,15 @@ public Bitmap cutSegmentInFilteredBitmap(Bitmap filteredBitmap, int orientation) dstRect.set(0, 0, filteredBitmap.getWidth(), filteredBitmap.getHeight()); if (selectedObject.orientation != 0) { Matrix matrix = new Matrix(); - matrix.postRotate(selectedObject.orientation, selectedObject.darkMaskImage.getWidth() / 2f, selectedObject.darkMaskImage.getHeight() / 2f); + matrix.postRotate(selectedObject.orientation, selectedObject.getDarkMaskImage().getWidth() / 2f, selectedObject.getDarkMaskImage().getHeight() / 2f); if (selectedObject.orientation / 90 % 2 != 0) { - float dxy = (selectedObject.image.getHeight() - selectedObject.image.getWidth()) / 2f; + float dxy = (selectedObject.getImage().getHeight() - selectedObject.getImage().getWidth()) / 2f; matrix.postTranslate(dxy, -dxy); } - matrix.postScale(filteredBitmap.getWidth() / (float) selectedObject.darkMaskImage.getHeight(), filteredBitmap.getHeight() / (float) selectedObject.darkMaskImage.getWidth()); - canvas.drawBitmap(selectedObject.darkMaskImage, matrix, maskPaint); + matrix.postScale(filteredBitmap.getWidth() / (float) selectedObject.getDarkMaskImage().getHeight(), filteredBitmap.getHeight() / (float) selectedObject.getDarkMaskImage().getWidth()); + canvas.drawBitmap(selectedObject.getDarkMaskImage(), matrix, maskPaint); } else { - canvas.drawBitmap(selectedObject.darkMaskImage, null, dstRect, maskPaint); + canvas.drawBitmap(selectedObject.getDarkMaskImage(), null, dstRect, maskPaint); } return result; } @@ -815,6 +1225,13 @@ public void clean() { actionTextView.setAlpha(0f); actionTextView.setScaleX(0.3f); actionTextView.setScaleY(0.3f); + if (stickerUploader != null) { + if (!stickerUploader.uploaded) + stickerUploader.destroy(true); + stickerUploader = null; + } + hideLoadingDialog(); + isThanosInProgress = false; } public static boolean isWaitingMlKitError(Exception e) { @@ -823,8 +1240,9 @@ public static boolean isWaitingMlKitError(Exception e) { public void setCurrentAccount(int account) { if (currentAccount != account) { - if (currentAccount >= 0) { + if (currentAccount >= 0 && isAttachedToWindow()) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingStarted); @@ -833,8 +1251,9 @@ public void setCurrentAccount(int account) { currentAccount = account; - if (currentAccount >= 0) { + if (currentAccount >= 0 && isAttachedToWindow()) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingStarted); @@ -848,6 +1267,7 @@ protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (currentAccount >= 0) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingStarted); @@ -860,6 +1280,7 @@ protected void onAttachedToWindow() { super.onAttachedToWindow(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingStarted); @@ -875,6 +1296,18 @@ public void didReceivedNotification(int id, int account, Object... args) { stickerUploader.file = file; uploadMedia(); } + } else if (id == NotificationCenter.fileUploadProgressChanged) { + String location = (String) args[0]; + if (stickerUploader != null && location.equalsIgnoreCase(stickerUploader.finalPath)) { + final long uploadedSize = (long) args[1]; + final long totalSize = (long) args[2]; + if (totalSize > 0) { + stickerUploader.uploadProgress = Utilities.clamp(uploadedSize / (float) totalSize, 1, stickerUploader.uploadProgress); + if (loadingToast != null) { + loadingToast.setProgress(stickerUploader.getProgress()); + } + } + } } else if (id == NotificationCenter.fileUploadFailed) { String location = (String) args[0]; if (stickerUploader != null && location.equalsIgnoreCase(stickerUploader.finalPath)) { @@ -892,21 +1325,14 @@ public void didReceivedNotification(int id, int account, Object... args) { long availableSize = (Long) args[2]; long finalSize = (Long) args[3]; float convertingProgress = (float) args[4]; -// progress = convertingProgress * .3f + uploadProgress * .7f; -// NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.uploadStoryProgress, path, progress); - -// if (firstSecondSize < 0 && convertingProgress * duration >= 1000) { -// firstSecondSize = availableSize; -// } + stickerUploader.messageObject.videoEditedInfo.needUpdateProgress = true; FileLoader.getInstance(currentAccount).checkUploadNewDataAvailable(finalPath, false, Math.max(1, availableSize), finalSize, convertingProgress); -// if (finalSize > 0) { -// if (firstSecondSize < 0) { -// firstSecondSize = finalSize; -// } -// ready = true; -// } + stickerUploader.convertingProgress = Math.max(stickerUploader.convertingProgress, convertingProgress); + if (loadingToast != null) { + loadingToast.setProgress(stickerUploader.getProgress()); + } } } else if (id == NotificationCenter.filePreparingFailed) { if (stickerUploader == null) return; @@ -916,13 +1342,19 @@ public void didReceivedNotification(int id, int account, Object... args) { } } - public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker) { - uploadStickerFile(path, videoEditedInfo, emoji, stickerPackName, addToFavorite, stickerSet, replacedSticker, ""); + public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker, String thumbPath, Utilities.Callback whenDone, Utilities.Callback2 customStickerHandler) { + uploadStickerFile(path, videoEditedInfo, emoji, stickerPackName, addToFavorite, stickerSet, replacedSticker, thumbPath, whenDone, customStickerHandler, ""); } - public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker, CharSequence stickerShortPackName) { + public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, String emoji, CharSequence stickerPackName, boolean addToFavorite, TLRPC.StickerSet stickerSet, TLRPC.Document replacedSticker, String thumbPath, Utilities.Callback whenDone, Utilities.Callback2 customStickerHandler, CharSequence stickerShortPackName) { AndroidUtilities.runOnUIThread(() -> { - stickerUploader = new StickerUploader(); + final boolean newStickerUploader = !(whenDone != null && stickerUploader != null && stickerUploader.uploaded); + if (newStickerUploader) { + if (stickerUploader != null) { + stickerUploader.destroy(true); + } + stickerUploader = new StickerUploader(); + } stickerUploader.emoji = emoji; stickerUploader.path = stickerUploader.finalPath = path; stickerUploader.stickerShortPackName = stickerShortPackName; @@ -931,7 +1363,13 @@ public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, Stri stickerUploader.stickerSet = stickerSet; stickerUploader.replacedSticker = replacedSticker; stickerUploader.videoEditedInfo = videoEditedInfo; - if (videoEditedInfo != null) { + stickerUploader.thumbPath = thumbPath; + stickerUploader.whenDone = whenDone; + stickerUploader.customHandler = customStickerHandler; + stickerUploader.setupFiles(); + if (!newStickerUploader) { + afterUploadingMedia(); + } else if (videoEditedInfo != null) { TLRPC.TL_message message = new TLRPC.TL_message(); message.id = 1; stickerUploader.finalPath = message.attachPath = StoryEntry.makeCacheFile(UserConfig.selectedAccount, "webm").getAbsolutePath(); @@ -939,25 +1377,50 @@ public void uploadStickerFile(String path, VideoEditedInfo videoEditedInfo, Stri stickerUploader.messageObject.videoEditedInfo = videoEditedInfo; MediaController.getInstance().scheduleVideoConvert(stickerUploader.messageObject, false, false); } else { - FileLoader.getInstance(UserConfig.selectedAccount).uploadFile(path, false, true, ConnectionsManager.FileTypeFile); + FileLoader.getInstance(currentAccount).uploadFile(path, false, true, ConnectionsManager.FileTypeFile); + } + if (whenDone == null) { + showLoadingDialog(); } - showLoadingDialog(); }, 300); } private void showLoadingDialog() { - loadingDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER, new DarkThemeResourceProvider()); - loadingDialog.show(); + if (loadingToast == null) { + loadingToast = new DownloadButton.PreparingVideoToast(getContext()); + } + loadingToast.setOnCancelListener(() -> { + if (stickerUploader != null) { + if (stickerUploader.messageObject != null) { + MediaController.getInstance().cancelVideoConvert(stickerUploader.messageObject); + FileLoader.getInstance(currentAccount).cancelFileUpload(stickerUploader.finalPath, false); + if (stickerUploader.reqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(stickerUploader.reqId, true); + } + } + stickerUploader.destroy(true); + stickerUploader = null; + } + loadingToast.hide(); + loadingToast = null; + }); + if (loadingToast.getParent() == null) { + addView(loadingToast, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + } + loadingToast.show(); } private void hideLoadingDialog() { - if (loadingDialog != null) { - loadingDialog.dismiss(); - loadingDialog = null; + if (loadingToast != null) { + loadingToast.hide(); + loadingToast = null; } } private void uploadMedia() { + final StickerUploader stickerUploader = this.stickerUploader; + if (stickerUploader == null) + return; TLRPC.TL_messages_uploadMedia req = new TLRPC.TL_messages_uploadMedia(); req.peer = new TLRPC.TL_inputPeerSelf(); req.media = new TLRPC.TL_inputMediaUploadedDocument(); @@ -986,23 +1449,54 @@ private void uploadMedia() { private void showError(TLRPC.TL_error error) { if (error != null) { + if ("PACK_TITLE_INVALID".equals(error.text)) { + return; + } BulletinFactory.of((FrameLayout) getParent(), resourcesProvider).createErrorBulletin(error.text).show(); } } private void afterUploadingMedia() { + final StickerUploader stickerUploader = this.stickerUploader; + if (stickerUploader == null) { + return; + } final int currentAccount = UserConfig.selectedAccount; + stickerUploader.uploaded = true; + if (stickerUploader.customHandler != null) { + hideLoadingDialog(); + stickerUploader.customHandler.run(stickerUploader.finalPath, stickerUploader.tlInputStickerSetItem.document); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated), 250); + return; + } if (stickerUploader.replacedSticker != null) { TLRPC.TL_stickers_replaceSticker req = new TLRPC.TL_stickers_replaceSticker(); - req.sticker = MediaDataController.getInputStickerSetItem(stickerUploader.replacedSticker, "").document; + req.sticker = MediaDataController.getInputStickerSetItem(stickerUploader.replacedSticker, stickerUploader.emoji).document; req.new_sticker = stickerUploader.tlInputStickerSetItem; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, true); + hideLoadingDialog(); + }, 450); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } else if (stickerUploader.stickerPackName != null) { TLRPC.TL_stickers_createStickerSet req = new TLRPC.TL_stickers_createStickerSet(); @@ -1011,33 +1505,68 @@ private void afterUploadingMedia() { req.short_name = stickerUploader.stickerShortPackName != null ? stickerUploader.stickerShortPackName.toString() : ""; req.stickers.add(stickerUploader.tlInputStickerSetItem); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, false); + hideLoadingDialog(); + }, 250); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } else if (stickerUploader.addToFavorite) { hideLoadingDialog(); NotificationCenter.getInstance(currentAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false); AndroidUtilities.runOnUIThread(() -> MediaDataController.getInstance(UserConfig.selectedAccount).addRecentSticker(MediaDataController.TYPE_FAVE, null, stickerUploader.mediaDocument.document, (int) (System.currentTimeMillis() / 1000), false), 350); + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(true); + } } else if (stickerUploader.stickerSet != null) { TLRPC.TL_stickers_addStickerToSet req = new TLRPC.TL_stickers_addStickerToSet(); req.stickerset = MediaDataController.getInputStickerSet(stickerUploader.stickerSet); req.sticker = stickerUploader.tlInputStickerSetItem; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + if (loadingToast != null) { + loadingToast.setProgress(1f); + } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, stickerUploader.mediaDocument.document, stickerUploader.thumbPath, false); + hideLoadingDialog(); + }, 450); + success = true; + } else { + showError(error); + hideLoadingDialog(); + } + if (stickerUploader.whenDone != null) { + stickerUploader.whenDone.run(success); + stickerUploader.whenDone = null; } - showError(error); - hideLoadingDialog(); })); } } - private static class StickerUploader { + public static class StickerUploader { public String path; public String finalPath; public String emoji; @@ -1049,9 +1578,59 @@ private static class StickerUploader { public boolean addToFavorite; public TLRPC.StickerSet stickerSet; public TLRPC.Document replacedSticker; + public String thumbPath; + public Utilities.Callback2 customHandler; + public Utilities.Callback whenDone; + public boolean uploaded; + + public ArrayList finalFiles = new ArrayList(); + public ArrayList files = new ArrayList(); public MessageObject messageObject; public VideoEditedInfo videoEditedInfo; + public int reqId; + + private float convertingProgress = 0, uploadProgress = 0; + public float getProgress() { + final float maxPercent = customHandler == null ? .9f : 1f; + if (videoEditedInfo == null) { + return maxPercent * uploadProgress; + } + return maxPercent * (.5f * convertingProgress + .5f * uploadProgress); + } + + public void setupFiles() { + if (!TextUtils.isEmpty(finalPath)) { + finalFiles.add(new File(finalPath)); + } + if (!TextUtils.isEmpty(path) && !TextUtils.equals(path, finalPath)) { + files.add(new File(path)); + } + if (!TextUtils.isEmpty(thumbPath)) { + files.add(new File(thumbPath)); + } + } + + public void destroy(boolean all) { + if (all) { + for (File file : finalFiles) { + try { + file.delete(); + } catch (Exception e) { + FileLog.e(e); + } + } + } + finalFiles.clear(); + for (File file : files) { + try { + file.delete(); + } catch (Exception e) { + FileLog.e(e); + } + } + files.clear(); + } } private static class Point extends android.graphics.Point { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java index 41386272b3..9ad20883dc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java @@ -349,7 +349,7 @@ public int getTextSize() { } public void setSwatch(Swatch swatch) { - this.swatch = swatch; + this.swatch = swatch.clone(); updateColor(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java index 7be320ebe1..52973e071b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java @@ -58,6 +58,14 @@ public void setData(String paintPath, ArrayList ent } } + public boolean drawChildren = true; + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (!drawChildren) return false; + return super.drawChild(canvas, child, drawingTime); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ignoreLayout = true; @@ -73,9 +81,14 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (child instanceof EditTextOutline) { child.measure(MeasureSpec.makeMeasureSpec(entity.viewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - float sc = entity.textViewWidth * width / entity.viewWidth; - child.setScaleX(entity.scale * sc); - child.setScaleY(entity.scale * sc); + float scale; + if (entity.customTextView) { + scale = entity.width * getMeasuredWidth() / entity.viewWidth; + } else { + scale = entity.scale * (entity.textViewWidth * width / entity.viewWidth); + } + child.setScaleX(scale); + child.setScaleY(scale); } else { child.measure(MeasureSpec.makeMeasureSpec((int) (width * entity.width), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (height * entity.height), MeasureSpec.EXACTLY)); } @@ -118,15 +131,20 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto if (entity == null) { continue; } - int x, y; + int x, y, w = child.getMeasuredWidth(), h = child.getMeasuredHeight(); if (child instanceof EditTextOutline) { - x = (int) (width * entity.textViewX) - child.getMeasuredWidth() / 2; - y = (int) (height * entity.textViewY) - child.getMeasuredHeight() / 2; + if (entity.customTextView) { + x = (int) (width * (entity.x + entity.width / 2f)) - child.getMeasuredWidth() / 2; + y = (int) (height * (entity.y + entity.height / 2f)) - child.getMeasuredHeight() / 2; + } else { + x = (int) (width * entity.textViewX) - child.getMeasuredWidth() / 2; + y = (int) (height * entity.textViewY) - child.getMeasuredHeight() / 2; + } } else { x = (int) (width * entity.x); y = (int) (height * entity.y); } - child.layout(x, y, x + child.getMeasuredWidth(), y + child.getMeasuredHeight()); + child.layout(x, y, x + w, y + h); } } } @@ -169,7 +187,7 @@ public void setEntities(ArrayList entities, boolean View child = null; if (entity.type == 0) { BackupImageView imageView = new BackupImageView(getContext()); - imageView.setLayerNum(8); + imageView.setLayerNum(4 | 8); imageView.setAspectFit(true); ImageReceiver imageReceiver = imageView.getImageReceiver(); if (isVideo) { @@ -187,7 +205,7 @@ public void setEntities(ArrayList entities, boolean } } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(entity.document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(entity.document), null, ImageLocation.getForDocument(thumb, entity.document), null, "webp", entity.parentObject, 1); + imageReceiver.setImage(ImageLocation.getForDocument(entity.document), null, null, null, ImageLocation.getForDocument(thumb, entity.document), null, null, 0, "webp", entity.parentObject, 1); if ((entity.subType & 2) != 0) { imageView.setScaleX(-1); } @@ -212,6 +230,14 @@ public boolean onTouchEvent(MotionEvent event) { for (VideoEditedInfo.EmojiEntity e : entity.entities) { text.setSpan(new AnimatedEmojiSpan(e.document_id, editText.getPaint().getFontMetricsInt()), e.offset, e.offset + e.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } + if (text instanceof Spanned) { + Emoji.EmojiSpan[] spans = ((Spanned) text).getSpans(0, text.length(), Emoji.EmojiSpan.class); + if (spans != null) { + for (int i = 0; i < spans.length; ++i) { + spans[i].scale = .85f; + } + } + } editText.setText(text); editText.setGravity(Gravity.CENTER); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java index 06770df5ac..15d56d5609 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java @@ -27,6 +27,7 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; +import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -49,8 +50,10 @@ import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -91,7 +94,7 @@ public class PollVotesAlert extends BottomSheet { private ArrayList voters = new ArrayList<>(); - private TextView titleTextView; + private AnimatedEmojiSpan.TextViewEmojis titleTextView; private int scrollOffsetY; private int topBeforeSwitch; @@ -144,7 +147,7 @@ public int getCollapsed() { public class SectionCell extends FrameLayout { - private TextView textView; + private AnimatedEmojiSpan.TextViewEmojis textView; private TextView middleTextView; private AnimatedTextView righTextView; @@ -153,7 +156,7 @@ public SectionCell(Context context) { setBackgroundColor(Theme.getColor(Theme.key_graySection)); - textView = new EmojiTextView(getContext()); + textView = new AnimatedEmojiSpan.TextViewEmojis(getContext()); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(Theme.getColor(Theme.key_graySectionText)); @@ -221,8 +224,17 @@ protected void onCollapseClick() { } - public void setText(String left, int percent, int votesCount, int collapsed, boolean animated) { - textView.setText(left); + public void setText(CharSequence left, ArrayList entities, int percent, int votesCount, int collapsed, boolean animated) { + if (entities != null) { + NotificationCenter.listenEmojiLoading(textView); + CharSequence answerText = new SpannableStringBuilder(left); + MediaDataController.addTextStyleRuns(entities, left, (Spannable) answerText); + answerText = Emoji.replaceEmoji(answerText, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); + MessageObject.replaceAnimatedEmoji(answerText, entities, textView.getPaint().getFontMetricsInt()); + textView.setText(answerText); + } else { + textView.setText(Emoji.replaceEmoji(left, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); + } String p = String.format("%d", percent); SpannableStringBuilder builder; if (LocaleController.isRTL) { @@ -602,7 +614,7 @@ public PollVotesAlert(ChatActivity parentFragment, MessageObject message) { Collections.sort(voters, new Comparator() { private int getIndex(VotesList votesList) { for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { return a; } @@ -902,13 +914,22 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { } }); - titleTextView = new EmojiTextView(context); + titleTextView = new AnimatedEmojiSpan.TextViewEmojis(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); titleTextView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(5), AndroidUtilities.dp(14), AndroidUtilities.dp(21)); titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); titleTextView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); - titleTextView.setText(poll.question); + if (poll.question != null && poll.question.entities != null) { + NotificationCenter.listenEmojiLoading(titleTextView); + CharSequence questionText = new SpannableStringBuilder(poll.question.text); + MediaDataController.addTextStyleRuns(poll.question.entities, poll.question.text, (Spannable) questionText); + questionText = Emoji.replaceEmoji(questionText, titleTextView.getPaint().getFontMetricsInt(), false); + MessageObject.replaceAnimatedEmoji(questionText, poll.question.entities, titleTextView.getPaint().getFontMetricsInt()); + titleTextView.setText(questionText); + } else { + titleTextView.setText(Emoji.replaceEmoji(poll.question == null ? "" : poll.question.text, titleTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false)); + } actionBar = new ActionBar(context) { @Override @@ -1160,13 +1181,13 @@ public View getSectionHeaderView(int section, View view) { view.setAlpha(1.0f); VotesList votesList = voters.get(section); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); sectionCell.setTag(R.id.object_tag, votesList); break; } @@ -1217,13 +1238,13 @@ public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder VotesList votesList = voters.get(section); TLRPC.MessagePeerVote vote = votesList.votes.get(0); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), false); sectionCell.setTag(R.id.object_tag, votesList); break; } @@ -1314,13 +1335,13 @@ public void animateSectionUpdates(View view) { SectionCell sectionCell = (SectionCell) child; VotesList votesList = (VotesList) child.getTag(R.id.object_tag); for (int a = 0, N = poll.answers.size(); a < N; a++) { - TLRPC.TL_pollAnswer answer = poll.answers.get(a); + TLRPC.PollAnswer answer = poll.answers.get(a); if (Arrays.equals(answer.option, votesList.option)) { Button button = votesPercents.get(votesList); if (button == null) { continue; } - sectionCell.setText(answer.text, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), true); + sectionCell.setText(answer.text == null ? "" : answer.text.text, answer.text == null ? null : answer.text.entities, calcPercent(votesList.option), votesList.count, votesList.getCollapsed(), true); sectionCell.setTag(R.id.object_tag, votesList); break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java index c806a759dc..fb76976ce9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java @@ -202,7 +202,7 @@ public void invalidateTransforms(boolean applyBackScaleY) { p.updateAnimation = false; p.setBackScaleX(w / p.getMeasuredWidth()); if (applyBackScaleY) { - p.setBackScaleY(h / p.getMeasuredHeight()); + p.setBackScaleY(Math.min(1, h / p.getMeasuredHeight())); } p.updateAnimation = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java index 34beeaa62b..78c45ab940 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/FeaturesPageView.java @@ -335,7 +335,7 @@ protected void onDetachedFromWindow() { Canvas canvas = new Canvas(bitmap); canvas.drawColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_premiumGradient2, resourcesProvider), Theme.getColor(Theme.key_dialogBackground, resourcesProvider), 0.5f)); iconTextureView.setBackgroundBitmap(bitmap); - iconTextureView.mRenderer.forceNight = true; +// iconTextureView.mRenderer.forceNight = true; iconTextureView.mRenderer.colorKey1 = Theme.key_premiumGradient2; iconTextureView.mRenderer.colorKey2 = Theme.key_premiumGradient1; iconTextureView.mRenderer.updateColors(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java index 8f4da1e584..d93617d138 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java @@ -43,8 +43,8 @@ public class GLIconRenderer implements GLSurfaceView.Renderer { int color1; int color2; - public int colorKey1 = Theme.key_premiumStartGradient1; - public int colorKey2 = Theme.key_premiumStartGradient2; + public int colorKey1 = Theme.key_premiumStarGradient1; + public int colorKey2 = Theme.key_premiumStarGradient2; private final int style; private final int type; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java index 6fd3fafca2..758be97f76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Icon3D.java @@ -88,7 +88,8 @@ public class Icon3D { private static final String[] coinModel = new String[] { "models/coin_outer.binobj", "models/coin_inner.binobj", - "models/coin_logo.binobj" + "models/coin_logo.binobj", + "models/coin_stars.binobj" }; public Icon3D(Context context, int type) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java index 4c891c19c2..083c1b29ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java @@ -71,7 +71,7 @@ public PremiumButtonView(@NonNull Context context, int radius, boolean createOve flickerDrawable.repeatProgress = 4f; LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); - buttonTextView = new AnimatedTextView(context) { + buttonTextView = new AnimatedTextView(context, true, true, true) { @Override protected void onDraw(Canvas canvas) { if (loadingT > 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java index 43d79eb4fb..ef09b3f0ca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java @@ -494,38 +494,14 @@ protected void onDetachedFromWindow() { titleView = new LinkSpanDrawable.LinksTextView[2]; for (int a = 0; a < 2; ++a) { titleView[a] = new LinkSpanDrawable.LinksTextView(context, resourcesProvider) { - private Layout lastLayout; - AnimatedEmojiSpan.EmojiGroupedSpans stack; - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - AnimatedEmojiSpan.release(this, stack); - lastLayout = null; - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (lastLayout != getLayout()) { - stack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, this, stack, lastLayout = getLayout()); - } - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), stack, 0, null, 0, 0, 0, 1f, colorFilter); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(99999999, MeasureSpec.AT_MOST)); - } - @Override - public int overrideColor() { - return accentColor != null ? Theme.multAlpha(accentColor, .10f) : super.overrideColor(); + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; } }; titleView[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE); titleView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - titleView[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView[a].setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleView[a].setGravity(Gravity.CENTER_HORIZONTAL); titleView[a].setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); titleView[a].setLinkTextColor(getThemedColor(Theme.key_windowBackgroundWhiteLinkText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java index fc3554d4cb..8732990545 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/PremiumPreviewGiftToUsersBottomSheet.java @@ -45,6 +45,7 @@ import org.telegram.ui.Components.Premium.boosts.cells.DurationWithDiscountCell; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; import java.util.Collections; @@ -101,12 +102,13 @@ protected void updateRows() { @Override public void setTitle(boolean animated) { titleView[0].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - subtitleView.setPadding(dp(30), 0, dp(30), 0); - subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); - titleView[0].setText(getString("GiftTelegramPremiumTitle", R.string.GiftTelegramPremiumTitle)); ((ViewGroup.MarginLayoutParams) subtitleView.getLayoutParams()).bottomMargin = dp(16); ((ViewGroup.MarginLayoutParams) subtitleView.getLayoutParams()).topMargin = dp(4f); + subtitleView.setPadding(dp(30), 0, dp(30), 0); + subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); + + titleView[0].setText(getString("GiftTelegramPremiumTitle", R.string.GiftTelegramPremiumTitle)); String subTitle; switch (selectedUsers.size()) { case 1: { @@ -220,7 +222,7 @@ private void updateActionButton(boolean animated) { TLRPC.TL_premiumGiftCodeOption giftCodeOption = getSelectedOption(); String priceStr = BillingController.getInstance().formatCurrency(giftCodeOption.amount, giftCodeOption.currency); if (selectedUsers.size() == 1) { - actionBtn.setText(formatString("GiftSubscriptionFor", R.string.GiftSubscriptionFor, priceStr), animated); + actionBtn.setText(formatString(R.string.GiftSubscriptionFor, priceStr), animated); } else { actionBtn.setText(formatPluralString("GiftSubscriptionCountFor", selectedUsers.size(), priceStr), animated); } @@ -251,23 +253,33 @@ private void init() { return; } actionBtn.setLoading(true); - BoostRepository.payGiftCode(new ArrayList<>(selectedUsers), getSelectedOption(), null, getBaseFragment(), result -> { - dismiss(); - NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.giftsToUserSent); - AndroidUtilities.runOnUIThread(() -> PremiumPreviewGiftSentBottomSheet.show(selectedUsers), 250); - }, error -> { - actionBtn.setLoading(false); - BoostDialogs.showToastError(getContext(), error); - }); + if (isSelf()) { + PremiumPreviewFragment.buyPremium(getBaseFragment(), "grace_period"); + } else { + BoostRepository.payGiftCode(new ArrayList<>(selectedUsers), getSelectedOption(), null, getBaseFragment(), result -> { + dismiss(); + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.giftsToUserSent); + AndroidUtilities.runOnUIThread(() -> PremiumPreviewGiftSentBottomSheet.show(selectedUsers), 250); + }, error -> { + actionBtn.setLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + } }); buttonContainer.addView(actionBtn, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); - overrideTitleIcon = AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); + if (!isSelf()) { + overrideTitleIcon = AvatarHolderView.createAvatarsContainer(getContext(), selectedUsers); + } updateActionButton(false); fixNavigationBar(); } + public boolean isSelf() { + return selectedUsers.size() == 1 && selectedUsers.get(0) != null && selectedUsers.get(0).id == UserConfig.getInstance(getCurrentAccount()).getClientUserId(); + } + protected void afterCellCreated(int viewType, View view) { if (viewType == 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java index 65a00b84a6..0ac039d88d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java @@ -486,7 +486,7 @@ private void updateCheckboxes(boolean animated) { View child = recyclerListView.getChildAt(i); if (child instanceof SelectorUserCell) { int position = recyclerListView.getChildAdapterPosition(child); - if (position < 0) { + if (position - 1 < 0 || position - 1 >= items.size()) { continue; } Item item = items.get(position - 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java index 8c3f1ddeb4..1693defd09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/UserSelectorBottomSheet.java @@ -11,6 +11,7 @@ import android.graphics.Paint; import android.graphics.Rect; import android.net.Uri; +import android.os.Bundle; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -18,6 +19,7 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; +import android.widget.FrameLayout; import android.widget.LinearLayout; import androidx.annotation.NonNull; @@ -32,17 +34,26 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.browser.Browser; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextCell; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.ItemOptions; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter; import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter.Item; @@ -51,7 +62,10 @@ import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorSearchCell; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorUserCell; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.DialogsActivity; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PrivacyControlActivity; +import org.telegram.ui.ProfileActivity; import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import java.util.ArrayList; @@ -120,6 +134,7 @@ public static boolean handleIntent(Intent intent, Browser.Progress progress) { private final View sectionCell; private final SelectorHeaderCell headerView; private final SelectorBtnCell buttonContainer; + private final FrameLayout bulletinContainer; private final ArrayList oldItems = new ArrayList<>(); private final ArrayList items = new ArrayList<>(); @@ -274,6 +289,9 @@ protected float calculateCounterWidth(float width, float percent) { buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + bulletinContainer = new FrameLayout(getContext()); + containerView.addView(bulletinContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, 300, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(68))); + selectorAdapter.setData(items, recyclerListView); recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, dp(BOTTOM_HEIGHT_DP)); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -285,6 +303,10 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat } }); recyclerListView.setOnItemClickListener((view, position, x, y) -> { + if (view instanceof TextCell) { + openBirthdaySetup(); + return; + } if (view instanceof SelectorUserCell) { TLRPC.User user = ((SelectorUserCell) view).getUser(); long id = user.id; @@ -404,6 +426,7 @@ public void scrollToTop(boolean animate) { public void onAttachedToWindow() { super.onAttachedToWindow(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.giftsToUserSent); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.contactsDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadHints); } @@ -412,6 +435,7 @@ public void onAttachedToWindow() { public void onDetachedFromWindow() { super.onDetachedFromWindow(); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.giftsToUserSent); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.contactsDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.reloadHints); } @@ -523,7 +547,7 @@ private int addSection(ArrayList items, CharSequence title } count++; h += dp(56); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (userItems.isEmpty()) { return h; @@ -570,9 +594,17 @@ public void updateItems(boolean animated, boolean notify) { if (isSearching()) { for (TLRPC.User foundedUser : foundedUsers) { h += dp(56); - items.add(Item.asUser(foundedUser, selectedIds.contains(foundedUser.id))); + items.add(Item.asUser(foundedUser, selectedIds.contains(foundedUser.id)).withOptions(openOptions(foundedUser))); } } else { + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + if (userFull == null) { + MessagesController.getInstance(currentAccount).loadFullUser(UserConfig.getInstance(currentAccount).getCurrentUser(), 0, true); + } + if (userFull != null && userFull.birthday == null) { + h += dp(50); + items.add(Item.asButton(1, R.drawable.menu_birthday, getString(R.string.GiftsBirthdaySetup))); + } if (userId >= 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userId); if (user != null) { @@ -598,7 +630,7 @@ public void updateItems(boolean animated, boolean notify) { } if (selectedIds.contains(user.id)) selected.add(user.id); h += dp(56); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (!userItems.isEmpty()) { h += dp(32); @@ -620,7 +652,7 @@ public void updateItems(boolean animated, boolean notify) { h += dp(56); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(contact.user_id); if (selectedIds.contains(user.id)) selected.add(user.id); - userItems.add(Item.asUser(user, selectedIds.contains(user.id))); + userItems.add(Item.asUser(user, selectedIds.contains(user.id)).withOptions(openOptions(user))); } if (!userItems.isEmpty()) { @@ -662,6 +694,33 @@ public void updateItems(boolean animated, boolean notify) { } } + public View.OnClickListener openOptions(TLRPC.User user) { + return (View view) -> { + ItemOptions.makeOptions(container, resourcesProvider, (View) view.getParent()) + .add(R.drawable.profile_discuss, LocaleController.getString(R.string.SendMessage), () -> { + BaseFragment fragment = getBaseFragment(); + if (user == null || fragment == null) return; + BaseFragment.BottomSheetParams bottomSheetParams = new BaseFragment.BottomSheetParams(); + bottomSheetParams.transitionFromLeft = true; + bottomSheetParams.allowNestedScroll = false; + Bundle args = new Bundle(); + args.putLong("user_id", user.id); + fragment.showAsSheet(new ChatActivity(args), bottomSheetParams); + }) + .add(R.drawable.msg_openprofile, LocaleController.getString(R.string.OpenProfile), () -> { + BaseFragment fragment = getBaseFragment(); + if (user == null || fragment == null) return; + BaseFragment.BottomSheetParams bottomSheetParams = new BaseFragment.BottomSheetParams(); + bottomSheetParams.transitionFromLeft = true; + bottomSheetParams.allowNestedScroll = false; + Bundle args = new Bundle(); + args.putLong("user_id", user.id); + fragment.showAsSheet(new ProfileActivity(args), bottomSheetParams); + }) + .show(); + }; + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -694,6 +753,65 @@ public void didReceivedNotification(int id, int account, Object... args) { AndroidUtilities.runOnUIThread(() -> initContacts(true)); } else if (id == NotificationCenter.reloadHints) { AndroidUtilities.runOnUIThread(() -> initHints(true)); + } else if (id == NotificationCenter.userInfoDidLoad) { + AndroidUtilities.runOnUIThread(() -> updateItems(true, true)); } } + + private void openBirthdaySetup() { + AlertsCreator.createBirthdayPickerDialog(getContext(), getString(R.string.EditProfileBirthdayTitle), getString(R.string.EditProfileBirthdayButton), null, birthday -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + req.flags |= 1; + req.birthday = birthday; + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + TLRPC.TL_birthday oldBirthday = userFull != null ? userFull.birthday : null; + if (userFull != null) { + userFull.flags2 |= 32; + userFull.birthday = birthday; + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_boolTrue) { + BulletinFactory.of(bulletinContainer, resourcesProvider) + .createSimpleBulletin(R.raw.contact_check, LocaleController.getString(R.string.PrivacyBirthdaySetDone)) + .setDuration(Bulletin.DURATION_PROLONG) + .show(); + } else { + if (userFull != null) { + if (oldBirthday == null) { + userFull.flags2 &=~ 32; + } else { + userFull.flags2 |= 32; + } + userFull.birthday = oldBirthday; + MessagesStorage.getInstance(currentAccount).updateUserInfo(userFull, false); + } + if (err != null && err.text != null && err.text.startsWith("FLOOD_WAIT_")) { + if (getContext() != null) { + new AlertDialog.Builder(getContext(), resourcesProvider) + .setTitle(getString(R.string.PrivacyBirthdayTooOftenTitle)) + .setMessage(getString(R.string.PrivacyBirthdayTooOftenMessage)) + .setPositiveButton(getString(R.string.OK), null) + .show(); + } + } else { + BulletinFactory.of(bulletinContainer, resourcesProvider) + .createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.UnknownError)) + .show(); + } + } + }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); + + MessagesController.getInstance(currentAccount).removeSuggestion(0, "BIRTHDAY_SETUP"); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.newSuggestionsAvailable); + updateItems(true, true); + }, () -> { + if (getBaseFragment() == null) { + return; + } + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + params.allowNestedScroll = false; + getBaseFragment().showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), params); + }, resourcesProvider).show(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java index dd95d46f64..d08c9b113f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java @@ -21,6 +21,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.GraySectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.boosts.BoostRepository; import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorCountryCell; @@ -41,6 +42,7 @@ public class SelectorAdapter extends AdapterWithDiffUtils { public static final int VIEW_TYPE_COUNTRY = 6; public static final int VIEW_TYPE_LETTER = 7; public static final int VIEW_TYPE_TOP_SECTION = 8; + public static final int VIEW_TYPE_BUTTON = 9; private final Theme.ResourcesProvider resourcesProvider; private final Context context; @@ -82,7 +84,7 @@ public void setGreenSelector(boolean isGreenSelector) { @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - return (holder.getItemViewType() == VIEW_TYPE_USER || holder.getItemViewType() == VIEW_TYPE_COUNTRY); + return (holder.getItemViewType() == VIEW_TYPE_USER || holder.getItemViewType() == VIEW_TYPE_COUNTRY || holder.getItemViewType() == VIEW_TYPE_BUTTON); } @NonNull @@ -105,6 +107,11 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view = new SelectorCountryCell(context, resourcesProvider); } else if (viewType == VIEW_TYPE_TOP_SECTION) { view = new GraySectionCell(context, resourcesProvider); + } else if (viewType == VIEW_TYPE_BUTTON) { + TextCell cell = new TextCell(context, resourcesProvider); + cell.leftPadding = 23 - 7; + cell.imageLeft = 19; + view = cell; } else { view = new View(context); } @@ -157,6 +164,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi if ((position + 1 < items.size()) && items.get(position + 1).viewType == VIEW_TYPE_LETTER) { userCell.setDivider(false); } + userCell.setOptions(item.options); } else if (viewType == VIEW_TYPE_COUNTRY) { SelectorCountryCell cell = (SelectorCountryCell) holder.itemView; boolean needDivider = (position < items.size() - 1) && (position + 1 < items.size() - 1) && (items.get(position + 1).viewType != VIEW_TYPE_LETTER); @@ -189,6 +197,10 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } topSectionCell = cell; + } else if (viewType == VIEW_TYPE_BUTTON) { + TextCell cell = (TextCell) holder.itemView; + cell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + cell.setTextAndIcon(item.text, item.resId, false); } } @@ -274,9 +286,12 @@ public static class Item extends AdapterWithDiffUtils.Item { public TLRPC.TL_help_country country; public CharSequence text, subtext; public int type; + public int id; + public int resId; public boolean checked; public int padHeight = -1; public View.OnClickListener callback; + public View.OnClickListener options; private Item(int viewType, boolean selectable) { super(viewType, selectable); @@ -288,6 +303,14 @@ public static Item asPad(int padHeight) { return item; } + public static Item asButton(int id, int resId, String text) { + Item item = new Item(VIEW_TYPE_BUTTON, false); + item.id = id; + item.resId = resId; + item.text = text; + return item; + } + public static Item asUser(TLRPC.User user, boolean checked) { Item item = new Item(VIEW_TYPE_USER, true); item.user = user; @@ -297,6 +320,11 @@ public static Item asUser(TLRPC.User user, boolean checked) { return item; } + public Item withOptions(View.OnClickListener onClickListener) { + this.options = onClickListener; + return this; + } + public static Item asLetter(String letter) { Item item = new Item(VIEW_TYPE_LETTER, false); item.text = letter; @@ -369,6 +397,8 @@ public boolean equals(Object o) { return false; } else if (viewType == VIEW_TYPE_TOP_SECTION && (!TextUtils.equals(text, i.text))) { return false; + } else if (viewType == VIEW_TYPE_BUTTON && (!TextUtils.equals(text, i.text) || id != i.id || resId != i.resId)) { + return false; } return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java index 01916702e4..180f8025fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.widget.LinearLayout; +import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.RecyclerListView; @@ -33,6 +34,6 @@ protected void dispatchDraw(Canvas canvas) { } else { dividerPaint.setAlpha((int) (0xFF * alpha.set(1))); } - canvas.drawRect(0, 0, getWidth(), 1, dividerPaint); + canvas.drawRect(0, 0, getWidth(), AndroidUtilities.getShadowHeight(), dividerPaint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java index fc28f0bc1c..85a14e0e32 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java @@ -4,8 +4,12 @@ import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.ColorFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.view.Gravity; import android.view.View; +import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -30,6 +34,7 @@ public class SelectorUserCell extends BaseCell { private final boolean[] isOnline = new boolean[1]; private final CheckBox2 checkBox; + private final ImageView optionsView; private TLRPC.User user; private TLRPC.Chat chat; private TL_stories.TL_myBoost boost; @@ -51,6 +56,21 @@ public SelectorUserCell(Context context, Theme.ResourcesProvider resourcesProvid addView(checkBox); checkBox.setChecked(false, false); checkBox.setLayoutParams(LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 13, 0, 14, 0)); + + optionsView = new ImageView(context); + optionsView.setScaleType(ImageView.ScaleType.CENTER); + optionsView.setImageResource(R.drawable.ic_ab_other); + optionsView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_inMenu, resourcesProvider), PorterDuff.Mode.SRC_IN)); + addView(optionsView, LayoutHelper.createFrame(32, 32, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 12, 0, 12, 0)); + } + + public void setOptions(View.OnClickListener listener) { + if (listener != null) { + optionsView.setVisibility(View.VISIBLE); + optionsView.setOnClickListener(listener); + } else { + optionsView.setVisibility(View.GONE); + } } @Override @@ -96,6 +116,7 @@ public void setCheckboxAlpha(float alpha, boolean animated) { } public void setUser(TLRPC.User user) { + optionsView.setVisibility(View.GONE); this.user = user; this.chat = null; avatarDrawable.setInfo(user); @@ -110,6 +131,8 @@ public void setUser(TLRPC.User user) { } public void setChat(TLRPC.Chat chat, int participants_count) { + optionsView.setVisibility(View.GONE); + this.chat = chat; this.user = null; avatarDrawable.setInfo(chat); @@ -134,6 +157,8 @@ public void setChat(TLRPC.Chat chat, int participants_count) { } public void setBoost(TL_stories.TL_myBoost boost) { + optionsView.setVisibility(View.GONE); + this.boost = boost; this.chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(boost.peer)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java index d72f043e2f..cac833fa9b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -56,6 +56,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma public static native long create(String src, String json, int w, int h, int[] params, boolean precache, int[] colorReplacement, boolean limitFps, int fitzModifier); public static native long getFramesCount(String src, String json); + public static native double getDuration(String src, String json); protected static native long createWithJson(String json, String name, int[] params, int[] colorReplacement); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java index 7de61dc833..0f5f6d6f01 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieImageView.java @@ -136,18 +136,24 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b } }; imageReceiver.setAllowLoadingOnAttachedOnly(true); + ImageLocation thumbLocation = null; + String thumbFilter = null; + if (document.localThumbPath != null) { + thumbLocation = ImageLocation.getForPath(document.localThumbPath); + thumbFilter = w + "_" + h; + } if (onlyLastFrame) { - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", null, null, null, null, null, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + "_lastframe", null, null, thumbLocation, thumbFilter, null, 0, null, document, 1); } else if ("video/webm".equals(document.mime_type)) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : "") + "_" + ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(thumb, document), null, null, document.size, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : "") + "_" + ImageLoader.AUTOPLAY_FILTER, thumbLocation != null ? thumbLocation : ImageLocation.getForDocument(thumb, document), thumbFilter, null, document.size, null, document, 1); } else { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); if (svgThumb != null) { svgThumb.overrideWidthAndHeight(512, 512); } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : ""), ImageLocation.getForDocument(thumb, document), null, null, null, svgThumb, 0, null, document, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), w + "_" + h + (cached ? "_pcache" : ""), ImageLocation.getForDocument(thumb, document), null, thumbLocation, thumbFilter, svgThumb, 0, null, document, 1); } imageReceiver.setAspectFit(true); imageReceiver.setParentView(this); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java index 594a3b2b1c..b65ff39c0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java @@ -265,10 +265,8 @@ private void load() { AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> { if (response instanceof TLRPC.TL_messages_messageReactionsList) { TLRPC.TL_messages_messageReactionsList res = (TLRPC.TL_messages_messageReactionsList) response; - - for (TLRPC.User u : res.users) { - MessagesController.getInstance(currentAccount).putUser(u, false); - } + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); HashSet visibleCustomEmojiReactions = new HashSet<>(); for (int i = 0; i < res.reactions.size(); i++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java index 3fc8967c15..ddfacc6986 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatCustomReactionsEditActivity.java @@ -31,6 +31,7 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; @@ -38,6 +39,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.SlideIntChooseView; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.ChatActivity; @@ -66,6 +68,7 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not private LinearLayout switchLayout; private LinearLayout contentLayout; private CustomReactionEditText editText; + private SlideIntChooseView slideView; private UpdateReactionsButton actionButton; private ScrollView scrollView; @@ -78,6 +81,7 @@ public class ChatCustomReactionsEditActivity extends BaseFragment implements Not private boolean emojiKeyboardVisible = false; private final TLRPC.ChatFull info; private final long chatId; + private int currentReactionsCount, reactionsCount; private TLRPC.Chat currentChat; private TL_stories.TL_premium_boostsStatus boostsStatus; private int selectedCustomReactions; @@ -205,16 +209,36 @@ public boolean onTextContextMenuItem(int id) { TextInfoPrivacyCell infoCell2 = new TextInfoPrivacyCell(context); infoCell2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4)); - infoCell2.setTopPadding(12); - infoCell2.setBottomPadding(70); infoCell2.setText(AndroidUtilities.replaceSingleTag( - LocaleController.getString("ReactionCreateOwnPack", R.string.ReactionCreateOwnPack), + getString(R.string.ReactionCreateOwnPack), Theme.key_chat_messageLinkIn, 0, - () -> presentFragment(ChatActivity.of(429000)), + () -> Browser.openUrl(getContext(), "https://t.me/stickers"), getResourceProvider() )); switchLayout.addView(infoCell2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + HeaderCell headerCell1 = new HeaderCell(context, resourceProvider); + headerCell1.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + headerCell1.setText(getString(R.string.MaximumReactionsHeader)); + switchLayout.addView(headerCell1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + slideView = new SlideIntChooseView(context, resourceProvider); + slideView.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + if (info instanceof TLRPC.TL_chatFull ? (info.flags & 1048576) != 0 : (info.flags2 & 8192) != 0) { + currentReactionsCount = reactionsCount = info.reactions_limit; + } else { + currentReactionsCount = reactionsCount = getMessagesController().reactionsUniqMax; + } + slideView.set(reactionsCount, SlideIntChooseView.Options.make(0, "MaximumReactionsValue", 1, getMessagesController().reactionsUniqMax), value -> { + reactionsCount = value; + }); + switchLayout.addView(slideView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + TextInfoPrivacyCell infoCell3 = new TextInfoPrivacyCell(context); + infoCell3.setTopPadding(12); + infoCell3.setBottomPadding(70); + infoCell3.setText(LocaleController.getString(R.string.MaximumReactionsInfo)); + switchLayout.addView(infoCell3, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + actionButton = new UpdateReactionsButton(context, getResourceProvider()); actionButton.setDefaultState(); actionButton.setOnClickListener(v -> { @@ -228,7 +252,7 @@ public boolean onTextContextMenuItem(int id) { } actionButton.setLoading(true); - getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), error -> { + getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), currentReactionsCount = reactionsCount, error -> { if (isFinishing()) { return; } @@ -576,8 +600,8 @@ public void onAnimationEnd(Animator animation) { public void onFragmentDestroy() { super.onFragmentDestroy(); AndroidUtilities.cancelRunOnUIThread(checkAfterFastDeleteRunnable); - if (selectedType == SELECT_TYPE_NONE) { - getMessagesController().setCustomChatReactions(chatId, selectedType, new ArrayList<>(), null, null); + if (selectedType == SELECT_TYPE_NONE && reactionsCount != currentReactionsCount) { + getMessagesController().setCustomChatReactions(chatId, selectedType, grabReactions(false), reactionsCount, null, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java index 7cca87513e..b378b15ab7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ChatSelectionReactionMenuOverlay.java @@ -226,7 +226,7 @@ public void invalidatePosition(boolean animate) { reactionsContainerLayout.setVisibility(VISIBLE); if (!messageSet) { messageSet = true; - reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo()); + reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo(), true); } } } @@ -352,7 +352,7 @@ private void animateVisible(boolean visible) { if (reactionsContainerLayout.isEnabled()) { messageSet = true; - reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo()); + reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo(), true); reactionsContainerLayout.startEnterAnimation(false); } else { messageSet = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java index ab5b8413d9..e6de8c9ee2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/CustomEmojiReactionsWindow.java @@ -1,5 +1,6 @@ package org.telegram.ui.Components.Reactions; +import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STICKER_SET_EMOJI; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY; import static org.telegram.ui.Components.ReactionsContainerLayout.TYPE_STORY_LIKES; @@ -76,6 +77,7 @@ public class CustomEmojiReactionsWindow { float fromRadius; RectF fromRect = new RectF(); + float fromRectTranslateX, fromRectTranslateY; public RectF drawingRect = new RectF(); float enterTransitionProgress; boolean enterTransitionFinished; @@ -233,7 +235,7 @@ protected void invalidateParent() { @Override public void getOutline(View view, Outline outline) { - float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress); + float radius = AndroidUtilities.lerp(fromRadius, dp(8), enterTransitionProgress); rectTmp.set(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); AndroidUtilities.lerp(fromRect, rectTmp, enterTransitionProgress, rectF); rectF.round(rect); @@ -298,9 +300,9 @@ private void updateWindowPosition() { return; } float y = yTranslation; - int bottomOffset = AndroidUtilities.dp(32); + int bottomOffset = dp(32); if (type == TYPE_STORY || type == TYPE_STORY_LIKES) { - bottomOffset = AndroidUtilities.dp(24); + bottomOffset = dp(24); } if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - keyboardHeight - bottomOffset) { y = windowView.getMeasuredHeight() - keyboardHeight - containerView.getMeasuredHeight() - bottomOffset; @@ -350,26 +352,26 @@ private void createTransition(boolean enter) { reactionsContainerLayout.getLocationOnScreen(location); } windowView.getLocationOnScreen(windowLocation); - float y = location[1] - windowLocation[1] - AndroidUtilities.dp(44) - AndroidUtilities.dp(52) - (selectAnimatedEmojiDialog.includeHint ? AndroidUtilities.dp(26) : 0) + reactionsContainerLayout.getTopOffset(); + float y = location[1] - windowLocation[1] - dp(44) - dp(52) - (selectAnimatedEmojiDialog.includeHint ? dp(26) : 0) + reactionsContainerLayout.getTopOffset(); if (reactionsContainerLayout.showExpandableReactions()) { - y = location[1] - windowLocation[1] - AndroidUtilities.dp(12); + y = location[1] - windowLocation[1] - dp(12); } - if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - AndroidUtilities.dp(32)) { - y = windowView.getMeasuredHeight() - AndroidUtilities.dp(32) - containerView.getMeasuredHeight(); + if (y + containerView.getMeasuredHeight() > windowView.getMeasuredHeight() - dp(32)) { + y = windowView.getMeasuredHeight() - dp(32) - containerView.getMeasuredHeight(); } - if (y < AndroidUtilities.dp(16)) { - y = AndroidUtilities.dp(16); + if (y < dp(16)) { + y = dp(16); } if (type == TYPE_STORY) { - containerView.setTranslationX((windowView.getMeasuredWidth() - containerView.getMeasuredWidth()) / 2f - AndroidUtilities.dp(16)); + containerView.setTranslationX((windowView.getMeasuredWidth() - containerView.getMeasuredWidth()) / 2f - dp(16)); } else if (type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { - containerView.setTranslationX(location[0] - windowLocation[0] - AndroidUtilities.dp(18)); + containerView.setTranslationX(location[0] - windowLocation[0] - dp(18)); } else { - containerView.setTranslationX(location[0] - windowLocation[0] - AndroidUtilities.dp(2)); + containerView.setTranslationX(location[0] - windowLocation[0] - dp(2)); } if (!enter) { @@ -379,7 +381,10 @@ private void createTransition(boolean enter) { containerView.setTranslationY(yTranslation); } - fromRect.offset(location[0] - windowLocation[0] - containerView.getX(), location[1] - windowLocation[1] - containerView.getY()); + fromRect.offset( + fromRectTranslateX = location[0] - windowLocation[0] - containerView.getX(), + fromRectTranslateY = location[1] - windowLocation[1] - containerView.getY() + ); reactionsContainerLayout.setCustomEmojiEnterProgress(enterTransitionProgress); @@ -397,7 +402,10 @@ private void createTransition(boolean enter) { selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(enter && cascadeAnimation); account = UserConfig.selectedAccount; notificationsLocker.lock(); - valueAnimator = StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); + if (valueAnimator != null) { + valueAnimator.cancel(); + } + valueAnimator = type == TYPE_STICKER_SET_EMOJI ? ValueAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0) : StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0); valueAnimator.addUpdateListener(animation -> { valueAnimator = null; enterTransitionProgress = (float) animation.getAnimatedValue(); @@ -441,7 +449,10 @@ public void onAnimationEnd(Animator animation) { } }); - if (cascadeAnimation) { + if (type == TYPE_STICKER_SET_EMOJI) { + valueAnimator.setDuration(420); + valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } else if (cascadeAnimation) { valueAnimator.setDuration(450); valueAnimator.setInterpolator(new OvershootInterpolator(0.5f)); } else { @@ -571,8 +582,13 @@ public void onAnimationEnd(Animator animation) { checkAnimationEnd(enter); } }); - valueAnimator.setDuration(350); - valueAnimator.setInterpolator(new OvershootInterpolator(1f)); + if (type == TYPE_STICKER_SET_EMOJI) { + valueAnimator.setDuration(420); + valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + } else { + valueAnimator.setDuration(350); + valueAnimator.setInterpolator(new OvershootInterpolator(1f)); + } valueAnimator.start(); } } @@ -639,6 +655,9 @@ public void dismiss() { if (dismissed) { return; } + if (reactionsContainerLayout != null) { + reactionsContainerLayout.onCustomEmojiWindowClosing(); + } Bulletin.hideVisible(); dismissed = true; AndroidUtilities.hideKeyboard(windowView); @@ -717,7 +736,7 @@ public class ContainerView extends FrameLayout { public ContainerView(@NonNull Context context) { super(context); shadow = ContextCompat.getDrawable(context, R.drawable.reactions_bubble_shadow).mutate(); - shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = AndroidUtilities.dp(7); + shadowPad.left = shadowPad.top = shadowPad.right = shadowPad.bottom = dp(7); shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow, resourcesProvider), PorterDuff.Mode.MULTIPLY)); if (type == TYPE_STORY_LIKES) { backgroundPaint.setColor(ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.13f)); @@ -741,18 +760,20 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { size = reactionsContainerLayout.getMeasuredWidth(); } else { size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); - int measuredSize = AndroidUtilities.dp(36) * 8 + AndroidUtilities.dp(12); + int measuredSize = dp(36) * 8 + dp(12); if (measuredSize < size) { size = measuredSize; } } int height = size; - if (reactionsContainerLayout.showExpandableReactions()) { + if (type == TYPE_STICKER_SET_EMOJI) { + height = dp(36) * 8 - dp(8); + } else if (reactionsContainerLayout.showExpandableReactions()) { int rows = (int) Math.ceil(reactions.size() / 8f); if (rows <= 8) { - height = rows * AndroidUtilities.dp(36) + AndroidUtilities.dp(8); + height = rows * dp(36) + dp(8); } else { - height = AndroidUtilities.dp(36) * 8 - AndroidUtilities.dp(8); + height = dp(36) * 8 - dp(8); } } super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); @@ -773,8 +794,12 @@ protected void dispatchDraw(Canvas canvas) { } float progressClpamped = Utilities.clamp(enterTransitionProgress,1f, 0f); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (type == TYPE_STICKER_SET_EMOJI) { + fromRect.set(reactionsContainerLayout.rect); + fromRect.offset(fromRectTranslateX, fromRectTranslateY); + } AndroidUtilities.lerp(fromRect, AndroidUtilities.rectTmp, enterTransitionProgress, drawingRect); - float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress); + float radius = AndroidUtilities.lerp(fromRadius, dp(8), enterTransitionProgress); transitionReactions.clear(); @@ -810,10 +835,10 @@ protected void dispatchDraw(Canvas canvas) { enterTransitionScalePy = 0; if (reactionsContainerLayout != null) { - for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) { + for (int i = selectAnimatedEmojiDialog.emojiGridView.getChildCount() - 1; i >= 0; --i) { if (selectAnimatedEmojiDialog.emojiGridView.getChildAt(i) instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) { SelectAnimatedEmojiDialog.ImageViewEmoji imageViewEmoji = (SelectAnimatedEmojiDialog.ImageViewEmoji) selectAnimatedEmojiDialog.emojiGridView.getChildAt(i); - if (imageViewEmoji.reaction != null) { + if (imageViewEmoji.isFirstReactions && imageViewEmoji.reaction != null) { transitionReactions.put(imageViewEmoji.reaction, imageViewEmoji); } } @@ -831,7 +856,7 @@ protected void dispatchDraw(Canvas canvas) { int top = (int) (selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX()); int left = (int) (selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.emojiGridView.getY()); boolean isEmojiTabsVisible = selectAnimatedEmojiDialog.emojiTabs.getParent() != null; - canvas.clipRect(left, isEmojiTabsVisible ? top + AndroidUtilities.dp(36) * enterTransitionProgress : 0, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight()); + canvas.clipRect(left, isEmojiTabsVisible ? top + dp(36) * enterTransitionProgress : 0, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight()); for (int i = -1; i < reactionsContainerLayout.recyclerListView.getChildCount(); i++) { View child; if (i == -1) { @@ -865,11 +890,19 @@ protected void dispatchDraw(Canvas canvas) { fromX -= reactionsContainerLayout.recyclerListView.getX(); fromY -= reactionsContainerLayout.recyclerListView.getY(); } - float toX = toImageView.getX() + selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX() - holderView.loopImageView.getX() - AndroidUtilities.dp(1); + float toX = toImageView.getX() + selectAnimatedEmojiDialog.getX() + selectAnimatedEmojiDialog.emojiGridView.getX() - holderView.loopImageView.getX() - dp(1); float toY = toImageView.getY() + selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.gridViewContainer.getY() + selectAnimatedEmojiDialog.emojiGridView.getY() - holderView.loopImageView.getY(); float toImageViewSize = toImageView.getMeasuredWidth(); - if (toImageView.selected) { - float sizeAfterScale = toImageViewSize * (0.8f + 0.2f * 0.3f); + if (toImageView.selected || type == TYPE_STICKER_SET_EMOJI) { + float sizeAfterScale = toImageViewSize; + if (type == TYPE_STICKER_SET_EMOJI) { + sizeAfterScale *= .87f; + toX -= dp(.33f); + toY -= dp(1.33f); + } + if (toImageView.selected) { + sizeAfterScale *= (0.8f + 0.2f * 0.3f); + } toX += (toImageViewSize - sizeAfterScale) / 2f; toY += (toImageViewSize - sizeAfterScale) / 2f; toImageViewSize = sizeAfterScale; @@ -881,10 +914,10 @@ protected void dispatchDraw(Canvas canvas) { float toScale = toImageViewSize / (float) holderView.loopImageView.getMeasuredWidth(); scale = AndroidUtilities.lerp(1f, toScale, enterTransitionProgress); if (holderView.position == 0) { - fromRoundRadiusLb = fromRoundRadiusLt = AndroidUtilities.dp(6); + fromRoundRadiusLb = fromRoundRadiusLt = dp(6); fromRoundRadiusRb = fromRoundRadiusRt = 0; } else if (holderView.selected) { - fromRoundRadiusRb = fromRoundRadiusLb = fromRoundRadiusRt = fromRoundRadiusLt = AndroidUtilities.dp(6); + fromRoundRadiusRb = fromRoundRadiusLb = fromRoundRadiusRt = fromRoundRadiusLt = dp(6); } canvas.translate(dX, dY); @@ -905,11 +938,11 @@ protected void dispatchDraw(Canvas canvas) { if (toImageView.selected) { float cx = holderView.getMeasuredWidth() / 2f; float cy = holderView.getMeasuredHeight() / 2f; - float fromSize = holderView.getMeasuredWidth() - AndroidUtilities.dp(2); - float toSize = toImageView.getMeasuredWidth() - AndroidUtilities.dp(2); + float fromSize = holderView.getMeasuredWidth() - dp(2); + float toSize = toImageView.getMeasuredWidth() - dp(2); float finalSize = AndroidUtilities.lerp(fromSize, toSize / scale, enterTransitionProgress); AndroidUtilities.rectTmp.set(cx - finalSize / 2f, cy - finalSize / 2f, cx + finalSize / 2f, cy + finalSize / 2f); - float rectRadius = AndroidUtilities.lerp(fromSize / 2f, AndroidUtilities.dp(4), enterTransitionProgress); + float rectRadius = AndroidUtilities.lerp(fromSize / 2f, dp(4), enterTransitionProgress); canvas.drawRoundRect(AndroidUtilities.rectTmp, rectRadius, rectRadius, selectAnimatedEmojiDialog.selectorPaint); } holderView.drawSelected = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java index d42a0903f2..23f350e1e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionImageHolder.java @@ -19,6 +19,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.RLottieDrawable; import java.util.Objects; @@ -96,6 +97,25 @@ public void draw(Canvas canvas) { } } + public boolean isLoaded() { + ImageReceiver imageReceiver; + if (animatedEmojiDrawable != null) { + imageReceiver = animatedEmojiDrawable.getImageReceiver(); + } else { + imageReceiver = this.imageReceiver; + } + if (imageReceiver == null) return false; + if (!imageReceiver.hasImageSet()) return false; + if (!imageReceiver.hasImageLoaded()) return false; + RLottieDrawable rLottieDrawable = imageReceiver.getLottieAnimation(); + if (rLottieDrawable != null) { + if (rLottieDrawable.isGeneratingCache()) { + return false; + } + } + return true; + } + public void setBounds(Rect bounds) { this.bounds.set(bounds); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java index 4a0d4c582b..77e2c3a1a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -51,6 +51,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LiteMode; @@ -153,7 +154,8 @@ public boolean equals(Object o) { private float bigCircleRadius = dp(8); private float smallCircleRadius = bigCircleRadius / 2; public int bigCircleOffset = dp(36); - private MessageObject messageObject; + public MessageObject messageObject; + public boolean hitLimit; private int currentAccount; private long waitingLoadingChatId; private boolean isTop; @@ -169,10 +171,10 @@ public boolean equals(Object o) { private List visibleReactionsList = new ArrayList<>(20); private List premiumLockedReactions = new ArrayList<>(10); - private List allReactionsList = new ArrayList<>(20); + public List allReactionsList = new ArrayList<>(20); private LinearLayoutManager linearLayoutManager; - private RecyclerView.Adapter listAdapter; + private Adapter listAdapter; RectF rectF = new RectF(); HashSet selectedReactions = new HashSet<>(); @@ -354,114 +356,7 @@ public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull R }); recyclerListView.setLayoutManager(linearLayoutManager); recyclerListView.setOverScrollMode(View.OVER_SCROLL_NEVER); - recyclerListView.setAdapter(listAdapter = new AdapterWithDiffUtils() { - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - return false; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view; - switch (viewType) { - default: - case VIEW_TYPE_REACTION: - case VIEW_TYPE_CUSTOM_REACTION: - view = new ReactionHolderView(context, true); - break; - case VIEW_TYPE_PREMIUM_BUTTON: - premiumLockContainer = new FrameLayout(context); - premiumLockIconView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_REACTIONS); - premiumLockIconView.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), Theme.getColor(Theme.key_dialogBackground), 0.7f)); - premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - premiumLockIconView.setScaleX(0f); - premiumLockIconView.setScaleY(0f); - premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); - premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); - premiumLockIconView.setOnClickListener(v -> { - int[] position = new int[2]; - v.getLocationOnScreen(position); - showUnlockPremium(position[0] + v.getMeasuredWidth() / 2f, position[1] + v.getMeasuredHeight() / 2f); - }); - view = premiumLockContainer; - break; - case VIEW_TYPE_CUSTOM_EMOJI_BUTTON: - customReactionsContainer = new CustomReactionsContainer(context); - customEmojiReactionsIconView = new InternalImageView(context); - customEmojiReactionsIconView.setImageResource(R.drawable.msg_reactions_expand); - customEmojiReactionsIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - if (type == TYPE_STORY || type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { - customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); - } else { - customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - } - customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); - customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); - customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); - customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); - customEmojiReactionsIconView.setOnClickListener(v -> { - showCustomEmojiReactionDialog(); - }); - view = customReactionsContainer; - break; - } - - int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); - view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { - ReactionHolderView h = (ReactionHolderView) holder.itemView; - h.setScaleX(1); - h.setScaleY(1); - h.setReaction(items.get(position).reaction, position); - } - } - - @Override - public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { - int position = holder.getAdapterPosition(); - if (position >= 0 && position < items.size()) { - ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); - } - } - super.onViewAttachedToWindow(holder); - } - - @Override - public int getItemCount() { - return items.size(); - } - - @Override - public int getItemViewType(int position) { - return items.get(position).viewType; - } - - @Override - public void notifyDataSetChanged() { - oldItems.clear(); - oldItems.addAll(items); - items.clear(); - for (int i = 0; i < visibleReactionsList.size(); i++) { - ReactionsLayoutInBubble.VisibleReaction visibleReaction = visibleReactionsList.get(i); - items.add(new InnerItem(visibleReaction.emojicon == null ? VIEW_TYPE_CUSTOM_REACTION : VIEW_TYPE_REACTION, visibleReaction)); - } - if (showUnlockPremiumButton()) { - items.add(new InnerItem(VIEW_TYPE_PREMIUM_BUTTON, null)); - } - if (showCustomEmojiReaction()) { - items.add(new InnerItem(VIEW_TYPE_CUSTOM_EMOJI_BUTTON, null)); - } - setItems(oldItems, items); - } - }); + recyclerListView.setAdapter(listAdapter = new Adapter()); recyclerListView.addOnScrollListener(new LeftRightShadowsListener()); recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -562,6 +457,9 @@ public int getWindowType() { private void animatePullingBack() { if (pullingLeftOffset != 0) { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } pullingDownBackAnimator = ValueAnimator.ofFloat(pullingLeftOffset, 0); pullingDownBackAnimator.addUpdateListener(animation -> { pullingLeftOffset = (float) pullingDownBackAnimator.getAnimatedValue(); @@ -660,7 +558,7 @@ public void setMirrorX(boolean mirrorX) { } @SuppressLint("NotifyDataSetChanged") - private void setVisibleReactionsList(List visibleReactionsList) { + private void setVisibleReactionsList(List visibleReactionsList, boolean animated) { this.visibleReactionsList.clear(); if (showCustomEmojiReaction()) { int i = 0; @@ -693,9 +591,7 @@ private void setVisibleReactionsList(List= MessagesController.getInstance(currentAccount).getChatMaxUniqReactions(messageObject.getDialogId()); TLRPC.ChatFull reactionsChat = chatFull; List visibleReactions = new ArrayList<>(); if (message != null && message.isForwardedChannelPost()) { @@ -1113,6 +1026,11 @@ public void setMessage(MessageObject message, TLRPC.ChatFull chatFull) { if (type == TYPE_TAGS) { allReactionsAvailable = UserConfig.getInstance(currentAccount).isPremium(); fillRecentReactionsList(visibleReactions); + } else if (hitLimit) { + allReactionsAvailable = false; + for (TLRPC.ReactionCount result : messageObject.messageOwner.reactions.results) { + visibleReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(result.reaction)); + } } else if (reactionsChat != null) { if (reactionsChat.available_reactions instanceof TLRPC.TL_chatReactionsAll) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(reactionsChat.id); @@ -1145,14 +1063,14 @@ public void setMessage(MessageObject message, TLRPC.ChatFull chatFull) { fillRecentReactionsList(visibleReactions); } filterReactions(visibleReactions); - showExpandableReactions = !allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + showExpandableReactions = !hitLimit && (!allReactionsAvailable && visibleReactions.size() > 16 || allReactionsAvailable && !UserConfig.getInstance(currentAccount).isPremium() && MessagesController.getInstance(currentAccount).premiumFeaturesBlocked()); if (type == TYPE_TAGS && !UserConfig.getInstance(currentAccount).isPremium()) { showExpandableReactions = false; } if (type == TYPE_STICKER_SET_EMOJI) { showExpandableReactions = true; } - setVisibleReactionsList(visibleReactions); + setVisibleReactionsList(visibleReactions, animated); if (message != null && message.messageOwner.reactions != null && message.messageOwner.reactions.results != null) { for (int i = 0; i < message.messageOwner.reactions.results.size(); i++) { @@ -1257,20 +1175,22 @@ public void setSelectedReactionsInclusive(ArrayList messages) { selectedReactions.clear(); selectedReactions.addAll(getInclusiveReactions(messages)); updateSelected(); - if (type == TYPE_STICKER_SET_EMOJI) { - alwaysSelectedReactions.addAll(selectedReactions); - setMessage(messageObject, null); - } } public void setSelectedReactionInclusive(ReactionsLayoutInBubble.VisibleReaction visibleReaction) { selectedReactions.clear(); selectedReactions.add(visibleReaction); updateSelected(); - if (type == TYPE_STICKER_SET_EMOJI) { - alwaysSelectedReactions.addAll(selectedReactions); - setMessage(messageObject, null); + } + + public void setSelectedEmojis(ArrayList emojis) { + selectedReactions.clear(); + for (String emoji : emojis) { + ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji); + selectedReactions.add(reaction); + alwaysSelectedReactions.add(reaction); } + updateSelected(); } private void updateSelected() { @@ -1289,8 +1209,9 @@ private void filterReactions(List visib if (set.contains(visibleReactions.get(i))) { i--; visibleReactions.remove(i); + } else { + set.add(visibleReactions.get(i)); } - set.add(visibleReactions.get(i)); } } @@ -1298,13 +1219,25 @@ private void fillRecentReactionsList(List hashSet = new HashSet<>(); int added = 0; if (type == TYPE_STICKER_SET_EMOJI) { - for (ReactionsLayoutInBubble.VisibleReaction visibleReaction : alwaysSelectedReactions) { + for (ReactionsLayoutInBubble.VisibleReaction visibleReaction : selectedReactions) { + if (!hashSet.contains(visibleReaction)) { + hashSet.add(visibleReaction); + visibleReactions.add(visibleReaction); + added++; + if (added >= 8) return; + } + } + List enabledReactions = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + for (int i = 0; i < enabledReactions.size(); i++) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(enabledReactions.get(i)); if (!hashSet.contains(visibleReaction)) { hashSet.add(visibleReaction); visibleReactions.add(visibleReaction); added++; + if (added >= 8) return; } } + return; } if (!allReactionsAvailable || type == TYPE_STICKER_SET_EMOJI) { if (type == TYPE_TAGS) { @@ -1519,6 +1452,21 @@ public void setSkipDraw(boolean b) { } public void onCustomEmojiWindowOpened() { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } + pullingLeftOffset = 0f; + if (customReactionsContainer != null) { + customReactionsContainer.invalidate(); + } + invalidate(); + } + + + public void onCustomEmojiWindowClosing() { + if (pullingDownBackAnimator != null) { + pullingDownBackAnimator.cancel(); + } pullingLeftOffset = 0f; if (customReactionsContainer != null) { customReactionsContainer.invalidate(); @@ -1534,7 +1482,7 @@ public void clearRecentReactions() { MediaDataController.getInstance(currentAccount).clearRecentReactions(); List visibleReactions = new ArrayList<>(); fillRecentReactionsList(visibleReactions); - setVisibleReactionsList(visibleReactions); + setVisibleReactionsList(visibleReactions, true); lastVisibleViews.clear(); reactionsWindow.setRecentReactions(visibleReactions); }) @@ -1918,9 +1866,9 @@ public void updateSelected(ReactionsLayoutInBubble.VisibleReaction react) { } private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int position) { + selected = selectedReactions.contains(react); if (currentReaction != null && currentReaction.equals(react)) { this.position = position; - selected = selectedReactions.contains(react); updateImage(react); return; } @@ -1938,7 +1886,6 @@ private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int posi resetAnimation(); currentReaction = react; - selected = selectedReactions.contains(react); hasEnterAnimation = currentReaction.emojicon != null && (showCustomEmojiReaction() || allReactionsIsDefault) && LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); if (type == TYPE_STICKER_SET_EMOJI) { hasEnterAnimation = false; @@ -1992,7 +1939,10 @@ private void setReaction(ReactionsLayoutInBubble.VisibleReaction react, int posi } private void updateImage(ReactionsLayoutInBubble.VisibleReaction react) { - if (currentReaction.emojicon != null) { + if (type == TYPE_STICKER_SET_EMOJI && react != null && react.emojicon != null) { + enterImageView.getImageReceiver().setImageBitmap(Emoji.getEmojiDrawable(react.emojicon)); + loopImageView.getImageReceiver().setImageBitmap(Emoji.getEmojiDrawable(react.emojicon)); + } else if (currentReaction.emojicon != null) { TLRPC.TL_availableReaction defaultReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(currentReaction.emojicon); if (defaultReaction != null) { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(defaultReaction.activate_animation, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f); @@ -2243,12 +2193,14 @@ default boolean drawBackground() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatInfoDidLoad); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad); } @@ -2257,10 +2209,12 @@ public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.chatInfoDidLoad) { TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0]; if (chatFull.id == waitingLoadingChatId && getVisibility() != View.VISIBLE && !(chatFull.available_reactions instanceof TLRPC.TL_chatReactionsNone)) { - setMessage(messageObject, null); + setMessage(messageObject, null, true); setVisibility(View.VISIBLE); startEnterAnimation(false); } + } else if (id == NotificationCenter.emojiLoaded) { + invalidateEmojis(); } } @@ -2388,4 +2342,116 @@ public void setParentLayout(ChatScrimPopupContainerLayout layout) { public static boolean allowSmoothEnterTransition() { return SharedConfig.deviceIsHigh(); } + + public class Adapter extends AdapterWithDiffUtils { + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + switch (viewType) { + default: + case VIEW_TYPE_REACTION: + case VIEW_TYPE_CUSTOM_REACTION: + view = new ReactionHolderView(getContext(), true); + break; + case VIEW_TYPE_PREMIUM_BUTTON: + premiumLockContainer = new FrameLayout(getContext()); + premiumLockIconView = new PremiumLockIconView(getContext(), PremiumLockIconView.TYPE_REACTIONS); + premiumLockIconView.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), Theme.getColor(Theme.key_dialogBackground), 0.7f)); + premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + premiumLockIconView.setScaleX(0f); + premiumLockIconView.setScaleY(0f); + premiumLockIconView.setPadding(dp(1), dp(1), dp(1), dp(1)); + premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); + premiumLockIconView.setOnClickListener(v -> { + int[] position = new int[2]; + v.getLocationOnScreen(position); + showUnlockPremium(position[0] + v.getMeasuredWidth() / 2f, position[1] + v.getMeasuredHeight() / 2f); + }); + view = premiumLockContainer; + break; + case VIEW_TYPE_CUSTOM_EMOJI_BUTTON: + customReactionsContainer = new CustomReactionsContainer(getContext()); + customEmojiReactionsIconView = new InternalImageView(getContext()); + customEmojiReactionsIconView.setImageResource(R.drawable.msg_reactions_expand); + customEmojiReactionsIconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + if (type == TYPE_STORY || type == TYPE_STORY_LIKES || type == TYPE_STICKER_SET_EMOJI) { + customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + } else { + customEmojiReactionsIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + } + customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40))); + customEmojiReactionsIconView.setPadding(dp(2), dp(2), dp(2), dp(2)); + customEmojiReactionsIconView.setContentDescription(LocaleController.getString(R.string.AccDescrExpandPanel)); + customReactionsContainer.addView(customEmojiReactionsIconView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); + customEmojiReactionsIconView.setOnClickListener(v -> { + showCustomEmojiReactionDialog(); + }); + view = customReactionsContainer; + break; + } + + int size = getLayoutParams().height - (int) getTopOffset() - getPaddingTop() - getPaddingBottom(); + view.setLayoutParams(new RecyclerView.LayoutParams(size - dp(12), size)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + ReactionHolderView h = (ReactionHolderView) holder.itemView; + h.setScaleX(1); + h.setScaleY(1); + h.setReaction(items.get(position).reaction, position); + } + } + + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == VIEW_TYPE_REACTION || holder.getItemViewType() == VIEW_TYPE_CUSTOM_REACTION) { + int position = holder.getAdapterPosition(); + if (position >= 0 && position < items.size()) { + ((ReactionHolderView) holder.itemView).updateSelected(items.get(position).reaction); + } + } + super.onViewAttachedToWindow(holder); + } + + @Override + public int getItemCount() { + return items.size(); + } + + @Override + public int getItemViewType(int position) { + return items.get(position).viewType; + } + + public void updateItems(boolean animated) { + oldItems.clear(); + oldItems.addAll(items); + items.clear(); + for (int i = 0; i < visibleReactionsList.size(); i++) { + ReactionsLayoutInBubble.VisibleReaction visibleReaction = visibleReactionsList.get(i); + items.add(new InnerItem(visibleReaction.emojicon == null ? VIEW_TYPE_CUSTOM_REACTION : VIEW_TYPE_REACTION, visibleReaction)); + } + if (showUnlockPremiumButton()) { + items.add(new InnerItem(VIEW_TYPE_PREMIUM_BUTTON, null)); + } + if (showCustomEmojiReaction()) { + items.add(new InnerItem(VIEW_TYPE_CUSTOM_EMOJI_BUTTON, null)); + } + if (animated) { + setItems(oldItems, items); + } else { + super.notifyDataSetChanged(); + } + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java index 6c8cc6ad59..102836da46 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java @@ -48,6 +48,7 @@ public class ReplyMessageLine { private Path color2Path = new Path(); private Path color3Path = new Path(); private int switchedCount = 0; + private float emojiAlpha = 1f; private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emoji; @@ -179,23 +180,17 @@ public int check(MessageObject messageObject, TLRPC.User currentUser, TLRPC.Chat messageObject.messageOwner != null && ( (messageObject.isFromUser() || DialogObject.isEncryptedDialog(messageObject.getDialogId())) && currentUser != null || messageObject.isFromChannel() && currentChat != null || - messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || - messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null || - messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null + messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null || + messageObject.isSponsored() && messageObject.sponsoredColor != null && messageObject.sponsoredColor.color != -1 ) )) { int colorId = 5; if (messageObject.overrideLinkColor >= 0) { colorId = messageObject.overrideLinkColor; - } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { - colorId = messageObject.sponsoredChatInvite.color; - if (type == TYPE_LINK && messageObject.sponsoredChatInvite.chat != null) { - emojiDocumentId = ChatObject.getEmojiId(messageObject.sponsoredChatInvite.chat); - } - } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { - colorId = ChatObject.getColorId(messageObject.sponsoredChatInvite.chat); + } else if (messageObject.isSponsored() && messageObject.sponsoredColor != null && messageObject.sponsoredColor.color != -1) { + colorId = messageObject.sponsoredColor.color; if (type == TYPE_LINK) { - emojiDocumentId = ChatObject.getEmojiId(messageObject.sponsoredChatInvite.chat); + emojiDocumentId = messageObject.sponsoredColor.background_emoji_id; } } else if (messageObject.messageOwner != null && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.from_id != null) { long dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.fwd_from.from_id); @@ -330,6 +325,11 @@ public int check(MessageObject messageObject, TLRPC.User currentUser, TLRPC.Chat return nameColorAnimated.set(nameColor); } + public void setEmojiAlpha(float emojiAlpha) { + this.emojiAlpha = emojiAlpha; + } + + public void resetAnimation() { color1Animated.set(color1, true); color2Animated.set(color2, true); @@ -509,7 +509,7 @@ public void drawBackground(Canvas canvas, RectF rect, float alpha, boolean hasQu if (emoji != null) { final float loadedScale = emojiLoadedT.set(isEmojiLoaded()); - if (loadedScale > 0) { + if (loadedScale > 0 && emojiAlpha > 0) { if (iconCoords == null) { iconCoords = new IconCoords[]{ new IconCoords(4, -6.33f, 1f, 1f), @@ -543,7 +543,7 @@ public void drawBackground(Canvas canvas, RectF rect, float alpha, boolean hasQu if (c.q && !hasQuote) { continue; } - emoji.setAlpha((int) (0xFF * .30f * c.a)); + emoji.setAlpha((int) (0xFF * .30f * c.a * emojiAlpha)); final float cx = x0 - dp(c.x); final float cy = y0 + dp(c.y); final float sz = dp(10) * c.s * loadedScale; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java index ffa3943617..4921e3ad77 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScaleStateListAnimator.java @@ -42,4 +42,9 @@ public static void apply(View view, float scale, float tension) { view.setStateListAnimator(scaleStateListAnimator); } + + public static void reset(View view) { + view.setStateListAnimator(null); + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index de1e6d2a50..5554b6a526 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -646,7 +646,7 @@ public void setImages() { TLRPC.TL_messages_stickerSet stickerSet = ((TLRPC.TL_messages_stickerSet) parentObject); thumbVersion = ((TLRPC.TL_messages_stickerSet) parentObject).set.thumb_version; if (!tabView.inited) { - tabView.svgThumb = DocumentObject.getSvgThumb(stickerSet.set.thumbs, Theme.key_emptyListPlaceholder, 0.2f); + tabView.svgThumb = DocumentObject.getSvgThumb(stickerSet.set.thumbs, Theme.key_emptyListPlaceholder, 0.2f, DocumentObject.containsPhotoSizeType(stickerSet.set.thumbs, "v")); } } thumbType = thumb.type; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java index d55ac5441b..5d116a5e00 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java @@ -447,8 +447,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { layoutParams.weight = 0.0f; layoutParams.width = LayoutHelper.WRAP_CONTENT; } else { - layoutParams.weight = 1.0f / allTextWidth * positionToWidth.get(a); - layoutParams.width = 0; + layoutParams.weight = AndroidUtilities.lerp(1.0f / count, 1.0f / allTextWidth * positionToWidth.get(a), .5f); + layoutParams.width = LayoutHelper.WRAP_CONTENT; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java index 04fe635449..2b062efe99 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -11,8 +11,11 @@ import android.os.Build; import android.os.Bundle; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -26,13 +29,18 @@ import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -46,6 +54,7 @@ import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.DialogCell; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HashtagSearchCell; import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.SharedAudioCell; @@ -53,6 +62,7 @@ import org.telegram.ui.Cells.SharedLinkCell; import org.telegram.ui.Cells.SharedPhotoVideoCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.DialogsActivity; import org.telegram.ui.FilteredSearchView; @@ -63,7 +73,7 @@ import java.util.Iterator; import java.util.Set; -public class SearchViewPager extends ViewPagerFixed implements FilteredSearchView.UiCallback { +public class SearchViewPager extends ViewPagerFixed implements FilteredSearchView.UiCallback, NotificationCenter.NotificationCenterDelegate { protected final ViewPagerAdapter viewPagerAdapter; public FrameLayout searchContainer; @@ -75,6 +85,13 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie private RecyclerItemsEnterAnimator itemsEnterAnimator; private boolean attached; + private DefaultItemAnimator channelsItemAnimator; + public FrameLayout channelsSearchContainer; + public StickerEmptyView channelsEmptyView; + private LinearLayoutManager channelsSearchLayoutManager; + public RecyclerListView channelsSearchListView; + public DialogsChannelsAdapter channelsSearchAdapter; + private NumberTextView selectedMessagesCountTextView; private boolean isActionModeShowed; private HashMap selectedFiles = new HashMap<>(); @@ -220,8 +237,6 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { noMediaFiltersSearchView.setVisibility(View.GONE); noMediaFiltersSearchView.setChatPreviewDelegate(chatPreviewDelegate); - searchContainer = new FrameLayout(context); - FlickerLoadingView loadingView = new FlickerLoadingView(context); loadingView.setViewType(1); emptyView = new StickerEmptyView(context, loadingView, StickerEmptyView.STICKER_TYPE_SEARCH) { @@ -240,6 +255,7 @@ public void setVisibility(int visibility) { emptyView.addView(loadingView, 0); emptyView.showProgress(true, false); + searchContainer = new FrameLayout(context); searchContainer.addView(emptyView); searchContainer.addView(searchListView); searchContainer.addView(noMediaFiltersSearchView); @@ -252,6 +268,82 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { } }); + channelsSearchContainer = new FrameLayout(context); + + channelsItemAnimator = new DefaultItemAnimator() { + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + invalidate(); + } + }; + channelsItemAnimator.setSupportsChangeAnimations(false); + channelsItemAnimator.setDelayAnimations(false); + channelsItemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + channelsItemAnimator.setDurations(350); + + channelsSearchListView = new BlurredRecyclerView(context); + channelsSearchListView.setItemAnimator(channelsItemAnimator); + channelsSearchListView.setPivotY(0); + channelsSearchListView.setVerticalScrollBarEnabled(true); + channelsSearchListView.setInstantClick(true); + channelsSearchListView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); + channelsSearchListView.setLayoutManager(channelsSearchLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + channelsSearchListView.setAnimateEmptyView(true, RecyclerListView.EMPTY_VIEW_ANIMATION_TYPE_ALPHA); + + loadingView = new FlickerLoadingView(context); + loadingView.setViewType(1); + channelsEmptyView = new StickerEmptyView(context, loadingView, StickerEmptyView.STICKER_TYPE_SEARCH) { + @Override + public void setVisibility(int visibility) { + if (noMediaFiltersSearchView.getTag() != null) { + super.setVisibility(View.GONE); + return; + } + super.setVisibility(visibility); + } + }; + channelsEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + channelsEmptyView.subtitle.setVisibility(View.GONE); + channelsEmptyView.setVisibility(View.GONE); + channelsEmptyView.addView(loadingView, 0); + channelsEmptyView.showProgress(true, false); + channelsSearchContainer.addView(channelsEmptyView); + channelsSearchContainer.addView(channelsSearchListView); + channelsSearchListView.setEmptyView(channelsEmptyView); + channelsSearchListView.setAdapter(channelsSearchAdapter = new DialogsChannelsAdapter(channelsSearchListView, context, currentAccount, folderId, null) { + @Override + public void update(boolean animated) { + super.update(animated); + channelsEmptyView.showProgress(loadingMessages || loadingChannels || messages == null || !messages.isEmpty() || searchMyChannels == null || !searchMyChannels.isEmpty() || searchChannels == null || !searchChannels.isEmpty() || searchRecommendedChannels == null || !searchRecommendedChannels.isEmpty(), animated); + if (TextUtils.isEmpty(query)) { + channelsEmptyView.title.setText(LocaleController.getString(R.string.NoChannelsTitle)); + channelsEmptyView.subtitle.setVisibility(View.VISIBLE); + channelsEmptyView.subtitle.setText(LocaleController.getString(R.string.NoChannelsMessage)); + } else { + channelsEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + channelsEmptyView.subtitle.setVisibility(View.GONE); + } + } + + @Override + protected void hideKeyboard() { + AndroidUtilities.hideKeyboard(fragment.getParentActivity().getCurrentFocus()); + } + }); + channelsSearchListView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + AndroidUtilities.hideKeyboard(fragment.getParentActivity().getCurrentFocus()); + } + } + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + channelsSearchAdapter.checkBottom(); + } + }); + itemsEnterAnimator = new RecyclerItemsEnterAnimator(searchListView, true); setAdapter(viewPagerAdapter = new ViewPagerAdapter()); @@ -312,7 +404,11 @@ private void search(View view, int position, String query, boolean reset) { } } - if (view == searchContainer) { + if (view == channelsSearchContainer) { + MessagesController.getInstance(currentAccount).getChannelRecommendations(0); + channelsSearchAdapter.search(query); + channelsEmptyView.setKeyboardHeight(keyboardSize, false); + } else if (view == searchContainer) { if (dialogId == 0 && minDate == 0 && maxDate == 0 || forumDialogId != 0) { lastSearchScrolledToTop = false; dialogsSearchAdapter.searchDialogs(query, includeFolder ? 1 : 0); @@ -779,6 +875,9 @@ public void reset() { if (dialogsSearchAdapter.getItemCount() > 0) { searchLayoutManager.scrollToPositionWithOffset(0, 0); } + if (channelsSearchLayoutManager != null) { + channelsSearchLayoutManager.scrollToPositionWithOffset(0, 0); + } viewsByType.clear(); } @@ -805,6 +904,8 @@ public void setKeyboardHeight(int keyboardSize) { noMediaFiltersSearchView.setKeyboardHeight(keyboardSize, animated); } else if (getChildAt(i) instanceof SearchDownloadsContainer) { ((SearchDownloadsContainer) getChildAt(i)).setKeyboardHeight(keyboardSize, animated); + } else if (getChildAt(i) == channelsSearchContainer) { + channelsEmptyView.setKeyboardHeight(keyboardSize, animated); } } } @@ -872,13 +973,35 @@ public TabsView getTabsView() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.channelRecommendationsLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogDeleted); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogsNeedReload); attached = true; + + if (channelsSearchAdapter != null) { + channelsSearchAdapter.update(false); + } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); attached = false; + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.channelRecommendationsLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogDeleted); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogsNeedReload); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.channelRecommendationsLoaded) { + channelsEmptyView.showProgress(MessagesController.getInstance(currentAccount).getChannelRecommendations(0) != null, true); + channelsSearchAdapter.updateMyChannels(); + channelsSearchAdapter.update(true); + } else if (id == NotificationCenter.dialogDeleted || id == NotificationCenter.dialogsNeedReload) { + channelsSearchAdapter.updateMyChannels(); + channelsSearchAdapter.update(true); + } } @Override @@ -893,7 +1016,7 @@ public void cancelEnterAnimation() { } public void showDownloads() { - setPosition(2); + setPosition(3); } public int getPositionForType(int initialSearchType) { @@ -910,8 +1033,9 @@ private class ViewPagerAdapter extends ViewPagerFixed.Adapter { ArrayList items = new ArrayList<>(); private final static int DIALOGS_TYPE = 0; - private final static int DOWNLOADS_TYPE = 1; - private final static int FILTER_TYPE = 2; + private final static int CHANNELS_TYPE = 1; + private final static int DOWNLOADS_TYPE = 2; + private final static int FILTER_TYPE = 3; public ViewPagerAdapter() { updateItems(); @@ -920,6 +1044,7 @@ public ViewPagerAdapter() { public void updateItems() { items.clear(); items.add(new Item(DIALOGS_TYPE)); + items.add(new Item(CHANNELS_TYPE)); if (!showOnlyDialogsAdapter) { Item item = new Item(FILTER_TYPE); item.filterIndex = 0; @@ -945,9 +1070,11 @@ public void updateItems() { @Override public String getItemTitle(int position) { if (items.get(position).type == DIALOGS_TYPE) { - return LocaleController.getString("SearchAllChatsShort", R.string.SearchAllChatsShort); + return LocaleController.getString(R.string.SearchAllChatsShort); + } else if (items.get(position).type == CHANNELS_TYPE) { + return LocaleController.getString(R.string.ChannelsTab); } else if (items.get(position).type == DOWNLOADS_TYPE) { - return LocaleController.getString("DownloadsTabs", R.string.DownloadsTabs); + return LocaleController.getString(R.string.DownloadsTabs); } else { return FiltersView.filters[items.get(position).filterIndex].getTitle(); } @@ -962,6 +1089,8 @@ public int getItemCount() { public View createView(int viewType) { if (viewType == 1) { return searchContainer; + } else if (viewType == 3) { + return channelsSearchContainer; } else if (viewType == 2) { downloadsContainer = new SearchDownloadsContainer(parent, currentAccount); downloadsContainer.recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -993,6 +1122,9 @@ public int getItemViewType(int position) { if (items.get(position).type == DIALOGS_TYPE) { return 1; } + if (items.get(position).type == CHANNELS_TYPE) { + return 3; + } if (items.get(position).type == DOWNLOADS_TYPE) { return 2; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index 445577f526..49ec818754 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -1149,6 +1149,9 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { updateLayout(); previousScrollOffsetY = scrollOffsetY; } + if (Bulletin.getVisibleBulletin() != null && Bulletin.getVisibleBulletin().getLayout() != null && Bulletin.getVisibleBulletin().getLayout().getParent() instanceof View && ((View) Bulletin.getVisibleBulletin().getLayout().getParent()).getParent() == bulletinContainer2) { + Bulletin.hideVisible(); + } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java index 7bfd691de2..c0218ad441 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareLocationDrawable.java @@ -26,28 +26,35 @@ public class ShareLocationDrawable extends Drawable { private Drawable drawableRight; private int currentType; + public static final int TYPE_ADD = 4; + public static final int TYPE_DISABLE = 5; + public ShareLocationDrawable(Context context, int type) { currentType = type; - if (type == 4) { - drawable = context.getResources().getDrawable(R.drawable.pin); - drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright); + if (type == TYPE_ADD) { + drawable = context.getResources().getDrawable(R.drawable.filled_extend_location).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); + } else if (type == TYPE_DISABLE) { + drawable = context.getResources().getDrawable(R.drawable.filled_stop_location).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); } else if (type == 3) { - drawable = context.getResources().getDrawable(R.drawable.nearby_l); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.nearby_l).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } else if (type == 2) { - drawable = context.getResources().getDrawable(R.drawable.nearby_m); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.nearby_m).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } else if (type == 1) { - drawable = context.getResources().getDrawable(R.drawable.smallanimationpin); - drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright); + drawable = context.getResources().getDrawable(R.drawable.smallanimationpin).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.smallanimationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.smallanimationpinright).mutate(); } else { - drawable = context.getResources().getDrawable(R.drawable.animationpin); - drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft); - drawableRight = context.getResources().getDrawable(R.drawable.animationpinright); + drawable = context.getResources().getDrawable(R.drawable.animationpin).mutate(); + drawableLeft = context.getResources().getDrawable(R.drawable.animationpinleft).mutate(); + drawableRight = context.getResources().getDrawable(R.drawable.animationpinright).mutate(); } } @@ -76,7 +83,7 @@ public void draw(Canvas canvas) { int drawableW = drawable.getIntrinsicWidth(); int drawableH = drawable.getIntrinsicHeight(); - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { size = AndroidUtilities.dp(24); } else if (currentType == 3) { size = AndroidUtilities.dp(44); @@ -104,7 +111,7 @@ public void draw(Canvas canvas) { int cx; int cx2; int cy; - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { w = AndroidUtilities.dp((2.5f) * scale); h = AndroidUtilities.dp((6.5f) * scale); tx = AndroidUtilities.dp((6.0f) * progress[a]); @@ -183,7 +190,7 @@ public int getOpacity() { @Override public int getIntrinsicWidth() { - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { return AndroidUtilities.dp(42); } else if (currentType == 3) { return AndroidUtilities.dp(100); @@ -197,7 +204,7 @@ public int getIntrinsicWidth() { @Override public int getIntrinsicHeight() { - if (currentType == 4) { + if (currentType == TYPE_ADD || currentType == TYPE_DISABLE) { return AndroidUtilities.dp(42); } else if (currentType == 3) { return AndroidUtilities.dp(100); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index b86483735e..4ae0079948 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -2,6 +2,7 @@ import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.lerp; +import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.getString; import static org.telegram.messenger.MediaDataController.MEDIA_PHOTOVIDEO; @@ -371,6 +372,9 @@ private boolean checkPointerIds(MotionEvent ev) { } public boolean isSwipeBackEnabled() { + if (canEditStories() && getClosestTab() == TAB_STORIES && isActionModeShown()) { + return false; + } return !photoVideoChangeColumnsAnimation && !tabsAnimationInProgress; } @@ -607,6 +611,7 @@ public void updateFastScrollVisibility(MediaPage mediaPage, boolean animated) { private SavedMessagesSearchAdapter savedMessagesSearchAdapter; private ChatActivityContainer savedMessagesContainer; private ChatUsersAdapter chatUsersAdapter; + private ItemTouchHelper storiesReorder; private StoriesAdapter storiesAdapter; private StoriesAdapter animationSupportingStoriesAdapter; private StoriesAdapter archivedStoriesAdapter; @@ -1431,6 +1436,8 @@ public Period(TLRPC.TL_searchResultPosition calendarPeriod) { private HintView fwdRestrictedHint; private Theme.ResourcesProvider resourcesProvider; + private Runnable applyBulletin; + public boolean hasInternet() { return profileActivity.getConnectionsManager().getConnectionState() == ConnectionsManager.ConnectionStateConnected; } @@ -1942,29 +1949,31 @@ public void onClick(View view) { actionModeViews.add(selectedMessagesCountTextView); if (!DialogObject.isEncryptedDialog(dialog_id)) { - forwardNoQuoteItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); - forwardNoQuoteItem.setIcon(R.drawable.msg_forward_noquote); - forwardNoQuoteItem.setContentDescription(LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); - forwardNoQuoteItem.setDuplicateParentStateEnabled(false); - actionModeLayout.addView(forwardNoQuoteItem, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); - actionModeViews.add(forwardNoQuoteItem); - forwardNoQuoteItem.setOnClickListener(v -> onActionBarItemClick(v, forward_noquote)); - - gotoItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); - gotoItem.setIcon(R.drawable.msg_message); - gotoItem.setContentDescription(getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); - gotoItem.setDuplicateParentStateEnabled(false); - actionModeLayout.addView(gotoItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); - actionModeViews.add(gotoItem); - gotoItem.setOnClickListener(v -> onActionBarItemClick(v, gotochat)); - - forwardItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); - forwardItem.setIcon(R.drawable.msg_forward); - forwardItem.setContentDescription(getString("Forward", R.string.Forward)); - forwardItem.setDuplicateParentStateEnabled(false); - actionModeLayout.addView(forwardItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); - actionModeViews.add(forwardItem); - forwardItem.setOnClickListener(v -> onActionBarItemClick(v, forward)); + if (!isStoriesView()) { + forwardNoQuoteItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + forwardNoQuoteItem.setIcon(R.drawable.msg_forward_noquote); + forwardNoQuoteItem.setContentDescription(LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); + forwardNoQuoteItem.setDuplicateParentStateEnabled(false); + actionModeLayout.addView(forwardNoQuoteItem, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); + actionModeViews.add(forwardNoQuoteItem); + forwardNoQuoteItem.setOnClickListener(v -> onActionBarItemClick(v, forward_noquote)); + + gotoItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + gotoItem.setIcon(R.drawable.msg_message); + gotoItem.setContentDescription(getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); + gotoItem.setDuplicateParentStateEnabled(false); + actionModeLayout.addView(gotoItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); + actionModeViews.add(gotoItem); + gotoItem.setOnClickListener(v -> onActionBarItemClick(v, gotochat)); + + forwardItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + forwardItem.setIcon(R.drawable.msg_forward); + forwardItem.setContentDescription(getString("Forward", R.string.Forward)); + forwardItem.setDuplicateParentStateEnabled(false); + actionModeLayout.addView(forwardItem, new LinearLayout.LayoutParams(dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); + actionModeViews.add(forwardItem); + forwardItem.setOnClickListener(v -> onActionBarItemClick(v, forward)); + } pinItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); pinItem.setIcon(R.drawable.msg_pin); @@ -2050,6 +2059,67 @@ public void notifyDataSetChanged() { } } }; + storiesReorder = new ItemTouchHelper(new ItemTouchHelper.Callback() { + private RecyclerListView listView; + @Override + public boolean isLongPressDragEnabled() { + return isActionModeShowed; + } + + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + if (isActionModeShowed && storiesAdapter.canReorder(viewHolder.getAdapterPosition())) { + listView = mediaPages[0] == null ? null : mediaPages[0].listView; + if (listView != null) { + listView.setItemAnimator(mediaPages[0].itemAnimator); + } + return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, 0); + } else { + return makeMovementFlags(0, 0); + } + } + + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + if (!storiesAdapter.canReorder(viewHolder.getAdapterPosition()) || !storiesAdapter.canReorder(target.getAdapterPosition())) { + return false; + } + storiesAdapter.swapElements(viewHolder.getAdapterPosition(), target.getAdapterPosition()); + return true; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + + } + + @Override + public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { + if (listView != null && viewHolder != null) { + listView.hideSelector(false); + } + if (actionState == ItemTouchHelper.ACTION_STATE_IDLE) { + storiesAdapter.reorderDone(); + if (listView != null) { + listView.setItemAnimator(null); + } + } else { + if (listView != null) { + listView.cancelClickRunnables(false); + } + if (viewHolder != null) { + viewHolder.itemView.setPressed(true); + } + } + super.onSelectedChanged(viewHolder, actionState); + } + + @Override + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + super.clearView(recyclerView, viewHolder); + viewHolder.itemView.setPressed(false); + } + }); animationSupportingStoriesAdapter = new StoriesAdapter(context, false); archivedStoriesAdapter = new StoriesAdapter(context, true) { @Override @@ -2116,7 +2186,7 @@ public void setTranslationX(float translationX) { invalidateBlur(); } }; - addView(mediaPage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, isStoriesView() ? 0 : 48, 0, 0)); + addView(mediaPage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, customTabs() ? 0 : 48, 0, 0)); if (a == 1) { mediaPage.setTranslationX(AndroidUtilities.displaySize.x); } @@ -2226,7 +2296,7 @@ public int getSpanSize(int position) { mediaPages[a].buttonView.setOnClickListener(v -> { if (v.getAlpha() < 0.5f) return; profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); - StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); + openStoryRecorder(); }); mediaPages[a].listView = new InternalListView(context) { @@ -2612,6 +2682,10 @@ protected void dispatchDraw(Canvas canvas) { poller = UserListPoller.getInstance(profileActivity.getCurrentAccount()); } poller.checkList(this); + + if (!photoVideoChangeColumnsAnimation) { + changeColumnsTab = -1; + } } @Override @@ -2948,7 +3022,7 @@ public boolean onItemClick(View view, int position, float x, float y) { return onItemLongClick(((SharedAudioCell) view).getMessage(), view, 0); } else if (mediaPage.selectedType == TAB_GIF && view instanceof ContextLinkCell) { return onItemLongClick((MessageObject) ((ContextLinkCell) view).getParentObject(), view, 0); - } else if ((mediaPage.selectedType == TAB_PHOTOVIDEO || mediaPage.selectedType == TAB_ARCHIVED_STORIES || mediaPage.selectedType == TAB_STORIES && isStoriesView()) && view instanceof SharedPhotoVideoCell2) { + } else if ((mediaPage.selectedType == TAB_PHOTOVIDEO || mediaPage.selectedType == TAB_ARCHIVED_STORIES || mediaPage.selectedType == TAB_STORIES && canEditStories()) && view instanceof SharedPhotoVideoCell2) { MessageObject messageObject = ((SharedPhotoVideoCell2) view).getMessageObject(); if (messageObject != null) { return onItemLongClick(messageObject, view, mediaPage.selectedType); @@ -3061,7 +3135,7 @@ protected void onDraw(Canvas canvas) { floatingDateView.setTranslationY(-dp(48)); addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 48 + 4, 0, 0)); - if (!isStoriesView()) { + if (!customTabs()) { addView(fragmentContextView = new FragmentContextView(context, parent, this, false, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); fragmentContextView.setDelegate((start, show) -> { if (!start) { @@ -3120,7 +3194,7 @@ public void updateTags(boolean notify) { shadowLine = new View(context); shadowLine.setBackgroundColor(getThemedColor(Theme.key_divider)); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1); - layoutParams.topMargin = isStoriesView() ? 0 : dp(48) - 1; + layoutParams.topMargin = customTabs() ? 0 : dp(48) - 1; addView(shadowLine, layoutParams); updateTabs(false); @@ -3130,6 +3204,10 @@ public void updateTags(boolean notify) { } } + protected boolean customTabs() { + return false; + } + protected boolean isStoriesView() { return false; } @@ -3147,6 +3225,10 @@ protected boolean includeSavedDialogs() { return false; } + protected boolean isSelf() { + return false; + } + protected int getInitialTab() { return 0; } @@ -3391,9 +3473,9 @@ private void startPinchToMediaColumnsCount(boolean pinchScaleUp) { } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : (changeColumnsTab == TAB_STORIES && isStoriesView() ? dp(72) : 0), + changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0, mediaPage.animationSupportingListView.getPaddingRight(), - mediaPage.animationSupportingListView.getPaddingBottom() + isStoriesView() ? dp(72) : 0 ); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES && isStoriesView() ? View.VISIBLE : View.GONE); @@ -3593,9 +3675,9 @@ private void animateToMediaColumnsCount(int newColumnsCount) { } mediaPage.animationSupportingListView.setPadding( mediaPage.animationSupportingListView.getPaddingLeft(), - (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : (changeColumnsTab == TAB_STORIES && isStoriesView() ? dp(72) : 0))), + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? dp(64) : 0)), mediaPage.animationSupportingListView.getPaddingRight(), - mediaPage.animationSupportingListView.getPaddingBottom() + (mediaPage.animationSupportingListView.hintPaddingBottom = (isStoriesView() ? dp(72) : 0)) ); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES ? View.VISIBLE : View.GONE); mediaPage.buttonView.setVisibility(changeColumnsTab == TAB_STORIES ? View.VISIBLE : View.GONE); @@ -3637,7 +3719,7 @@ public void onAnimationEnd(Animator animation) { continue; } int oldItemCount = adapter.getItemCount(); - if (i == TAB_PHOTOVIDEO) { + if (i == 0) { sharedMediaData[0].setListFrozen(false); } mediaPages[i].layoutManager.setSpanCount(mediaColumnsCount[ci]); @@ -4269,7 +4351,38 @@ public void setCommonGroupsCount(int count) { public void onActionBarItemClick(View v, int id) { if (id == delete) { - if (getSelectedTab() == TAB_SAVED_DIALOGS) { + if (getSelectedTab() == TAB_STORIES || getSelectedTab() == TAB_ARCHIVED_STORIES) { + if (selectedFiles[0] != null) { + ArrayList storyItems = new ArrayList<>(); + for (int i = 0; i < selectedFiles[0].size(); ++i) { + MessageObject messageObject = selectedFiles[0].valueAt(i); + if (messageObject.storyItem != null) { + storyItems.add(messageObject.storyItem); + } + } + + if (!storyItems.isEmpty()) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); + builder.setTitle(storyItems.size() > 1 ? LocaleController.getString(R.string.DeleteStoriesTitle) : LocaleController.getString(R.string.DeleteStoryTitle)); + builder.setMessage(LocaleController.formatPluralString("DeleteStoriesSubtitle", storyItems.size())); + builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + profileActivity.getMessagesController().getStoriesController().deleteStories(dialog_id, storyItems); + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_delete, LocaleController.formatPluralString("StoriesDeleted", storyItems.size())).show(); + closeActionMode(false); + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (DialogInterface.OnClickListener) (dialog, which) -> { + dialog.dismiss(); + }); + AlertDialog dialog = builder.create(); + dialog.show(); + dialog.redPositive(); + } + } + return; + } else if (getSelectedTab() == TAB_SAVED_DIALOGS) { final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); final ArrayList selectedDialogs = new ArrayList<>(); for (int i = 0; i < controller.allDialogs.size(); ++i) { @@ -4328,7 +4441,7 @@ public void onActionBarItemClick(View v, int id) { } else { currentChat = profileActivity.getMessagesController().getChat(-dialog_id); } - AlertsCreator.createDeleteMessagesAlert(profileActivity, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 0, 0, 1, () -> { + AlertsCreator.createDeleteMessagesAlert(profileActivity, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 0, 0, null, () -> { showActionMode(false); actionBar.closeSearchField(); cantDeleteMessagesCount = 0; @@ -4464,26 +4577,112 @@ public void onActionBarItemClick(View v, int id) { } profileActivity.presentFragment(chatActivity, false); } else if (id == pin || id == unpin) { - final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); - final ArrayList selectedDialogs = new ArrayList<>(); - for (int i = 0; i < controller.allDialogs.size(); ++i) { - final long did = controller.allDialogs.get(i).dialogId; - if (savedDialogsAdapter.selectedDialogs.contains(did)) { - selectedDialogs.add(did); + if (getClosestTab() == TAB_STORIES) { + if (storiesAdapter == null || storiesAdapter.storiesList == null) + return; + ArrayList ids = new ArrayList<>(); + for (int i = 0; i < selectedFiles[0].size(); ++i) { + ids.add(selectedFiles[0].valueAt(i).getId()); } - } - if (!controller.updatePinned(selectedDialogs, id == pin, true)) { - LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); - profileActivity.showDialog(limitReachedBottomSheet); + if (id == pin && ids.size() > profileActivity.getMessagesController().storiesPinnedToTopCountMax) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_infotip, AndroidUtilities.replaceTags(formatPluralString("StoriesPinLimit", profileActivity.getMessagesController().storiesPinnedToTopCountMax))).show(); + return; + } + + if (storiesAdapter.storiesList.updatePinned(ids, id == pin)) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_infotip, AndroidUtilities.replaceTags(formatPluralString("StoriesPinLimit", profileActivity.getMessagesController().storiesPinnedToTopCountMax))).show(); + } else { + if (id == pin) { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_pin, AndroidUtilities.replaceTags(formatPluralString("StoriesPinned", ids.size())), formatPluralString("StoriesPinnedText", ids.size())).show(); + } else { + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.ic_unpin, AndroidUtilities.replaceTags(formatPluralString("StoriesUnpinned", ids.size()))).show(); + } + + } + + closeActionMode(false); +// if (profileActivity == null) return; +// final long dialogId = profileActivity.getUserConfig().getClientUserId(); +// if (applyBulletin != null) { +// applyBulletin.run(); +// applyBulletin = null; +// } +// Bulletin.hideVisible(); +// boolean pin = getClosestTab() == SharedMediaLayout.TAB_ARCHIVED_STORIES; +// int count = 0; +// ArrayList storyItems = new ArrayList<>(); +// SparseArray actionModeMessageObjects = getActionModeSelected(); +// if (actionModeMessageObjects != null) { +// for (int i = 0; i < actionModeMessageObjects.size(); ++i) { +// MessageObject messageObject = actionModeMessageObjects.valueAt(i); +// if (messageObject.storyItem != null) { +// storyItems.add(messageObject.storyItem); +// count++; +// } +// } +// } +// closeActionMode(false); +// if (pin) { +// scrollToPage(SharedMediaLayout.TAB_STORIES); +// scrollSlidingTextTabStrip.selectTabWithId(SharedMediaLayout.TAB_STORIES, 1f); +// } +// if (storyItems.isEmpty()) { +// return; +// } +// boolean[] pastValues = new boolean[storyItems.size()]; +// for (int i = 0; i < storyItems.size(); ++i) { +// TL_stories.StoryItem storyItem = storyItems.get(i); +// pastValues[i] = storyItem.pinned; +// storyItem.pinned = pin; +// } +// profileActivity.getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); +// final boolean[] undone = new boolean[] { false }; +// applyBulletin = () -> { +// profileActivity.getMessagesController().getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, null); +// }; +// final Runnable undo = () -> { +// undone[0] = true; +// AndroidUtilities.cancelRunOnUIThread(applyBulletin); +// for (int i = 0; i < storyItems.size(); ++i) { +// TL_stories.StoryItem storyItem = storyItems.get(i); +// storyItem.pinned = pastValues[i]; +// } +// profileActivity.getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); +// }; +// Bulletin bulletin; +// if (pin) { +// bulletin = BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatPluralString("StorySavedTitle", count), LocaleController.getString(R.string.StorySavedSubtitle), LocaleController.getString(R.string.Undo), undo).show(); +// } else { +// bulletin = BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.chats_archived, LocaleController.formatPluralString("StoryArchived", count), LocaleController.getString(R.string.Undo), Bulletin.DURATION_PROLONG, undo).show(); +// } +// bulletin.setOnHideListener(() -> { +// if (!undone[0] && applyBulletin != null) { +// applyBulletin.run(); +// } +// applyBulletin = null; +// }); } else { - for (int i = 0; i < mediaPages.length; ++i) { - if (mediaPages[i].selectedType == TAB_SAVED_DIALOGS) { - mediaPages[i].layoutManager.scrollToPositionWithOffset(0, 0); - break; + final SavedMessagesController controller = profileActivity.getMessagesController().getSavedMessagesController(); + final ArrayList selectedDialogs = new ArrayList<>(); + for (int i = 0; i < controller.allDialogs.size(); ++i) { + final long did = controller.allDialogs.get(i).dialogId; + if (savedDialogsAdapter.selectedDialogs.contains(did)) { + selectedDialogs.add(did); } } + if (!controller.updatePinned(selectedDialogs, id == pin, true)) { + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(profileActivity, getContext(), LimitReachedBottomSheet.TYPE_PIN_SAVED_DIALOGS, profileActivity.getCurrentAccount(), null); + profileActivity.showDialog(limitReachedBottomSheet); + } else { + for (int i = 0; i < mediaPages.length; ++i) { + if (mediaPages[i].selectedType == TAB_SAVED_DIALOGS) { + mediaPages[i].layoutManager.scrollToPositionWithOffset(0, 0); + break; + } + } + } + closeActionMode(true); } - closeActionMode(true); } } @@ -4502,6 +4701,9 @@ private boolean prepareForMoving(MotionEvent ev, boolean forward) { if (searching && getSelectedTab() == TAB_SAVED_DIALOGS) { return false; } + if (canEditStories() && isActionModeShowed && getClosestTab() == TAB_STORIES) { + return false; + } updateOptionsSearch(); getParent().requestDisallowInterceptTouchEvent(true); @@ -4564,7 +4766,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (child instanceof MediaPage) { measureChildWithMargins(child, widthMeasureSpec, 0, MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY), 0); - ((MediaPage) child).listView.setPadding(0, ((MediaPage) child).listView.topPadding, 0, topPadding); + ((MediaPage) child).listView.setPadding(0, ((MediaPage) child).listView.topPadding, 0, ((MediaPage) child).listView.bottomPadding); } else { measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } @@ -4835,6 +5037,7 @@ public boolean closeActionMode(boolean uncheckAnimated) { selectedFiles[a].clear(); } cantDeleteMessagesCount = 0; + onActionModeSelectedUpdate(selectedFiles[0]); showActionMode(false); updateRowsSelection(uncheckAnimated); if (savedDialogsAdapter != null) { @@ -4859,6 +5062,10 @@ protected void onActionModeSelectedUpdate(SparseArray messageObje } + public SparseArray getActionModeSelected() { + return selectedFiles[0]; + } + private AnimatorSet actionModeAnimation; public boolean isActionModeShown() { @@ -4897,6 +5104,35 @@ public void onAnimationEnd(Animator animation) { } }); actionModeAnimation.start(); + if (show) { + updateStoriesPinButton(); + } + } + + private void updateStoriesPinButton() { + if (getClosestTab() == TAB_ARCHIVED_STORIES) { + if (pinItem != null) { + pinItem.setVisibility(View.GONE); + } + if (unpinItem != null) { + unpinItem.setVisibility(View.GONE); + } + } else if (getClosestTab() == TAB_STORIES) { + boolean hasUnpinned = false; + for (int i = 0; i < selectedFiles[0].size(); ++i) { + MessageObject msg = selectedFiles[0].valueAt(i); + if (storiesAdapter != null && storiesAdapter.storiesList != null && !storiesAdapter.storiesList.isPinned(msg.getId())) { + hasUnpinned = true; + break; + } + } + if (pinItem != null) { + pinItem.setVisibility(hasUnpinned ? View.VISIBLE : View.GONE); + } + if (unpinItem != null) { + unpinItem.setVisibility(!hasUnpinned ? View.VISIBLE : View.GONE); + } + } } @Override @@ -5671,16 +5907,16 @@ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues sta if (!NaConfig.INSTANCE.getDisableStories().Bool() && ((DialogObject.isUserDialog(dialog_id) || DialogObject.isChatDialog(dialog_id)) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || info != null && info.stories_pinned_available || isStoriesView()) && includeStories())) { if (isArchivedOnlyStoriesView()) { if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString(R.string.ProfileArchivedStories), idToView); } scrollSlidingTextTabStrip.animationDuration = 420; } else { if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, getString(R.string.ProfileStories), idToView); } if (isStoriesView()) { if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) { - scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString("ProfileStories", R.string.ProfileStories), idToView); + scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, getString(R.string.ProfileArchivedStories), idToView); } scrollSlidingTextTabStrip.animationDuration = 420; } @@ -5832,6 +6068,9 @@ private void switchToCurrentSelectedMode(boolean animated) { boolean fastScrollVisible = false; int spanCount = 100; RecyclerView.Adapter currentAdapter = mediaPages[a].listView.getAdapter(); + if (currentAdapter == storiesAdapter) { + storiesReorder.attachToRecyclerView(null); + } RecyclerView.RecycledViewPool viewPool = null; if (searching && searchWas) { if (mediaPages[a].searchViewPool == null) { @@ -5934,9 +6173,9 @@ private void switchToCurrentSelectedMode(boolean animated) { mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); mediaPages[a].listView.setPadding( mediaPages[a].listView.getPaddingLeft(), - (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : (mediaPages[a].selectedType == TAB_STORIES && isStoriesView() ? dp(72) : 0)), + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? dp(64) : 0), mediaPages[a].listView.getPaddingRight(), - mediaPages[a].listView.getPaddingBottom() + (mediaPages[a].listView.hintPaddingTop = isStoriesView() ? dp(72) : 0) ); mediaPages[a].buttonView.setVisibility(mediaPages[a].selectedType == TAB_STORIES && isStoriesView() ? View.VISIBLE : View.GONE); @@ -6004,6 +6243,7 @@ private void switchToCurrentSelectedMode(boolean animated) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(storiesAdapter); } + storiesReorder.attachToRecyclerView(mediaPages[a].listView); spanCount = mediaColumnsCount[1]; } else if (mediaPages[a].selectedType == TAB_ARCHIVED_STORIES) { if (currentAdapter != archivedStoriesAdapter) { @@ -6119,26 +6359,39 @@ private void switchToCurrentSelectedMode(boolean animated) { } } if (mediaPages[a].selectedType == TAB_STORIES) { - mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + if (isSelf()) { + mediaPages[a].emptyView.stickerView.setVisibility(View.GONE); + mediaPages[a].emptyView.button.setVisibility(View.GONE); + } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.button.setText(addPostText(), false); + } mediaPages[a].emptyView.title.setText(isStoriesView() ? getString(R.string.NoPublicStoriesTitle2) : getString(R.string.NoStoriesTitle)); mediaPages[a].emptyView.subtitle.setText(isStoriesView() ? getString(R.string.NoStoriesSubtitle2) : ""); - mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); - mediaPages[a].emptyView.button.setText(addPostText(), false); mediaPages[a].emptyView.button.setOnClickListener(v -> { profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); }); } else if (mediaPages[a].selectedType == TAB_ARCHIVED_STORIES) { - mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + if (isSelf()) { + mediaPages[a].emptyView.stickerView.setVisibility(View.GONE); + mediaPages[a].emptyView.button.setVisibility(View.GONE); + } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_ALBUM); + mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); + mediaPages[a].emptyView.button.setText(addPostText(), false); + } mediaPages[a].emptyView.title.setText(getString(R.string.NoArchivedStoriesTitle)); mediaPages[a].emptyView.subtitle.setText(isStoriesView() ? getString(R.string.NoArchivedStoriesSubtitle) : ""); - mediaPages[a].emptyView.button.setVisibility(View.VISIBLE); - mediaPages[a].emptyView.button.setText(addPostText(), false); mediaPages[a].emptyView.button.setOnClickListener(v -> { profileActivity.getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); }); } else { + mediaPages[a].emptyView.stickerView.setVisibility(View.VISIBLE); mediaPages[a].emptyView.setStickerType(StickerEmptyView.STICKER_TYPE_SEARCH); mediaPages[a].emptyView.title.setText(getString("NoResult", R.string.NoResult)); mediaPages[a].emptyView.subtitle.setText(getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); @@ -6176,7 +6429,10 @@ private boolean onItemLongClick(MessageObject item, View view, int a) { } deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(View.VISIBLE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); + } + if (forwardItem != null) { + forwardItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); } selectedMessagesCountTextView.setNumber(1, false); AnimatorSet animatorSet = new AnimatorSet(); @@ -6216,7 +6472,7 @@ private void onItemClick(int index, View view, MessageObject message, int a, int return; } if (isActionModeShowed) { - if (selectedMode == TAB_STORIES && !isStoriesView()) { + if (selectedMode == TAB_STORIES && !canEditStories()) { return; } int loadIndex = message.getDialogId() == dialog_id ? 0 : 1; @@ -6241,17 +6497,12 @@ private void onItemClick(int index, View view, MessageObject message, int a, int selectedMessagesCountTextView.setNumber(selectedFiles[0].size() + selectedFiles[1].size(), true); deleteItem.setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); if (gotoItem != null) { - gotoItem.setVisibility(selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); + gotoItem.setVisibility(getClosestTab() != TAB_STORIES && selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); } if (forwardItem != null) { - forwardItem.setVisibility(View.VISIBLE); - } - if (pinItem != null) { - pinItem.setVisibility(View.GONE); - } - if (unpinItem != null) { - unpinItem.setVisibility(View.GONE); + forwardItem.setVisibility(getClosestTab() != TAB_STORIES ? View.VISIBLE : View.GONE); } + updateStoriesPinButton(); } scrolling = false; if (view instanceof SharedDocumentCell) { @@ -6268,13 +6519,13 @@ private void onItemClick(int index, View view, MessageObject message, int a, int ((SharedPhotoVideoCell2) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); } } else { - if (selectedMode == 0) { + if (selectedMode == TAB_PHOTOVIDEO) { int i = index - sharedMediaData[selectedMode].startOffset; if (i >= 0 && i < sharedMediaData[selectedMode].messages.size()) { PhotoViewer.getInstance().setParentActivity(profileActivity); PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, i, dialog_id, mergeDialogId, topicId, provider); } - } else if (selectedMode == 2 || selectedMode == 4) { + } else if (selectedMode == TAB_VOICE || selectedMode == TAB_AUDIO) { if (view instanceof SharedAudioCell) { ((SharedAudioCell) view).didPressedButton(); } @@ -6288,7 +6539,7 @@ private void onItemClick(int index, View view, MessageObject message, int a, int } else { PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, dialog_id, mergeDialogId, topicId, provider); } - } else if (selectedMode == 1) { + } else if (selectedMode == TAB_FILES) { if (view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; TLRPC.Document document = message.getDocument(); @@ -6316,7 +6567,7 @@ private void onItemClick(int index, View view, MessageObject message, int a, int cell.updateFileExistIcon(true); } } - } else if (selectedMode == 3) { + } else if (selectedMode == TAB_LINKS) { try { TLRPC.WebPage webPage = MessageObject.getMedia(message.messageOwner) != null ? MessageObject.getMedia(message.messageOwner).webpage : null; String link = null; @@ -6990,7 +7241,28 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType if (sharedResources == null) { sharedResources = new SharedPhotoVideoCell2.SharedResources(parent.getContext(), resourcesProvider); } - SharedPhotoVideoCell2 cell = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()); + SharedPhotoVideoCell2 cell = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()) { +// private Runnable startDragRunnable = () -> { +// if (mediaPages[0] == null || mediaPages[0].listView == null) { +// return; +// } +// if (isActionModeShowed && viewType == VIEW_TYPE_STORY && SharedPhotoVideoAdapter.this == storiesAdapter && isStoriesView()) { +// storiesReorder.startDrag(mediaPages[0].listView.getChildViewHolder(this)); +// } +// }; +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// if (isActionModeShowed && viewType == VIEW_TYPE_STORY && SharedPhotoVideoAdapter.this == storiesAdapter && isStoriesView()) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// AndroidUtilities.cancelRunOnUIThread(this.startDragRunnable); +// AndroidUtilities.runOnUIThread(this.startDragRunnable, (long) (ViewConfiguration.getLongPressTimeout() * .75f)); +// } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { +// AndroidUtilities.cancelRunOnUIThread(this.startDragRunnable); +// } +// } +// return super.onTouchEvent(event); +// } + }; cell.setGradientView(globalGradientView); if (this == storiesAdapter || this == archivedStoriesAdapter) { cell.isStory = true; @@ -8213,7 +8485,7 @@ public void openPreview(int position) { } profileActivity.getNotificationCenter().postNotificationName(NotificationCenter.channelRecommendationsLoaded, -dialog_id); profileActivity.getMessagesController().addUserToChat(chat.id, profileActivity.getUserConfig().getCurrentUser(), 0, null, profileActivity, () -> { - BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatString(R.string.YouJoinedChannel, chat == null ? "" : chat.title)).show(); + BulletinFactory.of(profileActivity).createSimpleBulletin(R.raw.contact_check, LocaleController.formatString(R.string.YouJoinedChannel, chat == null ? "" : chat.title)).show(true); }); }); previewMenu.addView(joinChannel); @@ -8621,11 +8893,13 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { cell.isStory = true; position -= getTopOffset(); if (position < 0 || position >= storiesList.messageObjects.size()) { + cell.isStoryPinned = false; cell.setMessageObject(null, columnsCount()); cell.isStory = true; return; } MessageObject messageObject = storiesList.messageObjects.get(position); + cell.isStoryPinned = messageObject != null && storiesList.isPinned(messageObject.getId()); cell.setMessageObject(messageObject, columnsCount()); if (isActionModeShowed && messageObject != null) { cell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, false); @@ -8670,6 +8944,66 @@ public String getLetter(int position) { public void onFastScrollSingleTap() { showMediaCalendar(isArchive ? TAB_ARCHIVED_STORIES : TAB_STORIES, true); } + + public boolean canReorder(int position) { + if (isArchive) return false; + if (storiesList == null) return false; + if (position < 0 || position >= storiesList.messageObjects.size()) return false; + MessageObject messageObject = storiesList.messageObjects.get(position); + return storiesList.isPinned(messageObject.getId()); + } + + public ArrayList lastPinnedIds = new ArrayList<>(); + public boolean applyingReorder; + + public boolean swapElements(int fromPosition, int toPosition) { + if (isArchive) return false; + if (storiesList == null) return false; + if (fromPosition < 0 || fromPosition >= storiesList.messageObjects.size()) return false; + if (toPosition < 0 || toPosition >= storiesList.messageObjects.size()) return false; + + ArrayList pinnedIds = new ArrayList<>(storiesList.pinnedIds); + + if (!applyingReorder) { + lastPinnedIds.clear(); + lastPinnedIds.addAll(pinnedIds); + applyingReorder = true; + } + + MessageObject from = storiesList.messageObjects.get(fromPosition); + MessageObject to = storiesList.messageObjects.get(toPosition); + + pinnedIds.remove((Object) from.getId()); + pinnedIds.add(Utilities.clamp(toPosition, pinnedIds.size(), 0), from.getId()); + + storiesList.updatePinnedOrder(pinnedIds, false); + + notifyItemMoved(fromPosition, toPosition); + + return true; + } + + public void reorderDone() { + if (isArchive) return; + if (storiesList == null) return; + if (!applyingReorder) return; + + boolean changed = lastPinnedIds.size() != storiesList.pinnedIds.size(); + if (!changed) { + for (int i = 0; i < lastPinnedIds.size(); ++i) { + if (lastPinnedIds.get(i) != storiesList.pinnedIds.get(i)) { + changed = true; + break; + } + } + } + + if (changed) { + storiesList.updatePinnedOrder(storiesList.pinnedIds, true); + } + + applyingReorder = false; + } } private class ChatUsersAdapter extends RecyclerListView.SelectionAdapter { @@ -9328,6 +9662,7 @@ protected void onTabScroll(boolean scrolling) {} public static class InternalListView extends BlurredRecyclerView implements StoriesListPlaceProvider.ClippedView { public int hintPaddingTop; + public int hintPaddingBottom; public InternalListView(Context context) { super(context); @@ -9336,7 +9671,7 @@ public InternalListView(Context context) { @Override public void updateClip(int[] clip) { clip[0] = getPaddingTop() - dp(2) - hintPaddingTop; - clip[1] = getMeasuredHeight() - getPaddingBottom(); + clip[1] = getMeasuredHeight() - getPaddingBottom() - hintPaddingBottom; } } @@ -9414,4 +9749,12 @@ public void showPremiumFloodWaitBulletin(final boolean isUpload) { }), boldN) ).setDuration(8000).show(true); } + + public boolean canEditStories() { + return isStoriesView() || profileActivity != null && profileActivity.getMessagesController().getStoriesController().canEditStories(dialog_id); + } + + public void openStoryRecorder() { + StoryRecorder.getInstance(profileActivity.getParentActivity(), profileActivity.getCurrentAccount()).open(null); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java index bf9063c0db..ebef41627d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java @@ -63,6 +63,7 @@ public SharingLocationsAlert(Context context, SharingLocationsAlertDelegate shar super(context, false, resourcesProvider); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.liveLocationsChanged); delegate = sharingLocationsAlertDelegate; + fixNavigationBar(); shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.SRC_IN)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java index 8dd08be9ce..d4b2dad5a4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java @@ -63,4 +63,8 @@ public void restoreStateParams(Bundle bundle) { public boolean needBackButton() { return false; } + + public void onResume() { + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java index caf86c1ed6..a37349a5b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerCategoriesListView.java @@ -50,12 +50,18 @@ public class StickerCategoriesListView extends RecyclerListView { - @IntDef({CategoriesType.DEFAULT, CategoriesType.STATUS, CategoriesType.PROFILE_PHOTOS}) + @IntDef({ + CategoriesType.DEFAULT, + CategoriesType.STATUS, + CategoriesType.PROFILE_PHOTOS, + CategoriesType.STICKERS + }) @Retention(RetentionPolicy.SOURCE) public static @interface CategoriesType { int DEFAULT = 0; int STATUS = 1; int PROFILE_PHOTOS = 2; + int STICKERS = 3; } private float shownButtonsAtStart = 6.5f; @@ -98,7 +104,7 @@ public static void preload(int account, @CategoriesType int type) { if (emojiGroups == null || emojiGroups.groups == null) { return; } - for (TLRPC.TL_emojiGroup group : emojiGroups.groups) { + for (TLRPC.EmojiGroup group : emojiGroups.groups) { AnimatedEmojiDrawable.getDocumentFetcher(account).fetchDocument(group.icon_emoji_id, null); } }); @@ -150,6 +156,7 @@ public StickerCategoriesListView(Context context, EmojiCategory[] additionalCate for (int j = 0; j < emojiGroups.groups.size(); ++j) { categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j)); } + categories = preprocessCategories(categories); adapter.notifyDataSetChanged(); setCategoriesShownT(0); updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16); @@ -159,6 +166,10 @@ public StickerCategoriesListView(Context context, EmojiCategory[] additionalCate }); } + protected EmojiCategory[] preprocessCategories(StickerCategoriesListView.EmojiCategory[] categories) { + return categories; + } + public void setShownButtonsAtStart(float buttonsCount) { shownButtonsAtStart = buttonsCount; } @@ -832,6 +843,8 @@ public static class EmojiCategory { public boolean animated; public int iconResId; public String emojis; + public boolean premium; + public boolean greeting; public boolean remote; public long documentId; @@ -854,11 +867,17 @@ public static EmojiCategory withIcon(int iconResId, String emojis) { return category; } - public static EmojiCategory remote(TLRPC.TL_emojiGroup group) { + public static EmojiCategory remote(TLRPC.EmojiGroup group) { EmojiCategory category = new EmojiCategory(); category.remote = true; category.documentId = group.icon_emoji_id; - category.emojis = TextUtils.concat(group.emoticons.toArray(new String[0])).toString(); + if (group instanceof TLRPC.TL_emojiGroupPremium) { + category.emojis = "premium"; + category.premium = true; + } else { + category.emojis = TextUtils.concat(group.emoticons.toArray(new String[0])).toString(); + } + category.greeting = group instanceof TLRPC.TL_emojiGroupGreeting; category.title = group.title; return category; } @@ -875,6 +894,9 @@ protected void getRemote(int currentAccount, @CategoriesType Integer type, long } else if (type == CategoriesType.PROFILE_PHOTOS) { req = new TLRPC.TL_messages_getEmojiProfilePhotoGroups(); ((TLRPC.TL_messages_getEmojiProfilePhotoGroups) req).hash = (int) hash; + } else if (type == CategoriesType.STICKERS) { + req = new TLRPC.TL_messages_getEmojiStickerGroups(); + ((TLRPC.TL_messages_getEmojiStickerGroups) req).hash = (int) hash; } else { req = new TLRPC.TL_messages_getEmojiGroups(); ((TLRPC.TL_messages_getEmojiGroups) req).hash = (int) hash; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java new file mode 100644 index 0000000000..91edaded60 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetLinkIcon.java @@ -0,0 +1,137 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.openDocument; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LiteMode; +import org.telegram.messenger.MessageObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class StickerSetLinkIcon extends Drawable { + + private final int N, count; + private final AnimatedEmojiDrawable[] drawables; + public int alpha = 0xFF; + public final boolean out; + + public StickerSetLinkIcon(int currentAccount, boolean out, ArrayList documents, boolean text_color) { + this.out = out; + N = (int) Math.max(1, Math.sqrt(documents.size())); + count = Math.min(N * N, documents.size()); + drawables = new AnimatedEmojiDrawable[count]; + final boolean emoji = !documents.isEmpty() && MessageObject.isAnimatedEmoji(documents.get(0)); + final int cacheType = N < 2 ? AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES_LARGE : AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; + for (int i = 0; i < count; ++i) { + drawables[i] = AnimatedEmojiDrawable.make(currentAccount, cacheType, documents.get(i)); + } + } + + public boolean equals(ArrayList documents) { + if (documents == null) + return drawables.length == 0; + if (drawables.length != documents.size()) + return false; + for (int i = 0; i < drawables.length; ++i) { + TLRPC.Document d = drawables[i].getDocument(); + if ((d == null ? 0 : d.id) != documents.get(i).id) { + return false; + } + } + return true; + } + + public void attach(View parentView) { + for (int i = 0; i < count; ++i) { + drawables[i].addView(parentView); + } + } + + public void detach(View parentView) { + for (int i = 0; i < count; ++i) { + drawables[i].removeView(parentView); + } + } + + private final RectF rect = new RectF(); + @Override + public void draw(@NonNull Canvas canvas) { + if (alpha <= 0) return; + rect.set(getBounds()); + final float left = rect.centerX() - getIntrinsicWidth() / 2f; + final float top = rect.centerY() - getIntrinsicHeight() / 2f; + final float iw = getIntrinsicWidth() / N; + final float ih = getIntrinsicHeight() / N; + canvas.save(); + canvas.clipRect(left, top, left + getIntrinsicWidth(), top + getIntrinsicHeight()); + for (int y = 0; y < N; ++y) { + for (int x = 0; x < N; ++x) { + int i = x + y * N; + if (i < 0 || i >= drawables.length) continue; + if (drawables[i] == null) continue; + drawables[i].setBounds( + (int) (left + iw * x), + (int) (top + ih * y), + (int) (left + iw * (x + 1)), + (int) (top + ih * (y + 1)) + ); + drawables[i].setAlpha(alpha); + drawables[i].setColorFilter(out ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); + drawables[i].draw(canvas); + } + } + canvas.restore(); + } + + @Override + public void setAlpha(int alpha) { + this.alpha = alpha; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getIntrinsicHeight() { + return dp(48); + } + + @Override + public int getIntrinsicWidth() { + return dp(48); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + private boolean hit = false; + public void readyToDie() { + hit = true; + } + + public void keepAlive() { + hit = false; + } + + public boolean die() { + return hit; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index cc01c04f74..e135f16dad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -41,6 +41,7 @@ import android.transition.Transition; import android.transition.TransitionManager; import android.transition.TransitionValues; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; @@ -83,8 +84,10 @@ import org.telegram.messenger.R; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; @@ -108,8 +111,11 @@ import org.telegram.ui.PhotoViewer; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stories.DarkThemeResourceProvider; +import org.telegram.ui.Stories.recorder.StoryEntry; import java.io.File; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -125,6 +131,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { public final static boolean DISABLE_STICKER_EDITOR = false; + public final static int STICKERS_MAX_COUNT = 120; public interface StickersAlertDelegate { void onStickerSelected(TLRPC.Document sticker, String query, Object parent, MessageObject.SendAnimationData sendAnimationData, boolean clearsInputField, boolean notify, int scheduleDate); @@ -177,12 +184,13 @@ public interface StickersAlertCustomButtonDelegate { public boolean probablyEmojis; private boolean isEditModeEnabled; - private int menu_archive = 102; + private final int menu_archive = 102; private final int menuRefreshExternalCache = 100; private final int menuDeleteExternalCache = 101; private final int menu_copy_sticker_set = 103; + private final int menu_qrcode = 104; - private TLRPC.TL_messages_stickerSet stickerSet; + public TLRPC.TL_messages_stickerSet stickerSet; private TLRPC.Document selectedSticker; private SendMessagesHelper.ImportingSticker selectedStickerPath; private TLRPC.InputStickerSet inputStickerSet; @@ -247,16 +255,34 @@ public void remove(SendMessagesHelper.ImportingSticker importingSticker) { removeSticker(importingSticker); } + @Override + public boolean canDeleteSticker(TLRPC.Document document) { + return true; + } + @Override public void deleteSticker(TLRPC.Document document) { stickerSet.documents.remove(document); + boolean empty = stickerSet.documents.isEmpty(); + if (empty) + dismiss(); adapter.notifyDataSetChanged(); + AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER, resourcesProvider); + progressDialog.showDelayed(350); TLRPC.TL_stickers_removeStickerFromSet req = new TLRPC.TL_stickers_removeStickerFromSet(); req.sticker = MediaDataController.getInputStickerSetItem(document, "").document; - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); + MediaDataController.getInstance(UserConfig.selectedAccount).putStickerSet((TLRPC.TL_messages_stickerSet) response); + if (empty) { + MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 0, null, false, false); + } else { + stickerSet = (TLRPC.TL_messages_stickerSet) response; + loadStickerSet(); + updateFields(); + } } + progressDialog.dismiss(); })); } @@ -273,24 +299,103 @@ public void editSticker(TLRPC.Document document) { } else { chatActivity = null; } - final ArrayList photos = new ArrayList<>(); - File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); - if (file == null || !file.exists()) { - return; - } - AndroidUtilities.runOnUIThread(() -> { - final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); - photos.add(entry); - PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); - PhotoViewer.getInstance().openPhotoForSelect(photos, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { - @Override - public boolean allowCaption() { - return false; + if (MessageObject.isStaticStickerDocument(document)) { + final ArrayList photos = new ArrayList<>(); + File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); + if (file == null || !file.exists()) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + photos.add(entry); + PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); + PhotoViewer.getInstance().openPhotoForSelect(photos, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + }, chatActivity); + PhotoViewer.getInstance().enableStickerMode(document, false, null); + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); + }, 300); + } else { + AndroidUtilities.runOnUIThread(() -> { + File file = StoryEntry.makeCacheFile(currentAccount, "webp"); + int w = 512, h = 512; + int maxSide; + switch (SharedConfig.getDevicePerformanceClass()) { + case SharedConfig.PERFORMANCE_CLASS_LOW: + maxSide = 1280; + break; + default: + case SharedConfig.PERFORMANCE_CLASS_AVERAGE: + maxSide = 2560; + break; + case SharedConfig.PERFORMANCE_CLASS_HIGH: + maxSide = 3840; + break; + } + Size size = new Size(w, h); + size.width = maxSide; + size.height = (float) Math.floor(size.width * h / w); + if (size.height > maxSide) { + size.height = maxSide; + size.width = (float) Math.floor(size.height * w / h); + } + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + try { + b.compress(Bitmap.CompressFormat.WEBP, 100, new FileOutputStream(file)); + } catch (Throwable e) { + FileLog.e(e); + } + b.recycle(); + + ArrayList arrayList = new ArrayList<>(); + final MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, 0, 0, file.getAbsolutePath(), 0, false, 0, 0, 0); + arrayList.add(entry); + VideoEditedInfo.MediaEntity entity = new VideoEditedInfo.MediaEntity(); + entity.type = VideoEditedInfo.MediaEntity.TYPE_STICKER; + entity.parentObject = stickerSet; + entity.text = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true).getAbsolutePath(); + entity.x = .5f - (float) Math.min(w, h) / w / 2f; + entity.y = .5f - (float) Math.min(w, h) / h / 2f; + entity.width = (float) Math.min(w, h) / w; + entity.height = (float) Math.min(w, h) / h; + float side = (float) Math.floor(size.width * 0.5); + entity.viewWidth = (int) side; + entity.viewHeight = (int) side; + entity.scale = 2f; + entity.document = document; + if (MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) { + boolean isAnimatedSticker = MessageObject.isAnimatedStickerDocument(document, true); + entity.subType |= isAnimatedSticker ? 1 : 4; } - }, chatActivity); - PhotoViewer.getInstance().enableStickerMode(document); - ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); - }, 300); + entry.mediaEntities = new ArrayList<>(); + entry.mediaEntities.add(entity); + entry.averageDuration = 3000L; + if (MessageObject.isAnimatedStickerDocument(document, true)) { + File stickerFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); + if (stickerFile != null) { + try { + entry.averageDuration = (long) (RLottieDrawable.getDuration(stickerFile.getAbsolutePath(), null) * 1000L); + } catch (Exception e) { + FileLog.e(e); + } + } + } else if (MessageObject.isVideoStickerDocument(document)) { + entry.averageDuration = (long) (MessageObject.getDocumentDuration(document) * 1000L); + } + PhotoViewer.getInstance().setParentActivity(parentFragment.getParentActivity(), resourcesProvider); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, 0, PhotoViewer.SELECT_TYPE_STICKER, false, new PhotoViewer.EmptyPhotoViewerProvider() { + @Override + public boolean allowCaption() { + return false; + } + }, chatActivity); + PhotoViewer.getInstance().enableStickerMode(document, true, null); + ContentPreviewViewer.getInstance().setStickerSetForCustomSticker(stickerSet); + }, 300); + } } @Override @@ -505,7 +610,7 @@ public boolean isClearsInputField() { return clearsInputField; } - private void loadStickerSet() { + public void loadStickerSet() { if (inputStickerSet != null) { final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); if (stickerSet == null && inputStickerSet.short_name != null) { @@ -559,7 +664,12 @@ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues } optionsButton.setVisibility(View.VISIBLE); stickerSet = (TLRPC.TL_messages_stickerSet) response; - showEmoji = !stickerSet.set.masks; + mediaDataController.putStickerSet(stickerSet, false); + if (stickerSet != null && stickerSet.documents.isEmpty()) { + dismiss(); + return; + } + showEmoji = stickerSet != null && stickerSet.set != null && !stickerSet.set.masks; checkPremiumStickers(); mediaDataController.preloadStickerSetThumb(stickerSet); updateSendButton(); @@ -590,6 +700,18 @@ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues checkPremiumStickers(); } + public void updateStickerSet(TLRPC.TL_messages_stickerSet set) { + stickerSet = set; + if (adapter != null) { + updateSendButton(); + updateFields(); + adapter.notifyDataSetChanged(); + } + updateDescription(); + MediaDataController.getInstance(currentAccount).preloadStickerSetThumb(stickerSet); + checkPremiumStickers(); + } + private void checkPremiumStickers() { if (stickerSet != null) { stickerSet = MessagesController.getInstance(currentAccount).filterPremiumStickers(stickerSet); @@ -752,7 +874,7 @@ protected void onDraw(Canvas canvas) { int w = AndroidUtilities.dp(36); rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); Theme.dialogs_onlineCirclePaint.setColor(getThemedColor(Theme.key_sheet_scrollUp)); - Theme.dialogs_onlineCirclePaint.setAlpha((int) (255 * Math.max(0, Math.min(1f, (y - AndroidUtilities.statusBarHeight) / (float) AndroidUtilities.dp(16))))); + Theme.dialogs_onlineCirclePaint.setAlpha((int) (Theme.dialogs_onlineCirclePaint.getAlpha() * Math.max(0, Math.min(1f, (y - AndroidUtilities.statusBarHeight) / (float) AndroidUtilities.dp(16))))); canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); updateLightStatusBar(statusBarHeight > AndroidUtilities.statusBarHeight / 2); @@ -837,6 +959,9 @@ public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView. if (source.getItemViewType() != target.getItemViewType()) { return false; } + if (stickerSet == null) { + return false; + } int fromPosition = source.getAdapterPosition(); int toPosition = target.getAdapterPosition(); TLRPC.Document removed = stickerSet.documents.remove(fromPosition); @@ -846,6 +971,11 @@ public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView. return true; } + @Override + public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) { + + } + @Override public int getDragDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { if (viewHolder.getItemViewType() == GridAdapter.TYPE_ADD_STICKER) { @@ -861,11 +991,6 @@ public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionStat TLRPC.TL_stickers_changeStickerPosition req = new TLRPC.TL_stickers_changeStickerPosition(); req.position = movedPos; req.sticker = MediaDataController.getInputStickerSetItem(draggedDocument, "").document; - AndroidUtilities.runOnUIThread(() -> ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); - } - })), 200); movedPos = -1; draggedDocument = null; } else if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { @@ -1017,7 +1142,7 @@ public void requestLayout() { containerView.addView(optionsButton, LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 5, 5, 0)); optionsButton.addSubItem(1, R.drawable.msg_share, LocaleController.getString("StickersShare", R.string.StickersShare)); optionsButton.addSubItem(2, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink)); - optionsButton.addSubItem(3, R.drawable.msg_qrcode, LocaleController.getString("ShareQRCode", R.string.ShareQRCode)); + optionsButton.addSubItem(menu_qrcode, R.drawable.msg_qrcode, LocaleController.getString("ShareQRCode", R.string.ShareQRCode)); optionsButton.addSubItem(menu_archive, R.drawable.msg_archive, LocaleController.getString("Archive", R.string.Archive)); if (!NaConfig.INSTANCE.getExternalStickerCache().String().isBlank()) { optionsButton.addSubItem(menuRefreshExternalCache, R.drawable.menu_views_reposts, LocaleController.getString(R.string.ExternalStickerCacheRefresh)); @@ -1177,6 +1302,9 @@ private void checkOptions() { deleteItem.getRightIcon().setColorFilter(redColor); } } + if (optionsButton.getPopupLayout() != null) { + optionsButton.getPopupLayout().requestLayout(); + } } private void updateSendButton() { @@ -1292,6 +1420,36 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo FileLog.e(e); } } else if (id == 3) { + if (isEditModeEnabled) { + disableEditMode(); + } else { + enableEditMode(); + } + } else if (id == 4) { + StickersDialogs.showNameEditorDialog(stickerSet.set, resourcesProvider, getContext(), (text, whenDone) -> { + titleTextView.setText(text); + TLRPC.TL_stickers_renameStickerSet req = new TLRPC.TL_stickers_renameStickerSet(); + req.stickerset = MediaDataController.getInputStickerSet(stickerSet.set); + req.title = text.toString(); + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean success = false; + if (response instanceof TLRPC.TL_messages_stickerSet) { + TLRPC.TL_messages_stickerSet newset = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(UserConfig.selectedAccount).putStickerSet(newset); + if (!MediaDataController.getInstance(UserConfig.selectedAccount).isStickerPackInstalled(newset.set.id)) { + MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, newset, 2, null, false, false); + } + success = true; + } + whenDone.run(success); + })); + }); + } else if (id == 5) { + StickersDialogs.showDeleteForEveryOneDialog(stickerSet.set, resourcesProvider, getContext(), () -> { + dismiss(); + MediaDataController.getInstance(currentAccount).toggleStickerSet(getContext(), stickerSet, 1, parentFragment, false, false); + }); + } else if (id == menu_qrcode) { for (int i = 0, size = gridView.getChildCount(); i < size; i++) { final View child = gridView.getChildAt(i); if (child instanceof StickerEmojiCell) { @@ -1316,19 +1474,13 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo // Na: copy sticker set dismiss(); StickersDialogs.showShortNameEditorDialog(resourcesProvider, containerView.getContext(), short_name -> { - StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), pack_name -> { + StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), (pack_name, whenDone) -> { StickerSetHelper.INSTANCE.copyStickerSet(short_name, pack_name, stickerSet, UserConfig.selectedAccount); + if (whenDone != null) { + whenDone.run(true); + } }); }); - } else if (id == 4) { - StickersDialogs.showNameEditorDialog(stickerSet.set, resourcesProvider, getContext(), arg -> { - titleTextView.setText(arg); - }); - } else if (id == 5) { - StickersDialogs.showDeleteForEveryOneDialog(stickerSet.set, resourcesProvider, getContext(), () -> { - dismiss(); - MediaDataController.getInstance(currentAccount).toggleStickerSet(getContext(), stickerSet, 1, parentFragment, false, false); - }); } } @@ -1336,8 +1488,7 @@ private void updateFields() { if (titleTextView == null) { return; } - if (stickerSet != null && stickerSet.set != null) { - + if (stickerSet != null && stickerSet.set != null && stickerSet.documents != null && !stickerSet.documents.isEmpty()) { SpannableStringBuilder stringBuilder = null; CharSequence title = stickerSet.set.title; title = Emoji.replaceEmoji(title, titleTextView.getPaint().getFontMetricsInt(), dp(18), false); @@ -1773,22 +1924,25 @@ private void updateLayout() { setScrollOffsetY(gridView.getPaddingTop()); return; } - View child = gridView.getChildAt(0); - RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.findContainingViewHolder(child); - int top = child.getTop(); + int firstChildPosition = -1; + View firstChild = null; + for (int i = 0; i < gridView.getChildCount(); ++i) { + View child = gridView.getChildAt(i); + int position = gridView.getChildAdapterPosition(child); + if (firstChildPosition == -1 || firstChildPosition > position) { + firstChild = child; + firstChildPosition = position; + } + } int newOffset = 0; - if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) { - newOffset = top; + if (firstChild != null && firstChild.getTop() >= 0) { + newOffset = (int) firstChild.getTop(); runShadowAnimation(0, false); } else { runShadowAnimation(0, true); } -// if (layoutManager.findLastCompletelyVisibleItemPosition() == adapter.getItemCount() - 1) { -// runShadowAnimation(1, false); -// } else { runShadowAnimation(1, true); -// } if (scrollOffsetY != newOffset) { setScrollOffsetY(newOffset); @@ -1797,7 +1951,7 @@ private void updateLayout() { private void setScrollOffsetY(int newOffset) { scrollOffsetY = newOffset; - gridView.setTopGlowOffset(newOffset); +// gridView.setTopGlowOffset(newOffset); if (stickerSetCovereds == null) { titleTextView.setTranslationY(newOffset); if (descriptionTextView != null) { @@ -1987,7 +2141,7 @@ public void didReceivedNotification(int id, int account, Object... args) { newStickerSet = mediaDataController.getStickerSetById(inputStickerSet.id); } } - if (newStickerSet != stickerSet) { + if (newStickerSet != null && newStickerSet != stickerSet) { stickerSet = newStickerSet; loadStickerSet(); } @@ -2277,7 +2431,7 @@ public void notifyDataSetChanged() { totalItems = importingStickersPaths.size(); } else { totalItems = stickerSet != null ? stickerSet.documents.size() : 0; - if (stickerSet != null && stickerSet.set.creator && !DISABLE_STICKER_EDITOR && !stickerSet.set.masks && !stickerSet.set.emojis) { + if (stickerSet != null && stickerSet.set.creator && stickerSet.documents.size() < STICKERS_MAX_COUNT && !DISABLE_STICKER_EDITOR && !stickerSet.set.masks && !stickerSet.set.emojis) { totalItems++; } } @@ -2324,7 +2478,7 @@ public void enableEditMode() { } }); optionsButton.postDelayed(() -> adapter.notifyDataSetChanged(), 200); - optionsButton.animate().alpha(0f).start(); +// optionsButton.animate().alpha(0f).start(); pickerBottomLayout.setText(LocaleController.getString(R.string.Done), true); } @@ -2342,7 +2496,7 @@ public void disableEditMode() { } }); optionsButton.postDelayed(() -> adapter.notifyDataSetChanged(), 200); - optionsButton.animate().alpha(1f).start(); +// optionsButton.animate().alpha(1f).start(); pickerBottomLayout.setText(LocaleController.getString(R.string.EditStickers), true); } @@ -2416,6 +2570,7 @@ public float getTranslateYValueForPos(int pos) { } public void startShake() { + stopShake(false); init(); for (int i = 0; i < MAX_SHAKERS; i++) { final int pos = i; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java index c16aff11f9..4f8c543f91 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersDialogs.java @@ -17,6 +17,8 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BotWebViewVibrationEffect; +import org.telegram.messenger.FileRefController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; @@ -33,6 +35,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.ContentPreviewViewer; +import org.telegram.ui.Stories.DarkThemeResourceProvider; import org.telegram.ui.Stories.recorder.EmojiBottomSheet; import java.util.ArrayList; @@ -42,7 +45,7 @@ private static int getThemedColor(int key, Theme.ResourcesProvider resourcesProv return Theme.getColor(key, resourcesProvider); } - public static void showNameEditorDialog(TLRPC.StickerSet set, Theme.ResourcesProvider resourcesProvider, Context context, Utilities.Callback callback) { + public static void showNameEditorDialog(TLRPC.StickerSet set, Theme.ResourcesProvider resourcesProvider, Context context, Utilities.Callback2> callback) { AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); boolean editMode = set != null; builder.setTitle(LocaleController.getString(editMode ? R.string.EditStickerPack : R.string.NewStickerPack)); @@ -101,6 +104,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { @Override public void afterTextChanged(Editable s) { checkTextView.setNumber(maxLength - Character.codePointCount(s, 0, s.length()), true); + editText.setErrorText(null); } }); if (editMode) { @@ -111,20 +115,27 @@ public void afterTextChanged(Editable s) { builder.setCustomViewOffset(4); builder.setPositiveButton(LocaleController.getString(editMode ? R.string.Done : R.string.Create), (dialog, i) -> { CharSequence text = editText.getText().toString().trim(); - if (!TextUtils.isEmpty(text)) { + if (TextUtils.isEmpty(text) || TextUtils.isEmpty(AndroidUtilities.translitSafe(text.toString()))) { + editText.setErrorText("."); + AndroidUtilities.shakeViewSpring(editText, -6); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.showKeyboard(editText); + } else { AndroidUtilities.hideKeyboard(editText); - dialog.dismiss(); - callback.run(text); - if (editMode) { - TLRPC.TL_stickers_renameStickerSet req = new TLRPC.TL_stickers_renameStickerSet(); - req.stickerset = MediaDataController.getInputStickerSet(set); - req.title = text.toString(); - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 2, null, false, false); - } - })); - } + if (callback == null) return; + AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER, editMode ? null : new DarkThemeResourceProvider()); + progressDialog.showDelayed(250); + callback.run(text, success -> { + progressDialog.dismiss(); + if (success) { + dialog.dismiss(); + } else { + editText.setErrorText("."); + AndroidUtilities.shakeViewSpring(editText, -6); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + AndroidUtilities.showKeyboard(editText); + } + }); } }); builder.setNegativeButton(LocaleController.getString(R.string.Cancel), (dialog, which) -> { @@ -250,23 +261,52 @@ public static void showDeleteForEveryOneDialog(TLRPC.StickerSet set, Theme.Resou } private static void openStickerPickerDialog(TLRPC.TL_messages_stickerSet stickerSet, BaseFragment fragment, Theme.ResourcesProvider resourcesProvider) { - EmojiBottomSheet sheet = new EmojiBottomSheet(fragment.getContext(), true, resourcesProvider); + final int currentAccount = UserConfig.selectedAccount; + Context context = fragment.getContext(); + EmojiBottomSheet sheet = new EmojiBottomSheet(context, true, resourcesProvider, false); sheet.whenDocumentSelected((parentObject, document, a) -> { - String emoji = MessageObject.findAnimatedEmojiEmoticon(document, "\uD83D\uDE00", UserConfig.selectedAccount); +// if (stickerSet != null) { +// boolean found = false; +// for (int i = 0; i < stickerSet.documents.size(); ++i) { +// if (stickerSet.documents.get(i).id == document.id) { +// found = true; +// break; +// } +// } +// if (found) { +// BulletinFactory.of(sheet.getContainer(), resourcesProvider).createSimpleBulletin(R.raw.error, LocaleController.formatString(R.string.StickersStickerAlreadyThere, stickerSet.set.title)).show(true); +// return false; +// } +// } + String emoji = MessageObject.findAnimatedEmojiEmoticon(document, "\uD83D\uDE00", currentAccount); if (TextUtils.isEmpty(emoji)) { emoji = "\uD83D\uDE00"; } + AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER); TLRPC.TL_stickers_addStickerToSet req = new TLRPC.TL_stickers_addStickerToSet(); req.stickerset = MediaDataController.getInputStickerSet(stickerSet.set); req.sticker = MediaDataController.getInputStickerSetItem(document, emoji); ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + progressDialog.dismiss(); if (response instanceof TLRPC.TL_messages_stickerSet) { - MediaDataController.getInstance(UserConfig.selectedAccount).toggleStickerSet(null, response, 1, null, false, false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, document), 250); + TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response; + MediaDataController.getInstance(currentAccount).putStickerSet(set); + if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(set.set.id)) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(null, response, 2, null, false, false); + } + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, false, response, document, null, false), 250); } else if (error != null) { - BulletinFactory.showError(error); + if (FileRefController.isFileRefError(error.text)) { + FileRefController.getInstance(currentAccount).requestReference(parentObject, req); + } else { + BulletinFactory.showError(error); + } } })); + try { + progressDialog.showDelayed(350); + } catch (Exception e) {} + return true; }); if (fragment.visibleDialog != null) { sheet.show(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java index 98cf9c767f..e6a1d8d1b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java @@ -50,9 +50,12 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + public final static int DIRECTION_TO_BOTTOM = 0; + public final static int DIRECTION_TO_TOP = 1; + private final int currentAccount; private final Theme.ResourcesProvider resourcesProvider; - private final ChatActivityEnterView enterView; + private AnchorViewDelegate enterView; @Nullable private FrameLayout containerView; @@ -60,6 +63,18 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. private RecyclerListView listView; @Nullable private Adapter adapter; + private int direction = DIRECTION_TO_BOTTOM; + private int horizontalPadding = AndroidUtilities.dp(10); + + public interface AnchorViewDelegate { + BaseFragment getParentFragment(); + void setFieldText(CharSequence text); + void addTextChangedListener(TextWatcher watcher); + int getVisibility(); + EditTextBoldCursor getEditField(); + CharSequence getFieldText(); + Editable getEditText(); + } private ContentPreviewViewer.ContentPreviewViewerDelegate previewDelegate; private ContentPreviewViewer.ContentPreviewViewerDelegate getPreviewDelegate() { @@ -75,8 +90,12 @@ public boolean needSend(int contentType) { if (enterView == null) { return false; } - ChatActivity fragment = enterView.getParentFragment(); - return fragment != null && fragment.canSendMessage() && (UserConfig.getInstance(UserConfig.selectedAccount).isPremium() || fragment.getCurrentUser() != null && UserObject.isUserSelf(fragment.getCurrentUser())); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + return chatActivity.canSendMessage() && (UserConfig.getInstance(UserConfig.selectedAccount).isPremium() || chatActivity.getCurrentUser() != null && UserObject.isUserSelf(chatActivity.getCurrentUser())); + } + return false; } @Override @@ -84,13 +103,19 @@ public void sendEmoji(TLRPC.Document emoji) { if (enterView == null) { return; } - ChatActivity fragment = enterView.getParentFragment(); - fragment.sendAnimatedEmoji(emoji, true, 0); - enterView.setFieldText(""); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + chatActivity.sendAnimatedEmoji(emoji, true, 0); + enterView.setFieldText(""); + } } @Override public boolean needCopy(TLRPC.Document document) { + if (isCopyForbidden) { + return false; + } return UserConfig.getInstance(UserConfig.selectedAccount).isPremium(); } @@ -105,6 +130,9 @@ public void copyEmoji(TLRPC.Document document) { @Override public Boolean canSetAsStatus(TLRPC.Document document) { + if (isSetAsStatusForbidden) { + return null; + } if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) { return null; } @@ -160,8 +188,13 @@ public boolean isInScheduleMode() { if (enterView == null) { return false; } - ChatActivity fragment = enterView.getParentFragment(); - return fragment.isInScheduleMode(); + BaseFragment fragment = enterView.getParentFragment(); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + return chatActivity.isInScheduleMode(); + } else { + return false; + } } @Override @@ -180,8 +213,10 @@ public long getDialogId() { @Nullable private ArrayList keywordResults; private boolean clear; + private boolean isCopyForbidden; + private boolean isSetAsStatusForbidden; - public SuggestEmojiView(Context context, int currentAccount, ChatActivityEnterView enterView, Theme.ResourcesProvider resourcesProvider) { + public SuggestEmojiView(Context context, int currentAccount, AnchorViewDelegate enterView, Theme.ResourcesProvider resourcesProvider) { super(context); this.currentAccount = currentAccount; this.enterView = enterView; @@ -190,6 +225,14 @@ public SuggestEmojiView(Context context, int currentAccount, ChatActivityEnterVi postDelayed(() -> MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_EMOJIPACKS), 260); } + public void forbidCopy() { + isCopyForbidden = true; + } + + public void forbidSetAsStatus() { + isSetAsStatusForbidden = true; + } + private void createListView() { if (listView != null) { return; @@ -208,7 +251,7 @@ protected void dispatchDraw(Canvas canvas) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - this.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(8), AndroidUtilities.dp(10), AndroidUtilities.dp(6.66f)); + this.setPadding(horizontalPadding, direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(8) : AndroidUtilities.dp(6.66f), horizontalPadding, direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(6.66f) : AndroidUtilities.dp(8)); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @@ -279,18 +322,36 @@ public boolean onInterceptTouchEvent(MotionEvent event) { containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44 + 8)); addView(containerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 8 + 44 + 8 + 6.66f, Gravity.BOTTOM)); - enterView.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} - @Override - public void afterTextChanged(Editable editable) { - if (enterView.getVisibility() == View.VISIBLE) { - fireUpdate(); + if (enterView != null) { + enterView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } - } - }); + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + if (enterView != null && enterView.getVisibility() == View.VISIBLE) { + fireUpdate(); + } + } + }); + } + } + + public void setDelegate(AnchorViewDelegate delegate) { + this.enterView = delegate; + } + + public void setHorizontalPadding(int padding) { + this.horizontalPadding = padding; + } + + public AnchorViewDelegate getDelegate() { + return enterView; } public void onTextSelectionChanged(int start, int end) { @@ -301,6 +362,17 @@ public boolean isShown() { return show; } + public int getDirection() { + return direction; + } + + public void setDirection(int direction) { + if (this.direction != direction) { + this.direction = direction; + requestLayout(); + } + } + public void updateColors() { if (backgroundPaint != null) { backgroundPaint.setColor(Theme.getColor(Theme.key_chat_stickersHintPanel, resourcesProvider)); @@ -671,7 +743,11 @@ private void drawContainerBegin(Canvas canvas) { float center = listViewCenterAnimated.set((listViewLeft + listViewRight) / 2f, force); if (enterView != null && enterView.getEditField() != null) { - containerView.setTranslationY(-enterView.getEditField().getHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(5)); + if (direction == DIRECTION_TO_BOTTOM) { + containerView.setTranslationY(-enterView.getEditField().getHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(5)); + } else if (direction == DIRECTION_TO_TOP) { + containerView.setTranslationY(-getMeasuredHeight() - enterView.getEditField().getScrollY() + lastSpanY + AndroidUtilities.dp(20) + containerView.getHeight()); + } } int listViewPaddingLeft = (int) Math.max(this.arrowX - Math.max(width / 4f, Math.min(width / 2f, AndroidUtilities.dp(66))) - listView.getLeft(), 0); if (listView.getPaddingLeft() != listViewPaddingLeft) { @@ -683,28 +759,45 @@ private void drawContainerBegin(Canvas canvas) { listView.setTranslationX(listViewPaddingLeftI - listViewPaddingLeft); float left = center - width / 2f + listView.getPaddingLeft() + listView.getTranslationX(); - float top = listView.getTop() + listView.getTranslationY() + listView.getPaddingTop(); + float top = listView.getTop() + listView.getTranslationY() + listView.getPaddingTop() + (direction == DIRECTION_TO_BOTTOM ? 0: AndroidUtilities.dp(6.66f)); float right = Math.min(center + width / 2f + listView.getPaddingLeft() + listView.getTranslationX(), getWidth() - containerView.getPaddingRight()); - float bottom = listView.getBottom() + listView.getTranslationY() - AndroidUtilities.dp(6.66f); + float bottom = listView.getBottom() + listView.getTranslationY() - (direction == DIRECTION_TO_BOTTOM ? AndroidUtilities.dp(6.66f) : 0); float R = Math.min(AndroidUtilities.dp(9), width / 2f), D = R * 2; - AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); - path.arcTo(AndroidUtilities.rectTmp, 90, 90); + if (direction == DIRECTION_TO_BOTTOM) { + AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); + path.arcTo(AndroidUtilities.rectTmp, 90, 90); + + AndroidUtilities.rectTmp.set(left, top, left + D, top + D); + path.arcTo(AndroidUtilities.rectTmp, -180, 90); - AndroidUtilities.rectTmp.set(left, top, left + D, top + D); - path.arcTo(AndroidUtilities.rectTmp, -180, 90); + AndroidUtilities.rectTmp.set(right - D, top, right, top + D); + path.arcTo(AndroidUtilities.rectTmp, -90, 90); - AndroidUtilities.rectTmp.set(right - D, top, right, top + D); - path.arcTo(AndroidUtilities.rectTmp, -90, 90); + AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); + path.arcTo(AndroidUtilities.rectTmp, 0, 90); - AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); - path.arcTo(AndroidUtilities.rectTmp, 0, 90); + path.lineTo(arrowX + AndroidUtilities.dp(8.66f), bottom); + path.lineTo(arrowX, bottom + AndroidUtilities.dp(6.66f)); + path.lineTo(arrowX - AndroidUtilities.dp(8.66f), bottom); + } else if (direction == DIRECTION_TO_TOP) { + AndroidUtilities.rectTmp.set(right - D, top, right, top + D); + path.arcTo(AndroidUtilities.rectTmp, -90, 90); - path.lineTo(arrowX + AndroidUtilities.dp(8.66f), bottom); - path.lineTo(arrowX, bottom + AndroidUtilities.dp(6.66f)); - path.lineTo(arrowX - AndroidUtilities.dp(8.66f), bottom); + AndroidUtilities.rectTmp.set(right - D, bottom - D, right, bottom); + path.arcTo(AndroidUtilities.rectTmp, 0, 90); + AndroidUtilities.rectTmp.set(left, bottom - D, left + D, bottom); + path.arcTo(AndroidUtilities.rectTmp, 90, 90); + + AndroidUtilities.rectTmp.set(left, top, left + D, top + D); + path.arcTo(AndroidUtilities.rectTmp, -180, 90); + + path.lineTo(arrowX - AndroidUtilities.dp(8.66f), top); + path.lineTo(arrowX, top - AndroidUtilities.dp(6.66f)); + path.lineTo(arrowX + AndroidUtilities.dp(8.66f), top); + } path.close(); if (backgroundPaint == null) { @@ -716,7 +809,7 @@ private void drawContainerBegin(Canvas canvas) { if (showT1 < 1) { circlePath.rewind(); - float cx = arrowX, cy = bottom + AndroidUtilities.dp(6.66f); + float cx = arrowX, cy = (direction == DIRECTION_TO_BOTTOM) ? bottom + AndroidUtilities.dp(6.66f) : top - AndroidUtilities.dp(6.66f); float toRadius = (float) Math.sqrt(Math.max( Math.max( Math.pow(cx - left, 2) + Math.pow(cy - top, 2), @@ -828,17 +921,22 @@ public void didReceivedNotification(int id, int account, Object... args) { } } + protected int emojiCacheType() { + return AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD; + } + public void invalidateContent() { if (containerView != null) { containerView.invalidate(); } } - public static class EmojiImageView extends View { + public class EmojiImageView extends View { private String emoji; public Drawable drawable; private boolean attached; + private int direction = DIRECTION_TO_BOTTOM; private AnimatedFloat pressed = new AnimatedFloat(this, 350, new OvershootInterpolator(5.0f)); @@ -849,20 +947,20 @@ public EmojiImageView(Context context) { private final int paddingDp = 3; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setPadding(AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + 6.66f)); + setPadding(AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + (direction == DIRECTION_TO_BOTTOM ? 0 : 6.66f)), AndroidUtilities.dp(paddingDp), AndroidUtilities.dp(paddingDp + (direction == DIRECTION_TO_BOTTOM ? 6.66f : 0))); super.onMeasure( MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(44), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(44 + 8), MeasureSpec.EXACTLY) ); } - private void setEmoji(String emoji) { + private void setEmoji(String emoji, int direction) { this.emoji = emoji; if (emoji != null && emoji.startsWith("animated_")) { try { long documentId = Long.parseLong(emoji.substring(9)); if (!(drawable instanceof AnimatedEmojiDrawable) || ((AnimatedEmojiDrawable) drawable).getDocumentId() != documentId) { - setImageDrawable(AnimatedEmojiDrawable.make(UserConfig.selectedAccount, AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, documentId)); + setImageDrawable(AnimatedEmojiDrawable.make(UserConfig.selectedAccount, emojiCacheType(), documentId)); } } catch (Exception ignore) { setImageDrawable(null); @@ -870,6 +968,10 @@ private void setEmoji(String emoji) { } else { setImageDrawable(Emoji.getEmojiBigDrawable(emoji)); } + if (this.direction != direction) { + this.direction = direction; + requestLayout(); + } } public void setImageDrawable(@Nullable Drawable drawable) { @@ -882,6 +984,11 @@ public void setImageDrawable(@Nullable Drawable drawable) { } } + public void setDirection(int direction) { + this.direction = direction; + invalidate(); + } + @Override public void setPressed(boolean pressed) { super.setPressed(pressed); @@ -929,7 +1036,7 @@ public void attach() { } } - private static class Adapter extends RecyclerListView.SelectionAdapter { + private class Adapter extends RecyclerListView.SelectionAdapter { SuggestEmojiView suggestEmojiView; public Adapter(SuggestEmojiView suggestEmojiView) { @@ -954,7 +1061,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - ((EmojiImageView) holder.itemView).setEmoji(suggestEmojiView.keywordResults == null ? null : suggestEmojiView.keywordResults.get(position).emoji); + ((EmojiImageView) holder.itemView).setEmoji(suggestEmojiView.keywordResults == null ? null : suggestEmojiView.keywordResults.get(position).emoji, suggestEmojiView.getDirection()); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index dcd66375e4..cf065d0a94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -473,7 +473,7 @@ protected void onDraw(Canvas canvas) { colorProgress = progress; } - color1 = processColor(Theme.getColor(thumbColorKey, resourcesProvider)); + color1 = Theme.getColor(thumbColorKey, resourcesProvider); color2 = processColor(Theme.getColor(thumbCheckedColorKey, resourcesProvider)); r1 = Color.red(color1); r2 = Color.red(color2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java index 40f9827ec4..c1080e5866 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThanosEffect.java @@ -28,6 +28,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.EmuDetector; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessageObject; @@ -124,6 +125,7 @@ public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width drawThread = null; } drawThread = new DrawingThread(surface, ThanosEffect.this::invalidate, ThanosEffect.this::destroy, width, height); + drawThread.isEmulator = EmuDetector.with(getContext()).detect(); if (!toSet.isEmpty()) { for (int i = 0; i < toSet.size(); ++i) { ToSet toSetObj = toSet.get(i); @@ -258,6 +260,7 @@ public void animate(Matrix matrix, Bitmap bitmap, Runnable whenStarted, Runnable private static class DrawingThread extends DispatchQueue { + private boolean isEmulator; private volatile boolean alive = true; private final SurfaceTexture surfaceTexture; private final Runnable invalidate; @@ -435,6 +438,8 @@ private void killInternal() { private int densityHandle; private int longevityHandle; private int offsetHandle; + private int scaleHandle; + private int uvOffsetHandle; public volatile boolean running; private final ArrayList pendingAnimations = new ArrayList<>(); @@ -547,6 +552,8 @@ private void init() { densityHandle = GLES31.glGetUniformLocation(drawProgram, "dp"); longevityHandle = GLES31.glGetUniformLocation(drawProgram, "longevity"); offsetHandle = GLES31.glGetUniformLocation(drawProgram, "offset"); + scaleHandle = GLES31.glGetUniformLocation(drawProgram, "scale"); + uvOffsetHandle = GLES31.glGetUniformLocation(drawProgram, "uvOffset"); GLES31.glViewport(0, 0, width, height); GLES31.glEnable(GLES31.GL_BLEND); @@ -737,6 +744,12 @@ private void addAnimationInternal(Animation animation) { animation.bitmap.recycle(); animation.bitmap = null; + if (animation.isPhotoEditor) { + for (Animation anim : pendingAnimations) { + anim.done(true); + } + pendingAnimations.clear(); + } pendingAnimations.add(animation); running = true; @@ -776,8 +789,10 @@ private class Animation { public final int[] buffer = new int[2]; private Bitmap bitmap; + private boolean isPhotoEditor; public Animation(Matrix matrix, Bitmap bitmap, Runnable whenStarted, Runnable whenDone) { + isPhotoEditor = true; float[] v = new float[] { 0, 0, 0, 1, 1, 0, 1, 1 }; matrix.mapPoints(v); left = v[0]; @@ -789,6 +804,8 @@ public Animation(Matrix matrix, Bitmap bitmap, Runnable whenStarted, Runnable wh retrieveMatrixValues(); startCallback = whenStarted; doneCallback = whenDone; + longevity = 4f; + time = -.1f; // longevity = 1.5f * Utilities.clamp(viewWidth / (float) AndroidUtilities.displaySize.x, .6f, 0.2f); this.bitmap = bitmap; } @@ -1046,7 +1063,7 @@ private void drawChildElement(View chatListView, ChatActivity chatActivity, Canv } public void calcParticlesGrid(float part) { - final int maxParticlesCount; + int maxParticlesCount; switch (SharedConfig.getDevicePerformanceClass()) { case SharedConfig.PERFORMANCE_CLASS_HIGH: maxParticlesCount = 120_000; @@ -1059,6 +1076,12 @@ public void calcParticlesGrid(float part) { maxParticlesCount = 30_000; break; } + if (isEmulator) { + maxParticlesCount = 120_000; + } + if (isPhotoEditor) { + maxParticlesCount /= 2; + } float p = Math.max(AndroidUtilities.dpf2(.4f), 1); particlesCount = Utilities.clamp((int) (viewWidth * viewHeight / (p * p)), (int) (maxParticlesCount * part), 10); @@ -1174,6 +1197,8 @@ public void draw() { GLES31.glUniform1f(particlesCountHandle, particlesCount); GLES31.glUniform3f(gridSizeHandle, gridWidth, gridHeight, gridSize); GLES31.glUniform2f(offsetHandle, offsetLeft, offsetTop); + GLES31.glUniform1f(scaleHandle, isPhotoEditor ? .8f : 1); + GLES31.glUniform1f(uvOffsetHandle, isPhotoEditor ? 1f : .6f); GLES31.glUniform2f(rectSizeHandle, viewWidth, viewHeight); GLES31.glUniform1f(seedHandle, seed); @@ -1216,7 +1241,7 @@ public void draw() { } public boolean isDead() { - return time > longevity + .9f; + return time > longevity + (isPhotoEditor ? 2f : .9f); } public void done(boolean runCallback) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java index 980b286fe6..e50dc3cb72 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UItem.java @@ -4,7 +4,9 @@ import android.text.TextUtils; import android.view.View; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stats; import org.telegram.ui.Business.BusinessLinksActivity; @@ -21,13 +23,15 @@ public class UItem extends AdapterWithDiffUtils.Item { public View view; public int id; public boolean checked; + public boolean collapsed; public boolean enabled = true; + public int pad; public boolean hideDivider; public int iconResId; - public int backgroundKey; public CharSequence text, subtext, textValue; + public CharSequence animatedText; public String[] texts; - public boolean accent, red, transparent; + public boolean accent, red, transparent, locked; public boolean include; public long dialogId; @@ -37,10 +41,12 @@ public class UItem extends AdapterWithDiffUtils.Item { public int intValue; public Utilities.Callback intCallback; - public Runnable clickCallback; + public View.OnClickListener clickCallback; public Object object; + public boolean withUsername = true; + public UItem(int viewType, boolean selectable) { super(viewType, selectable); @@ -58,6 +64,13 @@ public static UItem asHeader(CharSequence text) { return i; } + public static UItem asAnimatedHeader(int id, CharSequence text) { + UItem i = new UItem(UniversalAdapter.VIEW_TYPE_ANIMATED_HEADER, false); + i.id = id; + i.animatedText = text; + return i; + } + public static UItem asLargeHeader(CharSequence text) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_LARGE_HEADER, false); i.text = text; @@ -117,13 +130,20 @@ public static UItem asButton(int id, int iconResId, CharSequence text, CharSeque return i; } - public static UItem asButton(int id, CharSequence text, TLRPC.Document sticker) { + public static UItem asStickerButton(int id, CharSequence text, TLRPC.Document sticker) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_TEXT, false); i.id = id; i.text = text; i.object = sticker; return i; } + public static UItem asStickerButton(int id, CharSequence text, String stickerPath) { + UItem i = new UItem(UniversalAdapter.VIEW_TYPE_TEXT, false); + i.id = id; + i.text = text; + i.object = stickerPath; + return i; + } public static UItem asRippleCheck(int id, CharSequence text) { UItem i = new UItem(UniversalAdapter.VIEW_TYPE_CHECKRIPPLE, false); @@ -281,11 +301,106 @@ public static UItem asSpace(int height) { return item; } - public UItem setCloseIcon(Runnable onCloseClick) { + public static UItem asRoundCheckbox(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX, false); + item.id = id; + item.text = text; + return item; + } + + public static UItem asRoundGroupCheckbox(int id, CharSequence text, CharSequence subtext) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_ROUND_GROUP_CHECKBOX, false); + item.id = id; + item.text = text; + item.animatedText = subtext; + return item; + } + + public static UItem asUserGroupCheckbox(int id, CharSequence text, CharSequence subtext) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX, false); + item.id = id; + item.text = text; + item.animatedText = subtext; + return item; + } + + public static UItem asUserCheckbox(int id, TLObject user) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_USER_CHECKBOX, false); + item.id = id; + item.object = user; + return item; + } + + public static UItem asShadowCollapseButton(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SHADOW_COLLAPSE_BUTTON, false); + item.id = id; + item.animatedText = text; + return item; + } + + public static UItem asSwitch(int id, CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SWITCH, false); + item.id = id; + item.text = text; + return item; + } + + public static UItem asExpandableSwitch(int id, CharSequence text, CharSequence subText) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_EXPANDABLE_SWITCH, false); + item.id = id; + item.text = text; + item.animatedText = subText; + return item; + } + + public static UItem asGraySection(CharSequence text) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_GRAY_SECTION, false); + item.text = text; + return item; + } + + public static UItem asGraySection(CharSequence text, CharSequence button, View.OnClickListener onClickListener) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_GRAY_SECTION, false); + item.text = text; + item.subtext = button; + item.clickCallback = onClickListener; + return item; + } + + public static UItem asProfileCell(TLObject obj) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_PROFILE_CELL, false); + item.object = obj; + return item; + } + + public static UItem asSearchMessage(MessageObject messageObject) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_SEARCH_MESSAGE, false); + item.object = messageObject; + return item; + } + + public static UItem asFlicker(int type) { + UItem item = new UItem(UniversalAdapter.VIEW_TYPE_FLICKER, false); + item.intValue = type; + return item; + } + + + public UItem withUsername(boolean value) { + withUsername = value; + return this; + } + + public UItem setCloseIcon(View.OnClickListener onCloseClick) { clickCallback = onCloseClick; return this; } + public UItem setClickCallback(View.OnClickListener clickCallback) { + this.clickCallback = clickCallback; + return this; + } + public UItem setChecked(boolean checked) { this.checked = checked; if (viewType == UniversalAdapter.VIEW_TYPE_FILTER_CHAT) { @@ -294,11 +409,36 @@ public UItem setChecked(boolean checked) { return this; } + public UItem setCollapsed(boolean collapsed) { + this.collapsed = collapsed; + return this; + } + + public UItem setPad(int pad) { + this.pad = pad; + return this; + } + + public UItem pad() { + this.pad = 1; + return this; + } + public UItem setEnabled(boolean enabled) { this.enabled = enabled; return this; } + public UItem setLocked(boolean locked) { + this.locked = locked; + return this; + } + + public UItem locked() { + this.locked = true; + return this; + } + public UItem red() { this.red = true; return this; @@ -314,15 +454,24 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UItem item = (UItem) o; + if (viewType != item.viewType) + return false; + if (viewType == UniversalAdapter.VIEW_TYPE_USER_GROUP_CHECKBOX || + viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX) { + return id == item.id; + } + if (viewType == UniversalAdapter.VIEW_TYPE_GRAY_SECTION) { + return TextUtils.equals(text, item.text); + } return ( - viewType == item.viewType && id == item.id && + pad == item.pad && dialogId == item.dialogId && iconResId == item.iconResId && - backgroundKey == item.backgroundKey && hideDivider == item.hideDivider && transparent == item.transparent && red == item.red && + locked == item.locked && accent == item.accent && TextUtils.equals(text, item.text) && TextUtils.equals(subtext, item.subtext) && @@ -332,4 +481,21 @@ public boolean equals(Object o) { Objects.equals(object, item.object) ); } + + @Override + protected boolean contentsEquals(AdapterWithDiffUtils.Item o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + UItem item = (UItem) o; + if (viewType != item.viewType) + return false; + if (viewType == UniversalAdapter.VIEW_TYPE_GRAY_SECTION) { + return TextUtils.equals(text, item.text) && TextUtils.equals(subtext, item.subtext); + } + if (viewType == UniversalAdapter.VIEW_TYPE_ROUND_CHECKBOX || + viewType == UniversalAdapter.VIEW_TYPE_USER_CHECKBOX) { + return id == item.id && TextUtils.equals(text, item.text) && checked == item.checked; + } + return super.contentsEquals(o); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java index 935ef74770..14c75b622e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalAdapter.java @@ -4,7 +4,12 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.text.SpannableStringBuilder; import android.text.TextUtils; +import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -14,20 +19,32 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_stats; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Business.BusinessLinksActivity; import org.telegram.ui.Business.QuickRepliesActivity; import org.telegram.ui.Business.QuickRepliesController; +import org.telegram.ui.Cells.CheckBoxCell; +import org.telegram.ui.Cells.CollapseTextCell; +import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.DialogRadioCell; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; +import org.telegram.ui.Cells.ProfileChannelCell; +import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.SlideIntChooseView; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; +import org.telegram.ui.Cells.TextCheckCell2; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextRightIconCell; import org.telegram.ui.Cells.UserCell; @@ -82,11 +99,25 @@ public class UniversalAdapter extends AdapterWithDiffUtils { public static final int VIEW_TYPE_RIGHT_ICON_TEXT = 30; - private final RecyclerListView listView; + public static final int VIEW_TYPE_GRAY_SECTION = 31; + public static final int VIEW_TYPE_PROFILE_CELL = 32; + public static final int VIEW_TYPE_SEARCH_MESSAGE = 33; + public static final int VIEW_TYPE_FLICKER = 34; + public static final int VIEW_TYPE_ROUND_CHECKBOX = 35; + public static final int VIEW_TYPE_USER_GROUP_CHECKBOX = 36; + public static final int VIEW_TYPE_USER_CHECKBOX = 37; + public static final int VIEW_TYPE_SHADOW_COLLAPSE_BUTTON = 38; + public static final int VIEW_TYPE_SWITCH = 39; + public static final int VIEW_TYPE_EXPANDABLE_SWITCH = 40; + public static final int VIEW_TYPE_ROUND_GROUP_CHECKBOX = 41; + public static final int VIEW_TYPE_ANIMATED_HEADER = 42; + + protected final RecyclerListView listView; private final Context context; private final int currentAccount; private final int classGuid; - private final Utilities.Callback2, UniversalAdapter> fillItems; + private final boolean dialog; + protected Utilities.Callback2, UniversalAdapter> fillItems; private final Theme.ResourcesProvider resourcesProvider; private final ArrayList oldItems = new ArrayList<>(); @@ -101,12 +132,25 @@ public UniversalAdapter( int classGuid, Utilities.Callback2, UniversalAdapter> fillItems, Theme.ResourcesProvider resourcesProvider + ) { + this(listView, context, currentAccount, classGuid, false, fillItems, resourcesProvider); + } + + public UniversalAdapter( + RecyclerListView listView, + Context context, + int currentAccount, + int classGuid, + boolean dialog, + Utilities.Callback2, UniversalAdapter> fillItems, + Theme.ResourcesProvider resourcesProvider ) { super(); this.listView = listView; this.context = context; this.currentAccount = currentAccount; this.classGuid = classGuid; + this.dialog = dialog; this.fillItems = fillItems; this.resourcesProvider = resourcesProvider; update(false); @@ -214,7 +258,7 @@ public void drawWhiteSections(Canvas canvas, RecyclerListView listView) { for (int i = 0; i < whiteSections.size(); ++i) { Section section = whiteSections.get(i); if (section.end < 0) continue; - listView.drawSectionBackground(canvas, section.start, section.end, getThemedColor(Theme.key_windowBackgroundWhite)); + listView.drawSectionBackground(canvas, section.start, section.end, getThemedColor(dialog ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite)); } } @@ -224,11 +268,13 @@ public void update(boolean animated) { items.clear(); whiteSections.clear(); reorderSections.clear(); - fillItems.run(items, this); - if (animated) { - setItems(oldItems, items); - } else { - notifyDataSetChanged(); + if (fillItems != null) { + fillItems.run(items, this); + if (animated) { + setItems(oldItems, items); + } else { + notifyDataSetChanged(); + } } } @@ -236,19 +282,27 @@ public void update(boolean animated) { @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; + final int key_background = dialog ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite; switch (viewType) { case VIEW_TYPE_HEADER: - view = new HeaderCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + if (dialog) { + view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, 0, false, resourcesProvider); + } else { + view = new HeaderCell(context, resourcesProvider); + } + view.setBackgroundColor(getThemedColor(key_background)); + break; + case VIEW_TYPE_ANIMATED_HEADER: + view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, 0, false, true, resourcesProvider); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_BLACK_HEADER: view = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 17, 15, false, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_LARGE_HEADER: - HeaderCell headerCell = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 23, 8, 10, false, resourcesProvider); + HeaderCell headerCell = new HeaderCell(context, Theme.key_windowBackgroundWhiteBlackText, 23, 20, 0, false, resourcesProvider); headerCell.setTextSize(20); - headerCell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); view = headerCell; break; case VIEW_TYPE_TOPVIEW: @@ -256,7 +310,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int break; case VIEW_TYPE_TEXT: view = new TextCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CHECK: case VIEW_TYPE_CHECKRIPPLE: @@ -267,17 +321,17 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int cell.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); cell.setHeight(56); } - cell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + cell.setBackgroundColor(getThemedColor(key_background)); view = cell; break; case VIEW_TYPE_RADIO: view = new DialogRadioCell(context); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_TEXT_CHECK: case VIEW_TYPE_ICON_TEXT_CHECK: view = new NotificationsCheckCell(context, 21, 60, viewType == VIEW_TYPE_ICON_TEXT_CHECK, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CUSTOM: view = new FrameLayout(context) { @@ -291,35 +345,35 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { case VIEW_TYPE_FILTER_CHAT_CHECK: UserCell userCell = new UserCell(context, 6, viewType == VIEW_TYPE_FILTER_CHAT_CHECK ? 3 : 0, false); userCell.setSelfAsSavedMessages(true); - userCell.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell.setBackgroundColor(getThemedColor(key_background)); view = userCell; break; case VIEW_TYPE_USER_ADD: UserCell userCell2 = new UserCell(context, 6, 0, false, true); - userCell2.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell2.setBackgroundColor(getThemedColor(key_background)); view = userCell2; break; case VIEW_TYPE_RADIO_USER: StoryPrivacyBottomSheet.UserCell userCell3 = new StoryPrivacyBottomSheet.UserCell(context, resourcesProvider); userCell3.setIsSendAs(false, false); - userCell3.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + userCell3.setBackgroundColor(getThemedColor(key_background)); view = userCell3; break; case VIEW_TYPE_SLIDE: view = new SlideChooseView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_INTSLIDE: view = new SlideIntChooseView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_QUICK_REPLY: view = new QuickRepliesActivity.QuickReplyView(context, onReordered != null, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_LARGE_QUICK_REPLY: view = new QuickRepliesActivity.LargeQuickReplyView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_CHART_LINEAR: case VIEW_TYPE_CHART_DOUBLE_LINEAR: @@ -331,26 +385,43 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { chartSharedUI = new BaseChartView.SharedUiComponents(); } view = new StatisticActivity.UniversalChartCell(context, currentAccount, viewType - VIEW_TYPE_CHART_LINEAR, chartSharedUI, classGuid); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_TRANSACTION: view = new ChannelMonetizationLayout.TransactionCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_PROCEED_OVERVIEW: view = new ChannelMonetizationLayout.ProceedOverviewCell(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_SPACE: view = new View(context); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_BUSINESS_LINK: view = new BusinessLinksActivity.BusinessLinkView(context, resourcesProvider); - view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(getThemedColor(key_background)); break; case VIEW_TYPE_RIGHT_ICON_TEXT: view = new TextRightIconCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(key_background)); + break; + case VIEW_TYPE_GRAY_SECTION: + view = new GraySectionCell(context, resourcesProvider); + break; + case VIEW_TYPE_PROFILE_CELL: + view = new ProfileSearchCell(context); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + break; + case VIEW_TYPE_SEARCH_MESSAGE: + view = new DialogCell(null, context, false, true); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + break; + case VIEW_TYPE_FLICKER: + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, resourcesProvider); + flickerLoadingView.setIsSingleCell(true); + view = flickerLoadingView; view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; default: @@ -358,6 +429,33 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { case VIEW_TYPE_LARGE_SHADOW: view = new TextInfoPrivacyCell(context, resourcesProvider); break; + case VIEW_TYPE_ROUND_CHECKBOX: + case VIEW_TYPE_ROUND_GROUP_CHECKBOX: + case VIEW_TYPE_USER_GROUP_CHECKBOX: + case VIEW_TYPE_USER_CHECKBOX: + int checkBoxType = 0; + if (viewType == VIEW_TYPE_ROUND_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_ROUND; + } else if (viewType == VIEW_TYPE_USER_GROUP_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_USER_GROUP; + } else if (viewType == VIEW_TYPE_USER_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_USER; + } else if (viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX) { + checkBoxType = CheckBoxCell.TYPE_CHECK_BOX_ROUND_GROUP; + } + CheckBoxCell checkBoxCell = new CheckBoxCell(context, checkBoxType, 21, true, resourcesProvider); + checkBoxCell.getCheckBoxRound().setColor(Theme.key_switch2TrackChecked, Theme.key_radioBackground, Theme.key_checkboxCheck); + checkBoxCell.setBackgroundColor(getThemedColor(key_background)); + view = checkBoxCell; + break; + case VIEW_TYPE_SHADOW_COLLAPSE_BUTTON: + view = new CollapseTextCell(context, resourcesProvider); + break; + case VIEW_TYPE_SWITCH: + case VIEW_TYPE_EXPANDABLE_SWITCH: + view = new TextCheckCell2(context); + view.setBackgroundColor(getThemedColor(key_background)); + break; } return new RecyclerListView.Holder(view); } @@ -376,7 +474,7 @@ private boolean hasDivider(int position) { } private boolean isShadow(int viewType) { - return viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW; + return viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW || viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON || viewType == VIEW_TYPE_GRAY_SECTION || viewType == VIEW_TYPE_FLICKER; } @Override @@ -392,9 +490,11 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi case VIEW_TYPE_BLACK_HEADER: case VIEW_TYPE_LARGE_HEADER: ((HeaderCell) holder.itemView).setText(item.text); - if (item.backgroundKey != 0) { - holder.itemView.setBackgroundColor(getThemedColor(item.backgroundKey)); - } + break; + case VIEW_TYPE_ANIMATED_HEADER: + HeaderCell animatedHeaderCell = (HeaderCell) holder.itemView; + animatedHeaderCell.setText(item.animatedText, animatedHeaderCell.id == item.id); + animatedHeaderCell.id = item.id; break; case VIEW_TYPE_TOPVIEW: TopViewCell topCell = (TopViewCell) holder.itemView; @@ -409,6 +509,8 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi TextCell cell = (TextCell) holder.itemView; if (item.object instanceof TLRPC.Document) { cell.setTextAndSticker(item.text, (TLRPC.Document) item.object, divider); + } else if (item.object instanceof String) { + cell.setTextAndSticker(item.text, (String) item.object, divider); } else if (TextUtils.isEmpty(item.textValue)) { if (item.iconResId == 0) { cell.setText(item.text, divider); @@ -429,9 +531,6 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } else { cell.setColors(Theme.key_windowBackgroundWhiteGrayIcon, Theme.key_windowBackgroundWhiteBlackText); } - if (item.backgroundKey != 0) { - cell.setBackgroundColor(getThemedColor(item.backgroundKey)); - } break; case VIEW_TYPE_CHECK: case VIEW_TYPE_CHECKRIPPLE: @@ -462,32 +561,48 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi break; case VIEW_TYPE_TEXT_CHECK: NotificationsCheckCell checkCell1 = (NotificationsCheckCell) holder.itemView; - checkCell1.setTextAndValueAndCheck(item.text, item.subtext, item.checked, divider); - checkCell1.setMultiline(item.subtext != null && item.subtext.toString().contains("\n")); + final boolean multiline = item.subtext != null && item.subtext.toString().contains("\n"); + checkCell1.setTextAndValueAndCheck(item.text, item.subtext, item.checked, 0, multiline, divider); break; case VIEW_TYPE_ICON_TEXT_CHECK: // TODO: image ((NotificationsCheckCell) holder.itemView).setTextAndValueAndCheck(item.text, item.subtext, item.checked, divider); break; + case VIEW_TYPE_SHADOW_COLLAPSE_BUTTON: case VIEW_TYPE_SHADOW: case VIEW_TYPE_LARGE_SHADOW: - TextInfoPrivacyCell cell2 = (TextInfoPrivacyCell) holder.itemView; - if (TextUtils.isEmpty(item.text)) { - cell2.setFixedSize(viewType == VIEW_TYPE_LARGE_SHADOW ? 220 : 12); - cell2.setText(""); - } else { - cell2.setFixedSize(0); - cell2.setText(item.text); - } - if (item.accent) { // asCenterShadow - cell2.setTextGravity(Gravity.CENTER); - cell2.getTextView().setWidth(Math.min(HintView2.cutInFancyHalf(cell2.getText(), cell2.getTextView().getPaint()), AndroidUtilities.displaySize.x - dp(60))); - cell2.getTextView().setPadding(0, dp(17), 0, dp(17)); - } else { - cell2.setTextGravity(Gravity.START); - cell2.getTextView().setMinWidth(0); - cell2.getTextView().setMaxWidth(AndroidUtilities.displaySize.x); - cell2.getTextView().setPadding(0, dp(10), 0, dp(17)); + View cell3 = null; + if (viewType == VIEW_TYPE_SHADOW || viewType == VIEW_TYPE_LARGE_SHADOW) { + TextInfoPrivacyCell cell2 = (TextInfoPrivacyCell) holder.itemView; + if (TextUtils.isEmpty(item.text)) { + cell2.setFixedSize(viewType == VIEW_TYPE_LARGE_SHADOW ? 220 : 12); + cell2.setText(""); + } else { + cell2.setFixedSize(0); + cell2.setText(item.text); + } + if (item.accent) { // asCenterShadow + cell2.setTextGravity(Gravity.CENTER); + cell2.getTextView().setWidth(Math.min(HintView2.cutInFancyHalf(cell2.getText(), cell2.getTextView().getPaint()), AndroidUtilities.displaySize.x - dp(60))); + cell2.getTextView().setPadding(0, dp(17), 0, dp(17)); + } else { + cell2.setTextGravity(Gravity.START); + cell2.getTextView().setMinWidth(0); + cell2.getTextView().setMaxWidth(AndroidUtilities.displaySize.x); + cell2.getTextView().setPadding(0, dp(10), 0, dp(17)); + } + cell3 = cell2; + } else if (viewType == VIEW_TYPE_SHADOW_COLLAPSE_BUTTON) { + CollapseTextCell btn = (CollapseTextCell) holder.itemView; + btn.set(item.animatedText, item.collapsed); + if (item.accent) { + btn.setColor(Theme.key_windowBackgroundWhiteBlueText4); + } else if (item.red) { + btn.setColor(Theme.key_text_RedRegular); + } else { + btn.setColor(Theme.key_windowBackgroundWhiteBlackText); + } + cell3 = btn; } final boolean prev = prevItem != null && !isShadow(prevItem.viewType); final boolean next = nextItem != null && !isShadow(nextItem.viewType); @@ -501,10 +616,15 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } else { drawable = R.drawable.field_carret_empty; } - if (item.backgroundKey != 0) { - cell2.setBackgroundColor(getThemedColor(item.backgroundKey)); + Drawable shadowDrawable = Theme.getThemedDrawableByKey(context, drawable, Theme.key_windowBackgroundGrayShadow, resourcesProvider); + if (dialog) { + cell3.setBackground(new LayerDrawable(new Drawable[]{ + new ColorDrawable(getThemedColor(Theme.key_dialogBackgroundGray)), + shadowDrawable + })); + } else { + cell3.setBackground(shadowDrawable); } - cell2.setBackground(Theme.getThemedDrawableByKey(context, drawable, Theme.key_windowBackgroundGrayShadow, resourcesProvider)); break; case VIEW_TYPE_CUSTOM: FrameLayout frameLayout = (FrameLayout) holder.itemView; @@ -608,8 +728,105 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi TextRightIconCell textCell = (TextRightIconCell) holder.itemView; textCell.setTextAndIcon(item.text, item.iconResId); textCell.setDivider(divider); - if (item.backgroundKey != 0) { - textCell.setBackgroundColor(getThemedColor(item.backgroundKey)); + textCell.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + break; + case VIEW_TYPE_GRAY_SECTION: + GraySectionCell sectionCell = (GraySectionCell) holder.itemView; + if (TextUtils.equals(sectionCell.getText(), item.text)) { + sectionCell.setRightText(item.subtext, true, item.clickCallback); + } else { + sectionCell.setText(item.text, item.subtext, item.clickCallback); + } + break; + case VIEW_TYPE_PROFILE_CELL: + ProfileSearchCell profileCell = (ProfileSearchCell) holder.itemView; + Object object = item.object; + CharSequence s = ""; + if (item.withUsername) { + String username = null; + if (object instanceof TLRPC.User) { + username = UserObject.getPublicUsername((TLRPC.User) object); + } else if (object instanceof TLRPC.Chat) { + username = ChatObject.getPublicUsername((TLRPC.Chat) object); + } + if (username != null) { + s += "@" + username; + } + } + String title = ""; + if (object instanceof TLRPC.Chat) { + TLRPC.Chat chat = (TLRPC.Chat) object; + if (chat.participants_count != 0) { + String membersString; + if (ChatObject.isChannel(chat) && !chat.megagroup) { + membersString = LocaleController.formatPluralStringComma("Subscribers", chat.participants_count, ' '); + } else { + membersString = LocaleController.formatPluralStringComma("Members", chat.participants_count, ' '); + } + if (s instanceof SpannableStringBuilder) { + ((SpannableStringBuilder) s).append(", ").append(membersString); + } else if (!TextUtils.isEmpty(s)) { + s = TextUtils.concat(s, ", ", membersString); + } else { + s = membersString; + } + } + title = chat.title; + } else if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; + // add status text + title = UserObject.getUserName(user); + } + profileCell.setData(object, null, title, s, false, false); + profileCell.useSeparator = divider; + break; + case VIEW_TYPE_SEARCH_MESSAGE: + DialogCell dialogCell = (DialogCell) holder.itemView; + MessageObject messageObject = null; + if (item.object instanceof MessageObject) { + messageObject = (MessageObject) item.object; + } + dialogCell.useSeparator = divider; + if (messageObject == null) { + dialogCell.setDialog(0, null, 0, false, false); + } else { + dialogCell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, false, false); + } + break; + case VIEW_TYPE_FLICKER: + FlickerLoadingView flickerLoadingView = (FlickerLoadingView) holder.itemView; + flickerLoadingView.setViewType(item.intValue); + break; + case VIEW_TYPE_ROUND_CHECKBOX: + case VIEW_TYPE_ROUND_GROUP_CHECKBOX: + case VIEW_TYPE_USER_GROUP_CHECKBOX: + CheckBoxCell checkBoxCell = (CheckBoxCell) holder.itemView; + checkBoxCell.setPad(item.pad); + checkBoxCell.setText(item.text, "", item.checked, divider, checkBoxCell.itemId == item.id); + checkBoxCell.itemId = item.id; + checkBoxCell.setIcon(item.locked ? R.drawable.permission_locked : 0); + if (viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX) { + checkBoxCell.setCollapseButton(item.collapsed, item.animatedText, item.clickCallback); + } + break; + case VIEW_TYPE_USER_CHECKBOX: + CheckBoxCell userCheckBoxCell = (CheckBoxCell) holder.itemView; + userCheckBoxCell.setPad(item.pad); + userCheckBoxCell.setUserOrChat((TLObject) item.object); + userCheckBoxCell.setChecked(item.checked, userCheckBoxCell.itemId == item.id); + userCheckBoxCell.itemId = item.id; + userCheckBoxCell.setNeedDivider(divider); + break; + case VIEW_TYPE_SWITCH: + case VIEW_TYPE_EXPANDABLE_SWITCH: + TextCheckCell2 switchCell = (TextCheckCell2) holder.itemView; + switchCell.setTextAndCheck(item.text.toString(), item.checked, divider, switchCell.id == item.id); + switchCell.id = item.id; + switchCell.setIcon(item.locked ? R.drawable.permission_locked : 0); + if (viewType == VIEW_TYPE_EXPANDABLE_SWITCH) { + switchCell.setCollapseArrow(item.animatedText.toString(), item.collapsed, () -> { + item.clickCallback.onClick(switchCell); + }); } break; } @@ -674,7 +891,15 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { viewType == VIEW_TYPE_QUICK_REPLY || viewType == VIEW_TYPE_BUSINESS_LINK || viewType == VIEW_TYPE_TRANSACTION || - viewType == VIEW_TYPE_RADIO_USER + viewType == VIEW_TYPE_RADIO_USER || + viewType == VIEW_TYPE_PROFILE_CELL || + viewType == VIEW_TYPE_SEARCH_MESSAGE || + viewType == VIEW_TYPE_ROUND_CHECKBOX || + viewType == VIEW_TYPE_USER_GROUP_CHECKBOX || + viewType == VIEW_TYPE_USER_CHECKBOX || + viewType == VIEW_TYPE_ROUND_GROUP_CHECKBOX || + viewType == VIEW_TYPE_SWITCH || + viewType == VIEW_TYPE_EXPANDABLE_SWITCH ) && (item == null || item.enabled); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java index 329644ee64..54fec81b71 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UniversalFragment.java @@ -44,32 +44,6 @@ public void onItemClick(int id) { }); FrameLayout contentView = new SizeNotifierFrameLayout(context) { -// private AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { -// @Override -// protected void onTransitionStart(boolean keyboardVisible, int contentHeight) {} -// @Override -// protected void onTransitionEnd() {} -// @Override -// protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { -// if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { -// return; -// } -// actionBar.setTranslationY(y); -// } -// }; -// -// @Override -// protected void onAttachedToWindow() { -// super.onAttachedToWindow(); -// adjustPanLayoutHelper.onAttach(); -// } -// -// @Override -// protected void onDetachedFromWindow() { -// super.onDetachedFromWindow(); -// adjustPanLayoutHelper.onDetach(); -// } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java index 40f6dda0f8..95fa8e4abb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java @@ -306,6 +306,12 @@ public void open(Uri uri) { }); } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setPivotY(getMeasuredHeight()); + } + public boolean isReady() { return ready; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index 6fc73838d6..dca21e77fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -34,6 +34,7 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -66,6 +67,7 @@ import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.WebFile; import org.telegram.tgnet.ConnectionsManager; @@ -143,7 +145,11 @@ default void stickerSetSelected(TLRPC.StickerSet set, String emoji) { } - default void newStickerPackSelected(CharSequence short_name, CharSequence name, String emoji) { + default void newStickerPackSelected(CharSequence short_name, CharSequence name, String emoji, Utilities.Callback whenDone) { + + } + + default void setIntroSticker(String emoji) { } @@ -181,6 +187,10 @@ default void remove(SendMessagesHelper.ImportingSticker sticker) { } + default boolean canDeleteSticker(TLRPC.Document document) { + return false; + } + default void deleteSticker(TLRPC.Document document) { } @@ -197,6 +207,14 @@ default boolean isReplacedSticker() { return false; } + default boolean isSettingIntroSticker() { + return false; + } + + default void sendIntroSticker() { + + } + default String getQuery(boolean isGif) { return null; } @@ -274,6 +292,7 @@ default boolean isStickerEditor() { private ContentPreviewViewerDelegate delegate; private boolean isPhotoEditor; private boolean isStickerEditor; + private ArrayList selectedEmojis; private boolean isRecentSticker; @@ -287,9 +306,9 @@ default boolean isStickerEditor() { private WindowManager.LayoutParams windowLayoutParams; private FrameLayout windowView; private FrameLayoutDrawer containerView; - private ImageReceiver centerImage = new ImageReceiver(); + public ImageReceiver centerImage = new ImageReceiver(); private ImageReceiver effectImage = new ImageReceiver(); - private PaintingOverlay paintingOverlay; + public PaintingOverlay paintingOverlay; private Path paintingOverlayClipPath; private boolean isVisible = false; private float showProgress; @@ -298,6 +317,7 @@ default boolean isStickerEditor() { private int keyboardHeight = AndroidUtilities.dp(200); private Drawable slideUpDrawable; private boolean menuVisible; + private View popupLayout; private float blurProgress; private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private UnlockPremiumView unlockPremiumView; @@ -325,18 +345,26 @@ public void run() { ArrayList icons = new ArrayList<>(); if (stickerSetForCustomSticker == null) { - items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); - icons.add(R.drawable.msg_send); - actions.add(0); + if (delegate != null && delegate.isSettingIntroSticker()) { + items.add(LocaleController.getString(R.string.SetIntroSticker)); + icons.add(R.drawable.menu_sticker_add); + actions.add(0); + } else { + items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); + icons.add(R.drawable.msg_send); + actions.add(0); - items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - icons.add(R.drawable.msg_fave); - actions.add(1); + items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); + icons.add(R.drawable.msg_fave); + actions.add(1); + } } - items.add(LocaleController.getString(delegate != null && delegate.isReplacedSticker() ? R.string.StickersReplaceSticker : R.string.AddToStickerPack)); - icons.add(delegate != null && delegate.isReplacedSticker() ? R.drawable.msg_replace : R.drawable.menu_sticker_add); - actions.add(2); + if (delegate == null || !delegate.isSettingIntroSticker()) { + items.add(LocaleController.getString(delegate != null && delegate.isReplacedSticker() ? R.string.StickersReplaceSticker : R.string.AddToStickerPack)); + icons.add(delegate != null && delegate.isReplacedSticker() ? R.drawable.msg_replace : R.drawable.menu_sticker_add); + actions.add(2); + } ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(parentActivity, true, false, resourcesProvider); backCell.setItemHeight(44); @@ -357,19 +385,26 @@ public void run() { } if (stickerSetCovered instanceof TLRPC.TL_stickerSetNoCovered) { StickersDialogs.showShortNameEditorDialog(resourcesProvider, containerView.getContext(), short_name -> { - StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), arg -> { - delegate.newStickerPackSelected(short_name, arg, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + StickersDialogs.showNameEditorDialog(null, resourcesProvider, containerView.getContext(), (text, whenDone) -> { + if (delegate != null) { + delegate.newStickerPackSelected(short_name, text, TextUtils.join("", selectedEmojis), whenDone != null ? success -> { + whenDone.run(success); + if (success) { + dismissPopupWindow(); + } + } : null); + if (whenDone == null) { + dismissPopupWindow(); + } } }); }); return; } - delegate.stickerSetSelected(stickerSetCovered.set, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + delegate.stickerSetSelected(stickerSetCovered.set, TextUtils.join("", selectedEmojis)); } + dismissPopupWindow(); }); backContainer.addView(backCell); linearLayout.addView(backContainer); @@ -387,20 +422,24 @@ public void run() { listView.getAdapter().notifyDataSetChanged(); previewMenu.getSwipeBack().openForeground(1); } else { - delegate.stickerSetSelected(stickerSetForCustomSticker.set, reactionsLayout.getSelectedEmoji()); - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + delegate.stickerSetSelected(stickerSetForCustomSticker.set, TextUtils.join("", selectedEmojis)); } + dismissPopupWindow(); } } else { - if (actions.get(which) == 1) { - delegate.addToFavoriteSelected(reactionsLayout.getSelectedEmoji()); - } else if (actions.get(which) == 0) { - delegate.sendSticker(); - } - if (popupWindow != null) { - popupWindow.dismiss(); + if (delegate != null) { + if (actions.get(which) == 1) { + delegate.addToFavoriteSelected(TextUtils.join("", selectedEmojis)); + } else if (actions.get(which) == 0) { + if (delegate.isSettingIntroSticker()) { + delegate.setIntroSticker(TextUtils.join("", selectedEmojis)); + } else { + delegate.sendSticker(); + } + } } + dismissPopupWindow(); } }; for (int i = 0; i < items.size(); i++) { @@ -414,27 +453,27 @@ public void run() { previewMenu.addViewToSwipeBack(linearLayout); backContainer.setOnClickListener(view -> previewMenu.getSwipeBack().closeForeground()); - popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - popupWindow = null; - menuVisible = false; - if (closeOnDismiss) { - close(); - } - } - }; - popupWindow.setPauseNotifications(true); - popupWindow.setDismissAnimationDuration(100); - popupWindow.setScaleOut(true); - popupWindow.setOutsideTouchable(false); - popupWindow.setClippingEnabled(false); - popupWindow.setAnimationStyle(R.style.PopupContextAnimation); - popupWindow.setFocusable(false); - previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); - popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - popupWindow.getContentView().setFocusableInTouchMode(true); +// popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { +// @Override +// public void dismiss() { +// super.dismiss(); +// popupWindow = null; +// menuVisible = false; +// if (closeOnDismiss) { +// close(); +// } +// } +// }; +// popupWindow.setPauseNotifications(true); +// popupWindow.setDismissAnimationDuration(100); +// popupWindow.setScaleOut(true); +// popupWindow.setOutsideTouchable(false); +// popupWindow.setClippingEnabled(false); +// popupWindow.setAnimationStyle(R.style.PopupContextAnimation); +// popupWindow.setFocusable(false); +// previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); +// popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); +// popupWindow.getContentView().setFocusableInTouchMode(true); int insets = 0; int top; @@ -447,7 +486,16 @@ public void dismiss() { int size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); int y = (int) (moveY + Math.max(size / 2 + top, (containerView.getHeight() - insets - keyboardHeight) / 2) + size / 2); y += AndroidUtilities.dp(24 + 60); - popupWindow.showAtLocation(containerView, 0, (int) ((containerView.getMeasuredWidth() - previewMenu.getMeasuredWidth()) / 2f), y); + containerView.addView(previewMenu, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, (float) (y / AndroidUtilities.density), 0, 0)); +// popupWindow.showAtLocation(containerView, 0, x, y); + popupLayout = previewMenu; + popupLayout.setTranslationY(-dp(12)); + popupLayout.setAlpha(0f); + popupLayout.setScaleX(.8f); + popupLayout.setScaleY(.8f); + popupLayout.setPivotY(0); + popupLayout.setPivotX(popupLayout.getMeasuredWidth() / 2f); + popupLayout.animate().translationY(0).alpha(1f).scaleX(1f).scaleY(1f).setDuration(320).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(); showEmojiSelectorForStickers(); menuVisible = true; containerView.invalidate(); @@ -517,12 +565,12 @@ public void dismiss() { final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); TLRPC.TL_messages_stickerSet stickerSet = mediaDataController.getStickerSet(currentStickerSet, true); if (stickerSet != null && stickerSet.set.creator && !StickersAlert.DISABLE_STICKER_EDITOR) { - if (delegate != null && delegate.canEditSticker() && !stickerSet.set.emojis && !stickerSet.set.masks && MessageObject.isStaticStickerDocument(currentDocument)) { + if (delegate != null && delegate.canEditSticker() && !stickerSet.set.emojis && !stickerSet.set.masks) { items.add(LocaleController.getString(R.string.EditSticker)); icons.add(R.drawable.msg_edit); actions.add(7); } - if (delegate != null) { + if (delegate != null && delegate.canDeleteSticker(currentDocument)) { items.add(LocaleController.getString(R.string.DeleteSticker)); icons.add(R.drawable.msg_delete); actions.add(8); @@ -582,9 +630,7 @@ public void onClick(View v) { } else if (actions.get(which) == 8) { delegate.deleteSticker(currentDocument); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); } }; @@ -726,9 +772,7 @@ public void dismiss() { } else if (action == 5) { MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_FAVE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); }; for (int i = 0; i < items.size(); i++) { @@ -864,9 +908,7 @@ public void dismiss() { ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; AlertsCreator.createScheduleDatePickerDialog(parentActivity, stickerPreviewViewerDelegate.getDialogId(), (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendGif(document != null ? document : result, parent, notify, scheduleDate), resourcesProvider); } - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); }; for (int i = 0; i < items.size(); i++) { @@ -967,25 +1009,37 @@ public void invalidateLoopViews() { reactionsLayoutContainer = new FrameLayout(containerView.getContext()); reactionsLayoutContainer.addView(reactionsLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 72 + 22 + 22, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 0)); containerView.addView(reactionsLayoutContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 100, 0, 0)); - reactionsLayout.setMessage(null, null); } + reactionsLayout.setSelectedEmojis(selectedEmojis); reactionsLayout.setDelegate((view, visibleReaction, longpress, addToRecent) -> { + if (visibleReaction == null) return; CustomEmojiReactionsWindow reactionsWindow = reactionsLayout.getReactionsWindow(); - if (reactionsWindow != null && reactionsWindow.isShowing()) { - reactionsLayout.setSelectedReactionInclusive(visibleReaction); - reactionsWindow.getSelectAnimatedEmojiDialog().setSelectedReaction(visibleReaction); - AndroidUtilities.runOnUIThread(reactionsWindow::dismiss, 200); + if (selectedEmojis.contains(visibleReaction.emojicon)) { + if (selectedEmojis.size() <= 1) { + return; + } + selectedEmojis.remove(visibleReaction.emojicon); } else { - reactionsLayout.setSelectedReactionInclusive(visibleReaction); + selectedEmojis.add(visibleReaction.emojicon); + if (selectedEmojis.size() > 7) { + selectedEmojis.remove(0); + } + } + reactionsLayout.setSelectedEmojis(selectedEmojis); + if (reactionsWindow != null) { + reactionsLayout.setMessage(null, null, false); + if (reactionsWindow.getSelectAnimatedEmojiDialog() != null) { + reactionsWindow.getSelectAnimatedEmojiDialog().setSelectedReactions(selectedEmojis); + reactionsWindow.getSelectAnimatedEmojiDialog().setRecentReactions(reactionsLayout.allReactionsList); + } + reactionsWindow.dismiss(); } }); - if (!reactionsLayout.getVisibleReactionsList().isEmpty()) { - reactionsLayout.setSelectedReaction(reactionsLayout.getVisibleReactionsList().get(0)); - } + reactionsLayout.setMessage(null, null, false); reactionsLayoutContainer.setScaleY(0.6f); reactionsLayoutContainer.setScaleX(0.6f); reactionsLayoutContainer.setAlpha(0f); - AndroidUtilities.runOnUIThread(() -> reactionsLayoutContainer.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start(), 10); + AndroidUtilities.runOnUIThread(() -> reactionsLayoutContainer.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(420).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start(), 10); } private void showUnlockPremiumView() { @@ -1180,9 +1234,7 @@ public boolean onTouch(MotionEvent event, final RecyclerListView listView, final clearsInputField = false; menuVisible = false; closeOnDismiss = false; - if (popupWindow != null) { - popupWindow.dismiss(); - } + dismissPopupWindow(); AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, false); if (currentPreviewCell instanceof StickerEmojiCell) { StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; @@ -1190,7 +1242,7 @@ public boolean onTouch(MotionEvent event, final RecyclerListView listView, final stickerEmojiCell.setScaled(true); } else if (currentPreviewCell instanceof StickerCell) { StickerCell stickerCell = (StickerCell) currentPreviewCell; - open(stickerCell.getSticker(), null, null, delegate != null ? delegate.getQuery(false) : null, null, contentType, false, stickerCell.getParentObject(), resourcesProvider); + open(stickerCell.getSticker(), null, MessageObject.findAnimatedEmojiEmoticon(stickerCell.getSticker(), null, currentAccount), delegate != null ? delegate.getQuery(false) : null, null, contentType, false, stickerCell.getParentObject(), resourcesProvider); stickerCell.setScaled(true); clearsInputField = stickerCell.isClearsInputField(); } else if (currentPreviewCell instanceof ContextLinkCell) { @@ -1435,7 +1487,20 @@ public void setParentActivity(Activity activity) { slideUpDrawable = parentActivity.getResources().getDrawable(R.drawable.preview_arrow); - windowView = new FrameLayout(activity); + windowView = new FrameLayout(activity) { + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == 1) { + if (isStickerEditor || menuVisible) { + closeWithMenu(); + } else { + close(); + } + return true; + } + return super.dispatchKeyEvent(event); + } + }; windowView.setFocusable(true); windowView.setFocusableInTouchMode(true); if (Build.VERSION.SDK_INT >= 21) { @@ -1474,7 +1539,6 @@ protected void onDetachedFromWindow() { return true; }); - SharedPreferences sharedPreferences = MessagesController.getInstance(currentAccount).getGlobalEmojiSettings(); keyboardHeight = sharedPreferences.getInt("kbd_height", AndroidUtilities.dp(200)); @@ -1546,14 +1610,20 @@ public void open(TLRPC.Document document, SendMessagesHelper.ImportingSticker st break; } } - if (contentType == CONTENT_TYPE_EMOJI && emojiPath != null) { + if (emojiPath != null) { CharSequence emoji = Emoji.replaceEmoji(emojiPath, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } if ((newSet != null || contentType == CONTENT_TYPE_EMOJI) && (delegate == null || delegate.needMenu())) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); } + TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSet(newSet, true); + if (stickerSet != null && stickerSet.documents.isEmpty()) { + newSet = null; + } currentStickerSet = newSet; TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (MessageObject.isVideoStickerDocument(document)) { @@ -1574,7 +1644,9 @@ public void open(TLRPC.Document document, SendMessagesHelper.ImportingSticker st if (attribute instanceof TLRPC.TL_documentAttributeSticker) { if (!TextUtils.isEmpty(attribute.alt)) { CharSequence emoji = Emoji.replaceEmoji(attribute.alt, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); break; } } @@ -1591,7 +1663,9 @@ public void open(TLRPC.Document document, SendMessagesHelper.ImportingSticker st } if (emojiPath != null) { CharSequence emoji = Emoji.replaceEmoji(emojiPath, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(500), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + emoji = TextUtils.ellipsize(emoji, textPaint, dp(200), TextUtils.TruncateAt.END); + emoji = AndroidUtilities.replaceCharSequence("\u2026", emoji, ""); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(200), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } if (delegate.needMenu()) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); @@ -1678,10 +1752,7 @@ public void closeWithMenu() { } } menuVisible = false; - if (popupWindow != null) { - popupWindow.dismiss(); - popupWindow = null; - } + dismissPopupWindow(); close(); } @@ -1865,9 +1936,9 @@ private void onDraw(Canvas canvas) { } if (stickerEmojiLayout != null) { if (drawEffect) { - canvas.translate(-AndroidUtilities.dp(250), -effectImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + canvas.translate(-stickerEmojiLayout.getWidth() / 2f, -effectImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); } else { - canvas.translate(-AndroidUtilities.dp(250), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + canvas.translate(-stickerEmojiLayout.getWidth() / 2f, -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); } textPaint.setAlpha((int) (0xFF * showProgress)); stickerEmojiLayout.draw(canvas); @@ -1967,7 +2038,7 @@ public boolean showMenuFor(View view) { return false; } - public void showCustomStickerActions(String path, VideoEditedInfo videoEditedInfo, View view, ContentPreviewViewerDelegate delegate) { + public void showCustomStickerActions(String path, VideoEditedInfo videoEditedInfo, View view, ArrayList selectedEmojis, ContentPreviewViewerDelegate delegate) { Activity activity = AndroidUtilities.findActivity(view.getContext()); if (activity == null) { return; @@ -1977,13 +2048,14 @@ public void showCustomStickerActions(String path, VideoEditedInfo videoEditedInf SendMessagesHelper.ImportingSticker sticker = new SendMessagesHelper.ImportingSticker(); sticker.path = path; sticker.videoEditedInfo = videoEditedInfo; + this.selectedEmojis = selectedEmojis; open(null, sticker, null, null, null, CONTENT_TYPE_CUSTOM_STIKER, false, null, new DarkThemeResourceProvider()); AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 16); } private void getMyStickersRemote(TLRPC.TL_messages_getMyStickers request, List resultList) { - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error != null) { return; } @@ -1991,7 +2063,12 @@ private void getMyStickersRemote(TLRPC.TL_messages_getMyStickers request, List { + Object obj = searchViewPager.channelsSearchAdapter.getObject(position); + if (obj instanceof TLRPC.Chat) { + Bundle args = new Bundle(); + args.putLong("chat_id", ((TLRPC.Chat) obj).id); + ChatActivity chatActivity = new ChatActivity(args); + chatActivity.setNextChannels(searchViewPager.channelsSearchAdapter.getNextChannels(position)); + presentFragment(chatActivity); + } else if (obj instanceof MessageObject) { + MessageObject msg = (MessageObject) obj; + Bundle args = new Bundle(); + if (msg.getDialogId() >= 0) { + args.putLong("user_id", msg.getDialogId()); + } else { + args.putLong("chat_id", -msg.getDialogId()); + } + args.putInt("message_id", msg.getId()); + ChatActivity chatActivity = new ChatActivity(args); + presentFragment(highlightFoundQuote(chatActivity, msg)); + } + }); + searchViewPager.searchListView.setOnItemClickListener((view, position, x, y) -> { if (view instanceof ProfileSearchCell && ((ProfileSearchCell) view).isBlocked()) { showPremiumBlockedToast(view, ((ProfileSearchCell) view).getDialogId()); @@ -5050,6 +5076,22 @@ public void onUserLongPressed(View view, long dialogId) { TLRPC.Chat chat = getMessagesController().getChat(-dialogId); final String key = NotificationsController.getSharedPrefKey(dialogId, 0); boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId); + boolean isPremiumBlocked = MessagesController.getInstance(currentAccount).premiumFeaturesBlocked(); + boolean isPremium = UserConfig.getInstance(currentAccount).isPremium(); + boolean isUnread = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasUnreadStories(dialogId); + CombinedDrawable stealthModeLockedDrawable = null; + if (!isPremiumBlocked && dialogId > 0 && !isPremium) { + Drawable lockIcon = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + if (lockIcon != null) { + Drawable stealthDrawable = ContextCompat.getDrawable(getContext(), R.drawable.msg_stealth_locked); + if (stealthDrawable != null) { + stealthDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon, resourceProvider), PorterDuff.Mode.MULTIPLY)); + } + + lockIcon.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + stealthModeLockedDrawable = new CombinedDrawable(stealthDrawable, lockIcon); + } + } filterOptions .addIf(dialogId > 0, R.drawable.msg_discussion, LocaleController.getString("SendMessage", R.string.SendMessage), () -> { presentFragment(ChatActivity.of(dialogId)); @@ -5079,6 +5121,35 @@ public void onUserLongPressed(View view, long dialogId) { name = name.substring(0, index); } BulletinFactory.of(DialogsActivity.this).createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryUnmutedHint", R.string.NotificationsStoryUnmutedHint, name))).show(); + }).makeMultiline(false).addIf(!isPremiumBlocked && dialogId > 0 && isPremium && isUnread, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.ViewAnonymously), () -> { + TL_stories.TL_storiesStealthMode stealthMode = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().getStealthMode(); + if (stealthMode != null && ConnectionsManager.getInstance(currentAccount).getCurrentTime() < stealthMode.active_until_date) { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + } + } else { + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), 0, StealthModeAlert.TYPE_FROM_DIALOGS, resourceProvider); + stealthModeAlert.setListener(isStealthModeEnabled -> { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + if (isStealthModeEnabled) { + AndroidUtilities.runOnUIThread(StealthModeAlert::showStealthModeEnabledBulletin, 500); + } + } + }); + showDialog(stealthModeAlert); + } + }).makeMultiline(false).addIf(!isPremiumBlocked && dialogId > 0 && !isPremium && isUnread, R.drawable.msg_stories_stealth2, stealthModeLockedDrawable, LocaleController.getString(R.string.ViewAnonymously), () -> { + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), 0, StealthModeAlert.TYPE_FROM_DIALOGS, resourceProvider); + stealthModeAlert.setListener(isStealthModeEnabled -> { + if (view instanceof StoryCell) { + dialogStoriesCell.openStoryForCell((StoryCell) view); + if (isStealthModeEnabled) { + AndroidUtilities.runOnUIThread(StealthModeAlert::showStealthModeEnabledBulletin, 500); + } + } + }); + showDialog(stealthModeAlert); }).makeMultiline(false).addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), () -> { toggleArciveForStory(dialogId); }).makeMultiline(false).addIf(isArchive(), R.drawable.msg_unarchive, LocaleController.getString("UnarchiveStories", R.string.UnarchiveStories), () -> { @@ -5769,7 +5840,23 @@ private void updateDialogsHint() { } authHintCell.set(DialogsActivity.this, currentAccount); updateAuthHintCellVisibility(true); - } else if (folderId == 0 && !getMessagesController().premiumPurchaseBlocked() && BirthdayController.getInstance(currentAccount).contains() && !NekoConfig.disableTrending.Bool()) { + } else if (folderId == 0 && MessagesController.getInstance(currentAccount).pendingSuggestions.contains("PREMIUM_GRACE") && !NekoConfig.disableTrending.Bool()) { + dialogsHintCellVisible = true; + dialogsHintCell.setVisibility(View.VISIBLE); + dialogsHintCell.setCompact(true); + dialogsHintCell.setOnClickListener(v -> { + Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); + }); + dialogsHintCell.setText(Emoji.replaceWithRestrictedEmoji(LocaleController.getString(R.string.GraceTitle), dialogsHintCell.titleView, this::updateDialogsHint), LocaleController.getString(R.string.GraceMessage)); + dialogsHintCell.setOnCloseListener(v -> { + MessagesController.getInstance(currentAccount).removeSuggestion(0, "PREMIUM_GRACE"); + ChangeBounds transition = new ChangeBounds(); + transition.setDuration(200); + TransitionManager.beginDelayedTransition((ViewGroup) dialogsHintCell.getParent(), transition); + updateDialogsHint(); + }); + updateAuthHintCellVisibility(false); + } else if (folderId == 0 && !getMessagesController().premiumPurchaseBlocked() && BirthdayController.getInstance(currentAccount).contains() && !getMessagesController().dismissedSuggestions.contains("BIRTHDAY_CONTACTS_TODAY") && !NekoConfig.disableTrending.Bool()) { BirthdayController.BirthdayState state = BirthdayController.getInstance(currentAccount).getState(); ArrayList users = state.today; dialogsHintCellVisible = true; @@ -5789,6 +5876,7 @@ private void updateDialogsHint() { ); dialogsHintCell.setOnCloseListener(v -> { BirthdayController.getInstance(currentAccount).hide(); + MessagesController.getInstance(currentAccount).removeSuggestion(0, "BIRTHDAY_CONTACTS_TODAY"); ChangeBounds transition = new ChangeBounds(); transition.setDuration(200); TransitionManager.beginDelayedTransition((ViewGroup) dialogsHintCell.getParent(), transition); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java index 43d501751c..18f0406625 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java @@ -390,9 +390,9 @@ public void updateDialogs() { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; if (Build.VERSION.SDK_INT >= 18) { - innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA \u2068%s\u2069", mediaPoll.poll.question.text); } else { - innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question); + innerMessage = String.format("\uD83D\uDCCA %s", mediaPoll.poll.question.text); } } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { @@ -454,7 +454,7 @@ public void updateDialogs() { } else { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; - messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; + messageString = "\uD83D\uDCCA " + mediaPoll.poll.question.text; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; } else if (message.type == MessageObject.TYPE_MUSIC) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java index 0ac4339eef..b05badda64 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java @@ -1294,7 +1294,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType break; } case VIEW_TYPE_EDIT: { - PollEditTextCell cell = new PollEditTextCell(mContext, false, null, view1 -> IconSelectorAlert.show(FilterCreateActivity.this, (emoticon) -> { + PollEditTextCell cell = new PollEditTextCell(mContext, false, PollEditTextCell.TYPE_DEFAULT, null, view1 -> IconSelectorAlert.show(FilterCreateActivity.this, (emoticon) -> { newFilterEmoticon = emoticon; ((PollEditTextCell) view1.getParent()).setIcon(FolderIconHelper.getTabIcon(newFilterEmoticon), newFilterEmoticon); checkDoneButton(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java index a863ea3d09..da2376005a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FragmentUsernameBottomSheet.java @@ -67,14 +67,23 @@ public static void open( layout.setOrientation(LinearLayout.VERTICAL); layout.setPadding(dp(16), 0, dp(16), 0); + FrameLayout imageContainerView = new FrameLayout(context); + imageContainerView.setBackground(Theme.createCircleDrawable(dp(80), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider))); + layout.addView(imageContainerView, LayoutHelper.createLinear(80, 80, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + RLottieImageView imageView = new RLottieImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); int sz = type == TYPE_USERNAME ? 70 : 78; imageView.setAnimation(type == TYPE_USERNAME ? R.raw.fragment_username : R.raw.fragment_phone, sz, sz); imageView.playAnimation(); imageView.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)); - imageView.setBackground(Theme.createCircleDrawable(dp(80), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider))); - layout.addView(imageView, LayoutHelper.createLinear(80, 80, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 16)); + if (type == TYPE_USERNAME) { + imageView.setScaleX(0.86f); + imageView.setScaleY(0.86f); + } else { + imageView.setTranslationY(dp(2)); + } + imageContainerView.addView(imageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); final String ownerName; if (owner instanceof TLRPC.User) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java index ca3c06340b..fa49268383 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GradientHeaderActivity.java @@ -448,7 +448,7 @@ public ArrayList getThemeDescriptions() { return SimpleThemeDescription.createThemeDescriptions(this::updateColors, Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4, Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4, - Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 + Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStarGradient1, Theme.key_premiumStarGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 ); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index 6c0d0d0a87..44bbbbe59b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -7417,7 +7417,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { options.add(5); } - if (participant.peer.channel_id != 0 && !ChatObject.isMegagroup(currentAccount, participant.peer.channel_id)) { + if (participant.peer != null && participant.peer.channel_id != 0 && !ChatObject.isMegagroup(currentAccount, participant.peer.channel_id)) { items.add(LocaleController.getString("VoipGroupOpenChannel", R.string.VoipGroupOpenChannel)); icons.add(R.drawable.msg_msgbubble3); options.add(8); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java index 496f5f4b2a..6da319cda4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupColorActivity.java @@ -90,6 +90,14 @@ protected void updateRows() { packEmojiHintRow = rowsCount++; statusEmojiRow = rowsCount++; statusHintRow = rowsCount++; + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId); + if (chatFull != null && chatFull.can_set_stickers) { + packStickerRow = rowsCount++; + packStickerHintRow = rowsCount++; + } else { + packStickerRow = -1; + packStickerHintRow = -1; + } messagesPreviewRow = rowsCount++; wallpaperThemesRow = rowsCount++; wallpaperRow = rowsCount++; @@ -114,6 +122,16 @@ protected int getEmojiPackInfoStrRes() { return R.string.GroupEmojiPackInfo; } + @Override + protected int getStickerPackStrRes() { + return R.string.GroupStickerPack; + } + + @Override + protected int getStickerPackInfoStrRes() { + return R.string.GroupStickerPackInfo; + } + @Override protected int getProfileInfoStrRes() { return R.string.GroupProfileInfo; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index a810743bd1..7482efb423 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -698,10 +698,16 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { } else if (id == 15) { showSelectStatusDialog(); } else if (id == 16) { + drawerLayoutContainer.closeDrawer(true); + Bundle args = new Bundle(); + args.putLong("user_id", UserConfig.getInstance(currentAccount).getClientUserId()); + args.putBoolean("my_profile", true); + presentFragment(new ProfileActivity(args, null)); + } else if (id == 17) { + drawerLayoutContainer.closeDrawer(true); Bundle args = new Bundle(); args.putLong("dialog_id", UserConfig.getInstance(currentAccount).getClientUserId()); args.putInt("type", MediaActivity.TYPE_STORIES); - drawerLayoutContainer.closeDrawer(true); presentFragment(new MediaActivity(args, null)); } else if (id == DrawerLayoutAdapter.nkbtnNewStory) { final StoriesController.StoryLimit storyLimit = MessagesController.getInstance(currentAccount).getStoriesController().checkStoryLimit(); @@ -1452,7 +1458,7 @@ public void switchToAccount(int account, boolean removeAll, GenericProvider 0) { + NotificationsController.getInstance(intentAccount[0]).processSeenStoryReactions(UserConfig.getInstance(intentAccount[0]).getClientUserId(), push_story_id); + openMyStory(push_story_id, true); + } else if (push_story_dids != null) { NotificationCenter.getInstance(intentAccount[0]).postNotificationName(NotificationCenter.closeChats); openStories(push_story_dids, true); } else if (push_user_id != 0) { @@ -4348,6 +4361,13 @@ public void didChangeOwner(TLRPC.User user) { } else { args.putLong("user_id", peerId); dialog_id = peerId; + if (text != null) { + String textToSet = text; + if (textToSet.startsWith("@")) { + textToSet = " " + textToSet; + } + args.putString("start_text", textToSet); + } } if (botUser != null && user != null && user.bot) { args.putString("botUser", botUser); @@ -4375,9 +4395,6 @@ public void didChangeOwner(TLRPC.User user) { if (setAsAttachBot != null) { args.putString("attach_bot_start_command", setAsAttachBot); } - if (text != null) { - args.putString("start_text", text); - } BaseFragment lastFragment = !mainFragmentsStack.isEmpty() && voicechat == null ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { final boolean sameDialogId = lastFragment instanceof ChatActivity && ((ChatActivity) lastFragment).getDialogId() == dialog_id; @@ -8114,6 +8131,119 @@ public boolean isLightNavigationBar() { return AndroidUtilities.getLightNavigationBar(getWindow()); } + private void openMyStory(final int storyId, boolean openViews) { + final long dialogId = UserConfig.getInstance(currentAccount).getClientUserId(); + StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); + TL_stories.PeerStories peerStories = storiesController.getStories(dialogId); + TL_stories.StoryItem storyItem = null; + if (peerStories != null) { + for (int i = 0; i < peerStories.stories.size(); ++i) { + if (peerStories.stories.get(i).id == storyId) { + storyItem = peerStories.stories.get(i); + break; + } + } + if (storyItem != null) { + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(storyItem.dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem, dialogIds, 0, null, peerStories, placeProvider, false); + return; + } + } + if (storyItem == null) { + StoriesController.StoriesList list = null; + StoriesController.StoriesList profileList = storiesController.getStoriesList(dialogId, StoriesController.StoriesList.TYPE_PINNED); + if (profileList != null) { + MessageObject msg = profileList.findMessageObject(storyId); + if (msg != null) { + storyItem = msg.storyItem; + list = profileList; + } + } + if (storyItem == null) { + StoriesController.StoriesList archiveList = storiesController.getStoriesList(dialogId, StoriesController.StoriesList.TYPE_ARCHIVE); + if (archiveList != null) { + MessageObject msg = archiveList.findMessageObject(storyId); + if (msg != null) { + storyItem = msg.storyItem; + list = archiveList; + } + } + } + if (storyItem != null && list != null) { + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(storyItem.dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem, dialogIds, 0, list, null, placeProvider, false); + return; + } + } + TL_stories.TL_stories_getStoriesByID req = new TL_stories.TL_stories_getStoriesByID(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.id.add(storyId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TL_stories.TL_stories_stories) { + TL_stories.TL_stories_stories response = (TL_stories.TL_stories_stories) res; + TL_stories.StoryItem storyItem1 = null; + for (int i = 0; i < response.stories.size(); ++i) { + if (response.stories.get(i).id == storyId) { + storyItem1 = response.stories.get(i); + break; + } + } + if (storyItem1 != null) { + storyItem1.dialogId = dialogId; + BaseFragment lastFragment = getLastFragment(); + if (lastFragment == null) { + return; + } + StoryViewer.PlaceProvider placeProvider = null; + if (lastFragment instanceof DialogsActivity) { + try { + placeProvider = StoriesListPlaceProvider.of(((DialogsActivity) lastFragment).dialogStoriesCell.recyclerListView); + } catch (Exception ignore) {} + } + lastFragment.getOrCreateStoryViewer().instantClose(); + ArrayList dialogIds = new ArrayList<>(); + dialogIds.add(dialogId); + if (openViews) { + lastFragment.getOrCreateStoryViewer().showViewsAfterOpening(); + } + lastFragment.getOrCreateStoryViewer().open(this, storyItem1, dialogIds, 0, null, null, placeProvider, false); + return; + } + } + BulletinFactory.global().createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.StoryNotFound)).show(false); + })); + } + private void openStories(long[] dialogIds, boolean requestWhenNeeded) { boolean onlyArchived = true; for (int i = 0; i < dialogIds.length; ++i) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index 8c4da20a9f..b2ad6ac05e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -9,6 +9,8 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -115,6 +117,7 @@ import org.telegram.ui.Components.ProximitySheet; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.UndoView; +import org.telegram.ui.Stories.recorder.HintView2; import java.io.File; import java.net.URLEncoder; @@ -143,7 +146,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private View shadow; private ActionBarMenuItem searchItem; private MapOverlayView overlayView; - private HintView hintView; + private HintView2 hintView; private UndoView[] undoView = new UndoView[2]; private boolean canUndo; @@ -227,7 +230,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private int locationType; - private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(66); + private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - dp(66); private final static int open_in = 1; private final static int share_live_location = 5; @@ -245,6 +248,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter public final static int LOCATION_TYPE_SEND = 0; public final static int LOCATION_TYPE_SEND_WITH_LIVE = 1; + public final static int LOCATION_TYPE_LIVE = 2; public final static int LOCATION_TYPE_GROUP = 4; public final static int LOCATION_TYPE_GROUP_VIEW = 5; public final static int LOCATION_TYPE_LIVE_VIEW = 6; @@ -365,7 +369,7 @@ public void addInfoView(IMapsProvider.IMarker marker) { addressTextView.setText(LocaleController.getString("TapToSendLocation", R.string.TapToSendLocation)); FrameLayout iconLayout = new FrameLayout(context); - iconLayout.setBackground(Theme.createCircleDrawable(AndroidUtilities.dp(36), LocationCell.getColorForIndex(location.num))); + iconLayout.setBackground(Theme.createCircleDrawable(dp(36), LocationCell.getColorForIndex(location.num))); frameLayout.addView(iconLayout, LayoutHelper.createFrame(36, 36, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 4)); BackupImageView imageView = new BackupImageView(context); @@ -432,7 +436,7 @@ public void updatePositions() { View view = entry.getValue(); Point point = projection.toScreenLocation(marker.getPosition()); view.setTranslationX(point.x - view.getMeasuredWidth() / 2); - view.setTranslationY(point.y - view.getMeasuredHeight() + AndroidUtilities.dp(22)); + view.setTranslationY(point.y - view.getMeasuredHeight() + dp(22)); } } } @@ -577,7 +581,7 @@ public void onItemClick(int id) { FileLog.e(e); } } else if (id == share_live_location) { - openShareLiveLocation(0); + openShareLiveLocation(false, 0); } else if (id == get_directions) { openDirections(null); } @@ -712,9 +716,9 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { FrameLayout.LayoutParams layoutParams; if (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) { - layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(21) + padding.top); + layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(21) + padding.top); } else { - layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(6) + padding.top); + layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(6) + padding.top); } layoutParams.gravity = Gravity.LEFT | Gravity.BOTTOM; @@ -731,18 +735,18 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (messageObject == null && (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) || messageObject != null && locationType == 3) { searchAreaButton = new SearchButton(context); - searchAreaButton.setTranslationX(-AndroidUtilities.dp(80)); - Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + searchAreaButton.setTranslationX(-dp(80)); + Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); if (Build.VERSION.SDK_INT < 21) { Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.places_btn).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); - CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, dp(2), dp(2)); combinedDrawable.setFullsize(true); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); searchAreaButton.setStateListAnimator(animator); searchAreaButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @@ -757,7 +761,7 @@ public void getOutline(View view, Outline outline) { searchAreaButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); searchAreaButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); searchAreaButton.setGravity(Gravity.CENTER); - searchAreaButton.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0); + searchAreaButton.setPadding(dp(20), 0, dp(20), 0); mapViewClip.addView(searchAreaButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 80, 12, 80, 0)); if (locationType == 3) { searchAreaButton.setText(LocaleController.getString(R.string.OpenInMaps)); @@ -785,8 +789,8 @@ public void getOutline(View view, Outline outline) { mapTypeButton = new ActionBarMenuItem(context, null, 0, getThemedColor(Theme.key_location_actionIcon), getResourceProvider()); mapTypeButton.setClickable(true); mapTypeButton.setSubMenuOpenSide(2); - mapTypeButton.setAdditionalXOffset(AndroidUtilities.dp(10)); - mapTypeButton.setAdditionalYOffset(-AndroidUtilities.dp(10)); + mapTypeButton.setAdditionalXOffset(dp(10)); + mapTypeButton.setAdditionalYOffset(-dp(10)); if (ApplicationLoader.getMapsProvider() instanceof OSMDroidMapsProvider) { mapTypeButton.addSubItem(map_list_menu_map, R.drawable.msg_map, "Standard OSM", getResourceProvider()); mapTypeButton.addSubItem(map_list_menu_satellite, R.drawable.msg_map, "Wikimedia", getResourceProvider()); @@ -797,23 +801,23 @@ public void getOutline(View view, Outline outline) { mapTypeButton.addSubItem(map_list_menu_hybrid, R.drawable.msg_hybrid, LocaleController.getString("Hybrid", R.string.Hybrid), getResourceProvider()); } mapTypeButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + Drawable drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); if (Build.VERSION.SDK_INT < 21) { Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); - combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + combinedDrawable.setIconSize(dp(40), dp(40)); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(mapTypeButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); mapTypeButton.setStateListAnimator(animator); mapTypeButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -838,23 +842,23 @@ public void getOutline(View view, Outline outline) { } locationButton = new ImageView(context); - drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); if (Build.VERSION.SDK_INT < 21) { Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); - combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + combinedDrawable.setIconSize(dp(40), dp(40)); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(locationButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); locationButton.setStateListAnimator(animator); locationButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -905,23 +909,23 @@ public void getOutline(View view, Outline outline) { }); proximityButton = new ImageView(context); - drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); + drawable = Theme.createSimpleSelectorCircleDrawable(dp(40), getThemedColor(Theme.key_location_actionBackground), getThemedColor(Theme.key_location_actionPressedBackground)); if (Build.VERSION.SDK_INT < 21) { Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); - combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + combinedDrawable.setIconSize(dp(40), dp(40)); drawable = combinedDrawable; } else { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, dp(2), dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(proximityButton, View.TRANSLATION_Z, dp(4), dp(2)).setDuration(200)); proximityButton.setStateListAnimator(animator); proximityButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @Override public void getOutline(View view, Outline outline) { - outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + outline.setOval(0, 0, dp(40), dp(40)); } }); } @@ -985,15 +989,17 @@ public void getOutline(View view, Outline outline) { } } - hintView = new HintView(context, 6, true); - hintView.setVisibility(View.INVISIBLE); - hintView.setShowingDuration(4000); - mapViewClip.addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); + hintView = new HintView2(context, HintView2.DIRECTION_TOP); + hintView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + hintView.setDuration(4000); + hintView.setJoint(1, -(12 + 13)); + hintView.setPadding(0, dp(4), 0, 0); + mapViewClip.addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 8, 12 + 50 + 44, 8, 0)); emptyView = new LinearLayout(context); emptyView.setOrientation(LinearLayout.VERTICAL); emptyView.setGravity(Gravity.CENTER_HORIZONTAL); - emptyView.setPadding(0, AndroidUtilities.dp(60 + 100), 0, 0); + emptyView.setPadding(0, dp(60 + 100), 0, 0); emptyView.setVisibility(View.GONE); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); emptyView.setOnTouchListener((v, event) -> true); @@ -1015,7 +1021,7 @@ public void getOutline(View view, Outline outline) { emptySubtitleTextView.setTextColor(getThemedColor(Theme.key_dialogEmptyText)); emptySubtitleTextView.setGravity(Gravity.CENTER); emptySubtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - emptySubtitleTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), 0); + emptySubtitleTextView.setPadding(dp(40), 0, dp(40), 0); emptyView.addView(emptySubtitleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 6, 0, 0)); listView = new RecyclerListView(context); @@ -1076,7 +1082,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { }); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); listView.setOnItemLongClickListener((view, position) -> { - if (locationType == 2) { + if (locationType == LOCATION_TYPE_LIVE) { Object object = adapter.getItem(position); if (object instanceof LiveLocation) { @@ -1084,7 +1090,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, getResourceProvider()); - cell.setMinimumWidth(AndroidUtilities.dp(200)); + cell.setMinimumWidth(dp(200)); cell.setTextAndIcon(LocaleController.getString("GetDirections", R.string.GetDirections), R.drawable.filled_directions); cell.setOnClickListener(e -> { openDirections(location); @@ -1108,7 +1114,7 @@ public void dismiss() { int[] loc = new int[2]; view.getLocationInWindow(loc); - popupWindow.showAtLocation(view, Gravity.TOP, 0, loc[1] - AndroidUtilities.dp(48 + 4)); + popupWindow.showAtLocation(view, Gravity.TOP, 0, loc[1] - dp(48 + 4)); popupWindow.dimBehind(); return true; @@ -1177,12 +1183,19 @@ public void dismiss() { } } } + } else if (locationType == LOCATION_TYPE_LIVE && getLocationController().isSharingLocation(dialogId) && adapter.getItemViewType(position) == LocationActivityAdapter.VIEW_TYPE_DELETE_LIVE_LOCATION) { + getLocationController().removeSharingLocation(dialogId); + adapter.notifyDataSetChanged(); + finishFragment(); + } else if (locationType == LOCATION_TYPE_LIVE && getLocationController().isSharingLocation(dialogId) && adapter.getItemViewType(position) == LocationActivityAdapter.VIEW_TYPE_LIVE_LOCATION) { + openShareLiveLocation(getLocationController().getSharingLocationInfo(dialogId).period != 0x7FFFFFFF, 0); } else if (position == 2 && locationType == 1 || position == 1 && locationType == 2 || position == 3 && locationType == 3) { if (getLocationController().isSharingLocation(dialogId)) { getLocationController().removeSharingLocation(dialogId); + adapter.notifyDataSetChanged(); finishFragment(); } else { - openShareLiveLocation(0); + openShareLiveLocation(false, 0); } } else { Object object = adapter.getItem(position); @@ -1230,7 +1243,7 @@ public void dismiss() { } animatorSet = new AnimatorSet(); animatorSet.setDuration(200); - animatorSet.playTogether(ObjectAnimator.ofFloat(markerImageView, View.TRANSLATION_Y, markerTop - AndroidUtilities.dp(10))); + animatorSet.playTogether(ObjectAnimator.ofFloat(markerImageView, View.TRANSLATION_Y, markerTop - dp(10))); animatorSet.start(); } else if (ev.getAction() == MotionEvent.ACTION_UP) { if (animatorSet != null) { @@ -1286,7 +1299,7 @@ public void dismiss() { IMapsProvider.IMapStyleOptions style = ApplicationLoader.getMapsProvider().loadRawResourceStyle(ApplicationLoader.applicationContext, themeResId); this.map.setMapStyle(style); } - this.map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + this.map.setPadding(dp(70), 0, dp(70), dp(10)); onMapInit(); }); mapsInitialized = true; @@ -1307,7 +1320,7 @@ public void dismiss() { mapViewClip.addView(frameLayout1, LayoutHelper.createFrame(62, 76, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); BackupImageView backupImageView = new BackupImageView(context); - backupImageView.setRoundRadius(AndroidUtilities.dp(26)); + backupImageView.setRoundRadius(dp(26)); backupImageView.setForUserOrChat(chat, new AvatarDrawable(chat)); frameLayout1.addView(backupImageView, LayoutHelper.createFrame(52, 52, Gravity.LEFT | Gravity.TOP, 5, 5, 0, 0)); @@ -1388,9 +1401,9 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { for (int a = 0; a < 2; a++) { undoView[a] = new UndoView(context); - undoView[a].setAdditionalTranslationY(AndroidUtilities.dp(10)); + undoView[a].setAdditionalTranslationY(dp(10)); if (Build.VERSION.SDK_INT >= 21) { - undoView[a].setTranslationZ(AndroidUtilities.dp(5)); + undoView[a].setTranslationZ(dp(5)); } mapViewClip.addView(undoView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); } @@ -1405,18 +1418,18 @@ protected void onDraw(Canvas canvas) { shadowDrawable.draw(canvas); if (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE) { - int w = AndroidUtilities.dp(36); - int y = padding.top + AndroidUtilities.dp(10); - rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); + int w = dp(36); + int y = padding.top + dp(10); + rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + dp(4)); int color = getThemedColor(Theme.key_sheet_scrollUp); int alpha = Color.alpha(color); Theme.dialogs_onlineCirclePaint.setColor(color); - canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); + canvas.drawRoundRect(rect, dp(2), dp(2), Theme.dialogs_onlineCirclePaint); } } }; if (Build.VERSION.SDK_INT >= 21) { - shadow.setTranslationZ(AndroidUtilities.dp(6)); + shadow.setTranslationZ(dp(6)); } mapViewClip.addView(shadow, layoutParams); @@ -1515,7 +1528,7 @@ private void showSearchPlacesButton(boolean show) { } searchAreaButton.setTag(show ? 1 : null); AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_X, show ? 0 : -AndroidUtilities.dp(80))); + animatorSet.playTogether(ObjectAnimator.ofFloat(searchAreaButton, View.TRANSLATION_X, show ? 0 : -dp(80))); animatorSet.setDuration(180); animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); animatorSet.start(); @@ -1539,11 +1552,11 @@ private Bitmap createUserBitmap(LiveLocation liveLocation) { } else if (liveLocation.chat != null && liveLocation.chat.photo != null) { photo = liveLocation.chat.photo.photo_small; } - result = Bitmap.createBitmap(AndroidUtilities.dp(62), AndroidUtilities.dp(85), Bitmap.Config.ARGB_8888); + result = Bitmap.createBitmap(dp(62), dp(85), Bitmap.Config.ARGB_8888); result.eraseColor(Color.TRANSPARENT); Canvas canvas = new Canvas(result); Drawable drawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.map_pin_photo); - drawable.setBounds(0, 0, AndroidUtilities.dp(62), AndroidUtilities.dp(85)); + drawable.setBounds(0, 0, dp(62), dp(85)); drawable.draw(canvas); Paint roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -1555,13 +1568,13 @@ private Bitmap createUserBitmap(LiveLocation liveLocation) { if (bitmap != null) { BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Matrix matrix = new Matrix(); - float scale = AndroidUtilities.dp(50) / (float) bitmap.getWidth(); - matrix.postTranslate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + float scale = dp(50) / (float) bitmap.getWidth(); + matrix.postTranslate(dp(6), dp(6)); matrix.postScale(scale, scale); roundPaint.setShader(shader); shader.setLocalMatrix(matrix); - bitmapRect.set(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(50 + 6), AndroidUtilities.dp(50 + 6)); - canvas.drawRoundRect(bitmapRect, AndroidUtilities.dp(25), AndroidUtilities.dp(25), roundPaint); + bitmapRect.set(dp(6), dp(6), dp(50 + 6), dp(50 + 6)); + canvas.drawRoundRect(bitmapRect, dp(25), dp(25), roundPaint); } } else { AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -1570,8 +1583,8 @@ private Bitmap createUserBitmap(LiveLocation liveLocation) { } else if (liveLocation.chat != null) { avatarDrawable.setInfo(currentAccount, liveLocation.chat); } - canvas.translate(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); - avatarDrawable.setBounds(0, 0, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); + canvas.translate(dp(6), dp(6)); + avatarDrawable.setBounds(0, 0, dp(50), dp(50)); avatarDrawable.draw(canvas); } canvas.restore(); @@ -1649,7 +1662,7 @@ private void openProximityAlert() { return true; }, () -> { if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } if (!proximitySheet.getRadiusSet()) { if (previousRadius > 0) { @@ -1666,7 +1679,7 @@ private void openProximityAlert() { proximitySheet.show(); } - private void openShareLiveLocation(int proximityRadius) { + private void openShareLiveLocation(boolean expand, int proximityRadius) { if (delegate == null || disablePermissionCheck() || getParentActivity() == null || myLocation == null || !checkGpsEnabled()) { return; } @@ -1679,7 +1692,7 @@ private void openShareLiveLocation(int proximityRadius) { int lastTime = preferences.getInt("backgroundloc", 0); if (Math.abs(System.currentTimeMillis() / 1000 - lastTime) > 24 * 60 * 60 && activity.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { preferences.edit().putInt("backgroundloc", (int) (System.currentTimeMillis() / 1000)).commit(); - AlertsCreator.createBackgroundLocationPermissionDialog(activity, getMessagesController().getUser(getUserConfig().getClientUserId()), () -> openShareLiveLocation(askWithRadius), null).show(); + AlertsCreator.createBackgroundLocationPermissionDialog(activity, getMessagesController().getUser(getUserConfig().getClientUserId()), () -> openShareLiveLocation(expand, askWithRadius), null).show(); return; } } @@ -1690,7 +1703,46 @@ private void openShareLiveLocation(int proximityRadius) { } else { user = null; } - showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), user, param -> shareLiveLocation(user, param, proximityRadius), null)); + showDialog(AlertsCreator.createLocationUpdateDialog(getParentActivity(), expand, user, param -> { + if (expand) { + LocationController.SharingLocationInfo info = getLocationController().getSharingLocationInfo(dialogId); + if (info != null) { + TLRPC.TL_messages_editMessage req = new TLRPC.TL_messages_editMessage(); + req.peer = getMessagesController().getInputPeer(info.did); + req.id = info.mid; + req.flags |= 16384; + req.media = new TLRPC.TL_inputMediaGeoLive(); + req.media.stopped = false; + req.media.geo_point = new TLRPC.TL_inputGeoPoint(); + Location lastKnownLocation = LocationController.getInstance(currentAccount).getLastKnownLocation(); + req.media.geo_point.lat = AndroidUtilities.fixLocationCoord(lastKnownLocation.getLatitude()); + req.media.geo_point._long = AndroidUtilities.fixLocationCoord(lastKnownLocation.getLongitude()); + req.media.geo_point.accuracy_radius = (int) lastKnownLocation.getAccuracy(); + if (req.media.geo_point.accuracy_radius != 0) { + req.media.geo_point.flags |= 1; + } + if (info.lastSentProximityMeters != info.proximityMeters) { + req.media.proximity_notification_radius = info.proximityMeters; + req.media.flags |= 8; + } + req.media.heading = LocationController.getHeading(lastKnownLocation); + req.media.flags |= 4; + req.media.period = info.period = param == 0x7FFFFFFF ? 0x7FFFFFFF : info.period + param; + info.stopTime = param == 0x7FFFFFFF ? Integer.MAX_VALUE : info.stopTime + param; + req.media.flags |= 2; + if (info.messageObject != null && info.messageObject.messageOwner != null && info.messageObject.messageOwner.media != null) { + info.messageObject.messageOwner.media.period = info.period; +// ArrayList messages = new ArrayList<>(); +// messages.add(info.messageObject.messageOwner); + getMessagesStorage().replaceMessageIfExists(info.messageObject.messageOwner, null, null, true); + } + getConnectionsManager().sendRequest(req, null); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.liveLocationsChanged); + } + return; + } + shareLiveLocation(user, param, proximityRadius); + }, null)); } private void shareLiveLocation(TLRPC.User user, int period, int radius) { @@ -1724,11 +1776,11 @@ private Bitmap createPlaceBitmap(int num) { try { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(0xffffffff); - Bitmap bitmap = Bitmap.createBitmap(AndroidUtilities.dp(12), AndroidUtilities.dp(12), Bitmap.Config.ARGB_8888); + Bitmap bitmap = Bitmap.createBitmap(dp(12), dp(12), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); - canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); + canvas.drawCircle(dp(6), dp(6), dp(6), paint); paint.setColor(LocationCell.getColorForIndex(num)); - canvas.drawCircle(AndroidUtilities.dp(6), AndroidUtilities.dp(6), AndroidUtilities.dp(5), paint); + canvas.drawCircle(dp(6), dp(6), dp(5), paint); canvas.setBitmap(null); return bitmapCache[num % 7] = bitmap; } catch (Throwable e) { @@ -1931,7 +1983,7 @@ private void onMapInit() { if (view != null) { RecyclerView.ViewHolder holder = listView.findContainingViewHolder(view); if (holder != null && holder.getAdapterPosition() == 0) { - int min = locationType == LOCATION_TYPE_SEND ? 0 : AndroidUtilities.dp(66); + int min = locationType == LOCATION_TYPE_SEND ? 0 : dp(66); int top = view.getTop(); if (top < -min) { IMapsProvider.CameraPosition cameraPosition = map.getCameraPosition(); @@ -2092,7 +2144,7 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { } if (mapViewClip != null) { - mapViewClip.addView(mapView.getView(), 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); + mapViewClip.addView(mapView.getView(), 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + dp(10), Gravity.TOP | Gravity.LEFT)); if (overlayView != null) { try { if (overlayView.getParent() instanceof ViewGroup) { @@ -2102,7 +2154,7 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { } catch (Exception ignore) { } - mapViewClip.addView(overlayView, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); + mapViewClip.addView(overlayView, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + dp(10), Gravity.TOP | Gravity.LEFT)); } updateClipView(false); maybeShowProximityHint(); @@ -2122,11 +2174,11 @@ private void maybeShowProximityHint() { preferences.edit().putInt("proximityhint", ++val).commit(); if (DialogObject.isUserDialog(dialogId)) { TLRPC.User user = getMessagesController().getUser(dialogId); - hintView.setOverrideText(LocaleController.formatString("ProximityTooltioUser", R.string.ProximityTooltioUser, UserObject.getFirstName(user))); + hintView.setText(LocaleController.formatString("ProximityTooltioUser", R.string.ProximityTooltioUser, UserObject.getFirstName(user))); } else { - hintView.setOverrideText(LocaleController.getString("ProximityTooltioGroup", R.string.ProximityTooltioGroup)); + hintView.setText(LocaleController.getString("ProximityTooltioGroup", R.string.ProximityTooltioGroup)); } - hintView.showForView(proximityButton, true); + hintView.show(); } } @@ -2139,8 +2191,8 @@ private void showResults() { return; } View child = listView.getChildAt(0); - int offset = AndroidUtilities.dp(258) + child.getTop(); - if (offset < 0 || offset > AndroidUtilities.dp(258)) { + int offset = dp(258) + child.getTop(); + if (offset < 0 || offset > dp(258)) { return; } listView.smoothScrollBy(0, offset); @@ -2181,31 +2233,31 @@ private void updateClipView(boolean fromLayout) { if (overlayView != null) { overlayView.setTranslationY(Math.max(0, -top / 2)); } - float translationY = Math.min(overScrollHeight - mapTypeButton.getMeasuredHeight() - AndroidUtilities.dp(64 + (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE ? 30 : 10)), -top); + float translationY = Math.min(overScrollHeight - mapTypeButton.getMeasuredHeight() - dp(64 + (locationType == LOCATION_TYPE_SEND || locationType == LOCATION_TYPE_SEND_WITH_LIVE ? 30 : 10)), -top); mapTypeButton.setTranslationY(translationY); proximityButton.setTranslationY(translationY); if (hintView != null) { - hintView.setExtraTranslationY(translationY); + hintView.setTranslationY(translationY); } if (searchAreaButton != null) { searchAreaButton.setTranslation(translationY); } if (markerImageView != null) { - markerImageView.setTranslationY(markerTop = -top - AndroidUtilities.dp(markerImageView.getTag() == null ? 48 : 69) + height / 2); + markerImageView.setTranslationY(markerTop = -top - dp(markerImageView.getTag() == null ? 48 : 69) + height / 2); } if (!fromLayout) { layoutParams = (FrameLayout.LayoutParams) mapView.getView().getLayoutParams(); - if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + if (layoutParams != null && layoutParams.height != overScrollHeight + dp(10)) { + layoutParams.height = overScrollHeight + dp(10); if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } mapView.getView().setLayoutParams(layoutParams); } if (overlayView != null) { layoutParams = (FrameLayout.LayoutParams) overlayView.getLayoutParams(); - if (layoutParams != null && layoutParams.height != overScrollHeight + AndroidUtilities.dp(10)) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + if (layoutParams != null && layoutParams.height != overScrollHeight + dp(10)) { + layoutParams.height = overScrollHeight + dp(10); overlayView.setLayoutParams(layoutParams); } } @@ -2221,11 +2273,11 @@ private void fixLayoutInternal(final boolean resume) { return; } if (locationType == LOCATION_TYPE_LIVE_VIEW) { - overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; + overScrollHeight = viewHeight - dp(66) - height; } else if (locationType == 2) { - overScrollHeight = viewHeight - AndroidUtilities.dp(66 + 7) - height; + overScrollHeight = viewHeight - dp(66 + 7) - height; } else { - overScrollHeight = viewHeight - AndroidUtilities.dp(66) - height; + overScrollHeight = viewHeight - dp(66) - height; } FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); @@ -2244,16 +2296,16 @@ private void fixLayoutInternal(final boolean resume) { adapter.setOverScrollHeight(overScrollHeight); layoutParams = (FrameLayout.LayoutParams) mapView.getView().getLayoutParams(); if (layoutParams != null) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + layoutParams.height = overScrollHeight + dp(10); if (map != null) { - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), AndroidUtilities.dp(10)); + map.setPadding(dp(70), 0, dp(70), dp(10)); } mapView.getView().setLayoutParams(layoutParams); } if (overlayView != null) { layoutParams = (FrameLayout.LayoutParams) overlayView.getLayoutParams(); if (layoutParams != null) { - layoutParams.height = overScrollHeight + AndroidUtilities.dp(10); + layoutParams.height = overScrollHeight + dp(10); overlayView.setLayoutParams(layoutParams); } } @@ -2268,10 +2320,10 @@ private void fixLayoutInternal(final boolean resume) { } else { top = 0; } - layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); + layoutManager.scrollToPositionWithOffset(0, -dp(top)); updateClipView(false); listView.post(() -> { - layoutManager.scrollToPositionWithOffset(0, -AndroidUtilities.dp(top)); + layoutManager.scrollToPositionWithOffset(0, -dp(top)); updateClipView(false); }); } else { @@ -2416,7 +2468,7 @@ public void onAnimationEnd(Animator animation) { } if (builder != null) { if (firstFocus) { - listView.smoothScrollBy(0, AndroidUtilities.dp(66 * 1.5f)); + listView.smoothScrollBy(0, dp(66 * 1.5f)); } firstFocus = false; adapter.setLiveLocations(markers); @@ -2431,7 +2483,7 @@ public void onAnimationEnd(Animator animation) { bounds = builder.build(); if (messages.size() > 1) { try { - moveToBounds = ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, AndroidUtilities.dp(80 + 33)); + moveToBounds = ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, dp(80 + 33)); map.moveCamera(moveToBounds); moveToBounds = null; } catch (Exception e) { @@ -2459,8 +2511,8 @@ private void moveToBounds(int radius, boolean self, boolean animated) { builder.include(northEast); bounds = builder.build(); try { - int height = (int) (proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(40) + mapViewClip.getTranslationY()); - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + int height = (int) (proximitySheet.getCustomView().getMeasuredHeight() - dp(40) + mapViewClip.getTranslationY()); + map.setPadding(dp(70), 0, dp(70), height); if (animated) { map.animateCamera(ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, 0), 500, null); } else { @@ -2490,8 +2542,8 @@ private void moveToBounds(int radius, boolean self, boolean animated) { builder.include(northEast); bounds = builder.build(); try { - int height = proximitySheet.getCustomView().getMeasuredHeight() - AndroidUtilities.dp(100); - map.setPadding(AndroidUtilities.dp(70), 0, AndroidUtilities.dp(70), height); + int height = proximitySheet.getCustomView().getMeasuredHeight() - dp(100); + map.setPadding(dp(70), 0, dp(70), height); map.moveCamera(ApplicationLoader.getMapsProvider().newCameraUpdateLatLngBounds(bounds, 0)); } catch (Exception e) { FileLog.e(e); @@ -2597,6 +2649,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.liveLocationsChanged) { if (adapter != null) { + adapter.notifyDataSetChanged(); adapter.updateLiveLocationCell(); } } else if (id == NotificationCenter.didReceiveNewMessages) { @@ -2816,7 +2869,7 @@ protected boolean disablePermissionCheck() { @Override public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 30) { - openShareLiveLocation(askWithRadius); + openShareLiveLocation(false, askWithRadius); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index acbcbbc0b2..cfb366ce84 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -8,6 +8,11 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.replaceArrows; +import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -18,6 +23,7 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; +import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -42,6 +48,7 @@ import android.os.Bundle; import android.os.Looper; import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; import android.text.Editable; import android.text.InputFilter; import android.text.InputType; @@ -154,6 +161,7 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; +import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.SimpleThemeDescription; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.SlideView; @@ -206,7 +214,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AUTH_TYPE_FLASH_CALL = 3, AUTH_TYPE_CALL = 4, AUTH_TYPE_MISSED_CALL = 11, - AUTH_TYPE_FRAGMENT_SMS = 15; + AUTH_TYPE_FRAGMENT_SMS = 15, + AUTH_TYPE_WORD = 16, + AUTH_TYPE_PHRASE = 17; private final static int MODE_LOGIN = 0, MODE_CANCEL_ACCOUNT_DELETION = 1, @@ -229,7 +239,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No VIEW_ADD_EMAIL = 12, VIEW_CODE_EMAIL_SETUP = 13, VIEW_CODE_EMAIL = 14, - VIEW_CODE_FRAGMENT_SMS = 15; + VIEW_CODE_FRAGMENT_SMS = 15, + VIEW_CODE_WORD = 16, + VIEW_CODE_PHRASE = 17; public final static int COUNTRY_STATE_NOT_SET_OR_VALID = 0, COUNTRY_STATE_EMPTY = 1, @@ -242,7 +254,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AUTH_TYPE_FLASH_CALL, AUTH_TYPE_CALL, AUTH_TYPE_MISSED_CALL, - AUTH_TYPE_FRAGMENT_SMS + AUTH_TYPE_FRAGMENT_SMS, + AUTH_TYPE_PHRASE, + AUTH_TYPE_WORD }) public @interface AuthType {} @@ -273,7 +287,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No VIEW_ADD_EMAIL, VIEW_CODE_EMAIL_SETUP, VIEW_CODE_EMAIL, - VIEW_CODE_FRAGMENT_SMS + VIEW_CODE_FRAGMENT_SMS, + VIEW_CODE_WORD, + VIEW_CODE_PHRASE }) private @interface ViewNumber {} @@ -286,7 +302,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @ViewNumber private int currentViewNum; - private SlideView[] views = new SlideView[16]; + private SlideView[] views = new SlideView[18]; private CustomPhoneKeyboardView keyboardView; private ValueAnimator keyboardAnimator; @@ -510,8 +526,15 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateConnectionState); } + private View cachedFragmentView; @Override public View createView(Context context) { + if (cachedFragmentView != null) { + fragmentView = cachedFragmentView; + cachedFragmentView = null; + return fragmentView; + } + actionBar.setAddToContainer(false); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -645,6 +668,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { views[VIEW_CODE_EMAIL_SETUP] = new LoginActivityEmailCodeView(context, true); views[VIEW_CODE_EMAIL] = new LoginActivityEmailCodeView(context, false); views[VIEW_CODE_FRAGMENT_SMS] = new LoginActivitySmsView(context, AUTH_TYPE_FRAGMENT_SMS); + views[VIEW_CODE_WORD] = new LoginActivityPhraseView(context, AUTH_TYPE_WORD); + views[VIEW_CODE_PHRASE] = new LoginActivityPhraseView(context, AUTH_TYPE_PHRASE); for (int a = 0; a < views.length; a++) { views[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE); @@ -696,6 +721,7 @@ public void getOutline(View view, Outline outline) { } floatingAutoAnimator = VerticalPositionAutoAnimator.attach(floatingButtonContainer); sizeNotifierFrameLayout.addView(floatingButtonContainer, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 24, 16)); +// ScaleStateListAnimator.apply(floatingButtonContainer, .1f, 1.4f); floatingButtonContainer.setOnClickListener(view -> onDoneButtonPressed()); floatingAutoAnimator.addUpdateListener((animation, value, velocity) -> { if (phoneNumberConfirmView != null) { @@ -710,7 +736,7 @@ public void getOutline(View view, Outline outline) { finishFragment(); } }); - backButtonView.setContentDescription(LocaleController.getString(R.string.Back)); + backButtonView.setContentDescription(getString(R.string.Back)); int padding = AndroidUtilities.dp(4); backButtonView.setPadding(padding, padding, padding, padding); sizeNotifierFrameLayout.addView(backButtonView, LayoutHelper.createFrame(32, 32, Gravity.LEFT | Gravity.TOP, 16, 16, 0, 0)); @@ -775,7 +801,7 @@ public void getOutline(View view, Outline outline) { floatingButtonIcon.setTransformType(TransformableLoginButtonView.TRANSFORM_OPEN_ARROW); floatingButtonIcon.setProgress(1f); floatingButtonIcon.setDrawBackground(false); - floatingButtonContainer.setContentDescription(LocaleController.getString("Done", R.string.Done)); + floatingButtonContainer.setContentDescription(getString("Done", R.string.Done)); floatingButtonContainer.addView(floatingButtonIcon, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60)); floatingProgressView = new RadialProgressView(context); @@ -945,6 +971,10 @@ public void onResume() { AndroidUtilities.hideKeyboard(fragmentView); AndroidUtilities.requestAltFocusable(getParentActivity(), classGuid); } + + if (currentViewNum >= 0 && currentViewNum < views.length) { + views[currentViewNum].onResume(); + } } @Override @@ -1132,7 +1162,7 @@ private void needShowAlert(String title, String text) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(title); builder.setMessage(text); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); showDialog(builder.create()); } @@ -1197,8 +1227,8 @@ public static void needShowInvalidAlert(BaseFragment fragment, String phoneNumbe } AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity()); if (banned) { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString("BannedPhoneNumber", R.string.BannedPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString("BannedPhoneNumber", R.string.BannedPhoneNumber)); } else { if (inputData != null && inputData.patterns != null && !inputData.patterns.isEmpty() && inputData.country != null) { int patternLength = Integer.MAX_VALUE; @@ -1209,18 +1239,18 @@ public static void needShowInvalidAlert(BaseFragment fragment, String phoneNumbe } } if (PhoneFormat.stripExceptNumbers(phoneNumber).length() - inputData.country.code.length() < patternLength) { - builder.setTitle(LocaleController.getString(R.string.WrongNumberFormat)); + builder.setTitle(getString(R.string.WrongNumberFormat)); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ShortNumberInfo", R.string.ShortNumberInfo, inputData.country.name, inputData.phoneNumber))); } else { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString(R.string.InvalidPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString(R.string.InvalidPhoneNumber)); } } else { - builder.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder.setMessage(LocaleController.getString(R.string.InvalidPhoneNumber)); + builder.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder.setMessage(getString(R.string.InvalidPhoneNumber)); } } - builder.setNeutralButton(LocaleController.getString("BotHelp", R.string.BotHelp), (dialog, which) -> { + builder.setNeutralButton(getString("BotHelp", R.string.BotHelp), (dialog, which) -> { try { PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); String version = String.format(Locale.US, "%s (%d)", pInfo.versionName, pInfo.versionCode); @@ -1238,13 +1268,13 @@ public static void needShowInvalidAlert(BaseFragment fragment, String phoneNumbe fragment.getParentActivity().startActivity(Intent.createChooser(mailer, "Send email...")); } catch (Exception e) { AlertDialog.Builder builder2 = new AlertDialog.Builder(fragment.getParentActivity()); - builder2.setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)); - builder2.setMessage(LocaleController.getString("NoMailInstalled", R.string.NoMailInstalled)); - builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder2.setTitle(getString(R.string.RestorePasswordNoEmailTitle)); + builder2.setMessage(getString("NoMailInstalled", R.string.NoMailInstalled)); + builder2.setPositiveButton(getString("OK", R.string.OK), null); fragment.showDialog(builder2.create()); } }); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); fragment.showDialog(builder.create()); } @@ -1360,10 +1390,10 @@ private void onDoneButtonPressed() { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("StopLoadingTitle", R.string.StopLoadingTitle)); - builder.setMessage(LocaleController.getString("StopLoading", R.string.StopLoading)); - builder.setPositiveButton(LocaleController.getString("WaitMore", R.string.WaitMore), null); - builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { + builder.setTitle(getString("StopLoadingTitle", R.string.StopLoadingTitle)); + builder.setMessage(getString("StopLoading", R.string.StopLoading)); + builder.setPositiveButton(getString("WaitMore", R.string.WaitMore), null); + builder.setNegativeButton(getString("Stop", R.string.Stop), (dialogInterface, i) -> { views[currentViewNum].onCancelPressed(); needHideProgress(true); }); @@ -1557,7 +1587,7 @@ private void needHideProgress(boolean cancel, boolean animated) { public void setPage(@ViewNumber int page, boolean animated, Bundle params, boolean back) { boolean needFloatingButton = page == VIEW_PHONE_INPUT || page == VIEW_REGISTER || page == VIEW_PASSWORD || - page == VIEW_NEW_PASSWORD_STAGE_1 || page == VIEW_NEW_PASSWORD_STAGE_2 || page == VIEW_ADD_EMAIL; + page == VIEW_NEW_PASSWORD_STAGE_1 || page == VIEW_NEW_PASSWORD_STAGE_2 || page == VIEW_ADD_EMAIL || page == VIEW_CODE_PHRASE || page == VIEW_CODE_WORD; if (page == currentViewNum) { animated = false; } @@ -1662,11 +1692,13 @@ private void needFinishActivity(boolean afterSignup, boolean showSetPasswordConf if (getParentActivity() instanceof LaunchActivity) { if (newAccount) { newAccount = false; + pendingSwitchingAccount = true; ((LaunchActivity) getParentActivity()).switchToAccount(currentAccount, false, obj -> { Bundle args = new Bundle(); args.putBoolean("afterSignup", afterSignup); return new DialogsActivity(args); }); + pendingSwitchingAccount = false; finishFragment(); } else { @@ -1691,10 +1723,18 @@ private void needFinishActivity(boolean afterSignup, boolean showSetPasswordConf } } + private void fakeSuccess() { + TLRPC.TL_auth_authorization res = new TLRPC.TL_auth_authorization(); + res.user = UserConfig.getInstance(0).getCurrentUser(); + onAuthSuccess(res); + } + private void onAuthSuccess(TLRPC.TL_auth_authorization res) { onAuthSuccess(res, false); } + private boolean pendingSwitchingAccount; + private void onAuthSuccess(TLRPC.TL_auth_authorization res, boolean afterSignup) { BackButtonMenuRecent.clearRecentDialogs(currentAccount); PasscodeHelper.removePasscodeForAccount(currentAccount); @@ -1758,9 +1798,9 @@ private void resendCodeFromSafetyNet(Bundle params, TLRPC.auth_SentCode res) { return; } new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString(R.string.SafetyNetErrorOccurred)) - .setPositiveButton(LocaleController.getString(R.string.OK), (dialog, which) -> { + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString(R.string.SafetyNetErrorOccurred)) + .setPositiveButton(getString(R.string.OK), (dialog, which) -> { forceDisableSafetyNet = true; if (currentViewNum != VIEW_PHONE_INPUT) { setPage(VIEW_PHONE_INPUT, true, null, true); @@ -1859,7 +1899,7 @@ private void fillNextCodeParams(Bundle params, TLRPC.auth_SentCode res, boolean setPage(VIEW_CODE_MESSAGE, animate, params, false); } else { if (res.timeout == 0) { - res.timeout = 60; + res.timeout = BuildVars.DEBUG_PRIVATE_VERSION ? 5 : 60; } params.putInt("timeout", res.timeout * 1000); if (res.type instanceof TLRPC.TL_auth_sentCodeTypeCall) { @@ -1896,6 +1936,16 @@ private void fillNextCodeParams(Bundle params, TLRPC.auth_SentCode res, boolean params.putInt("resetAvailablePeriod", res.type.reset_available_period); params.putInt("resetPendingDate", res.type.reset_pending_date); setPage(VIEW_CODE_EMAIL, animate, params, false); + } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + if (res.type.beginning != null) { + params.putString("beginning", res.type.beginning); + } + setPage(VIEW_CODE_WORD, animate, params, false); + } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + if (res.type.beginning != null) { + params.putString("beginning", res.type.beginning); + } + setPage(VIEW_CODE_PHRASE, animate, params, false); } } } @@ -1939,14 +1989,14 @@ public PhoneView(Context context) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneNewNumber : R.string.YourNumber)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneNewNumber : R.string.YourNumber)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 0, 32, 0)); subtitleView = new TextView(context); - subtitleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneHelp : R.string.StartText)); + subtitleView.setText(getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneHelp : R.string.StartText)); subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setGravity(Gravity.CENTER); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -1980,11 +2030,11 @@ public PhoneView(Context context) { countryButtonLinearLayout.addView(chevronRight, LayoutHelper.createLinearRelatively(24, 24, 0, 0, 0, 14, 0)); countryOutlineView = new OutlineTextContainerView(context); - countryOutlineView.setText(LocaleController.getString(R.string.Country)); + countryOutlineView.setText(getString(R.string.Country)); countryOutlineView.addView(countryButtonLinearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 0, 0)); countryOutlineView.setForceUseCenter(true); countryOutlineView.setFocusable(true); - countryOutlineView.setContentDescription(LocaleController.getString(R.string.Country)); + countryOutlineView.setContentDescription(getString(R.string.Country)); countryOutlineView.setOnFocusChangeListener((v, hasFocus) -> countryOutlineView.animateSelection(hasFocus ? 1 : 0)); addView(countryOutlineView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 58, 16, 24, 16, 14)); countryOutlineView.setOnClickListener(view -> { @@ -2003,7 +2053,7 @@ public PhoneView(Context context) { phoneOutlineView = new OutlineTextContainerView(context); phoneOutlineView.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 8, 16, 8)); - phoneOutlineView.setText(LocaleController.getString(R.string.PhoneNumber)); + phoneOutlineView.setText(getString(R.string.PhoneNumber)); addView(phoneOutlineView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 58, 16, 8, 16, 8)); plusTextView = new TextView(context); @@ -2036,7 +2086,7 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { codeField.setShowSoftInputOnFocus(!(hasCustomKeyboard() && !isCustomKeyboardForceDisabled())); } - codeField.setContentDescription(LocaleController.getString(R.string.LoginAccessibilityCountryCode)); + codeField.setContentDescription(getString(R.string.LoginAccessibilityCountryCode)); linearLayout.addView(codeField, LayoutHelper.createLinear(55, 36, -9, 0, 0, 0)); codeField.addTextChangedListener(new TextWatcher() { @Override @@ -2209,7 +2259,7 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc keyboardView.setDispatchBackWhenEmpty(true); if (countryState == COUNTRY_STATE_INVALID) { - setCountryButtonText(LocaleController.getString(R.string.WrongCountry)); + setCountryButtonText(getString(R.string.WrongCountry)); } } else { if (countryState == COUNTRY_STATE_INVALID) { @@ -2231,7 +2281,7 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { phoneField.setShowSoftInputOnFocus(!(hasCustomKeyboard() && !isCustomKeyboardForceDisabled())); } - phoneField.setContentDescription(LocaleController.getString(R.string.PhoneNumber)); + phoneField.setContentDescription(getString(R.string.PhoneNumber)); linearLayout.addView(phoneField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36)); phoneField.addTextChangedListener(new TextWatcher() { @@ -2359,7 +2409,7 @@ public void afterTextChanged(Editable s) { int bottomMargin = 72; if (newAccount && activityMode == MODE_LOGIN) { syncContactsBox = new CheckBoxCell(context, 2); - syncContactsBox.setText(LocaleController.getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); + syncContactsBox.setText(getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); addView(syncContactsBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); bottomMargin -= 24; syncContactsBox.setOnClickListener(v -> { @@ -2370,16 +2420,16 @@ public void afterTextChanged(Editable s) { syncContacts = !syncContacts; cell.setChecked(syncContacts, true); if (syncContacts) { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, LocaleController.getString("SyncContactsOn", R.string.SyncContactsOn)).show(); + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, getString("SyncContactsOn", R.string.SyncContactsOn)).show(); } else { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, LocaleController.getString("SyncContactsOff", R.string.SyncContactsOff)).show(); + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, getString("SyncContactsOff", R.string.SyncContactsOff)).show(); } }); } if (activityMode == MODE_LOGIN) { testBackendCheckBox = new CheckBoxCell(context, 2); - testBackendCheckBox.setText(LocaleController.getString(R.string.DebugTestBackend), "", testBackend, false); + testBackendCheckBox.setText(getString(R.string.DebugTestBackend), "", testBackend, false); addView(testBackendCheckBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); bottomMargin -= 24; testBackendCheckBox.setOnClickListener(v -> { @@ -2837,16 +2887,16 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { preferences.edit().putBoolean("firstlogin", false).commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); int resId; if (!allowCall && (!allowCancelCall || !allowReadCallLog)) { - builder.setMessage(LocaleController.getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); + builder.setMessage(getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); resId = R.raw.calls_log; } else if (!allowCancelCall || !allowReadCallLog) { - builder.setMessage(LocaleController.getString("AllowReadCallLog", R.string.AllowReadCallLog)); + builder.setMessage(getString("AllowReadCallLog", R.string.AllowReadCallLog)); resId = R.raw.calls_log; } else { - builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); + builder.setMessage(getString("AllowReadCall", R.string.AllowReadCall)); resId = R.raw.incoming_calls; } builder.setTopAnimation(resId, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); @@ -2914,16 +2964,16 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { preferences.edit().putBoolean("firstlogin", false).commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); int resId; if (!allowCall && (!allowCancelCall || !allowReadCallLog)) { - builder.setMessage(LocaleController.getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); + builder.setMessage(getString("AllowReadCallAndLog", R.string.AllowReadCallAndLog)); resId = R.raw.calls_log; } else if (!allowCancelCall || !allowReadCallLog) { - builder.setMessage(LocaleController.getString("AllowReadCallLog", R.string.AllowReadCallLog)); + builder.setMessage(getString("AllowReadCallLog", R.string.AllowReadCallLog)); resId = R.raw.calls_log; } else { - builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); + builder.setMessage(getString("AllowReadCall", R.string.AllowReadCall)); resId = R.raw.incoming_calls; } builder.setTopAnimation(resId, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); @@ -2942,11 +2992,11 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { } if (countryState == COUNTRY_STATE_EMPTY) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ChooseCountry", R.string.ChooseCountry)); needHideProgress(false); return; } else if (countryState == COUNTRY_STATE_INVALID && !BuildVars.DEBUG_VERSION) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("WrongCountry", R.string.WrongCountry)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("WrongCountry", R.string.WrongCountry)); needHideProgress(false); return; } @@ -2975,15 +3025,15 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { if (PhoneNumberUtils.compare(phone, userPhone) && ConnectionsManager.getInstance(a).isTestBackend() == testBackend) { final int num = a; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString(R.string.AppName)); - builder.setMessage(LocaleController.getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); - builder.setPositiveButton(LocaleController.getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { + builder.setTitle(getString(R.string.AppName)); + builder.setMessage(getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); + builder.setPositiveButton(getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { if (UserConfig.selectedAccount != num) { ((LaunchActivity) getParentActivity()).switchToAccount(num, false); } finishFragment(); }); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + builder.setNegativeButton(getString("OK", R.string.OK), null); showDialog(builder.create()); needHideProgress(false); return; @@ -3046,11 +3096,10 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { try { String number = ""; if (!TextUtils.isEmpty(number)) { + settings.unknown_number = false; settings.current_number = PhoneNumberUtils.compare(phone, number); - if (!settings.current_number) { - settings.allow_flashcall = false; - } } else { + settings.unknown_number = true; if (UserConfig.getActivatedAccountsCount() > 0) { settings.allow_flashcall = false; } else { @@ -3058,7 +3107,7 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { } } } catch (Exception e) { - settings.allow_flashcall = false; + settings.unknown_number = true; FileLog.e(e); } } @@ -3197,7 +3246,7 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -3207,25 +3256,25 @@ private void onConfirm(PhoneNumberConfirmView confirmView) { bundle.putString("phoneFormated", phone); setPage(VIEW_PASSWORD, true, bundle, false); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else if (error.text.contains("PHONE_NUMBER_INVALID")) { needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, false); } else if (error.text.contains("PHONE_PASSWORD_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("PHONE_NUMBER_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); } else if (error.text.contains("PHONE_NUMBER_BANNED")) { needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, true); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.code != -1000) { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req, phoneInputData.phoneNumber); } @@ -3270,8 +3319,8 @@ public void fillNumber() { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTopAnimation(R.raw.incoming_calls, 46, false, Theme.getColor(Theme.key_dialogTopBackground)); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); - builder.setMessage(LocaleController.getString("AllowFillNumber", R.string.AllowFillNumber)); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); + builder.setMessage(getString("AllowFillNumber", R.string.AllowFillNumber)); permissionsShowDialog = showDialog(builder.create(), true, null); needRequestPermissions = true; } else { @@ -3388,7 +3437,7 @@ public void onShow() { @Override public String getHeaderName() { - return LocaleController.getString("YourPhone", R.string.YourPhone); + return getString("YourPhone", R.string.YourPhone); } @Override @@ -3431,6 +3480,7 @@ public class LoginActivitySmsView extends SlideView implements NotificationCente private String requestPhone; private String emailPhone; private CodeFieldContainer codeFieldContainer; + private TextView prevTypeTextView; private TextView confirmTextView; private TextView titleTextView; private ImageView blackImageView; @@ -3476,6 +3526,8 @@ public class LoginActivitySmsView extends SlideView implements NotificationCente private int currentType; @AuthType private int nextType; + @AuthType + private int prevType; private boolean isResendingCode = false; @@ -3485,6 +3537,9 @@ public class LoginActivitySmsView extends SlideView implements NotificationCente private int length; private String url; + private Bundle nextCodeParams; + private TLRPC.TL_auth_sentCode nextCodeAuth; + private boolean postedErrorColorTimeout; private Runnable errorColorTimeout = () -> { postedErrorColorTimeout = false; @@ -3510,7 +3565,7 @@ public LoginActivitySmsView(Context context, @AuthType int type) { titleTextView = new TextView(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); @@ -3522,12 +3577,12 @@ public LoginActivitySmsView(Context context, @AuthType int type) { overrideTitle = null; break; case MODE_CANCEL_ACCOUNT_DELETION: - overrideTitle = LocaleController.getString(R.string.CancelAccountReset); + overrideTitle = getString(R.string.CancelAccountReset); break; } FrameLayout centerContainer = null; if (currentType == AUTH_TYPE_MISSED_CALL) { - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString("MissedCallDescriptionTitle", R.string.MissedCallDescriptionTitle)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString("MissedCallDescriptionTitle", R.string.MissedCallDescriptionTitle)); FrameLayout frameLayout = new FrameLayout(context); missedCallArrowIcon = new ImageView(context); @@ -3545,7 +3600,7 @@ public LoginActivitySmsView(Context context, @AuthType int type) { missedCallDescriptionSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); missedCallDescriptionSubtitle.setGravity(Gravity.CENTER_HORIZONTAL); missedCallDescriptionSubtitle.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - missedCallDescriptionSubtitle.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle", R.string.MissedCallDescriptionSubtitle))); + missedCallDescriptionSubtitle.setText(AndroidUtilities.replaceTags(getString("MissedCallDescriptionSubtitle", R.string.MissedCallDescriptionSubtitle))); addView(missedCallDescriptionSubtitle, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 16, 36, 0)); @@ -3561,7 +3616,7 @@ protected void processNextPressed() { prefixTextView = new TextView(context); prefixTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); prefixTextView.setMaxLines(1); - prefixTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + prefixTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); prefixTextView.setPadding(0, 0, 0, 0); prefixTextView.setGravity(Gravity.CENTER_VERTICAL); @@ -3574,7 +3629,7 @@ protected void processNextPressed() { missedCallDescriptionSubtitle2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); missedCallDescriptionSubtitle2.setGravity(Gravity.CENTER_HORIZONTAL); missedCallDescriptionSubtitle2.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - missedCallDescriptionSubtitle2.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); + missedCallDescriptionSubtitle2.setText(AndroidUtilities.replaceTags(getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); addView(missedCallDescriptionSubtitle2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 28, 36, 12)); } else if (currentType == AUTH_TYPE_FLASH_CALL) { @@ -3597,7 +3652,7 @@ protected void processNextPressed() { blueImageView.setAnimation(hintDrawable); frameLayout.addView(blueImageView, LayoutHelper.createFrame(64, 64)); - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString(R.string.YourCode)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString(R.string.YourCode)); innerLinearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 0)); innerLinearLayout.addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 8, 0, 0)); } else { @@ -3622,7 +3677,7 @@ protected void processNextPressed() { blueImageView.setTranslationY(-AndroidUtilities.dp(24)); } frameLayout.addView(blueImageView, LayoutHelper.createFrame(size, size, Gravity.LEFT | Gravity.TOP, 0, 0, 0, currentType == AUTH_TYPE_MESSAGE && !AndroidUtilities.isSmallScreen() ? -AndroidUtilities.dp(16) : 0)); - titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString(currentType == AUTH_TYPE_MESSAGE ? R.string.SentAppCodeTitle : R.string.SentSmsCodeTitle)); + titleTextView.setText(overrideTitle != null ? overrideTitle : getString(currentType == AUTH_TYPE_MESSAGE ? R.string.SentAppCodeTitle : R.string.SentSmsCodeTitle)); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 18, 0, 0)); int sideMargin = currentType == AUTH_TYPE_FRAGMENT_SMS ? 16 : 0; addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, sideMargin, 17, sideMargin, 0)); @@ -3641,19 +3696,34 @@ protected void processNextPressed() { codeFieldContainer.setVisibility(GONE); } + prevTypeTextView = new LoadingTextView(context); + prevTypeTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + prevTypeTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + prevTypeTextView.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + prevTypeTextView.setOnClickListener(v -> onBackPressed(true)); + addView(prevTypeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + prevTypeTextView.setVisibility(View.GONE); + problemFrame = new FrameLayout(context); timeText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } @Override protected boolean isRippleEnabled() { return getVisibility() == View.VISIBLE && !(time > 0 && timeTimer != null); } }; + timeText.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); timeText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - timeText.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - timeText.setOnClickListener(v-> { + timeText.setGravity(Gravity.TOP | Gravity.LEFT); + timeText.setOnClickListener(v -> { // if (isRequestingFirebaseSms || isResendingCode) { // return; // } @@ -3664,17 +3734,18 @@ protected boolean isRippleEnabled() { timeText.invalidate(); timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { // timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { - timeText.setText(LocaleController.getString("Calling", R.string.Calling)); + timeText.setText(getString(R.string.Calling)); } else { - timeText.setText(LocaleController.getString("SendingSms", R.string.SendingSms)); + timeText.setText(getString(R.string.SendingSms)); } Bundle params = new Bundle(); params.putString("phone", phone); params.putString("ephone", emailPhone); params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); createCodeTimer(); TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); @@ -3682,7 +3753,16 @@ protected boolean isRippleEnabled() { req.phone_code_hash = phoneHash; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { - AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response)); + AndroidUtilities.runOnUIThread(() -> { + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + nextType = AUTH_TYPE_PHRASE; + } else if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + nextType = AUTH_TYPE_WORD; + } + fillNextCodeParams(nextCodeParams, nextCodeAuth); + }); } else if (error != null && error.text != null) { AndroidUtilities.runOnUIThread(() -> lastError = error.text); } @@ -3714,6 +3794,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { errorViewSwitcher.setOutAnimation(anim); problemText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } @Override protected boolean isRippleEnabled() { return isClickable() && getVisibility() == View.VISIBLE && !(nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode); @@ -3753,7 +3837,7 @@ protected boolean isRippleEnabled() { openFragmentButton.addView(openFragmentImageView, LayoutHelper.createLinear(36, 36, Gravity.CENTER_VERTICAL, 0, 0, 2, 0)); openFragmentButtonText = new TextView(context); - openFragmentButtonText.setText(LocaleController.getString(R.string.OpenFragment)); + openFragmentButtonText.setText(getString(R.string.OpenFragment)); openFragmentButtonText.setTextColor(Color.WHITE); openFragmentButtonText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); openFragmentButtonText.setGravity(Gravity.CENTER); @@ -3762,7 +3846,7 @@ protected boolean isRippleEnabled() { } wrongCode = new TextView(context); - wrongCode.setText(LocaleController.getString("WrongCode", R.string.WrongCode)); + wrongCode.setText(getString(R.string.WrongCode)); wrongCode.setLineSpacing(AndroidUtilities.dp(2), 1.0f); wrongCode.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); wrongCode.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); @@ -3780,6 +3864,10 @@ protected boolean isRippleEnabled() { if (currentType != AUTH_TYPE_FRAGMENT_SMS) { problemText.setOnClickListener(v -> { + if (nextCodeParams != null && nextCodeAuth != null) { + fillNextCodeParams(nextCodeParams, nextCodeAuth); + return; + } if (nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode) { return; } @@ -3790,10 +3878,29 @@ protected boolean isRippleEnabled() { } resendCode(); } else { + TLRPC.TL_auth_reportMissingCode req = new TLRPC.TL_auth_reportMissingCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + req.mnc = ""; + String networkOperator = null; + try { + TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); + networkOperator = tm.getNetworkOperator(); + if (!TextUtils.isEmpty(networkOperator)) { + final String mcc = networkOperator.substring(0, 3); + final String mnc = networkOperator.substring(3); +// req.mcc = mcc; + req.mnc = mnc; + } + } catch (Exception e) { + FileLog.e(e); + } + String finalNetworkOperator = networkOperator; + getConnectionsManager().sendRequest(req, null, ConnectionsManager.RequestFlagWithoutLogin); new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("DidNotGetTheCodeInfo", R.string.DidNotGetTheCodeInfo, phone))) - .setNeutralButton(LocaleController.getString(R.string.DidNotGetTheCodeHelpButton), (dialog, which) -> { + .setNeutralButton(getString(R.string.DidNotGetTheCodeHelpButton), (dialog, which) -> { try { PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); String version = String.format(Locale.US, "%s (%d)", pInfo.versionName, pInfo.versionCode); @@ -3802,14 +3909,14 @@ protected boolean isRippleEnabled() { mailer.setData(Uri.parse("mailto:")); mailer.putExtra(Intent.EXTRA_EMAIL, new String[]{"sms@telegram.org"}); mailer.putExtra(Intent.EXTRA_SUBJECT, "Android registration/login issue " + version + " " + emailPhone); - mailer.putExtra(Intent.EXTRA_TEXT, "Phone: " + requestPhone + "\nApp version: " + version + "\nOS version: SDK " + Build.VERSION.SDK_INT + "\nDevice Name: " + Build.MANUFACTURER + Build.MODEL + "\nLocale: " + Locale.getDefault() + "\nError: " + lastError); + mailer.putExtra(Intent.EXTRA_TEXT, "Phone: " + requestPhone + "\nApp version: " + version + "\nOS version: SDK " + Build.VERSION.SDK_INT + "\nDevice Name: " + Build.MANUFACTURER + Build.MODEL + (finalNetworkOperator != null ? "\nOperator: " + finalNetworkOperator : "") + "\nLocale: " + Locale.getDefault() + "\nError: " + lastError); getContext().startActivity(Intent.createChooser(mailer, "Send email...")); } catch (Exception e) { - needShowAlert(LocaleController.getString(R.string.NekoX), LocaleController.getString("NoMailInstalled", R.string.NoMailInstalled)); + needShowAlert(getString(R.string.NekoX), getString("NoMailInstalled", R.string.NoMailInstalled)); } }) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.DidNotGetTheCodeEditNumberButton), (dialog, which) -> setPage(VIEW_PHONE_INPUT, true, null, true)) + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.DidNotGetTheCodeEditNumberButton), (dialog, which) -> setPage(VIEW_PHONE_INPUT, true, null, true)) .show(); } }); @@ -3882,6 +3989,7 @@ private void resendCode() { params.putString("phone", phone); params.putString("ephone", emailPhone); params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); nextPressed = true; @@ -3891,21 +3999,28 @@ private void resendCode() { int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { nextPressed = false; if (error == null) { - fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsPhrase) { + nextType = AUTH_TYPE_PHRASE; + } else if (nextCodeAuth.type instanceof TLRPC.TL_auth_sentCodeTypeSmsWord) { + nextType = AUTH_TYPE_WORD; + } + fillNextCodeParams(nextCodeParams, nextCodeAuth); } else { if (error.text != null) { if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); } else if (error.code != -1000) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); } } } @@ -3991,7 +4106,7 @@ public String getHeaderName() { if (currentType == AUTH_TYPE_FLASH_CALL || currentType == AUTH_TYPE_MISSED_CALL) { return phone; } else { - return LocaleController.getString("YourCode", R.string.YourCode); + return getString("YourCode", R.string.YourCode); } } @@ -4003,6 +4118,23 @@ public boolean needBackButton() { @Override public void setParams(Bundle params, boolean restore) { if (params == null) { + if (nextCodeParams != null && nextCodeAuth != null) { + setProblemTextVisible(true); + timeText.setVisibility(GONE); + if (problemText != null) { + problemText.setVisibility(VISIBLE); + problemText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + int resId; + if (nextType == AUTH_TYPE_PHRASE) { + resId = R.string.ReturnEnteringPhrase; + } else if (nextType == AUTH_TYPE_WORD) { + resId = R.string.ReturnEnteringWord; + } else { + resId = R.string.ReturnEnteringSMS; + } + problemText.setText(AndroidUtilities.replaceArrows(getString(resId), true, dp(1), dp(1))); + } + } return; } waitingForEvent = true; @@ -4032,11 +4164,15 @@ public void setParams(Bundle params, boolean restore) { pattern = params.getString("pattern"); prefix = params.getString("prefix"); length = params.getInt("length"); + prevType = params.getInt("prevType", 0); if (length == 0) { length = 5; } url = params.getString("url"); + nextCodeParams = null; + nextCodeAuth = null; + codeFieldContainer.setNumbersCount(length, currentType); for (CodeNumberField f : codeFieldContainer.codeField) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -4066,6 +4202,16 @@ public void afterTextChanged(Editable s) {} }); } + if (prevType == AUTH_TYPE_PHRASE) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringPhrase), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_WORD) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringWord), true, dp(-1), dp(1))); + } else { + prevTypeTextView.setVisibility(View.GONE); + } + if (progressView != null) { progressView.setVisibility(nextType != 0 ? VISIBLE : GONE); } @@ -4106,16 +4252,16 @@ public void afterTextChanged(Editable s) {} if (currentType != AUTH_TYPE_FRAGMENT_SMS) { if (currentType == AUTH_TYPE_MESSAGE) { if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { - problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone)); + problemText.setText(getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone)); } else if (nextType == AUTH_TYPE_FRAGMENT_SMS) { - problemText.setText(LocaleController.getString("DidNotGetTheCodeFragment", R.string.DidNotGetTheCodeFragment)); + problemText.setText(getString("DidNotGetTheCodeFragment", R.string.DidNotGetTheCodeFragment)); } else if (nextType == 0) { - problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); + problemText.setText(getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); } else { - problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); + problemText.setText(getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); } } else { - problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); + problemText.setText(getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); } } @@ -4137,13 +4283,13 @@ public void afterTextChanged(Editable s) {} problemText.setVisibility(VISIBLE); } } else if (currentType == AUTH_TYPE_FLASH_CALL) { - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { setProblemTextVisible(false); timeText.setVisibility(VISIBLE); problemText.setVisibility(GONE); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); } } @@ -4152,11 +4298,15 @@ public void afterTextChanged(Editable s) {} onNextPressed(callLogNumber); } else if (catchedPhone != null) { onNextPressed(catchedPhone); - } else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + } else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { createTimer(); } - } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { - timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 2, 0)); + } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { + if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { + timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); + } else { + timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 2, 0)); + } setProblemTextVisible(time < 1000); timeText.setVisibility(time < 1000 ? GONE : VISIBLE); if (problemText != null) { @@ -4180,7 +4330,7 @@ public void afterTextChanged(Editable s) {} } else { createTimer(); } - } else if (currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + } else if (currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 2, 0)); setProblemTextVisible(time < 1000); timeText.setVisibility(time < 1000 ? GONE : VISIBLE); @@ -4189,13 +4339,13 @@ public void afterTextChanged(Editable s) {} } createTimer(); } else if (currentType == AUTH_TYPE_MISSED_CALL) { - if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { setProblemTextVisible(false); timeText.setVisibility(VISIBLE); problemText.setVisibility(GONE); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); } createTimer(); @@ -4227,104 +4377,6 @@ public void afterTextChanged(Editable s) {} } } - private class LoadingTextView extends TextView { - - private final Drawable rippleDrawable = Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), .10f), Theme.RIPPLE_MASK_ROUNDRECT_6DP); - public final LoadingDrawable loadingDrawable = new LoadingDrawable(); - - public LoadingTextView(Context context) { - super(context); - rippleDrawable.setCallback(this); - loadingDrawable.setAppearByGradient(true); - loadingDrawable.setSpeed(.8f); - } - - @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - - updateLoadingLayout(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - updateLoadingLayout(); - } - - private void updateLoadingLayout() { - Layout layout = getLayout(); - if (layout == null) { - return; - } - CharSequence text = layout.getText(); - if (text == null) { - return; - } - LinkPath path = new LinkPath(true); - path.setInset(AndroidUtilities.dp(3), AndroidUtilities.dp(6)); - int start = 0; - int end = text.length(); - path.setCurrentLayout(layout, start, 0); - layout.getSelectionPath(start, end, path); - path.getBounds(AndroidUtilities.rectTmp); - rippleDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); - loadingDrawable.usePath(path); - loadingDrawable.setRadiiDp(4); - - int color = getThemedColor(Theme.key_chat_linkSelectBackground); - loadingDrawable.setColors( - Theme.multAlpha(color, 0.85f), - Theme.multAlpha(color, 2f), - Theme.multAlpha(color, 3.5f), - Theme.multAlpha(color, 6f) - ); - - loadingDrawable.updateBounds(); - } - - @Override - protected void onDraw(Canvas canvas) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - rippleDrawable.draw(canvas); - canvas.restore(); - - super.onDraw(canvas); - - if (isResendingCode || loadingDrawable.isDisappearing()) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - loadingDrawable.draw(canvas); - canvas.restore(); - invalidate(); - } - } - - @Override - protected boolean verifyDrawable(@NonNull Drawable who) { - return who == rippleDrawable || super.verifyDrawable(who); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isRippleEnabled() && event.getAction() == MotionEvent.ACTION_DOWN) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - rippleDrawable.setHotspot(event.getX(), event.getY()); - } - rippleDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); - } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_UP) { - rippleDrawable.setState(new int[]{}); - } - return super.onTouchEvent(event); - } - - protected boolean isRippleEnabled() { - return true; - } - } - private void setProblemTextVisible(boolean visible) { if (problemText == null) { return; @@ -4406,9 +4458,9 @@ public void run() { int seconds = time / 1000 - minutes * 60; if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, minutes, seconds)); - } else if (currentType == AUTH_TYPE_SMS && nextType == AUTH_TYPE_SMS) { + } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { timeText.setText(LocaleController.formatString("ResendSmsAvailableIn", R.string.ResendSmsAvailableIn, minutes, seconds)); - } else if (nextType == AUTH_TYPE_SMS) { + } else if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, minutes, seconds)); } if (progressView != null && !progressView.isProgressAnimationRunning()) { @@ -4416,13 +4468,13 @@ public void run() { } } else { destroyTimer(); - if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD || nextType == AUTH_TYPE_MISSED_CALL) { if (nextType == AUTH_TYPE_CALL) { - timeText.setText(LocaleController.getString("RequestCallButton", R.string.RequestCallButton)); + timeText.setText(getString("RequestCallButton", R.string.RequestCallButton)); } else if (nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FLASH_CALL) { - timeText.setText(LocaleController.getString("RequestMissedCall", R.string.RequestMissedCall)); + timeText.setText(getString("RequestMissedCall", R.string.RequestMissedCall)); } else { - timeText.setText(LocaleController.getString("RequestSmsButton", R.string.RequestSmsButton)); + timeText.setText(getString("RequestSmsButton", R.string.RequestSmsButton)); } timeText.setTextColor(Theme.getColor(Theme.key_chats_actionBackground)); timeText.setTag(R.id.color_key_tag, Theme.key_chats_actionBackground); @@ -4523,9 +4575,9 @@ public void onNextPressed(String code) { fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignored) {} new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.YourPasswordSuccess)) + .setTitle(getString(R.string.YourPasswordSuccess)) .setMessage(LocaleController.formatString(R.string.ChangePhoneNumberSuccessWithPhone, PhoneFormat.getInstance().format("+" + requestPhone))) - .setPositiveButton(LocaleController.getString(R.string.OK), null) + .setPositiveButton(getString(R.string.OK), null) .setOnDismissListener(dialog -> finishFragment()) .show(); }); @@ -4533,7 +4585,7 @@ public void onNextPressed(String code) { lastError = error.text; nextPressed = false; showDoneButton(false, true); - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4549,18 +4601,18 @@ public void onNextPressed(String code) { if (currentType != AUTH_TYPE_FLASH_CALL) { boolean isWrongCode = false; if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -4599,15 +4651,15 @@ public void onNextPressed(String code) { return; } animateSuccess(() -> new AlertDialog.Builder(activity) - .setTitle(LocaleController.getString(R.string.CancelLinkSuccessTitle)) + .setTitle(getString(R.string.CancelLinkSuccessTitle)) .setMessage(LocaleController.formatString("CancelLinkSuccess", R.string.CancelLinkSuccess, PhoneFormat.getInstance().format("+" + phone))) - .setPositiveButton(LocaleController.getString(R.string.Close), null) + .setPositiveButton(getString(R.string.Close), null) .setOnDismissListener(dialog -> finishFragment()) .show()); } else { lastError = error.text; - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && - (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && + (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4683,7 +4735,7 @@ public void onNextPressed(String code) { if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -4696,7 +4748,7 @@ public void onNextPressed(String code) { animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); destroyTimer(); @@ -4704,7 +4756,7 @@ public void onNextPressed(String code) { } else { nextPressed = false; showDoneButton(false, true); - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_PHRASE || nextType == AUTH_TYPE_WORD)) { createTimer(); } if (currentType == AUTH_TYPE_FRAGMENT_SMS) { @@ -4723,18 +4775,18 @@ public void onNextPressed(String code) { if (currentType != AUTH_TYPE_FLASH_CALL) { boolean isWrongCode = false; if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -4822,12 +4874,17 @@ public boolean onBackPressed(boolean force) { return false; } + if (prevType != 0) { + setPage(prevType, true, null, true); + return false; + } + if (!force) { showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString(R.string.EditNumber)) + .setTitle(getString(R.string.EditNumber)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("EditNumberInfo", R.string.EditNumberInfo, phone))) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.Edit), (dialogInterface, i) -> { + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.Edit), (dialogInterface, i) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); }) @@ -4930,6 +4987,9 @@ public void onHide() { super.onHide(); isResendingCode = false; nextPressed = false; + if (prevType != 0 && currentParams != null) { + currentParams.putInt("timeout", time); + } } @Override @@ -4977,6 +5037,110 @@ public void restoreStateParams(Bundle bundle) { } } + + public class LoadingTextView extends TextView { + + private final Drawable rippleDrawable = Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), .10f), Theme.RIPPLE_MASK_ROUNDRECT_6DP); + public final LoadingDrawable loadingDrawable = new LoadingDrawable(); + + public LoadingTextView(Context context) { + super(context); + rippleDrawable.setCallback(this); + loadingDrawable.setAppearByGradient(true); + loadingDrawable.setSpeed(.8f); + } + + @Override + public void setText(CharSequence text, BufferType type) { + super.setText(text, type); + + updateLoadingLayout(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + updateLoadingLayout(); + } + + private void updateLoadingLayout() { + Layout layout = getLayout(); + if (layout == null) { + return; + } + CharSequence text = layout.getText(); + if (text == null) { + return; + } + LinkPath path = new LinkPath(true); + path.setInset(AndroidUtilities.dp(3), AndroidUtilities.dp(6)); + int start = 0; + int end = text.length(); + path.setCurrentLayout(layout, start, 0); + layout.getSelectionPath(start, end, path); + path.getBounds(AndroidUtilities.rectTmp); + rippleDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + loadingDrawable.usePath(path); + loadingDrawable.setRadiiDp(4); + + int color = getThemedColor(Theme.key_chat_linkSelectBackground); + loadingDrawable.setColors( + Theme.multAlpha(color, 0.85f), + Theme.multAlpha(color, 2f), + Theme.multAlpha(color, 3.5f), + Theme.multAlpha(color, 6f) + ); + + loadingDrawable.updateBounds(); + } + + protected boolean isResendingCode() { + return false; + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + float offset = (getGravity() & Gravity.CENTER_VERTICAL) != 0 && getLayout() != null ? getPaddingTop() + (getHeight() - getPaddingTop() - getPaddingBottom() - getLayout().getHeight()) / 2f : getPaddingTop(); + canvas.translate(getPaddingLeft(), offset); + rippleDrawable.draw(canvas); + canvas.restore(); + + super.onDraw(canvas); + + if (isResendingCode() || loadingDrawable.isDisappearing()) { + canvas.save(); + canvas.translate(getPaddingLeft(), offset); + loadingDrawable.draw(canvas); + canvas.restore(); + invalidate(); + } + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == rippleDrawable || super.verifyDrawable(who); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isRippleEnabled() && event.getAction() == MotionEvent.ACTION_DOWN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setHotspot(event.getX(), event.getY()); + } + rippleDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_UP) { + rippleDrawable.setState(new int[]{}); + } + return super.onTouchEvent(event); + } + + protected boolean isRippleEnabled() { + return true; + } + } + public class LoginActivityPasswordView extends SlideView { private EditTextBoldCursor codeField; @@ -5011,7 +5175,7 @@ public LoginActivityPasswordView(Context context) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(R.string.YourPasswordHeader)); + titleView.setText(getString(R.string.YourPasswordHeader)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5020,12 +5184,12 @@ public LoginActivityPasswordView(Context context) { confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmTextView.setGravity(Gravity.CENTER_HORIZONTAL); confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - confirmTextView.setText(LocaleController.getString(R.string.LoginPasswordTextShort)); + confirmTextView.setText(getString(R.string.LoginPasswordTextShort)); addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 8, 12, 0)); outlineCodeField = new OutlineTextContainerView(context); - outlineCodeField.setText(LocaleController.getString(R.string.EnterPassword)); - codeField = new EditTextAutoFill(context); + outlineCodeField.setText(getString(R.string.EnterPassword)); + codeField = new EditTextBoldCursor(context); codeField.setCursorSize(AndroidUtilities.dp(20)); codeField.setCursorWidth(1.5f); codeField.setBackground(null); @@ -5052,7 +5216,7 @@ public LoginActivityPasswordView(Context context) { cancelButton = new TextView(context); cancelButton.setGravity(Gravity.CENTER | Gravity.LEFT); - cancelButton.setText(LocaleController.getString(R.string.ForgotPassword)); + cancelButton.setText(getString(R.string.ForgotPassword)); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); @@ -5097,9 +5261,9 @@ public LoginActivityPasswordView(Context context) { run.end = endIndex + 1; emailPattern.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - builder.setMessage(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.RestoreEmailSent), emailPattern)); - builder.setTitle(LocaleController.getString("RestoreEmailSentTitle", R.string.RestoreEmailSentTitle)); - builder.setPositiveButton(LocaleController.getString(R.string.Continue), (dialogInterface, i) -> { + builder.setMessage(AndroidUtilities.formatSpannable(getString(R.string.RestoreEmailSent), emailPattern)); + builder.setTitle(getString("RestoreEmailSentTitle", R.string.RestoreEmailSentTitle)); + builder.setPositiveButton(getString(R.string.Continue), (dialogInterface, i) -> { Bundle bundle = new Bundle(); bundle.putString("email_unconfirmed_pattern", res.email_pattern); bundle.putString("password", passwordString); @@ -5122,19 +5286,19 @@ public LoginActivityPasswordView(Context context) { } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.WrongCodeTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.WrongCodeTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else { AndroidUtilities.hideKeyboard(codeField); new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString(R.string.RestorePasswordNoEmailText)) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setNegativeButton(LocaleController.getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)) + .setTitle(getString(R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString(R.string.RestorePasswordNoEmailText)) + .setPositiveButton(getString(R.string.Close), null) + .setNegativeButton(getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)) .show(); } }); @@ -5154,7 +5318,7 @@ public void updateColors() { @Override public String getHeaderName() { - return LocaleController.getString("LoginPassword", R.string.LoginPassword); + return getString("LoginPassword", R.string.LoginPassword); } @Override @@ -5266,9 +5430,9 @@ public void onNextPressed(String code) { } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }); @@ -5384,8 +5548,8 @@ public LoginActivityResetWaitView(Context context) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(R.string.ResetAccount)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(R.string.ResetAccount)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); innerLinearLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5400,7 +5564,7 @@ public LoginActivityResetWaitView(Context context) { resetAccountText = new TextView(context); resetAccountText.setGravity(Gravity.CENTER_HORIZONTAL); - resetAccountText.setText(LocaleController.getString("ResetAccountStatus", R.string.ResetAccountStatus)); + resetAccountText.setText(getString("ResetAccountStatus", R.string.ResetAccountStatus)); resetAccountText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); resetAccountText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(resetAccountText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 24, 0, 0)); @@ -5408,14 +5572,14 @@ public LoginActivityResetWaitView(Context context) { resetAccountTime = new TextView(context); resetAccountTime.setGravity(Gravity.CENTER_HORIZONTAL); resetAccountTime.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - resetAccountTime.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + resetAccountTime.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); resetAccountTime.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(resetAccountTime, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 8, 0, 0)); resetAccountButton = new TextView(context); resetAccountButton.setGravity(Gravity.CENTER); - resetAccountButton.setText(LocaleController.getString(R.string.ResetAccount)); - resetAccountButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + resetAccountButton.setText(getString(R.string.ResetAccount)); + resetAccountButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); resetAccountButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); resetAccountButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); resetAccountButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); @@ -5426,9 +5590,9 @@ public LoginActivityResetWaitView(Context context) { return; } showDialog(new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)) - .setMessage(LocaleController.getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)) - .setPositiveButton(LocaleController.getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { + .setTitle(getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)) + .setMessage(getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)) + .setPositiveButton(getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { needShowProgress(0); TLRPC.TL_account_deleteAccount req = new TLRPC.TL_account_deleteAccount(); req.reason = "Forgot password"; @@ -5447,14 +5611,14 @@ public LoginActivityResetWaitView(Context context) { setPage(VIEW_REGISTER, true, params, false); } else { if (error.text.equals("2FA_RECENT_CONFIRM")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); }) - .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null).create()); + .setNegativeButton(getString("Cancel", R.string.Cancel), null).create()); }); } @@ -5469,7 +5633,7 @@ public void updateColors() { @Override public String getHeaderName() { - return LocaleController.getString("ResetAccount", R.string.ResetAccount); + return getString("ResetAccount", R.string.ResetAccount); } private void updateTimeText() { @@ -5594,7 +5758,7 @@ public LoginActivitySetupEmail(Context context) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.EnterNewEmail : R.string.AddEmailTitle)); + titleView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.EnterNewEmail : R.string.AddEmailTitle)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5603,11 +5767,11 @@ public LoginActivitySetupEmail(Context context) { subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setGravity(Gravity.CENTER); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - subtitleView.setText(LocaleController.getString(R.string.AddEmailSubtitle)); + subtitleView.setText(getString(R.string.AddEmailSubtitle)); addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 8, 32, 0)); emailOutlineView = new OutlineTextContainerView(context); - emailOutlineView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.YourNewEmail : R.string.YourEmail)); + emailOutlineView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.YourNewEmail : R.string.YourEmail)); emailField = new EditTextBoldCursor(context); emailField.setCursorSize(AndroidUtilities.dp(20)); @@ -5655,7 +5819,7 @@ public boolean needBackButton() { @Override public String getHeaderName() { - return LocaleController.getString("AddEmailTitle", R.string.AddEmailTitle); + return getString("AddEmailTitle", R.string.AddEmailTitle); } @Override @@ -5740,19 +5904,19 @@ public void onNextPressed(String code) { if (error.text.contains("EMAIL_INVALID")) { onPasscodeError(false); } else if (error.text.contains("EMAIL_NOT_ALLOWED")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailNotAllowed)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailNotAllowed)); } else if (error.text.contains("PHONE_PASSWORD_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("PHONE_NUMBER_FLOOD")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else if (error.code != -1000) { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req, requestPhone); } @@ -5860,7 +6024,7 @@ public LoginActivityEmailCodeView(Context context, boolean setup) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.CheckYourNewEmail : setup ? R.string.VerificationCode : R.string.CheckYourEmail)); + titleView.setText(getString(activityMode == MODE_CHANGE_LOGIN_EMAIL ? R.string.CheckYourNewEmail : setup ? R.string.VerificationCode : R.string.CheckYourEmail)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -5891,7 +6055,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.AT_MOST)); } }; - cantAccessEmailView.setText(LocaleController.getString(R.string.LoginCantAccessThisEmail)); + cantAccessEmailView.setText(getString(R.string.LoginCantAccessThisEmail)); cantAccessEmailView.setGravity(Gravity.CENTER); cantAccessEmailView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); cantAccessEmailView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); @@ -5909,9 +6073,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } new AlertDialog.Builder(context) - .setTitle(LocaleController.getString(R.string.LoginEmailResetTitle)) - .setMessage(AndroidUtilities.formatSpannable(AndroidUtilities.replaceTags(LocaleController.getString(R.string.LoginEmailResetMessage)), email, getTimePattern(resetAvailablePeriod))) - .setPositiveButton(LocaleController.getString(R.string.LoginEmailResetButton), (dialog, which) -> { + .setTitle(getString(R.string.LoginEmailResetTitle)) + .setMessage(AndroidUtilities.formatSpannable(AndroidUtilities.replaceTags(getString(R.string.LoginEmailResetMessage)), email, getTimePattern(resetAvailablePeriod))) + .setPositiveButton(getString(R.string.LoginEmailResetButton), (dialog, which) -> { Bundle params = new Bundle(); params.putString("phone", phone); params.putString("ephone", emailPhone); @@ -5932,14 +6096,14 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); }) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .setNegativeButton(getString(R.string.Cancel), null) .show(); }); cantAccessEmailFrameLayout.addView(cantAccessEmailView); @@ -5965,7 +6129,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { resendCodeView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); resendCodeView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); resendCodeView.setMaxLines(2); - resendCodeView.setText(LocaleController.getString(R.string.ResendCode)); + resendCodeView.setText(getString(R.string.ResendCode)); resendCodeView.setOnClickListener(v -> { if (resendCodeView.getVisibility() != View.VISIBLE || resendCodeView.getAlpha() != 1f) { return; @@ -6017,7 +6181,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { errorViewSwitcher.addView(resendFrameLayout); wrongCodeView = new TextView(context); - wrongCodeView.setText(LocaleController.getString("WrongCode", R.string.WrongCode)); + wrongCodeView.setText(getString("WrongCode", R.string.WrongCode)); wrongCodeView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); wrongCodeView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); wrongCodeView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); @@ -6062,14 +6226,14 @@ private void requestEmailReset() { } else if (error != null && error.text != null) { if (error.text.contains("TASK_ALREADY_EXISTS")) { new AlertDialog.Builder(getContext()) - .setTitle(LocaleController.getString(R.string.LoginEmailResetPremiumRequiredTitle)) + .setTitle(getString(R.string.LoginEmailResetPremiumRequiredTitle)) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.LoginEmailResetPremiumRequiredMessage, LocaleController.addNbsp(PhoneFormat.getInstance().format("+" + requestPhone))))) - .setPositiveButton(LocaleController.getString(R.string.OK), null) + .setPositiveButton(getString(R.string.OK), null) .show(); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else { AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); } @@ -6120,7 +6284,7 @@ public boolean needBackButton() { @Override public String getHeaderName() { - return LocaleController.getString(R.string.VerificationCode); + return getString(R.string.VerificationCode); } @Override @@ -6195,7 +6359,7 @@ public void afterTextChanged(Editable s) {} confirmText.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - confirmTextView.setText(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.CheckYourEmailSubtitle), confirmText)); + confirmTextView.setText(AndroidUtilities.formatSpannable(getString(R.string.CheckYourEmailSubtitle), confirmText)); } // int v = params.getBoolean("googleSignInAllowed") && PushListenerController.GooglePushListenerServiceProvider.INSTANCE.hasServices() ? VISIBLE : GONE; @@ -6271,7 +6435,7 @@ private void updateResetPendingDate() { int timeRemaining = (int) (resetPendingDate - System.currentTimeMillis() / 1000L); if (resetPendingDate <= 0 || timeRemaining <= 0) { emailResetInView.setVisibility(VISIBLE); - emailResetInView.setText(LocaleController.getString(R.string.LoginEmailResetPleaseWait)); + emailResetInView.setText(getString(R.string.LoginEmailResetPleaseWait)); AndroidUtilities.runOnUIThread(this::requestEmailReset, 1000); return; } @@ -6429,7 +6593,7 @@ public void onNextPressed(String code) { if (error1 == null) { TLRPC.account_Password password = (TLRPC.account_Password) response1; if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); return; } Bundle bundle = new Bundle(); @@ -6442,7 +6606,7 @@ public void onNextPressed(String code) { animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else { @@ -6450,22 +6614,22 @@ public void onNextPressed(String code) { showDoneButton(false, true); boolean isWrongCode = false; if (error.text.contains("EMAIL_ADDRESS_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailAddressInvalid)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailAddressInvalid)); } else if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("CODE_EMPTY") || error.text.contains("CODE_INVALID") || error.text.contains("EMAIL_CODE_INVALID") || error.text.contains("PHONE_CODE_INVALID")) { shakeWrongCode(); isWrongCode = true; } else if (error.text.contains("EMAIL_TOKEN_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString(R.string.EmailTokenInvalid)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.EmailTokenInvalid)); } else if (error.text.contains("EMAIL_VERIFY_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.startsWith("FLOOD_WAIT")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); } if (!isWrongCode) { @@ -6612,8 +6776,8 @@ public LoginActivityRecoverView(Context context) { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(R.string.EnterCode)); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setText(getString(R.string.EnterCode)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 16, 32, 0)); @@ -6622,7 +6786,7 @@ public LoginActivityRecoverView(Context context) { confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmTextView.setGravity(Gravity.CENTER); confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - confirmTextView.setText(LocaleController.getString(R.string.RestoreEmailSentInfo)); + confirmTextView.setText(getString(R.string.RestoreEmailSentInfo)); addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12, 8, 12, 0)); codeFieldContainer = new CodeFieldContainer(context) { @@ -6668,10 +6832,10 @@ public void afterTextChanged(Editable s) {} troubleButton.setOnClickListener(view -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("RestorePasswordNoEmailTitle", R.string.RestorePasswordNoEmailTitle)) - .setMessage(LocaleController.getString("RestoreEmailTroubleText", R.string.RestoreEmailTroubleText)) - .setPositiveButton(LocaleController.getString(R.string.OK), (dialogInterface, i) -> setPage(VIEW_PASSWORD, true, new Bundle(), true)) - .setNegativeButton(LocaleController.getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)); + .setTitle(getString("RestorePasswordNoEmailTitle", R.string.RestorePasswordNoEmailTitle)) + .setMessage(getString("RestoreEmailTroubleText", R.string.RestoreEmailTroubleText)) + .setPositiveButton(getString(R.string.OK), (dialogInterface, i) -> setPage(VIEW_PASSWORD, true, new Bundle(), true)) + .setNegativeButton(getString(R.string.ResetAccount), (dialog, which) -> tryResetAccount(requestPhone, phoneHash, phoneCode)); Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); @@ -6717,7 +6881,7 @@ public void onCancelPressed() { @Override public String getHeaderName() { - return LocaleController.getString("LoginPassword", R.string.LoginPassword); + return getString("LoginPassword", R.string.LoginPassword); } @Override @@ -6741,7 +6905,7 @@ public void setParams(Bundle params, boolean restore) { run.end = endIndex + 1; unconfirmedPattern.setSpan(new TextStyleSpan(run), startIndex, endIndex + 1, 0); } - troubleButton.setText(AndroidUtilities.formatSpannable(LocaleController.getString(R.string.RestoreEmailNoAccess), unconfirmedPattern)); + troubleButton.setText(AndroidUtilities.formatSpannable(getString(R.string.RestoreEmailNoAccess), unconfirmedPattern)); showKeyboard(codeFieldContainer); codeFieldContainer.requestFocus(); @@ -6820,9 +6984,9 @@ public void onNextPressed(String code) { } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); @@ -6902,10 +7066,10 @@ public LoginActivityNewPasswordView(Context context, int stage) { titleTextView = new TextView(context); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - titleTextView.setText(LocaleController.getString(R.string.SetNewPassword)); + titleTextView.setText(getString(R.string.SetNewPassword)); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, AndroidUtilities.isSmallScreen() ? 16 : 72, 8, 0)); confirmTextView = new TextView(context); @@ -6917,7 +7081,7 @@ public LoginActivityNewPasswordView(Context context, int stage) { for (int a = 0; a < codeField.length; a++) { OutlineTextContainerView outlineField = new OutlineTextContainerView(context); outlineFields[a] = outlineField; - outlineField.setText(LocaleController.getString(stage == 0 ? a == 0 ? R.string.PleaseEnterNewFirstPasswordHint : R.string.PleaseEnterNewSecondPasswordHint : R.string.PasswordHintPlaceholder)); + outlineField.setText(getString(stage == 0 ? a == 0 ? R.string.PleaseEnterNewFirstPasswordHint : R.string.PleaseEnterNewSecondPasswordHint : R.string.PasswordHintPlaceholder)); codeField[a] = new EditTextBoldCursor(context); codeField[a].setCursorSize(AndroidUtilities.dp(20)); @@ -7004,9 +7168,9 @@ public void afterTextChanged(Editable s) { } if (stage == 0) { - confirmTextView.setText(LocaleController.getString("PleaseEnterNewFirstPasswordLogin", R.string.PleaseEnterNewFirstPasswordLogin)); + confirmTextView.setText(getString("PleaseEnterNewFirstPasswordLogin", R.string.PleaseEnterNewFirstPasswordLogin)); } else { - confirmTextView.setText(LocaleController.getString("PasswordHintTextLogin", R.string.PasswordHintTextLogin)); + confirmTextView.setText(getString("PasswordHintTextLogin", R.string.PasswordHintTextLogin)); } cancelButton = new TextView(context); @@ -7014,7 +7178,7 @@ public void afterTextChanged(Editable s) { cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); - cancelButton.setText(LocaleController.getString(R.string.YourEmailSkip)); + cancelButton.setText(getString(R.string.YourEmailSkip)); FrameLayout bottomContainer = new FrameLayout(context); bottomContainer.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, (Build.VERSION.SDK_INT >= 21 ? 56 : 60), Gravity.BOTTOM, 0, 0, 0, 32)); @@ -7060,7 +7224,7 @@ public void onCancelPressed() { @Override public String getHeaderName() { - return LocaleController.getString("NewPassword", R.string.NewPassword); + return getString("NewPassword", R.string.NewPassword); } @Override @@ -7157,13 +7321,13 @@ private void recoverPassword(String password, String hint) { needHideProgress(false); if (response instanceof TLRPC.auth_Authorization) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setPositiveButton(LocaleController.getString(R.string.Continue), (dialogInterface, i) -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); + builder.setPositiveButton(getString(R.string.Continue), (dialogInterface, i) -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); if (TextUtils.isEmpty(password)) { - builder.setMessage(LocaleController.getString(R.string.YourPasswordReset)); + builder.setMessage(getString(R.string.YourPasswordReset)); } else { - builder.setMessage(LocaleController.getString(R.string.YourPasswordChangedSuccessText)); + builder.setMessage(getString(R.string.YourPasswordChangedSuccessText)); } - builder.setTitle(LocaleController.getString(R.string.TwoStepVerificationTitle)); + builder.setTitle(getString(R.string.TwoStepVerificationTitle)); Dialog dialog = showDialog(builder.create()); if (dialog != null) { dialog.setCanceledOnTouchOutside(false); @@ -7179,9 +7343,9 @@ private void recoverPassword(String password, String hint) { } else { timeString = LocaleController.formatPluralString("Minutes", time / 60); } - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), LocaleController.formatString("FloodWaitTime", R.string.FloodWaitTime, timeString)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }); @@ -7291,29 +7455,29 @@ private void showTermsOfService(boolean needAccept) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("TermsOfService", R.string.TermsOfService)); + builder.setTitle(getString("TermsOfService", R.string.TermsOfService)); if (needAccept) { - builder.setPositiveButton(LocaleController.getString("Accept", R.string.Accept), (dialog, which) -> { + builder.setPositiveButton(getString("Accept", R.string.Accept), (dialog, which) -> { currentTermsOfService.popup = false; onNextPressed(null); }); - builder.setNegativeButton(LocaleController.getString("Decline", R.string.Decline), (dialog, which) -> { + builder.setNegativeButton(getString("Decline", R.string.Decline), (dialog, which) -> { AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity()); - builder1.setTitle(LocaleController.getString("TermsOfService", R.string.TermsOfService)); - builder1.setMessage(LocaleController.getString("TosDecline", R.string.TosDecline)); - builder1.setPositiveButton(LocaleController.getString("SignUp", R.string.SignUp), (dialog1, which1) -> { + builder1.setTitle(getString("TermsOfService", R.string.TermsOfService)); + builder1.setMessage(getString("TosDecline", R.string.TosDecline)); + builder1.setPositiveButton(getString("SignUp", R.string.SignUp), (dialog1, which1) -> { currentTermsOfService.popup = false; onNextPressed(null); }); - builder1.setNegativeButton(LocaleController.getString("Decline", R.string.Decline), (dialog12, which12) -> { + builder1.setNegativeButton(getString("Decline", R.string.Decline), (dialog12, which12) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); }); showDialog(builder1.create()); }); } else { - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.setPositiveButton(getString("OK", R.string.OK), null); } SpannableStringBuilder text = new SpannableStringBuilder(currentTermsOfService.text); @@ -7473,15 +7637,15 @@ public void setAlpha(float alpha) { showAvatarProgress(false, false); titleTextView = new TextView(context); - titleTextView.setText(LocaleController.getString(R.string.RegistrationProfileInfo)); + titleTextView.setText(getString(R.string.RegistrationProfileInfo)); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.CENTER_HORIZONTAL); addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, 12, 8, 0)); descriptionTextView = new TextView(context); - descriptionTextView.setText(LocaleController.getString("RegisterText2", R.string.RegisterText2)); + descriptionTextView.setText(getString("RegisterText2", R.string.RegisterText2)); descriptionTextView.setGravity(Gravity.CENTER_HORIZONTAL); descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); descriptionTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -7491,7 +7655,7 @@ public void setAlpha(float alpha) { addView(editTextContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 8, 21, 8, 0)); firstNameOutlineView = new OutlineTextContainerView(context); - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstName)); + firstNameOutlineView.setText(getString(R.string.FirstName)); firstNameField = new EditTextBoldCursor(context); firstNameField.setCursorSize(AndroidUtilities.dp(20)); @@ -7516,7 +7680,7 @@ public void setAlpha(float alpha) { }); lastNameOutlineView = new OutlineTextContainerView(context); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastName)); + lastNameOutlineView.setText(getString(R.string.LastName)); lastNameField = new EditTextBoldCursor(context); lastNameField.setCursorSize(AndroidUtilities.dp(20)); @@ -7542,7 +7706,7 @@ public void setAlpha(float alpha) { buildEditTextLayout(AndroidUtilities.isSmallScreen()); wrongNumber = new TextView(context); - wrongNumber.setText(LocaleController.getString("CancelRegistration", R.string.CancelRegistration)); + wrongNumber.setText(getString("CancelRegistration", R.string.CancelRegistration)); wrongNumber.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_HORIZONTAL); wrongNumber.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); wrongNumber.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -7567,7 +7731,7 @@ public void setAlpha(float alpha) { privacyLayout.addView(privacyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 56 : 60, Gravity.LEFT | Gravity.BOTTOM, 14, 0, 70, 32)); VerticalPositionAutoAnimator.attach(privacyView); - String str = LocaleController.getString("TermsOfServiceLogin", R.string.TermsOfServiceLogin); + String str = getString("TermsOfServiceLogin", R.string.TermsOfServiceLogin); SpannableStringBuilder text = new SpannableStringBuilder(str); int index1 = str.indexOf('*'); int index2 = str.lastIndexOf('*'); @@ -7604,8 +7768,8 @@ private void buildEditTextLayout(boolean small) { LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(HORIZONTAL); - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstNameSmall)); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastNameSmall)); + firstNameOutlineView.setText(getString(R.string.FirstNameSmall)); + lastNameOutlineView.setText(getString(R.string.LastNameSmall)); linearLayout.addView(firstNameOutlineView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f, 0, 0, 8, 0)); linearLayout.addView(lastNameOutlineView, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f, 8, 0, 0, 0)); @@ -7620,8 +7784,8 @@ private void buildEditTextLayout(boolean small) { AndroidUtilities.showKeyboard(lastNameField); } } else { - firstNameOutlineView.setText(LocaleController.getString(R.string.FirstName)); - lastNameOutlineView.setText(LocaleController.getString(R.string.LastName)); + firstNameOutlineView.setText(getString(R.string.FirstName)); + lastNameOutlineView.setText(getString(R.string.LastName)); editTextContainer.addView(firstNameOutlineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 8, 0, 8, 0)); editTextContainer.addView(lastNameOutlineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 8, 82, 8, 0)); @@ -7698,14 +7862,14 @@ public void onAnimationCancel(Animator animation) { public boolean onBackPressed(boolean force) { if (!force) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString(R.string.Warning)); - builder.setMessage(LocaleController.getString("AreYouSureRegistration", R.string.AreYouSureRegistration)); - builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { + builder.setTitle(getString(R.string.Warning)); + builder.setMessage(getString("AreYouSureRegistration", R.string.AreYouSureRegistration)); + builder.setNegativeButton(getString("Stop", R.string.Stop), (dialogInterface, i) -> { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); hidePrivacyView(); }); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); + builder.setPositiveButton(getString("Continue", R.string.Continue), null); showDialog(builder.create()); return false; } @@ -7717,7 +7881,7 @@ public boolean onBackPressed(boolean force) { @Override public String getHeaderName() { - return LocaleController.getString("YourName", R.string.YourName); + return getString("YourName", R.string.YourName); } @Override @@ -7804,19 +7968,19 @@ public void onNextPressed(String code) { } else { needHideProgress(false); if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { onBackPressed(true); setPage(VIEW_PHONE_INPUT, true, null, true); - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); } else if (error.text.contains("FIRSTNAME_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidFirstName", R.string.InvalidFirstName)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidFirstName", R.string.InvalidFirstName)); } else if (error.text.contains("LASTNAME_INVALID")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidLastName", R.string.InvalidLastName)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidLastName", R.string.InvalidLastName)); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); @@ -8042,9 +8206,9 @@ private void tryResetAccount(String requestPhone, String phoneHash, String phone return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)); - builder.setTitle(LocaleController.getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)); - builder.setPositiveButton(LocaleController.getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { + builder.setMessage(getString("ResetMyAccountWarningText", R.string.ResetMyAccountWarningText)); + builder.setTitle(getString("ResetMyAccountWarning", R.string.ResetMyAccountWarning)); + builder.setPositiveButton(getString("ResetMyAccountWarningReset", R.string.ResetMyAccountWarningReset), (dialogInterface, i) -> { needShowProgress(0); TLRPC.TL_account_deleteAccount req = new TLRPC.TL_account_deleteAccount(); req.reason = "Forgot password"; @@ -8062,7 +8226,7 @@ private void tryResetAccount(String requestPhone, String phoneHash, String phone setPage(VIEW_REGISTER, true, params, false); } else { if (error.text.equals("2FA_RECENT_CONFIRM")) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ResetAccountCancelledAlert", R.string.ResetAccountCancelledAlert)); } else if (error.text.startsWith("2FA_CONFIRM_WAIT_")) { Bundle params = new Bundle(); params.putString("phoneFormated", requestPhone); @@ -8072,12 +8236,12 @@ private void tryResetAccount(String requestPhone, String phoneHash, String phone params.putInt("waitTime", Utilities.parseInt(error.text.replace("2FA_CONFIRM_WAIT_", ""))); setPage(VIEW_RESET_WAIT, true, params, false); } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error.text); } } }), ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } @@ -8132,7 +8296,7 @@ private PhoneNumberConfirmView(@NonNull Context context, ViewGroup fragmentView, floatingProgressView.setScaleY(0.1f); popupFabContainer.addView(floatingProgressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - popupFabContainer.setContentDescription(LocaleController.getString(R.string.Done)); + popupFabContainer.setContentDescription(getString(R.string.Done)); addView(popupFabContainer, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60)); popupLayout = new FrameLayout(context); @@ -8140,7 +8304,7 @@ private PhoneNumberConfirmView(@NonNull Context context, ViewGroup fragmentView, addView(popupLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 140, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 24, 0, 24, 0)); confirmMessageView = new TextView(context); - confirmMessageView.setText(LocaleController.getString(R.string.ConfirmCorrectNumber)); + confirmMessageView.setText(getString(R.string.ConfirmCorrectNumber)); confirmMessageView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); confirmMessageView.setSingleLine(); popupLayout.addView(confirmMessageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 24, 20, 24, 0)); @@ -8148,7 +8312,7 @@ private PhoneNumberConfirmView(@NonNull Context context, ViewGroup fragmentView, numberView = new TextView(context); numberView.setText(numberText); numberView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - numberView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + numberView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); numberView.setSingleLine(); popupLayout.addView(numberView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 24, 48, 24, 0)); @@ -8156,7 +8320,7 @@ private PhoneNumberConfirmView(@NonNull Context context, ViewGroup fragmentView, int buttonMargin = 8; editTextView = new TextView(context); - editTextView.setText(LocaleController.getString(R.string.Edit)); + editTextView.setText(getString(R.string.Edit)); editTextView.setSingleLine(); editTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); editTextView.setBackground(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_changephoneinfo_image2))); @@ -8166,7 +8330,7 @@ private PhoneNumberConfirmView(@NonNull Context context, ViewGroup fragmentView, popupLayout.addView(editTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), buttonMargin, buttonMargin, buttonMargin, buttonMargin)); confirmTextView = new TextView(context); - confirmTextView.setText(LocaleController.getString(R.string.CheckPhoneNumberYes)); + confirmTextView.setText(getString(R.string.CheckPhoneNumberYes)); confirmTextView.setSingleLine(); confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); confirmTextView.setBackground(Theme.getRoundRectSelectorDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_changephoneinfo_image2))); @@ -8469,7 +8633,939 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { editText.requestFocus(); AndroidUtilities.showKeyboard(editText); }); + } + + public class LoginActivityPhraseView extends SlideView { + + private final @AuthType int currentType; + + private final LinearLayout fieldContainer; + private final OutlineTextContainerView outlineField; + private final EditTextBoldCursor codeField; + private final FrameLayout infoContainer; + private final TextView prevTypeTextView; + private final TextView errorTextView; + private final TextView infoTextView; + private final RLottieImageView imageView; + private final TextView titleTextView; + private final TextView confirmTextView; + private final TextView pasteTextView; + private final LoadingTextView timeText; +// private TextView cancelButton; + private boolean pasteShown = true; + private boolean errorShown = false; + private boolean pasting = false, pasted = false; + + private @AuthType int nextType; + private @AuthType int prevType; + private String requestPhone, phoneHash, emailPhone, phone; + private String beginning; + private Bundle currentParams; + + private boolean isResendingCode; + private Timer timeTimer; + private Timer codeTimer; + private int openTime; + private final Object timerSync = new Object(); + private int time = 60000; + private int codeTime = 15000; + private double lastCurrentTime; + private double lastCodeTime; + private boolean ignoreOnTextChange; + private boolean waitingForEvent; + private boolean nextPressed; + private String lastError = ""; + + private Bundle nextCodeParams; + private TLRPC.TL_auth_sentCode nextCodeAuth; + + public LoginActivityPhraseView(Context context, @AuthType int type) { + super(context); + currentType = type; + final int a; + if (type == AUTH_TYPE_WORD) { + a = 0; + } else /* if (type == AUTH_TYPE_PHRASE) */ { + a = 1; + } + + setOrientation(VERTICAL); + + imageView = new RLottieImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setAnimation(R.raw.bubble, 95, 95); + boolean hideImage = AndroidUtilities.isSmallScreen() || (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y && !AndroidUtilities.isTablet()); + imageView.setVisibility(hideImage ? GONE : VISIBLE); + addView(imageView, LayoutHelper.createLinear(95, 95, Gravity.CENTER_HORIZONTAL, 0, 10, 0, 5)); + + titleTextView = new TextView(context); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); + titleTextView.setText(getString(a == 0 ? R.string.SMSWordTitle : R.string.SMSPhraseTitle)); + addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, hideImage ? 25 : 0, 8, 0)); + + confirmTextView = new TextView(context); + confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + confirmTextView.setGravity(Gravity.CENTER_HORIZONTAL); + confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 8, 5, 8, 16)); + + outlineField = new OutlineTextContainerView(context); + outlineField.setText(getString(a == 0 ? R.string.SMSWord : R.string.SMSPhrase)); + + codeField = new EditTextBoldCursor(context) { + @Override + public boolean onTextContextMenuItem(int id) { + switch (id) { + case android.R.id.paste: + case android.R.id.pasteAsPlainText: + pasting = pasted = true; + postDelayed(() -> pasting = false, 1000); + break; + } + return super.onTextContextMenuItem(id); + } + }; + codeField.setSingleLine(); + codeField.setLines(1); + codeField.setCursorSize(AndroidUtilities.dp(20)); + codeField.setCursorWidth(1.5f); + codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + codeField.setMaxLines(1); + codeField.setBackground(null); + codeField.setHint(getString(a == 0 ? R.string.SMSWordHint : R.string.SMSPhraseHint)); + codeField.addTextChangedListener(new TextWatcher() { + private boolean ignoreTextChange; + private int trimmedLength; + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (ignoreTextChange) return; + if (s == null || beginning == null) return; + trimmedLength = trimLeft(s.toString()).length(); + } + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (ignoreTextChange) return; + } + @Override + public void afterTextChanged(Editable s) { + if (ignoreTextChange) return; + checkPaste(true); + AndroidUtilities.cancelRunOnUIThread(dismissField); + animateError(false); + if (TextUtils.isEmpty(s)) { + pasted = false; + } + if (!beginsOk(s.toString())) { + onInputError(true); + ignoreTextChange = true; + boolean selectedEnd = codeField.getSelectionEnd() >= codeField.getText().length(); + if (!pasted) { + codeField.setText(beginning.substring(0, Utilities.clamp(trimmedLength, beginning.length(), 0))); + if (selectedEnd) { + codeField.setSelection(codeField.getText().length()); + } + } + ignoreTextChange = false; + } + } + }); + codeField.setEllipsizeByGradient(true); + codeField.setInputType(InputType.TYPE_CLASS_TEXT); + + codeField.setTypeface(Typeface.DEFAULT); + codeField.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + + codeField.setOnFocusChangeListener((v, hasFocus) -> outlineField.animateSelection(hasFocus ? 1f : 0f)); + + pasteTextView = new TextView(context); + pasteTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + pasteTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + pasteTextView.setText(getString(R.string.Paste)); + pasteTextView.setPadding(dp(10), 0, dp(10), 0); + pasteTextView.setGravity(Gravity.CENTER); + int textColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourceProvider); + pasteTextView.setTextColor(textColor); + pasteTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(6), Theme.multAlpha(textColor, .12f), Theme.multAlpha(textColor, .15f))); + ScaleStateListAnimator.apply(pasteTextView, .1f, 1.5f); + codeField.setPadding(dp(16), dp(16 - 2.66f), dp(16), dp(16 - 2.66f)); + pasteTextView.setOnClickListener(v -> { + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + CharSequence text = null; + try { + text = clipboardManager.getPrimaryClip().getItemAt(0).coerceToText(getContext()); + } catch (Exception e) { + FileLog.e(e); + } + if (text != null) { + Editable fieldText = codeField.getText(); + pasting = pasted = true; + if (fieldText != null) { + final int start = Math.max(0, codeField.getSelectionStart()); + final int end = Math.max(start, codeField.getSelectionEnd()); + fieldText.replace(start, end, text); + } + pasting = false; + } + checkPaste(true); + }); + + outlineField.addView(codeField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 0, 0, 0, 0)); + outlineField.attachEditText(codeField); + outlineField.addView(pasteTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 26, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 10, 0)); + + fieldContainer = new LinearLayout(context); + fieldContainer.setOrientation(VERTICAL); + fieldContainer.addView(outlineField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); + addView(fieldContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 16, 3, 16, 0)); + codeField.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_NEXT) { + onNextPressed(null); + return true; + } + return false; + }); + + infoContainer = new FrameLayout(context); + fieldContainer.addView(infoContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + prevTypeTextView = new LoadingTextView(context); + prevTypeTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteValueText)); + prevTypeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + prevTypeTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + prevTypeTextView.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + prevTypeTextView.setOnClickListener(v -> onBackPressed(true)); + addView(prevTypeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + prevTypeTextView.setVisibility(View.GONE); + + errorTextView = new TextView(context); + errorTextView.setPivotX(0); + errorTextView.setPivotY(0); + errorTextView.setText(getString(a == 0 ? R.string.SMSWordError : R.string.SMSPhraseError)); + errorTextView.setTextColor(getThemedColor(Theme.key_text_RedRegular)); + errorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + infoContainer.addView(errorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 16, 8, 16, 8)); + errorTextView.setAlpha(0f); + errorTextView.setScaleX(.8f); + errorTextView.setScaleY(.8f); + errorTextView.setTranslationY(-dp(4)); + + infoTextView = new TextView(context); + infoTextView.setPivotX(0); + infoTextView.setPivotY(0); + infoTextView.setText(getString(a == 0 ? R.string.SMSWordPasteHint : R.string.SMSPhrasePasteHint)); + infoTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + infoContainer.addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 16, 8, 16, 8)); + + timeText = new LoadingTextView(context) { + @Override + protected boolean isResendingCode() { + return isResendingCode; + } + @Override + protected boolean isRippleEnabled() { + return getVisibility() == View.VISIBLE && !(time > 0 && timeTimer != null); + } + }; + timeText.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + timeText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + timeText.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + timeText.setOnClickListener(v -> { +// if (isRequestingFirebaseSms || isResendingCode) { +// return; +// } + if (time > 0 && timeTimer != null) { + return; + } + if (nextCodeParams != null && nextCodeAuth != null) { + fillNextCodeParams(nextCodeParams, nextCodeAuth); + return; + } + + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { + isResendingCode = true; + timeText.invalidate(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); +// timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setText(getString(R.string.Calling)); + } else { + timeText.setText(getString(R.string.SendingSms)); + } + Bundle params = new Bundle(); + params.putString("phone", phone); + params.putString("ephone", emailPhone); + params.putString("phoneFormated", requestPhone); + params.putInt("prevType", currentType); +// createCodeTimer(); + TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + isResendingCode = false; + timeText.invalidate(); + if (response != null) { + nextCodeParams = params; + nextCodeAuth = (TLRPC.TL_auth_sentCode) response; + fillNextCodeParams(nextCodeParams, nextCodeAuth); + } else if (error != null && error.text != null) { + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); + } else if (error.code != -1000) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); + } + lastError = error.text; + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + } else if (nextType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.setWaitingForSms(false); +// NotificationCenter.getGlobalInstance().removeObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); + waitingForEvent = false; +// destroyCodeTimer(); + resendCode(); + } + }); + +// cancelButton = new TextView(context); +// cancelButton.setGravity(Gravity.CENTER | Gravity.LEFT); +// cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); +// cancelButton.setLineSpacing(AndroidUtilities.dp(2), 1.0f); +// cancelButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); +// cancelButton.setText(getString(R.string.YourEmailSkip)); + + FrameLayout bottomContainer = new FrameLayout(context); + bottomContainer.addView(timeText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, (Build.VERSION.SDK_INT >= 21 ? 56 : 60), Gravity.BOTTOM, 6, 0, 60, 28)); + addView(bottomContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM)); + VerticalPositionAutoAnimator.attach(timeText); + +// cancelButton.setOnClickListener(view -> { +// +// }); + } + + private final Runnable checkPasteRunnable = () -> checkPaste(true); + + private void checkPaste(boolean animated) { + AndroidUtilities.cancelRunOnUIThread(checkPasteRunnable); + + boolean show; + ClipboardManager clipboardManager = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + show = TextUtils.isEmpty(codeField.getText()) && clipboardManager != null && clipboardManager.hasPrimaryClip(); + + if (pasteShown != show) { + pasteShown = show; + if (animated) { + pasteTextView.animate() + .alpha(show ? 1f : 0f) + .scaleX(show ? 1f : .7f) + .scaleY(show ? 1f : .7f) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setDuration(300) + .start(); + + infoTextView.animate() + .scaleX(pasteShown && !errorShown ? 1f : .9f) + .scaleY(pasteShown && !errorShown ? 1f : .9f) + .alpha(pasteShown && !errorShown ? 1f : 0f) + .translationY(pasteShown && !errorShown ? 0 : dp(errorShown ? 5 : -5)) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setDuration(300) + .start(); + } else { + pasteTextView.setAlpha(show ? 1f : 0f); + pasteTextView.setScaleX(show ? 1f : .7f); + pasteTextView.setScaleY(show ? 1f : .7f); + + infoTextView.setScaleX(pasteShown && !errorShown ? 1f : .9f); + infoTextView.setScaleY(pasteShown && !errorShown ? 1f : .9f); + infoTextView.setAlpha(pasteShown && !errorShown ? 1f : 0f); + infoTextView.setTranslationY(pasteShown && !errorShown ? 0 : dp(errorShown ? 5 : -5)); + } + } + + AndroidUtilities.runOnUIThread(checkPasteRunnable, 1000 * 5); + } + + @Override + public void updateColors() { + titleTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + confirmTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText6)); + codeField.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + codeField.setCursorColor(getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated)); + codeField.setHintTextColor(getThemedColor(Theme.key_windowBackgroundWhiteHintText)); + outlineField.updateColor(); +// cancelButton.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + } + + @Override + public boolean needBackButton() { + return true; + } + + @Override + public void onCancelPressed() { + nextPressed = false; + } + + @Override + public String getHeaderName() { + return getString("NewPassword", R.string.NewPassword); + } + + @Override + public void setParams(Bundle params, boolean restore) { + if (params == null) { + if (nextCodeParams != null && nextCodeAuth != null) { + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + int resId; + if (nextType == AUTH_TYPE_PHRASE) { + resId = R.string.ReturnEnteringPhrase; + } else if (nextType == AUTH_TYPE_WORD) { + resId = R.string.ReturnEnteringWord; + } else { + resId = R.string.ReturnEnteringSMS; + } + timeText.setText(AndroidUtilities.replaceArrows(getString(resId), true, dp(1), dp(1))); + } + return; + } + codeField.setText(""); + currentParams = params; + beginning = null; + nextType = params.getInt("nextType"); + prevType = params.getInt("prevType", 0); + emailPhone = params.getString("ephone"); + if (currentParams.containsKey("beginning")) { + beginning = currentParams.getString("beginning"); + } + requestPhone = params.getString("phoneFormated"); + phoneHash = params.getString("phoneHash"); + phone = currentParams.getString("phone"); + time = params.getInt("timeout"); + + if (prevType == AUTH_TYPE_PHRASE) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringPhrase), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_WORD) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringWord), true, dp(-1), dp(1))); + } else if (prevType == AUTH_TYPE_MESSAGE || prevType == AUTH_TYPE_SMS || prevType == AUTH_TYPE_CALL || prevType == AUTH_TYPE_FLASH_CALL || prevType == AUTH_TYPE_FRAGMENT_SMS) { + prevTypeTextView.setVisibility(View.VISIBLE); + prevTypeTextView.setText(AndroidUtilities.replaceArrows(getString(R.string.BackEnteringCode), true, dp(-1), dp(1))); + } else { + prevTypeTextView.setVisibility(View.GONE); + } + + nextCodeParams = null; + nextCodeAuth = null; + nextPressed = false; + isResendingCode = false; + isRequestingFirebaseSms = false; + timeText.invalidate(); + + final int a = currentType == AUTH_TYPE_WORD ? 0 : 1; + final String formattedPhone = "+" + PhoneFormat.getInstance().format(PhoneFormat.stripExceptNumbers(phone)); + if (beginning == null) { + confirmTextView.setText(AndroidUtilities.replaceTags(formatString(a == 0 ? R.string.SMSWordText : R.string.SMSPhraseText, formattedPhone))); + } else { + confirmTextView.setText(AndroidUtilities.replaceTags(formatString(a == 0 ? R.string.SMSWordBeginningText : R.string.SMSPhraseBeginningText, formattedPhone, beginning))); + } + + showKeyboard(codeField); + codeField.requestFocus(); + + if (imageView.getAnimatedDrawable() != null) { + imageView.getAnimatedDrawable().setCurrentFrame(0, false); + } + AndroidUtilities.runOnUIThread(imageView::playAnimation, 500); + + checkPaste(false); + animateError(false); + + lastCurrentTime = System.currentTimeMillis(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + if (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) { + createTimer(); + } else { + timeText.setVisibility(GONE); + } + } + + private void animateError(boolean show) { + errorShown = show; + float value = show ? 1f : 0f; + outlineField.animateError(value); + errorTextView.animate().scaleX(.9f + .1f * value).scaleY(.9f + .1f * value).alpha(value).translationY((1f - value) * dp(-5)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(290).start(); + + boolean showPaste = pasteShown && !errorShown; + value = showPaste ? 1f : 0f; + infoTextView.animate().scaleX(.9f + .1f * value).scaleY(.9f + .1f * value).alpha(value).translationY((1f - value) * dp(errorShown ? 5 : -5)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(290).start(); + } + + private final Runnable dismissField = () -> animateError(false); + + private float shiftDp = -3; + private void onInputError(boolean asBeginning) { + if (getParentActivity() == null) { + return; + } + try { + codeField.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) {} + final int a = currentType == AUTH_TYPE_WORD ? 0 : 1; + if (asBeginning) { + errorTextView.setText(getString(a == 0 ? R.string.SMSWordBeginningError : R.string.SMSPhraseBeginningError)); + } else if (TextUtils.isEmpty(codeField.getText())) { + errorTextView.setText(""); + } else { + errorTextView.setText(getString(a == 0 ? R.string.SMSWordError : R.string.SMSPhraseError)); + } + if (!errorShown && !pasted) { + AndroidUtilities.shakeViewSpring(codeField, shiftDp); + AndroidUtilities.shakeViewSpring(errorTextView, shiftDp); + } + AndroidUtilities.cancelRunOnUIThread(dismissField); + animateError(true); + AndroidUtilities.runOnUIThread(dismissField, 10_000); + shiftDp = -shiftDp; + } + + @Override + public void onNextPressed(String code) { + if (nextPressed) { + return; + } + + code = codeField.getText().toString(); + if (code.length() == 0) { + onInputError(false); + return; + } + + if (!beginsOk(code)) { + onInputError(true); + return; + } + + nextPressed = true; + + TLRPC.TL_auth_signIn req = new TLRPC.TL_auth_signIn(); + req.phone_number = requestPhone; + req.phone_code = code; + req.phone_code_hash = phoneHash; + req.flags |= 1; + int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + needHideProgress(false, true); + + boolean ok = false; + + if (error == null) { + nextPressed = false; + ok = true; + showDoneButton(false, true); + destroyTimer(); +// destroyCodeTimer(); + if (response instanceof TLRPC.TL_auth_authorizationSignUpRequired) { + TLRPC.TL_auth_authorizationSignUpRequired authorization = (TLRPC.TL_auth_authorizationSignUpRequired) response; + if (authorization.terms_of_service != null) { + currentTermsOfService = authorization.terms_of_service; + } + Bundle params = new Bundle(); + params.putString("phoneFormated", requestPhone); + params.putString("phoneHash", phoneHash); + params.putString("code", req.phone_code); + + setPage(VIEW_REGISTER, true, params, false); + } else { + onAuthSuccess((TLRPC.TL_auth_authorization) response); + } + } else { + lastError = error.text; + if (error.text.contains("SESSION_PASSWORD_NEEDED")) { + ok = true; + TLRPC.TL_account_getPassword req2 = new TLRPC.TL_account_getPassword(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; + showDoneButton(false, true); + if (error1 == null) { + TLRPC.account_Password password = (TLRPC.account_Password) response1; + if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { + AlertsCreator.showUpdateAppAlert(getParentActivity(), getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + return; + } + Bundle bundle = new Bundle(); + SerializedData data = new SerializedData(password.getObjectSize()); + password.serializeToStream(data); + bundle.putString("password", Utilities.bytesToHex(data.toByteArray())); + bundle.putString("phoneFormated", requestPhone); + bundle.putString("phoneHash", phoneHash); + bundle.putString("code", req.phone_code); + + setPage(VIEW_PASSWORD, true, bundle, false); + } else { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), error1.text); + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + destroyTimer(); +// destroyCodeTimer(); + } else { + nextPressed = false; +// showDoneButton(true, true); +// if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { +// createTimer(); +// } + if (currentType != AUTH_TYPE_FLASH_CALL) { + boolean isWrongCode = false; + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + onInputError(false); + isWrongCode = true; + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("CodeExpired", R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("FloodWait", R.string.FloodWait)); + } else { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + } + + if (isWrongCode) { + codeField.post(() -> { + codeField.requestFocus(); + if (beginning != null && beginning.length() > 1) { + String text = codeField.getText().toString(); + int select = trimLeftLen(text) + beginning.length(); + boolean nextIsSpace = select >= 0 && select < text.length() && text.charAt(select) == ' '; + codeField.setSelection(Utilities.clamp(select + (nextIsSpace ? 1 : 0), text.length(), 0), codeField.getText().length()); + } else { + codeField.setSelection(0, codeField.getText().length()); + } + }); + } else { + codeField.setText(""); + codeField.requestFocus(); + } + } + } + } + if (ok) { + if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.endIncomingCall(); + AndroidUtilities.setWaitingForCall(false); + } + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + needShowProgress(reqId, true); + showDoneButton(true, true); + } + + + private void resendCode() { + if (nextPressed || isResendingCode || isRequestingFirebaseSms) { + return; + } + + isResendingCode = true; + timeText.invalidate(); + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); +// problemText.invalidate(); + + final Bundle params = new Bundle(); + params.putString("phone", phone); + params.putString("ephone", emailPhone); + params.putString("phoneFormated", requestPhone); + + nextPressed = true; + + TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; + if (error == null) { + fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); + } else { + if (error.text != null) { + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.FloodWait)); + } else if (error.code != -1000) { + needShowAlert(getString(R.string.RestorePasswordNoEmailTitle), getString(R.string.ErrorOccurred) + "\n" + error.text); + } + } + } + needHideProgress(false); + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + needShowProgress(reqId); + } + + @Override + public boolean onBackPressed(boolean force) { + needHideProgress(true); + if (prevType != 0) { + setPage(prevType, true, null, true); + return false; + } + currentParams = null; + nextPressed = false; + return true; + } + + @Override + public void onResume() { + super.onResume(); + checkPaste(true); + } + + @Override + public void onShow() { + super.onShow(); + AndroidUtilities.runOnUIThread(() -> { + if (codeField != null) { + codeField.requestFocus(); + codeField.setSelection(codeField.length()); + AndroidUtilities.showKeyboard(codeField); + } + }, SHOW_DELAY); + } + + @Override + public void onHide() { + super.onHide(); + AndroidUtilities.cancelRunOnUIThread(checkPasteRunnable); + } + + @Override + public void saveStateParams(Bundle bundle) { + if (currentParams != null) { + bundle.putBundle("recoveryview_word" + currentType, currentParams); + } + } + + @Override + public void restoreStateParams(Bundle bundle) { + currentParams = bundle.getBundle("recoveryview_word" + currentType); + if (currentParams != null) { + setParams(currentParams, true); + } + } + +// private void setProblemTextVisible(boolean visible) { +// if (problemText == null) { +// return; +// } +// float newAlpha = visible ? 1f : 0f; +// if (problemText.getAlpha() != newAlpha) { +// problemText.animate().cancel(); +// problemText.animate().alpha(newAlpha).setDuration(150).start(); +// } +// } +// +// private void createCodeTimer() { +// if (codeTimer != null) { +// return; +// } +// codeTime = 15000; +// if (time > codeTime) { +// codeTime = time; +// } +// codeTimer = new Timer(); +// lastCodeTime = System.currentTimeMillis(); +// codeTimer.schedule(new TimerTask() { +// @Override +// public void run() { +// AndroidUtilities.runOnUIThread(() -> { +// double currentTime = System.currentTimeMillis(); +// double diff = currentTime - lastCodeTime; +// lastCodeTime = currentTime; +// codeTime -= diff; +// if (codeTime <= 1000) { +// setProblemTextVisible(true); +// timeText.setVisibility(GONE); +// if (problemText != null) { +// problemText.setVisibility(VISIBLE); +// } +// destroyCodeTimer(); +// } +// }); +// } +// }, 0, 1000); +// } + +// +// private void destroyCodeTimer() { +// try { +// synchronized (timerSync) { +// if (codeTimer != null) { +// codeTimer.cancel(); +// codeTimer = null; +// } +// } +// } catch (Exception e) { +// FileLog.e(e); +// } +// } + + private void createTimer() { + if (timeTimer != null) { + return; + } + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + timeText.setTag(R.id.color_key_tag, Theme.key_windowBackgroundWhiteGrayText); +// if (progressView != null) { +// progressView.resetProgressAnimation(); +// } + timeTimer = new Timer(); + timeTimer.schedule(new TimerTask() { + @Override + public void run() { + if (timeTimer == null) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + double currentTime = System.currentTimeMillis(); + double diff = currentTime - lastCurrentTime; + lastCurrentTime = currentTime; + time -= diff; + if (time >= 1000) { + int minutes = time / 1000 / 60; + int seconds = time / 1000 - minutes * 60; + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setText(LocaleController.formatString(R.string.CallAvailableIn2, minutes, seconds)); + } else if (nextType == AUTH_TYPE_SMS) { + timeText.setText(LocaleController.formatString(R.string.SmsAvailableIn2, minutes, seconds)); + } +// if (progressView != null && !progressView.isProgressAnimationRunning()) { +// progressView.startProgressAnimation(time - 1000L); +// } + } else { + destroyTimer(); + if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + if (nextType == AUTH_TYPE_CALL) { + timeText.setText(getString(R.string.RequestCallButton)); + } else if (nextType == AUTH_TYPE_FRAGMENT_SMS) { + timeText.setText(getString(R.string.DidNotGetTheCodeFragment)); + } else if (nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FLASH_CALL) { + timeText.setText(getString(R.string.RequestMissedCall)); + } else { + timeText.setText(replaceArrows(getString(R.string.RequestAnotherSMS), true, 0, 0)); + } + timeText.setTextColor(Theme.getColor(Theme.key_chats_actionBackground)); + timeText.setTag(R.id.color_key_tag, Theme.key_chats_actionBackground); + } + } + }); + } + }, 0, 1000); + } + + private void destroyTimer() { + timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + timeText.setTag(R.id.color_key_tag, Theme.key_windowBackgroundWhiteGrayText); + try { + synchronized (timerSync) { + if (timeTimer != null) { + timeTimer.cancel(); + timeTimer = null; + } + } + } catch (Exception e) { + FileLog.e(e); + } + } + + private boolean beginsOk(String text) { + if (beginning == null) { + return true; + } + String lt = trimLeft(text).toLowerCase(); + String lb = beginning.toLowerCase(); + int len = Math.min(lt.length(), lb.length()); + if (len <= 0) return true; + return TextUtils.equals(lt.substring(0, len), lb.substring(0, len)); + } + + private int trimLeftLen(String str) { + int len = str.length(); + int st = 0; + while ((st < len) && (str.charAt(st) <= ' ')) { + st++; + } + return st; + } + + private String trimLeft(String str) { + int len = str.length(); + int st = 0; + + while ((st < len) && (str.charAt(st) <= ' ')) { + st++; + } +// while ((st < len) && (str.charAt(len - 1) <= ' ')) { +// len--; +// } + return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str; + } + } + + @Override + public void clearViews() { + if (fragmentView != null) { + ViewGroup parent = (ViewGroup) fragmentView.getParent(); + if (parent != null) { + try { + onRemoveFromParent(); + parent.removeViewInLayout(fragmentView); + } catch (Exception e) { + FileLog.e(e); + } + } + if (pendingSwitchingAccount) { + cachedFragmentView = fragmentView; + } + fragmentView = null; + } + if (actionBar != null && !pendingSwitchingAccount) { + ViewGroup parent = (ViewGroup) actionBar.getParent(); + if (parent != null) { + try { + parent.removeViewInLayout(actionBar); + } catch (Exception e) { + FileLog.e(e); + } + } + actionBar = null; + } + clearStoryViewers(); + parentLayout = null; } private void regenerateLoginToken(Boolean refresh) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index d7b32bbf14..8ec1bb975d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -8,9 +8,13 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; import static org.telegram.messenger.NotificationsController.TYPE_CHANNEL; import static org.telegram.messenger.NotificationsController.TYPE_GROUP; import static org.telegram.messenger.NotificationsController.TYPE_PRIVATE; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_MESSAGES; +import static org.telegram.messenger.NotificationsController.TYPE_REACTIONS_STORIES; import static org.telegram.messenger.NotificationsController.TYPE_STORIES; import android.animation.Animator; @@ -22,6 +26,8 @@ import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; @@ -30,11 +36,14 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.LongSparseArray; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.OvershootInterpolator; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.recyclerview.widget.DefaultItemAnimator; @@ -53,6 +62,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLObject; @@ -68,6 +78,7 @@ import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; +import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; @@ -107,6 +118,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements private final static int search_button = 0; + private int settingsStart, settingsEnd; private int exceptionsStart, exceptionsEnd; private boolean showAutoExceptions = true; @@ -260,6 +272,8 @@ private int getLedColor() { case TYPE_GROUP: color = getNotificationsSettings().getInt("GroupLed", color); break; case TYPE_STORIES: color = getNotificationsSettings().getInt("StoriesLed", color); break; case TYPE_CHANNEL: color = getNotificationsSettings().getInt("ChannelLed", color); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: color = getNotificationsSettings().getInt("ReactionsLed", color); break; } for (int a = 0; a < 9; a++) { if (TextColorCell.colorsToSave[a] == color) { @@ -277,12 +291,12 @@ private String getPopupOption() { case TYPE_GROUP: option = getNotificationsSettings().getInt("popupGroup", 0); break; case TYPE_CHANNEL: option = getNotificationsSettings().getInt("popupChannel", 0); break; } - return LocaleController.getString(popupOptions[Utilities.clamp(option, popupOptions.length - 1, 0)]); + return getString(popupOptions[Utilities.clamp(option, popupOptions.length - 1, 0)]); } private String getSound() { final SharedPreferences prefs = getNotificationsSettings(); - String value = LocaleController.getString("SoundDefault", R.string.SoundDefault); + String value = getString("SoundDefault", R.string.SoundDefault); long documentId; switch (currentType) { case TYPE_PRIVATE: @@ -293,6 +307,11 @@ private String getSound() { value = prefs.getString("GroupSound", value); documentId = prefs.getLong("GroupSoundDocId", 0); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: + value = prefs.getString("ReactionSound", value); + documentId = prefs.getLong("ReactionSoundDocId", 0); + break; case TYPE_STORIES: value = prefs.getString("StoriesSound", value); documentId = prefs.getLong("StoriesSoundDocId", 0); @@ -305,14 +324,14 @@ private String getSound() { if (documentId != 0) { TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId); if (document == null) { - return LocaleController.getString("CustomSound", R.string.CustomSound); + return getString("CustomSound", R.string.CustomSound); } else { return NotificationsSoundActivity.trimTitle(document, FileLoader.getDocumentFileName(document)); } } else if (value.equals("NoSound")) { - return LocaleController.getString("NoSound", R.string.NoSound); + return getString("NoSound", R.string.NoSound); } else if (value.equals("Default")) { - return LocaleController.getString("SoundDefault", R.string.SoundDefault); + return getString("SoundDefault", R.string.SoundDefault); } return value; } @@ -324,8 +343,10 @@ private String getPriorityOption() { case TYPE_GROUP: option = getNotificationsSettings().getInt("priority_group", 1); break; case TYPE_STORIES: option = getNotificationsSettings().getInt("priority_stories", 1); break; case TYPE_CHANNEL: option = getNotificationsSettings().getInt("priority_channel", 1); break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: option = getNotificationsSettings().getInt("priority_react", 1); break; } - return LocaleController.getString(priorityOptions[Utilities.clamp(option, priorityOptions.length - 1, 0)]); + return getString(priorityOptions[Utilities.clamp(option, priorityOptions.length - 1, 0)]); } @Override @@ -336,9 +357,9 @@ public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (currentType == -1) { - actionBar.setTitle(LocaleController.getString("NotificationsExceptions", R.string.NotificationsExceptions)); + actionBar.setTitle(getString("NotificationsExceptions", R.string.NotificationsExceptions)); } else { - actionBar.setTitle(LocaleController.getString("Notifications", R.string.Notifications)); + actionBar.setTitle(getString("Notifications", R.string.Notifications)); } actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -362,7 +383,7 @@ public void onSearchCollapse() { searchAdapter.searchDialogs(null); searching = false; searchWas = false; - emptyView.setText(LocaleController.getString("NoExceptions", R.string.NoExceptions)); + emptyView.setText(getString("NoExceptions", R.string.NoExceptions)); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); listView.setFastScrollVisible(true); @@ -379,7 +400,7 @@ public void onTextChanged(EditText editText) { if (text.length() != 0) { searchWas = true; if (listView != null) { - emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + emptyView.setText(getString("NoResult", R.string.NoResult)); emptyView.showProgress(); listView.setAdapter(searchAdapter); searchAdapter.notifyDataSetChanged(); @@ -390,7 +411,7 @@ public void onTextChanged(EditText editText) { searchAdapter.searchDialogs(text); } }); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setSearchFieldHint(getString("Search", R.string.Search)); } searchAdapter = new SearchAdapter(context); @@ -401,7 +422,7 @@ public void onTextChanged(EditText editText) { emptyView = new EmptyTextProgressView(context); emptyView.setTextSize(18); - emptyView.setText(LocaleController.getString("NoExceptions", R.string.NoExceptions)); + emptyView.setText(getString("NoExceptions", R.string.NoExceptions)); emptyView.showTextView(); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -409,12 +430,17 @@ public void onTextChanged(EditText editText) { @Override protected void dispatchDraw(Canvas canvas) { if (currentType != -1) { - drawSectionBackground(canvas, exceptionsStart, exceptionsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + if (exceptionsStart >= 0) { + drawSectionBackground(canvas, exceptionsStart, exceptionsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + } + if (currentType != TYPE_REACTIONS_MESSAGES && currentType != TYPE_REACTIONS_STORIES) { + drawSectionBackground(canvas, settingsStart, settingsEnd, getThemedColor(Theme.key_windowBackgroundWhite)); + } } super.dispatchDraw(canvas); } }; - listView.setTranslateSelector(true); +// listView.setTranslateSelector(true); listView.setEmptyView(emptyView); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setVerticalScrollBarEnabled(false); @@ -429,16 +455,22 @@ protected void dispatchDraw(Canvas canvas) { if (listView.getAdapter() == adapter && position >= 0 && position < items.size()) { item = items.get(position); } + if (item != null && item.viewType == VIEW_TYPE_EXPAND) { + expanded = !expanded; + updateRows(true); + return; + } if (currentType == TYPE_STORIES && item != null && item.exception != null) { NotificationsSettingsActivity.NotificationException exception = item.exception; ItemOptions.makeOptions(NotificationsCustomSettingsActivity.this, view) - .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, LocaleController.getString(R.string.NotificationsStoryMute), false, () -> { + .setGravity(Gravity.LEFT) + .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, getString(R.string.NotificationsStoryMute), false, () -> { updateMute(exception, view, position, false, true); }) - .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, LocaleController.getString(R.string.NotificationsStoryUnmute), false, () -> { + .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, getString(R.string.NotificationsStoryUnmute), false, () -> { updateMute(exception, view, position, false, false); }) - .addIf(!exception.auto, R.drawable.msg_delete, LocaleController.getString("DeleteException", R.string.DeleteException), true, () -> { + .addIf(!exception.auto, R.drawable.msg_delete, getString("DeleteException", R.string.DeleteException), true, () -> { deleteException(exception, view, position); }) .show(); @@ -482,15 +514,16 @@ protected void dispatchDraw(Canvas canvas) { } ItemOptions.makeOptions(NotificationsCustomSettingsActivity.this, view) - .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, LocaleController.getString(R.string.NotificationsStoryMute), false, () -> { + .setGravity(Gravity.LEFT) + .addIf(exception.notify <= 0 || exception.auto, R.drawable.msg_mute, getString(R.string.NotificationsStoryMute), false, () -> { actionBar.closeSearchField(); updateMute(exception, view, -1, newException, true); }) - .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, LocaleController.getString(R.string.NotificationsStoryUnmute), false, () -> { + .addIf(exception.notify > 0 || exception.auto, R.drawable.msg_unmute, getString(R.string.NotificationsStoryUnmute), false, () -> { actionBar.closeSearchField(); updateMute(exception, view, -1, newException, false); }) - .addIf(!newException && !exception.auto, R.drawable.msg_delete, LocaleController.getString("DeleteException", R.string.DeleteException), true, () -> { + .addIf(!newException && !exception.auto, R.drawable.msg_delete, getString("DeleteException", R.string.DeleteException), true, () -> { deleteException(exception, view, position); }) .show(); @@ -545,7 +578,7 @@ protected void dispatchDraw(Canvas canvas) { } long did = exception.did; - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did, false, false); ChatNotificationsPopupWrapper chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, null, true, true, new ChatNotificationsPopupWrapper.Callback() { @Override public void toggleSound() { @@ -719,9 +752,9 @@ private void setDefault() { presentFragment(activity); } else if (item.id == 7) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("NotificationsDeleteAllExceptionTitle", R.string.NotificationsDeleteAllExceptionTitle)); - builder.setMessage(LocaleController.getString("NotificationsDeleteAllExceptionAlert", R.string.NotificationsDeleteAllExceptionAlert)); - builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> { + builder.setTitle(getString("NotificationsDeleteAllExceptionTitle", R.string.NotificationsDeleteAllExceptionTitle)); + builder.setMessage(getString("NotificationsDeleteAllExceptionAlert", R.string.NotificationsDeleteAllExceptionAlert)); + builder.setPositiveButton(getString("Delete", R.string.Delete), (dialogInterface, i) -> { SharedPreferences preferences = getNotificationsSettings(); SharedPreferences.Editor editor = preferences.edit(); for (int a = 0, N = exceptions.size(); a < N; a++) { @@ -748,16 +781,16 @@ private void setDefault() { updateRows(true); getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); } - } else if (item.viewType == VIEW_TYPE_CHECK2) { + } else if (item.id == BUTTON_ENABLE || item.id == BUTTON_NEW_STORIES) { enabled = getNotificationsController().isGlobalNotificationsEnabled(currentType); - NotificationsCheckCell checkCell = (NotificationsCheckCell) view; + TextCheckCell checkCell = (TextCheckCell) view; RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(position); if (currentType == TYPE_STORIES) { @@ -771,24 +804,9 @@ private void setDefault() { editor.putBoolean("EnableAllStories", !enabled); storiesEnabled = !enabled; } - editor.commit(); + editor.apply(); getNotificationsController().updateServerNotificationsSettings(currentType); - checkCell.setChecked(!enabled); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - for (int i = 0; i < items.size(); ++i) { - ItemInner item2 = items.get(i); - if (item2.id == 5) { - item2.checked = storiesAuto && (storiesEnabled == null || !storiesEnabled); - RecyclerView.ViewHolder holder2 = listView.findViewHolderForAdapterPosition(i); - if (holder2 != null && holder2.itemView instanceof TextCheckCell) { - TextCheckCell checkCell1 = (TextCheckCell) holder2.itemView; - checkCell1.setChecked(item2.checked); - } - break; - } - } + updateRows(true); if (showAutoExceptions != (storiesEnabled == null)) { toggleShowAutoExceptions(); } @@ -798,36 +816,10 @@ private void setDefault() { if (!enabled) { getNotificationsController().setGlobalNotificationsEnabled(currentType, 0); - checkCell.setChecked(true); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - checkRowsEnabled(); + updateRows(true); } else { AlertsCreator.showCustomNotificationsDialog(NotificationsCustomSettingsActivity.this, 0, 0, currentType, exceptions, autoExceptions, currentAccount, param -> { - int offUntil; - SharedPreferences preferences = getNotificationsSettings(); - if (currentType == TYPE_PRIVATE) { - offUntil = preferences.getInt("EnableAll2", 0); - } else if (currentType == TYPE_GROUP) { - offUntil = preferences.getInt("EnableGroup2", 0); - } else { - offUntil = preferences.getInt("EnableChannel2", 0); - } - int currentTime = getConnectionsManager().getCurrentTime(); - int iconType; - if (offUntil < currentTime) { - iconType = 0; - } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - iconType = 0; - } else { - iconType = 2; - } - checkCell.setChecked(getNotificationsController().isGlobalNotificationsEnabled(currentType), iconType); - if (holder != null) { - adapter.onBindViewHolder(holder, position); - } - checkRowsEnabled(); + updateRows(true); }); } } else if (item.id == 3) { @@ -850,7 +842,7 @@ private void setDefault() { if (position >= 0 && position < items.size()) { items.get(position).color = getLedColor(); } - ((TextColorCell) view).setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), getLedColor(), true); + ((TextColorCell) view).setTextAndColor(getString("LedColor", R.string.LedColor), getLedColor(), true); } else { updateRows(true); } @@ -864,7 +856,7 @@ private void setDefault() { if (position >= 0 && position < items.size()) { items.get(position).text2 = getPopupOption(); } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("PopupNotification", R.string.PopupNotification), getPopupOption(), true, ((TextSettingsCell) view).needDivider); + ((TextSettingsCell) view).setTextAndValue(getString("PopupNotification", R.string.PopupNotification), getPopupOption(), true, ((TextSettingsCell) view).needDivider); } else { updateRows(true); } @@ -880,16 +872,18 @@ private void setDefault() { key = "vibrate_group"; } else if (currentType == TYPE_STORIES) { key = "vibrate_stories"; + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + key = "vibrate_react"; } else { key = "vibrate_channel"; } showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), 0, 0, key, () -> { if (view instanceof TextSettingsCell) { - String value = LocaleController.getString(vibrateLabels[Utilities.clamp(getNotificationsSettings().getInt(key, 0), vibrateLabels.length - 1, 0)]); + String value = getString(vibrateLabels[Utilities.clamp(getNotificationsSettings().getInt(key, 0), vibrateLabels.length - 1, 0)]); if (position >= 0 && position < items.size()) { items.get(position).text2 = value; } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), value, true, true); + ((TextSettingsCell) view).setTextAndValue(getString("Vibrate", R.string.Vibrate), value, true, true); } else { updateRows(true); } @@ -903,12 +897,12 @@ private void setDefault() { if (position >= 0 && position < items.size()) { items.get(position).text2 = getPriorityOption(); } - ((TextSettingsCell) view).setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption(), true, ((TextSettingsCell) view).needDivider); + ((TextSettingsCell) view).setTextAndValue(getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption(), true, ((TextSettingsCell) view).needDivider); } else { updateRows(true); } })); - } else if (item.id == 5) { + } else if (item.id == BUTTON_IMPORTANT_STORIES) { if (!view.isEnabled()) { return; } @@ -950,6 +944,9 @@ private void setDefault() { } else if (currentType == TYPE_STORIES) { enabled = !preferences.getBoolean("EnableHideStoriesSenders", false); editor.putBoolean("EnableHideStoriesSenders", enabled); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + enabled = preferences.getBoolean("EnableReactionsPreview", true); + editor.putBoolean("EnableReactionsPreview", !enabled); } else { enabled = preferences.getBoolean("EnablePreviewChannel", true); editor.putBoolean("EnablePreviewChannel", !enabled); @@ -959,6 +956,56 @@ private void setDefault() { if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!enabled); } + } else if (item != null && (item.id == BUTTON_MESSAGES_REACTIONS || item.id == BUTTON_STORIES_REACTIONS)) { + final boolean check = LocaleController.isRTL ? x < dp(76) : x > view.getMeasuredWidth() - dp(76); + + SharedPreferences prefs = getNotificationsSettings(); + if (check) { + final String key = item.id == BUTTON_MESSAGES_REACTIONS ? "EnableReactionsMessages" : "EnableReactionsStories"; + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(key, !prefs.getBoolean(key, true)); + editor.apply(); + updateRows(true); + getNotificationsController().updateServerNotificationsSettings(currentType); + } else { + final String key = item.id == BUTTON_MESSAGES_REACTIONS ? "EnableReactionsMessagesContacts" : "EnableReactionsStoriesContacts"; + final LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + boolean[] contacts = new boolean[] { prefs.getBoolean(key, false) }; + + RadioColorCell[] cells = new RadioColorCell[2]; + for (int a = 0; a < cells.length; ++a) { + cells[a] = new RadioColorCell(context, getResourceProvider()); + cells[a].setPadding(dp(4), 0, dp(4), 0); + cells[a].setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + cells[a].setTextAndValue(getString(a == 0 ? R.string.NotifyAboutReactionsFromEveryone : R.string.NotifyAboutReactionsFromContacts), a == 0 ? !contacts[0] : contacts[0]); + cells[a].setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); + linearLayout.addView(cells[a]); + final int finalA = a; + cells[a].setOnClickListener(v -> { + contacts[0] = finalA == 1; + for (int i = 0; i < cells.length; ++i) { + cells[i].setChecked(contacts[0] == (i == 1), true); + } + }); + } + + showDialog( + new AlertDialog.Builder(getContext(), resourceProvider) + .setTitle(getString(R.string.NotifyAboutReactionsFrom)) + .setView(linearLayout) + .setNegativeButton(getString(R.string.Cancel), null) + .setPositiveButton(getString(R.string.Save), (di, w) -> { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(key, contacts[0]); + editor.apply(); + updateRows(true); + getNotificationsController().updateServerNotificationsSettings(currentType); + }) + .create() + ); + } } }); DefaultItemAnimator itemAnimator = new DefaultItemAnimator() { @@ -1015,8 +1062,8 @@ private void checkRowsEnabled() { item = items.get(position); } final boolean enabled; - if (item != null && item.id == 5) { - enabled = storiesEnabled == null || !storiesEnabled; + if (item != null && (item.id == BUTTON_IMPORTANT_STORIES || item.id == BUTTON_NEW_STORIES || item.id == BUTTON_ENABLE)) { + enabled = true; } else { enabled = globalEnabled; } @@ -1296,6 +1343,14 @@ private void loadExceptions() { R.string.NotificationsPriorityMedium }; + private static final int BUTTON_ENABLE = 100; + private static final int BUTTON_NEW_STORIES = 101; + private static final int BUTTON_IMPORTANT_STORIES = 102; + private static final int BUTTON_MESSAGES_REACTIONS = 103; + private static final int BUTTON_STORIES_REACTIONS = 104; + + boolean expanded; + private void updateRows(boolean animated) { oldItems.clear(); oldItems.addAll(items); @@ -1303,68 +1358,137 @@ private void updateRows(boolean animated) { SharedPreferences prefs = getNotificationsSettings(); boolean enabled = false; if (currentType != -1) { - items.add(ItemInner.asCheck2()); - items.add(ItemInner.asShadow(null)); - items.add(ItemInner.asHeader(LocaleController.getString(R.string.SETTINGS))); + items.add(ItemInner.asHeader(getString(R.string.NotifyMeAbout))); + if (currentType == TYPE_STORIES) { + items.add(ItemInner.asCheck(BUTTON_NEW_STORIES, getString(R.string.NotifyMeAboutNewStories), prefs.getBoolean("EnableAllStories", false))); + if (!prefs.getBoolean("EnableAllStories", false)) { + items.add(ItemInner.asCheck(BUTTON_IMPORTANT_STORIES, getString(R.string.NotifyMeAboutImportantStories), storiesAuto && (storiesEnabled == null || !storiesEnabled))); + } + items.add(ItemInner.asShadow(-1, getString(R.string.StoryAutoExceptionsInfo))); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + items.add(ItemInner.asCheck2( + BUTTON_MESSAGES_REACTIONS, + R.drawable.msg_markunread, + getString(R.string.NotifyMeAboutMessagesReactions), + getString( + !prefs.getBoolean("EnableReactionsMessages", true) ? + R.string.NotifyFromNobody : + prefs.getBoolean("EnableReactionsMessagesContacts", false) ? + R.string.NotifyFromContacts : + R.string.NotifyFromEveryone + ), + prefs.getBoolean("EnableReactionsMessages", true) + )); + items.add(ItemInner.asCheck2( + BUTTON_STORIES_REACTIONS, + R.drawable.msg_stories_saved, + getString(R.string.NotifyMeAboutStoriesReactions), + getString( + !prefs.getBoolean("EnableReactionsStories", true) ? + R.string.NotifyFromNobody : + prefs.getBoolean("EnableReactionsStoriesContacts", false) ? + R.string.NotifyFromContacts : + R.string.NotifyFromEveryone + ), + prefs.getBoolean("EnableReactionsStories", true) + )); + items.add(ItemInner.asShadow(-1, null)); + } else { + int text; + if (currentType == TYPE_PRIVATE) { + text = R.string.NotifyMeAboutPrivate; + } else if (currentType == TYPE_GROUP) { + text = R.string.NotifyMeAboutGroups; + } else { + text = R.string.NotifyMeAboutChannels; + } + items.add(ItemInner.asCheck(BUTTON_ENABLE, getString(text), getNotificationsController().isGlobalNotificationsEnabled(currentType))); + items.add(ItemInner.asShadow(-1, null)); + } + items.add(ItemInner.asHeader(getString(R.string.SETTINGS))); + settingsStart = items.size() - 1; if (currentType == TYPE_STORIES) { - items.add(ItemInner.asCheck(0, LocaleController.getString(R.string.NotificationShowSenderNames), !prefs.getBoolean("EnableHideStoriesSenders", false))); + items.add(ItemInner.asCheck(0, getString(R.string.NotificationShowSenderNames), !prefs.getBoolean("EnableHideStoriesSenders", false))); + } else if (currentType == TYPE_REACTIONS_MESSAGES || currentType == TYPE_REACTIONS_STORIES) { + items.add(ItemInner.asCheck(0, getString(R.string.NotificationShowSenderNames), prefs.getBoolean("EnableReactionsPreview", true))); } else { switch (currentType) { case TYPE_PRIVATE: enabled = prefs.getBoolean("EnablePreviewAll", true); break; case TYPE_GROUP: enabled = prefs.getBoolean("EnablePreviewGroup", true); break; case TYPE_CHANNEL: enabled = prefs.getBoolean("EnablePreviewChannel", true); break; } - items.add(ItemInner.asCheck(0, LocaleController.getString(R.string.MessagePreview), enabled)); + items.add(ItemInner.asCheck(0, getString(R.string.MessagePreview), enabled)); } - items.add(ItemInner.asColor(LocaleController.getString("LedColor", R.string.LedColor), getLedColor())); - - int vibrate = 0; - switch (currentType) { - case TYPE_PRIVATE: vibrate = prefs.getInt("vibrate_messages", 0); break; - case TYPE_GROUP: vibrate = prefs.getInt("vibrate_group", 0); break; - case TYPE_STORIES: vibrate = prefs.getInt("vibrate_stories", 0); break; - case TYPE_CHANNEL: vibrate = prefs.getInt("vibrate_channel", 0); break; - } - items.add(ItemInner.asSetting(1, LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString(vibrateLabels[Utilities.clamp(vibrate, vibrateLabels.length - 1, 0)]))); + items.add(ItemInner.asSetting(3, getString("Sound", R.string.Sound), getSound())); - if (currentType == TYPE_PRIVATE || currentType == TYPE_GROUP) { - items.add(ItemInner.asSetting(2, LocaleController.getString("PopupNotification", R.string.PopupNotification), getPopupOption())); - } + if (expanded) { - items.add(ItemInner.asSetting(3, LocaleController.getString("Sound", R.string.Sound), getSound())); + items.add(ItemInner.asColor(getString("LedColor", R.string.LedColor), getLedColor())); - if (Build.VERSION.SDK_INT >= 21) { - items.add(ItemInner.asSetting(4, LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption())); - } - - if (currentType == TYPE_STORIES) { - items.add(ItemInner.asCheck(5, LocaleController.getString(R.string.StoryAutoExceptions), storiesAuto && (storiesEnabled == null || !storiesEnabled))); - items.add(ItemInner.asShadow(LocaleController.getString(R.string.StoryAutoExceptionsInfo))); + int vibrate = 0; + switch (currentType) { + case TYPE_PRIVATE: + vibrate = prefs.getInt("vibrate_messages", 0); + break; + case TYPE_GROUP: + vibrate = prefs.getInt("vibrate_group", 0); + break; + case TYPE_STORIES: + vibrate = prefs.getInt("vibrate_stories", 0); + break; + case TYPE_CHANNEL: + vibrate = prefs.getInt("vibrate_channel", 0); + break; + case TYPE_REACTIONS_MESSAGES: + case TYPE_REACTIONS_STORIES: + vibrate = prefs.getInt("vibrate_react", 0); + break; + } + items.add(ItemInner.asSetting(1, getString("Vibrate", R.string.Vibrate), getString(vibrateLabels[Utilities.clamp(vibrate, vibrateLabels.length - 1, 0)]))); + + if (currentType == TYPE_PRIVATE || currentType == TYPE_GROUP) { + items.add(ItemInner.asSetting(2, getString("PopupNotification", R.string.PopupNotification), getPopupOption())); + } + + if (Build.VERSION.SDK_INT >= 21) { + items.add(ItemInner.asSetting(4, getString("NotificationsImportance", R.string.NotificationsImportance), getPriorityOption())); + } + + items.add(ItemInner.asExpand(getString(R.string.NotifyLessOptions), false)); } else { - items.add(ItemInner.asShadow(null)); + items.add(ItemInner.asExpand(getString(R.string.NotifyMoreOptions), true)); } + settingsEnd = items.size() - 1; - items.add(ItemInner.asButton(6, R.drawable.msg_contact_add, LocaleController.getString("NotificationsAddAnException", R.string.NotificationsAddAnException))); + items.add(ItemInner.asShadow(-2, null)); } - exceptionsStart = items.size() - 1; - if (autoExceptions != null && showAutoExceptions) { - for (int i = 0; i < autoExceptions.size(); ++i) { - items.add(ItemInner.asException(autoExceptions.get(i))); + if (currentType != TYPE_REACTIONS_MESSAGES && currentType != TYPE_REACTIONS_STORIES) { + if (currentType != -1) { + items.add(ItemInner.asButton(6, R.drawable.msg_contact_add, getString("NotificationsAddAnException", R.string.NotificationsAddAnException))); } - } - if (exceptions != null) { - for (int i = 0; i < exceptions.size(); ++i) { - items.add(ItemInner.asException(exceptions.get(i))); + exceptionsStart = items.size() - 1; + if (autoExceptions != null && showAutoExceptions) { + for (int i = 0; i < autoExceptions.size(); ++i) { + items.add(ItemInner.asException(autoExceptions.get(i))); + } } - } - exceptionsEnd = items.size() - 1; - if (currentType != -1 || exceptions != null && !exceptions.isEmpty()) { - items.add(ItemInner.asShadow(null)); - } - if (exceptions != null && !exceptions.isEmpty()) { - items.add(ItemInner.asButton(7, 0, LocaleController.getString("NotificationsDeleteAllException", R.string.NotificationsDeleteAllException))); + if (exceptions != null) { + for (int i = 0; i < exceptions.size(); ++i) { + items.add(ItemInner.asException(exceptions.get(i))); + } + } + exceptionsEnd = items.size() - 1; + if (currentType != -1 || exceptions != null && !exceptions.isEmpty()) { + items.add(ItemInner.asShadow(-3, null)); + } + if (exceptions != null && !exceptions.isEmpty()) { + items.add(ItemInner.asButton(7, 0, getString("NotificationsDeleteAllException", R.string.NotificationsDeleteAllException))); + } + } else { + exceptionsStart = -1; + exceptionsEnd = -1; } if (adapter != null) { if (animated) { @@ -1390,7 +1514,7 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat Ringtone rng = RingtoneManager.getRingtone(getParentActivity(), ringtone); if (rng != null) { if (ringtone.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { - name = LocaleController.getString("SoundDefault", R.string.SoundDefault); + name = getString("SoundDefault", R.string.SoundDefault); } else { name = rng.getTitle(getParentActivity()); } @@ -1676,14 +1800,14 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { position -= searchResult.size() + 1; ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); TLObject object = globalSearch.get(position); - cell.setData(object, null, LocaleController.getString("NotificationsOn", R.string.NotificationsOn), 0, position != globalSearch.size() - 1); + cell.setData(object, null, getString("NotificationsOn", R.string.NotificationsOn), 0, position != globalSearch.size() - 1); cell.setAddButtonVisible(true); } break; } case 1: { GraySectionCell cell = (GraySectionCell) holder.itemView; - cell.setText(LocaleController.getString("AddToExceptions", R.string.AddToExceptions)); + cell.setText(getString("AddToExceptions", R.string.AddToExceptions)); break; } } @@ -1706,6 +1830,7 @@ public int getItemViewType(int position) { private static final int VIEW_TYPE_SETTING = 5; private static final int VIEW_TYPE_CHECK2 = 6; private static final int VIEW_TYPE_BUTTON = 7; + private static final int VIEW_TYPE_EXPAND = 8; private static class ItemInner extends AdapterWithDiffUtils.Item { @@ -1732,6 +1857,15 @@ public static ItemInner asCheck(int id, CharSequence text, boolean checked) { item.checked = checked; return item; } + public static ItemInner asCheck2(int id, int icon, CharSequence text, CharSequence subtext, boolean checked) { + ItemInner item = new ItemInner(VIEW_TYPE_CHECK2); + item.id = id; + item.resId = icon; + item.text = text; + item.text2 = subtext; + item.checked = checked; + return item; + } public static ItemInner asException(NotificationsSettingsActivity.NotificationException exception) { ItemInner item = new ItemInner(VIEW_TYPE_USER); item.exception = exception; @@ -1743,8 +1877,9 @@ public static ItemInner asColor(CharSequence text, int color) { item.color = color; return item; } - public static ItemInner asShadow(CharSequence text) { + public static ItemInner asShadow(int id, CharSequence text) { ItemInner item = new ItemInner(VIEW_TYPE_SHADOW); + item.id = id; item.text = text; return item; } @@ -1755,9 +1890,6 @@ public static ItemInner asSetting(int id, CharSequence text, CharSequence value) item.text2 = value; return item; } - public static ItemInner asCheck2() { - return new ItemInner(VIEW_TYPE_CHECK2); - } public static ItemInner asButton(int id, int resId, CharSequence text) { ItemInner item = new ItemInner(VIEW_TYPE_BUTTON); item.id = id; @@ -1765,9 +1897,23 @@ public static ItemInner asButton(int id, int resId, CharSequence text) { item.text = text; return item; } + public static ItemInner asExpand(CharSequence text, boolean expand) { + ItemInner item = new ItemInner(VIEW_TYPE_EXPAND); + item.text = text; + item.resId = expand ? 1 : 0; + return item; + } @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ItemInner itemInner = (ItemInner) o; + return id == itemInner.id && color == itemInner.color && (viewType == VIEW_TYPE_EXPAND || resId == itemInner.resId && Objects.equals(text, itemInner.text) && (viewType == VIEW_TYPE_CHECK2 || Objects.equals(text2, itemInner.text2))) && exception == itemInner.exception; + } + + @Override + protected boolean contentsEquals(AdapterWithDiffUtils.Item o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ItemInner itemInner = (ItemInner) o; @@ -1825,7 +1971,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case VIEW_TYPE_CHECK2: - view = new NotificationsCheckCell(mContext); + view = new NotificationsCheckCell(mContext, 21, 64, true, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case VIEW_TYPE_BUTTON: @@ -1833,6 +1979,10 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view = new TextCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case VIEW_TYPE_EXPAND: + view = new ExpandView(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } return new RecyclerListView.Holder(view); } @@ -1888,39 +2038,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } case VIEW_TYPE_CHECK2: { NotificationsCheckCell checkCell = (NotificationsCheckCell) holder.itemView; - checkCell.setDrawLine(false); - String text; - StringBuilder builder = new StringBuilder(); - int offUntil; - SharedPreferences preferences = getNotificationsSettings(); - - if (currentType == TYPE_PRIVATE) { - text = LocaleController.getString("NotificationsForPrivateChats", R.string.NotificationsForPrivateChats); - offUntil = preferences.getInt("EnableAll2", 0); - } else if (currentType == TYPE_GROUP) { - text = LocaleController.getString("NotificationsForGroups", R.string.NotificationsForGroups); - offUntil = preferences.getInt("EnableGroup2", 0); - } else if (currentType == TYPE_STORIES) { - text = LocaleController.getString("NotificationsForStories", R.string.NotificationsForStories); - offUntil = preferences.getBoolean("EnableAllStories", false) ? 0 : Integer.MAX_VALUE; - } else { - text = LocaleController.getString("NotificationsForChannels", R.string.NotificationsForChannels); - offUntil = preferences.getInt("EnableChannel2", 0); - } - int currentTime = getConnectionsManager().getCurrentTime(); - boolean enabled; - int iconType; - if (enabled = offUntil < currentTime) { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); - iconType = 0; - } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); - iconType = 0; - } else { - builder.append(LocaleController.formatString("NotificationsOffUntil", R.string.NotificationsOffUntil, LocaleController.stringForMessageListDate(offUntil))); - iconType = 2; - } - checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, false); + checkCell.setDrawLine(true); + checkCell.setChecked(item.checked); + checkCell.setTextAndValueAndIconAndCheck(item.text, item.text2, item.resId, item.checked, 0, false, divider, true); break; } case VIEW_TYPE_BUTTON: { @@ -1934,6 +2054,12 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } break; } + case VIEW_TYPE_EXPAND: { + ExpandView textCell = (ExpandView) holder.itemView; + textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + textCell.set(item.text, item.resId == 1, divider); + break; + } } } @@ -1954,8 +2080,9 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { item = items.get(position); } final boolean enabled; - if (item != null && item.id == 5) { - enabled = storiesEnabled == null || !storiesEnabled; + if (item != null && item.id == BUTTON_IMPORTANT_STORIES) { + return; +// enabled = storiesEnabled == null || !storiesEnabled; } else { enabled = globalEnabled; } @@ -1992,6 +2119,49 @@ public int getItemViewType(int position) { } } + public class ExpandView extends TextCell { + public ImageView imageView; + public ExpandView(Context context) { + super(context); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN)); + imageView.setImageResource(R.drawable.msg_expand); + addView(imageView, LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 17, 0, 17,0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + imageView.measure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int w = right - left; + int l = LocaleController.isRTL ? dp(17) : w - dp(17 + 24); + int t = (bottom - top - dp(24)) / 2; + imageView.layout(l, t, l + dp(24), t + dp(24)); + } + + public void set(CharSequence text, boolean expand, boolean divider) { + setArrow(expand, true); + setText(text, divider); + } + + public void setArrow(boolean expand, boolean animated) { + if (animated) { + imageView.animate().rotation(expand ? 0 : 180).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(340).start(); + } else { + imageView.setRotation(expand ? 0 : 180); + } + } + + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 7a6dd1aa9a..998b82010c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.LocaleController.getString; + import android.app.Activity; import android.content.ComponentName; import android.content.Context; @@ -106,6 +108,7 @@ public static class NotificationException { private int groupRow; private int channelsRow; private int storiesRow; + private int reactionsRow; private int notificationsSection2Row; private int inappSectionRow; @@ -161,6 +164,7 @@ public boolean onFragmentCreate() { groupRow = rowCount++; channelsRow = rowCount++; storiesRow = rowCount++; + reactionsRow = rowCount++; notificationsSection2Row = rowCount++; callsSectionRow = rowCount++; @@ -203,6 +207,8 @@ public boolean onFragmentCreate() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); + getMessagesController().reloadReactionsNotifySettings(); + return super.onFragmentCreate(); } @@ -426,7 +432,7 @@ public void onFragmentDestroy() { public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); - actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); + actionBar.setTitle(getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { @@ -457,7 +463,7 @@ public boolean supportsPredictiveItemAnimations() { if (getParentActivity() == null) { return; } - if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow) { + if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow || position == reactionsRow) { int type; ArrayList exceptions; ArrayList autoExceptions = null; @@ -474,12 +480,16 @@ public boolean supportsPredictiveItemAnimations() { exceptions = exceptionStories; autoExceptions = exceptionAutoStories; enabled = getNotificationsSettings().getBoolean("EnableAllStories", false); + } else if (position == reactionsRow) { + type = NotificationsController.TYPE_REACTIONS_MESSAGES; + exceptions = null; + enabled = getNotificationsSettings().getBoolean("EnableReactionsMessages", true) || getNotificationsSettings().getBoolean("EnableReactionsStories", true); } else { type = NotificationsController.TYPE_CHANNEL; exceptions = exceptionChannels; enabled = getNotificationsController().isGlobalNotificationsEnabled(type); } - if (exceptions == null) { + if (exceptions == null && type != NotificationsController.TYPE_REACTIONS_MESSAGES) { return; } @@ -496,6 +506,21 @@ public boolean supportsPredictiveItemAnimations() { } edit.apply(); getNotificationsController().updateServerNotificationsSettings(type); + } else if ( + type == NotificationsController.TYPE_REACTIONS_MESSAGES || + type == NotificationsController.TYPE_REACTIONS_STORIES + ) { + SharedPreferences.Editor edit = getNotificationsSettings().edit(); + if (enabledFinal) { + edit.putBoolean("EnableReactionsMessages", false); + edit.putBoolean("EnableReactionsStories", false); + } else { + edit.putBoolean("EnableReactionsMessages", true); + edit.putBoolean("EnableReactionsStories", true); + } + edit.apply(); + getNotificationsController().updateServerNotificationsSettings(type); + getNotificationsController().deleteNotificationChannelGlobal(type); } else { getNotificationsController().setGlobalNotificationsEnabled(type, !enabledFinal ? 0 : Integer.MAX_VALUE); } @@ -535,9 +560,9 @@ public boolean supportsPredictiveItemAnimations() { } } else if (position == resetNotificationsRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("ResetNotificationsAlertTitle", R.string.ResetNotificationsAlertTitle)); - builder.setMessage(LocaleController.getString("ResetNotificationsAlert", R.string.ResetNotificationsAlert)); - builder.setPositiveButton(LocaleController.getString("Reset", R.string.Reset), (dialogInterface, i) -> { + builder.setTitle(getString("ResetNotificationsAlertTitle", R.string.ResetNotificationsAlertTitle)); + builder.setMessage(getString("ResetNotificationsAlert", R.string.ResetNotificationsAlert)); + builder.setPositiveButton(getString("Reset", R.string.Reset), (dialogInterface, i) -> { if (reseting) { return; } @@ -554,13 +579,13 @@ public boolean supportsPredictiveItemAnimations() { exceptionUsers.clear(); adapter.notifyDataSetChanged(); if (getParentActivity() != null) { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("ResetNotificationsText", R.string.ResetNotificationsText), Toast.LENGTH_SHORT); + Toast toast = Toast.makeText(getParentActivity(), getString("ResetNotificationsText", R.string.ResetNotificationsText), Toast.LENGTH_SHORT); toast.show(); } getMessagesStorage().updateMutedDialogsFiltersCounters(); })); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); @@ -700,9 +725,9 @@ public boolean supportsPredictiveItemAnimations() { })); } else if (position == repeatRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications)); + builder.setTitle(getString("RepeatNotifications", R.string.RepeatNotifications)); builder.setItems(new CharSequence[]{ - LocaleController.getString("RepeatDisabled", R.string.RepeatDisabled), + getString("RepeatDisabled", R.string.RepeatDisabled), LocaleController.formatPluralString("Minutes", 5), LocaleController.formatPluralString("Minutes", 10), LocaleController.formatPluralString("Minutes", 30), @@ -729,7 +754,7 @@ public boolean supportsPredictiveItemAnimations() { updateRepeatNotifications = true; adapter.notifyItemChanged(position); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } if (view instanceof TextCheckCell) { @@ -776,13 +801,13 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat if (rng != null) { if (requestCode == callsRingtoneRow) { if (ringtone.equals(Settings.System.DEFAULT_RINGTONE_URI)) { - name = LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone); + name = getString("DefaultRingtone", R.string.DefaultRingtone); } else { name = rng.getTitle(getParentActivity()); } } else { if (ringtone.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { - name = LocaleController.getString("SoundDefault", R.string.SoundDefault); + name = getString("SoundDefault", R.string.SoundDefault); } else { name = rng.getTitle(getParentActivity()); } @@ -832,6 +857,9 @@ private void showExceptionsAlert(int position, Runnable whenDone) { if (exceptions != null && !exceptions.isEmpty()) { alertText = LocaleController.formatPluralString("Groups", exceptions.size()); } + } else if (position == reactionsRow) { + whenDone.run(); + return; } else { exceptions = exceptionChannels; autoExceptions = null; @@ -849,9 +877,9 @@ private void showExceptionsAlert(int position, Runnable whenDone) { } else { builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsExceptionsAlert", R.string.NotificationsExceptionsAlert, alertText))); } - builder.setTitle(LocaleController.getString("NotificationsExceptions", R.string.NotificationsExceptions)); - builder.setNeutralButton(LocaleController.getString("ViewExceptions", R.string.ViewExceptions), (dialogInterface, i) -> presentFragment(new NotificationsCustomSettingsActivity(-1, exceptions, autoExceptions))); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), (di, i) -> whenDone.run()); + builder.setTitle(getString("NotificationsExceptions", R.string.NotificationsExceptions)); + builder.setNeutralButton(getString("ViewExceptions", R.string.ViewExceptions), (dialogInterface, i) -> presentFragment(new NotificationsCustomSettingsActivity(-1, exceptions, autoExceptions))); + builder.setNegativeButton(getString("OK", R.string.OK), (di, i) -> whenDone.run()); showDialog(builder.create()); } @@ -899,11 +927,11 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType View view; switch (viewType) { case 0: - view = new HeaderCell(mContext); + view = new HeaderCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 1: - view = new TextCheckCell(mContext); + view = new TextCheckCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 2: @@ -911,19 +939,19 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 3: - view = new NotificationsCheckCell(mContext); + view = new NotificationsCheckCell(mContext, 21, 64, true, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: - view = new ShadowSectionCell(mContext); + view = new ShadowSectionCell(mContext, resourceProvider); break; case 5: - view = new TextSettingsCell(mContext); + view = new TextSettingsCell(mContext, resourceProvider); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 6: default: - view = new TextInfoPrivacyCell(mContext); + view = new TextInfoPrivacyCell(mContext, resourceProvider); view.setBackgroundDrawable(Theme.getThemedDrawableByKey(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; } @@ -936,21 +964,21 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { case 0: { HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == notificationsSectionRow) { - headerCell.setText(LocaleController.getString("NotificationsForChats", R.string.NotificationsForChats)); + headerCell.setText(getString("NotificationsForChats", R.string.NotificationsForChats)); } else if (position == inappSectionRow) { - headerCell.setText(LocaleController.getString("InAppNotifications", R.string.InAppNotifications)); + headerCell.setText(getString("InAppNotifications", R.string.InAppNotifications)); } else if (position == eventsSectionRow) { - headerCell.setText(LocaleController.getString("Events", R.string.Events)); + headerCell.setText(getString("Events", R.string.Events)); } else if (position == otherSectionRow) { - headerCell.setText(LocaleController.getString("NotificationsOther", R.string.NotificationsOther)); + headerCell.setText(getString("NotificationsOther", R.string.NotificationsOther)); } else if (position == resetSectionRow) { - headerCell.setText(LocaleController.getString("Reset", R.string.Reset)); + headerCell.setText(getString("Reset", R.string.Reset)); } else if (position == callsSectionRow) { - headerCell.setText(LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings)); + headerCell.setText(getString("VoipNotificationSettings", R.string.VoipNotificationSettings)); } else if (position == badgeNumberSection) { - headerCell.setText(LocaleController.getString("BadgeNumber", R.string.BadgeNumber)); + headerCell.setText(getString("BadgeNumber", R.string.BadgeNumber)); } else if (position == accountsSectionRow) { - headerCell.setText(LocaleController.getString("ShowNotificationsFor", R.string.ShowNotificationsFor)); + headerCell.setText(getString("ShowNotificationsFor", R.string.ShowNotificationsFor)); } break; } @@ -958,35 +986,35 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { TextCheckCell checkCell = (TextCheckCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == inappSoundRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppSounds", R.string.InAppSounds), preferences.getBoolean("EnableInAppSounds", true), true); + checkCell.setTextAndCheck(getString("InAppSounds", R.string.InAppSounds), preferences.getBoolean("EnableInAppSounds", true), true); } else if (position == inappVibrateRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppVibrate", R.string.InAppVibrate), preferences.getBoolean("EnableInAppVibrate", true), true); + checkCell.setTextAndCheck(getString("InAppVibrate", R.string.InAppVibrate), preferences.getBoolean("EnableInAppVibrate", true), true); } else if (position == inappPreviewRow) { - checkCell.setTextAndCheck(LocaleController.getString("InAppPreview", R.string.InAppPreview), preferences.getBoolean("EnableInAppPreview", true), true); + checkCell.setTextAndCheck(getString("InAppPreview", R.string.InAppPreview), preferences.getBoolean("EnableInAppPreview", true), true); } else if (position == inappPriorityRow) { - checkCell.setTextAndCheck(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), preferences.getBoolean("EnableInAppPriority", false), false); + checkCell.setTextAndCheck(getString("NotificationsImportance", R.string.NotificationsImportance), preferences.getBoolean("EnableInAppPriority", false), false); } else if (position == contactJoinedRow) { - checkCell.setTextAndCheck(LocaleController.getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), true); + checkCell.setTextAndCheck(getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), true); } else if (position == pinnedMessageRow) { - checkCell.setTextAndCheck(LocaleController.getString("PinnedMessages", R.string.PinnedMessages), preferences.getBoolean("PinnedMessages", true), false); + checkCell.setTextAndCheck(getString("PinnedMessages", R.string.PinnedMessages), preferences.getBoolean("PinnedMessages", true), false); } else if (position == androidAutoAlertRow) { checkCell.setTextAndCheck("Android Auto", preferences.getBoolean("EnableAutoNotifications", false), true); } else if (position == notificationsServiceRow) { - checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsService", R.string.NotificationsService), LocaleController.getString("NotificationsServiceInfo", R.string.NotificationsServiceInfo), preferences.getBoolean("pushService", getMessagesController().keepAliveService), true, true); + checkCell.setTextAndValueAndCheck(getString("NotificationsService", R.string.NotificationsService), getString("NotificationsServiceInfo", R.string.NotificationsServiceInfo), preferences.getBoolean("pushService", getMessagesController().keepAliveService), true, true); } else if (position == notificationsServiceConnectionRow) { - checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), LocaleController.getString("NotificationsServiceConnectionInfo", R.string.NotificationsServiceConnectionInfo), preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); + checkCell.setTextAndValueAndCheck(getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), getString("NotificationsServiceConnectionInfo", R.string.NotificationsServiceConnectionInfo), preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); } else if (position == badgeNumberShowRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberShow", R.string.BadgeNumberShow), getNotificationsController().showBadgeNumber, true); + checkCell.setTextAndCheck(getString("BadgeNumberShow", R.string.BadgeNumberShow), getNotificationsController().showBadgeNumber, true); } else if (position == badgeNumberMutedRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberMutedChats", R.string.BadgeNumberMutedChats), getNotificationsController().showBadgeMuted, true); + checkCell.setTextAndCheck(getString("BadgeNumberMutedChats", R.string.BadgeNumberMutedChats), getNotificationsController().showBadgeMuted, true); } else if (position == badgeNumberMessagesRow) { - checkCell.setTextAndCheck(LocaleController.getString("BadgeNumberUnread", R.string.BadgeNumberUnread), getNotificationsController().showBadgeMessages, false); + checkCell.setTextAndCheck(getString("BadgeNumberUnread", R.string.BadgeNumberUnread), getNotificationsController().showBadgeMessages, false); } else if (position == inchatSoundRow) { - checkCell.setTextAndCheck(LocaleController.getString("InChatSound", R.string.InChatSound), preferences.getBoolean("EnableInChatSound", true), true); + checkCell.setTextAndCheck(getString("InChatSound", R.string.InChatSound), preferences.getBoolean("EnableInChatSound", true), true); } else if (position == callsVibrateRow) { - checkCell.setTextAndCheck(LocaleController.getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableCallVibrate", true), true); + checkCell.setTextAndCheck(getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableCallVibrate", true), true); } else if (position == accountsAllRow) { - checkCell.setTextAndCheck(LocaleController.getString("AllAccounts", R.string.AllAccounts), MessagesController.getGlobalNotificationsSettings().getBoolean("AllAccounts", true), false); + checkCell.setTextAndCheck(getString("AllAccounts", R.string.AllAccounts), MessagesController.getGlobalNotificationsSettings().getBoolean("AllAccounts", true), false); } break; } @@ -994,7 +1022,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { TextDetailSettingsCell settingsCell = (TextDetailSettingsCell) holder.itemView; settingsCell.setMultilineDetail(true); if (position == resetNotificationsRow) { - settingsCell.setTextAndValue(LocaleController.getString("ResetAllNotifications", R.string.ResetAllNotifications), LocaleController.getString("UndoAllCustom", R.string.UndoAllCustom), false); + settingsCell.setTextAndValue(getString("ResetAllNotifications", R.string.ResetAllNotifications), getString("UndoAllCustom", R.string.UndoAllCustom), false); } break; } @@ -1009,23 +1037,34 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ArrayList autoExceptions = null; boolean enabled; boolean allAuto = false; + int icon = 0; if (position == privateRow) { - text = LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats); + text = getString(R.string.NotificationsPrivateChats); exceptions = exceptionUsers; offUntil = preferences.getInt("EnableAll2", 0); + icon = R.drawable.msg_openprofile; } else if (position == groupRow) { - text = LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups); + text = getString(R.string.NotificationsGroups); exceptions = exceptionChats; offUntil = preferences.getInt("EnableGroup2", 0); + icon = R.drawable.msg_groups; } else if (position == storiesRow) { - text = LocaleController.getString("NotificationStories", R.string.NotificationStories); + text = getString(R.string.NotificationStories); exceptions = exceptionStories; autoExceptions = exceptionAutoStories; offUntil = preferences.getBoolean("EnableAllStories", false) ? 0 : Integer.MAX_VALUE; + icon = R.drawable.msg_menu_stories; + } else if (position == reactionsRow) { + text = getString(R.string.NotificationReactions); + exceptions = null; + autoExceptions = null; + offUntil = preferences.getBoolean("EnableReactionsMessages", true) || preferences.getBoolean("EnableReactionsStories", true) ? 0 : Integer.MAX_VALUE; + icon = R.drawable.msg_reactions; } else { - text = LocaleController.getString("NotificationsChannels", R.string.NotificationsChannels); + text = getString(R.string.NotificationsChannels); exceptions = exceptionChannels; offUntil = preferences.getInt("EnableChannel2", 0); + icon = R.drawable.msg_channel; } int iconType; if (enabled = offUntil < currentTime) { @@ -1036,11 +1075,27 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { iconType = 2; } StringBuilder builder = new StringBuilder(); - if (exceptions != null && !exceptions.isEmpty()) { + if (position == reactionsRow) { + if (offUntil > 0) { + enabled = false; + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); + } else { + enabled = true; + if (preferences.getBoolean("EnableReactionsMessages", true)) { + builder.append(getString(R.string.NotificationReactionsMessages)); + } + if (preferences.getBoolean("EnableReactionsStories", true)) { + if (builder.length() > 0) { + builder.append(", "); + } + builder.append(getString(R.string.NotificationReactionsStories)); + } + } + } else if (exceptions != null && !exceptions.isEmpty()) { if (enabled = offUntil < currentTime) { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); + builder.append(getString("NotificationsOn", R.string.NotificationsOn)); } else if (offUntil - 60 * 60 * 24 * 365 >= currentTime) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); } else { builder.append(LocaleController.formatString("NotificationsOffUntil", R.string.NotificationsOffUntil, LocaleController.stringForMessageListDate(offUntil))); } @@ -1054,18 +1109,18 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { builder.append(LocaleController.formatPluralString("Exception", exceptionsCount)); } else if (autoExceptions != null && !autoExceptions.isEmpty()) { if (offUntil > 0) { - builder.append(LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + builder.append(getString("NotificationsOff", R.string.NotificationsOff)); } else { - builder.append(LocaleController.getString("NotificationsOn", R.string.NotificationsOn)); + builder.append(getString("NotificationsOn", R.string.NotificationsOn)); } if (autoExceptions != null && !autoExceptions.isEmpty() && !preferences.contains("EnableAllStories")) { builder.append(", "); builder.append(LocaleController.formatPluralString("AutoException", autoExceptions.size())); } } else { - builder.append(LocaleController.getString("TapToChange", R.string.TapToChange)); + builder.append(getString("TapToChange", R.string.TapToChange)); } - checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, position != storiesRow); + checkCell.setTextAndValueAndIconAndCheck(text, builder, icon, enabled, iconType, false, position != reactionsRow); break; } case 4: { @@ -1080,37 +1135,37 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { TextSettingsCell textCell = (TextSettingsCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == callsRingtoneRow) { - String value = preferences.getString("CallsRingtone", LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone)); + String value = preferences.getString("CallsRingtone", getString("DefaultRingtone", R.string.DefaultRingtone)); if (value.equals("NoSound")) { - value = LocaleController.getString("NoSound", R.string.NoSound); + value = getString("NoSound", R.string.NoSound); } - textCell.setTextAndValue(LocaleController.getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, updateRingtone, false); + textCell.setTextAndValue(getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, updateRingtone, false); updateRingtone = false; } else if (position == callsVibrateRow) { int value = preferences.getInt("vibrate_calls", 0); if (value == 0) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("VibrationDefault", R.string.VibrationDefault), updateVibrate, true); } else if (value == 1) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("Short", R.string.Short), updateVibrate, true); } else if (value == 2) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("VibrationDisabled", R.string.VibrationDisabled), updateVibrate, true); } else if (value == 3) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("Long", R.string.Long), updateVibrate, true); } else if (value == 4) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("OnlyIfSilent", R.string.OnlyIfSilent), updateVibrate, true); + textCell.setTextAndValue(getString("Vibrate", R.string.Vibrate), getString("OnlyIfSilent", R.string.OnlyIfSilent), updateVibrate, true); } updateVibrate = false; } else if (position == repeatRow) { int minutes = preferences.getInt("repeat_messages", 60); String value; if (minutes == 0) { - value = LocaleController.getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever); + value = getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever); } else if (minutes < 60) { value = LocaleController.formatPluralString("Minutes", minutes); } else { value = LocaleController.formatPluralString("Hours", minutes / 60); } - textCell.setTextAndValue(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); + textCell.setTextAndValue(getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); updateRepeatNotifications = false; } break; @@ -1118,7 +1173,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { case 6: { TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; if (position == accountsInfoRow) { - textCell.setText(LocaleController.getString("ShowNotificationsForInfo", R.string.ShowNotificationsForInfo)); + textCell.setText(getString("ShowNotificationsForInfo", R.string.ShowNotificationsForInfo)); } break; } @@ -1139,7 +1194,7 @@ public int getItemViewType(int position) { return 1; } else if (position == resetNotificationsRow) { return 2; - } else if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow) { + } else if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow || position == reactionsRow) { return 3; } else if (position == eventsSection2Row || position == notificationsSection2Row || position == otherSection2Row || position == resetSection2Row || position == callsSection2Row || position == badgeNumberSection2Row || diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java index 7f6dbaccd8..fab6d5ccac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java @@ -154,6 +154,9 @@ public boolean onFragmentCreate() { } else if (currentType == NotificationsController.TYPE_STORIES) { prefPath = "StoriesSoundPath"; prefDocId = "StoriesSoundDocId"; + } else if (currentType == NotificationsController.TYPE_REACTIONS_MESSAGES || currentType == NotificationsController.TYPE_REACTIONS_STORIES) { + prefPath = "ReactionSoundPath"; + prefDocId = "ReactionSoundDocId"; } else { throw new RuntimeException("Unsupported type"); } @@ -296,7 +299,9 @@ private void deleteSelectedMessages() { } else if (currentType == NotificationsController.TYPE_CHANNEL) { actionBar.setTitle(LocaleController.getString("NotificationsSoundChannels", R.string.NotificationsSoundChannels)); } else if (currentType == NotificationsController.TYPE_STORIES) { - actionBar.setTitle(LocaleController.getString("NotificationsSoundStories", R.string.NotificationsSoundStories)); + actionBar.setTitle(LocaleController.getString(R.string.NotificationsSoundStories)); + } else if (currentType == NotificationsController.TYPE_REACTIONS_STORIES || currentType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + actionBar.setTitle(LocaleController.getString(R.string.NotificationsSoundReactions)); } } else { avatarContainer = new ChatAvatarContainer(context, null, false, resourcesProvider); @@ -888,6 +893,10 @@ public void onFragmentDestroy() { prefName = "StoriesSound"; prefPath = "StoriesSoundPath"; prefDocId = "StoriesSoundDocId"; + } else if (currentType == NotificationsController.TYPE_REACTIONS_STORIES || currentType == NotificationsController.TYPE_REACTIONS_MESSAGES) { + prefName = "ReactionSound"; + prefPath = "ReactionSoundPath"; + prefDocId = "ReactionSoundDocId"; } else { throw new RuntimeException("Unsupported type"); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index da61cc6bab..aaf60ca231 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -6309,6 +6309,7 @@ private void startPhoneVerification(boolean checkPermissions, final String phone req.settings.allow_flashcall = false; } } else { + req.settings.unknown_number = true; req.settings.current_number = false; } } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index eb11f16a6f..cdfaa4e3ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -55,6 +55,7 @@ import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.net.Uri; +import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; @@ -111,6 +112,7 @@ import android.widget.LinearLayout; import android.widget.OverScroller; import android.widget.Scroller; +import android.widget.Space; import android.widget.TextView; import android.widget.Toast; @@ -234,6 +236,7 @@ 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; import org.telegram.ui.Components.Paint.Views.StickerCutOutBtn; import org.telegram.ui.Components.Paint.Views.StickerMakerView; import org.telegram.ui.Components.Paint.Views.StickerMakerBackgroundView; @@ -796,6 +799,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { public static final int EDIT_MODE_CROP = 1; public static final int EDIT_MODE_FILTER = 2; public static final int EDIT_MODE_PAINT = 3; + public static final int EDIT_MODE_STICKER_MASK = 4; private int videoWidth, videoHeight; private float inlineOutAnimationProgress; @@ -877,6 +881,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { private AnimatorSet paintKeyboardAnimator; private KeyboardNotifier paintKeyboardNotifier; private LPhotoPaintView photoPaintView; + private boolean maskPaintViewEraser; + private MaskPaintView maskPaintView; + private boolean maskPaintViewShuttingDown; private AlertDialog visibleDialog; private CaptionTextViewSwitcher captionTextViewSwitcher; private CaptionScrollView captionScrollView; @@ -1872,9 +1879,12 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b boolean fromCamera; private boolean captionTranslated; private String captionDetectedLanguage; - private StickerMakerView stickerMakerView; + public StickerMakerView stickerMakerView; + private ArrayList selectedEmojis; private StickerMakerBackgroundView stickerMakerBackgroundView; - private StickerCutOutBtn cutOutBtn; + private BlurButton cutOutBtn; + private LinearLayout btnLayout; + private BlurButton eraseBtn, restoreBtn, undoBtn, outlineBtn; private long avatarsDialogId; private boolean canEditAvatar; @@ -1915,6 +1925,7 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b private float animateToScale; private float animateToRotate; private float animateToMirror; + private float savedTx, savedTy, savedScale, savedRotation; private float animationValue; private float clippingImageProgress; private boolean applying; @@ -1926,7 +1937,9 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b private boolean doubleTapEnabled; private DecelerateInterpolator interpolator = new DecelerateInterpolator(1.5f); private float pinchStartDistance; + private float pinchStartAngle; private float pinchStartScale = 1; + private float pinchStartRotate = 0; private float pinchCenterX; private float pinchCenterY; private float pinchStartX; @@ -1942,6 +1955,7 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b private boolean zooming; private boolean moving; private int paintViewTouched; + private int maskPaintViewTouched; private boolean doubleTap; private boolean invalidCoords; private boolean canDragDown = true; @@ -4373,6 +4387,9 @@ public void setParentActivity(Activity inActivity, BaseFragment fragment, Theme. if (captionEdit != null) { captionEdit.setAccount(currentAccount); } + if (stickerMakerView != null) { + stickerMakerView.setCurrentAccount(currentAccount); + } if (parentActivity == activity || activity == null) { updateColors(); return; @@ -4566,11 +4583,11 @@ public boolean dispatchKeyEventPreIme(KeyEvent event) { @Override protected void onDraw(Canvas canvas) { - if (stickerMakerBackgroundView != null) { + if (stickerMakerBackgroundView != null && stickerMakerBackgroundView.getVisibility() == View.VISIBLE) { View parent = (View) stickerMakerBackgroundView.getParent(); float alpha = Math.min(stickerMakerBackgroundView.getAlpha(), parent != null ? parent.getAlpha() : 1f); if (alpha > 0) { - canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) alpha * 255, Canvas.ALL_SAVE_FLAG); + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); stickerMakerBackgroundView.draw(canvas); canvas.restore(); } @@ -4638,6 +4655,18 @@ protected void dispatchDraw(Canvas canvas) { View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); overlay.draw(canvas); } + + @Override + protected void onLayout(boolean changed, int _l, int t, int _r, int _b) { + if (btnLayout != null && undoBtn != null) { + int sz = _r - _l - dp(20); + undoBtn.setTranslationY(-sz / 2f - dp(29 + 18)); + btnLayout.setTranslationY(sz / 2f + dp(29 + 18)); + cutOutBtn.setTranslationY(sz / 2f + dp(29 + 18)); + outlineBtn.setTranslationY(sz / 2f + dp(29 + 18 + 36 + 12)); + } + super.onLayout(changed, _l, t, _r, _b); + } }; containerView.setFocusable(false); @@ -5975,15 +6004,6 @@ public void setAlpha(float alpha) { if (captionEdit != null && captionEdit.getVisibility() != GONE) { captionEdit.setAlpha(alpha); } - if (cutOutBtn != null && cutOutBtn.getVisibility() != GONE) { - cutOutBtn.setAlpha(alpha); - } - if (stickerMakerView != null && stickerMakerView.getVisibility() != GONE) { - stickerMakerView.setAlpha(alpha); - } - if (stickerMakerBackgroundView != null && stickerMakerBackgroundView.getVisibility() != GONE) { - stickerMakerBackgroundView.setAlpha(alpha); - } } @Override @@ -6293,7 +6313,9 @@ public void invalidate() { }); captionEdit.setAccount(currentAccount); captionEdit.setOnHeightUpdate(height -> { - videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, height - dp(46))); + if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) { + videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46))); + } muteItem.setTranslationY(-Math.max(0, height - dp(46))); }); captionEdit.setOnAddPhotoClick(v -> { @@ -6311,29 +6333,21 @@ public void setAlpha(float alpha) { windowView.invalidate(); } }; + stickerMakerBackgroundView.setVisibility(View.GONE); containerView.addView(stickerMakerBackgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); stickerMakerView = new StickerMakerView(activityContext, resourcesProvider); stickerMakerView.setCurrentAccount(currentAccount); containerView.addView(stickerMakerView, containerView.indexOfChild(actionBar) - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cutOutBtn = new StickerCutOutBtn(stickerMakerView, activityContext, resourcesProvider, blurManager) { - private final Path path = new Path(); - - @Override - protected void onDraw(Canvas canvas) { - canvas.save(); - path.rewind(); - path.addRoundRect(bounds, dp(8), dp(8), Path.Direction.CW); - canvas.clipPath(path); - canvas.translate(-getX(), -getY()); - drawCaptionBlur(canvas, blurDrawer, 0xFF2b2b2b, 0x33000000, false, true, false); - canvas.restore(); - super.onDraw(canvas); - } - }; + cutOutBtn = new BlurButton(); + cutOutBtn.setRad(18); + cutOutBtn.wrapContentDynamic(); stickerMakerView.setStickerCutOutBtn(cutOutBtn); cutOutBtn.setOnClickListener(v -> { - if (cutOutBtn.isLoading()) { + if (stickerEmpty) { + return; + } + if (cutOutBtn.isLoading() || cutOutBtn.isUndoCutState()) { return; } if (currentIndex < 0 || currentIndex >= imagesArrLocals.size() || stickerMakerView.isThanosInProgress) { @@ -6355,7 +6369,8 @@ protected void onDraw(Canvas canvas) { if (thanosEffect == null/* || photoEntry.isCropped || centerImage.getOrientation() == 180*/) { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); return; } @@ -6363,17 +6378,34 @@ protected void onDraw(Canvas canvas) { if (bitmap == null) { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); return; } if (entry.cropState != null) { bitmap = createCroppedBitmap(bitmap, entry.cropState, new int[]{centerImage.getOrientation(), centerImage.getInvert()}, true); } + if (bitmap == null) { + centerImage.setImageBitmap(segmentedImage); + cutOutBtn.setUndoCutState(true); + showEditStickerMode(true, true); + cutOutBtn.post(this::applyCurrentEditMode); + return; + } Matrix matrix = new Matrix(); - float w = getContainerViewWidth(), h = stickerMakerView.getSegmentBorderImageHeight(); + int BW = bitmap.getWidth(), BH = bitmap.getHeight(); + if (!photoEntry.isCropped && centerImage.getOrientation() / 90 % 2 != 0) { + BW = bitmap.getHeight(); + BH = bitmap.getWidth(); + } + float scale = Math.min( + (float) getContainerViewWidth() / BW, + (float) getContainerViewHeight() / BH + ); + float w = BW * scale, h = BH * scale; float tx = 0, ty = 0; - if (centerImage.getOrientation() != 0 && !photoEntry.isCropped) { + if (centerImage.getOrientation() != 0 && !photoEntry.isCropped || rotate != 0) { final float bw = bitmap.getWidth(); final float bh = bitmap.getHeight(); final float r = (float) Math.sqrt((bw / 2f) * (bw / 2f) + (bh / 2f) * (bh / 2f)); @@ -6381,7 +6413,7 @@ protected void onDraw(Canvas canvas) { Bitmap newBitmap = Bitmap.createBitmap((int) d, (int) d, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(newBitmap); canvas.save(); - canvas.rotate(centerImage.getOrientation(), r, r); + canvas.rotate((photoEntry.isCropped ? 0 : centerImage.getOrientation()) + rotate, r, r); canvas.drawBitmap(bitmap, (d - bw) / 2, (d - bh) / 2, null); bitmap.recycle(); bitmap = newBitmap; @@ -6393,20 +6425,27 @@ protected void onDraw(Canvas canvas) { h = pd; } matrix.postScale(w, h); - matrix.postScale(scale, scale, w / 2f, h / 2f); - int marginTop = (int) ((getContainerViewHeight() - stickerMakerView.getSegmentBorderImageHeight()) / 2f); - matrix.postTranslate(translationX + tx, translationY + ty + marginTop); + matrix.postScale(this.scale, this.scale, w / 2f, h / 2f); + matrix.postTranslate( + translationX + tx + Math.max(0, (int) ((getContainerViewWidth() - BW * scale) / 2f)), + translationY + ty + Math.max(0, (int) ((getContainerViewHeight() - BH * scale) / 2f)) + ); stickerMakerView.isThanosInProgress = true; + Utilities.themeQueue.postRunnable(() -> { + applyCurrentEditMode(segmentedImage); + }); + Runnable turnOff = () -> stickerMakerView.isThanosInProgress = false; thanosEffect.animate(matrix, bitmap, () -> { centerImage.setImageBitmap(segmentedImage); cutOutBtn.setUndoCutState(true); - cutOutBtn.postDelayed(() -> { - applyCurrentEditMode(); - stickerMakerView.isThanosInProgress = false; - }, 1000); + showStickerMode(true, true); + AndroidUtilities.cancelRunOnUIThread(turnOff); + AndroidUtilities.runOnUIThread(turnOff, 800); }, () -> {}); + AndroidUtilities.runOnUIThread(turnOff, 1200); } else { cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); } stickerMakerView.disableClippingMode(); containerView.invalidate(); @@ -6414,17 +6453,98 @@ protected void onDraw(Canvas canvas) { containerView.invalidate(); } else if (cutOutBtn.isCancelState()) { cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); stickerMakerView.disableClippingMode(); containerView.invalidate(); } else { + stickerMakerView.resetPaths(); + stickerMakerView.getThanosEffect(); stickerMakerView.setSegmentedState(false, null); centerImage.setImageBitmap(stickerMakerView.getSourceBitmap(hasFilters)); cutOutBtn.setCutOutState(true); - cutOutBtn.postDelayed(this::applyCurrentEditMode, 250); + showEditStickerMode(false, true); + applyCurrentEditMode(); } }); cutOutBtn.setCutOutState(false); - containerView.addView(cutOutBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 10, 0, 10, 48 + 24)); + containerView.addView(cutOutBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.CENTER)); + + btnLayout = new LinearLayout(parentActivity); + btnLayout.setOrientation(LinearLayout.HORIZONTAL); + + eraseBtn = new BlurButton(); + eraseBtn.wrapContent(); + eraseBtn.setRad(18); + eraseBtn.setEraseState(false); + eraseBtn.setOnClickListener(v -> { + eraseBtn.setActive(true, true); + restoreBtn.setActive(false, true); + if (stickerMakerView != null) { + stickerMakerView.setOutlineVisible(false); + } + maskPaintViewEraser = true; + if (maskPaintView != null) { + maskPaintView.setEraser(maskPaintViewEraser); + } + switchToEditMode(EDIT_MODE_STICKER_MASK); + }); + btnLayout.addView(eraseBtn, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36)); + + btnLayout.addView(new Space(parentActivity), LayoutHelper.createLinear(12, LayoutHelper.MATCH_PARENT)); + + restoreBtn = new BlurButton(); + restoreBtn.wrapContent(); + restoreBtn.setRad(18); + restoreBtn.setRestoreState(false); + restoreBtn.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(true, true); + if (stickerMakerView != null) { + stickerMakerView.setOutlineVisible(false); + } + maskPaintViewEraser = false; + if (maskPaintView != null) { + maskPaintView.setEraser(maskPaintViewEraser); + } + switchToEditMode(EDIT_MODE_STICKER_MASK); + }); + btnLayout.addView(restoreBtn, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36)); + + containerView.addView(btnLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); + + undoBtn = new BlurButton(); + undoBtn.setUndoState(false); + undoBtn.setRad(18); + undoBtn.wrapContent(); + undoBtn.setOnClickListener(v -> { + if (maskPaintView == null || !maskPaintView.undo()) { + switchToEditMode(EDIT_MODE_NONE); + stickerMakerView.resetPaths(); + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + boolean hasFilters = !TextUtils.isEmpty(entry.filterPath); + if (stickerMakerView != null && !stickerMakerView.empty) { + stickerMakerView.setSegmentedState(false, null); + } + centerImage.setImageBitmap(stickerMakerView.getSourceBitmap(hasFilters)); + if (stickerMakerView == null || !stickerMakerView.empty) { + cutOutBtn.setCutOutState(true); + } + showStickerMode(true, true); + } + }); + containerView.addView(undoBtn, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); + + outlineBtn = new BlurButton(); + outlineBtn.setOutlineState(false); + outlineBtn.setRad(18); + outlineBtn.wrapContent(); + outlineBtn.setOnClickListener(v -> { + if (stickerMakerView != null) { + outlineBtn.setActive(!outlineBtn.isActive(), true); + stickerMakerView.setOutlineVisible(outlineBtn.isActive() && !(eraseBtn.isActive() || restoreBtn.isActive())); + } + }); + containerView.addView(outlineBtn, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER)); showEditCaption(false, false); showStickerMode(false, false); @@ -6476,6 +6596,9 @@ public void setTranslationY(float translationY) { if (placeProvider != null && !placeProvider.allowSendingSubmenu()) { return false; } + if (sendPhotoType == SELECT_TYPE_STICKER) { + return false; + } boolean isStoryViewer = parentFragment != null && parentFragment.getLastStoryViewer() != null; if (!isStoryViewer && (parentChatActivity == null || parentChatActivity.isInScheduleMode())) { return false; @@ -6828,6 +6951,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { tuneItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(tuneItem, LayoutHelper.createLinear(48, 48)); tuneItem.setOnClickListener(v -> { + if (v.getAlpha() < .9f) return; cancelStickerClippingMode(); if (isCaptionOpen()) { return; @@ -7307,121 +7431,208 @@ public void onDismiss(DialogInterface dialog) { if (object instanceof MediaController.PhotoEntry) { int stickerMaxSize = 512; MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); - String path = photoEntry.imagePath != null ? photoEntry.imagePath : photoEntry.path; - Bitmap paintBitmap = BitmapFactory.decodeFile(path); Bitmap canvasBitmap = Bitmap.createBitmap(stickerMaxSize, stickerMaxSize, Bitmap.Config.ARGB_8888); - float scaleImage = Math.min( - (float) getContainerViewWidth() / paintBitmap.getWidth(), - (float) getContainerViewHeight() / paintBitmap.getHeight() - ) / (getContainerViewWidth() - dp(20)) * canvasBitmap.getWidth() * scale; - float scaleContainer = (float) canvasBitmap.getWidth() / (getContainerViewWidth() - dp(20)); - Canvas canvas = new Canvas(canvasBitmap); - Matrix matrix = new Matrix(); - - if (centerImage.getOrientation() != 0 && !(photoEntry.isPainted || photoEntry.isCropped)) { - float cx = paintBitmap.getWidth() / 2f; - float cy = paintBitmap.getHeight() / 2f; - matrix.postRotate(centerImage.getOrientation(), cx, cy); - float scaleFactor = paintBitmap.getWidth() / (float) paintBitmap.getHeight(); - matrix.postScale(scaleFactor, scaleFactor, cx, cy); - } - - matrix.postScale(scaleImage, scaleImage); - float newSrcImgWidth = paintBitmap.getWidth() * scaleImage; - float newSrcImgHeight = paintBitmap.getHeight() * scaleImage; - float dyToCenter = -(newSrcImgHeight - canvasBitmap.getHeight()) / 2; - float dxToCenter = -(newSrcImgWidth - canvasBitmap.getWidth()) / 2; - matrix.postTranslate(dxToCenter, dyToCenter); - matrix.postTranslate(translationX * scaleContainer, translationY * scaleContainer); Path clipPath = new Path(); RectF clipRect = new RectF(); clipRect.set(0, 0, canvasBitmap.getWidth(), canvasBitmap.getHeight()); int r = canvasBitmap.getWidth() / 8; clipPath.addRoundRect(clipRect, r, r, Path.Direction.CW); canvas.clipPath(clipPath); - canvas.drawBitmap(paintBitmap, matrix, new Paint(Paint.FILTER_BITMAP_FLAG)); - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(canvasBitmap, Bitmap.CompressFormat.WEBP, stickerMaxSize, stickerMaxSize, 100, false, 101, 101); - final String fullStickerPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(size, "webp", true).toString(); + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + float borderSize = containerWidth - dp(20); + + if (stickerMakerView != null && stickerMakerView.outlineVisible && stickerMakerView.getSourceBitmap() != null) { + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + stickerMakerView.drawOutline(canvas, false, null, false); + canvas.restore(); + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + centerImage.draw(canvas); + canvas.restore(); + + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + stickerMakerView.drawOutline(canvas, true, null, false); + canvas.restore(); + } else { + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + centerImage.draw(canvas); + canvas.restore(); + } + if (paintingOverlay != null) { + canvas.save(); + canvas.translate(canvasBitmap.getWidth() / 2f, canvasBitmap.getHeight() / 2f); + canvas.scale(canvasBitmap.getWidth() / borderSize, canvasBitmap.getHeight() / borderSize); + applyTransformToOutline(canvas); + canvas.translate(-centerImage.getImageWidth() / 2f, -centerImage.getImageHeight() / 2f); + canvas.scale(centerImage.getImageWidth() / paintingOverlay.getMeasuredWidth(), centerImage.getImageHeight() / paintingOverlay.getMeasuredHeight()); + paintingOverlay.drawChildren = !hasAnimatedMediaEntities(); + paintingOverlay.draw(canvas); + paintingOverlay.drawChildren = true; + canvas.restore(); + } + + String stickerEmoji = null; VideoEditedInfo videoEditedInfo1 = null; if (hasAnimatedMediaEntities()) { + Matrix matrix = new Matrix(); + matrix.reset(); + matrix.preTranslate(borderSize / 2f, borderSize / 2f); + applyTransformToMatrix(matrix); + matrix.preTranslate(-centerImage.getImageWidth() / 2f, -centerImage.getImageHeight() / 2f); + matrix.preScale(centerImage.getImageWidth(), centerImage.getImageHeight()); + ArrayList entities = new ArrayList<>(); for (VideoEditedInfo.MediaEntity entity : photoEntry.mediaEntities) { VideoEditedInfo.MediaEntity e = entity.copy(); - AndroidUtilities.rectTmp.set( - e.x * paintBitmap.getWidth(), - e.y * paintBitmap.getHeight(), - (e.x + e.width) * paintBitmap.getWidth(), - (e.y + e.height) * paintBitmap.getHeight() - ); - matrix.mapRect(AndroidUtilities.rectTmp); - e.x = AndroidUtilities.rectTmp.left / canvasBitmap.getWidth(); - e.y = AndroidUtilities.rectTmp.top / canvasBitmap.getHeight(); - e.width = AndroidUtilities.rectTmp.width() / canvasBitmap.getWidth(); - e.height = AndroidUtilities.rectTmp.height() / canvasBitmap.getHeight(); - e.scale *= scaleImage; + float x = e.x; + float y = e.y; + float w = e.width; + float h = e.height; + float pos[] = new float[] { + x, y, + x + w, y, + x + w, y + h, + x, y + h + }; + matrix.mapPoints(pos); + e.width = (float) Math.sqrt(Math.pow(pos[0] - pos[2], 2) + Math.pow(pos[1] - pos[3], 2)) / borderSize; + e.height = (float) Math.sqrt(Math.pow(pos[0] - pos[6], 2) + Math.pow(pos[1] - pos[7], 2)) / borderSize; + e.x = ((pos[0] + pos[4]) / 2f) / borderSize - e.width / 2f; + e.y = ((pos[1] + pos[5]) / 2f) / borderSize - e.height / 2f; + e.scale = 1f; + e.customTextView = true; + if (photoEntry.isCropped && photoEntry.cropState != null) { + e.rotation -= photoEntry.cropState.transformRotation / 180f * Math.PI; + } + e.rotation -= rotate / 180f * Math.PI; entities.add(e); + if (e.document != null && stickerEmoji == null) { + stickerEmoji = MessageObject.findAnimatedEmojiEmoticon(e.document, null); + } } videoEditedInfo1 = new VideoEditedInfo(); - videoEditedInfo1.originalPath = fullStickerPath; videoEditedInfo1.isPhoto = true; videoEditedInfo1.originalWidth = videoEditedInfo1.resultWidth = stickerMaxSize; videoEditedInfo1.originalHeight = videoEditedInfo1.resultHeight = stickerMaxSize; videoEditedInfo1.mediaEntities = entities; - videoEditedInfo1.originalDuration = videoEditedInfo1.estimatedDuration = Utilities.clamp(photoEntry.averageDuration, 2800L, 800L); - videoEditedInfo1.bitrate = (int) (255 * 1024 * 8 / (videoEditedInfo1.originalDuration / 1000.0) * 0.24); + videoEditedInfo1.originalDuration = videoEditedInfo1.estimatedDuration = Utilities.clamp(photoEntry.averageDuration, 2999L, 800L); + videoEditedInfo1.bitrate = 200_000; videoEditedInfo1.framerate = 30; videoEditedInfo1.isSticker = true; - videoEditedInfo1.estimatedSize = 256 * 1024 * 8; + videoEditedInfo1.estimatedSize = 256 * 1024; } - if (photoEntry.thumbPath != null) { - try { - new File(photoEntry.thumbPath).delete(); - } catch (Exception e) { - FileLog.e(e); - } - photoEntry.thumbPath = null; - } - if (photoEntry.fullPaintPath != null) { - try { - Bitmap paintBitmap2 = BitmapFactory.decodeFile(photoEntry.fullPaintPath); - canvas.drawBitmap(paintBitmap2, matrix, new Paint(Paint.FILTER_BITMAP_FLAG)); - paintBitmap2.recycle(); - } catch (Exception e) { - FileLog.e(e); - } + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(canvasBitmap, Bitmap.CompressFormat.WEBP, stickerMaxSize, stickerMaxSize, 100, false, 101, 101); + final String fullStickerPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(size, "webp", true).toString(); + if (videoEditedInfo1 != null) { + videoEditedInfo1.originalPath = fullStickerPath; } - size = ImageLoader.scaleAndSaveImage(canvasBitmap, getCompressFormat(), thumbSize, thumbSize, 83, false, 101, 101); - photoEntry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); VideoEditedInfo finalVideoEditedInfo = videoEditedInfo1; + if (selectedEmojis == null) { + selectedEmojis = new ArrayList<>(); + } + if (selectedEmojis.isEmpty()) { + if (stickerMakerView.detectedEmoji != null && Emoji.getEmojiDrawable(stickerMakerView.detectedEmoji) != null) { + selectedEmojis.add(stickerMakerView.detectedEmoji); + } else if (stickerEmoji != null) { + selectedEmojis.add(stickerEmoji); + } else { + selectedEmojis.add("👍"); + } + } + doneButtonPressed = false; - ContentPreviewViewer.getInstance().showCustomStickerActions(fullStickerPath, videoEditedInfo1, stickerMakerView, new ContentPreviewViewer.ContentPreviewViewerDelegate() { + ContentPreviewViewer.getInstance().showCustomStickerActions(fullStickerPath, videoEditedInfo1, stickerMakerView, selectedEmojis, new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker() { + if (placeProvider == null) + return; + stickerEmptySent = true; + generateThumb(); photoEntry.imagePath = fullStickerPath; placeProvider.sendButtonPressed(currentIndex, finalVideoEditedInfo, notify, scheduleDate, forceDocument); NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationNameOnUIThread(NotificationCenter.customStickerCreated, true); } + private void generateThumb() { + ContentPreviewViewer viewer = ContentPreviewViewer.getInstance(); + if (photoEntry.thumbPath != null) { + try { + new File(photoEntry.thumbPath).delete(); + } catch (Exception e) { + FileLog.e(e); + } + photoEntry.thumbPath = null; + } + Bitmap bitmap = Bitmap.createBitmap(thumbSize, thumbSize, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + if (viewer.centerImage != null) { + viewer.centerImage.setAlpha(1f); + viewer.centerImage.setImageCoords(0, 0, bitmap.getWidth(), bitmap.getHeight()); + viewer.centerImage.draw(canvas); + } + if (viewer.paintingOverlay != null) { + canvas.save(); + canvas.scale((float) bitmap.getWidth() / viewer.paintingOverlay.getWidth(), (float) bitmap.getHeight() / viewer.paintingOverlay.getHeight()); + viewer.paintingOverlay.setAlpha(1f); + Path paintingOverlayClipPath = new Path(); + paintingOverlayClipPath.rewind(); + AndroidUtilities.rectTmp.set(0, 0, viewer.paintingOverlay.getWidth(), viewer.paintingOverlay.getHeight()); + paintingOverlayClipPath.addRoundRect(AndroidUtilities.rectTmp, viewer.paintingOverlay.getWidth() / 8f, viewer.paintingOverlay.getHeight() / 8f, Path.Direction.CW); + canvas.clipPath(paintingOverlayClipPath); + viewer.paintingOverlay.draw(canvas); + canvas.restore(); + } + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), thumbSize, thumbSize, 83, false, 101, 101); + photoEntry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + @Override public void addToFavoriteSelected(String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, true, null, null); + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, true, null, null, photoEntry.thumbPath, null, null); } @Override public void stickerSetSelected(TLRPC.StickerSet stickerSet, String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, stickerSet, replacedSticker); + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, stickerSet, replacedSticker, photoEntry.thumbPath, null, null); + } + + @Override + public void newStickerPackSelected(CharSequence short_name, CharSequence name, String emoji, Utilities.Callback whenDone) { + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, name, false, null, null, photoEntry.thumbPath, whenDone, null, short_name); } @Override - public void newStickerPackSelected(CharSequence short_name, CharSequence name, String emoji) { - stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, name, false, null, null, short_name); + public void setIntroSticker(String emoji) { + stickerEmptySent = true; + generateThumb(); + stickerMakerView.uploadStickerFile(fullStickerPath, finalVideoEditedInfo, emoji, null, false, null, null, photoEntry.thumbPath, null, customStickerHandler); } @Override @@ -7429,6 +7640,11 @@ public boolean isReplacedSticker() { return replacedSticker != null; } + @Override + public boolean isSettingIntroSticker() { + return customStickerHandler != null; + } + @Override public long getDialogId() { return currentDialogId; @@ -8170,10 +8386,35 @@ private boolean cropRotate(float diff) { } private float scale1() { + return scale1(true); + } + + private float scale1(boolean fit) { if (sendPhotoType == SELECT_TYPE_STICKER) { int width = getContainerViewWidth(); if (width == 0) width = AndroidUtilities.displaySize.x; - return (width - dp(20) + 1) / (float) width; + float scale = (width - dp(20) + 1) / (float) width; + if (fit) { + int w = centerImage.getBitmapWidth(); + int h = centerImage.getBitmapHeight(); + if ((w <= 1 || h <= 1) && currentIndex >= 0 && currentIndex < imagesArrLocals.size()) { + Object object = imagesArrLocals.get(currentIndex); + if (object instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); + if (photoEntry.orientation / 90 % 2 != 0) { + w = photoEntry.height; + h = photoEntry.width; + } else { + w = photoEntry.width; + h = photoEntry.height; + } + } + } + if (w > 1 && h > 1 && w > h) { + scale *= (float) w / h; + } + } + return scale; } return 1f; } @@ -8215,8 +8456,8 @@ private boolean cropRotate(final float diff, boolean restoreMirror, Runnable onE animateToScale = newScale / oldScale; } if (sendPhotoType == SELECT_TYPE_STICKER) { - scale *= scale1(); - animateToScale *= scale1(); + scale *= scale1(false); + animateToScale *= scale1(false); } ValueAnimator areaRotateAnimator = ValueAnimator.ofFloat(0, 1f); final float wasRotation = photoCropView.wheelView.getRotation(); @@ -8236,9 +8477,9 @@ public void onAnimationEnd(Animator animation) { imageMoveAnimation = null; rotate = animateToRotate = 0; mirror = animateToMirror = 0; - scale = animateToScale = scale1(); + scale = animateToScale = scale1(false); containerView.invalidate(); - photoCropView.cropView.areaView.setRotationScaleTranslation(0, scale1(), 0, 0); + photoCropView.cropView.areaView.setRotationScaleTranslation(0, scale1(false), 0, 0); photoCropView.wheelView.setRotated(false); if (Math.abs(diff) > 0) { if (photoCropView.rotate(diff)) { @@ -8441,9 +8682,13 @@ private void updateVideoSeekPreviewPosition() { int min = dp(10); int max = videoPlayerControlFrameLayout.getMeasuredWidth() - dp(10) - videoPreviewFrame.getMeasuredWidth() / 2; if (x < min) { + videoPreviewFrame.setPivotX(Utilities.clamp(videoPreviewFrame.getMeasuredWidth() / 2f - (min - x), videoPreviewFrame.getMeasuredWidth(), 0)); x = min; } else if (x >= max) { + videoPreviewFrame.setPivotX(Utilities.clamp(videoPreviewFrame.getMeasuredWidth() / 2f + (x - max), videoPreviewFrame.getMeasuredWidth(), 0)); x = max; + } else { + videoPreviewFrame.setPivotX(videoPreviewFrame.getMeasuredWidth() / 2f); } videoPreviewFrame.setTranslationX(x); } @@ -8461,14 +8706,20 @@ private void showVideoSeekPreviewPosition(boolean show) { } videoPreviewFrame.setTag(show ? 1 : null); videoPreviewFrameAnimation = new AnimatorSet(); - videoPreviewFrameAnimation.playTogether(ObjectAnimator.ofFloat(videoPreviewFrame, View.ALPHA, show ? 1.0f : 0.0f)); + videoPreviewFrameAnimation.playTogether( + ObjectAnimator.ofFloat(videoPreviewFrame, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.SCALE_X, show ? 1.0f : 0.5f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.SCALE_Y, show ? 1.0f : 0.5f), + ObjectAnimator.ofFloat(videoPreviewFrame, View.TRANSLATION_Y, show ? 0f : dp(12)) + ); + videoPreviewFrameAnimation.setDuration(380); + videoPreviewFrameAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); videoPreviewFrameAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { videoPreviewFrameAnimation = null; } }); - videoPreviewFrameAnimation.setDuration(180); videoPreviewFrameAnimation.start(); } @@ -10027,6 +10278,109 @@ private Bitmap createCroppedBitmap(Bitmap bitmap, MediaController.CropState crop return null; } + private Matrix createCroppedMatrix(int w, int h, MediaController.CropState cropState, int[] extraTransform, boolean mirror) { + try { + int tr = (cropState.transformRotation + (extraTransform != null ? extraTransform[0] : 0)) % 360; + int inv = extraTransform != null && extraTransform.length > 1 ? extraTransform[1] : 0; + int fw = w, rotatedW = w; + int fh = h, rotatedH = h; + if (tr == 90 || tr == 270) { + int temp = fw; + fw = rotatedW = fh; + fh = rotatedH = temp; + } + fw *= cropState.cropPw; + fh *= cropState.cropPh; + Matrix matrix = new Matrix(); + matrix.postTranslate(-w / 2, -h / 2); + if (mirror && cropState.mirrored) { + if (tr == 90 || tr == 270) { + matrix.postScale(1, -1); + } else { + matrix.postScale(-1, 1); + } + } + if (inv == 1) { + matrix.postScale(-1, 1); + } else if (inv == 2) { + matrix.postScale(1, -1); + } + matrix.postRotate(cropState.cropRotate + tr); + matrix.postTranslate(cropState.cropPx * rotatedW, cropState.cropPy * rotatedH); + matrix.postScale(cropState.cropScale, cropState.cropScale); + matrix.postTranslate(fw / 2, fh / 2); + return matrix; + } catch (Throwable e) { + FileLog.e(e); + } + return null; + } + + private void applyCurrentEditMode(Bitmap bitmap) { + Bitmap[] paintThumbBitmap = new Bitmap[1]; + int[] orientation = null; + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + orientation = new int[]{centerImage.getOrientation(), centerImage.getInvert()}; + boolean recycleCropped; + Bitmap croppedBitmap; + if (entry.cropState != null) { + croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); + recycleCropped = true; + } else { + croppedBitmap = bitmap; + if (orientation[0] != 0) { + Matrix matrix = new Matrix(); + matrix.postRotate(orientation[0]); + if (orientation[1] == 1) { + matrix.postScale(-1, 1); + } else if (orientation[1] == 2) { + matrix.postScale(1, -1); + } + croppedBitmap = Bitmaps.createBitmap(croppedBitmap, 0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight(), matrix, true); + recycleCropped = true; + } else { + recycleCropped = false; + } + } + if ((currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK) && sendPhotoType == SELECT_TYPE_STICKER && !isCurrentVideo) { + if (entry.cropState != null) { + if (entry.paintPath != null) { + Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); + Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); + if (hasAnimatedMediaEntities()) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } else { + mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); + } + mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); + } else { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + } else if (entry.paintPath != null) { + Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); + if (hasAnimatedMediaEntities()) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } else { + mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedBitmap, paintBitmap, AndroidUtilities.getPhotoSize(), false); + } + mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedBitmap, paintBitmap, thumbSize, false); + } else { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + } + if (recycleCropped && croppedBitmap != null) { + croppedBitmap.recycle(); + } + } + private void applyCurrentEditMode() { if (currentIndex < 0 || currentIndex >= imagesArrLocals.size()) { return; @@ -10043,10 +10397,7 @@ private void applyCurrentEditMode() { int[] orientation = null; boolean hasChanged = false; MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); - if (currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER) { - bitmap = centerImage.getBitmap(); - orientation = new int[]{centerImage.getOrientation(), centerImage.getInvert()}; - } else if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { photoCropView.makeCrop(entry); if (entry.cropState == null && currentEditMode != EDIT_MODE_CROP) { return; @@ -10079,6 +10430,34 @@ private void applyCurrentEditMode() { stickers = photoPaintView.getMasks(); photoPaintView.onCleanupEntities(); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + hasChanged = true; + bitmap = maskPaintView.getBitmap(); + centerImage.setImageBitmap(bitmap); + applyCurrentEditMode(bitmap); + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + if (stickerMakerView != null) { + int r = centerImage.getOrientation() - stickerMakerView.orientation; + if (r != 0) { + int w = bitmap.getWidth(), h = bitmap.getHeight(); + int rw = w, rh = h; + if (r / 90 % 2 != 0) { + rw = h; + rh = w; + } + Bitmap rotatedBitmap = Bitmap.createBitmap(rw, rh, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(rotatedBitmap); + canvas.translate(-w / 2f, -h / 2f); + canvas.rotate(r); + canvas.translate(rw / 2f, rh / 2f); + canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + stickerMakerView.updateOutlinePath(rotatedBitmap); + } else { + stickerMakerView.updateOutlinePath(bitmap); + } + } + return; } if (bitmap == null) { return; @@ -10093,49 +10472,7 @@ private void applyCurrentEditMode() { entry.imagePath = null; } - if (currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER) { - if (entry.cropState != null) { - Bitmap croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); - if (entry.paintPath != null) { - Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); - Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); - if (!isCurrentVideo) { - if (hasAnimatedMediaEntities()) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } else { - mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); - } - } - mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); - } else { - if (!isCurrentVideo) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); - entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - } else if (entry.paintPath != null) { - Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); - if (!isCurrentVideo) { - if (hasAnimatedMediaEntities()) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } else { - mergeImages(entry.imagePath = getTempFileAbsolutePath(), null, paintBitmap, bitmap, AndroidUtilities.getPhotoSize(), true); - } - } - mergeImages(entry.thumbPath = getTempFileAbsolutePath(), null, paintBitmap, bitmap, thumbSize, true); - } else { - if (!isCurrentVideo) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, getCompressFormat(), AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, thumbSize, thumbSize, 70, false, 101, 101); - entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); - } - } else if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { editState.cropState = entry.cropState; editState.croppedPaintPath = entry.croppedPaintPath; editState.croppedMediaEntities = entry.croppedMediaEntities; @@ -10365,6 +10702,8 @@ private void applyCurrentEditMode() { if (hasChanged) { entry.isPainted = true; paintItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_editMediaButton), PorterDuff.Mode.MULTIPLY)); + } else if (sendPhotoType == SELECT_TYPE_STICKER) { + entry.isPainted = true; } } @@ -10601,12 +10940,12 @@ public void switchToEditMode(final int mode) { } else if (mode == EDIT_MODE_PAINT) { navigationBarColorTo = 0xff000000; } else if (mode == EDIT_MODE_NONE && fancyShadows && savedState == null) { - navigationBarColorTo = 0; + navigationBarColorTo = sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0; } else { - navigationBarColorTo = 0x7f000000; + navigationBarColorTo = sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000; } showEditCaption(editing && savedState == null && mode == EDIT_MODE_NONE, true); - showStickerMode(mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_STICKER, true); + showStickerMode((mode == EDIT_MODE_NONE || mode == EDIT_MODE_STICKER_MASK || mode == EDIT_MODE_PAINT && stickerEmpty) && sendPhotoType == SELECT_TYPE_STICKER, true); navigationBar.setVisibility(mode != EDIT_MODE_FILTER ? View.VISIBLE : View.INVISIBLE); switchingToMode = mode; if (currentEditMode == EDIT_MODE_NONE) { @@ -10617,7 +10956,17 @@ public void switchToEditMode(final int mode) { } if (mode == EDIT_MODE_NONE) { Bitmap bitmap = centerImage.getBitmap(); - if (bitmap != null) { + if (photoPaintView != null) { + photoPaintView.setDrawShadow(false); + } + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + animationStartTime = System.currentTimeMillis(); + animateToY = savedTy = translationY; + animateToX = savedTx = translationX; + animateToRotate = savedRotation = rotate; + animateToMirror = mirror; + animateToScale = savedScale = scale; + } else if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -10681,33 +11030,59 @@ public void switchToEditMode(final int mode) { newScale = Math.min(getContainerViewWidth(0) / (float) bitmapWidth, getContainerViewHeight(0) / (float) bitmapHeight); } } - animateToScale = newScale / oldScale * scale1(); - animateToX = 0; - translationX = getLeftInset() / 2 - getRightInset() / 2; - if (sendPhotoType == SELECT_TYPE_AVATAR) { - if (currentEditMode == EDIT_MODE_FILTER) { - animateToY = dp(36); - } else if (currentEditMode == EDIT_MODE_PAINT) { - animateToY = -dp(12); - if (photoPaintView != null) { - animateToY -= photoPaintView.getAdditionalTop() / 2f; - } - } - } else { + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + } + if (sendPhotoType == SELECT_TYPE_STICKER && (currentEditMode == EDIT_MODE_PAINT || currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_CROP)) { + animationStartTime = System.currentTimeMillis(); + animateToX = savedTx; if (currentEditMode == EDIT_MODE_CROP) { - animateToY = dp(24 + 32); - } else if (currentEditMode == EDIT_MODE_FILTER) { - animateToY = dp(93); + animateToY = savedTy + dp(24 + 32); } else if (currentEditMode == EDIT_MODE_PAINT) { - animateToY = dp(44); + animateToY = savedTy + dp(44); if (photoPaintView != null) { animateToY -= photoPaintView.getAdditionalTop() / 2f; animateToY += photoPaintView.getAdditionalBottom() / 2f; } + } else if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = savedTy + dp(93); } if (isStatusBarVisible()) { animateToY -= AndroidUtilities.statusBarHeight / 2; } + animateToScale = newScale / oldScale * savedScale; + animateToRotate = savedRotation; + animateToMirror = mirror; + } else { + animateToScale = newScale / oldScale * scale1(); + animateToX = 0; + translationX = getLeftInset() / 2 - getRightInset() / 2; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = dp(36); + } else if (currentEditMode == EDIT_MODE_PAINT) { + animateToY = -dp(12); + if (photoPaintView != null) { + animateToY -= photoPaintView.getAdditionalTop() / 2f; + } + } + } else { + if (currentEditMode == EDIT_MODE_CROP) { + animateToY = dp(24 + 32); + } else if (currentEditMode == EDIT_MODE_FILTER) { + animateToY = dp(93); + } else if (currentEditMode == EDIT_MODE_PAINT) { + animateToY = dp(44); + if (photoPaintView != null) { + animateToY -= photoPaintView.getAdditionalTop() / 2f; + animateToY += photoPaintView.getAdditionalBottom() / 2f; + } + } + if (isStatusBarVisible()) { + animateToY -= AndroidUtilities.statusBarHeight / 2; + } + } } animationStartTime = System.currentTimeMillis(); zoomAnimation = true; @@ -10748,6 +11123,11 @@ public void switchToEditMode(final int mode) { animators.add(animatorX); animators.add(ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1)); photoPaintView.onAnimationStateChanged(true); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + animators.add(ObjectAnimator.ofFloat(maskPaintView.buttonsLayout, View.TRANSLATION_Y, dp(18))); + animators.add(ObjectAnimator.ofFloat(maskPaintView.buttonsLayout, View.ALPHA, 0)); + animators.add(ObjectAnimator.ofFloat(maskPaintView.weightChooserView, View.TRANSLATION_X, dp(-18))); + animators.add(ObjectAnimator.ofFloat(maskPaintView.weightChooserView, View.ALPHA, 0)); } animators.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); imageMoveAnimation.playTogether(animators); @@ -10777,8 +11157,24 @@ public void onAnimationEnd(Animator animation) { FileLog.e(e); } photoPaintView = null; + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintViewShuttingDown = true; + containerView.invalidate(); + final MaskPaintView _maskPaintView = maskPaintView; + containerView.post(() -> { + _maskPaintView.shutdown(); + try { + containerView.removeView(_maskPaintView); + } catch (Exception e) { + FileLog.e(e); + } + }); + maskPaintView = null; + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); } imageMoveAnimation = null; + final int fromEditMode = currentEditMode; currentEditMode = mode; captionEdit.keyboardNotifier.ignore(currentEditMode != EDIT_MODE_NONE); if (paintKeyboardNotifier != null) { @@ -10787,15 +11183,22 @@ public void onAnimationEnd(Animator animation) { if (currentEditMode != EDIT_MODE_PAINT) { translateY = 0; } - switchingToMode = -1; applying = false; if (sendPhotoType == SELECT_TYPE_AVATAR) { photoCropView.setVisibility(View.VISIBLE); } - scale = animateToScale = scale1(); - animateToX = 0; - animateToY = 0; - updateMinMax(scale); + if (sendPhotoType == SELECT_TYPE_STICKER && (fromEditMode == EDIT_MODE_PAINT || fromEditMode == EDIT_MODE_FILTER || fromEditMode == EDIT_MODE_CROP || fromEditMode == EDIT_MODE_STICKER_MASK)) { + animateToX = savedTx; + animateToY = savedTy; + animateToScale = savedScale; + animateToRotate = savedRotation; + } else { + scale = animateToScale = scale1(false); + updateMinMax(scale); + animateToX = 0; + animateToY = 0; + } + switchingToMode = -1; containerView.invalidate(); if (savedState != null) { @@ -10811,6 +11214,12 @@ public void onAnimationEnd(Animator animation) { ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0)); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 1)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 1)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 1)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0)); if (sendPhotoType != SELECT_TYPE_AVATAR) { arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0)); @@ -10884,6 +11293,12 @@ public void onAnimationEnd(Animator animation) { ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); @@ -10927,6 +11342,13 @@ public void onAnimationEnd(Animator animation) { photosCounterView.setVisibility(View.GONE); updateActionBarTitlePadding(); } + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } final Bitmap bitmap = centerImage.getBitmap(); if (bitmap != null || isCurrentVideo) { @@ -11070,6 +11492,12 @@ public void onAnimationEnd(Animator animation) { ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); if (sendPhotoType == 0 || sendPhotoType == 4) { @@ -11115,6 +11543,13 @@ public void onAnimationEnd(Animator animation) { } Bitmap bitmap = centerImage.getBitmap(); + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -11184,6 +11619,12 @@ public void onAnimationEnd(Animator animation) { ArrayList arrayList = new ArrayList<>(); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, stickerEmpty ? 1 : 0)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, stickerEmpty ? 1 : 0)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); @@ -11211,6 +11652,49 @@ public void onAnimationEnd(Animator animation) { } }); changeModeAnimation.start(); + } else if (mode == EDIT_MODE_STICKER_MASK) { + createMaskPaintView(); + + changeModeAnimation = new AnimatorSet(); + ArrayList arrayList = new ArrayList<>(); + arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, pickerView.getHeight() + captionEdit.getEditTextHeight() + (isCurrentVideo ? dp(58) : 0))); + arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, 0)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, 1)); + } + if (stickerMakerBackgroundView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, 1)); + } + arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); + arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); + arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); + if (needCaptionLayout) { + arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, dp(isCurrentVideo ? 154 : 96))); + } + if (sendPhotoType == 0 || sendPhotoType == 4) { + arrayList.add(ObjectAnimator.ofFloat(checkImageView, View.ALPHA, 1, 0)); + arrayList.add(ObjectAnimator.ofFloat(photosCounterView, View.ALPHA, 1, 0)); + } else if (sendPhotoType == SELECT_TYPE_AVATAR) { + arrayList.add(ObjectAnimator.ofFloat(photoCropView, View.ALPHA, 1, 0)); + } + if (selectedPhotosListView.getVisibility() == View.VISIBLE) { + arrayList.add(ObjectAnimator.ofFloat(selectedPhotosListView, View.ALPHA, 1, 0)); + } + if (muteItem.getTag() != null) { + arrayList.add(ObjectAnimator.ofFloat(muteItem, View.ALPHA, 1, 0)); + } + changeModeAnimation.playTogether(arrayList); + changeModeAnimation.setDuration(200); + changeModeAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + maskPaintView.init(); + currentEditMode = mode; + changeModeAnimation = null; + switchingToMode = -1; + } + }); + changeModeAnimation.start(); } if (containerView != null) { @@ -11218,6 +11702,77 @@ public void onAnimationEnd(Animator animation) { } } + private void createMaskPaintView() { + if (maskPaintView != null) { + return; + } + MediaController.CropState state; + if (sendPhotoType == SELECT_TYPE_AVATAR) { + state = new MediaController.CropState(); + state.transformRotation = cropTransform.getOrientation(); + } else { + state = editState.cropState; + } + Bitmap originalBitmap = Bitmap.createBitmap(centerImage.getBitmapWidth(), centerImage.getBitmapHeight(), Bitmap.Config.ARGB_8888); + if (stickerMakerView != null && stickerMakerView.getSourceBitmap() != null) { + Bitmap b = stickerMakerView.getSourceBitmap(); + Canvas canvas = new Canvas(originalBitmap); + canvas.translate(originalBitmap.getWidth() / 2f, originalBitmap.getHeight() / 2f); + canvas.rotate(stickerMakerView.orientation); + final float s = originalBitmap.getWidth() / (float) (stickerMakerView.orientation / 90 % 2 != 0 ? b.getHeight() : b.getWidth()); + AndroidUtilities.rectTmp.set( + -b.getWidth() / 2f * s, + -b.getHeight() / 2f * s, + b.getWidth() / 2f * s, + b.getHeight() / 2f * s + ); + canvas.drawBitmap(b, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + } + Bitmap bitmapToEdit = Bitmap.createBitmap(centerImage.getBitmapWidth(), centerImage.getBitmapHeight(), Bitmap.Config.ARGB_8888); + if (centerImage.getBitmap() != null) { + Bitmap b = centerImage.getBitmap(); + Canvas canvas = new Canvas(bitmapToEdit); + canvas.translate(bitmapToEdit.getWidth() / 2f, bitmapToEdit.getHeight() / 2f); + canvas.rotate(centerImage.getOrientation()); + final float s = bitmapToEdit.getWidth() / (float) (centerImage.getOrientation() / 90 % 2 != 0 ? b.getHeight() : b.getWidth()); + AndroidUtilities.rectTmp.set( + -b.getWidth() / 2f * s, + -b.getHeight() / 2f * s, + b.getWidth() / 2f * s, + b.getHeight() / 2f * s + ); + canvas.drawBitmap(b, null, AndroidUtilities.rectTmp, new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); + } + maskPaintView = new MaskPaintView(parentActivity, currentAccount, bitmapToEdit, originalBitmap, centerImage.getOrientation(), state) { + @Override + protected void onRenderViewAlphaUpdate(ValueAnimator animation) { + super.onRenderViewAlphaUpdate(animation); + containerView.invalidate(); + } + + @Override + protected void onDrawn() { + showEditStickerMode(true, true); + } + }; + maskPaintView.cancelButton.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + switchToEditMode(EDIT_MODE_NONE); + }); + maskPaintView.doneButton.setOnClickListener(v -> { + eraseBtn.setActive(false, true); + restoreBtn.setActive(false, true); + applyCurrentEditMode(); + switchToEditMode(EDIT_MODE_NONE); + }); + maskPaintView.setEraser(maskPaintViewEraser); + int index = containerView.indexOfChild(btnLayout) - 1; + if (index < 0) index = containerView.getChildCount(); + containerView.addView(maskPaintView, index, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + maskPaintViewShuttingDown = false; + } + private void createPaintView() { if (photoPaintView == null) { int w; @@ -11338,8 +11893,8 @@ protected void onTextAdd() { photoPaintView.setOffsetTranslationX(-dp(12)); } if (photoPaintView != null) { - photoPaintView.entitiesView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); - photoPaintView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); +// photoPaintView.entitiesView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); +// photoPaintView.setClipChildren(sendPhotoType != SELECT_TYPE_STICKER); } } @@ -11393,10 +11948,17 @@ private void switchToPaintMode() { updateActionBarTitlePadding(); } showEditCaption(false, true); - showStickerMode(false, true); + showStickerMode(false, false,true); Bitmap bitmap = centerImage.getBitmap(); final float finalScale = scale; + if (sendPhotoType == SELECT_TYPE_STICKER) { + savedTy = translationY; + savedTx = translationX; + savedScale = scale; + savedRotation = rotate; + animateToRotate = 0; + } if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -11431,12 +11993,16 @@ private void switchToPaintMode() { } oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); newScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); - animateToScale = newScale / oldScale * scale1(); // * finalScale; + animateToScale = newScale / oldScale * scale1(false); // * finalScale; animateToX = getLeftInset() / 2 - getRightInset() / 2; animationStartTime = System.currentTimeMillis(); zoomAnimation = true; } + if (photoPaintView != null) { + photoPaintView.setDrawShadow(sendPhotoType == SELECT_TYPE_STICKER && (editState == null || editState.cropState == null)); + } + windowView.setClipChildren(true); navigationBar.setVisibility(View.INVISIBLE); imageMoveAnimation = new AnimatorSet(); @@ -11464,9 +12030,8 @@ public void onAnimationEnd(Animator animation) { if (paintKeyboardNotifier != null) { paintKeyboardNotifier.ignore(currentEditMode != EDIT_MODE_PAINT); } - translateY = 0; switchingToMode = -1; - animateToScale = scale = scale1(); + animateToScale = scale = scale1(false); animateToX = 0; animateToY = 0; updateMinMax(scale); @@ -11487,6 +12052,12 @@ private void toggleCheckImageView(boolean show) { final float offsetY = AndroidUtilities.dpf2(24); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.ALPHA, show ? 1.0f : 0.0f)); arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, show ? 0.0f : offsetY)); + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerView, View.ALPHA, show ? 1.0f : 0.0f)); + } + if (stickerMakerView != null) { + arrayList.add(ObjectAnimator.ofFloat(stickerMakerBackgroundView, View.ALPHA, show ? 1.0f : 0.0f)); + } arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.ALPHA, show ? 1.0f : 0.0f)); arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, show ? 0.0f : offsetY)); if (sendPhotoType == 0 || sendPhotoType == 4) { @@ -12206,6 +12777,15 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca if (countView != null) { countView.updateShow(false, false); } + if (sendPhotoType != SELECT_TYPE_STICKER && stickerMakerView != null) { + stickerEmpty = false; + if (tuneItem != null) { + tuneItem.setAlpha(1f); + } + if (outlineBtn != null) outlineBtn.setActive(false, false); + stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); + } bottomLayout.setTranslationY(0); captionTextViewSwitcher.setTranslationY(0); setItemVisible(editItem, false, false); @@ -12536,7 +13116,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca pickerViewSendButton.setTranslationY(0); pickerViewSendButton.setAlpha(1.0f); } - if (navigationBar != null && !fancyShadows) { + if (navigationBar != null && (!fancyShadows || sendPhotoType == SELECT_TYPE_STICKER)) { navigationBar.setVisibility(View.VISIBLE); navigationBar.setAlpha(1.0f); } @@ -12560,6 +13140,9 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca } else { setImageIndex(index); } + if (tuneItem != null) { + tuneItem.setAlpha(stickerEmpty ? .4f : 1f); + } dialogPhotos = null; if (currentAnimation == null && !isEvent) { @@ -13348,12 +13931,12 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated menuItem.hideSubItem(gallery_menu_translate); menuItem.hideSubItem(gallery_menu_hide_translation); } - fancyShadows = editing && setAvatarFor == null; + fancyShadows = editing && setAvatarFor == null || sendPhotoType == SELECT_TYPE_STICKER; actionBar.setBackgroundColor(fancyShadows || setAvatarFor != null ? 0 : Theme.ACTION_BAR_PHOTO_VIEWER_COLOR); actionBarContainer.setTextShadows(fancyShadows); - navigationBar.setVisibility(fancyShadows ? View.GONE : View.VISIBLE); + navigationBar.setVisibility(fancyShadows && sendPhotoType != SELECT_TYPE_STICKER ? View.GONE : View.VISIBLE); if (currentEditMode == EDIT_MODE_NONE) { - navigationBar.setBackgroundColor(fancyShadows ? 0 : (sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); + navigationBar.setBackgroundColor(fancyShadows ? (sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0) : (sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); } if (title != null) { if (animated) { @@ -13395,7 +13978,7 @@ private CharSequence postProcessTranslated(MessageObject messageObject) { message = MessageObject.replaceAnimatedEmoji(message, messageObject.messageOwner.translatedText.entities, Theme.chat_msgTextPaint.getFontMetricsInt(), false); if (MessageObject.containsUrls(message)) { try { - AndroidUtilities.addLinks((Spannable) message, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + AndroidUtilities.addLinksSafe((Spannable) message, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, false, true); } catch (Exception e) { FileLog.e(e); } @@ -13411,58 +13994,188 @@ private CharSequence postProcessTranslated(MessageObject messageObject) { } public TLRPC.Document replacedSticker; + public boolean stickerEmpty; + public boolean stickerEmptySent; + public Utilities.Callback2 customStickerHandler; - public void enableStickerMode(TLRPC.Document document) { + public void enableStickerMode(TLRPC.Document document, boolean empty, Utilities.Callback2 customHandler) { replacedSticker = document; + stickerEmpty = empty; + stickerEmptySent = false; + customStickerHandler = customHandler; + rotate = 0; + animateToRotate = 0; if (stickerMakerView != null) { + if (outlineBtn != null) outlineBtn.setActive(false, false); stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); + } + if (replacedSticker != null) { + if (selectedEmojis == null) { + selectedEmojis = new ArrayList<>(); + } else { + selectedEmojis.clear(); + } + ArrayList stickerEmojis = MessageObject.findStickerEmoticons(document, currentAccount); + if (stickerEmojis != null) { + selectedEmojis.addAll(stickerEmojis); + } } if (cutOutBtn != null) { cutOutBtn.clean(); } showStickerMode(true, false); + if (tuneItem != null) { + tuneItem.setAlpha(stickerEmpty ? .4f : 1f); + } } public void prepareSegmentImage() { if (stickerMakerView != null && sendPhotoType == SELECT_TYPE_STICKER) { - stickerMakerView.segmentImage(centerImage.getBitmap(), centerImage.getOrientation(), getContainerViewWidth(), getContainerViewHeight()); + if (stickerEmpty) { + stickerMakerView.clean(); + } else { + stickerMakerView.segmentImage(centerImage.getBitmap(), centerImage.getOrientation(), getContainerViewWidth(), getContainerViewHeight(), object -> { + try { + MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); + boolean hasFilters = !TextUtils.isEmpty(entry.filterPath); + stickerMakerView.setSegmentedState(true, object); + Bitmap segmentedImage = stickerMakerView.getSegmentedImage(centerImage.getBitmap(), hasFilters, centerImage.getOrientation()); + centerImage.setImageBitmap(segmentedImage); + cutOutBtn.setUndoCutState(true); + showStickerMode(true, true, true); + cutOutBtn.post(this::applyCurrentEditMode); + } catch (Exception e) { + FileLog.e(e); + } + }); + } } } private void showStickerMode(boolean show, boolean animated) { + showStickerMode(show, show, animated); + } + + private void showStickerMode(boolean show, boolean buttonsShow, boolean animated) { if (!animated) { stickerMakerView.animate().setListener(null).cancel(); stickerMakerView.setVisibility(show ? View.VISIBLE : View.GONE); stickerMakerView.setAlpha(pickerView.getAlpha()); stickerMakerBackgroundView.animate().setListener(null).cancel(); stickerMakerBackgroundView.setVisibility(show ? View.VISIBLE : View.GONE); - stickerMakerBackgroundView.setAlpha(show ? pickerView.getAlpha() : 0f); - cutOutBtn.animate().setListener(null).cancel(); - cutOutBtn.setVisibility(show ? View.VISIBLE : View.GONE); - cutOutBtn.setAlpha(pickerView.getAlpha()); + stickerMakerBackgroundView.setAlpha(show ? 1f : 0f); } else { - if (show && cutOutBtn.getTag() == null) { + if (show && stickerMakerView.getTag() == null) { stickerMakerView.animate().setListener(null).cancel(); - cutOutBtn.animate().setListener(null).cancel(); stickerMakerBackgroundView.animate().setListener(null).cancel(); - if (cutOutBtn.getVisibility() != View.VISIBLE) { - cutOutBtn.setVisibility(View.VISIBLE); - cutOutBtn.animate().alpha(pickerView.getAlpha()).start(); + if (stickerMakerView.getVisibility() != View.VISIBLE) { stickerMakerView.setVisibility(View.VISIBLE); - stickerMakerView.animate().alpha(pickerView.getAlpha()).start(); + stickerMakerView.animate().alpha(1f).start(); stickerMakerBackgroundView.setVisibility(View.VISIBLE); - stickerMakerBackgroundView.animate().alpha(pickerView.getAlpha()).start(); + stickerMakerBackgroundView.animate().alpha(1f).start(); } - } else if (!show && cutOutBtn.getTag() != null) { + } else if (!show && stickerMakerView.getTag() != null) { stickerMakerView.animate().setListener(null).cancel(); - cutOutBtn.animate().setListener(null).cancel(); - stickerMakerBackgroundView.animate().setListener(null).cancel(); - cutOutBtn.animate().alpha(0f).setListener(new HideViewAfterAnimation(cutOutBtn)).start(); stickerMakerView.animate().alpha(0f).setListener(new HideViewAfterAnimation(stickerMakerView)).start(); + stickerMakerBackgroundView.animate().setListener(null).cancel(); stickerMakerBackgroundView.animate().alpha(0f).setListener(new HideViewAfterAnimation(stickerMakerBackgroundView)).start(); } } - cutOutBtn.setTag(show ? 1 : null); + stickerMakerView.setTag(show ? 1 : null); + boolean buttonShow = show && !cutOutBtn.isUndoCutState() && !stickerEmpty; + if (!animated) { + cutOutBtn.animate().setListener(null).cancel(); + cutOutBtn.setVisibility(buttonShow ? View.VISIBLE : View.GONE); + cutOutBtn.setAlpha(buttonShow ? 1f : 0f); + } else { + if (buttonShow && cutOutBtn.getTag() == null) { + cutOutBtn.animate().setListener(null).cancel(); + if (cutOutBtn.getVisibility() != View.VISIBLE) { + cutOutBtn.setVisibility(View.VISIBLE); + } + cutOutBtn.animate().alpha(1f).start(); + } else if (!buttonShow && cutOutBtn.getTag() != null) { + cutOutBtn.animate().setListener(null).cancel(); + cutOutBtn.animate().alpha(0f).setListener(new HideViewAfterAnimation(cutOutBtn)).start(); + } + } + cutOutBtn.setTag(buttonShow ? 1 : null); + showEditStickerMode(show && cutOutBtn.isUndoCutState() && !stickerEmpty, animated); + + stickerMakerView.setOutlineVisible(show && cutOutBtn.isUndoCutState() && outlineBtn.isActive() && !(eraseBtn.isActive() || restoreBtn.isActive())); + boolean outlineShow = show && cutOutBtn.isUndoCutState() && !(eraseBtn.isActive() || restoreBtn.isActive()); + if (!animated) { + outlineBtn.animate().setListener(null).cancel(); + outlineBtn.setVisibility(outlineShow ? View.VISIBLE : View.GONE); + outlineBtn.setAlpha(outlineShow ? 1f : 0f); + outlineBtn.setScaleX(outlineShow ? 1f : .8f); + outlineBtn.setScaleY(outlineShow ? 1f : .8f); + } else { + if (outlineShow && outlineBtn.getTag() == null) { + outlineBtn.animate().setListener(null).cancel(); + if (outlineBtn.getVisibility() != View.VISIBLE) { + outlineBtn.setVisibility(View.VISIBLE); + } + outlineBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } else if (!outlineShow && outlineBtn.getTag() != null) { + outlineBtn.animate().setListener(null).cancel(); + outlineBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(outlineBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + outlineBtn.setTag(outlineShow ? 1 : null); + } + + private void showEditStickerMode(boolean show, boolean animated) { + boolean showUndoBtn = show && stickerMakerView != null && (!stickerMakerView.empty || stickerMakerView.overriddenPaths() || maskPaintView != null && maskPaintView.canUndo()); + if (!animated) { + undoBtn.animate().setListener(null).cancel(); + undoBtn.setVisibility(showUndoBtn ? View.VISIBLE : View.GONE); + undoBtn.setAlpha(showUndoBtn ? 1f : 0f); + undoBtn.setScaleX(showUndoBtn ? 1f : .8f); + undoBtn.setScaleY(showUndoBtn ? 1f : .8f); + } else { + if (showUndoBtn && undoBtn.getTag() == null) { + undoBtn.animate().setListener(null).cancel(); + if (undoBtn.getVisibility() != View.VISIBLE) { + undoBtn.setVisibility(View.VISIBLE); + undoBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } else if (!showUndoBtn && undoBtn.getTag() != null) { + undoBtn.animate().setListener(null).cancel(); + undoBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(undoBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + undoBtn.setTag(showUndoBtn ? 1 : null); + if (!animated) { + eraseBtn.animate().setListener(null).cancel(); + eraseBtn.setVisibility(show ? View.VISIBLE : View.GONE); + eraseBtn.setAlpha(show ? 1f : 0f); + eraseBtn.setScaleX(show ? 1f : .8f); + eraseBtn.setScaleY(show ? 1f : .8f); + restoreBtn.animate().setListener(null).cancel(); + restoreBtn.setVisibility(show ? View.VISIBLE : View.GONE); + restoreBtn.setAlpha(show ? 1f : 0f); + restoreBtn.setScaleX(show ? 1f : .8f); + restoreBtn.setScaleY(show ? 1f : .8f); + } else { + if (show && eraseBtn.getTag() == null) { + eraseBtn.animate().setListener(null).cancel(); + restoreBtn.animate().setListener(null).cancel(); + if (eraseBtn.getVisibility() != View.VISIBLE) { + eraseBtn.setVisibility(View.VISIBLE); + eraseBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + restoreBtn.setVisibility(View.VISIBLE); + restoreBtn.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } else if (!show && eraseBtn.getTag() != null) { + eraseBtn.animate().setListener(null).cancel(); + eraseBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(eraseBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + restoreBtn.animate().setListener(null).cancel(); + restoreBtn.animate().alpha(0f).scaleX(.8f).scaleY(.8f).setListener(new HideViewAfterAnimation(restoreBtn)).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(400).start(); + } + } + eraseBtn.setTag(show ? 1 : null); } private ObjectAnimator captionAnimator; @@ -13540,6 +14253,9 @@ private void showVideoTimeline(boolean show, boolean animated) { videoTimelineAnimator.start(); } } + if (videoTimelineViewContainer != null && videoTimelineViewContainer.getVisibility() != View.GONE) { + videoTimelineViewContainer.setTranslationY(pickerView.getTranslationY() - Math.max(0, captionEdit.getEditTextHeight() - dp(46))); + } videoTimelineViewContainer.setTag(show ? 1 : null); } @@ -13793,7 +14509,9 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { } pinchStartDistance = 0; + pinchStartAngle = 0; pinchStartScale = 1; + pinchStartRotate = 0; pinchCenterX = 0; pinchCenterY = 0; pinchStartX = 0; @@ -13803,6 +14521,7 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { zooming = false; moving = false; paintViewTouched = 0; + maskPaintViewTouched = 0; doubleTap = false; invalidCoords = false; canDragDown = true; @@ -14939,7 +15658,13 @@ public boolean openPhotoForSelect(final TLRPC.FileLocation fileLocation, final I pickerViewSendButton.setLayoutParams(layoutParams2); } if (type != SELECT_TYPE_STICKER && stickerMakerView != null) { + stickerEmpty = false; + if (tuneItem != null) { + tuneItem.setAlpha(1f); + } + if (outlineBtn != null) outlineBtn.setActive(false, false); stickerMakerView.clean(); + if (selectedEmojis != null) selectedEmojis.clear(); } if (sendPhotoType != SELECT_TYPE_AVATAR && type == SELECT_TYPE_AVATAR && isVisible) { sendPhotoType = type; @@ -14978,6 +15703,9 @@ public boolean openPhotoForSelect(final TLRPC.FileLocation fileLocation, final I return true; } sendPhotoType = type; + if (sendPhotoType == SELECT_TYPE_STICKER) { + navigationBar.setBackgroundColor(0xFF000000); + } return openPhoto(null, fileLocation, imageLocation, null, null, null, photos, index, provider, chatActivity, 0, 0, 0, true, null, null); } @@ -15420,6 +16148,8 @@ public boolean onPreDraw() { } yPos = ((AndroidUtilities.displaySize.y + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0)) - (layoutParams.height * scale)) / 2.0f; xPos = (windowView.getMeasuredWidth() - layoutParams.width * scale) / 2.0f; + rotate = 0; + animateToRotate = 0; } int clipHorizontal = (int) Math.abs(left - object.imageReceiver.getImageX()); int clipVertical = (int) Math.abs(top - object.imageReceiver.getImageY()); @@ -15649,7 +16379,7 @@ public boolean onPreDraw() { animatorSet.playTogether( ObjectAnimator.ofFloat(containerView, View.ALPHA, 0f, 1f).setDuration(220), ObjectAnimator.ofFloat(navigationBar, View.ALPHA, 0f, 1f).setDuration(220), - a2 + a2, a3 ); animatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -15792,6 +16522,15 @@ public void injectVideoPlayerToMediaController() { } public void closePhoto(boolean animated, boolean fromEditMode) { + if (stickerMakerView != null) { + stickerMakerView.isThanosInProgress = false; + if (cutOutBtn.isCancelState()) { + cutOutBtn.setCutOutState(true); + showEditStickerMode(false, true); + stickerMakerView.disableClippingMode(); + containerView.invalidate(); + } + } if (!fromEditMode && currentEditMode != EDIT_MODE_NONE) { if (currentEditMode == EDIT_MODE_PAINT && photoPaintView != null) { closePaintMode(); @@ -15800,6 +16539,9 @@ public void closePhoto(boolean animated, boolean fromEditMode) { if (currentEditMode == EDIT_MODE_CROP) { cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, 1.0f, 1.0f, previousCropPw, previousCropPh, 0, 0, previousCropMirrored); } + if (currentEditMode == EDIT_MODE_STICKER_MASK) { + applyCurrentEditMode(); + } switchToEditMode(EDIT_MODE_NONE); return; } @@ -15834,6 +16576,19 @@ public void closePhoto(boolean animated, boolean fromEditMode) { containerView.removeView(photoPaintView.getView()); photoPaintView = null; savedState = null; + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintViewShuttingDown = true; + if (containerView != null) { + containerView.invalidate(); + final MaskPaintView _maskPaintView = maskPaintView; + containerView.post(() -> { + _maskPaintView.shutdown(); + containerView.removeView(maskPaintView); + }); + } else { + maskPaintView.shutdown(); + } + maskPaintView = null; } currentEditMode = EDIT_MODE_NONE; captionEdit.keyboardNotifier.ignore(false); @@ -16122,6 +16877,14 @@ public void closePhoto(boolean animated, boolean fromEditMode) { invalidateBlur(); onPhotoClosed(object); MediaController.getInstance().tryResumePausedAudio(); + if (stickerEmpty && !stickerEmptySent && imagesArrLocals != null) { + for (Object obj : imagesArrLocals) { + if (obj instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry entry = (MediaController.PhotoEntry) obj; + entry.deleteAll(); + } + } + } }; animatorSet.setDuration(200); @@ -16166,6 +16929,14 @@ public void onAnimationEnd(Animator animation) { containerView.setScaleX(1.0f); containerView.setScaleY(1.0f); MediaController.getInstance().tryResumePausedAudio(); + if (stickerEmpty && !stickerEmptySent && imagesArrLocals != null) { + for (Object obj : imagesArrLocals) { + if (obj instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry entry = (MediaController.PhotoEntry) obj; + entry.deleteAll(); + } + } + } }; animatorSet.setDuration(200); animatorSet.addListener(new AnimatorListenerAdapter() { @@ -16452,21 +17223,23 @@ private void updateMinMax(float scale) { } } - private int getAdditionX() { - if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + private int getAdditionX(int mode) { + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { return dp(16); - } else if (currentEditMode != EDIT_MODE_NONE && currentEditMode != EDIT_MODE_PAINT) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK && mode != EDIT_MODE_PAINT) { return dp(14); } return 0; } - private int getAdditionY() { - if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { + private int getAdditionY(int mode) { + if (mode < 0) + return 0; + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { return dp(16) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0); - } else if (currentEditMode == EDIT_MODE_PAINT) { + } else if (mode == EDIT_MODE_PAINT && photoPaintView != null) { return dp(8) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0) + photoPaintView.getAdditionalTop(); - } else if (currentEditMode != EDIT_MODE_NONE) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK) { return dp(14) + (isStatusBarVisible() ? AndroidUtilities.statusBarHeight : 0); } return 0; @@ -16478,9 +17251,9 @@ private int getContainerViewWidth() { private int getContainerViewWidth(int mode) { int width = containerView.getWidth(); - if (mode == 1 || mode == 0 && sendPhotoType == SELECT_TYPE_AVATAR) { + if (mode == EDIT_MODE_CROP || mode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { width -= dp(32); - } else if (mode != 0 && mode != 3) { + } else if (mode != EDIT_MODE_NONE && mode != EDIT_MODE_STICKER_MASK && mode != EDIT_MODE_PAINT) { width -= dp(28); } return width; @@ -16500,7 +17273,7 @@ private int getContainerViewHeight(boolean trueHeight, int mode) { height = containerView.getMeasuredHeight(); } else { height = AndroidUtilities.displaySize.y; - if (mode == EDIT_MODE_NONE && sendPhotoType != SELECT_TYPE_AVATAR && isStatusBarVisible()) { + if ((mode == EDIT_MODE_NONE || mode == EDIT_MODE_STICKER_MASK) && sendPhotoType != SELECT_TYPE_AVATAR && isStatusBarVisible()) { height += AndroidUtilities.statusBarHeight; } } @@ -16577,9 +17350,16 @@ private boolean onTouchEvent(MotionEvent ev) { photoPaintView.onTouch(event); event.recycle(); paintViewTouched = 2; + } else if (maskPaintViewTouched == 1) { + MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); + maskPaintView.onTouch(event); + event.recycle(); + maskPaintViewTouched = 2; } pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)); + pinchStartAngle = (float) Math.atan2(ev.getY(1) - ev.getY(0), ev.getX(1) - ev.getX(0)); pinchStartScale = scale; + pinchStartRotate = rotate; pinchCenterX = (ev.getX(0) + ev.getX(1)) / 2.0f; pinchCenterY = (ev.getY(0) + ev.getY(1)) / 2.0f; pinchStartX = translationX; @@ -16609,6 +17389,18 @@ private boolean onTouchEvent(MotionEvent ev) { paintViewTouched = 1; } } + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + if (maskPaintViewTouched == 0) { + View v = maskPaintView; + v.getHitRect(hitRect); + if (hitRect.contains((int) ev.getX(), (int) ev.getY())) { + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + maskPaintViewTouched = 1; + } + } } else { moveStartX = ev.getX(); dragY = moveStartY = ev.getY(); @@ -16648,6 +17440,9 @@ private boolean onTouchEvent(MotionEvent ev) { pinchCenterX = newPinchCenterX; pinchCenterY = newPinchCenterY; } + if (sendPhotoType == SELECT_TYPE_STICKER && currentEditMode == EDIT_MODE_NONE) { + rotate = (float) ((Math.atan2(ev.getY(1) - ev.getY(0), ev.getX(1) - ev.getX(0)) - pinchStartAngle) / Math.PI * 180 + pinchStartRotate); + } scale = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)) / pinchStartDistance * pinchStartScale; translationX = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (scale / pinchStartScale); translationY = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (scale / pinchStartScale); @@ -16662,6 +17457,13 @@ private boolean onTouchEvent(MotionEvent ev) { photoPaintView.onTouch(event); event.recycle(); return true; + } else if (maskPaintViewTouched == 1 && maskPaintView != null) { + View v = maskPaintView; + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + return true; } if (velocityTracker != null) { velocityTracker.addMovement(ev); @@ -16748,20 +17550,33 @@ private boolean onTouchEvent(MotionEvent ev) { photoPaintView.onTouch(event); event.recycle(); } - paintViewTouched = 0; + maskPaintViewTouched = paintViewTouched = 0; + return true; + } + if (maskPaintViewTouched == 1) { + if (maskPaintView != null) { + View v = maskPaintView; + MotionEvent event = MotionEvent.obtain(ev); + event.offsetLocation(-v.getX(), -v.getY()); + maskPaintView.onTouch(event); + event.recycle(); + } + maskPaintViewTouched = paintViewTouched = 0; return true; } paintViewTouched = 0; + maskPaintViewTouched = 0; if (zooming) { invalidCoords = true; - float maxScale = sendPhotoType == SELECT_TYPE_STICKER ? 0.33f : 1f; - if (scale < maxScale) { + float maxScale = sendPhotoType == SELECT_TYPE_STICKER ? 10.0f : 3.0f; + float minScale = sendPhotoType == SELECT_TYPE_STICKER ? 0.33f : 1f; + if (scale < minScale) { + updateMinMax(minScale); + animateTo(minScale, 0, 0, true); + } else if (scale > maxScale) { + float atx = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (maxScale / pinchStartScale); + float aty = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (maxScale / pinchStartScale); updateMinMax(maxScale); - animateTo(maxScale, 0, 0, true); - } else if (scale > 3.0f) { - float atx = (pinchCenterX - getContainerViewWidth() / 2) - ((pinchCenterX - getContainerViewWidth() / 2) - pinchStartX) * (3.0f / pinchStartScale); - float aty = (pinchCenterY - getContainerViewHeight() / 2) - ((pinchCenterY - getContainerViewHeight() / 2) - pinchStartY) * (3.0f / pinchStartScale); - updateMinMax(3.0f); if (atx < minX) { atx = minX; } else if (atx > maxX) { @@ -16772,7 +17587,7 @@ private boolean onTouchEvent(MotionEvent ev) { } else if (aty > maxY) { aty = maxY; } - animateTo(3.0f, atx, aty, true); + animateTo(maxScale, atx, aty, true); } else { checkMinMax(true); if (currentEditMode == EDIT_MODE_PAINT) { @@ -17129,6 +17944,7 @@ private void onDraw(Canvas canvas) { translationX = animateToX; translationY = animateToY; scale = animateToScale; + rotate = animateToRotate; animationStartTime = 0; updateMinMax(scale); zoomAnimation = false; @@ -17324,7 +18140,7 @@ public void onAnimationEnd(Animator animation) { float translateX = currentTranslationX; float scaleDiff = 0; float alpha = 1; - if (!zoomAnimation && translateX > maxX && currentEditMode == EDIT_MODE_NONE && sendPhotoType != SELECT_TYPE_AVATAR) { + if (!zoomAnimation && translateX > maxX && (currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK) && sendPhotoType != SELECT_TYPE_AVATAR) { alpha = Math.min(1.0f, (translateX - maxX) / containerWidth); scaleDiff = alpha * 0.3f; alpha = 1.0f - alpha; @@ -17333,22 +18149,46 @@ public void onAnimationEnd(Animator animation) { boolean drawTextureView = videoSizeSet && aspectRatioFrameLayout != null && aspectRatioFrameLayout.getVisibility() == View.VISIBLE; centerImageTransformLocked = false; centerImageTransform.reset(); + if (maskPaintView != null && !maskPaintViewShuttingDown && maskPaintView.getRenderView() != null) { + alpha = maskPaintView.getRenderView().getAlpha() > .99f ? 0f : 1f; + } if (centerImage.hasBitmapImage() || drawTextureView && textureUploaded) { + if (stickerMakerView != null && stickerMakerView.outlineVisible) { + boolean isCropped = false; + try { + Object object = imagesArrLocals.get(currentIndex); + MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); + isCropped = photoEntry.isCropped; + } catch (Exception e) {} + if (isCropped) { + stickerMakerView.updateOutlineBounds(false); + } else { + int stickerSize = containerWidth - dp(20); + stickerMakerView.outlineMatrix.reset(); + stickerMakerView.outlineMatrix.postTranslate(-.5f, -.5f); + stickerMakerView.outlineMatrix.postScale(stickerSize, stickerSize); + stickerMakerView.outlineMatrix.postScale(1f / currentScale, 1f / currentScale); + stickerMakerView.outlineMatrix.postTranslate(-currentTranslationX / currentScale, -currentTranslationY / currentScale); + stickerMakerView.outlineMatrix.postRotate(-currentRotation); + stickerMakerView.updateOutlineBounds(true); + } + } + canvas.save(); - canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); - centerImageTransform.postTranslate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + canvas.translate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); + centerImageTransform.preTranslate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); canvas.translate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); centerImageTransform.preTranslate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); centerImageTransform.preScale(currentScale - scaleDiff, currentScale - scaleDiff); canvas.rotate(currentRotation); - centerImageTransform.postRotate(currentRotation); + centerImageTransform.preRotate(currentRotation); if (currentEditMode == EDIT_MODE_PAINT && photoPaintView != null) { int trueH = getContainerViewHeight(true, 0); trueH -= photoPaintView.getEmojiPadding(Math.abs(AndroidUtilities.displaySize.y + AndroidUtilities.statusBarHeight - trueH) < dp(20)); int h = getContainerViewHeight(false, 0); canvas.translate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); - centerImageTransform.postTranslate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); + centerImageTransform.preTranslate(0, (trueH - h) / 2f * (1f - photoPaintView.adjustPanLayoutHelperProgress())); } boolean drawCenterImage = false; @@ -17374,15 +18214,14 @@ public void onAnimationEnd(Animator animation) { } width *= scale; height *= scale; -// centerImageTransform.postScale(scale, scale); centerImage.setImageCoords(-width / 2, -height / 2, width, height); if (isCurrentVideo) { centerImage.draw(canvas); + centerImageTransformLocked = true; } else { drawCenterImage = true; } } - centerImageTransformLocked = true; } int bitmapWidth, originalWidth; @@ -17406,9 +18245,9 @@ public void onAnimationEnd(Animator animation) { if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) { applyCrop = true; } else if (sendPhotoType == SELECT_TYPE_AVATAR) { - applyCrop = (switchingToMode == EDIT_MODE_NONE || currentEditMode != EDIT_MODE_PAINT && currentEditMode != EDIT_MODE_FILTER); + applyCrop = (switchingToMode == EDIT_MODE_NONE || currentEditMode != EDIT_MODE_FILTER); } else { - applyCrop = imageMoveAnimation != null && switchingToMode != -1 || currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_CROP || switchingToMode != -1; + applyCrop = imageMoveAnimation != null && switchingToMode != -1 || currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_STICKER_MASK || currentEditMode == EDIT_MODE_CROP || switchingToMode != -1; } } else { applyCrop = false; @@ -17430,7 +18269,7 @@ public void onAnimationEnd(Animator animation) { if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { cropAnimationValue = 1.0f; } else if (imageMoveAnimation != null && switchingToMode != -1) { - if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) { + if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP) { cropAnimationValue = 1.0f; } else if (switchingToMode == EDIT_MODE_NONE) { cropAnimationValue = animationValue; @@ -17499,21 +18338,21 @@ public void onAnimationEnd(Animator animation) { } canvas.translate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); canvas.scale(cropScale, cropScale); - if (!centerImageTransformLocked) centerImageTransform.postScale(cropScale, cropScale); + if (!centerImageTransformLocked) centerImageTransform.preScale(cropScale, cropScale); canvas.translate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); float rotation = (cropTransform.getRotation() + orientation); if (rotation > 180) { rotation -= 360; } if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { canvas.rotate(rotation); - if (!centerImageTransformLocked) centerImageTransform.postRotate(rotation); + if (!centerImageTransformLocked) centerImageTransform.preRotate(rotation); } else { canvas.rotate(rotation * cropAnimationValue); - if (!centerImageTransformLocked) centerImageTransform.postRotate(rotation * cropAnimationValue); + if (!centerImageTransformLocked) centerImageTransform.preRotate(rotation * cropAnimationValue); } } else { if (videoTextureView != null) { @@ -17528,6 +18367,8 @@ public void onAnimationEnd(Animator animation) { } if (currentEditMode == EDIT_MODE_PAINT) { photoPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY + (sendPhotoType == SELECT_TYPE_AVATAR ? AndroidUtilities.statusBarHeight / 2f : 0) * photoPaintView.getRenderView().getScaleX(), bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); + } else if (currentEditMode == EDIT_MODE_STICKER_MASK) { + maskPaintView.setTransform(currentScale, currentTranslationX, currentTranslationY, currentRotation, bitmapWidth * scaleToFitX, bitmapHeight * scaleToFitX); } if (drawCenterImage && !usedSurfaceView) { @@ -17557,7 +18398,7 @@ public void onAnimationEnd(Animator animation) { } if (videoTextureView instanceof VideoEditTextureView) { VideoEditTextureView videoEditTextureView = (VideoEditTextureView) videoTextureView; - videoEditTextureView.setViewRect((containerWidth - width) / 2 + getAdditionX() + translateX, (containerHeight - height) / 2 + getAdditionY() + currentTranslationY + currentPanTranslationY, width, height); + videoEditTextureView.setViewRect((containerWidth - width) / 2f + getAdditionX(currentEditMode) + translateX, (containerHeight - height) / 2f + getAdditionY(currentEditMode) + currentTranslationY + currentPanTranslationY, width, height); } if (videoSurfaceView != null && waitingForDraw == 0 && !changingTextureView && !switchingInlineMode && !pipAnimationInProgress && videoSurfaceView.getVisibility() != View.VISIBLE) { videoSurfaceView.setVisibility(View.VISIBLE); @@ -17747,6 +18588,7 @@ public void onAnimationEnd(Animator animation) { drawFancyShadows(canvas); } + private Matrix m; private Path clipFancyShadows; private Paint topFancyShadowPaint, bottomFancyShadowPaint; @@ -17826,8 +18668,11 @@ private void drawCenterImageInternal(Canvas canvas, float currentMirror, float a canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); } if (photoViewerWebView == null || !photoViewerWebView.isLoaded()) { + if (!centerImageTransformLocked) centerImageTransform.preTranslate(centerImage.getImageX(), centerImage.getImageY()); + stickerMakerView.drawOutline(canvas, false, containerView, switchingToMode != -1); centerImage.setAlpha(alpha); centerImage.draw(canvas); + stickerMakerView.drawOutline(canvas, true, containerView, switchingToMode != -1); stickerMakerView.drawSegmentBorderPath(canvas, centerImage, centerImageTransform, containerView); centerImageTransformLocked = true; } @@ -17972,6 +18817,7 @@ private int[] applyCrop(Canvas canvas, int containerWidth, int containerHeight, return tempInt; } + private void onActionClick(boolean download) { if (currentMessageObject == null && currentBotInlineResult == null && (pageBlocksAdapter == null || currentFileNames[0] == null) && sendPhotoType != SELECT_TYPE_NO_SELECT) { return; @@ -18851,8 +19697,8 @@ private void showQualityView(final boolean show) { if (show) { if (fancyShadows) { navigationBar.setVisibility(View.VISIBLE); - navigationBar.setAlpha(0f); - navigationBar.setBackgroundColor((sendPhotoType == SELECT_TYPE_STICKER ? 0xFF000000 : 0x7f000000)); + navigationBar.setAlpha(sendPhotoType == SELECT_TYPE_STICKER ? 1f : 0f); + navigationBar.setBackgroundColor((sendPhotoType == SELECT_TYPE_STICKER ? 0x66000000 : 0x7f000000)); } qualityChooseView.setTag(1); qualityChooseViewAnimation.playTogether( @@ -19455,12 +20301,12 @@ private void drawCaptionBlur(Canvas canvas, BlurringShader.StoryBlurDrawer drawe boolean drawTextureView = videoSizeSet && aspectRatioFrameLayout != null && aspectRatioFrameLayout.getVisibility() == View.VISIBLE; if (centerImage.hasBitmapImage() || drawTextureView && textureUploaded) { canvas.save(); - canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + canvas.translate(containerWidth / 2 + getAdditionX(currentEditMode), containerHeight / 2 + getAdditionY(currentEditMode)); canvas.translate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); canvas.rotate(currentRotation); if (allowCrossfade) { - imageBoundsMatrix.preTranslate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); + imageBoundsMatrix.preTranslate(containerWidth / 2 + getAdditionX(currentEditMode), containerHeight / 2 + getAdditionY(currentEditMode)); imageBoundsMatrix.preTranslate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); imageBoundsMatrix.preScale(currentScale - scaleDiff, currentScale - scaleDiff, 0, 0); imageBoundsMatrix.preRotate(currentRotation); @@ -19847,12 +20693,16 @@ private void drawCaptionBlur(Canvas canvas, BlurringShader.StoryBlurDrawer drawe private void cancelStickerClippingMode() { if (sendPhotoType == SELECT_TYPE_STICKER && cutOutBtn.isCancelState()) { cutOutBtn.setCutOutState(true); + showEditStickerMode(true, true); stickerMakerView.disableClippingMode(); containerView.invalidate(); } } private void invalidateBlur() { + if (stickerMakerView != null && stickerMakerView.isThanosInProgress) { + return; + } if (animationInProgress != 0) { return; } @@ -19862,6 +20712,18 @@ private void invalidateBlur() { if (cutOutBtn != null) { cutOutBtn.invalidateBlur(); } + if (eraseBtn != null) { + eraseBtn.invalidateBlur(); + } + if (restoreBtn != null) { + restoreBtn.invalidateBlur(); + } + if (undoBtn != null) { + undoBtn.invalidateBlur(); + } + if (outlineBtn != null) { + outlineBtn.invalidateBlur(); + } if (videoTimelineView != null) { videoTimelineView.invalidateBlur(); } @@ -19869,4 +20731,278 @@ private void invalidateBlur() { containerView.invalidate(); } } + + private class BlurButton extends StickerCutOutBtn { + public BlurButton() { + super(stickerMakerView, activityContext, resourcesProvider, blurManager); + } + + private final Path path = new Path(); + private boolean active; + private final AnimatedFloat activeFloat = new AnimatedFloat(this, 0, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + path.rewind(); + path.addRoundRect(bounds, dp(rad), dp(rad), Path.Direction.CW); + canvas.clipPath(path); + canvas.translate(-getX(), -getY()); + if (this == eraseBtn || this == restoreBtn) { + canvas.translate(-btnLayout.getX(), -btnLayout.getY()); + } + drawCaptionBlur(canvas, blurDrawer, 0xFF2b2b2b, 0x33000000, false, true, false); + float active = activeFloat.set(this.active); + if (active > 0) { + canvas.drawColor(Theme.multAlpha(Color.WHITE, active)); + } + setTextColor(ColorUtils.blendARGB(0xFFFFFFFF, 0xFF000000, active)); + canvas.restore(); + super.onDraw(canvas); + } + + @Override + public void onDrawForeground(Canvas canvas) { + canvas.save(); + canvas.clipPath(path); + super.onDrawForeground(canvas); + canvas.restore(); + } + + public void setActive(boolean active, boolean animated) { + this.active = active; + if (!animated) { + activeFloat.set(active, true); + } + invalidate(); + } + + public boolean isActive() { + return active; + } + } + + private void applyTransformToOutline(Canvas canvas) { + float currentTranslationY; + float currentTranslationX; + float currentScale; + float currentRotation; + float currentMirror; + if (imageMoveAnimation != null) { + currentMirror = lerp(mirror, animateToMirror, animationValue); + currentScale = lerp(scale, animateToScale, animationValue); + currentRotation = lerp(rotate, animateToRotate, animationValue); + currentTranslationY = lerp(translationY, animateToY, animationValue); + currentTranslationX = lerp(translationX, animateToX, animationValue); + } else { + currentScale = scale; + currentMirror = mirror; + currentRotation = rotate; + currentTranslationY = translationY; + currentTranslationX = translationX; + if (animationStartTime != 0) { + currentTranslationX = animateToX; + currentTranslationY = animateToY; + currentScale = animateToScale; + } + } + + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + + canvas.translate(getAdditionX(currentEditMode), getAdditionY(currentEditMode)); + canvas.translate(currentTranslationX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); + canvas.scale(currentScale, currentScale); + canvas.rotate(currentRotation); + + int bitmapWidth, originalWidth; + int bitmapHeight, originalHeight; + originalWidth = bitmapWidth = centerImage.getBitmapWidth(); + originalHeight = bitmapHeight = centerImage.getBitmapHeight(); + + float scale = Math.min(containerWidth / (float) originalWidth, containerHeight / (float) originalHeight); + + float scaleToFitX = 1.0f; + int rotatedWidth = originalWidth; + int rotatedHeight = originalHeight; + int orientation = cropTransform.getOrientation(); + if (orientation == 90 || orientation == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + + temp = rotatedWidth; + rotatedWidth = rotatedHeight; + rotatedHeight = temp; + } + float cropAnimationValue = 1.0f; + float cropPw = cropTransform.getCropPw(); + float cropPh = cropTransform.getCropPh(); + bitmapWidth *= cropPw + (1.0f - cropPw) * (1.0f - cropAnimationValue); + bitmapHeight *= cropPh + (1.0f - cropPh) * (1.0f - cropAnimationValue); + scaleToFitX = containerWidth / (float) bitmapWidth; + if (scaleToFitX * bitmapHeight > containerHeight) { + scaleToFitX = containerHeight / (float) bitmapHeight; + } + if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == EDIT_MODE_NONE) && editState.cropState != null) { + float startW = bitmapWidth * scaleToFitX; + float startH = bitmapHeight * scaleToFitX; + float originalScaleToFitX = containerWidth / (float) originalWidth; + if (originalScaleToFitX * originalHeight > containerHeight) { + originalScaleToFitX = containerHeight / (float) originalHeight; + } + float finalW = originalWidth * originalScaleToFitX / (currentScale); + float finalH = originalHeight * originalScaleToFitX / (currentScale); + + float w = startW + (finalW - startW) * (1.0f - cropAnimationValue); + float h = startH + (finalH - startH) * (1.0f - cropAnimationValue); + + canvas.clipRect(-w / 2, -h / 2, w / 2, h / 2); + } + if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) { + float cropScale; + if (videoTextureView != null) { + videoTextureView.setScaleX(editState.cropState != null && editState.cropState.mirrored ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } + } + cropScale = editState.cropState != null ? editState.cropState.cropScale : 1.0f; + float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue); + cropScale *= scaleToFitX / scale / trueScale; + + canvas.translate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + canvas.scale(cropScale, cropScale); + canvas.translate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + float rotation = (cropTransform.getRotation() + orientation); + if (rotation > 180) { + rotation -= 360; + } + canvas.rotate(rotation); + } + + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + mirror = editState.cropState != null && editState.cropState.mirrored; + } + if (mirror) { + canvas.scale(-1, 1); + } + if (currentMirror > 0) { + canvas.scale(1 - currentMirror * 2, 1f); + canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); + } + } + + private void applyTransformToMatrix(Matrix matrix) { + float currentTranslationY; + float currentTranslationX; + float currentScale; + float currentRotation; + float currentMirror; + if (imageMoveAnimation != null) { + currentMirror = lerp(mirror, animateToMirror, animationValue); + currentScale = lerp(scale, animateToScale, animationValue); + currentRotation = lerp(rotate, animateToRotate, animationValue); + currentTranslationY = lerp(translationY, animateToY, animationValue); + currentTranslationX = lerp(translationX, animateToX, animationValue); + } else { + currentScale = scale; + currentMirror = mirror; + currentRotation = rotate; + currentTranslationY = translationY; + currentTranslationX = translationX; + if (animationStartTime != 0) { + currentTranslationX = animateToX; + currentTranslationY = animateToY; + currentScale = animateToScale; + } + } + + int containerWidth = getContainerViewWidth(); + int containerHeight = getContainerViewHeight(); + +// matrix.postTranslate(containerWidth / 2f + getAdditionX(currentEditMode), containerHeight / 2f + getAdditionY(currentEditMode)); + matrix.preTranslate(currentTranslationX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : 0)); + matrix.preScale(currentScale, currentScale); + matrix.preRotate(currentRotation); + + int bitmapWidth, originalWidth; + int bitmapHeight, originalHeight; + originalWidth = bitmapWidth = centerImage.getBitmapWidth(); + originalHeight = bitmapHeight = centerImage.getBitmapHeight(); + + float scale = Math.min(containerWidth / (float) originalWidth, containerHeight / (float) originalHeight); + + float scaleToFitX = 1.0f; + int rotatedWidth = originalWidth; + int rotatedHeight = originalHeight; + int orientation = cropTransform.getOrientation(); + if (orientation == 90 || orientation == 270) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + + temp = rotatedWidth; + rotatedWidth = rotatedHeight; + rotatedHeight = temp; + } + float cropAnimationValue = 1.0f; + float cropPw = cropTransform.getCropPw(); + float cropPh = cropTransform.getCropPh(); + bitmapWidth *= cropPw + (1.0f - cropPw) * (1.0f - cropAnimationValue); + bitmapHeight *= cropPh + (1.0f - cropPh) * (1.0f - cropAnimationValue); + scaleToFitX = containerWidth / (float) bitmapWidth; + if (scaleToFitX * bitmapHeight > containerHeight) { + scaleToFitX = containerHeight / (float) bitmapHeight; + } +// if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == EDIT_MODE_NONE) && editState.cropState != null) { +// float startW = bitmapWidth * scaleToFitX; +// float startH = bitmapHeight * scaleToFitX; +// float originalScaleToFitX = containerWidth / (float) originalWidth; +// if (originalScaleToFitX * originalHeight > containerHeight) { +// originalScaleToFitX = containerHeight / (float) originalHeight; +// } +// float finalW = originalWidth * originalScaleToFitX / (currentScale); +// float finalH = originalHeight * originalScaleToFitX / (currentScale); +// +// float w = startW + (finalW - startW) * (1.0f - cropAnimationValue); +// float h = startH + (finalH - startH) * (1.0f - cropAnimationValue); +// +// canvas.clipRect(-w / 2, -h / 2, w / 2, h / 2); +// } + if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) { + float cropScale; + if (videoTextureView != null) { + videoTextureView.setScaleX(editState.cropState != null && editState.cropState.mirrored ? -1.0f : 1.0f); + if (firstFrameView != null) { + firstFrameView.setScaleX(videoTextureView.getScaleX()); + } + } + cropScale = editState.cropState != null ? editState.cropState.cropScale : 1.0f; + float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue); + cropScale *= scaleToFitX / scale / trueScale; + + matrix.preTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue); + matrix.preScale(cropScale, cropScale); + matrix.preTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue); + float rotation = (cropTransform.getRotation() + orientation); + if (rotation > 180) { + rotation -= 360; + } + matrix.preRotate(rotation); + } + + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + mirror = editState.cropState != null && editState.cropState.mirrored; + } + if (mirror) { + matrix.preScale(-1, 1); + } + if (currentMirror > 0) { + matrix.preScale(1 - currentMirror * 2, 1f); + matrix.preSkew(0, 4 * currentMirror * (1f - currentMirror) * .25f); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java index 31e3c76c51..6bf221062e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java @@ -1,5 +1,10 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -7,8 +12,11 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; @@ -19,16 +27,24 @@ import android.widget.FrameLayout; import android.widget.TextView; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; @@ -41,12 +57,18 @@ import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.ChatActivityEnterViewAnimatedIconView; import org.telegram.ui.Components.ChatAttachAlertPollLayout; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EmojiView; import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.SuggestEmojiView; +import org.telegram.ui.Stories.recorder.KeyboardNotifier; import java.util.ArrayList; import java.util.Arrays; @@ -57,18 +79,20 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -public class PollCreateActivity extends BaseFragment { +public class PollCreateActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate { private ActionBarMenuItem doneItem; private ListAdapter listAdapter; private RecyclerListView listView; + private RecyclerView.LayoutManager layoutManager; + private SizeNotifierFrameLayout sizeNotifierFrameLayout; private ChatActivity parentFragment; private HintView hintView; - private String[] answers = new String[10]; + private CharSequence[] answers = new CharSequence[10]; private boolean[] answersChecks = new boolean[10]; private int answersCount = 1; - private String questionString; + private CharSequence questionString; private CharSequence solutionString; private boolean anonymousPoll = true; private boolean multipleChoise; @@ -76,6 +100,21 @@ public class PollCreateActivity extends BaseFragment { private boolean hintShowed; private int quizOnly; + public boolean emojiViewVisible, emojiViewWasVisible; + + private SuggestEmojiView suggestEmojiPanel; + private EmojiView emojiView; + private KeyboardNotifier keyboardNotifier; + private boolean waitingForKeyboardOpen; + private boolean destroyed; + private int emojiPadding; + private int keyboardHeight, keyboardHeightLand; + private boolean keyboardVisible, isAnimatePopupClosing; + private int lastSizeChangeValue1; + private boolean lastSizeChangeValue2; + private PollEditTextCell currentCell; + private boolean isPremium; + private PollCreateActivityDelegate delegate; private int requestFieldFocusAtPosition = -1; @@ -152,9 +191,25 @@ public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHol } } + private Runnable openKeyboardRunnable = new Runnable() { + @Override + public void run() { + if (currentCell != null) { + EditTextBoldCursor editText = currentCell.getEditField(); + if (!destroyed && editText != null && waitingForKeyboardOpen && !keyboardVisible && !AndroidUtilities.usingHardwareInput && !AndroidUtilities.isInMultiwindow && AndroidUtilities.isTablet()) { + editText.requestFocus(); + AndroidUtilities.showKeyboard(editText); + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + } + }; + public PollCreateActivity(ChatActivity chatActivity, Boolean quiz) { super(); parentFragment = chatActivity; + isPremium = AccountInstance.getInstance(currentAccount).getUserConfig().isPremium(); if (quiz != null) { quizPoll = quiz; quizOnly = quizPoll ? 1 : 2; @@ -200,19 +255,44 @@ public void onItemClick(int id) { } return; } + CharSequence questionText = ChatAttachAlertPollLayout.getFixedString(questionString); + CharSequence[] questionCharSequence = new CharSequence[]{ questionText }; + ArrayList questionEntities = MediaDataController.getInstance(currentAccount).getEntities(questionCharSequence, true); + questionText = questionCharSequence[0]; + for (int a = 0, N = questionEntities.size(); a < N; a++) { + TLRPC.MessageEntity entity = questionEntities.get(a); + if (entity.offset + entity.length > questionText.length()) { + entity.length = questionText.length() - entity.offset; + } + } + TLRPC.TL_messageMediaPoll poll = new TLRPC.TL_messageMediaPoll(); poll.poll = new TLRPC.TL_poll(); poll.poll.multiple_choice = multipleChoise; poll.poll.quiz = quizPoll; poll.poll.public_voters = !anonymousPoll; - poll.poll.question = ChatAttachAlertPollLayout.getFixedString(questionString).toString(); + poll.poll.question = new TLRPC.TL_textWithEntities(); + poll.poll.question.text = questionText.toString(); + poll.poll.question.entities = questionEntities; SerializedData serializedData = new SerializedData(10); for (int a = 0; a < answers.length; a++) { if (TextUtils.isEmpty(ChatAttachAlertPollLayout.getFixedString(answers[a]))) { continue; } - TLRPC.TL_pollAnswer answer = new TLRPC.TL_pollAnswer(); - answer.text = ChatAttachAlertPollLayout.getFixedString(answers[a]).toString(); + CharSequence answerText = ChatAttachAlertPollLayout.getFixedString(answers[a]); + CharSequence[] answerCharSequence = new CharSequence[]{ answerText }; + ArrayList answerEntities = MediaDataController.getInstance(currentAccount).getEntities(answerCharSequence, true); + answerText = answerCharSequence[0]; + for (int b = 0, N = answerEntities.size(); b < N; b++) { + TLRPC.MessageEntity entity = answerEntities.get(b); + if (entity.offset + entity.length > answerText.length()) { + entity.length = answerText.length() - entity.offset; + } + } + TLRPC.PollAnswer answer = new TLRPC.TL_pollAnswer(); + answer.text = new TLRPC.TL_textWithEntities(); + answer.text.text = answerText.toString(); + answer.text.entities = answerEntities; answer.option = new byte[1]; answer.option[0] = (byte) (48 + poll.poll.answers.size()); poll.poll.answers.add(answer); @@ -253,7 +333,131 @@ public void onItemClick(int id) { listAdapter = new ListAdapter(context); - fragmentView = new FrameLayout(context); + sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + + private boolean ignoreLayout; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + heightSize -= getPaddingTop(); + + measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); + + int keyboardSize = measureKeyboardHeight(); + if (keyboardSize > AndroidUtilities.dp(20) && !emojiViewVisible) { + ignoreLayout = true; + hideEmojiView(); + ignoreLayout = false; + } + + int keyboardPad = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? getEmojiPadding() : 0; + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE || child == actionBar) { + continue; + } + if (emojiView != null && emojiView == child) { + if (AndroidUtilities.isInMultiwindow || AndroidUtilities.isTablet()) { + if (AndroidUtilities.isTablet()) { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(AndroidUtilities.isTablet() ? 200 : 320), heightSize - AndroidUtilities.statusBarHeight + getPaddingTop()), MeasureSpec.EXACTLY)); + } else { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - AndroidUtilities.statusBarHeight + getPaddingTop(), MeasureSpec.EXACTLY)); + } + } else { + child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); + } + } else if (listView == child) { + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(heightSize - keyboardPad, MeasureSpec.EXACTLY)); + } else { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int count = getChildCount(); + + int keyboardSize = measureKeyboardHeight(); + int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? getEmojiPadding() : 0; + setBottomClip(paddingBottom); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + int childLeft; + int childTop; + + int gravity = lp.gravity; + if (gravity == -1) { + gravity = Gravity.TOP | Gravity.LEFT; + } + + final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = r - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.TOP: + childTop = lp.topMargin + getPaddingTop(); + break; + case Gravity.CENTER_VERTICAL: + childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = ((b - paddingBottom) - t) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + + if (emojiView != null && emojiView == child) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + keyboardSize - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + sizeNotifierFrameLayout.setDelegate(this); + + fragmentView = sizeNotifierFrameLayout; fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); FrameLayout frameLayout = (FrameLayout) fragmentView; @@ -274,7 +478,8 @@ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean }; listView.setVerticalScrollBarEnabled(false); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); + listView.setLayoutManager(layoutManager); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new TouchHelperCallback()); itemTouchHelper.attachToRecyclerView(listView); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); @@ -286,6 +491,9 @@ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean TextCheckCell cell = (TextCheckCell) view; boolean checked; boolean wasChecksBefore = quizPoll; + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } if (position == anonymousRow) { checked = anonymousPoll = !anonymousPoll; } else if (position == multipleRow) { @@ -366,6 +574,27 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (dy != 0 && hintView != null) { hintView.hide(); } + if (suggestEmojiPanel != null && suggestEmojiPanel.isShown()) { + SuggestEmojiView.AnchorViewDelegate emojiDelegate = suggestEmojiPanel.getDelegate(); + if (emojiDelegate instanceof PollEditTextCell) { + PollEditTextCell cell = (PollEditTextCell) emojiDelegate; + RecyclerView.ViewHolder holder = listView.findContainingViewHolder(cell); + if (holder != null) { + if (suggestEmojiPanel.getDirection() == SuggestEmojiView.DIRECTION_TO_BOTTOM) { + suggestEmojiPanel.setTranslationY(holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight()); + } else { + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + if (!layoutManager.isViewPartiallyVisible(holder.itemView, true, true)) { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } else { + suggestEmojiPanel.forceClose(); + } + } } }); @@ -375,11 +604,32 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { hintView.setVisibility(View.INVISIBLE); frameLayout.addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + if (isPremium) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + suggestEmojiPanel = new SuggestEmojiView(context, currentAccount, null, resourceProvider); + suggestEmojiPanel.forbidCopy(); + suggestEmojiPanel.forbidSetAsStatus(); + suggestEmojiPanel.setHorizontalPadding(AndroidUtilities.dp(24)); + frameLayout.addView(suggestEmojiPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 160, Gravity.LEFT | Gravity.TOP)); + } + keyboardNotifier = new KeyboardNotifier(sizeNotifierFrameLayout, null); + checkDoneButton(); return fragmentView; } + @Override + public void onPause() { + super.onPause(); + if (isPremium) { + hideEmojiPopup(false); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + } + } + @Override public void onResume() { super.onResume(); @@ -389,6 +639,32 @@ public void onResume() { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + destroyed = true; + if (isPremium) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + if (emojiView != null) { + sizeNotifierFrameLayout.removeView(emojiView); + } + } + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + if (emojiView != null) { + emojiView.invalidateViews(); + } + if (currentCell != null) { + int color = currentCell.getEditField().getCurrentTextColor(); + currentCell.getEditField().setTextColor(0xffffffff); + currentCell.getEditField().setTextColor(color); + } + } + } + private void showQuizHint() { int count = listView.getChildCount(); for (int a = answerStartRow; a < answerStartRow + answersCount; a++) { @@ -483,6 +759,10 @@ private void updateRows() { @Override public boolean onBackPressed() { + if (emojiViewVisible) { + hideEmojiPopup(true); + return true; + } return checkDiscard(); } @@ -543,6 +823,11 @@ private void setTextLeft(View cell, int index) { } private void addNewField() { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + resetSuggestEmojiPanel(); answersChecks[answersCount] = false; answersCount++; if (answersCount == answers.length) { @@ -554,6 +839,341 @@ private void addNewField() { listAdapter.notifyItemChanged(answerSectionRow); } + private void updateSuggestEmojiPanelDelegate(RecyclerView.ViewHolder holder) { + if (suggestEmojiPanel != null ) { + suggestEmojiPanel.forceClose(); + if (suggestEmojiPanel != null && holder != null && holder.itemView instanceof PollEditTextCell && suggestEmojiPanel.getDelegate() != holder.itemView) { + suggestEmojiPanel.setDelegate((PollEditTextCell) holder.itemView); + } + } + } + + private void resetSuggestEmojiPanel() { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.setDelegate(null); + suggestEmojiPanel.forceClose(); + } + } + + @Override + public void onSizeChanged(int height, boolean isWidthGreater) { + if (!isPremium) { + return; + } + if (height > dp(50) && keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + if (isWidthGreater) { + keyboardHeightLand = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height_land3", keyboardHeightLand).commit(); + } else { + keyboardHeight = height; + MessagesController.getGlobalEmojiSettings().edit().putInt("kbd_height", keyboardHeight).commit(); + } + } + + if (emojiViewVisible) { + int newHeight = (isWidthGreater ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emojiView.getLayoutParams(); + if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { + layoutParams.width = AndroidUtilities.displaySize.x; + layoutParams.height = newHeight; + emojiView.setLayoutParams(layoutParams); + emojiPadding = layoutParams.height; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + } + + if (lastSizeChangeValue1 == height && lastSizeChangeValue2 == isWidthGreater) { + return; + } + lastSizeChangeValue1 = height; + lastSizeChangeValue2 = isWidthGreater; + + boolean oldValue = keyboardVisible; + if (currentCell != null) { + final EditTextBoldCursor editText = currentCell.getEditField(); + keyboardVisible = editText.isFocused() && keyboardNotifier.keyboardVisible() && height > 0; + } else { + keyboardVisible = false; + } + + if (keyboardVisible && emojiViewVisible) { + showEmojiPopup(0); + } + + if (emojiPadding != 0 && !keyboardVisible && keyboardVisible != oldValue && !emojiViewVisible) { + emojiPadding = 0; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + + if (keyboardVisible && waitingForKeyboardOpen) { + waitingForKeyboardOpen = false; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + } + } + + public boolean isWaitingForKeyboardOpen() { + return waitingForKeyboardOpen; + } + + private void onEmojiClicked(PollEditTextCell cell) { + this.currentCell = cell; + if (emojiViewVisible) { + openKeyboardInternal(); + } else { + showEmojiPopup(1); + } + } + + private void openKeyboardInternal() { + keyboardNotifier.awaitKeyboard(); + final EditTextBoldCursor editText = currentCell.getEditField(); + AndroidUtilities.showKeyboard(editText); + showEmojiPopup(AndroidUtilities.usingHardwareInput ? 0 : 2); + + if (!AndroidUtilities.usingHardwareInput && !keyboardVisible && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet()) { + waitingForKeyboardOpen = true; + AndroidUtilities.cancelRunOnUIThread(openKeyboardRunnable); + AndroidUtilities.runOnUIThread(openKeyboardRunnable, 100); + } + } + + private void showEmojiPopup(int show) { + if (!isPremium) { + return; + } + + if (show == 1) { + boolean emojiWasVisible = emojiView != null && emojiView.getVisibility() == View.VISIBLE; + createEmojiView(); + + emojiView.setVisibility(View.VISIBLE); + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = true; + View currentView = emojiView; + + if (keyboardHeight <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeight = dp(150); + } else { + keyboardHeight = MessagesController.getGlobalEmojiSettings().getInt("kbd_height", dp(200)); + } + } + if (keyboardHeightLand <= 0) { + if (AndroidUtilities.isTablet()) { + keyboardHeightLand = dp(150); + } else { + keyboardHeightLand = MessagesController.getGlobalEmojiSettings().getInt("kbd_height_land3", dp(200)); + } + } + int currentHeight = (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight); + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) currentView.getLayoutParams(); + layoutParams.height = currentHeight; + currentView.setLayoutParams(layoutParams); + if (!AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() && currentCell != null) { + AndroidUtilities.hideKeyboard(currentCell.getEditField()); + } + + emojiPadding = currentHeight; + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, true); + } + if (!emojiWasVisible && !keyboardVisible) { + ValueAnimator animator = ValueAnimator.ofFloat(emojiPadding, 0); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + emojiView.setTranslationY(0); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } + } else { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, true); + } + if (emojiView != null) { + emojiViewWasVisible = emojiViewVisible; + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(View.GONE); + } + } + if (show == 0) { + emojiPadding = 0; + } + keyboardNotifier.fire(); + sizeNotifierFrameLayout.requestLayout(); + } + } + + private void hideEmojiPopup(boolean byBackButton) { + if (!isPremium) { + return; + } + if (emojiViewVisible) { + showEmojiPopup(0); + } + if (byBackButton) { + if (emojiView != null && emojiView.getVisibility() == View.VISIBLE) { + int height = emojiView.getMeasuredHeight(); + ValueAnimator animator = ValueAnimator.ofFloat(0, height); + animator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + emojiView.setTranslationY(v); + }); + isAnimatePopupClosing = true; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimatePopupClosing = false; + emojiView.setTranslationY(0); + hideEmojiView(); + } + }); + animator.setDuration(AdjustPanLayoutHelper.keyboardDuration); + animator.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); + animator.start(); + } else { + hideEmojiView(); + } + } + } + + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != View.GONE) { + if (currentCell != null) { + ChatActivityEnterViewAnimatedIconView emojiButton = currentCell.getEmojiButton(); + if (emojiButton != null) { + emojiButton.setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + } + } + emojiView.setVisibility(View.GONE); + } + int wasEmojiPadding = emojiPadding; + emojiPadding = 0; + if (wasEmojiPadding != emojiPadding) { + keyboardNotifier.fire(); + } + } + + public boolean isAnimatePopupClosing() { + return isAnimatePopupClosing; + } + + public boolean isPopupShowing() { + return emojiViewVisible; + } + + public boolean isPopupVisible() { + return emojiView != null && emojiView.getVisibility() == View.VISIBLE; + } + + public int getEmojiPadding() { + return emojiPadding; + } + + private void createEmojiView() { + if (emojiView != null && emojiView.currentAccount != UserConfig.selectedAccount) { + sizeNotifierFrameLayout.removeView(emojiView); + emojiView = null; + } + if (emojiView != null) { + return; + } + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourceProvider, false); + emojiView.fixBottomTabContainerTranslation = false; + emojiView.allowEmojisForNonPremium(false); + emojiView.setVisibility(View.GONE); + if (AndroidUtilities.isTablet()) { + emojiView.setForseMultiwindowLayout(true); + } + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { + @Override + public boolean onBackspace() { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return false; + } + editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); + return true; + } + + @Override + public void onEmojiSelected(String symbol) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, editText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + editText.setText(editText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onCustomEmojiSelected(long documentId, TLRPC.Document document, String emoticon, boolean isRecent) { + final EditTextBoldCursor editText = currentCell.getEditField(); + if (editText == null) { + return; + } + int i = editText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + SpannableString spannable = new SpannableString(emoticon); + AnimatedEmojiSpan span; + if (document != null) { + span = new AnimatedEmojiSpan(document, editText.getPaint().getFontMetricsInt()); + } else { + span = new AnimatedEmojiSpan(documentId, editText.getPaint().getFontMetricsInt()); + } + span.cacheType = emojiView.emojiCacheType; + spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editText.setText(editText.getText().insert(i, spannable)); + int j = i + spannable.length(); + editText.setSelection(j, j); + } catch (Exception e) { + FileLog.e(e); + } + } + + @Override + public void onClearEmojiRecent() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourceProvider); + builder.setTitle(LocaleController.getString("ClearRecentEmojiTitle", R.string.ClearRecentEmojiTitle)); + builder.setMessage(LocaleController.getString("ClearRecentEmojiText", R.string.ClearRecentEmojiText)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton), (dialogInterface, i) -> emojiView.clearRecentEmoji()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.show(); + } + }); + sizeNotifierFrameLayout.addView(emojiView); + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -666,10 +1286,17 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { @Override public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() == 4) { + if (holder.getItemViewType() == 4 || holder.getItemViewType() == 5) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; EditTextBoldCursor editText = editTextCell.getTextView(); if (editText.isFocused()) { + if (isPremium) { + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + } + hideEmojiPopup(true); + } + currentCell = null; editText.clearFocus(); AndroidUtilities.hideKeyboard(editText); } @@ -701,7 +1328,38 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: { - PollEditTextCell cell = new PollEditTextCell(mContext, null); + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { + @Override + protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { + if (editText.isFocused() && editText.hasSelection()) { + Menu menu = actionMode.getMenu(); + if (menu.findItem(android.R.id.copy) == null) { + return; + } + ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat(), false); + } + } + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } + }; cell.createErrorTextView(); cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.addTextWatcher(new TextWatcher() { @@ -720,8 +1378,22 @@ public void afterTextChanged(Editable s) { if (cell.getTag() != null) { return; } - questionString = s.toString(); RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } + questionString = s; if (holder != null) { setTextLeft(holder.itemView, questionRow); } @@ -736,7 +1408,7 @@ public void afterTextChanged(Editable s) { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 7: { - PollEditTextCell cell = new PollEditTextCell(mContext, true, null) { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, null) { @Override protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionMode) { if (editText.isFocused() && editText.hasSelection()) { @@ -747,6 +1419,26 @@ protected void onActionModeStart(EditTextBoldCursor editText, ActionMode actionM ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat(), false); } } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } }; cell.createErrorTextView(); cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -766,8 +1458,22 @@ public void afterTextChanged(Editable s) { if (cell.getTag() != null) { return; } + RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(questionRow); + if (holder != null) { + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + suggestEmojiPanel.fireUpdate(); + } + } solutionString = s; - RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(solutionRow); if (holder != null) { setTextLeft(holder.itemView, solutionRow); } @@ -778,7 +1484,7 @@ public void afterTextChanged(Editable s) { break; } default: { - PollEditTextCell cell = new PollEditTextCell(mContext, v -> { + PollEditTextCell cell = new PollEditTextCell(mContext, false, isPremium ? PollEditTextCell.TYPE_EMOJI : PollEditTextCell.TYPE_DEFAULT, v -> { if (v.getTag() != null) { return; } @@ -803,16 +1509,54 @@ public void afterTextChanged(Editable s) { if (holder != null && holder.itemView instanceof PollEditTextCell) { PollEditTextCell editTextCell = (PollEditTextCell) holder.itemView; editTextCell.getTextView().requestFocus(); + if (isPremium) { + if (emojiViewVisible) { + currentCell = editTextCell; + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.KEYBOARD, false); + } else { + editTextCell.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + hideEmojiPopup(false); + } + } } else if (editText.isFocused()) { AndroidUtilities.hideKeyboard(editText); + if (isPremium) { + hideEmojiPopup(false); + } + } + if (isPremium) { + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); } editText.clearFocus(); checkDoneButton(); updateRows(); + if (suggestEmojiPanel != null) { + suggestEmojiPanel.forceClose(); + suggestEmojiPanel.setDelegate(null); + } listAdapter.notifyItemChanged(answerSectionRow); } } }) { + + @Override + protected void onFieldTouchUp(EditTextBoldCursor editText) { + super.onFieldTouchUp(editText); + if (isPremium) { + PollEditTextCell p = (PollEditTextCell) editText.getParent(); + currentCell = p; + if (emojiView != null) { + emojiView.scrollEmojiToTop(); + } + hideEmojiPopup(false); + p.getEmojiButton().setState(ChatActivityEnterViewAnimatedIconView.State.SMILE, false); + updateSuggestEmojiPanelDelegate(listView.findContainingViewHolder(this)); + } + } + @Override protected boolean drawDivider() { RecyclerView.ViewHolder holder = listView.findContainingViewHolder(this); @@ -867,6 +1611,11 @@ protected boolean isChecked(PollEditTextCell editText) { } return false; } + + @Override + protected void onEmojiButtonClicked(PollEditTextCell cell1) { + onEmojiClicked(cell1); + } }; cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.addTextWatcher(new TextWatcher() { @@ -889,7 +1638,25 @@ public void afterTextChanged(Editable s) { if (index < 0 || index >= answers.length) { return; } - answers[index] = s.toString(); + if (suggestEmojiPanel != null) { + ImageSpan[] spans = s.getSpans(0, s.length(), ImageSpan.class); + for (ImageSpan span : spans) { + s.removeSpan(span); + } + Emoji.replaceEmoji(s, cell.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + float y = holder.itemView.getY() - AndroidUtilities.dp(166) + holder.itemView.getMeasuredHeight(); + if (y > 0) { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_BOTTOM); + suggestEmojiPanel.setTranslationY(y); + } else { + suggestEmojiPanel.setDirection(SuggestEmojiView.DIRECTION_TO_TOP); + suggestEmojiPanel.setTranslationY(holder.itemView.getY()); + } + suggestEmojiPanel.setDelegate(cell); + suggestEmojiPanel.fireUpdate(); + } + + answers[index] = s; setTextLeft(cell, index); checkDoneButton(); } @@ -967,7 +1734,7 @@ public void swapElements(int fromIndex, int toIndex) { if (idx1 < 0 || idx2 < 0 || idx1 >= answersCount || idx2 >= answersCount) { return; } - String from = answers[idx1]; + CharSequence from = answers[idx1]; answers[idx1] = answers[idx2]; answers[idx2] = from; boolean temp = answersChecks[idx1]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java index 976ec4eeab..633104aa74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -1,6 +1,7 @@ package org.telegram.ui; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.LocaleController.getString; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -79,9 +80,11 @@ import org.telegram.ui.Business.TimezonesController; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FillLastLinearLayoutManager; @@ -138,6 +141,9 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification int statusRow; int privacyRow; int lastPaddingRow; + int showAdsHeaderRow; + int showAdsRow; + int showAdsInfoRow; Drawable shadowDrawable; private FrameLayout buttonContainer; private View buttonDivider; @@ -209,6 +215,7 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification private PremiumButtonView premiumButtonView; float totalProgress; private final int type; + private boolean whiteBackground; private String source; private boolean selectAnnualByDefault; @@ -401,6 +408,7 @@ public PremiumPreviewFragment(String source) { public PremiumPreviewFragment(int type, String source) { super(); this.type = type; + whiteBackground = !Theme.isCurrentThemeDark() && type == FEATURES_BUSINESS; this.source = source; } @@ -497,7 +505,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) { float listX = backgroundView.getX() + backgroundView.tierListView.getX(), listY = backgroundView.getY() + backgroundView.tierListView.getY(); AndroidUtilities.rectTmp.set(listX, listY, listX + backgroundView.tierListView.getWidth(), listY + backgroundView.tierListView.getHeight()); - if ((AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || listInterceptedTouch) && !listView.scrollingByUser) { + if (progressToFull < 1.0f && (AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || listInterceptedTouch) && !listView.scrollingByUser) { ev.offsetLocation(-listX, -listY); if (ev.getAction() == MotionEvent.ACTION_DOWN) { listInterceptedTouch = true; @@ -550,6 +558,8 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { measureGradient(w, h); } + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + @Override protected void dispatchDraw(Canvas canvas) { if (!isDialogVisible) { @@ -622,9 +632,18 @@ protected void dispatchDraw(Canvas canvas) { invalidate(); } gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0); - canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), gradientTools.paint); + if (whiteBackground) { + backgroundPaint.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_windowBackgroundGray), getThemedColor(Theme.key_windowBackgroundWhite), progressToFull)); + canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), backgroundPaint); + } else { + canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + dp(20), gradientTools.paint); + } super.dispatchDraw(canvas); + + if (parentLayout != null && whiteBackground) { + parentLayout.drawHeaderShadow(canvas, (int) (0xFF * progressToFull), actionBar.getBottom()); + } } @Override @@ -692,20 +711,54 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { particlesView = new StarParticlesView(context); particlesView.setClipWithGradient(); if (type == FEATURES_BUSINESS) { -// particlesView.doNotFling = true; - particlesView.drawable.isCircle = true; - particlesView.drawable.centerOffsetY = dp(28); - particlesView.drawable.minLifeTime = 2000; - particlesView.drawable.randLifeTime = 3000; - particlesView.drawable.size1 = 16; - particlesView.drawable.useRotate = false; - particlesView.drawable.type = PREMIUM_FEATURE_BUSINESS; + if (whiteBackground) { + particlesView.drawable.useGradient = true; + particlesView.drawable.useBlur = false; + particlesView.drawable.checkBounds = true; + particlesView.drawable.isCircle = true; + particlesView.drawable.centerOffsetY = dp(-14); + particlesView.drawable.minLifeTime = 2000; + particlesView.drawable.randLifeTime = 3000; + particlesView.drawable.size1 = 16; + particlesView.drawable.useRotate = false; + particlesView.drawable.type = PremiumPreviewFragment.PREMIUM_FEATURE_BUSINESS; + particlesView.drawable.colorKey = Theme.key_premiumGradient2; + } else { + particlesView.drawable.isCircle = true; + particlesView.drawable.centerOffsetY = dp(28); + particlesView.drawable.minLifeTime = 2000; + particlesView.drawable.randLifeTime = 3000; + particlesView.drawable.size1 = 16; + particlesView.drawable.useRotate = false; + particlesView.drawable.type = PREMIUM_FEATURE_BUSINESS; + } } backgroundView.imageView.setStarParticlesView(particlesView); contentView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); listView.setOnItemClickListener((view, position) -> { + if (position == showAdsRow) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(getUserConfig().getClientUserId()); + if (userFull == null) return; + + TextCell cell = (TextCell) view; + cell.setChecked(!cell.isChecked()); + userFull.sponsored_enabled = cell.isChecked(); + + TLRPC.TL_account_toggleSponsoredMessages req = new TLRPC.TL_account_toggleSponsoredMessages(); + req.enabled = userFull.sponsored_enabled; + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (!(res instanceof TLRPC.TL_boolTrue)) { + BulletinFactory.of(PremiumPreviewFragment.this).createErrorBulletin(getString(R.string.UnknownError)).show(); + } + })); + + getMessagesStorage().updateUserInfo(userFull, false); + return; + } if (view instanceof PremiumFeatureCell) { PremiumFeatureCell cell = (PremiumFeatureCell) view; @@ -813,28 +866,28 @@ public static void buyPremium(BaseFragment fragment) { public static void fillPremiumFeaturesList(ArrayList premiumFeatures, int currentAccount, boolean all) { MessagesController messagesController = MessagesController.getInstance(currentAccount); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, LocaleController.getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription, + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription, messagesController.channelsLimitPremium, messagesController.dialogFiltersLimitPremium, messagesController.dialogFiltersPinnedLimitPremium, messagesController.publicLinksLimitPremium, 4))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.msg_filled_stories, LocaleController.getString(R.string.PremiumPreviewStories), LocaleController.formatString(R.string.PremiumPreviewStoriesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, LocaleController.getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), LocaleController.getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, LocaleController.getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), LocaleController.getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, LocaleController.getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), LocaleController.getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), LocaleController.getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString(R.string.PremiumPreviewReactions2), LocaleController.getString(R.string.PremiumPreviewReactions2Description))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString(R.string.PremiumPreviewStickers), LocaleController.getString(R.string.PremiumPreviewStickersDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, LocaleController.getString(R.string.PremiumPreviewEmoji), LocaleController.getString(R.string.PremiumPreviewEmojiDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString(R.string.PremiumPreviewProfileBadge), LocaleController.getString(R.string.PremiumPreviewProfileBadgeDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString(R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString(R.string.PremiumPreviewAnimatedProfilesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, LocaleController.getString(R.string.PremiumPreviewTags2), LocaleController.getString(R.string.PremiumPreviewTagsDescription2))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString(R.string.PremiumPreviewAppIcon), LocaleController.getString(R.string.PremiumPreviewAppIconDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, LocaleController.getString(R.string.PremiumPreviewEmojiStatus), LocaleController.getString(R.string.PremiumPreviewEmojiStatusDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, LocaleController.getString(R.string.PremiumPreviewTranslations), LocaleController.getString(R.string.PremiumPreviewTranslationsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, LocaleController.getString(R.string.PremiumPreviewWallpaper), LocaleController.getString(R.string.PremiumPreviewWallpaperDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, LocaleController.getString(R.string.PremiumPreviewProfileColor), LocaleController.getString(R.string.PremiumPreviewProfileColorDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, LocaleController.getString(R.string.PremiumPreviewLastSeen), LocaleController.getString(R.string.PremiumPreviewLastSeenDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, LocaleController.getString(R.string.PremiumPreviewMessagePrivacy), LocaleController.getString(R.string.PremiumPreviewMessagePrivacyDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS, R.drawable.filled_premium_business, applyNewSpan(LocaleController.getString(R.string.TelegramBusiness)), LocaleController.getString(R.string.PremiumPreviewBusinessDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.msg_filled_stories, getString(R.string.PremiumPreviewStories), LocaleController.formatString(R.string.PremiumPreviewStoriesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, getString(R.string.PremiumPreviewReactions2), getString(R.string.PremiumPreviewReactions2Description))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, getString(R.string.PremiumPreviewStickers), getString(R.string.PremiumPreviewStickersDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_EMOJI, R.drawable.msg_premium_emoji, getString(R.string.PremiumPreviewEmoji), getString(R.string.PremiumPreviewEmojiDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.menu_premium_tools, getString(R.string.PremiumPreviewAdvancedChatManagement), getString(R.string.PremiumPreviewAdvancedChatManagementDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, getString(R.string.PremiumPreviewProfileBadge), getString(R.string.PremiumPreviewProfileBadgeDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, getString(R.string.PremiumPreviewAnimatedProfiles), getString(R.string.PremiumPreviewAnimatedProfilesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_SAVED_TAGS, R.drawable.premium_tags, getString(R.string.PremiumPreviewTags2), getString(R.string.PremiumPreviewTagsDescription2))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, getString(R.string.PremiumPreviewAppIcon), getString(R.string.PremiumPreviewAppIconDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.premium_status, getString(R.string.PremiumPreviewEmojiStatus), getString(R.string.PremiumPreviewEmojiStatusDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_TRANSLATIONS, R.drawable.msg_premium_translate, getString(R.string.PremiumPreviewTranslations), getString(R.string.PremiumPreviewTranslationsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_WALLPAPER, R.drawable.premium_wallpaper, getString(R.string.PremiumPreviewWallpaper), getString(R.string.PremiumPreviewWallpaperDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_NAME_COLOR, R.drawable.premium_colors, getString(R.string.PremiumPreviewProfileColor), getString(R.string.PremiumPreviewProfileColorDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LAST_SEEN, R.drawable.menu_premium_seen, getString(R.string.PremiumPreviewLastSeen), getString(R.string.PremiumPreviewLastSeenDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_MESSAGE_PRIVACY, R.drawable.menu_premium_privacy, getString(R.string.PremiumPreviewMessagePrivacy), getString(R.string.PremiumPreviewMessagePrivacyDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS, R.drawable.filled_premium_business, applyNewSpan(getString(R.string.TelegramBusiness)), getString(R.string.PremiumPreviewBusinessDescription))); if (messagesController.premiumFeaturesTypesToPosition.size() > 0) { for (int i = 0; i < premiumFeatures.size(); i++) { @@ -856,18 +909,18 @@ public static void fillBusinessFeaturesList(ArrayList premiu MessagesController messagesController = MessagesController.getInstance(currentAccount); if (!additional) { - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_LOCATION, R.drawable.filled_location, LocaleController.getString(R.string.PremiumBusinessLocation), LocaleController.getString(R.string.PremiumBusinessLocationDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_OPENING_HOURS, R.drawable.filled_premium_hours, LocaleController.getString(R.string.PremiumBusinessOpeningHours), LocaleController.getString(R.string.PremiumBusinessOpeningHoursDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_QUICK_REPLIES, R.drawable.filled_open_message, LocaleController.getString(R.string.PremiumBusinessQuickReplies), LocaleController.getString(R.string.PremiumBusinessQuickRepliesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_GREETING_MESSAGES, R.drawable.premium_status, LocaleController.getString(R.string.PremiumBusinessGreetingMessages), LocaleController.getString(R.string.PremiumBusinessGreetingMessagesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_AWAY_MESSAGES, R.drawable.filled_premium_away, LocaleController.getString(R.string.PremiumBusinessAwayMessages), LocaleController.getString(R.string.PremiumBusinessAwayMessagesDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHATBOTS, R.drawable.filled_premium_bots, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessChatbots2)), LocaleController.getString(R.string.PremiumBusinessChatbotsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHAT_LINKS, R.drawable.filled_premium_chatlink, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessChatLinks)), LocaleController.getString(R.string.PremiumBusinessChatLinksDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_INTRO, R.drawable.filled_premium_intro, applyNewSpan(LocaleController.getString(R.string.PremiumBusinessIntro)), LocaleController.getString(R.string.PremiumBusinessIntroDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_LOCATION, R.drawable.filled_location, getString(R.string.PremiumBusinessLocation), getString(R.string.PremiumBusinessLocationDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_OPENING_HOURS, R.drawable.filled_premium_hours, getString(R.string.PremiumBusinessOpeningHours), getString(R.string.PremiumBusinessOpeningHoursDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_QUICK_REPLIES, R.drawable.filled_open_message, getString(R.string.PremiumBusinessQuickReplies), getString(R.string.PremiumBusinessQuickRepliesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_GREETING_MESSAGES, R.drawable.premium_status, getString(R.string.PremiumBusinessGreetingMessages), getString(R.string.PremiumBusinessGreetingMessagesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_AWAY_MESSAGES, R.drawable.filled_premium_away, getString(R.string.PremiumBusinessAwayMessages), getString(R.string.PremiumBusinessAwayMessagesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHATBOTS, R.drawable.filled_premium_bots, applyNewSpan(getString(R.string.PremiumBusinessChatbots2)), getString(R.string.PremiumBusinessChatbotsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_CHAT_LINKS, R.drawable.filled_premium_chatlink, applyNewSpan(getString(R.string.PremiumBusinessChatLinks)), getString(R.string.PremiumBusinessChatLinksDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_BUSINESS_INTRO, R.drawable.filled_premium_intro, applyNewSpan(getString(R.string.PremiumBusinessIntro)), getString(R.string.PremiumBusinessIntroDescription))); } else { - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.filled_premium_status2, LocaleController.getString(R.string.PremiumPreviewBusinessEmojiStatus), LocaleController.getString(R.string.PremiumPreviewBusinessEmojiStatusDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_FOLDER_TAGS, R.drawable.premium_tags, LocaleController.getString(R.string.PremiumPreviewFolderTags), LocaleController.getString(R.string.PremiumPreviewFolderTagsDescription))); - premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.filled_premium_camera, LocaleController.getString(R.string.PremiumPreviewBusinessStories), LocaleController.getString(R.string.PremiumPreviewBusinessStoriesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_EMOJI_STATUS, R.drawable.filled_premium_status2, getString(R.string.PremiumPreviewBusinessEmojiStatus), getString(R.string.PremiumPreviewBusinessEmojiStatusDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_FOLDER_TAGS, R.drawable.premium_tags, getString(R.string.PremiumPreviewFolderTags), getString(R.string.PremiumPreviewFolderTagsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STORIES, R.drawable.filled_premium_camera, getString(R.string.PremiumPreviewBusinessStories), getString(R.string.PremiumPreviewBusinessStoriesDescription))); } if (messagesController.businessFeaturesTypesToPosition.size() > 0) { @@ -899,12 +952,19 @@ private void updateBackgroundImage() { if (contentView.getMeasuredWidth() == 0 || contentView.getMeasuredHeight() == 0 || backgroundView == null || backgroundView.imageView == null) { return; } - gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0); - gradientCanvas.save(); - gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight()); - gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint); - gradientCanvas.restore(); - backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap); + if (whiteBackground) { + Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.drawColor(ColorUtils.blendARGB(getThemedColor(Theme.key_premiumGradient2), getThemedColor(Theme.key_dialogBackground), 0.5f)); + backgroundView.imageView.setBackgroundBitmap(bitmap); + } else { + gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0); + gradientCanvas.save(); + gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight()); + gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint); + gradientCanvas.restore(); + backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap); + } } private void checkButtonDivider() { @@ -970,6 +1030,9 @@ private void updateRows() { moreHeaderRow = -1; moreFeaturesStartRow = -1; moreFeaturesEndRow = -1; + showAdsHeaderRow = -1; + showAdsRow = -1; + showAdsInfoRow = -1; paddingRow = rowCount++; featuresStartRow = rowCount; @@ -985,6 +1048,12 @@ private void updateRows() { statusRow = rowCount++; lastPaddingRow = rowCount++; + if (type == FEATURES_BUSINESS && getUserConfig().isPremium()) { + showAdsHeaderRow = rowCount++; + showAdsRow = rowCount++; + showAdsInfoRow = rowCount++; + } + AndroidUtilities.updateViewVisibilityAnimated(buttonContainer, !getUserConfig().isPremium() || currentSubscriptionTier != null && currentSubscriptionTier.getMonths() < subscriptionTiers.get(selectedTierIndex).getMonths() && !forcePremium, 1f, false); int buttonHeight = buttonContainer.getVisibility() == View.VISIBLE ? dp(64) : 0; @@ -1051,7 +1120,8 @@ private class Adapter extends RecyclerListView.SelectionAdapter { TYPE_HELP_US = 4, TYPE_SHADOW = 5, TYPE_BOTTOM_PADDING = 6, - TYPE_HEADER = 7; + TYPE_HEADER = 7, + TYPE_CHECK = 8; @NonNull @Override @@ -1113,6 +1183,9 @@ protected void dispatchDraw(Canvas canvas) { case TYPE_HEADER: view = new HeaderCell(context); break; + case TYPE_CHECK: + view = new TextCell(context, 23, false, true, resourceProvider); + break; } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); @@ -1135,7 +1208,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi privacyCell.setText(""); privacyCell.setFixedSize(12); - } else if (position == statusRow || position == privacyRow) { + } else if (position == statusRow || position == privacyRow || position == showAdsInfoRow) { TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; Drawable shadowDrawable = Theme.getThemedDrawable(privacyCell.getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow)); @@ -1145,8 +1218,12 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi privacyCell.setBackground(combinedDrawable); privacyCell.setFixedSize(0); - if (position == statusRow && type == FEATURES_BUSINESS) { - privacyCell.setText(LocaleController.getString(R.string.PremiumPreviewMoreBusinessFeaturesInfo)); + if (position == showAdsInfoRow) { + privacyCell.setText(AndroidUtilities.replaceArrows(AndroidUtilities.replaceSingleTag(getString(R.string.ShowAdsInfo), () -> { + showDialog(new RevenueSharingAdsInfoBottomSheet(PremiumPreviewFragment.this, getContext(), getResourceProvider())); + }), true)); + } else if (position == statusRow && type == FEATURES_BUSINESS) { + privacyCell.setText(getString(R.string.PremiumPreviewMoreBusinessFeaturesInfo)); } else if (position == statusRow) { TLRPC.TL_help_premiumPromo premiumPromo = getMediaDataController().getPremiumPromo(); if (premiumPromo == null) { @@ -1202,7 +1279,12 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi privacyCell.setText(spannableString); } } else if (position == moreHeaderRow) { - ((HeaderCell) holder.itemView).setText(LocaleController.getString(R.string.PremiumPreviewMoreBusinessFeatures)); + ((HeaderCell) holder.itemView).setText(getString(R.string.PremiumPreviewMoreBusinessFeatures)); + } else if (position == showAdsHeaderRow) { + ((HeaderCell) holder.itemView).setText(getString(R.string.ShowAdsTitle)); + } else if (position == showAdsRow) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(getUserConfig().getClientUserId()); + ((TextCell) holder.itemView).setTextAndCheck(getString(R.string.ShowAds), userFull == null || userFull.sponsored_enabled, false); } } @@ -1219,19 +1301,21 @@ public int getItemViewType(int position) { return TYPE_FEATURE; } else if (position == helpUsRow) { return TYPE_HELP_US; - } else if (position == sectionRow || position == statusRow || position == privacyRow) { + } else if (position == sectionRow || position == statusRow || position == privacyRow || position == showAdsInfoRow) { return TYPE_SHADOW; } else if (position == lastPaddingRow) { return TYPE_BOTTOM_PADDING; - } else if (position == moreHeaderRow) { + } else if (position == moreHeaderRow || position == showAdsHeaderRow) { return TYPE_HEADER; + } else if (position == showAdsRow) { + return TYPE_CHECK; } return TYPE_PADDING; } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - return holder.getItemViewType() == TYPE_FEATURE; + return holder.getItemViewType() == TYPE_FEATURE || holder.getItemViewType() == TYPE_CHECK; } } @@ -1267,7 +1351,7 @@ public BackgroundView(Context context) { imageFrameLayout = new FrameLayout(context); final int sz = type == FEATURES_BUSINESS ? 175 : 190; addView(imageFrameLayout, LayoutHelper.createLinear(sz, sz, Gravity.CENTER_HORIZONTAL)); - imageView = new GLIconTextureView(context, type == FEATURES_BUSINESS ? GLIconRenderer.BUSINESS_STYLE : GLIconRenderer.FRAGMENT_STYLE, type == FEATURES_BUSINESS ? Icon3D.TYPE_COIN : Icon3D.TYPE_STAR) { + imageView = new GLIconTextureView(context, whiteBackground ? GLIconRenderer.DIALOG_STYLE : type == FEATURES_BUSINESS ? GLIconRenderer.BUSINESS_STYLE : GLIconRenderer.FRAGMENT_STYLE, type == FEATURES_BUSINESS ? Icon3D.TYPE_COIN : Icon3D.TYPE_STAR) { @Override public void onLongPress() { super.onLongPress(); @@ -1295,7 +1379,7 @@ public void onLongPress() { titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); titleView.setGravity(Gravity.CENTER_HORIZONTAL); addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 16, type == FEATURES_BUSINESS ? 8 : 20, 16, 0)); @@ -1310,18 +1394,21 @@ public void onLongPress() { { paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + if (whiteBackground) { + paint.setShadowLayer(dp(2), 0, dp(.66f), 0x30000000); + } } private Path path = new Path(); @Override - public void draw(Canvas c) { + public void dispatchDraw(Canvas c) { path.rewind(); AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); path.addRoundRect(AndroidUtilities.rectTmp, dp(12), dp(12), Path.Direction.CW); c.drawPath(path, paint); c.save(); c.clipPath(path); - super.draw(c); + super.dispatchDraw(c); c.restore(); } @@ -1330,6 +1417,22 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); measureGradient(w, h); } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (progressToFull >= 1.0f) { + return false; + } + return super.onInterceptTouchEvent(e); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent e) { + if (progressToFull >= 1.0f) { + return false; + } + return super.dispatchTouchEvent(e); + } }; tierListView.setOverScrollMode(OVER_SCROLL_NEVER); tierListView.setLayoutManager(new LinearLayoutManager(context)); @@ -1445,7 +1548,9 @@ public int getItemCount() { path.addRoundRect(AndroidUtilities.rectTmp, radii, Path.Direction.CW); canvas.clipPath(path); }); - addView(tierListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 12, 16, 12, 0)); + setClipChildren(false); + setClipToPadding(false); + addView(tierListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 12, 16, 12, 4)); updatePremiumTiers(); updateText(); @@ -1529,11 +1634,11 @@ public void updatePremiumTiers() { private boolean tierListViewVisible; public void updateText() { if (type == FEATURES_PREMIUM) { - titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium)); - subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle))); + titleView.setText(getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium)); + subtitleView.setText(AndroidUtilities.replaceTags(getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle))); } else if (type == FEATURES_BUSINESS) { - titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramBusiness)); - subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramBusinessSubscribedSubtitleTemp : R.string.TelegramBusinessSubtitleTemp))); + titleView.setText(getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramBusiness)); + subtitleView.setText(AndroidUtilities.replaceTags(getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramBusinessSubscribedSubtitleTemp : R.string.TelegramBusinessSubtitleTemp))); } subtitleView.getLayoutParams().width = Math.min(AndroidUtilities.displaySize.x - dp(42), HintView2.cutInFancyHalf(subtitleView.getText(), subtitleView.getPaint())); boolean tierNotVisible = forcePremium || BuildVars.IS_BILLING_UNAVAILABLE || IS_PREMIUM_TIERS_UNAVAILABLE || subscriptionTiers.size() <= 1; @@ -1595,7 +1700,7 @@ private void updateButtonText(boolean animated) { return; } if (!BuildVars.useInvoiceBilling() && (!BillingController.getInstance().isReady() || subscriptionTiers.isEmpty() || selectedTierIndex >= subscriptionTiers.size() || subscriptionTiers.get(selectedTierIndex).googlePlayProductDetails == null)) { - premiumButtonView.setButton(LocaleController.getString(R.string.Loading), v -> {}, animated); + premiumButtonView.setButton(getString(R.string.Loading), v -> {}, animated); premiumButtonView.setFlickerDisabled(true); return; } @@ -1617,7 +1722,7 @@ private void updateButtonText(boolean animated) { @Override public boolean isLightStatusBar() { - return false; + return whiteBackground; } @Override @@ -1651,7 +1756,7 @@ public ArrayList getThemeDescriptions() { return SimpleThemeDescription.createThemeDescriptions(this::updateColors, Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4, Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4, - Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 + Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStarGradient1, Theme.key_premiumStarGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 ); } @@ -1659,14 +1764,19 @@ private void updateColors() { if (backgroundView == null || actionBar == null) { return; } - actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false); - actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), true); + actionBar.setItemsColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay), false); + actionBar.setItemsColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay), true); actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false); particlesView.drawable.updateColors(); if (backgroundView != null) { - backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); - backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.titleView.setTextColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.subtitleView.setTextColor(Theme.getColor(whiteBackground ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_premiumGradientBackgroundOverlay)); if (backgroundView.imageView != null && backgroundView.imageView.mRenderer != null) { + if (whiteBackground) { +// backgroundView.imageView.mRenderer.forceNight = true; + backgroundView.imageView.mRenderer.colorKey1 = Theme.key_premiumCoinGradient1; + backgroundView.imageView.mRenderer.colorKey2 = Theme.key_premiumCoinGradient2; + } backgroundView.imageView.mRenderer.updateColors(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 5fcb567045..6e63465be9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -11,7 +11,9 @@ import static androidx.core.view.ViewCompat.TYPE_TOUCH; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.ContactsController.PRIVACY_RULES_TYPE_ADDED_BY_PHONE; +import static org.telegram.messenger.LocaleController.formatPluralString; import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; import android.Manifest; import android.animation.Animator; @@ -68,7 +70,9 @@ import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; +import android.util.Log; import android.util.Property; +import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Display; @@ -116,13 +120,13 @@ import com.jakewharton.processphoenix.ProcessPhoenix; import org.apache.commons.lang3.StringUtils; -import com.google.android.exoplayer2.util.Log; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.AuthTokensHelper; import org.telegram.messenger.BillingController; import org.telegram.messenger.BirthdayController; import org.telegram.messenger.BuildVars; @@ -161,6 +165,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.tl.TL_fragment; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -178,7 +183,6 @@ import org.telegram.ui.Business.OpeningHoursActivity; import org.telegram.ui.Business.ProfileHoursCell; import org.telegram.ui.Business.ProfileLocationCell; -import org.telegram.ui.Business.TimezonesController; import org.telegram.ui.Cells.AboutLinkCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.DividerCell; @@ -190,7 +194,6 @@ import org.telegram.ui.Cells.SettingsSearchCell; import org.telegram.ui.Cells.SettingsSuggestionCell; import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextDetailCell; @@ -202,6 +205,7 @@ import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.AutoDeletePopupWrapper; @@ -269,6 +273,7 @@ import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; 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.BotBiometry; @@ -278,13 +283,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Period; -import java.time.format.TextStyle; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -424,6 +426,9 @@ public void setAlpha(int a) { private ActionBarMenuItem eventLogItem; private ActionBarMenuItem otherItem; private ActionBarMenuItem searchItem; + private ActionBarMenuSubItem editColorItem; + private ActionBarMenuSubItem linkItem; + private ActionBarMenuSubItem setUsernameItem; private ImageView ttlIconView; // private ActionBarMenuItem qrItem; private ActionBarMenuSubItem autoDeleteItem; @@ -445,6 +450,7 @@ public void setAlpha(int a) { private boolean hasVoiceChatItem; private boolean isTopic; private boolean openSimilar; + private boolean myProfile; private boolean scrolling; @@ -539,7 +545,7 @@ public void setAlpha(int a) { private final static int statistics = 19; private final static int start_secret_chat = 20; private final static int gallery_menu_save = 21; - private final static int event_log = 42; + private final static int event_log = 102; private final static int view_discussion = 22; private final static int delete_topic = 23; @@ -556,6 +562,9 @@ public void setAlpha(int a) { // private final static int gift_premium = 38; private final static int channel_stories = 39; private final static int edit_color = 40; + private final static int edit_profile = 41; + private final static int copy_link_profile = 42; + private final static int set_username = 43; private Rect rect = new Rect(); @@ -573,6 +582,8 @@ public void setAlpha(int a) { private int setUsernameRow; private int bioRow; private int phoneSuggestionSectionRow; + private int graceSuggestionRow; + private int graceSuggestionSectionRow; private int phoneSuggestionRow; private int passwordSuggestionSectionRow; private int passwordSuggestionRow; @@ -761,6 +772,11 @@ public void openPhotoForEdit(String file, String thumb, boolean isVideo) { private ImageReceiver fallbackImage; private boolean loadingBoostsStats; private boolean waitCanSendStoryRequest; + private FrameLayout bottomButtonsContainer; + private FrameLayout[] bottomButtonContainer; + private SpannableStringBuilder bottomButtonPostText; + private ButtonWithCounterView[] bottomButton; + private Runnable applyBulletin; public static ProfileActivity of(long dialogId) { Bundle bundle = new Bundle(); @@ -1526,7 +1542,7 @@ public void onNestedPreScroll(View target, int dx, int dy, int[] consumed, int t if (t > 0) { consumed[1] -= dy; } - if (consumed[1] > 0) { + if (innerListView != null && consumed[1] > 0) { innerListView.scrollBy(0, consumed[1]); } } @@ -1831,6 +1847,7 @@ public boolean onFragmentCreate() { vcardFirstName = arguments.getString("vcard_first_name"); vcardLastName = arguments.getString("vcard_last_name"); reportSpam = arguments.getBoolean("reportSpam", false); + myProfile = arguments.getBoolean("my_profile", false); if (!expandPhoto) { expandPhoto = arguments.getBoolean("expandPhoto", false); if (expandPhoto) { @@ -1943,6 +1960,7 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().addObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().addObserver(this, NotificationCenter.userIsPremiumBlockedUpadted); + getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); updateRowsIds(); if (listAdapter != null) { @@ -1965,6 +1983,28 @@ public boolean onFragmentCreate() { }); } } + + Bulletin.addDelegate(this, new Bulletin.Delegate() { + @Override + public int getTopOffset(int tag) { + return AndroidUtilities.statusBarHeight; + } + + @Override + public int getBottomOffset(int tag) { + if (bottomButtonsContainer == null) { + return 0; + } + final float stories = Math.min(1f, 1f - Math.abs(sharedMediaLayout.getTabProgress() - SharedMediaLayout.TAB_STORIES)); + final float archivedStories = Math.min(1f, 1f - Math.abs(sharedMediaLayout.getTabProgress() - SharedMediaLayout.TAB_ARCHIVED_STORIES)); + return (int) (dp(72) - bottomButtonsContainer.getTranslationY() - archivedStories * bottomButtonContainer[1].getTranslationY() - stories * bottomButtonContainer[0].getTranslationY()); + } + + @Override + public boolean bottomOffsetAnimated() { + return bottomButtonsContainer == null; + } + }); return true; } @@ -2038,6 +2078,7 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.storiesReadUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.userIsPremiumBlockedUpadted); + getNotificationCenter().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); if (avatarsViewPager != null) { avatarsViewPager.onDestroy(); @@ -2074,6 +2115,12 @@ public void onFragmentDestroy() { birthdayFetcher.detach(true); birthdayFetcher = null; } + + if (applyBulletin != null) { + Runnable runnable = applyBulletin; + applyBulletin = null; + AndroidUtilities.runOnUIThread(runnable); + } } @Override @@ -2336,6 +2383,8 @@ public void onClick(DialogInterface dialog, int which) { } presentFragment(fragment); } + } else if (id == edit_profile) { + presentFragment(new UserInfoActivity()); } else if (id == invite_to_group) { final TLRPC.User user = getMessagesController().getUser(userId); if (user == null) { @@ -2533,7 +2582,16 @@ public void didChangeOwner(TLRPC.User user) { } else if (id == edit_info) { presentFragment(new UserInfoActivity()); } else if (id == edit_color) { + if (!getUserConfig().isPremium()) { + showDialog(new PremiumFeatureBottomSheet(ProfileActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_NAME_COLOR, true)); + return; + } presentFragment(new PeerColorActivity(0).startOnProfile().setOnApplied(ProfileActivity.this)); + } else if (id == copy_link_profile) { + TLRPC.User user = getMessagesController().getUser(userId); + AndroidUtilities.addToClipboard(getMessagesController().linkPrefix + "/" + UserObject.getPublicUsername(user)); + } else if (id == set_username) { + presentFragment(new ChangeUsernameActivity()); } else if (id == logout) { presentFragment(new LogoutActivity()); } else if (id == set_as_main) { @@ -2667,7 +2725,7 @@ public void didChangeOwner(TLRPC.User user) { getMessagesController().deleteUserPhoto(inputPhoto); getMessagesStorage().clearUserPhoto(userId, photo.id); } - if (avatarsViewPager.removePhotoAtIndex(position)) { + if (avatarsViewPager.removePhotoAtIndex(position) || avatarsViewPager.getRealCount() <= 0) { avatarsViewPager.setVisibility(View.GONE); avatarImage.setForegroundAlpha(1f); avatarContainer.setVisibility(View.VISIBLE); @@ -3169,6 +3227,15 @@ protected void onSelectedTabChanged() { protected boolean includeSavedDialogs() { return dialogId == getUserConfig().getClientUserId() && !saved; } + @Override + protected boolean isSelf() { + return myProfile; + } + + @Override + protected boolean isStoriesView() { + return myProfile; + } @Override protected void onSearchStateChanged(boolean expanded) { @@ -3214,12 +3281,80 @@ protected void invalidateBlur() { protected int getInitialTab() { return TAB_STORIES; } + + @Override + protected void showActionMode(boolean show) { + super.showActionMode(show); + if (myProfile) { + disableScroll(show); + + int a = getSelectedTab() - SharedMediaLayout.TAB_STORIES; + if (a < 0 || a > 1) return; + bottomButtonContainer[a] + .animate() + .translationY(show || a == 0 && MessagesController.getInstance(currentAccount).storiesEnabled() ? 0 : dp(72)) + .setDuration(320) + .setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT) + .setUpdateListener(anm -> updateBottomButtonY()) + .start(); + } + } + @Override + protected void onTabProgress(float progress) { + super.onTabProgress(progress); + if (myProfile) { + bottomButtonContainer[0].setTranslationX((SharedMediaLayout.TAB_STORIES - progress) * sharedMediaLayout.getMeasuredWidth()); + bottomButtonContainer[1].setTranslationX((SharedMediaLayout.TAB_ARCHIVED_STORIES - progress) * sharedMediaLayout.getMeasuredWidth()); + updateBottomButtonY(); + } + } + + @Override + protected void onActionModeSelectedUpdate(SparseArray messageObjects) { + super.onActionModeSelectedUpdate(messageObjects); + if (myProfile) { + final int count = messageObjects.size(); + int a = getSelectedTab() - SharedMediaLayout.TAB_STORIES; + if (a < 0 || a > 1) return; + if (a == 0) { + bottomButton[a].setText(count > 0 || !MessagesController.getInstance(currentAccount).storiesEnabled() ? formatPluralString("ArchiveStories", count) : bottomButtonPostText, true); + } + bottomButton[a].setCount(count, true); + } + } + + @Override + public void openStoryRecorder() { + StoryRecorder.getInstance(getParentActivity(), currentAccount) + .selectedPeerId(getDialogId()) + .canChangePeer(false) + .closeToWhenSent(new StoryRecorder.ClosingViewProvider() { + @Override + public void preLayout(long dialogId, Runnable runnable) { + avatarImage.setHasStories(needInsetForStories()); + if (dialogId == getDialogId()) { + collapseAvatarInstant(); + } + AndroidUtilities.runOnUIThread(runnable, 30); + } + + @Override + public StoryRecorder.SourceView getView(long dialogId) { + if (dialogId != getDialogId()) { + return null; + } + updateAvatarRoundRadius(); + return StoryRecorder.SourceView.fromAvatarImage(avatarImage, ChatObject.isForum(currentChat)); + } + }) + .open(StoryRecorder.SourceView.fromFloatingButton(floatingButtonContainer), true); + } }; sharedMediaLayout.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.MATCH_PARENT)); ActionBarMenu menu = actionBar.createMenu(); -// if (userId == getUserConfig().clientUserId) { +// if (userId == getUserConfig().clientUserId && !myProfile) { // qrItem = menu.addItem(qr_button, R.drawable.msg_qr_mini, getResourceProvider()); // qrItem.setContentDescription(LocaleController.getString("GetQRCode", R.string.GetQRCode)); // updateQrItemVisibility(false); @@ -3227,8 +3362,7 @@ protected int getInitialTab() { // ContactsController.getInstance(currentAccount).loadPrivacySettings(); // } // } - - if (imageUpdater != null) { + if (imageUpdater != null && !myProfile) { searchItem = menu.addItem(search_button, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override @@ -3274,8 +3408,13 @@ public void onTextChanged(EditText editText) { } eventLogItem = menu.addItem(event_log, R.drawable.msg_log); eventLogItem.setContentDescription(LocaleController.getString("EventLog", R.string.EventLog)); - editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); - editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + if (myProfile) { + editItem = menu.addItem(edit_profile, R.drawable.group_edit_profile); + editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + } else { + editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); + editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + } otherItem = menu.addItem(10, R.drawable.ic_ab_other, resourcesProvider); ttlIconView = new ImageView(context); ttlIconView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); @@ -3344,6 +3483,14 @@ public void invalidate() { } } + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (sharedMediaLayout.canEditStories() && sharedMediaLayout != null && sharedMediaLayout.isActionModeShown() && sharedMediaLayout.getClosestTab() == SharedMediaLayout.TAB_STORIES) { + return false; + } + return super.onInterceptTouchEvent(e); + } + @Override public boolean onTouchEvent(MotionEvent e) { final int action = e.getAction(); @@ -3405,6 +3552,12 @@ protected void dispatchDraw(Canvas canvas) { } super.dispatchDraw(canvas); } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + updateBottomButtonY(); + } }; listView.setVerticalScrollBarEnabled(false); DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator() { @@ -3439,6 +3592,12 @@ public void runPendingAnimations() { protected long getAddAnimationDelay(long removeDuration, long moveDuration, long changeDuration) { return 0; } + + @Override + protected void onMoveAnimationUpdate(RecyclerView.ViewHolder holder) { + super.onMoveAnimationUpdate(holder); + updateBottomButtonY(); + } }; listView.setItemAnimator(defaultItemAnimator); defaultItemAnimator.setMoveDelay(0); @@ -3563,7 +3722,7 @@ public void onClick(DialogInterface dialog, int which) { if (button != null) { button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); } - } if (position == settingsKeyRow) { + } else if (position == settingsKeyRow) { Bundle args = new Bundle(); args.putInt("chat_id", DialogObject.getEncryptedChatId(dialogId)); presentFragment(new IdenticonActivity(args)); @@ -3574,7 +3733,7 @@ public void onClick(DialogInterface dialog, int which) { NotificationsCheckCell checkCell = (NotificationsCheckCell) view; boolean checked = !checkCell.isChecked(); - boolean defaultEnabled = getNotificationsController().isGlobalNotificationsEnabled(did); + boolean defaultEnabled = getNotificationsController().isGlobalNotificationsEnabled(did, false, false); String key = NotificationsController.getSharedPrefKey(did, topicId); if (checked) { @@ -4060,48 +4219,7 @@ public void openExceptions() { layoutManager.scrollToPositionWithOffset(savedScrollPosition, savedScrollOffset - listView.getPaddingTop()); } } else if (position == bizLocationRow) { - if (userInfo == null || userInfo.business_location == null) return; - if (userInfo.business_location.geo_point != null) { - LocationActivity fragment = new LocationActivity(3) { - @Override - protected boolean disablePermissionCheck() { - return true; - } - }; - fragment.setResourceProvider(resourcesProvider); - TLRPC.TL_message message = new TLRPC.TL_message(); - message.local_id = -1; - message.peer_id = getMessagesController().getPeer(dialogId); - TLRPC.TL_messageMediaGeo media = new TLRPC.TL_messageMediaGeo(); - media.geo = userInfo.business_location.geo_point; - media.address = userInfo.business_location.address; - message.media = media; - fragment.setSharingAllowed(false); - fragment.setMessageObject(new MessageObject(UserConfig.selectedAccount, message, false, false)); - presentFragment(fragment); - } else { - String domain; -// if (BuildVars.isHuaweiStoreApp()) { -// domain = "mapapp://navigation"; -// } else { - domain = "http://maps.google.com/maps"; -// } -// if (myLocation != null) { -// try { -// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?saddr=%f,%f&daddr=%f,%f", myLocation.getLatitude(), myLocation.getLongitude(), daddrLat, daddrLong))); -// getParentActivity().startActivity(intent); -// } catch (Exception e) { -// FileLog.e(e); -// } -// } else { - try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?q=" + userInfo.business_location.address ))); - getParentActivity().startActivity(intent); - } catch (Exception e) { - FileLog.e(e); - } -// } - } + openLocation(false); } else if (position == channelRow) { // na: Group Profile Show Linked Channel Info if (chatInfo != null) { @@ -4116,6 +4234,9 @@ protected boolean disablePermissionCheck() { if (birthdayEffect != null && birthdayEffect.start()) { return; } + if (editRow(view, position)) { + return; + } TextDetailCell cell = (TextDetailCell) view; if (cell.hasImage()) { onTextDetailCellImageClicked(cell.getImageView()); @@ -4172,8 +4293,9 @@ public boolean onItemClick(View view, int position) { BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.photoViewerBlur ? "do not blur in photoviewer" : "blur in photoviewer") : null, !SharedConfig.payByInvoice ? "Enable Invoice Payment" : "Disable Invoice Payment", BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null, - Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? (!SharedConfig.useCamera2 ? "Use Camera 2 API" : "Use old Camera 1 API") : null, - BuildVars.DEBUG_VERSION ? "Clear bot biometry data" : null + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? (!SharedConfig.isUsingCamera2(currentAccount) ? "Use Camera 2 API" : "Use old Camera 1 API") : null, + BuildVars.DEBUG_VERSION ? "Clear bot biometry data" : null, + BuildVars.DEBUG_PRIVATE_VERSION ? "Clear all login tokens" : null }; builder.setItems(items, (dialog, which) -> { @@ -4475,9 +4597,11 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo } else if (which == 26) { getMediaDataController().loadAttachMenuBots(false, true); } else if (which == 27) { - SharedConfig.toggleUseCamera2(); + SharedConfig.toggleUseCamera2(currentAccount); } else if (which == 28) { BotBiometry.clear(); + } else if (which == 29) { + AuthTokensHelper.clearLogInTokens(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -4499,6 +4623,7 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo } return onMemberClick(participant, true, view); } else if (position == birthdayRow) { + if (editRow(view, position)) return true; if (userInfo == null) return false; try { AndroidUtilities.addToClipboard(UserInfoActivity.birthdayString(userInfo.birthday)); @@ -4508,6 +4633,7 @@ protected void onSend(LongSparseArray dids, int count, TLRPC.TL_fo } return true; } else { + if (editRow(view, position)) return true; return processOnClickOrPress(position, view, view.getWidth() / 2f, (int) (view.getHeight() * .75f)); } } @@ -4638,8 +4764,19 @@ protected void onDraw(Canvas canvas) { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { removeSelfFromStack(); + TLRPC.User user = getMessagesController().getUser(userId); + if (user != null && chat != null && userId != 0 && fragment != null && fragment.banning && fragment.getParentLayout() != null) { + for (BaseFragment fragment : fragment.getParentLayout().getFragmentStack()) { + if (fragment instanceof ChannelAdminLogActivity) { + ((ChannelAdminLogActivity) fragment).reloadLastMessages(); + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.createRemoveFromChatBulletin(fragment, user, chat.title).show(); + }); + return; + } + } + } } - @Override public void didChangeOwner(TLRPC.User user) { undoView.showWithAction(-chatId, currentChat.megagroup ? UndoView.ACTION_OWNER_TRANSFERED_GROUP : UndoView.ACTION_OWNER_TRANSFERED_CHANNEL, user); @@ -4652,7 +4789,7 @@ public void didChangeOwner(TLRPC.User user) { textView.setTextColor(getThemedColor(Theme.key_text_RedRegular)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setGravity(Gravity.CENTER); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); textView.setText(LocaleController.getString("BanFromTheGroup", R.string.BanFromTheGroup)); frameLayout1.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 1, 0, 0)); @@ -5142,7 +5279,8 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (participantsMap != null && !usersEndReached && layoutManager.findLastVisibleItemPosition() > membersEndRow - 8) { getChannelParticipants(false); } - sharedMediaLayout.setPinnedToTop(sharedMediaLayout.getY() == 0); + sharedMediaLayout.setPinnedToTop(sharedMediaLayout.getY() <= 0); + updateBottomButtonY(); } }); @@ -5393,9 +5531,143 @@ public void setAlpha(float alpha) { createBirthdayEffect(); createFloatingActionButton(getContext()); + + if (myProfile) { + bottomButtonsContainer = new FrameLayout(context); + contentView.addView(bottomButtonsContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 72 + (1 / AndroidUtilities.density), Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + + bottomButtonContainer = new FrameLayout[2]; + bottomButton = new ButtonWithCounterView[2]; + for (int a = 0; a < 2; ++a) { + bottomButtonContainer[a] = new FrameLayout(context); + bottomButtonContainer[a].setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + + View shadow = new View(context); + shadow.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundGray)); + bottomButtonContainer[a].addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1 / AndroidUtilities.density, Gravity.TOP | Gravity.FILL_HORIZONTAL)); + + bottomButton[a] = new ButtonWithCounterView(context, resourcesProvider); + if (a == 0) { + bottomButtonPostText = new SpannableStringBuilder("c"); + bottomButtonPostText.setSpan(new ColoredImageSpan(R.drawable.filled_premium_camera), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + bottomButtonPostText.append(" ").append(getString(R.string.StoriesAddPost)); + bottomButton[a].setText(bottomButtonPostText, false); + } else { + bottomButton[a].setText(getString(R.string.StorySave), false); + } + final int finalA = a; + bottomButton[a].setOnClickListener(v -> { + if (finalA == 0 && !sharedMediaLayout.isActionModeShown()) { + if (!getMessagesController().storiesEnabled()) { + showDialog(new PremiumFeatureBottomSheet(this, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, true)); + return; + } + getMessagesController().getMainSettings().edit().putBoolean("story_keep", true).apply(); + StoryRecorder.getInstance(getParentActivity(), getCurrentAccount()) + .closeToWhenSent(new StoryRecorder.ClosingViewProvider() { + @Override + public void preLayout(long dialogId, Runnable runnable) { + avatarImage.setHasStories(needInsetForStories()); + if (dialogId == getDialogId()) { + collapseAvatarInstant(); + } + AndroidUtilities.runOnUIThread(runnable, 30); + } + + @Override + public StoryRecorder.SourceView getView(long dialogId) { + if (dialogId != getDialogId()) { + return null; + } + updateAvatarRoundRadius(); + return StoryRecorder.SourceView.fromAvatarImage(avatarImage, ChatObject.isForum(currentChat)); + } + }) + .open(null); + } else { + final long dialogId = getUserConfig().getClientUserId(); + if (applyBulletin != null) { + applyBulletin.run(); + applyBulletin = null; + } + Bulletin.hideVisible(); + boolean pin = sharedMediaLayout.getClosestTab() == SharedMediaLayout.TAB_ARCHIVED_STORIES; + int count = 0; + ArrayList storyItems = new ArrayList<>(); + SparseArray actionModeMessageObjects = sharedMediaLayout.getActionModeSelected(); + if (actionModeMessageObjects != null) { + for (int i = 0; i < actionModeMessageObjects.size(); ++i) { + MessageObject messageObject = actionModeMessageObjects.valueAt(i); + if (messageObject.storyItem != null) { + storyItems.add(messageObject.storyItem); + count++; + } + } + } + sharedMediaLayout.closeActionMode(false); + if (pin) { + sharedMediaLayout.scrollToPage(SharedMediaLayout.TAB_STORIES); + } + if (storyItems.isEmpty()) { + return; + } + boolean[] pastValues = new boolean[storyItems.size()]; + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + pastValues[i] = storyItem.pinned; + storyItem.pinned = pin; + } + getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); + final boolean[] undone = new boolean[] { false }; + applyBulletin = () -> { + getMessagesController().getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, null); + }; + final Runnable undo = () -> { + undone[0] = true; + AndroidUtilities.cancelRunOnUIThread(applyBulletin); + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + storyItem.pinned = pastValues[i]; + } + getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); + }; + Bulletin bulletin; + if (pin) { + bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.contact_check, LocaleController.formatPluralString("StorySavedTitle", count), LocaleController.getString(R.string.StorySavedSubtitle), LocaleController.getString(R.string.Undo), undo).show(); + } else { + bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.chats_archived, LocaleController.formatPluralString("StoryArchived", count), LocaleController.getString(R.string.Undo), Bulletin.DURATION_PROLONG, undo).show(); + } + bulletin.setOnHideListener(() -> { + if (!undone[0] && applyBulletin != null) { + applyBulletin.run(); + } + applyBulletin = null; + }); + } + }); + bottomButtonContainer[a].addView(bottomButton[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 12, 12, 12, 12)); + + bottomButtonsContainer.addView(bottomButtonContainer[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + if (a == 1 || !getMessagesController().storiesEnabled()) { + bottomButtonContainer[a].setTranslationY(dp(72)); + } + } + } + return fragmentView; } + private void updateBottomButtonY() { + if (bottomButtonsContainer == null) { + return; + } + bottomButtonsContainer.setTranslationY(sharedMediaLayout.isAttachedToWindow() ? Math.max(0, dp(72 + 64 + 48) - (listView.getMeasuredHeight() - sharedMediaLayout.getY())) : dp(72)); + Bulletin bulletin = Bulletin.getVisibleBulletin(); + if (bulletin != null) { + bulletin.updatePosition(); + } + } + FrameLayout floatingButtonContainer; RLottieImageView floatingButton; boolean floatingHidden; @@ -6295,6 +6567,8 @@ private boolean processOnClickOrPress(final int position, final View view, final showDialog(dialog); } else if (position == phoneRow || position == numberRow) { + if (editRow(view, position)) return true; + final TLRPC.User user = getMessagesController().getUser(userId); if (user == null || user.phone == null || user.phone.length() == 0 || getParentActivity() == null) { return false; @@ -6462,6 +6736,7 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (position == bioRow && (userInfo == null || TextUtils.isEmpty(userInfo.about))) { return false; } + if (editRow(view, position)) return true; if (view instanceof AboutLinkCell && ((AboutLinkCell) view).onClick()) { return false; } @@ -6511,41 +6786,9 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { final String finalText; if (position == bizHoursRow) { if (userInfo.business_work_hours == null) return false; - ArrayList[] days = OpeningHoursActivity.getDaysHours(userInfo.business_work_hours.weekly_open); - StringBuilder sb = new StringBuilder(); - if (userInfo.user != null) { - sb.append(formatString(R.string.BusinessHoursCopyHeader, UserObject.getUserName(userInfo.user))).append("\n"); - } - for (int i = 0; i < days.length; ++i) { - ArrayList periods = days[i]; - String day = DayOfWeek.values()[i].getDisplayName(TextStyle.FULL, LocaleController.getInstance().getCurrentLocale()); - day = day.substring(0, 1).toUpperCase() + day.substring(1); - sb.append(day).append(": "); - if (OpeningHoursActivity.isFull(periods)) { - sb.append(LocaleController.getString(R.string.BusinessHoursProfileOpen)); - } else if (periods.isEmpty()) { - sb.append(LocaleController.getString(R.string.BusinessHoursProfileClose)); - } else { - for (int j = 0; j < periods.size(); ++j) { - if (j > 0) sb.append(", "); - OpeningHoursActivity.Period p = periods.get(j); - sb.append(OpeningHoursActivity.Period.timeToString(p.start)); - sb.append(" - "); - sb.append(OpeningHoursActivity.Period.timeToString(p.end)); - } - } - sb.append("\n"); - } - TLRPC.TL_timezone timezone = TimezonesController.getInstance(currentAccount).findTimezone(userInfo.business_work_hours.timezone_id); - Calendar calendar = Calendar.getInstance(); - int currentUtcOffset = calendar.getTimeZone().getRawOffset() / 1000; - int valueUtcOffset = timezone == null ? 0 : timezone.utc_offset; - int utcOffset = (currentUtcOffset - valueUtcOffset) / 60; - if (utcOffset != 0 && timezone != null) { - sb.append(formatString(R.string.BusinessHoursCopyFooter, TimezonesController.getInstance(currentAccount).getTimezoneName(timezone, true))); - } - finalText = sb.toString(); + finalText = OpeningHoursActivity.toString(currentAccount, userInfo.user, userInfo.business_work_hours); } else if (position == bizLocationRow) { + if (editRow(view, position)) return true; if (userInfo.business_location == null) return false; finalText = userInfo.business_location.address; } else return true; @@ -7118,6 +7361,8 @@ public void updateSelectedMediaTabText() { mediaCounterTextView.setText(onlineTextView[1].getText()); } else if (id == SharedMediaLayout.TAB_STORIES) { mediaCounterTextView.setText(LocaleController.formatPluralString("ProfileStoriesCount", sharedMediaLayout.getStoriesCount(id))); + } else if (id == SharedMediaLayout.TAB_ARCHIVED_STORIES) { + mediaCounterTextView.setText(LocaleController.formatPluralString("ProfileStoriesArchiveCount", sharedMediaLayout.getStoriesCount(id))); } else if (id == SharedMediaLayout.TAB_RECOMMENDED_CHANNELS) { MessagesController.ChannelRecommendations rec = MessagesController.getInstance(currentAccount).getChannelRecommendations(chatId); mediaCounterTextView.setText(LocaleController.formatPluralString("Channels", rec == null ? 0 : rec.chats.size() + rec.more)); @@ -7905,10 +8150,18 @@ public void didReceivedNotification(int id, int account, final Object... args) { avatarImage.setHasStories(needInsetForStories()); updateAvatarRoundRadius(); } + if (userInfo != null) { + storyView.setStories(userInfo.stories); + } else if (chatInfo != null) { + storyView.setStories(chatInfo.stories); + } } else if (id == NotificationCenter.userIsPremiumBlockedUpadted) { if (otherItem != null) { otherItem.setSubItemShown(start_secret_chat, !getMessagesController().isUserPremiumBlocked(userId)); } + updateEditColorIcon(); + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + updateEditColorIcon(); } } @@ -8022,6 +8275,7 @@ public void onResume() { if (flagSecure != null) { flagSecure.attach(); } + updateItemsUsername(); } @Override @@ -8082,7 +8336,7 @@ public boolean onBackPressed() { } public boolean isSettings() { - return imageUpdater != null; + return imageUpdater != null && !myProfile; } @Override @@ -8713,6 +8967,8 @@ private void updateRowsIds() { phoneSuggestionSectionRow = -1; phoneSuggestionRow = -1; passwordSuggestionSectionRow = -1; + graceSuggestionRow = -1; + graceSuggestionSectionRow = -1; passwordSuggestionRow = -1; settingsSectionRow = -1; settingsSectionRow2 = -1; @@ -8809,7 +9065,7 @@ private void updateRowsIds() { hasMedia = chatInfo.stories_pinned_available; } if (!hasMedia) { - if (MessagesController.ChannelRecommendations.hasRecommendations(currentAccount, chatId)) { + if (chatId != 0 && MessagesController.ChannelRecommendations.hasRecommendations(currentAccount, chatId)) { hasMedia = true; } } @@ -8820,7 +9076,7 @@ private void updateRowsIds() { } TLRPC.User user = getMessagesController().getUser(userId); - if (UserObject.isUserSelf(user)) { + if (UserObject.isUserSelf(user) && !myProfile) { if (avatarBig == null && (user.photo == null || !(user.photo.photo_big instanceof TLRPC.TL_fileLocation_layer97) && !(user.photo.photo_big instanceof TLRPC.TL_fileLocationToBeDeprecated)) && (avatarsViewPager == null || avatarsViewPager.getRealCount() == 0)) { setAvatarRow = rowCount++; setAvatarSectionRow = rowCount++; @@ -8835,11 +9091,13 @@ private void updateRowsIds() { settingsSectionRow = rowCount++; Set suggestions = getMessagesController().pendingSuggestions; - if (suggestions.contains("VALIDATE_PHONE_NUMBER")) { + if (suggestions.contains("PREMIUM_GRACE")) { + graceSuggestionRow = rowCount++; + graceSuggestionSectionRow = rowCount++; + } else if (suggestions.contains("VALIDATE_PHONE_NUMBER")) { phoneSuggestionRow = rowCount++; phoneSuggestionSectionRow = rowCount++; - } - if (suggestions.contains("VALIDATE_PASSWORD")) { + } else if (suggestions.contains("VALIDATE_PASSWORD")) { passwordSuggestionRow = rowCount++; passwordSuggestionSectionRow = rowCount++; } @@ -8851,7 +9109,7 @@ private void updateRowsIds() { dataRow = rowCount++; liteModeRow = rowCount++; // stickersRow = rowCount++; - if (getMessagesController().filtersEnabled || !getMessagesController().dialogFilters.isEmpty() || true) { + if (getMessagesController().filtersEnabled || !getMessagesController().dialogFilters.isEmpty()) { filtersRow = rowCount++; } devicesRow = rowCount++; @@ -8951,11 +9209,11 @@ private void updateRowsIds() { } boolean divider = false; - if (showAddToContacts && user != null && !user.contact && !user.bot && !UserObject.isService(user.id)) { + if (!myProfile && showAddToContacts && user != null && !user.contact && !user.bot && !UserObject.isService(user.id)) { addToContactsRow = rowCount++; divider = true; } - if (reportReactionMessageId != 0 && !ContactsController.getInstance(currentAccount).isContact(userId)) { + if (!myProfile && reportReactionMessageId != 0 && !ContactsController.getInstance(currentAccount).isContact(userId)) { reportReactionRow = rowCount++; divider = true; } @@ -8963,7 +9221,7 @@ private void updateRowsIds() { reportDividerRow = rowCount++; } - if (hasMedia || userInfo != null && userInfo.common_chats_count != 0) { + if (hasMedia || userInfo != null && userInfo.common_chats_count != 0 || myProfile) { sharedMediaRow = rowCount++; } else if (lastSectionRow == -1 && needSendMessage) { sendMessageRow = rowCount++; @@ -9163,7 +9421,7 @@ private Drawable getVerifiedCrossfadeDrawable(int a) { verifiedDrawable[a] = Theme.profile_verifiedDrawable.getConstantState().newDrawable().mutate(); verifiedCheckDrawable[a] = Theme.profile_verifiedCheckDrawable.getConstantState().newDrawable().mutate(); if (a == 1 && peerColor != null) { - int color = Theme.adaptHSV(ColorUtils.blendARGB(peerColor.getColor2(), peerColor.hasColor6(Theme.isCurrentThemeDark()) ? peerColor.getColor5() : peerColor.getColor3(), .4f), +.1f, Theme.isCurrentThemeDark() ? -.1f : -.08f); + int color = Theme.adaptHSV(peerColor.hasColor6(Theme.isCurrentThemeDark()) ? peerColor.getColor5() : peerColor.getColor3(), +.1f, Theme.isCurrentThemeDark() ? -.1f : -.08f); verifiedDrawable[1].setColorFilter(AndroidUtilities.getOffsetColor(color, getThemedColor(Theme.key_player_actionBarTitle), mediaHeaderAnimationProgress, 1.0f), PorterDuff.Mode.MULTIPLY); color = Color.WHITE; verifiedCheckDrawable[1].setColorFilter(AndroidUtilities.getOffsetColor(color, getThemedColor(Theme.key_windowBackgroundWhite), mediaHeaderAnimationProgress, 1.0f), PorterDuff.Mode.MULTIPLY); @@ -9977,14 +10235,25 @@ private void createActionBarMenu(boolean animated) { videoCallItemVisible = false; canSearchMembers = false; boolean selfUser = false; + if (userId != 0) { TLRPC.User user = getMessagesController().getUser(userId); if (user == null) { return; } if (UserObject.isUserSelf(user)) { + editItemVisible = myProfile; otherItem.addSubItem(edit_info, R.drawable.msg_edit, LocaleController.getString(R.string.EditInfo)); - otherItem.addSubItem(edit_color, R.drawable.msg_colors, LocaleController.getString(R.string.EditProfileColor)); + if (imageUpdater != null) { + otherItem.addSubItem(add_photo, R.drawable.msg_addphoto, LocaleController.getString("AddPhoto", R.string.AddPhoto)); + } + editColorItem = otherItem.addSubItem(edit_color, R.drawable.menu_profile_colors, LocaleController.getString(R.string.ProfileColorEdit)); + updateEditColorIcon(); + if (myProfile) { + setUsernameItem = otherItem.addSubItem(set_username, R.drawable.menu_username_change, getString(R.string.ProfileUsernameEdit)); + linkItem = otherItem.addSubItem(copy_link_profile, R.drawable.msg_link2, getString(R.string.ProfileCopyLink)); + updateItemsUsername(); + } selfUser = true; } else { if (user.bot && user.bot_can_edit) { @@ -10161,7 +10430,7 @@ private void createActionBarMenu(boolean animated) { otherItem.hideSubItem(gallery_menu_save); } - if (selfUser) { + if (selfUser && !myProfile) { otherItem.addSubItem(logout, R.drawable.msg_leave, LocaleController.getString("LogOut", R.string.LogOut)); } if (!isPulledDown) { @@ -11068,10 +11337,15 @@ protected int processColor(int color) { @Override protected void onYesClick(int type) { getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); - getMessagesController().removeSuggestion(0, type == SettingsSuggestionCell.TYPE_PHONE ? "VALIDATE_PHONE_NUMBER" : "VALIDATE_PASSWORD"); + if (type == SettingsSuggestionCell.TYPE_GRACE) { + Browser.openUrl(getContext(), getMessagesController().premiumManageSubscriptionUrl); + getMessagesController().removeSuggestion(0, "PREMIUM_GRACE"); + updateListAnimated(false); + } else { + getMessagesController().removeSuggestion(0, type == SettingsSuggestionCell.TYPE_PHONE ? "VALIDATE_PHONE_NUMBER" : "VALIDATE_PASSWORD"); + updateListAnimated(false); + } getNotificationCenter().addObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); - int oldRow = type == SettingsSuggestionCell.TYPE_PHONE ? phoneSuggestionRow : passwordSuggestionRow; - updateListAnimated(false); } @Override @@ -11177,7 +11451,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { isTopic || bizHoursRow != -1 || bizLocationRow != -1 ); - containsGift = today && !getMessagesController().premiumPurchaseBlocked(); + containsGift = !myProfile && today && !getMessagesController().premiumPurchaseBlocked(); } } else if (position == phoneRow) { String text; @@ -11546,7 +11820,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (hasOverride) { enabled = true; } else { - enabled = getNotificationsController().isGlobalNotificationsEnabled(did); + enabled = getNotificationsController().isGlobalNotificationsEnabled(did, false, false); } } else if (value == 1) { enabled = true; @@ -11623,7 +11897,13 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { break; case VIEW_TYPE_SUGGESTION: SettingsSuggestionCell suggestionCell = (SettingsSuggestionCell) holder.itemView; - suggestionCell.setType(position == passwordSuggestionRow ? SettingsSuggestionCell.TYPE_PASSWORD : SettingsSuggestionCell.TYPE_PHONE); + if (position == passwordSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_PASSWORD); + } else if (position == phoneSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_PHONE); + } else if (position == graceSuggestionRow) { + suggestionCell.setType(SettingsSuggestionCell.TYPE_GRACE); + } break; case VIEW_TYPE_ADDTOGROUP_INFO: TextInfoPrivacyCell addToGroupInfo = (TextInfoPrivacyCell) holder.itemView; @@ -11635,7 +11915,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { textCheckCell.setTextAndCheck(LocaleController.getString("Notifications", R.string.Notifications), !getMessagesController().isDialogMuted(getDialogId(), topicId), false); break; case VIEW_TYPE_LOCATION: - ((ProfileLocationCell) holder.itemView).set(userInfo != null ? userInfo.business_location : null, notificationsDividerRow < 0); + ((ProfileLocationCell) holder.itemView).set(userInfo != null ? userInfo.business_location : null, notificationsDividerRow < 0 && !myProfile); break; case VIEW_TYPE_HOURS: ProfileHoursCell hoursCell = (ProfileHoursCell) holder.itemView; @@ -11651,7 +11931,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { layoutManager.scrollToPositionWithOffset(savedScrollPosition, savedScrollOffset - listView.getPaddingTop()); } }); - hoursCell.set(userInfo != null ? userInfo.business_work_hours : null, hoursExpanded, hoursShownMine, notificationsDividerRow < 0 || bizLocationRow >= 0); + hoursCell.set(userInfo != null ? userInfo.business_work_hours : null, hoursExpanded, hoursShownMine, notificationsDividerRow < 0 && !myProfile || bizLocationRow >= 0); break; case VIEW_TYPE_CHANNEL: if (userInfo != null) { @@ -11733,6 +12013,9 @@ public void onClick(@NonNull View view) { } else { obj = getMessagesController().getChat(chatId); } + if (getContext() == null) { + return; + } FragmentUsernameBottomSheet.open(getContext(), FragmentUsernameBottomSheet.TYPE_USERNAME, usernameObj.username, obj, (TL_fragment.TL_collectibleInfo) res, getResourceProvider()); } else { BulletinFactory.showError(err); @@ -11830,7 +12113,9 @@ public int getItemViewType(int position) { } else if (position == infoSectionRow || position == lastSectionRow || position == membersSectionRow || position == secretSettingsSectionRow || position == settingsSectionRow || position == devicesSectionRow || position == helpSectionCell || position == setAvatarSectionRow || position == passwordSuggestionSectionRow || - position == phoneSuggestionSectionRow || position == premiumSectionsRow || position == reportDividerRow || position == channelDividerRow) { + position == phoneSuggestionSectionRow || position == premiumSectionsRow || position == reportDividerRow || + position == channelDividerRow || position == graceSuggestionSectionRow + ) { return VIEW_TYPE_SHADOW; } else if (position >= membersStartRow && position < membersEndRow) { return VIEW_TYPE_USER; @@ -11842,7 +12127,7 @@ public int getItemViewType(int position) { return VIEW_TYPE_SHARED_MEDIA; } else if (position == versionRow) { return VIEW_TYPE_VERSION; - } else if (position == passwordSuggestionRow || position == phoneSuggestionRow) { + } else if (position == passwordSuggestionRow || position == phoneSuggestionRow || position == graceSuggestionRow) { return VIEW_TYPE_SUGGESTION; } else if (position == addToGroupInfoRow) { return VIEW_TYPE_ADDTOGROUP_INFO; @@ -12933,7 +13218,11 @@ private void onTextDetailCellImageClicked(View view) { args.putLong("user_id", userId); presentFragment(new QrActivity(args)); } else if (parent.getTag() != null && ((int) parent.getTag()) == birthdayRow) { - TLRPC.User user = getMessagesController().getUser(dialogId); + if (userId == getUserConfig().getClientUserId()) { + presentFragment(new PremiumPreviewFragment("my_profile_gift")); + return; + } + TLRPC.User user = getMessagesController().getUser(userId); if (user == null || userInfo == null) return; ArrayList options = new ArrayList<>(userInfo.premium_gifts); if (options.isEmpty()) { @@ -13100,6 +13389,8 @@ public void fillPositions(SparseIntArray sparseIntArray) { put(++pointer, phoneSuggestionSectionRow, sparseIntArray); put(++pointer, passwordSuggestionRow, sparseIntArray); put(++pointer, passwordSuggestionSectionRow, sparseIntArray); + put(++pointer, graceSuggestionRow, sparseIntArray); + put(++pointer, graceSuggestionSectionRow, sparseIntArray); put(++pointer, settingsSectionRow, sparseIntArray); put(++pointer, settingsSectionRow2, sparseIntArray); put(++pointer, notificationRow, sparseIntArray); @@ -13404,10 +13695,25 @@ public ShowDrawable getShowStatusButton() { public static class ShowDrawable extends Drawable implements SimpleTextView.PressableDrawable { - private final Text text; + public final AnimatedTextView.AnimatedTextDrawable textDrawable; public final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); public ShowDrawable(String string) { - text = new Text(string, 11); + textDrawable = new AnimatedTextView.AnimatedTextDrawable(); + textDrawable.setCallback(new Callback() { + @Override + public void invalidateDrawable(@NonNull Drawable who) { + if (view != null) { + view.invalidate(); + } + } + @Override + public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {} + @Override + public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {} + }); + textDrawable.setText(string); + textDrawable.setTextSize(dp(11)); + textDrawable.setGravity(Gravity.CENTER); backgroundPaint.setColor(0x1f000000); } @@ -13436,7 +13742,10 @@ public void draw(@NonNull Canvas canvas) { backgroundPaint.setAlpha((int) (wasAlpha * alpha)); canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(20), dp(20), backgroundPaint); backgroundPaint.setAlpha(wasAlpha); - text.draw(canvas, AndroidUtilities.rectTmp.left + dp(5.5f), AndroidUtilities.rectTmp.centerY(), textColor, alpha); + textDrawable.setTextColor(textColor); + textDrawable.setAlpha((int) (0xFF * alpha)); + textDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + textDrawable.draw(canvas); canvas.restore(); } @@ -13454,7 +13763,7 @@ public void setColorFilter(@Nullable ColorFilter colorFilter) { @Override public int getIntrinsicWidth() { - return (int) (text.getCurrentWidth() + dp(11)); + return (int) (textDrawable.getAnimateToWidth() + dp(11)); } @Override @@ -13485,6 +13794,11 @@ public void setPressed(boolean pressed) { public boolean isPressed() { return pressed; } + + private View view; + public void setView(View view) { + this.view = view; + } } public void setLoadingSpan(CharacterStyle span) { @@ -13514,4 +13828,320 @@ private void createBirthdayEffect() { ((FrameLayout) fragmentView).addView(birthdayEffect, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL_HORIZONTAL | Gravity.TOP)); } + private void openLocation(boolean inMapsApp) { + if (userInfo == null || userInfo.business_location == null) return; + if (userInfo.business_location.geo_point != null && !inMapsApp) { + LocationActivity fragment = new LocationActivity(3) { + @Override + protected boolean disablePermissionCheck() { + return true; + } + }; + fragment.setResourceProvider(resourcesProvider); + TLRPC.TL_message message = new TLRPC.TL_message(); + message.local_id = -1; + message.peer_id = getMessagesController().getPeer(dialogId); + TLRPC.TL_messageMediaGeo media = new TLRPC.TL_messageMediaGeo(); + media.geo = userInfo.business_location.geo_point; + media.address = userInfo.business_location.address; + message.media = media; + fragment.setSharingAllowed(false); + fragment.setMessageObject(new MessageObject(UserConfig.selectedAccount, message, false, false)); + presentFragment(fragment); + } else { + String domain; +// if (BuildVars.isHuaweiStoreApp()) { +// domain = "mapapp://navigation"; +// } else { + domain = "http://maps.google.com/maps"; +// } +// if (myLocation != null) { +// try { +// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?saddr=%f,%f&daddr=%f,%f", myLocation.getLatitude(), myLocation.getLongitude(), daddrLat, daddrLong))); +// getParentActivity().startActivity(intent); +// } catch (Exception e) { +// FileLog.e(e); +// } +// } else { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(Locale.US, domain + "?q=" + userInfo.business_location.address ))); + getParentActivity().startActivity(intent); + } catch (Exception e) { + FileLog.e(e); + } +// } + } + + } + + private boolean editRow(View view, int position) { + if (!myProfile) return false; + + if (view instanceof ProfileChannelCell) { + view = ((ProfileChannelCell) view).dialogCell; + } + + TLRPC.User user = getUserConfig().getCurrentUser(); + if (user == null) return false; + TLRPC.UserFull userFull = userInfo == null ? getMessagesController().getUserFull(user.id) : userInfo; + if (userFull == null) return false; + + String copyButton = getString(R.string.Copy); + String textToCopy = null; + if (position == channelInfoRow || position == userInfoRow || position == bioRow) { + textToCopy = userFull.about; + } else if (position == bizHoursRow) { + textToCopy = OpeningHoursActivity.toString(currentAccount, user, userFull.business_work_hours); + copyButton = getString(R.string.ProfileHoursCopy); + } else if (position == bizLocationRow) { + textToCopy = userFull.business_location.address; + copyButton = getString(R.string.ProfileLocationCopy); + } else if (position == usernameRow) { + textToCopy = UserObject.getPublicUsername(user); + if (textToCopy != null) textToCopy = "@" + textToCopy; + copyButton = getString(R.string.ProfileCopyUsername); + } else if (position == phoneRow) { + textToCopy = user.phone; + } else if (position == birthdayRow) { + textToCopy = UserInfoActivity.birthdayString(userInfo.birthday); + } + + ItemOptions itemOptions = ItemOptions.makeOptions(contentView, resourcesProvider, view); + itemOptions.setGravity(Gravity.LEFT); + + if (position == bizLocationRow && userFull.business_location != null) { + if (userFull.business_location.geo_point != null) { + itemOptions.add(R.drawable.msg_view_file, getString(R.string.ProfileLocationView), () -> { + openLocation(false); + }); + } + itemOptions.add(R.drawable.msg_map, getString(R.string.ProfileLocationMaps), () -> { + openLocation(true); + }); + } + + if (textToCopy != null) { + final String text = textToCopy; + itemOptions.add(R.drawable.msg_copy, copyButton, () -> { + AndroidUtilities.addToClipboard(text); + }); + } + + if (position == bizHoursRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileHoursEdit), () -> { + presentFragment(new OpeningHoursActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.ProfileHoursRemove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BusinessHoursClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BusinessHoursClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBusinessWorkHours req = new TLRPC.TL_account_updateBusinessWorkHours(); + if (userFull != null) { + userFull.business_work_hours = null; + userFull.flags2 &=~ 1; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == bizLocationRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileLocationEdit), () -> { + presentFragment(new org.telegram.ui.Business.LocationActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.ProfileLocationRemove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BusinessLocationClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BusinessLocationClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBusinessLocation req = new TLRPC.TL_account_updateBusinessLocation(); + if (userFull != null) { + userFull.business_location = null; + userFull.flags2 &=~ 2; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == usernameRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileUsernameEdit), () -> { + presentFragment(new ChangeUsernameActivity()); + }); + } else if (position == channelInfoRow || position == userInfoRow || position == bioRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileEditBio), () -> { + presentFragment(new UserInfoActivity()); + }); + } else if (position == phoneRow) { + itemOptions.add(R.drawable.menu_storage_path, getString(R.string.ProfilePhoneEdit), () -> { + presentFragment(new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER)); + }); + } else if (position == birthdayRow) { + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileBirthdayChange), () -> { + showDialog(AlertsCreator.createBirthdayPickerDialog(getContext(), getString(R.string.EditProfileBirthdayTitle), getString(R.string.EditProfileBirthdayButton), userFull.birthday, birthday -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + req.flags |= 1; + req.birthday = birthday; + TLRPC.TL_birthday oldBirthday = userFull != null ? userFull.birthday : null; + if (userFull != null) { + userFull.flags2 |= 32; + userFull.birthday = birthday; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (res instanceof TLRPC.TL_boolTrue) { + BulletinFactory.of(ProfileActivity.this) + .createSimpleBulletin(R.raw.contact_check, LocaleController.getString(R.string.PrivacyBirthdaySetDone)) + .setDuration(Bulletin.DURATION_PROLONG).show(); + } else { + if (userFull != null) { + if (oldBirthday == null) { + userFull.flags2 &=~ 32; + } else { + userFull.flags2 |= 32; + } + userFull.birthday = oldBirthday; + getMessagesStorage().updateUserInfo(userFull, false); + } + if (err != null && err.text != null && err.text.startsWith("FLOOD_WAIT_")) { + if (getContext() != null) { + showDialog( + new AlertDialog.Builder(getContext(), resourceProvider) + .setTitle(getString(R.string.PrivacyBirthdayTooOftenTitle)) + .setMessage(getString(R.string.PrivacyBirthdayTooOftenMessage)) + .setPositiveButton(getString(R.string.OK), null) + .create() + ); + } + } else { + BulletinFactory.of(ProfileActivity.this) + .createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.UnknownError)) + .show(); + } + } + }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); + }, () -> { + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + params.allowNestedScroll = false; + showAsSheet(new PrivacyControlActivity(PrivacyControlActivity.PRIVACY_RULES_TYPE_BIRTHDAY), params); + }, getResourceProvider()).create()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.Remove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.BirthdayClearTitle)); + builder.setMessage(LocaleController.getString(R.string.BirthdayClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updateBirthday req = new TLRPC.TL_account_updateBirthday(); + if (userFull != null) { + userFull.birthday = null; + userFull.flags2 &=~ 32; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } else if (position == channelRow) { + TLRPC.Chat channel = getMessagesController().getChat(userFull.personal_channel_id); + if (channel != null && ChatObject.getPublicUsername(channel) != null) { + itemOptions.add(R.drawable.msg_copy, getString(R.string.ProfileChannelCopy), () -> { + AndroidUtilities.addToClipboard("https://" + getMessagesController().linkPrefix + "/" + ChatObject.getPublicUsername(channel)); + }); + } + itemOptions.add(R.drawable.msg_edit, getString(R.string.ProfileChannelChange), () -> { + presentFragment(new UserInfoActivity()); + }); + itemOptions.add(R.drawable.msg_delete, getString(R.string.Remove), true, () -> { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.ProfileChannelClearTitle)); + builder.setMessage(LocaleController.getString(R.string.ProfileChannelClearMessage)); + builder.setPositiveButton(LocaleController.getString(R.string.Remove), (di, w) -> { + TLRPC.TL_account_updatePersonalChannel req = new TLRPC.TL_account_updatePersonalChannel(); + if (userFull != null) { + userFull.personal_channel_id = 0; + userFull.personal_channel_message = 0; + userFull.flags2 &=~ 64; + } + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + if (err != null) { + BulletinFactory.showError(err); + } else if (res instanceof TLRPC.TL_boolFalse) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show(); + } + })); + updateRowsIds(); + listAdapter.notifyItemRemoved(position); + getMessagesStorage().updateUserInfo(userFull, false); + }); + builder.setNegativeButton(LocaleController.getString(R.string.Cancel), null); + showDialog(builder.create()); + }); + } + + if (itemOptions.getItemsCount() <= 0) { + return false; + } + + itemOptions.show(); + + return true; + } + + private void updateItemsUsername() { + if (!myProfile) return; + TLRPC.User user = getMessagesController().getUser(userId); + if (user == null) { + return; + } + final boolean hasUsername = UserObject.getPublicUsername(user) != null; + setUsernameItem.setIcon(hasUsername ? R.drawable.menu_username_change : R.drawable.menu_username_set); + setUsernameItem.setText(hasUsername ? getString(R.string.ProfileUsernameEdit) : getString(R.string.ProfileUsernameSet)); + linkItem.setVisibility(UserObject.getPublicUsername(user) != null ? View.VISIBLE : View.GONE); + } + + private void updateEditColorIcon() { + if (getContext() == null || editColorItem == null) return; + if (getUserConfig().isPremium()) { + editColorItem.setIcon(R.drawable.menu_profile_colors); + } else { + Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.menu_profile_colors_locked); + icon.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); + Drawable lockIcon = ContextCompat.getDrawable(getContext(), R.drawable.msg_gallery_locked2); + lockIcon.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(icon, lockIcon, dp(1), -dp(1)) { + @Override + public void setColorFilter(ColorFilter colorFilter) {} + }; + editColorItem.setIcon(combinedDrawable); + } + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java index cfd1f41c57..787574f04b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileBirthdayEffect.java @@ -233,7 +233,7 @@ public static BirthdayEffectFetcher of(int currentAccount, TLRPC.UserFull userIn return null; } final int age; - if ((userInfo.birthday.flags & 1) != 0) { + if (userInfo != null && userInfo.birthday != null && (userInfo.birthday.flags & 1) != 0) { age = Period.between(LocalDate.of(userInfo.birthday.year, userInfo.birthday.month, userInfo.birthday.day), LocalDate.now()).getYears(); } else { age = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 07429a0453..b0d251b509 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -229,7 +229,7 @@ public boolean onFragmentCreate() { customResetShadowRow = -1; } - boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId, false, false); if (addingException) { notificationsEnabled = !defaultEnabled; } else { @@ -242,7 +242,7 @@ public boolean onFragmentCreate() { if (hasOverride) { notificationsEnabled = true; } else { - notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId, false, false); } } else if (value == 1) { notificationsEnabled = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java index 7a3b363b1a..7b8be2431a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ReportAdBottomSheet.java @@ -170,6 +170,7 @@ private void submitOption(CharSequence optionText, byte[] option) { } } } else if (response instanceof TLRPC.TL_channels_sponsoredMessageReportResultAdsHidden) { + MessagesController.getInstance(currentAccount).disableAds(false); if (listener != null) { listener.onHidden(); dismiss(); @@ -382,7 +383,6 @@ public void fillItems(ArrayList items, UniversalAdapter adapter) { for (int i = 0; i < option.options.size(); i++) { UItem buttonItem = new UItem(UniversalAdapter.VIEW_TYPE_RIGHT_ICON_TEXT, false); buttonItem.text = option.options.get(i).text; - buttonItem.backgroundKey = Theme.key_dialogBackground; buttonItem.iconResId = R.drawable.msg_arrowright; buttonItem.id = i; items.add(buttonItem); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index c4ab2453e1..202f10d821 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -8,6 +8,7 @@ import android.animation.ValueAnimator; import android.app.Activity; import android.app.Dialog; +import android.app.Notification; import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; @@ -72,6 +73,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; +import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -222,6 +224,22 @@ public void setSelectedReaction(ReactionsLayoutInBubble.VisibleReaction reaction } } + public void setSelectedReactions(ArrayList emojis) { + selectedReactions.clear(); + for (String emoji : emojis) { + selectedReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji)); + } + if (emojiGridView != null) { + for (int i = 0; i < emojiGridView.getChildCount(); i++) { + if (emojiGridView.getChildAt(i) instanceof ImageViewEmoji) { + ImageViewEmoji imageViewEmoji = (ImageViewEmoji) emojiGridView.getChildAt(i); + imageViewEmoji.setViewSelected(selectedReactions.contains(imageViewEmoji.reaction), true); + } + } + emojiGridView.invalidate(); + } + } + public void setForUser(boolean forUser) { this.forUser = forUser; updateRows(false, false); @@ -404,7 +422,7 @@ public void dismiss() { private boolean recentExpanded = false; private ArrayList recent = new ArrayList<>(); private ArrayList recentStickers = new ArrayList<>(); - private ArrayList standardEmojis = new ArrayList<>(); + private ArrayList standardEmojis = new ArrayList<>(); private ArrayList topReactions = new ArrayList<>(); private ArrayList recentReactions = new ArrayList<>(); private ArrayList defaultStatuses = new ArrayList<>(); @@ -547,7 +565,7 @@ protected void dispatchDraw(Canvas canvas) { } }; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && type != TYPE_AVATAR_CONSTRUCTOR) { contentView.setOutlineProvider(new ViewOutlineProvider() { private final Rect rect = new Rect(); @@ -841,7 +859,7 @@ public void onScrolled(int dx, int dy) { TextView emptyViewText = new TextView(context); if (type == TYPE_AVATAR_CONSTRUCTOR) { emptyViewText.setText(LocaleController.getString("NoEmojiOrStickersFound", R.string.NoEmojiOrStickersFound)); - } else if (type == TYPE_EMOJI_STATUS || type == TYPE_EMOJI_STATUS_TOP || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { + } else if (type == TYPE_EMOJI_STATUS || type == TYPE_STICKER_SET_EMOJI || type == TYPE_EMOJI_STATUS_TOP || type == TYPE_TAGS || type == TYPE_EMOJI_STATUS_CHANNEL || type == TYPE_EMOJI_STATUS_CHANNEL_TOP) { emptyViewText.setText(LocaleController.getString("NoEmojiFound", R.string.NoEmojiFound)); } else if (type == TYPE_REACTIONS || type == TYPE_SET_DEFAULT_REACTION) { emptyViewText.setText(LocaleController.getString("NoReactionsFound", R.string.NoReactionsFound)); @@ -1015,7 +1033,7 @@ public void onAnimationEnd(Animator animation) { RecyclerListView.OnItemClickListener onItemClick = (view, position) -> { if (view instanceof ImageViewEmoji) { ImageViewEmoji viewEmoji = (ImageViewEmoji) view; - if (viewEmoji.isDefaultReaction) { + if (viewEmoji.isDefaultReaction || type == TYPE_STICKER_SET_EMOJI) { incrementHintUse(); onReactionClick(viewEmoji, viewEmoji.reaction); } else if (viewEmoji.isStaticIcon && viewEmoji.document != null) { @@ -1682,6 +1700,7 @@ public void search(String query, boolean liftUp, boolean delay) { lastSearchKeyboardLanguage = newLanguage; AndroidUtilities.runOnUIThread(searchRunnable = () -> { final LinkedHashSet documentIds = new LinkedHashSet<>(); + final LinkedHashSet emojis = new LinkedHashSet<>(); final HashMap availableReactions = MediaDataController.getInstance(currentAccount).getReactionsMap(); final ArrayList reactions = new ArrayList<>(); final boolean queryFullyConsistsOfEmojis = Emoji.fullyConsistsOfEmojis(query); @@ -1731,6 +1750,9 @@ public void search(String query, boolean liftUp, boolean delay) { for (long documentId : documentIds) { searchResult.add(ReactionsLayoutInBubble.VisibleReaction.fromCustomEmoji(documentId)); } + for (String emoji : emojis) { + searchResult.add(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji)); + } searchSets.addAll(sets); for (ArrayList array : emojiArrays) { stickersSearchResult.addAll(array); @@ -1739,24 +1761,6 @@ public void search(String query, boolean liftUp, boolean delay) { }); if (type == TYPE_STICKER_SET_EMOJI) { - final TLRPC.TL_messages_stickerSet[] restrictedSet = new TLRPC.TL_messages_stickerSet[] { null }; - final TLRPC.TL_messages_stickerSet[] staticSet = new TLRPC.TL_messages_stickerSet[] { null }; - - final Utilities.Callback loadSets = next -> { -// TLRPC.TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC.TL_inputStickerSetShortName(); -// inputStickerSetShortName.short_name = "RestrictedEmoji"; -// MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetShortName, 0, false, set -> { -// restrictedSet[0] = set; -// if (staticSet[0] != null) next.run(); -// }); - TLRPC.TL_inputStickerSetShortName inputStickerSetShortName2 = new TLRPC.TL_inputStickerSetShortName(); - inputStickerSetShortName2.short_name = "StaticEmoji"; - MediaDataController.getInstance(currentAccount).getStickerSet(inputStickerSetShortName2, 0, false, set -> { - staticSet[0] = set; -// if (restrictedSet[0] != null) - next.run(); - }); - }; final Utilities.Callback search = next -> { MediaDataController.getInstance(currentAccount).getEmojiSuggestions( lastSearchKeyboardLanguage, query, false, @@ -1766,26 +1770,19 @@ public void search(String query, boolean liftUp, boolean delay) { if (result.get(i).emoji.startsWith("animated_")) { continue; } - String emoji = result.get(i).emoji; - TLRPC.Document document; - document = findSticker(restrictedSet[0], emoji); - if (document == null) { - document = findSticker(staticSet[0], emoji); - } - if (document != null) { - AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocument(document); - documentIds.add(document.id); + String emoji = Emoji.fixEmoji(result.get(i).emoji); + if (Emoji.getEmojiDrawable(emoji) == null) { + continue; } + emojis.add(emoji); } - } catch (Exception ignore) { - } + } catch (Exception ignore) {} next.run(); }, null, false, false, false, 0 ); }; - - Utilities.doCallbacks(loadSets, search, applySearch); + Utilities.doCallbacks(search, applySearch); } else { final Utilities.Callback searchCategories = next -> { if (queryFullyConsistsOfEmojis) { @@ -2052,7 +2049,7 @@ public int getItemViewType(int position) { return VIEW_TYPE_EMOJI; } if (position > emojiStartRow && position - emojiStartRow - 1 < searchResult.size()) { - if (searchResult.get(position - emojiStartRow - 1).documentId != 0) { + if (type == TYPE_STICKER_SET_EMOJI || searchResult.get(position - emojiStartRow - 1).documentId != 0) { return VIEW_TYPE_EMOJI; } } @@ -2105,10 +2102,13 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } imageView.imageReceiver.setParentView(emojiSearchGridView); imageView.reaction = currentReaction; + imageView.isFirstReactions = false; imageView.setViewSelected(selectedReactions.contains(currentReaction), false); imageView.notDraw = false; imageView.invalidate(); - if (currentReaction.emojicon != null) { + if (type == TYPE_STICKER_SET_EMOJI) { + imageView.setDrawable(Emoji.getEmojiDrawable(currentReaction.emojicon)); + } else if (currentReaction.emojicon != null) { imageView.isDefaultReaction = true; TLRPC.TL_availableReaction reaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(currentReaction.emojicon); if (reaction != null) { @@ -2159,7 +2159,17 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi Long documentId = null; TLRPC.Document document = null; if (searchResult != null && position >= 0 && position < searchResult.size()) { - documentId = searchResult.get(position).documentId; + ReactionsLayoutInBubble.VisibleReaction visibleReaction = searchResult.get(position); + if (visibleReaction.documentId == 0) { + selected = selectedReactions.contains(visibleReaction); + imageView.reaction = visibleReaction; + imageView.isFirstReactions = true; + imageView.setDrawable(Emoji.getEmojiDrawable(visibleReaction.emojicon)); + imageView.setViewSelected(selected, false); + return; + } else { + documentId = visibleReaction.documentId; + } } else if (searchSets != null && (position - setsStartRow) >= 0 && (position - setsStartRow) < searchSets.size()) { document = searchSets.get(position - setsStartRow); if (document instanceof SetTitleDocument) { @@ -2397,14 +2407,14 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } if (position == recentReactionsSectionRow) { header.setText(LocaleController.getString("RecentlyUsed", R.string.RecentlyUsed), false); - if (type == TYPE_AVATAR_CONSTRUCTOR) { +// if (type == TYPE_AVATAR_CONSTRUCTOR) { header.closeIcon.setVisibility(View.GONE); - } else { - header.closeIcon.setVisibility(View.VISIBLE); - header.closeIcon.setOnClickListener((view) -> { - clearRecent(); - }); - } +// } else { +// header.closeIcon.setVisibility(View.VISIBLE); +// header.closeIcon.setOnClickListener((view) -> { +// clearRecent(); +// }); +// } return; } header.closeIcon.setVisibility(View.GONE); @@ -2432,7 +2442,17 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi currentReaction = topReactions.get(index); } + if (type == TYPE_STICKER_SET_EMOJI) { + imageView.notDraw = false; + imageView.isFirstReactions = true; + imageView.reaction = currentReaction; + imageView.setDrawable(Emoji.getEmojiDrawable(currentReaction.emojicon)); + imageView.setViewSelected(selectedReactions.contains(currentReaction), false); + return; + } + imageView.createImageReceiver(emojiGridView); + imageView.isFirstReactions = true; imageView.reaction = currentReaction; imageView.setViewSelected(selectedReactions.contains(currentReaction), false); imageView.notDraw = false; @@ -2548,7 +2568,6 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi recentSize = recent.size() > recentmaxlen && !recentExpanded ? recentmaxlen : recent.size() + (includeEmpty ? 1 : 0); } boolean selected = false; - imageView.setDrawable(null); if (includeEmpty && position == (searchRow != -1 ? 1 : 0) + (longtapHintRow != -1 ? 1 : 0)) { selected = selectedDocumentIds.contains(null); imageView.empty = true; @@ -2561,8 +2580,14 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } else if (type == TYPE_STICKER_SET_EMOJI && position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) < standardEmojis.size()) { int pos = position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) - (includeEmpty ? 1 : 0); - TLRPC.Document document = standardEmojis.get(pos); - imageView.setSticker(document, emojiGridView); + String emoji = standardEmojis.get(pos); + imageView.notDraw = false; + imageView.isFirstReactions = false; + imageView.reaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(emoji); + imageView.setDrawable(Emoji.getEmojiDrawable(emoji)); + selected = selectedReactions.contains(imageView.reaction); + imageView.setViewSelected(selected, false); + return; } else if (position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) < recentSize) { int resentPosition = position - (searchRow != -1 ? 1 : 0) - (longtapHintRow != -1 ? 1 : 0) - (includeEmpty ? 1 : 0); if (type == TYPE_AVATAR_CONSTRUCTOR && showStickers) { @@ -2931,6 +2956,7 @@ public class ImageViewEmoji extends View { public ImageReceiver imageReceiverToDraw; public boolean isDefaultReaction; public ReactionsLayoutInBubble.VisibleReaction reaction; + public boolean isFirstReactions; public Drawable drawable; public Rect drawableBounds; public float bigReactionSelectedProgress; @@ -3592,20 +3618,10 @@ private void updateRows(boolean updateEmojipacks, boolean animated, boolean diff } } if (type == TYPE_STICKER_SET_EMOJI) { -// TLRPC.TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC.TL_inputStickerSetShortName(); -// inputStickerSetShortName.short_name = "RestrictedEmoji"; -// TLRPC.TL_messages_stickerSet restrictedSet = mediaDataController.getStickerSet(inputStickerSetShortName, 0, false); - - TLRPC.TL_inputStickerSetShortName inputStickerSetShortName2 = new TLRPC.TL_inputStickerSetShortName(); - inputStickerSetShortName2.short_name = "StaticEmoji"; - TLRPC.TL_messages_stickerSet staticSet = mediaDataController.getStickerSet(inputStickerSetShortName2, 0, false); - - TLRPC.TL_messages_stickerSet baseSet = staticSet; // staticSet != null ? staticSet : restrictedSet; - - if (baseSet != null) { - for (TLRPC.Document d : baseSet.documents) { - standardEmojis.add(d); - rowHashCodes.add(43223 + 13L * d.id); + for (String[] section : EmojiData.dataColored) { + for (String emoji : section) { + standardEmojis.add(emoji); + rowHashCodes.add(13334 + 322L * emoji.hashCode()); totalCount++; } } @@ -4107,7 +4123,7 @@ public void draw(Canvas canvas, long time, int w, int h, float alpha) { skewAlpha = .25f + .75f * skewAlpha; } } - boolean drawInUi = skewAlpha < 1 || isAnimating() || imageViewEmojis.size() <= 4 || !lite || enterAnimationInProgress() || type == TYPE_AVATAR_CONSTRUCTOR || type == TYPE_CHAT_REACTIONS; + boolean drawInUi = type == TYPE_STICKER_SET_EMOJI || skewAlpha < 1 || isAnimating() || imageViewEmojis.size() <= 4 || !lite || enterAnimationInProgress() || type == TYPE_AVATAR_CONSTRUCTOR || type == TYPE_CHAT_REACTIONS; if (!drawInUi) { boolean animatedExpandIn = animateExpandStartTime > 0 && (SystemClock.elapsedRealtime() - animateExpandStartTime) < animateExpandDuration(); for (int i = 0; i < imageViewEmojis.size(); i++) { @@ -4316,6 +4332,9 @@ protected void drawInUiThread(Canvas canvas, float alpha) { } float scale = imageView.getScaleX(); + if (type == TYPE_STICKER_SET_EMOJI) { + scale *= .87f; + } if (imageView.pressedProgress != 0 || imageView.selected) { scale *= 0.8f + 0.2f * (1f - ((imageView.selected && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR) ? 0.7f : imageView.pressedProgress)); } @@ -4351,7 +4370,7 @@ protected void drawInUiThread(Canvas canvas, float alpha) { drawable.setAlpha(255); } else if (!imageView.isDefaultReaction && !imageView.isStaticIcon) { AnimatedEmojiSpan span = imageView.span; - if (span == null || imageView.notDraw) { + if (span == null && type != TYPE_STICKER_SET_EMOJI || imageView.notDraw) { continue; } drawable = imageView.drawable; @@ -4374,7 +4393,7 @@ protected void drawInUiThread(Canvas canvas, float alpha) { //scale here only selected emoji canvas.scale(0.85f, 0.85f, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); } - if (type == TYPE_CHAT_REACTIONS) { + if (type == TYPE_CHAT_REACTIONS || type == TYPE_STICKER_SET_EMOJI) { canvas.scale(scale, scale, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); } else { skew(canvas, i, imageView.getHeight()); @@ -4492,6 +4511,7 @@ protected void onAttachedToWindow() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentEmojiStatusesUpdate); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); if (scrimDrawable != null) { scrimDrawable.setSecondParent(this); @@ -4507,6 +4527,7 @@ protected void onDetachedFromWindow() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentEmojiStatusesUpdate); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); if (scrimDrawable != null) { scrimDrawable.setSecondParent(null); @@ -4536,6 +4557,11 @@ public void didReceivedNotification(int id, int account, Object... args) { updateRowsDelayed(); } else if (id == NotificationCenter.groupStickersDidLoad) { updateRowsDelayed(); + } else if (id == NotificationCenter.emojiLoaded) { + AndroidUtilities.forEachViews(emojiGridView, View::invalidate); + if (emojiGridView != null) { + emojiGridView.invalidate(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java index 45749e3617..a3ca6f18e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -317,6 +317,10 @@ public void onMiniListClicked() { } + public void openStoryForCell(StoryCell cell) { + openStoryForCell(cell, false); + } + private void openStoryForCell(StoryCell cell, boolean overscroll) { if (cell == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java index 06e2188d91..a6b992db63 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -1787,7 +1787,7 @@ private void createStealthModeItem(ActionBarPopupWindow.ActionBarPopupWindowLayo if (stealthModeIsActive) { StealthModeAlert.showStealthModeEnabledBulletin(); } else { - StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), resourcesProvider); + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), StealthModeAlert.TYPE_FROM_STORIES, resourcesProvider); delegate.showDialog(stealthModeAlert); } if (popupMenu != null) { @@ -1808,7 +1808,7 @@ public void setColorFilter(ColorFilter colorFilter) { }; ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.StealthModeButton), false, resourcesProvider); item2.setOnClickListener(v -> { - StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), resourcesProvider); + StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), StealthModeAlert.TYPE_FROM_STORIES, resourcesProvider); delegate.showDialog(stealthModeAlert); if (popupMenu != null) { popupMenu.dismiss(); @@ -2031,7 +2031,7 @@ private ArrayList getAnimatedEmojiSets(StoryItemHolder st if (storyHolder != null) { HashSet ids = new HashSet<>(); ArrayList inputStickerSets = new ArrayList<>(); - if (storyHolder.storyItem.media_areas != null) { + if (storyHolder.storyItem != null && storyHolder.storyItem.media_areas != null) { for (int i = 0; i < storyHolder.storyItem.media_areas.size(); ++i) { TL_stories.MediaArea mediaArea = storyHolder.storyItem.media_areas.get(i); if (mediaArea instanceof TL_stories.TL_mediaAreaSuggestedReaction && mediaArea.reaction instanceof TLRPC.TL_reactionCustomEmoji) { @@ -3617,6 +3617,9 @@ private void deleteStory() { selectedPosition = 0; } updatePosition(); + if (storyViewer != null) { + storyViewer.checkSelfStoriesView(); + } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (DialogInterface.OnClickListener) (dialog, which) -> { dialog.dismiss(); @@ -4026,7 +4029,7 @@ private void updatePosition(boolean preload) { final boolean sameId = getStoryId(currentStory.storyItem, currentStory.uploadingStory) == getStoryId(oldStoryItem, oldUploadingStory) || oldUploadingStory != null && currentStory.storyItem != null && TextUtils.equals(oldUploadingStory.path, currentStory.storyItem.attachPath); - final boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading || isFailed != wasFailed); + boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading || isFailed != wasFailed); boolean storyChanged = false; if (!( @@ -4059,15 +4062,16 @@ private void updatePosition(boolean preload) { if (storyChanged || oldUploadingStory != null && currentStory.uploadingStory == null) { headerView.setOnSubtitleClick(null); + CharSequence subtitle = null; if (currentStory.uploadingStory != null) { if (currentStory.uploadingStory.failed) { - headerView.setSubtitle(LocaleController.getString("FailedToUploadStory", R.string.FailedToUploadStory), animateSubtitle); + subtitle = LocaleController.getString("FailedToUploadStory", R.string.FailedToUploadStory); } else { - headerView.setSubtitle(StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing), animateSubtitle); + subtitle = StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing); } } else if (currentStory.storyItem != null) { if (currentStory.storyItem.date == -1) { - headerView.setSubtitle(LocaleController.getString("CachedStory", R.string.CachedStory)); + subtitle = LocaleController.getString("CachedStory", R.string.CachedStory); } else if (currentStory.getReply() != null) { StoryCaptionView.Reply reply = currentStory.getReply(); @@ -4123,7 +4127,8 @@ private void updatePosition(boolean preload) { dot.setSpan(dotDividerSpan, 0, dot.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append(" ").append(dot).append(" ").append(LocaleController.formatShortDate(currentStory.storyItem.date)); - headerView.setSubtitle(ssb, false); + subtitle = ssb; + animateSubtitle = false; } else if (isGroup && currentStory.storyItem != null && currentStory.storyItem.from_id != null) { SpannableStringBuilder ssb = new SpannableStringBuilder(); AvatarSpan avatar = new AvatarSpan(headerView.subtitleView[0], currentAccount, 15); @@ -4159,7 +4164,8 @@ private void updatePosition(boolean preload) { dot.setSpan(dotDividerSpan, 0, dot.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append(" ").append(dot).append(" ").append(LocaleController.formatShortDate(currentStory.storyItem.date)); - headerView.setSubtitle(ssb, false); + subtitle = ssb; + animateSubtitle = false; } else { CharSequence string = LocaleController.formatStoryDate(currentStory.storyItem.date); if (currentStory.storyItem.edited) { @@ -4171,8 +4177,20 @@ private void updatePosition(boolean preload) { spannableStringBuilder.append(LocaleController.getString("EditedMessage", R.string.EditedMessage)); string = spannableStringBuilder; } - headerView.setSubtitle(string, animateSubtitle); + subtitle = string; + } + } + if (subtitle != null) { + if (storyViewer != null && storyViewer.storiesList != null && currentStory.storyItem != null && storyViewer.storiesList.isPinned(currentStory.storyItem.id)) { + if (!(subtitle instanceof SpannableStringBuilder)) { + subtitle = new SpannableStringBuilder(subtitle); + } + + SpannableString pin = new SpannableString("p "); + pin.setSpan(new ColoredImageSpan(R.drawable.msg_pin_mini), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ((SpannableStringBuilder) subtitle).insert(0, pin); } + headerView.setSubtitle(subtitle, animateSubtitle); } if (privacyHint != null) { privacyHint.hide(false); @@ -4947,7 +4965,7 @@ public void setAccount(int currentAccount) { emojiAnimationsOverlay.setAccount(currentAccount); if (reactionsContainerLayout != null) { reactionsContainerLayout.setCurrentAccount(currentAccount); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } if (likesReactionLayout != null) { likesReactionLayout.setCurrentAccount(currentAccount); @@ -6475,7 +6493,7 @@ public void onEmojiWindowDismissed() { delegate.requestAdjust(false); } }); - reactionsContainerLayout.setMessage(null, null); + reactionsContainerLayout.setMessage(null, null, true); } reactionsContainerLayout.setFragment(LaunchActivity.getLastFragment()); reactionsContainerLayout.setHint(LocaleController.getString(isGroup ? R.string.StoryGroupReactionsHint : R.string.StoryReactionsHint)); @@ -6611,7 +6629,7 @@ public boolean needEnterText() { return false; } }); - likesReactionLayout.setMessage(null, null); + likesReactionLayout.setMessage(null, null, true); } else { bringChildToFront(likesReactionLayout); likesReactionLayout.reset(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java index 7aa3509784..72360b29b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java @@ -334,6 +334,10 @@ public void setItems(ArrayList storyItems, } else { scrollToPositionInLayout = position; } + + for (int i = 0; i < lastDrawnImageReceivers.size(); i++) { + lastDrawnImageReceivers.get(i).onBind(lastDrawnImageReceivers.get(i).position); + } } public int getClosestPosition() { @@ -412,6 +416,7 @@ public ImageHolder() { } void onBind(int position) { + if (position < 0 || position >= storyItems.size()) return; storyItem = storyItems.get(position); if (isAttachedToWindow) { receiver.onAttachedToWindow(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java index b1ec273058..ca09f49e1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -41,6 +41,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -520,6 +521,9 @@ public void setStoryItem(long dialogId, SelfStoryViewsView.StoryItemInternal sto this.storyItem = storyItem; updateViewsVisibility(); updateViewState(false); + if (storyItem != null && storyItem.storyItem != null) { + NotificationsController.getInstance(currentAccount).processSeenStoryReactions(dialogId, storyItem.storyItem.id); + } } private void updateViewsVisibility() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java index 5c750bb23c..8c8a29f9eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java @@ -39,11 +39,21 @@ public class StealthModeAlert extends BottomSheet { + public interface Listener { + void onButtonClicked(boolean isStealthModeEnabled); + } + + public static final int TYPE_FROM_STORIES = 0; + public static final int TYPE_FROM_DIALOGS = 1; + private final PremiumButtonView button; - boolean stealthModeIsActive; + private boolean stealthModeIsActive; + private int type; + private Listener listener; - public StealthModeAlert(Context context, float topOffset, Theme.ResourcesProvider resourcesProvider) { + public StealthModeAlert(Context context, float topOffset, int type, Theme.ResourcesProvider resourcesProvider) { super(context, false, resourcesProvider); + this.type = type; FrameLayout frameLayout = new FrameLayout(getContext()) { @Override protected void onAttachedToWindow() { @@ -142,6 +152,9 @@ protected void onDetachedFromWindow() { } else { if (stealthModeIsActive) { dismiss(); + if (listener != null) { + listener.onButtonClicked(false); + } return; } StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); @@ -160,9 +173,17 @@ protected void onDetachedFromWindow() { })); containerView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); dismiss(); - showStealthModeEnabledBulletin(); + if (type == TYPE_FROM_STORIES) { + showStealthModeEnabledBulletin(); + } + if (listener != null) { + listener.onButtonClicked(true); + } } else if (stealthModeIsActive) { dismiss(); + if (listener != null) { + listener.onButtonClicked(false); + } } else { BulletinFactory factory = BulletinFactory.of(container, resourcesProvider); if (factory != null) { @@ -175,6 +196,10 @@ protected void onDetachedFromWindow() { }); } + public void setListener(Listener listener) { + this.listener = listener; + } + public static void showStealthModeEnabledBulletin() { BaseFragment fragment = LaunchActivity.getLastFragment(); BulletinFactory factory; @@ -205,7 +230,11 @@ private void updateButton(boolean animated) { button.setOverlayText(LocaleController.getString("StealthModeIsActive", R.string.StealthModeIsActive), true, animated); button.overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); } else if (stealthMode == null || ConnectionsManager.getInstance(currentAccount).getCurrentTime() > stealthMode.cooldown_until_date) { - button.setOverlayText(LocaleController.getString("EnableStealthMode", R.string.EnableStealthMode), true, animated); + if (type == TYPE_FROM_STORIES) { + button.setOverlayText(LocaleController.getString("EnableStealthMode", R.string.EnableStealthMode), true, animated); + } else if (type == TYPE_FROM_DIALOGS) { + button.setOverlayText(LocaleController.getString(R.string.EnableStealthModeAndOpenStory), true, animated); + } button.overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); } else { long timeLeft = stealthMode.cooldown_until_date - ConnectionsManager.getInstance(currentAccount).getCurrentTime(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java index 9a7ec1caa2..3b52b97e8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -941,7 +941,7 @@ private void updateStoriesForFullPeer(long dialogId, List if (newStory instanceof TL_stories.TL_storyItemDeleted) { FileLog.d("StoriesController story is not found, but already deleted storyId=" + newStory.id); } else { - FileLog.d(" StoriesController add new story for full peer storyId=" + newStory.id); + FileLog.d("StoriesController add new story for full peer storyId=" + newStory.id); peerStories.stories.add(newStory); } } @@ -1153,6 +1153,31 @@ public void deleteStories(long dialogId, ArrayList storyIt } req.id.add(storyItem.id); } + if (dialogId >= 0) { + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); + if (userFull != null && userFull.stories != null) { + stories = userFull.stories; + } + } else { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId); + if (chatFull != null && chatFull.stories != null) { + stories = chatFull.stories; + } + } + for (int i = 0; i < storyItems.size(); ++i) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { + continue; + } + if (stories != null) { + for (int j = 0; j < stories.stories.size(); j++) { + if (stories.stories.get(j).id == storyItem.id) { + stories.stories.remove(j); + break; + } + } + } + } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { AndroidUtilities.runOnUIThread(this::invalidateStoryLimit); }); @@ -2374,6 +2399,7 @@ public void unlink(int id) { public final long dialogId; public final int type; + public final ArrayList pinnedIds = new ArrayList<>(); public final HashMap> groupedByDay = new HashMap<>(); public final ArrayList messageObjects = new ArrayList<>(); @@ -2420,9 +2446,19 @@ public void fill(boolean notify) { private void fill(ArrayList arrayList, boolean showPhotos, boolean showVideos) { tempArr.clear(); + if (type == TYPE_PINNED) { + for (int id : pinnedIds) { + MessageObject msg = messageObjectsMap.get(id); + if (filter(msg, showPhotos, showVideos)) { + tempArr.add(msg); + } + } + } int minId = Integer.MAX_VALUE; for (int id : loadedObjects) { MessageObject msg = messageObjectsMap.get(id); + if (type == TYPE_PINNED && pinnedIds.contains(id)) + continue; if (filter(msg, showPhotos, showVideos)) { tempArr.add(msg); } @@ -2434,6 +2470,8 @@ private void fill(ArrayList arrayList, boolean showPhotos, boolea Iterator i = cachedObjects.iterator(); while (i.hasNext() && (totalCount == -1 || tempArr.size() < totalCount)) { int id = i.next(); + if (type == TYPE_PINNED && pinnedIds.contains(id)) + continue; if (minId == Integer.MAX_VALUE || id < minId) { MessageObject msg = messageObjectsMap.get(id); if (filter(msg, showPhotos, showVideos)) { @@ -2477,6 +2515,7 @@ private void preloadCache() { final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); storage.getStorageQueue().postRunnable(() -> { SQLiteCursor cursor = null; + ArrayList pins = new ArrayList<>(); HashSet seen = new HashSet<>(); HashSet loadUserIds = new HashSet<>(); HashSet loadChatIds = new HashSet<>(); @@ -2485,7 +2524,7 @@ private void preloadCache() { final ArrayList loadedChats = new ArrayList<>(); try { SQLiteDatabase database = storage.getDatabase(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, seen FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, seen, pin FROM profile_stories WHERE dialog_id = %d AND type = %d ORDER BY story_id DESC", dialogId, type)); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -2529,6 +2568,10 @@ private void preloadCache() { if (cursor.intValue(1) == 1) { seen.add(storyItem.id); } + int pinIndex = cursor.intValue(2); + if (pinIndex > 0) { + pins.add(Utilities.clamp(pinIndex, pins.size() - 1, 0), storyItem.id); + } } } cursor.dispose(); @@ -2550,6 +2593,10 @@ private void preloadCache() { AndroidUtilities.runOnUIThread(() -> { FileLog.d("StoriesList "+type+"{"+ dialogId +"} preloadCache {" + storyItemMessageIds(cacheResult) + "}"); + + pinnedIds.clear(); + pinnedIds.addAll(pins); + preloading = false; MessagesController.getInstance(currentAccount).putUsers(loadedUsers, true); MessagesController.getInstance(currentAccount).putChats(loadedChats, true); @@ -2598,9 +2645,10 @@ private boolean removeObject(int storyId, boolean removeFromCache) { cachedObjects.remove(storyId); } loadedObjects.remove(storyId); + pinnedIds.remove((Object) storyId); if (messageObject != null) { long id = day(messageObject); - SortedSet group = groupedByDay.get(id); + Collection group = groupedByDay.get(id); if (group != null) { group.remove(storyId); if (group.isEmpty()) { @@ -2625,18 +2673,25 @@ public static long day(MessageObject messageObject) { return year * 10000L + month * 100L + day; } - public SortedSet getStoryDayGroup(MessageObject messageObject) { - return groupedByDay.get(day(messageObject)); - } - public ArrayList> getDays() { final ArrayList keys = new ArrayList<>(groupedByDay.keySet()); Collections.sort(keys, (a, b) -> (int) (b - a)); final ArrayList> days = new ArrayList<>(); + if (type == TYPE_PINNED && !pinnedIds.isEmpty()) { + days.add(new ArrayList<>(pinnedIds)); + } for (Long key : keys) { TreeSet storyIds = groupedByDay.get(key); if (storyIds != null) { - days.add(new ArrayList<>(storyIds)); + ArrayList ids = new ArrayList<>(storyIds); + if (type == TYPE_PINNED && !pinnedIds.isEmpty()) { + for (int id : pinnedIds) { + ids.remove((Object) id); + } + } + if (!ids.isEmpty()) { + days.add(ids); + } } } return days; @@ -2675,6 +2730,7 @@ private void saveCache() { saving = true; final ArrayList toSave = new ArrayList<>(); + final ArrayList pinnedIds = new ArrayList<>(this.pinnedIds); fill(toSave, true, true); final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); @@ -2684,7 +2740,7 @@ private void saveCache() { try { SQLiteDatabase database = storage.getDatabase(); database.executeFast(String.format(Locale.US, "DELETE FROM profile_stories WHERE dialog_id = %d AND type = %d", dialogId, type)).stepThis().dispose(); - state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?, ?)"); + state = database.executeFast("REPLACE INTO profile_stories VALUES(?, ?, ?, ?, ?, ?)"); for (int i = 0; i < toSave.size(); ++i) { MessageObject messageObject = toSave.get(i); @@ -2702,6 +2758,7 @@ private void saveCache() { state.bindByteBuffer(3, data); state.bindInteger(4, type); state.bindInteger(5, seenStories.contains(storyItem.id) ? 1 : 0); + state.bindInteger(6, 1 + pinnedIds.indexOf(storyItem.id)); state.step(); data.reuse(); } @@ -2812,11 +2869,14 @@ public boolean load(boolean force, final int count, List ids) { TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; for (int i = 0; i < stories.stories.size(); ++i) { TL_stories.StoryItem storyItem = stories.stories.get(i); - newMessageObjects.add(toMessageObject(storyItem)); + newMessageObjects.add(toMessageObject(storyItem, stories)); } AndroidUtilities.runOnUIThread(() -> { FileLog.d("StoriesList " + type + "{"+ dialogId +"} loaded {" + storyItemMessageIds(newMessageObjects) + "}"); + pinnedIds.clear(); + pinnedIds.addAll(stories.pinned_to_top); + MessagesController.getInstance(currentAccount).putUsers(stories.users, false); MessagesController.getInstance(currentAccount).putChats(stories.chats, false); MessagesStorage.getInstance(currentAccount).putUsersAndChats(stories.users, stories.chats, true, true); @@ -2960,7 +3020,7 @@ public void updateStories(List storyItems) { } } else { FileLog.d("StoriesList put story " + storyItem.id); - pushObject(toMessageObject(storyItem), false); + pushObject(toMessageObject(storyItem, null), false); if (totalCount != -1) { totalCount++; } @@ -2969,7 +3029,7 @@ public void updateStories(List storyItems) { MessageObject messageObject = messageObjectsMap.get(storyItem.id); if (messageObject == null || !equal(messageObject.storyItem, storyItem)) { FileLog.d("StoriesList update story " + storyItem.id); - messageObjectsMap.put(storyItem.id, toMessageObject(storyItem)); + messageObjectsMap.put(storyItem.id, toMessageObject(storyItem, null)); changed = true; } } @@ -2999,7 +3059,7 @@ public boolean equal(TL_stories.StoryItem a, TL_stories.StoryItem b) { ); } - private MessageObject toMessageObject(TL_stories.StoryItem storyItem) { + private MessageObject toMessageObject(TL_stories.StoryItem storyItem, TL_stories.TL_stories_stories stories) { storyItem.dialogId = dialogId; storyItem.messageId = storyItem.id; MessageObject msg = new MessageObject(currentAccount, storyItem); @@ -3033,6 +3093,86 @@ public int getCount() { return messageObjects.size(); } } + + public boolean isPinned(int storyId) { + if (type != TYPE_PINNED) return false; + return pinnedIds.contains(storyId); + } + + public boolean updatePinned(ArrayList ids, boolean pin) { + ArrayList newPinnedOrder = new ArrayList<>(pinnedIds); + for (int i = ids.size() - 1; i >= 0; --i) { + int id = ids.get(i); + if (pin && !newPinnedOrder.contains(id)) + newPinnedOrder.add(0, id); + else if (!pin && newPinnedOrder.contains(id)) + newPinnedOrder.remove((Object) id); + } + + final int limit = MessagesController.getInstance(currentAccount).storiesPinnedToTopCountMax; + boolean hitLimit = newPinnedOrder.size() > limit; + if (hitLimit) { + return true; +// newPinnedOrder.subList(limit, newPinnedOrder.size()).clear(); + } + + boolean changed = pinnedIds.size() != newPinnedOrder.size(); + if (!changed) { + for (int i = 0; i < pinnedIds.size(); ++i) { + if (pinnedIds.get(i) != newPinnedOrder.get(i)) { + changed = true; + break; + } + } + } + + if (changed) { + pinnedIds.clear(); + pinnedIds.addAll(newPinnedOrder); + fill(true); + TL_stories.TL_togglePinnedToTop req = new TL_stories.TL_togglePinnedToTop(); + req.id.addAll(pinnedIds); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + + })); + } + + return hitLimit; + } + + public void updatePinnedOrder(ArrayList ids, boolean apply) { + ArrayList newPinnedOrder = new ArrayList<>(ids); + + final int limit = MessagesController.getInstance(currentAccount).storiesPinnedToTopCountMax; + boolean hitLimit = newPinnedOrder.size() > limit; + if (hitLimit) { + newPinnedOrder.subList(limit, newPinnedOrder.size()).clear(); + } + + boolean changed = pinnedIds.size() != newPinnedOrder.size(); + if (!changed) { + for (int i = 0; i < pinnedIds.size(); ++i) { + if (pinnedIds.get(i) != newPinnedOrder.get(i)) { + changed = true; + break; + } + } + } + + pinnedIds.clear(); + pinnedIds.addAll(newPinnedOrder); + fill(false); + + if (apply) { + TL_stories.TL_togglePinnedToTop req = new TL_stories.TL_togglePinnedToTop(); + req.id.addAll(pinnedIds); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + + })); + } + } } private final Comparator peerStoriesComparator = (o1, o2) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java index 9be11843e2..c2700e77f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -194,6 +194,7 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto holder.drawAbove = (canvas, bounds, alpha, opening) -> { cell.drawDuration(canvas, bounds, alpha); cell.drawViews(canvas, bounds, alpha); + cell.drawPrivacy(canvas, bounds, alpha); if (fastScroll != null && fastScroll.isVisible && fastScroll.getVisibility() == View.VISIBLE) { canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); canvas.translate(loc[0], loc[1]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index abf0fc4483..0600c14e01 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -1710,7 +1710,7 @@ public void onAnimationEnd(Animator animation) { } } - private void checkSelfStoriesView() { + public void checkSelfStoriesView() { if (selfStoryViewsView == null) { selfStoryViewsView = new SelfStoryViewsView(containerView.getContext(), this); containerView.addView(selfStoryViewsView, 0); @@ -2140,6 +2140,11 @@ private void updateProgressToDismiss() { } } + private boolean showViewsAfterOpening; + public void showViewsAfterOpening() { + showViewsAfterOpening = true; + } + private void startOpenAnimation() { updateTransitionParams(); progressToOpen = 0f; @@ -2189,7 +2194,10 @@ public void onAnimationEnd(Animator animation) { peerStoriesView.updatePosition(); } - if (!SharedConfig.storiesIntroShown) { + if (showViewsAfterOpening) { + showViewsAfterOpening = false; + openViews(); + } else if (!SharedConfig.storiesIntroShown) { if (storiesIntro == null) { storiesIntro = new StoriesIntro(containerView.getContext(), windowView); storiesIntro.setAlpha(0f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java index e991d80812..d048ea6728 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java @@ -100,6 +100,10 @@ public ReactionWidget(TL_stories.TL_mediaAreaSuggestedReaction mediaArea) { } public void draw(Canvas canvas, ImageReceiver imageReceiver, float alpha) { + if (!imageHolder.isLoaded()) { + return; + } + float x = (float) (imageX + imageW * mediaArea.coordinates.x / 100); float y = (float) (imageY + imageH * mediaArea.coordinates.y / 100); float w = (float) (imageW * mediaArea.coordinates.w / 100); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java index b9e47e91e3..9ba4057fbc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ButtonWithCounterView.java @@ -60,7 +60,6 @@ public ButtonWithCounterView(Context context, boolean filled, Theme.ResourcesPro ScaleStateListAnimator.apply(this, .02f, 1.2f); rippleView = new View(context); - rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); addView(rippleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (filled) { @@ -77,14 +76,12 @@ public ButtonWithCounterView(Context context, boolean filled, Theme.ResourcesPro if (filled) { text.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); } - text.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); text.setGravity(Gravity.CENTER_HORIZONTAL); subText = new AnimatedTextView.AnimatedTextDrawable(true, true, false); subText.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT); subText.setCallback(this); subText.setTextSize(dp(12)); - subText.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); subText.setGravity(Gravity.CENTER_HORIZONTAL); countText = new AnimatedTextView.AnimatedTextDrawable(false, false, true); @@ -92,11 +89,15 @@ public ButtonWithCounterView(Context context, boolean filled, Theme.ResourcesPro countText.setCallback(this); countText.setTextSize(dp(12)); countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); - countText.setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); countText.setText(""); countText.setGravity(Gravity.CENTER_HORIZONTAL); setWillNotDraw(false); + updateColors(); + } + + public void disableRippleView() { + removeView(rippleView); } public void setColor(int color) { @@ -106,7 +107,11 @@ public void setColor(int color) { } public void updateColors() { - rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + if (filled) { + rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 8, 8)); + } else { + rippleView.setBackground(Theme.createRadSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), .10f), 8, 8)); + } text.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); subText.setTextColor(Theme.getColor(filled ? Theme.key_featuredStickers_buttonText : Theme.key_featuredStickers_addButton, resourcesProvider)); countText.setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); @@ -523,4 +528,9 @@ public void setTextAlpha(float v) { public void setGlobalAlpha(float v) { globalAlpha = ((int) (v * 255)); } + + public boolean wrapContentDynamic; + public void wrapContentDynamic() { + wrapContentDynamic = true; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java index 1b689d2b78..975d73d465 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java @@ -382,6 +382,10 @@ public static class PreparingVideoToast extends View { private float doneLayoutWidth, doneLayoutLeft; public PreparingVideoToast(Context context) { + this(context, LocaleController.getString(R.string.PreparingSticker)); + } + + public PreparingVideoToast(Context context, String text) { super(context); dimPaint.setColor(0x5a000000); @@ -401,7 +405,7 @@ public PreparingVideoToast(Context context) { textPaint.setTextSize(dp(14)); textPaint2.setTextSize(dpf2(14.66f)); - preparingLayout = new StaticLayout(LocaleController.getString("PreparingVideo"), textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1f, 0, false); + preparingLayout = new StaticLayout(text, textPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1f, 0, false); preparingLayoutWidth = preparingLayout.getLineCount() > 0 ? preparingLayout.getLineWidth(0) : 0; preparingLayoutLeft = preparingLayout.getLineCount() > 0 ? preparingLayout.getLineLeft(0) : 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java index bef5fd6e35..0cc09275fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java @@ -1,5 +1,6 @@ package org.telegram.ui.Stories.recorder; +import static org.telegram.messenger.AndroidUtilities.TYPEFACE_COURIER_NEW_BOLD; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.dpf2; import static org.telegram.messenger.AndroidUtilities.lerp; @@ -29,7 +30,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TypedValue; @@ -46,7 +46,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.GridLayoutManager; @@ -55,7 +54,6 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -84,7 +82,6 @@ import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.StickerSetNameCell; import org.telegram.ui.Components.AnimatedEmojiDrawable; -import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.BackupImageView; @@ -92,6 +89,7 @@ import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ButtonBounce; import org.telegram.ui.Components.CloseProgressDrawable2; +import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.DrawingInBackgroundThreadDrawable; import org.telegram.ui.Components.EditTextBoldCursor; @@ -111,6 +109,7 @@ import org.telegram.ui.Components.ViewPagerFixed; import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.NewContactBottomSheet; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.SelectAnimatedEmojiDialog; import org.telegram.ui.Stories.StoryReactionWidgetBackground; @@ -136,6 +135,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. private int categoryIndex = -1; public final TLRPC.Document widgets = new TLRPC.Document() {}; + public final TLRPC.Document plus = new TLRPC.Document() {}; abstract class IPage extends FrameLayout { public int currentType; @@ -227,6 +227,7 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { EmojiBottomSheet.this.categoryIndex = category; adapter.updateItems(query); }); + searchField.checkCategoriesView(PAGE_TYPE_GIFS, false); addView(searchField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); } @@ -576,6 +577,13 @@ public int getSpanSize(int position) { return; } TLRPC.Document document = position >= adapter.documents.size() ? null : adapter.documents.get(position); + if (document == plus) { + if (onPlusSelected != null) { + onPlusSelected.run(); + } + dismiss(); + return; + } long documentId = position >= adapter.documentIds.size() ? 0L : adapter.documentIds.get(position); if (document == null && view instanceof EmojiListView.EmojiImageView && ((EmojiListView.EmojiImageView) view).drawable != null) { document = ((EmojiListView.EmojiImageView) view).drawable.getDocument(); @@ -587,7 +595,7 @@ public int getSpanSize(int position) { return; } if (onDocumentSelected != null) { - onDocumentSelected.run(null, document, false); + onDocumentSelected.run(document != null ? adapter.setByDocumentId.get(document.id) : null, document, false); } dismiss(); }); @@ -743,23 +751,28 @@ public void bind(int type) { searchField.ignoreTextChange = true; searchField.editText.setText(""); searchField.ignoreTextChange = false; - searchField.categoriesListView.selectCategory(categoryIndex); - searchField.categoriesListView.scrollToSelected(); - StickerCategoriesListView.EmojiCategory category = searchField.categoriesListView.getSelectedCategory(); - if (category != null) { - adapter.query = searchField.categoriesListView.getSelectedCategory().emojis; - AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); - AndroidUtilities.runOnUIThread(adapter.searchRunnable); + if (searchField.categoriesListView != null) { + searchField.categoriesListView.selectCategory(categoryIndex); + searchField.categoriesListView.scrollToSelected(); + StickerCategoriesListView.EmojiCategory category = searchField.categoriesListView.getSelectedCategory(); + if (category != null) { + adapter.query = searchField.categoriesListView.getSelectedCategory().emojis; + AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); + AndroidUtilities.runOnUIThread(adapter.searchRunnable); + } } } else if (!TextUtils.isEmpty(query)) { searchField.editText.setText(query); - searchField.categoriesListView.selectCategory(null); - searchField.categoriesListView.scrollToStart(); + if (searchField.categoriesListView != null) { + searchField.categoriesListView.selectCategory(null); + searchField.categoriesListView.scrollToStart(); + } AndroidUtilities.cancelRunOnUIThread(adapter.searchRunnable); AndroidUtilities.runOnUIThread(adapter.searchRunnable); } else { searchField.clear(); } + searchField.checkCategoriesView(type, greeting); MediaDataController.getInstance(currentAccount).checkStickers(type == PAGE_TYPE_EMOJI ? MediaDataController.TYPE_EMOJIPACKS : MediaDataController.TYPE_IMAGE); } @@ -779,6 +792,7 @@ private class Adapter extends RecyclerView.Adapter { private int lastAllSetsCount; private final HashMap> allEmojis = new HashMap<>(); private final HashMap> packsBySet = new HashMap<>(); + private final HashMap setByDocumentId = new HashMap<>(); private final ArrayList allStickerSets = new ArrayList<>(); private final ArrayList stickerSets = new ArrayList<>(); @@ -826,6 +840,7 @@ private void updateItems(String query) { positionToSection.clear(); stickerSets.clear(); allStickerSets.clear(); + setByDocumentId.clear(); itemsCount++; // pan documents.add(null); packs.clear(); @@ -853,6 +868,9 @@ private void updateItems(String query) { recentSet = new TLRPC.TL_messages_stickerSet(); } recentSet.documents = recent; + if (onPlusSelected != null) { + recentSet.documents.add(0, plus); + } recentSet.set = new TLRPC.TL_stickerSet(); recentSet.set.title = LocaleController.getString("RecentStickers", R.string.RecentStickers); stickerSets.add(recentSet); @@ -874,6 +892,12 @@ private void updateItems(String query) { // emoji/stickers documents.addAll(set.documents); itemsCount += set.documents.size(); + Object parentObject = set; + if (set == recentSet) parentObject = "recent"; + else if (set == faveSet) parentObject = "fav"; + for (int j = 0; j < set.documents.size(); ++j) { + setByDocumentId.put(set.documents.get(j).id, parentObject); + } EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); pack.documents = set.documents; @@ -967,6 +991,9 @@ private void updateItems(String query) { // emoji/stickers documents.addAll(set.documents); itemsCount += set.documents.size(); + for (int k = 0; k < set.documents.size(); ++k) { + setByDocumentId.put(set.documents.get(k).id, set); + } EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); pack.documents = set.documents; @@ -1029,8 +1056,28 @@ private void updateItems(String query) { private HashSet searchDocumentIds = new HashSet<>(); private final Runnable searchRunnable = () -> { - final String thisQuery = query; final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); + final String thisQuery = query; + if ("premium".equalsIgnoreCase(thisQuery)) { + ArrayList premiumStickers = mediaDataController.getRecentStickers(MediaDataController.TYPE_PREMIUM_STICKERS); + itemsCount = 0; + documents.clear(); + documentIds.clear(); + positionToSection.clear(); + stickerSets.clear(); + itemsCount++; // pan + documents.add(null); + documentIds.add(0L); + documents.addAll(premiumStickers); + itemsCount += premiumStickers.size(); + activeQuery = query; + notifyDataSetChanged(); + + listView.scrollToPosition(0, 0); + searchField.showProgress(false); + tabsStrip.showSelected(false); + return; + } String[] lang = AndroidUtilities.getCurrentKeyboardLanguage(); if (lastLang == null || !Arrays.equals(lang, lastLang)) { MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(lang); @@ -1173,21 +1220,33 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } else if (viewType == VIEW_TYPE_EMOJI) { final TLRPC.Document document = position >= documents.size() ? null : documents.get(position); + EmojiListView.EmojiImageView imageView = (EmojiListView.EmojiImageView) holder.itemView; + if (document == plus) { + imageView.setSticker(null); + Drawable circle = Theme.createRoundRectDrawable(dp(28), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelIcon), .12f)); + Drawable drawable = getResources().getDrawable(R.drawable.filled_add_sticker).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_emojiPanelIcon), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); + combinedDrawable.setCustomSize(dp(56), dp(56)); + combinedDrawable.setIconSize(dp(24), dp(24)); + combinedDrawable.setCenter(true); + imageView.setDrawable(combinedDrawable); + return; + } final long documentId = position >= documentIds.size() ? 0L : documentIds.get(position); if (document == null && documentId == 0) { return; } - EmojiListView.EmojiImageView imageView = (EmojiListView.EmojiImageView) holder.itemView; if (currentType == PAGE_TYPE_EMOJI) { if (document != null) { imageView.setSticker(null); - imageView.setEmoji(document); + imageView.setEmoji(document, currentType == PAGE_TYPE_STICKERS); } else { imageView.setSticker(null); - imageView.setEmojiId(documentId); + imageView.setEmojiId(documentId, currentType == PAGE_TYPE_STICKERS); } } else { - imageView.setEmoji(null); + imageView.setEmoji(null, currentType == PAGE_TYPE_STICKERS); imageView.setSticker(document); } } else if (viewType == VIEW_TYPE_NOT_FOUND) { @@ -1318,16 +1377,18 @@ protected boolean checkAudioPermission(Runnable granted) { private TabsView tabsView; private float maxPadding = -1; private final boolean onlyStickers; + private final boolean greeting; // private final GestureDetector gestureDetector; private boolean wasKeyboardVisible; public static int savedPosition = 1; - public EmojiBottomSheet(Context context, boolean onlyStickers, Theme.ResourcesProvider resourcesProvider) { + public EmojiBottomSheet(Context context, boolean onlyStickers, Theme.ResourcesProvider resourcesProvider, boolean greeting) { super(context, true, resourcesProvider); this.onlyStickers = onlyStickers; + this.greeting = greeting; useSmoothKeyboard = true; fixNavigationBar(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); @@ -1410,6 +1471,7 @@ public void bindView(View view, int position, int viewType) { MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_IMAGE); MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_IMAGE, false, true, false); MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_FAVE, false, true, false); + MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_PREMIUM_STICKERS, false, true, false); } public void closeKeyboard() { @@ -1594,12 +1656,26 @@ public int getContainerViewHeight() { return (int) (containerView.getMeasuredHeight() - viewPager.getY()); } - private Utilities.Callback3 onDocumentSelected; - public EmojiBottomSheet whenDocumentSelected(Utilities.Callback3 listener) { + private Utilities.Callback3Return onDocumentSelected; + private Runnable onPlusSelected; + public EmojiBottomSheet whenDocumentSelected(Utilities.Callback3Return listener) { this.onDocumentSelected = listener; return this; } private Utilities.Callback onWidgetSelected; + + public EmojiBottomSheet whenPlusSelected(Runnable listener) { + this.onPlusSelected = listener; + View[] pages = viewPager.getViewPages(); + for (int i = 0; i < pages.length; ++i) { + View view = pages[i]; + if (view instanceof Page) { + Page page = (Page) view; + page.adapter.update(); + } + } + return this; + } public EmojiBottomSheet whenWidgetSelected(Utilities.Callback listener) { this.onWidgetSelected = listener; View[] pages = viewPager.getViewPages(); @@ -1625,8 +1701,8 @@ public static class EmojiImageView extends View { public boolean emoji; private final int currentAccount = UserConfig.selectedAccount; - private final EmojiListView listView; public AnimatedEmojiDrawable drawable; + private final EmojiListView listView; public ImageReceiver imageReceiver; private long documentId; @@ -1641,7 +1717,25 @@ public EmojiImageView(Context context, EmojiListView parent) { this.listView = parent; } - public void setEmoji(TLRPC.Document document) { + public void setDrawable(Drawable drawable) { + if (this.drawable != null) { + this.drawable.removeView(this); + } + this.drawable = null; + documentId = 0; + emoji = false; + if (imageReceiver == null) { + imageReceiver = new ImageReceiver(); + imageReceiver.setLayerNum(7); + imageReceiver.setAspectFit(true); + if (attached) { + imageReceiver.onAttachedToWindow(); + } + } + imageReceiver.setImageBitmap(drawable); + } + + public void setEmoji(TLRPC.Document document, boolean isSticker) { if (documentId == (document == null ? 0 : document.id)) { return; } @@ -1651,7 +1745,7 @@ public void setEmoji(TLRPC.Document document) { if (document != null) { emoji = true; documentId = document.id; - drawable = AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, document); + drawable = AnimatedEmojiDrawable.make(currentAccount, getCacheType(isSticker), document); if (attached) { drawable.addView(this); } @@ -1667,7 +1761,7 @@ public void invalidate() { listView.invalidate(); } - public void setEmojiId(long documentId) { + public void setEmojiId(long documentId, boolean isSticker) { if (this.documentId == documentId) { return; } @@ -1677,7 +1771,7 @@ public void setEmojiId(long documentId) { if (documentId != 0) { emoji = true; this.documentId = documentId; - drawable = AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW, documentId); + drawable = AnimatedEmojiDrawable.make(currentAccount, getCacheType(isSticker), documentId); if (attached) { drawable.addView(this); } @@ -1721,6 +1815,9 @@ public void setSticker(TLRPC.Document document) { if ("video/webm".equals(document.mime_type)) { filter += "_" + ImageLoader.AUTOPLAY_FILTER; } + if (!LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_KEYBOARD)) { + filter += "_firstframe"; + } // if (svgThumb != null) { // svgThumb.overrideWidthAndHeight(512, 512); // } @@ -2189,7 +2286,9 @@ private static class SearchField extends FrameLayout { private final FrameLayout inputBox; private final EditTextBoldCursor editText; - private final StickerCategoriesListView categoriesListView; + private int categoriesListViewType = -1; + @Nullable + private StickerCategoriesListView categoriesListView; private boolean clearVisible; private final ImageView clear; @@ -2304,18 +2403,70 @@ public void afterTextChanged(Editable s) { } }); - categoriesListView = new StickerCategoriesListView(context, null, StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { + clear = new ImageView(context); + clear.setScaleType(ImageView.ScaleType.CENTER); + clear.setImageDrawable(new CloseProgressDrawable2(1.25f) { + { setSide(AndroidUtilities.dp(7)); } + @Override + protected int getCurrentColor() { + return Theme.getColor(Theme.key_chat_emojiSearchIcon, resourcesProvider); + } + }); + clear.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), Theme.RIPPLE_MASK_CIRCLE_20DP, AndroidUtilities.dp(15))); + clear.setAlpha(0f); + clear.setScaleX(.7f); + clear.setScaleY(.7f); + clear.setVisibility(View.GONE); + clear.setOnClickListener(e -> clear()); + box.addView(clear, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); + + + searchImageView.setOnClickListener(e -> { + if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_BACK) { + clear(); + if (categoriesListView != null) { + categoriesListView.scrollToStart(); + } + } else if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_SEARCH) { + editText.requestFocus(); + } + }); + } + + public void checkCategoriesView(int type, boolean greeting) { + if (categoriesListViewType == type && categoriesListView != null) return; + if (categoriesListView != null) { + box.removeView(categoriesListView); + } + categoriesListView = new StickerCategoriesListView(getContext(), null, type == PAGE_TYPE_STICKERS ? StickerCategoriesListView.CategoriesType.STICKERS : StickerCategoriesListView.CategoriesType.DEFAULT, resourcesProvider) { @Override public void selectCategory(int categoryIndex) { super.selectCategory(categoryIndex); -// if (type == 1 && emojiTabs != null) { -// emojiTabs.showSelected(categoriesListView.getSelectedCategory() == null); -// } else if (type == 0 && stickersTab != null) { -// stickersTab.showSelected(categoriesListView.getSelectedCategory() == null); -// } updateButton(); } + @Override + protected EmojiCategory[] preprocessCategories(EmojiCategory[] categories) { + if (categories != null && greeting) { + int index = -1; + for (int i = 0; i < categories.length; ++i) { + if (categories[i] != null && categories[i].greeting) { + index = i; + break; + } + } + if (index >= 0) { + EmojiCategory[] newCategories = new EmojiCategory[categories.length]; + newCategories[0] = categories[index]; + for (int i = 1; i < newCategories.length; ++i) { + newCategories[i] = categories[i <= index ? i - 1 : i]; + } + return newCategories; + } + } + return categories; + } + @Override protected boolean isTabIconsAnimationEnabled(boolean loaded) { return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS); @@ -2325,39 +2476,9 @@ protected boolean isTabIconsAnimationEnabled(boolean loaded) { categoriesListView.setOnScrollIntoOccupiedWidth(scrolled -> { editText.animate().cancel(); editText.setTranslationX(-Math.max(0, scrolled)); -// showInputBoxGradient(scrolled > 0); updateButton(); }); -// categoriesListView.setOnTouchListener(new OnTouchListener() { -// @Override -// public boolean onTouch(View v, MotionEvent event) { -//// if (event.getAction() == MotionEvent.ACTION_DOWN) { -//// ignorePagerScroll = true; -//// } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { -//// ignorePagerScroll = false; -//// } -// return false; -// } -// }); categoriesListView.setOnCategoryClick(category -> { -// if (category == recent) { -//// showInputBoxGradient(false); -// categoriesListView.selectCategory(recent); -// gifSearchField.searchEditText.setText(""); -// gifLayoutManager.scrollToPositionWithOffset(0, 0); -// return; -// } else -// if (category == trending) { -//// showInputBoxGradient(false); -// gifSearchField.searchEditText.setText(""); -// gifLayoutManager.scrollToPositionWithOffset(gifAdapter.trendingSectionItem, -dp(4)); -// categoriesListView.selectCategory(trending); -// final ArrayList gifSearchEmojies = MessagesController.getInstance(currentAccount).gifSearchEmojies; -// if (!gifSearchEmojies.isEmpty()) { -// gifSearchPreloader.preload(gifSearchEmojies.get(0)); -// } -// return; -// } if (categoriesListView.getSelectedCategory() == category) { categoriesListView.selectCategory(null); search(null, -1); @@ -2366,34 +2487,7 @@ protected boolean isTabIconsAnimationEnabled(boolean loaded) { search(category.emojis, categoriesListView.getCategoryIndex()); } }); - box.addView(categoriesListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 36, 0, 0, 0)); - - clear = new ImageView(context); - clear.setScaleType(ImageView.ScaleType.CENTER); - clear.setImageDrawable(new CloseProgressDrawable2(1.25f) { - { setSide(AndroidUtilities.dp(7)); } - @Override - protected int getCurrentColor() { - return Theme.getColor(Theme.key_chat_emojiSearchIcon, resourcesProvider); - } - }); - clear.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), Theme.RIPPLE_MASK_CIRCLE_20DP, AndroidUtilities.dp(15))); - clear.setAlpha(0f); - clear.setScaleX(.7f); - clear.setScaleY(.7f); - clear.setVisibility(View.GONE); - clear.setOnClickListener(e -> clear()); - box.addView(clear, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); - - - searchImageView.setOnClickListener(e -> { - if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_BACK) { - clear(); - categoriesListView.scrollToStart(); - } else if (searchImageDrawable.getIconState() == SearchStateDrawable.State.STATE_SEARCH) { - editText.requestFocus(); - } - }); + box.addView(categoriesListView, Math.max(0, box.getChildCount() - 1), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 36, 0, 0, 0)); } private void updateButton() { @@ -2412,7 +2506,7 @@ public void showProgress(boolean progress) { private void updateButton(boolean force) { if (!isprogress || editText.length() == 0 && (categoriesListView == null || categoriesListView.getSelectedCategory() == null) || force) { - boolean backButton = editText.length() > 0 || categoriesListView != null && categoriesListView.isCategoriesShown() && (categoriesListView.isScrolledIntoOccupiedWidth() || categoriesListView.getSelectedCategory() != null); + boolean backButton = editText.length() > 0 || categoriesListView != null && categoriesListView.isCategoriesShown() && (categoriesListView != null && categoriesListView.isScrolledIntoOccupiedWidth() || categoriesListView.getSelectedCategory() != null); searchImageDrawable.setIconState(backButton ? SearchStateDrawable.State.STATE_BACK : SearchStateDrawable.State.STATE_SEARCH); isprogress = false; } @@ -2440,7 +2534,9 @@ private void search(String query, int categoryIndex) { private void clear() { editText.setText(""); search(null, -1); - categoriesListView.selectCategory(null); + if (categoriesListView != null) { + categoriesListView.selectCategory(null); + } } } @@ -2900,4 +2996,9 @@ protected void onDetachedFromWindow() { } } } + + public static int getCacheType(boolean stickers) { + return LiteMode.isEnabled(stickers ? LiteMode.FLAG_ANIMATED_STICKERS_KEYBOARD : LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD) ? + AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW : AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java index 3f41bd3718..3e5b34cce6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java @@ -42,7 +42,6 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -67,7 +66,6 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.DialogObject; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; @@ -1479,7 +1477,7 @@ public void onReactionClicked(View view, ReactionsLayoutInBubble.VisibleReaction showReactionsLayout(false); } }); - reactionLayout.setMessage(null, null); + reactionLayout.setMessage(null, null, true); } reactionLayout.setFragment(LaunchActivity.getLastFragment()); reactionForEntity = entityView; @@ -1758,7 +1756,7 @@ private void openStickersView() { detectFaces(); } }, 350); - EmojiBottomSheet alert = emojiPopup = new EmojiBottomSheet(getContext(), false, resourcesProvider) { + EmojiBottomSheet alert = emojiPopup = new EmojiBottomSheet(getContext(), false, resourcesProvider, false) { @Override public void onDismissAnimationStart() { super.onDismissAnimationStart(); @@ -1817,6 +1815,7 @@ protected boolean checkAudioPermission(Runnable granted) { stickerView.setScale(1.5f); } appearAnimation(stickerView); + return true; }); alert.whenWidgetSelected(widgetId -> { if (widgetId == EmojiBottomSheet.WIDGET_LOCATION) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index 615b2879da..b87c948dec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -186,6 +186,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private boolean wasSend; private long wasSendPeer = 0; private ClosingViewProvider closingSourceProvider; + private Runnable closeListener; public static StoryRecorder getInstance(Activity activity, int currentAccount) { if (instance != null && (instance.activity != activity || instance.currentAccount != currentAccount)) { @@ -433,6 +434,11 @@ protected void drawAbove(Canvas canvas, float alpha) { } } + public StoryRecorder whenSent(Runnable listener) { + closeListener = listener; + return this; + } + public StoryRecorder closeToWhenSent(ClosingViewProvider closingSourceProvider) { this.closingSourceProvider = closingSourceProvider; return this; @@ -2736,6 +2742,10 @@ private void uploadInternal(boolean asStory) { fromSourceView.show(); fromSourceView = null; } + if (closeListener != null) { + closeListener.run(); + closeListener = null; + } fromSourceView = closingSourceProvider != null ? closingSourceProvider.getView(finalSendAsDialogId) : null; if (fromSourceView != null) { openType = fromSourceView.type; @@ -3044,6 +3054,9 @@ public void onVideoRecordStart(boolean byLongPress, Runnable whenStarted) { } private void startRecording(boolean byLongPress, Runnable whenStarted) { + if (cameraView == null) { + return; + } CameraController.getInstance().recordVideo(cameraView.getCameraSessionObject(), outputFile, false, (thumbPath, duration) -> { if (recordControl != null) { recordControl.stopRecordingLoading(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java index c1d3862e4d..12183e006e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/UserInfoActivity.java @@ -31,6 +31,8 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Business.LocationActivity; +import org.telegram.ui.Business.OpeningHoursActivity; import org.telegram.ui.Cells.EditTextCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BottomSheetWithRecyclerListView; @@ -145,16 +147,18 @@ public void onItemClick(int id) { private static final int BUTTON_BIRTHDAY = 1; private static final int BUTTON_REMOVE_BIRTHDAY = 2; private static final int BUTTON_CHANNEL = 3; + private static final int BUTTON_HOURS = 4; + private static final int BUTTON_LOCATION = 5; @Override protected void fillItems(ArrayList items, UniversalAdapter adapter) { items.add(UItem.asHeader(getString(R.string.EditProfileName))); items.add(UItem.asCustom(firstNameEdit)); items.add(UItem.asCustom(lastNameEdit)); - items.add(UItem.asShadow(null)); + items.add(UItem.asShadow(-1, null)); items.add(UItem.asHeader(getString(R.string.EditProfileChannel))); items.add(UItem.asButton(BUTTON_CHANNEL, getString(R.string.EditProfileChannelTitle), channel == null ? getString(R.string.EditProfileChannelAdd) : channel.title)); - items.add(UItem.asShadow(null)); + items.add(UItem.asShadow(-2, null)); items.add(UItem.asHeader(getString(R.string.EditProfileBio))); items.add(UItem.asCustom(bioEdit)); items.add(UItem.asShadow(bioInfo)); @@ -184,6 +188,15 @@ protected void fillItems(ArrayList items, UniversalAdapter adapter) { } } items.add(UItem.asShadow(birthdayInfo)); + if (hadLocation) { + items.add(UItem.asButton(BUTTON_HOURS, R.drawable.menu_premium_clock, getString(R.string.EditProfileHours))); + } + if (hadLocation) { + items.add(UItem.asButton(BUTTON_LOCATION, R.drawable.msg_map, getString(R.string.EditProfileLocation))); + } + if (hadLocation || hadHours) { + items.add(UItem.asShadow(-3, null)); + } } public static String birthdayString(TLRPC.TL_birthday birthday) { @@ -251,6 +264,10 @@ protected void onClick(UItem item, View view, int position, float x, float y) { // listView.adapter.update(true); // } // })); + } else if (item.id == BUTTON_LOCATION) { + presentFragment(new LocationActivity()); + } else if (item.id == BUTTON_HOURS) { + presentFragment(new OpeningHoursActivity()); } } @@ -295,7 +312,9 @@ public void onResume() { private TLRPC.TL_birthday birthday; private TLRPC.Chat channel; - private AdminedChannelsFetcher channels = new AdminedChannelsFetcher(currentAccount); + private boolean hadHours, hadLocation; + + private AdminedChannelsFetcher channels = new AdminedChannelsFetcher(currentAccount, true); private boolean valueSet; private void setValue() { @@ -328,6 +347,8 @@ private void setValue() { currentChannel = 0; channel = null; } + hadHours = userFull.business_work_hours != null; + hadLocation = userFull.business_location != null; checkDone(true); if (listView != null && listView.adapter != null) { @@ -490,14 +511,16 @@ private void processDone(boolean error) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_NAME); } - private static class AdminedChannelsFetcher { + public static class AdminedChannelsFetcher { public final int currentAccount; - public AdminedChannelsFetcher(int currentAccount) { + public final boolean for_personal; + public AdminedChannelsFetcher(int currentAccount, boolean for_personal) { this.currentAccount = currentAccount; + this.for_personal = for_personal; } public boolean loaded, loading; - public ArrayList chats = new ArrayList<>(); + public final ArrayList chats = new ArrayList<>(); public void invalidate() { loaded = false; @@ -507,7 +530,7 @@ public void fetch() { if (loaded || loading) return; loading = true; TLRPC.TL_channels_getAdminedPublicChannels req = new TLRPC.TL_channels_getAdminedPublicChannels(); - req.for_personal = true; + req.for_personal = for_personal; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (res instanceof TLRPC.messages_Chats) { chats.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java b/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java index 7f94bfd5ad..fe91a3a5df 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/bots/BotBiometry.java @@ -134,7 +134,9 @@ public void updateToken(String reason, String token, Utilities.Callback if (result != null) { try { BiometricPrompt.CryptoObject cryptoObject = result.getCryptoObject(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + if (TextUtils.isEmpty(token)) { + encrypted_token = null; + } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { encrypted_token = token; } else { if (cryptoObject == null) { diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt index 228f844d0e..9e855cf0a3 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/parts/MessageTrans.kt @@ -25,7 +25,7 @@ fun MessageObject.toRawString(): String { if (messageOwner.media is TLRPC.TL_messageMediaPoll) { val poll = (messageOwner.media as TLRPC.TL_messageMediaPoll).poll - content = poll.question + content = poll.question.text content += "\n" for (answer in poll.answers) { @@ -55,16 +55,16 @@ fun MessageObject.translateFinished(locale: Locale): Int { val pool = (messageOwner.media as TLRPC.TL_messageMediaPoll).poll - val question = db.query(pool.question) ?: return 0 + val question = db.query(pool.question.text) ?: return 0 pool.translatedQuestion = - "${if (!NaConfig.hideOriginAfterTranslation.Bool()) pool.question + "\n\n--------\n\n" else ""}$question" + "${if (!NaConfig.hideOriginAfterTranslation.Bool()) pool.question.text + "\n\n--------\n\n" else ""}$question" pool.answers.forEach { - val answer = db.query(it.text) ?: return 0 + val answer = db.query(it.text.text) ?: return 0 - it.translatedText = it.text + " | " + answer + it.translatedText = it.text.text + " | " + answer } @@ -175,7 +175,7 @@ fun ChatActivity.translateMessages(target: Locale = NekoConfig.translateToLang.S val pool = (selectedObject.messageOwner.media as TLRPC.TL_messageMediaPoll).poll - var question = db.query(pool.question) + var question = db.query(pool.question.text) if (question == null) { @@ -183,7 +183,7 @@ fun ChatActivity.translateMessages(target: Locale = NekoConfig.translateToLang.S runCatching { - question = Translator.translate(target, pool.question) + question = Translator.translate(target, pool.question.text) }.onFailure { @@ -209,11 +209,11 @@ fun ChatActivity.translateMessages(target: Locale = NekoConfig.translateToLang.S } pool.translatedQuestion = - "${if (!NaConfig.hideOriginAfterTranslation.Bool()) pool.question + "\n\n--------\n\n" else ""}$question" + "${if (!NaConfig.hideOriginAfterTranslation.Bool()) pool.question.text + "\n\n--------\n\n" else ""}$question" pool.answers.forEach { - var answer = db.query(it.text) + var answer = db.query(it.text.text) if (answer == null) { @@ -221,7 +221,7 @@ fun ChatActivity.translateMessages(target: Locale = NekoConfig.translateToLang.S runCatching { - answer = Translator.translate(target, it.text) + answer = Translator.translate(target, it.text.text) }.onFailure { e -> @@ -246,7 +246,7 @@ fun ChatActivity.translateMessages(target: Locale = NekoConfig.translateToLang.S } - it.translatedText = answer + " | " + it.text + it.translatedText = answer + " | " + it.text.text } diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java index 1595f68709..37e069e005 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java @@ -790,7 +790,7 @@ private void showDeleteMenuAlert() { TextCheckCell textCell = new TextCheckCell(context); switch (a) { case 0: { - textCell.setTextAndCheck(LocaleController.getString("DeleteBanUser", R.string.DeleteBanUser), checks[a], false); + textCell.setTextAndCheck(LocaleController.getString("DeleteBanUsers", R.string.DeleteBanUsers), checks[a], false); break; } case 1: { diff --git a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/MessageHelper.kt b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/MessageHelper.kt index 6177c6277e..2dac47b726 100644 --- a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/MessageHelper.kt +++ b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/MessageHelper.kt @@ -6,6 +6,8 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Build +import android.text.SpannableStringBuilder +import android.text.Spanned import android.text.TextUtils import androidx.core.content.FileProvider import org.telegram.messenger.AndroidUtilities @@ -19,6 +21,7 @@ import org.telegram.messenger.FileLog import org.telegram.messenger.LocaleController import org.telegram.messenger.MediaDataController import org.telegram.messenger.MessageObject +import org.telegram.messenger.R import org.telegram.messenger.UserConfig import org.telegram.tgnet.TLRPC.Chat import org.telegram.tgnet.TLRPC.TL_messageEntityBankCard @@ -30,13 +33,19 @@ import org.telegram.tgnet.TLRPC.TL_messageEntityMention import org.telegram.tgnet.TLRPC.TL_messageEntityPhone import org.telegram.tgnet.TLRPC.TL_messageEntityUrl import org.telegram.tgnet.TLRPC.TL_messageMediaPoll +import org.telegram.ui.ActionBar.Theme import org.telegram.ui.ChatActivity +import org.telegram.ui.Components.ColoredImageSpan import xyz.nextalone.nagram.NaConfig import java.io.File import java.io.FileOutputStream +import java.util.Date object MessageHelper { + + private val spannedStrings = arrayOfNulls(5) + fun getPathToMessage(messageObject: MessageObject): File? { var path = messageObject.messageOwner.attachPath if (!TextUtils.isEmpty(path)) { @@ -248,10 +257,10 @@ object MessageHelper { fun getMessagePlainText(messageObject: MessageObject): String { val message: String = if (messageObject.isPoll) { val poll = (messageObject.messageOwner.media as TL_messageMediaPoll).poll - val pollText = StringBuilder(poll.question).append("\n") + val pollText = StringBuilder(poll.question.text).append("\n") for (answer in poll.answers) { pollText.append("\n\uD83D\uDD18 ") - pollText.append(answer.text) + pollText.append(answer.text.text) } pollText.toString() } else if (messageObject.isVoiceTranscriptionOpen) { @@ -261,4 +270,42 @@ object MessageHelper { } return message } + + private fun formatTime(timestamp: Int): String { + return LocaleController.formatString(R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(Date(timestamp * 1000L)), LocaleController.getInstance().formatterDay.format(Date(timestamp * 1000L))) + } + + fun getTimeHintText(messageObject: MessageObject): CharSequence { + val text = SpannableStringBuilder() + if (spannedStrings[3] == null) { + spannedStrings[3] = SpannableStringBuilder("\u200B") + spannedStrings[3]?.setSpan(ColoredImageSpan(Theme.chat_timeHintSentDrawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + text.append(spannedStrings[3]) + text.append(' ') + text.append(formatTime(messageObject.messageOwner.date)) + if (messageObject.messageOwner.edit_date != 0) { + text.append("\n") + if (spannedStrings[1] == null) { + spannedStrings[1] = SpannableStringBuilder("\u200B") + spannedStrings[1]?.setSpan(ColoredImageSpan(Theme.chat_editDrawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + text.append(spannedStrings[1]) + text.append(' ') + text.append(formatTime(messageObject.messageOwner.edit_date)) + } + if (messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.date != 0) { + text.append("\n") + if (spannedStrings[4] == null) { + spannedStrings[4] = SpannableStringBuilder("\u200B") + val span = ColoredImageSpan(Theme.chat_timeHintForwardDrawable) + span.setSize(AndroidUtilities.dp(12f)) + spannedStrings[4]?.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + text.append(spannedStrings[4]) + text.append(' ') + text.append(formatTime(messageObject.messageOwner.fwd_from.date)) + } + return text + } } diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png new file mode 100644 index 0000000000..bc79a6ec77 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_extend_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png new file mode 100644 index 0000000000..68b42e964b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_location_forever.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png new file mode 100644 index 0000000000..12c43b9721 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_stop_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-hdpi/large_log_actions.png new file mode 100644 index 0000000000..89a977be43 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/large_log_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-hdpi/left_status_profile.png new file mode 100644 index 0000000000..af74317b88 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/left_status_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png new file mode 100644 index 0000000000..c10494655f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/media_button_erase.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png new file mode 100644 index 0000000000..66009667d6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/media_button_restore.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png new file mode 100644 index 0000000000..6578b283cf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/media_button_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png new file mode 100644 index 0000000000..7f7acef8a8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/media_sticker_stroke.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_birthday.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_birthday.png new file mode 100644 index 0000000000..697cb3a174 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_birthday.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png new file mode 100644 index 0000000000..377ca4a58f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png new file mode 100644 index 0000000000..394cfe2f0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_profile_colors_locked.png differ diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-hdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-hdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-hdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png new file mode 100644 index 0000000000..194c013d7f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_username_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_username_set.png new file mode 100644 index 0000000000..f3dae9065f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_username_set.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_extend_location.png new file mode 100644 index 0000000000..d61f44ae22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_extend_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png new file mode 100644 index 0000000000..9542a68d0f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_location_forever.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png new file mode 100644 index 0000000000..ee5f790adb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_stop_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png new file mode 100644 index 0000000000..41e266dd5c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/large_log_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png new file mode 100644 index 0000000000..06e1b645d4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/left_status_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-mdpi/media_button_erase.png new file mode 100644 index 0000000000..569802025d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/media_button_erase.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png new file mode 100644 index 0000000000..1150e2b8bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/media_button_restore.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png new file mode 100644 index 0000000000..e27bdb34f1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/media_button_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png new file mode 100644 index 0000000000..c65e16cd03 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/media_sticker_stroke.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png new file mode 100644 index 0000000000..65912197d0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_birthday.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors.png new file mode 100644 index 0000000000..b31bdd94d9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors_locked.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors_locked.png new file mode 100644 index 0000000000..2f1e76de4a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_profile_colors_locked.png differ diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-mdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-mdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-mdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png new file mode 100644 index 0000000000..3d7bfda3e5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png new file mode 100644 index 0000000000..0c9abc3216 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_username_set.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_extend_location.png new file mode 100644 index 0000000000..565be3b76d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_extend_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png new file mode 100644 index 0000000000..c79e516943 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_location_forever.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_stop_location.png new file mode 100644 index 0000000000..448e3c5a87 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_stop_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png new file mode 100644 index 0000000000..9c80bd1b22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/large_log_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png new file mode 100644 index 0000000000..577e619343 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/left_status_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_erase.png new file mode 100644 index 0000000000..3e1167081a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_erase.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png new file mode 100644 index 0000000000..ee2b87758b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_restore.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png new file mode 100644 index 0000000000..b2bf2a8c0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/media_button_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png new file mode 100644 index 0000000000..d390a1bb87 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/media_sticker_stroke.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_birthday.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_birthday.png new file mode 100644 index 0000000000..641d3daaea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_birthday.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png new file mode 100644 index 0000000000..c775f7d6be Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors_locked.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors_locked.png new file mode 100644 index 0000000000..aae9a3cd73 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_profile_colors_locked.png differ diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-xhdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-xhdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-xhdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png new file mode 100644 index 0000000000..2c1bd2ee78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png new file mode 100644 index 0000000000..9a4a5d71ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_username_set.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png new file mode 100644 index 0000000000..ed72b0b95b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_extend_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png new file mode 100644 index 0000000000..15d8905cc0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_location_forever.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_stop_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_stop_location.png new file mode 100644 index 0000000000..5c85816a7f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_stop_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png new file mode 100644 index 0000000000..609d815f0f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/large_log_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png new file mode 100644 index 0000000000..869d4874b1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/left_status_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png new file mode 100644 index 0000000000..40b40c9c6d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_erase.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png new file mode 100644 index 0000000000..868f20231b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_restore.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_undo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_undo.png new file mode 100644 index 0000000000..603c0623da Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_button_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png new file mode 100644 index 0000000000..159f44b9c9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_sticker_stroke.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_birthday.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_birthday.png new file mode 100644 index 0000000000..25e06da49c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_birthday.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors.png new file mode 100644 index 0000000000..355be5bb92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors_locked.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors_locked.png new file mode 100644 index 0000000000..764c9904eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_profile_colors_locked.png differ diff --git a/TMessagesProj_AppStandalone/src/main/res/drawable-xxhdpi/menu_storage_path.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_storage_path.png similarity index 100% rename from TMessagesProj_AppStandalone/src/main/res/drawable-xxhdpi/menu_storage_path.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/menu_storage_path.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png new file mode 100644 index 0000000000..5d35379ea8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png new file mode 100644 index 0000000000..f3fb0a53aa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_username_set.png differ diff --git a/TMessagesProj/src/main/res/raw/bubble.json b/TMessagesProj/src/main/res/raw/bubble.json new file mode 100644 index 0000000000..76098aabc1 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/bubble.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":180,"w":512,"h":512,"nm":"Speech Balloon (@syrreel)","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[15.424]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":21,"s":[-9.581]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[2.745]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[-0.778]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":66,"s":[0.225]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":81,"s":[-0.065]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0.018]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":111,"s":[-0.005]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":125,"s":[0.002]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":153,"s":[0]},{"t":166,"s":[0]}]},"p":{"a":0,"k":[83.03,458.311,0]},"a":{"a":0,"k":[60,60,0]},"s":{"a":0,"k":[92.918,92.918,100]}},"ao":0,"ef":[{"ty":5,"nm":"Rotation - Overshoot","np":3,"mn":"ADBE Slider Control","ix":1,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":20,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"Rotation - Bounce","np":3,"mn":"ADBE Slider Control","ix":2,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":40,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]},{"ty":5,"nm":"Rotation - Friction","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":180,"x":"var $bm_rt;\n$bm_rt = clamp(value, 0, 100);"}}]}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Layer 13","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[91.192,-41.909,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-3.207,-1.179]],"o":[[0,0],[0,0]],"v":[[-3.454,-1.419],[3.454,1.419]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.466666668653,0.466666668653,0.466666668653,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Layer 12","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[179.494,-5.882,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[5.006,1.527]],"o":[[0,0],[0,0]],"v":[[4.66,1.105],[-4.66,-1.105]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.466666668653,0.466666668653,0.466666668653,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Layer 11","parent":1,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":37,"s":[322.869,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":47,"s":[322.864,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":94,"s":[322.861,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":101.494,"s":[322.869,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":114.74,"s":[322.864,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"t":177,"s":[322.861,-182.443,0]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-9.934],[9.934,0],[0,9.934],[-9.934,0]],"o":[[0,9.934],[-9.934,0],[0,-9.934],[9.934,0]],"v":[[17.986,0],[0,17.986],[-17.986,0],[0,-17.986]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211765006185,0.211765006185,0.211765006185,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Layer 10","parent":1,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":26,"s":[246.119,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":36,"s":[246.114,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":83,"s":[246.111,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":86.922,"s":[246.119,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":100.168,"s":[246.114,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"t":162.427734375,"s":[246.111,-182.443,0]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-9.934],[9.934,0],[0,9.934],[-9.934,0]],"o":[[0,9.934],[-9.934,0],[0,-9.934],[9.934,0]],"v":[[17.986,0],[0,17.986],[-17.986,0],[0,-17.986]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211765006185,0.211765006185,0.211765006185,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Layer 9","parent":1,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":17,"s":[169.369,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":27,"s":[169.364,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":74,"s":[169.361,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.29,"y":1},"o":{"x":0.29,"y":0},"t":75,"s":[169.369,-182.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.29,"y":0},"t":88.246,"s":[169.364,-214.73,0],"to":[0,0,0],"ti":[0,0,0]},{"t":150.505859375,"s":[169.361,-182.443,0]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-9.934],[9.934,0],[0,9.934],[-9.934,0]],"o":[[0,9.934],[-9.934,0],[0,-9.934],[9.934,0]],"v":[[17.986,0],[0,17.986],[-17.986,0],[0,-17.986]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.211765006185,0.211765006185,0.211765006185,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Layer 8","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[244.018,-51.305,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-12.655,-20.292],[-7.35,-2.981],[7.701,-28.541],[0.317,-3.808],[-36.225,24.19],[0,0],[-68.816,21.924],[-3.837,72.844]],"o":[[2.332,42.118],[11.602,18.604],[0,0],[-7.136,26.447],[-0.317,3.808],[38.943,-26.006],[0,0],[79.528,-25.336],[0,0]],"v":[[-217.807,-113.176],[-191.477,-25.646],[-156.279,7.978],[-157.429,59.013],[-184.018,111.305],[-109.444,90.996],[-59.864,46.529],[101.519,40.439],[217.807,-113.151]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.466666668653,0.466666668653,0.466666668653,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Layer 7","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[243.991,-156.124,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-68.816,21.924],[11.435,100.018],[142.983,0],[-0.105,-111.016],[-14.184,-22.743],[-7.35,-2.981],[7.701,-28.541],[0.317,-3.808],[-36.225,24.19]],"o":[[0,0],[98.763,-31.464],[-11.012,-96.322],[-146.477,0],[0.049,52.004],[11.602,18.604],[0,0],[-7.136,26.447],[-0.317,3.808],[38.943,-26.006]],"v":[[-59.838,151.347],[101.546,145.257],[215.761,-64.07],[-5.99,-217.994],[-218.218,-24.382],[-191.45,79.172],[-156.253,112.796],[-157.403,163.831],[-183.991,216.124],[-109.418,195.814]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.607843160629,0.607843160629,0.607843160629,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":7},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Layer 6","parent":1,"sr":1,"ks":{"o":{"a":0,"k":30},"p":{"a":0,"k":[101.895,10.306,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-38.799,26.074],[0,0],[3.273,-2.182],[-0.316,3.814],[-7.138,26.451],[1.376,6.169],[-3.385,-1.438],[37.004,-48.301]],"o":[[0,0],[-2.875,2.07],[-36.23,24.187],[0.316,-3.803],[6.322,-23.433],[2.325,0.632],[0,0],[0,0]],"v":[[41.9,22.995],[41.9,23.006],[32.682,29.389],[-41.898,49.691],[-15.305,-2.599],[-13.643,-51.565],[-5.128,-48.516],[-29.815,44.786]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Layer 5","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[89.009,32.224,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[37.393,-7.677],[0.041,-0.01],[2.101,-0.408],[-1.866,0.357],[0.612,-0.133],[-0.163,1.917],[-8.107,15.877],[-14.281,-7.027]],"o":[[-0.041,0.01],[-2.263,0.571],[-0.031,0.01],[-0.632,0.102],[-14.265,2.57],[0.224,-2.672],[9.738,-16.723],[13.713,6.748]],"v":[[-6.292,25.466],[-5.223,28.089],[-6.689,28.344],[-3.357,27.733],[-5.223,28.089],[-29.013,27.773],[-11.168,-2.451],[21.926,-27.934]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.752941012383,0.752941012383,0.752941012383,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Layer 4","parent":1,"sr":1,"ks":{"o":{"a":0,"k":20},"p":{"a":0,"k":[243.99,-69.281,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[92.161,-29.367],[0,0],[38.942,-26.012],[-0.316,3.814],[-7.138,26.451],[0,0],[11.604,18.599],[0.051,52.005],[0,0],[-179.831,-7.96],[-0.969,48.466]],"o":[[-68.809,21.923],[0,0],[-36.23,24.187],[0.316,-3.803],[7.699,-28.541],[-7.352,-2.977],[-14.184,-22.749],[0,0],[2.131,37.668],[222.466,9.847],[5.761,90.468]],"v":[[101.543,58.42],[-59.834,64.507],[-109.412,108.976],[-183.993,129.279],[-157.4,76.988],[-156.247,25.953],[-191.447,-7.667],[-218.214,-111.228],[-218.214,-111.911],[-8.028,33.265],[217.524,-131.153]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.588235318661,0.588235318661,0.588235318661,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Layer 3","parent":1,"sr":1,"ks":{"o":{"a":0,"k":40},"p":{"a":0,"k":[244.018,-344.054,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-15.716],[57.535,0],[0,15.716],[-57.535,0]],"o":[[0,15.716],[-57.535,0],[0,-15.716],[57.535,0]],"v":[[104.176,0],[0,28.457],[-104.176,0],[0,-28.457]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Layer 2","parent":1,"sr":1,"ks":{"o":{"a":0,"k":50},"p":{"a":0,"k":[243.991,-225.055,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[24.218,-38.025],[5.7,51.474],[138.536,0],[-0.102,-111.015],[-10.89,-21.098],[0.051,51.413],[-146.48,0],[-11.013,-96.321]],"o":[[18.416,-36.434],[-10.666,-96.321],[-141.922,0],[0.031,43.674],[-13.99,-22.627],[-0.102,-111.015],[142.982,0],[6.475,56.644]],"v":[[192.203,149.065],[209.049,15.556],[-5.802,-138.368],[-211.425,55.242],[-191.928,147.331],[-218.215,44.546],[-5.985,-149.065],[215.758,4.859]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"Layer 1","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[243.991,-156.124,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-68.816,21.924],[11.435,100.018],[142.983,0],[-0.105,-111.016],[-14.184,-22.743],[-7.35,-2.981],[7.701,-28.541],[0.317,-3.808],[-36.225,24.19]],"o":[[0,0],[98.763,-31.464],[-11.012,-96.322],[-146.477,0],[0.049,52.004],[11.602,18.604],[0,0],[-7.136,26.447],[-0.317,3.808],[38.943,-26.006]],"v":[[-59.838,151.347],[101.546,145.257],[215.761,-64.07],[-5.99,-217.994],[-218.218,-24.382],[-191.45,79.172],[-156.253,112.796],[-157.403,163.831],[-183.991,216.124],[-109.418,195.814]],"c":true}},"nm":"Path 1","hd":false},{"ty":"gf","o":{"a":0,"k":100},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0.303,0.988,0.988,0.988,0.909,0.796,0.796,0.796,1,0.604,0.604,0.604]}},"s":{"a":0,"k":[-0.306,-33.251]},"e":{"a":0,"k":[226.698,-32.932]},"t":2,"h":{"a":0,"k":0},"a":{"a":0,"k":0},"nm":"Gradient Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/thanos_vertex.glsl b/TMessagesProj/src/main/res/raw/thanos_vertex.glsl index e927a26699..d592871acc 100644 --- a/TMessagesProj/src/main/res/raw/thanos_vertex.glsl +++ b/TMessagesProj/src/main/res/raw/thanos_vertex.glsl @@ -18,7 +18,6 @@ out float alpha; uniform mat3 matrix; uniform vec2 rectSize; -// uniform vec2 rectPos; uniform float reset; uniform float time; @@ -30,6 +29,8 @@ uniform float seed; uniform float longevity; uniform float dp; uniform vec2 offset; +uniform float scale; +uniform float uvOffset; #define noiseScale 12.0 #define noiseSpeed 0.6 @@ -43,24 +44,6 @@ float rand(vec2 n) { return fract(sin(dot(n,vec2(12.9898,4.1414-seed*.42)))*43758.5453); } -float particleEaseInWindowFunction(float t) { - return t; -} - -float particleEaseInValueAt(float fraction, float t) { - float windowSize = 0.8; - - float effectiveT = t; - float windowStartOffset = -windowSize; - float windowEndOffset = 1.0; - - float windowPosition = (1.0 - fraction) * windowStartOffset + fraction * windowEndOffset; - float windowT = max(0.0, min(windowSize, effectiveT - windowPosition)) / windowSize; - float localT = 1.0 - particleEaseInWindowFunction(windowT); - - return localT; -} - void main() { vec2 uv = inUV; vec2 position = inPosition; @@ -75,15 +58,15 @@ void main() { ) / gridSize.xy; position = (matrix * vec3(uv + .5 / gridSize.xy, 1.0)).xy; float direction = rand(3. * uv) * (3.14159265 * 2.0); - velocity = vec2(cos(direction), sin(direction)) * (0.1 + rand(5. * uv) * (0.2 - 0.1)) * 260.0 * dp; + velocity = vec2(cos(direction), sin(direction)) * (0.1 + rand(5. * uv) * (0.2 - 0.1)) * 260.0 * scale * dp; particleTime = (0.7 + rand(uv) * (1.5 - 0.7)) / 1.15; } float effectFraction = max(0.0, min(0.35, time)) / 0.35; - float particleFraction = max(0.0, min(0.2, .1 + time - uv.x * 0.6)) / 0.2; + float particleFraction = max(0.0, min(0.2, .1 + time - uv.x * uvOffset)) / 0.2; position += velocity * deltaTime * particleFraction; velocity += vec2(19.0 * (velocity.x > 0.0 ? 1.0 : -1.0) * (1.0 - effectFraction), -65.0) * deltaTime * dp * particleFraction; - particleTime = max(0.0, particleTime - 1.2 * deltaTime * effectFraction); + particleTime = max(0.0, particleTime - 1.2 * deltaTime * particleFraction); outUV = uv; outPosition = position; diff --git a/TMessagesProj/src/main/res/values-ar-rSA/strings_na.xml b/TMessagesProj/src/main/res/values-ar-rSA/strings_na.xml index 4d7deface9..7a2ffed0f8 100644 --- a/TMessagesProj/src/main/res/values-ar-rSA/strings_na.xml +++ b/TMessagesProj/src/main/res/values-ar-rSA/strings_na.xml @@ -130,6 +130,7 @@ في التطبيق جوجل FCM دفع موحد + مايكروجي إظهار الإشعارات المقيمة بوابة دفع موحدة إرسال مستند mp4 كفيديو diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index aa809ca249..3f4089e51f 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -4474,4 +4474,5 @@ \'ذكّرني بتاريخ\' d MMM \'عند\' HH:mm \'ذكّرني بتاريخ\' d MMM yyyy \'عند\' HH:mm Menu + ارسلت من diff --git a/TMessagesProj/src/main/res/values-cs-rCZ/strings_na.xml b/TMessagesProj/src/main/res/values-cs-rCZ/strings_na.xml index 2f2ea554ab..0440fe16a3 100644 --- a/TMessagesProj/src/main/res/values-cs-rCZ/strings_na.xml +++ b/TMessagesProj/src/main/res/values-cs-rCZ/strings_na.xml @@ -130,6 +130,7 @@ V aplikaci Google FCM Sjednocený posun + MikroG Zobrazit rezidentní oznámení Sjednocená posuvná brána Poslat dokument mp4 jako video diff --git a/TMessagesProj/src/main/res/values-da-rDK/strings_na.xml b/TMessagesProj/src/main/res/values-da-rDK/strings_na.xml index 193f33ce62..384d4ff494 100644 --- a/TMessagesProj/src/main/res/values-da-rDK/strings_na.xml +++ b/TMessagesProj/src/main/res/values-da-rDK/strings_na.xml @@ -130,6 +130,7 @@ I App Google FCM Unified Push + Mikrog Vis residente notifikationer Unified Push Gateway Send mp4-dokument som video diff --git a/TMessagesProj/src/main/res/values-de-rDE/strings_na.xml b/TMessagesProj/src/main/res/values-de-rDE/strings_na.xml index de883dccbe..3bc6dd4c7b 100644 --- a/TMessagesProj/src/main/res/values-de-rDE/strings_na.xml +++ b/TMessagesProj/src/main/res/values-de-rDE/strings_na.xml @@ -130,6 +130,7 @@ In App Google FCM Einheitlicher Push + MikroG Resident-Benachrichtigungen anzeigen Einheitliches Push-Gateway mp4 Dokument als Video senden diff --git a/TMessagesProj/src/main/res/values-el-rGR/strings_na.xml b/TMessagesProj/src/main/res/values-el-rGR/strings_na.xml index 55e8b172e0..d80bc46b99 100644 --- a/TMessagesProj/src/main/res/values-el-rGR/strings_na.xml +++ b/TMessagesProj/src/main/res/values-el-rGR/strings_na.xml @@ -130,6 +130,7 @@ Στην Εφαρμογή Google FCM Ενοποιημένη Προώθηση + MicroG Εμφάνιση ειδοποιήσεων κατοίκων Ενοποιημένη Πύλη Ώθησης Αποστολή εγγράφου mp4 ως βίντεο diff --git a/TMessagesProj/src/main/res/values-es-rES/strings_na.xml b/TMessagesProj/src/main/res/values-es-rES/strings_na.xml index 8e6d9bd83e..04c0f9064f 100644 --- a/TMessagesProj/src/main/res/values-es-rES/strings_na.xml +++ b/TMessagesProj/src/main/res/values-es-rES/strings_na.xml @@ -130,6 +130,7 @@ En la App FCM de Google Unified Push + MicroG Mostrar notificación permanente Gateway de Unified Push Enviar documento mp4 como vídeo diff --git a/TMessagesProj/src/main/res/values-fa-rIR/strings_na.xml b/TMessagesProj/src/main/res/values-fa-rIR/strings_na.xml index 102c398717..8e63ded331 100644 --- a/TMessagesProj/src/main/res/values-fa-rIR/strings_na.xml +++ b/TMessagesProj/src/main/res/values-fa-rIR/strings_na.xml @@ -130,6 +130,7 @@ In App Google FCM Unified Push + MicroG Show resident notifications Unified Push Gateway Send mp4 document as video diff --git a/TMessagesProj/src/main/res/values-fi-rFI/strings_na.xml b/TMessagesProj/src/main/res/values-fi-rFI/strings_na.xml index b8c892b5e6..f4949b648b 100644 --- a/TMessagesProj/src/main/res/values-fi-rFI/strings_na.xml +++ b/TMessagesProj/src/main/res/values-fi-rFI/strings_na.xml @@ -130,6 +130,7 @@ Sovelluksessa Google FCM Yhdistetty Työntö + MikroG Näytä kotimaiset ilmoitukset Yhdistetty Push-Yhdyskäytävä Lähetä mp4-asiakirja videona diff --git a/TMessagesProj/src/main/res/values-fr-rFR/strings_na.xml b/TMessagesProj/src/main/res/values-fr-rFR/strings_na.xml index bd140917f7..ce208277ce 100644 --- a/TMessagesProj/src/main/res/values-fr-rFR/strings_na.xml +++ b/TMessagesProj/src/main/res/values-fr-rFR/strings_na.xml @@ -130,6 +130,7 @@ Dans l\'application Google FCM Push unifié + MicroG Afficher les notifications des résidents Passerelle Push unifiée Envoyer le document mp4 en tant que vidéo diff --git a/TMessagesProj/src/main/res/values-it-rIT/strings_na.xml b/TMessagesProj/src/main/res/values-it-rIT/strings_na.xml index f9e4e2640e..f0962ee7a2 100644 --- a/TMessagesProj/src/main/res/values-it-rIT/strings_na.xml +++ b/TMessagesProj/src/main/res/values-it-rIT/strings_na.xml @@ -130,6 +130,7 @@ In App Google FCM Push Unificato + MicroG Mostra notifiche residenti Unified Push Gateway Invia il documento mp4 come video diff --git a/TMessagesProj/src/main/res/values-ja-rJP/strings_na.xml b/TMessagesProj/src/main/res/values-ja-rJP/strings_na.xml index 2b59be8c11..89b7232470 100644 --- a/TMessagesProj/src/main/res/values-ja-rJP/strings_na.xml +++ b/TMessagesProj/src/main/res/values-ja-rJP/strings_na.xml @@ -130,6 +130,7 @@ アプリ内 Google FCM 統一されたプッシュ + MicroG 常駐通知を表示 Unified Push Gateway mp4ドキュメントを動画として送信 diff --git a/TMessagesProj/src/main/res/values-nl-rNL/strings_na.xml b/TMessagesProj/src/main/res/values-nl-rNL/strings_na.xml index e154336610..e6177068f2 100644 --- a/TMessagesProj/src/main/res/values-nl-rNL/strings_na.xml +++ b/TMessagesProj/src/main/res/values-nl-rNL/strings_na.xml @@ -130,6 +130,7 @@ In de App Google FCM Gecombineerde Push + MicroG Toon inactieve meldingen Gecombineerde Push Gateway Stuur mp4-document als video diff --git a/TMessagesProj/src/main/res/values-no-rNO/strings_na.xml b/TMessagesProj/src/main/res/values-no-rNO/strings_na.xml index 6c876455a2..21136065d1 100644 --- a/TMessagesProj/src/main/res/values-no-rNO/strings_na.xml +++ b/TMessagesProj/src/main/res/values-no-rNO/strings_na.xml @@ -130,6 +130,7 @@ I App Google FCM Felles Push + Mikrog Vis varsling fra kunder Enhetlig Push Gateway Send mp4-dokument som video diff --git a/TMessagesProj/src/main/res/values-pl-rPL/strings_na.xml b/TMessagesProj/src/main/res/values-pl-rPL/strings_na.xml index ef45449fd2..69ff3dd958 100644 --- a/TMessagesProj/src/main/res/values-pl-rPL/strings_na.xml +++ b/TMessagesProj/src/main/res/values-pl-rPL/strings_na.xml @@ -130,6 +130,7 @@ W aplikacji Google FCM Jednolite Push + MikroG Pokaż powiadomienia mieszkańców Zunifikowana brama popychająca Wyślij dokument mp4 jako film diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings_na.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings_na.xml index 035c36192e..bdc30b61a1 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings_na.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings_na.xml @@ -130,6 +130,7 @@ No aplicativo Google FCM Envio Unificado + Microfone Mostrar notificações residentes Gateway Unificado Enviar documento mp4 como vídeo diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings_na.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings_na.xml index 035c36192e..bdc30b61a1 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings_na.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings_na.xml @@ -130,6 +130,7 @@ No aplicativo Google FCM Envio Unificado + Microfone Mostrar notificações residentes Gateway Unificado Enviar documento mp4 como vídeo diff --git a/TMessagesProj/src/main/res/values-ro-rRO/strings_na.xml b/TMessagesProj/src/main/res/values-ro-rRO/strings_na.xml index 397fa03a67..4aab93c217 100644 --- a/TMessagesProj/src/main/res/values-ro-rRO/strings_na.xml +++ b/TMessagesProj/src/main/res/values-ro-rRO/strings_na.xml @@ -130,6 +130,7 @@ În aplicație Google FCM Push unificat + MicroG Arată notificările rezidenților Gateway Push Unificat Trimite documentul mp4 ca video diff --git a/TMessagesProj/src/main/res/values-ru-rRU/strings_na.xml b/TMessagesProj/src/main/res/values-ru-rRU/strings_na.xml index 8d2f2e11cb..4d59c96fbd 100644 --- a/TMessagesProj/src/main/res/values-ru-rRU/strings_na.xml +++ b/TMessagesProj/src/main/res/values-ru-rRU/strings_na.xml @@ -130,6 +130,7 @@ В приложении Google FCM Единый толчок + МикроГ Показывать уведомления жителя Единый Push шлюз Отправить mp4 документ как видео diff --git a/TMessagesProj/src/main/res/values-sv-rSE/strings_na.xml b/TMessagesProj/src/main/res/values-sv-rSE/strings_na.xml index f8d74a6af3..104192a663 100644 --- a/TMessagesProj/src/main/res/values-sv-rSE/strings_na.xml +++ b/TMessagesProj/src/main/res/values-sv-rSE/strings_na.xml @@ -130,6 +130,7 @@ I appen Google FCM Enhetlig Push + MikroG Visa inhemska aviseringar Enhetlig Push Gateway Skicka mp4-dokument som video diff --git a/TMessagesProj/src/main/res/values-tr-rTR/strings_na.xml b/TMessagesProj/src/main/res/values-tr-rTR/strings_na.xml new file mode 100644 index 0000000000..7dd1af9928 --- /dev/null +++ b/TMessagesProj/src/main/res/values-tr-rTR/strings_na.xml @@ -0,0 +1,142 @@ + + + N-Config + Kopyalamaya Zorla + Tersine Çevir + Great + Poor + Mesajı Birleştir + Metin Stili + Etkinleştirilmiş İletiyi Yanıtla Birleştir + Mesajı Birleştirme Etkin + Mesajı Birleştirme Devre Dışı + Geri Al/Yinele + Geri Al + Yinele + Gürültü Bastırma ve Ses Geliştirme + Kopya Olarak Tekrarla + Çift Dokunma Eylemi + Tepkileri Gönder + Tepkileri Göster + Özel Başlık + Nagram\'ı kullanmak için boş bırakın + Kod söz dizimini vurgulama + Tek Boşluk Oluştur + Kod dili + Prismjs ve Nekogram\'a teşekkürler + Parola Kilidi Açma sistem kullanıcı arayüzünü kullanın + Fotoğrafı Kopyala + Fotoğraf Pano\'ya kopyalandı + Başlangıca + İletilen mesajın tarihini göster + Mesaj kimliğini göster + Tüm RPC hatalarını toast + Hizmet mesajlarında zaman damgasını göster + Premium çıkartmaları Animasyonu göster + Sohbette Premium Yıldızı Göster + Premium Avatar Animasyonunu Göster + AlwaysSaveChatOffset + Kopyalama Olarak Tekrarlamak için Tekrarlamayı Otomatik Değiştir + Google + Renkli + Koyu Yeşil + Neon + Niello + Mavi + Koyu Mavi + Mavi Bulanıklaştır + GIF gönderilmeden önce otomatik olarak resim yazısı ekle + Özel varsayılan kod dili + Global Aramayı Devre Dışı Bırak + Mesaj Kimliğini Girin + Mesaja + Çeviriden sonra kaynağı gizle + \"Zalgo\" simgelerini filtrele + Takma adlar veya mesajlardaki tüm \"Z̷͍͌ā̸̜l̸̞̂g̷̝͘o̶̩̓\" sembolleri kaldırılacaktır. + Özel varsayılan kanal etiketi + İndirme Simgesini Her Zaman Göster + Anonimlere hızlı geçiş + Grubun sahibiyseniz + Çıkartmalar için gerçek saklanma süresi + Başlığı Gizle + Klasör Sayısını Yoksay + İşaretlemeden gönder + İşaretlemeden kaydet + Emoji olarak gönder + Özel Çizim API\'si + Özel yanıt sözcüğü + Varsayılan harika + Özel uzun tıklama yanıt sözcüğü + Varsayılan havuz + Özel Düzenlenmiş Mesaj kelimesi + Sahte Yüksek Performanslı Cihaz + Emoji Çizim Sınırını Devre Dışı Bırak + Simge Dekorasyonu + Bildirim Simgesi + Resmi + Nekogram + HalloWeen + Çevrimiçi Durumu Göster + Gruplardaki diğer kişilerin çevrimiçi durumunu profil fotoğraflarının yanında gösterin + Son Çevrimiçi Durumu Göster + Ortak gruplarda uygulanır + Hakkında tüm bilgileri göster + Mesajın görülmesi ipucunu gizle + Mesaj ipucu türü olarak grup adını kullan + Giriş alanındaki bot düğmesini gizle + Göndermeyi mesaj ipucunun altında göster + Forum ekle + Forumu normal sohbet olarak göster + Yok + Sohbet Dekorasyonu + N-Settings\'i değiştirmeniz gerekiyor + Kaydırarak arşivden çıkarmayın + Telefon numaramı paylaşma + Varsayılan Silme Menüsü + Profil Ayarları Önerisini Devre Dışı Bırak + Hikayeleri Devre Dışı Bırak + Okuma Hikayelerini Göndermeyi Devre Dışı Bırak + Filtreyi gizle, tümünü kapat + Yerel alıntı rengini kullan + Kare avatarı göster + Kullanıcı özel duvar kağıdını devre dışı bırak + Kanal özel duvar kağıdını devre dışı bırak + Fotoğrafı Etiket Olarak Kopyala + Harici çıkartma önbelleği + Çıkartma paketlerini diğer uygulamalarla paylaşmak için. Depolama konumunu seçmek için tıklayın. + Harici Önbelleği Yenile + Harici Önbelleği Sil + Önbellek senkronizasyonunun tamamlanması bekleniyor + Önbellek senkronizasyonu zaten çalışıyor + Otomatik senkronizasyon + Çıkartma etkinliklerini aldıktan sonra tüm önbellekleri otomatik olarak senkronize et + Tüm önbellekleri senkronize et + Tüm önbellekleri sil + Dizin adlandırma + TranSmart Çevirmen + Markdown\'ı devre dışı bırak + Markdown ile gönder + Dokunarak avatarları çevirmeyi devre dışı bırakın + Özellik ipuçları kanalımızı takip etmek ister misiniz? + Özellikler İpuçları Kanalı + Küçük GIF\'i Göster + Gönderilecek tıklama komutu metnini devre dışı bırakın + Yanlışlıkla dokunmayı önlemek için + İletişim Kutuları Kayan Düğmesini Devre Dışı Bırak + Güvenli İşaretlemeyi Devre Dışı Bırak + Başlığı işlem çubuğunda ortalayın + Bot Komutlarında Hızlı Yanıtı Göster + Push Hizmet Türü + Uygulama İçi + Google FCM + Birleşik Aktarma + MicroG + Yerleşik bildirimleri göster + Birleşik Aktarma Ağ Geçidi + Mp4 belgesini video olarak gönder + Paketiniz için kısa bir ad seçin. + Çıkartma Setini Kopyala + Kanal sesini kapatma düğmesini devre dışı bırak + Önizleme videosu ses kısayolunu devre dışı bırak + Önizleme video sesini etkinleştirmek için ses seviyesi tuşlarını devre dışı bırakın + diff --git a/TMessagesProj/src/main/res/values-uk-rUA/strings_na.xml b/TMessagesProj/src/main/res/values-uk-rUA/strings_na.xml index 2d3e3fe5eb..1f3dcf6970 100644 --- a/TMessagesProj/src/main/res/values-uk-rUA/strings_na.xml +++ b/TMessagesProj/src/main/res/values-uk-rUA/strings_na.xml @@ -130,6 +130,7 @@ В додатку Google FCM Одноразове штовхання + МікроГ Показувати сповіщення резидента Уніфікований Push-шлюз Відправити mp4 документ як відео diff --git a/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml b/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml index d0b3073c39..0dd0a5ce14 100644 --- a/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml +++ b/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml @@ -131,6 +131,7 @@ 内置 Google FCM Unified Push + MicroG 显示常驻通知 Unified Push Gateway MP4 视频作为文件发送时可预览 diff --git a/TMessagesProj/src/main/res/values-zh-rTW/strings_na.xml b/TMessagesProj/src/main/res/values-zh-rTW/strings_na.xml index 5252da3d1a..05006fc450 100644 --- a/TMessagesProj/src/main/res/values-zh-rTW/strings_na.xml +++ b/TMessagesProj/src/main/res/values-zh-rTW/strings_na.xml @@ -131,6 +131,7 @@ In App Google FCM Unified Push + MicroG Show resident notifications Unified Push Gateway Send mp4 document as video diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index ae5c4c2d6a..9c2ee5334e 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -679,6 +679,12 @@ Removed by %1$s User Permissions What can this user do? + What can %1$s selected users do? + What can %1$s selected user do? + What can %1$s selected users do? + What can %1$s selected users do? + What can %1$s selected users do? + What can %1$s selected users do? Read Messages Send Messages Send Polls @@ -882,8 +888,8 @@ All actions Selected actions All admins - **No actions here yet**\n\nThe group\'s members and admins\nhave not taken any service actions\nin the last 48 hours. - **No actions here yet**\n\nThe channel\'s admins\nhave not taken any service actions\nin the last 48 hours. + **No actions here yet**\n\nThe group\'s members and admins have not taken any service actions in the last **48** hours. + **No actions here yet**\n\nThe channel\'s admins have not taken any service actions in the last **48** hours. **No actions found**\n\nNo recent actions that match your query\nhave been found. No recent actions that contain \'**%1$s**\' have been found. What is the Recent Actions? @@ -916,6 +922,12 @@ un1 stopped the poll: un1 stopped the quiz: un1 deleted this message: + un1 deleted message from %2$s + un1 deleted %1$d messages from %2$s + un1 deleted message from %2$s: + un1 deleted %1$d messages from %2$s: + Hide all + Show all un1 changed group location to \"%1$s\" un1 removed group location transferred ownership to %1$s @@ -983,6 +995,16 @@ Edited messages Pinned messages Leaving members + Members left the Group + Members And Admins + Apply Filter + New Admin Rights + Messages + Group Settings + Channel Settings + Filter actions by type + Filter actions by admins + Show Actions by All Admins Voice chats Invite links un1 set the slow mode timer to %1$s @@ -1259,7 +1281,10 @@ Do you want to pin this message in this channel? Do you want to pin this message at the top of the chat? Do you want to unpin this message? - Ban user + Ban %1$s + Ban users + Restrict %1$s + Restrict users Report spam Translate Hide Translation @@ -1268,6 +1293,38 @@ Translation failed. Try again later. Translation failed. Delete all from %1$s + Delete all from users + Delete %1$d Messages? + Delete %1$d Message? + Delete %1$d Messages? + Delete %1$d Messages? + Delete %1$d Messages? + Delete %1$d Messages? + Additional actions + Fully ban users + Fully ban this user + Partially restrict users + Partially restrict this user + Proceed + Messages Deleted + %1$d users reported for spam. + %1$d user reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users reported for spam. + %1$d users banned. + %1$d user banned. + %1$d users banned. + %1$d users banned. + %1$d users banned. + %1$d users banned. + %1$d users restricted. + %1$d user restricted. + %1$d users restricted. + %1$d users restricted. + %1$d users restricted. + %1$d users restricted. Clear recent emoji Do you want to clear all your recent emoji? Clear recent statuses @@ -1969,6 +2026,7 @@ Set emoji that corresponds to your sticker Choose a name for your pack. Sticker added to %1$s sticker set. + Sticker edited in %1$s sticker set. Stickers removed. %1$s is no longer in your stickers. Masks removed. @@ -2446,7 +2504,7 @@ Save to Gallery Sound muted Edit Name - Edit Profile Color + Change profile color Customize Custom Enable Custom Notifications @@ -2538,6 +2596,10 @@ Cut Out Cut an Object Undo Cut + Undo + Add Outline + Erase + Restore edit Paste from clipboard Proxy Settings @@ -2594,6 +2656,7 @@ Groups Channels Stories + Reactions Please note that **%1$s** are listed as exceptions and won\'t be affected by this change. Please note that **%1$s** is listed as an exception and won\'t be affected by this change. View Exceptions @@ -2698,6 +2761,7 @@ Stickers & Emoji Profile Photos Miscellaneous + Logs Photos Voice messages Videos @@ -3122,6 +3186,8 @@ Share My Live Location for... Share my Live Location Stop Sharing Location + Sharing Location... + tap to add more time Stop location sharing Do you want to stop sharing your live location with **%1$s**? Do you want to stop sharing your live location with **%1$s**? @@ -3142,6 +3208,7 @@ for 15 minutes for 1 hour for 8 hours + until I turn it off updated updated %1$s updated just now @@ -3151,6 +3218,8 @@ %1$s sharing with %2$s STOP ALL You are sharing your Live Location with %1$s + Add More Time + For how long do you want to extend sharing your location? Choose for how long %1$s will see your accurate location. Choose for how long people in this chat will see your live location. Enable GPS @@ -3734,6 +3803,8 @@ Call Video Call Copy + Restrict + Ban Rename Delete Start @@ -5619,6 +5690,11 @@ Release to go to the next unread folder Pull up to go to archived channels Release to go to archived channels + Pull up to go to next channel + Release to go to next channel + Pull up to go to the next unread topic + Release to go to the next unread topic + No more unread topics in %1$s You have no unread channels Favorites @@ -5862,6 +5938,7 @@ Nobody viewed QR Code + New reaction to your message %2$s to your "%3$s" %2$s to your message %2$s to your photo @@ -5894,6 +5971,8 @@ %3$s to your game in %2$s %3$s to your invoice in %2$s %3$s to your GIF in %2$s + %2$s to your story + New reaction to your story Blur in chat Allow background activity @@ -5960,6 +6039,7 @@ Groups Sound Channels Sound Stories Sound + Reactions Sound Too long Too large Invalid format @@ -7020,9 +7100,10 @@ Message sent. Just now Expired story - Stories + Posts + Archived Posts Reaction sent. - My Stories + My Profile Saved %d saved stories %d saved story @@ -7149,6 +7230,7 @@ Close Friends Failed to process video file. Preparing video… + Preparing sticker… No saved stories No posts yet… Publish photos and videos to display on your profile page @@ -7422,6 +7504,7 @@ Hide My View Stealth Mode Subscribe to Telegram Premium to hide the fact that you viewed peoples’ stories from them. + View\nAnonymously Hide Recent Views Hide my views in the last 5 minutes. Hide Next Views @@ -7429,6 +7512,7 @@ Unlock Stealth Mode Turn Stealth Mode on to hide the fact that you viewed peoples’ stories from them. Enable Stealth Mode + Enable and open the story Available in %s Stealth Mode On The creators of stories you viewed in the last 5 minutes or will view in the next 25 minutes won’t see you in viewers’ lists. @@ -7448,6 +7532,10 @@ Update Reactions Level %1$d Required Level %1$d Required + Maximum number of reactions + %d reaction per post + %d reactions per post + Limit the number of different reactions that can be added to a post, including already published ones. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions. Your channel needs to reach Level **%2$d** to add **%1$d** custom emoji as reactions.\n\nAsk your **Premium** subscribers to boost your channel with this link: @@ -8204,6 +8292,8 @@ Group Emoji Pack Group Emoji Choose an emoji pack that will be available to all members within the group. + Group Sticker Pack + You can choose a sticker set that will be shown to all group members. Channel Emoji Status Group Emoji Status Choose a status that will be shown next to the channel\'s name. @@ -8463,6 +8553,12 @@ You have changed the business location. Apply changes? Remove Location Are you sure you want to remove business location? + Remove Hours + Are you sure you want to remove business opening hours? + Remove date of birth + Are you sure you want to remove date of birth from your profile? + Remove channel + Are you sure you want to remove channel from your profile? New Greeting Message Create greetings that will be automatically sent to new customers. Add a Greeting @@ -8565,6 +8661,7 @@ Telegram shares %1$d%% of the revenue from ads displayed in your channel. **Learn more >** Available balance You can collect your reward using Fragment, a third-party platform used by advertisers to pay for ads. **Learn more >** + https://telegram.org/tos/content-creator-rewards In the coming weeks you will be able to collect your reward using Fragment, a third-party platform used by advertisers to pay ads. **Learn more >** Transaction history Show %d more transaction @@ -8624,6 +8721,9 @@ **Remove date of birth.** Date of Birth Save + Change Opening Hours + Change Location + Channel %1$s %2$s (%1$d years old) 🎂 %1$s @@ -8638,6 +8738,7 @@ Date of birth added. Oops Sorry, you can’t change your birthday so often. + Add Your Birthday Add your birthday! 🎂 Let your contacts know when you’re celebrating You can always set your birthday in profile settings. @@ -8675,4 +8776,98 @@ Invite via Link You can send an invite link to the group in a private message instead. You can send these people an invite link to the group in a private message instead. + Replace number + Copy username + Change username + Set username + Edit bio + Copy hours + Edit hours + Remove + Copy address + View location + Open in Maps + Change location + Remove + Change + Copy link to profile + Copy Link + Change Channel + Ads in Channels + Do Not Hide Ads + As a Premium subscriber, you don’t see any ads on Telegram, but you can turn them on, for example, to view your own ads that you launched on the **Telegram Ad Platform >** + Channels + %d story deleted + %d stories deleted + ⚠️ Your Premium subscription is expiring! + Don’t lose access to exclusive features. + Access to Telegram Premium is expiring! + ⚠️ Unfortunately, your latest payment didn’t come through. To keep your access to exclusive features, please renew the subscription. + Restore Subscription + Channels you joined + Recommended Channels + Channels + VIEW STICKERS + VIEW EMOJI + Story pinned + %d stories pinned + Story unpinned. + %d stories unpinned. + Now it will be always shown on the top. + Now they will be always shown on the top. + You can’t pin more than %d posts. + Reactions + Messages + Stories + Notify me about… + New Messages in Private Chats + New Stories + Important Stories + New Messages in Groups + New Messages in Channels + Reactions to My Messages + Reactions to My Stories + From My Contacts + From Everyone + Off + More Options + Less Options + Notify about reactions from + My Contacts + Everyone + Create + No channels yet… + You are not subscribed to any channel. + Set Intro Sticker + Enter word from SMS + We’ve sent an SMS with a secret word that starts with “**%2$s**” to your phone **%1$s**. + We’ve sent an SMS with a secret word to your phone **%1$s**. + Secret word + Enter Word from SMS + You can copy and paste the word here. + Incorrect, please try again + Incorrect word + Enter phrase from SMS + We’ve sent an SMS with a secret phrase to your phone **%1$s**. + We’ve sent an SMS with a secret phrase that starts with “**%2$s**” to your phone **%1$s**. + Secret phrase + You can copy and paste the phrase here. + Enter Phrase from SMS + Incorrect, please try again + Incorrect word + Request another SMS + < Back to entering the word + < Back to entering the phrase + < Back to entering the code + Return to entering the code > + Return to entering the word > + Return to entering the word > + You can request another\nSMS in %1$d:%2$02d + Telegram can call you in %1$d:%2$02d + Forwarded from + Restricted **%s** from sending any messages + Show %d More Message + Show %d More Messages + **No results found** + **No results matching your filters** \ No newline at end of file