diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 63db5816b55..e12d3434e80 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -21,15 +21,15 @@ dependencies { compileOnly 'org.checkerframework:checker-qual:2.5.2' compileOnly 'org.checkerframework:checker-compat-qual:2.5.0' - implementation 'com.google.firebase:firebase-messaging:19.0.1' - implementation 'com.google.firebase:firebase-config:18.0.0' + implementation 'com.google.firebase:firebase-messaging:20.0.0' + implementation 'com.google.firebase:firebase-config:19.0.0' implementation 'com.google.android.gms:play-services-maps:17.0.0' implementation 'com.google.android.gms:play-services-auth:17.0.0' implementation 'com.google.android.gms:play-services-vision:16.2.0' implementation 'com.google.android.gms:play-services-wallet:17.0.0' implementation 'com.google.android.gms:play-services-wearable:17.0.0' implementation 'com.google.android.gms:play-services-location:17.0.0' - implementation 'net.hockeyapp.android:HockeySDK:5.1.1' + implementation 'net.hockeyapp.android:HockeySDK:5.2.0' implementation 'com.googlecode.mp4parser:isoparser:1.0.6' implementation 'com.stripe:stripe-android:2.0.2' } @@ -51,6 +51,7 @@ android { lintOptions { disable 'MissingTranslation' disable 'ExtraTranslation' + disable 'BlockedPrivateApi' } dexOptions { @@ -242,7 +243,7 @@ android { } } - defaultConfig.versionCode = 1684 + defaultConfig.versionCode = 1710 applicationVariants.all { variant -> variant.outputs.all { output -> @@ -276,7 +277,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 27 - versionName "5.10.0" + versionName "5.11.0" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp index 7305a858096..75c1521a308 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.cpp @@ -78,6 +78,16 @@ LOTCompItem::LOTCompItem(LOTModel *model) mViewSize = mCompData->size(); } +static bool isGoodParentLayer(LOTLayerItem *parent, LOTLayerItem *child) { + do { + if (parent == child) { + return false; + } + parent = parent->resolvedParentLayer(); + } while (parent); + return true; +} + void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value) { LOTKeyPath key(keypath); @@ -527,7 +537,10 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) auto search = std::find_if(mLayers.begin(), mLayers.end(), [id](const auto &val) { return val->id() == id; }); - if (search != mLayers.end()) layer->setParentLayer((*search).get()); + if (search != mLayers.end() && + isGoodParentLayer((*search).get(), layer.get())) { + layer->setParentLayer((*search).get()); + } } } diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h index 407994dee93..e3941e1946c 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieitem.h @@ -107,6 +107,7 @@ class LOTLayerItem LOTLayerItem(LOTLayerData *layerData); int id() const {return mLayerData->id();} int parentId() const {return mLayerData->parentId();} + LOTLayerItem *resolvedParentLayer() const {return mParentLayer;} void setParentLayer(LOTLayerItem *parent){mParentLayer = parent;} void setComplexContent(bool value) { mComplexContent = value;} bool complexContent() const {return mComplexContent;} diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottieparser.cpp b/TMessagesProj/jni/rlottie/src/lottie/lottieparser.cpp index 56403093431..2ca2a008249 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottieparser.cpp +++ b/TMessagesProj/jni/rlottie/src/lottie/lottieparser.cpp @@ -622,6 +622,10 @@ void LottieParserImpl::parseComposition() { parsingError = true; return; } + if (comp->mVersion.empty() || !comp->mRootLayer) { + // don't have a valid bodymovin header + return; + } resolveLayerRefs(); comp->setStatic(comp->mRootLayer->isStatic()); comp->mRootLayer->mInFrame = comp->mStartFrame; @@ -1969,7 +1973,7 @@ void LottieParserImpl::getValue(std::vector &v) { void LottieParserImpl::getValue(VPointF &pt) { - float val[4]; + float val[4] = {0.f}; int i = 0; if (PeekType() == kArrayType) EnterArray(); @@ -1978,7 +1982,10 @@ void LottieParserImpl::getValue(VPointF &pt) if (parsingError) { return; } - val[i++] = GetDouble(); + const auto value = GetDouble(); + if (i < 4) { + val[i++] = value; + } } if (!IsValid()) { parsingError = true; @@ -2014,7 +2021,7 @@ void LottieParserImpl::getValue(float &val) void LottieParserImpl::getValue(LottieColor &color) { - float val[4]; + float val[4] = {0.f}; int i = 0; if (PeekType() == kArrayType) EnterArray(); @@ -2022,7 +2029,10 @@ void LottieParserImpl::getValue(LottieColor &color) if (parsingError) { return; } - val[i++] = GetDouble(); + const auto value = GetDouble(); + if (i < 4) { + val[i++] = value; + } } if (!IsValid()) { parsingError = true; diff --git a/TMessagesProj/jni/tgnet/ApiScheme.cpp b/TMessagesProj/jni/tgnet/ApiScheme.cpp index a20409a14b7..e8d7049dd4a 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.cpp +++ b/TMessagesProj/jni/tgnet/ApiScheme.cpp @@ -339,13 +339,37 @@ void TL_account_registerDevice::serializeToStream(NativeByteBuffer *stream) { stream->writeString(token); } +TL_restrictionReason *TL_restrictionReason::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { + if (TL_restrictionReason::constructor != constructor) { + error = true; + if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_restrictionReason", constructor); + return nullptr; + } + TL_restrictionReason *result = new TL_restrictionReason(); + result->readParams(stream, instanceNum, error); + return result; +} + +void TL_restrictionReason::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { + platform = stream->readString(&error); + reason = stream->readString(&error); + text = stream->readString(&error); +} + +void TL_restrictionReason::serializeToStream(NativeByteBuffer *stream) { + stream->writeInt32(constructor); + stream->writeString(platform); + stream->writeString(reason); + stream->writeString(text); +} + User *User::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { User *result = nullptr; switch (constructor) { case 0x200250ba: result = new TL_userEmpty(); break; - case 0x2e13f4c3: + case 0x938458c1: result = new TL_user(); break; default: @@ -394,7 +418,20 @@ void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er bot_info_version = stream->readInt32(&error); } if ((flags & 262144) != 0) { - restriction_reason = stream->readString(&error); + uint32_t magic = stream->readUint32(&error); + if (magic != 0x1cb5c415) { + error = true; + if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic); + return; + } + int32_t count = stream->readInt32(&error); + for (int32_t a = 0; a < count; a++) { + TL_restrictionReason *object = TL_restrictionReason::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error); + if (object == nullptr) { + return; + } + restriction_reason.push_back(std::unique_ptr(object)); + } } if ((flags & 524288) != 0) { bot_inline_placeholder = stream->readString(&error); @@ -433,7 +470,12 @@ void TL_user::serializeToStream(NativeByteBuffer *stream) { stream->writeInt32(bot_info_version); } if ((flags & 262144) != 0) { - stream->writeString(restriction_reason); + stream->writeInt32(0x1cb5c415); + uint32_t count = (uint32_t) restriction_reason.size(); + stream->writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason[a]->serializeToStream(stream); + } } if ((flags & 524288) != 0) { stream->writeString(bot_inline_placeholder); diff --git a/TMessagesProj/jni/tgnet/ApiScheme.h b/TMessagesProj/jni/tgnet/ApiScheme.h index 760729eddeb..ee26d11ce7e 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.h +++ b/TMessagesProj/jni/tgnet/ApiScheme.h @@ -277,6 +277,20 @@ class TL_userProfilePhoto : public UserProfilePhoto { void serializeToStream(NativeByteBuffer *stream); }; +class TL_restrictionReason : public TLObject { + +public: + static const uint32_t constructor = 0xd072acb4; + + std::string platform; + std::string reason; + std::string text; + + static TL_restrictionReason *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); + void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); + void serializeToStream(NativeByteBuffer *stream); +}; + class User : public TLObject { public: @@ -290,7 +304,7 @@ class User : public TLObject { std::unique_ptr status; int32_t flags; int32_t bot_info_version; - std::string restriction_reason; + std::vector> restriction_reason; std::string bot_inline_placeholder; std::string lang_code; @@ -309,7 +323,7 @@ class TL_userEmpty : public User { class TL_user : public User { public: - static const uint32_t constructor = 0x2e13f4c3; + static const uint32_t constructor = 0x938458c1; void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); void serializeToStream(NativeByteBuffer *stream); diff --git a/TMessagesProj/jni/tgnet/ByteStream.cpp b/TMessagesProj/jni/tgnet/ByteStream.cpp index d4949cccf58..c41e126651c 100644 --- a/TMessagesProj/jni/tgnet/ByteStream.cpp +++ b/TMessagesProj/jni/tgnet/ByteStream.cpp @@ -58,6 +58,9 @@ void ByteStream::discard(uint32_t count) { uint32_t remaining; NativeByteBuffer *buffer; while (count > 0) { + if (buffersQueue.empty()) { + break; + } buffer = buffersQueue[0]; remaining = buffer->remaining(); if (count < remaining) { diff --git a/TMessagesProj/jni/tgnet/ConnectionSocket.cpp b/TMessagesProj/jni/tgnet/ConnectionSocket.cpp index bb9ccf4ded1..783bc9fa214 100644 --- a/TMessagesProj/jni/tgnet/ConnectionSocket.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionSocket.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "ByteStream.h" #include "ConnectionSocket.h" #include "FileLog.h" @@ -34,6 +35,95 @@ #define MAX_GREASE 8 +static BIGNUM *get_y2(BIGNUM *x, const BIGNUM *mod, BN_CTX *big_num_context) { + // returns y^2 = x^3 + 486662 * x^2 + x + BIGNUM *y = BN_dup(x); + assert(y != NULL); + BIGNUM *coef = BN_new(); + BN_set_word(coef, 486662); + BN_mod_add(y, y, coef, mod, big_num_context); + BN_mod_mul(y, y, x, mod, big_num_context); + BN_one(coef); + BN_mod_add(y, y, coef, mod, big_num_context); + BN_mod_mul(y, y, x, mod, big_num_context); + BN_clear_free(coef); + return y; +} + +static BIGNUM *get_double_x(BIGNUM *x, const BIGNUM *mod, BN_CTX *big_num_context) { + // returns x_2 =(x^2 - 1)^2/(4*y^2) + BIGNUM *denominator = get_y2(x, mod, big_num_context); + assert(denominator != NULL); + BIGNUM *coef = BN_new(); + BN_set_word(coef, 4); + BN_mod_mul(denominator, denominator, coef, mod, big_num_context); + + BIGNUM *numerator = BN_new(); + assert(numerator != NULL); + BN_mod_mul(numerator, x, x, mod, big_num_context); + BN_one(coef); + BN_mod_sub(numerator, numerator, coef, mod, big_num_context); + BN_mod_mul(numerator, numerator, numerator, mod, big_num_context); + + BN_mod_inverse(denominator, denominator, mod, big_num_context); + BN_mod_mul(numerator, numerator, denominator, mod, big_num_context); + + BN_clear_free(coef); + BN_clear_free(denominator); + return numerator; +} + +static void generate_public_key(unsigned char *key) { + BIGNUM *mod = NULL; + BN_hex2bn(&mod, "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed"); + BIGNUM *pow = NULL; + BN_hex2bn(&pow, "3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6"); + BN_CTX *big_num_context = BN_CTX_new(); + assert(big_num_context != NULL); + + BIGNUM *x = BN_new(); + while (1) { + RAND_bytes(key, 32); + key[31] &= 127; + BN_bin2bn(key, 32, x); + assert(x != NULL); + BN_mod_mul(x, x, x, mod, big_num_context); + + BIGNUM *y = get_y2(x, mod, big_num_context); + + BIGNUM *r = BN_new(); + BN_mod_exp(r, y, pow, mod, big_num_context); + BN_clear_free(y); + if (BN_is_one(r)) { + BN_clear_free(r); + break; + } + BN_clear_free(r); + } + + int i; + for (i = 0; i < 3; i++) { + BIGNUM *x2 = get_double_x(x, mod, big_num_context); + BN_clear_free(x); + x = x2; + } + + int num_size = BN_num_bytes(x); + assert(num_size <= 32); + memset(key, '\0', 32 - num_size); + BN_bn2bin(x, key + (32 - num_size)); + for (i = 0; i < 16; i++) { + unsigned char t = key[i]; + key[i] = key[31 - i]; + key[31 - i] = t; + } + + BN_clear_free(x); + BN_CTX_free(big_num_context); + BN_clear_free(pow); + BN_clear_free(mod); +} + class TlsHello { public: @@ -51,7 +141,7 @@ class TlsHello { struct Op { enum class Type { - String, Random, Zero, Domain, Grease, BeginScope, EndScope + String, Random, K, Zero, Domain, Grease, BeginScope, EndScope }; Type type; size_t length; @@ -72,6 +162,13 @@ class TlsHello { return res; } + static Op K() { + Op res; + res.type = Type::K; + res.length = 32; + return res; + } + static Op zero(size_t length) { Op res; res.type = Type::Zero; @@ -135,7 +232,7 @@ class TlsHello { "\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06\x01\x02\x01\x00\x12\x00\x00\x00\x33\x00\x2b\x00\x29", 77), Op::grease(4), Op::string("\x00\x01\x00\x00\x1d\x00\x20", 7), - Op::random(32), + Op::K(), Op::string("\x00\x2d\x00\x02\x01\x01\x00\x2b\x00\x0b\x0a", 11), Op::grease(6), Op::string("\x03\x04\x03\x03\x03\x02\x03\x01\x00\x1b\x00\x03\x02\x00\x02", 15), @@ -186,13 +283,21 @@ class TlsHello { RAND_bytes(data + offset, (size_t) op.length); offset += op.length; break; + case Type::K: + generate_public_key(data + offset); + offset += op.length; + break; case Type::Zero: std::memset(data + offset, 0, op.length); offset += op.length; break; case Type::Domain: { - memcpy(data + offset, domain.data(), domain.size()); - offset += domain.size(); + size_t size = domain.size(); + if (size > 253) { + size = 253; + } + memcpy(data + offset, domain.data(), size); + offset += size; break; } case Type::Grease: { @@ -460,7 +565,6 @@ void ConnectionSocket::onEvent(uint32_t events) { NativeByteBuffer *buffer = ConnectionsManager::getInstance(instanceNum).networkBuffer; while (true) { buffer->rewind(); - Connection *connection = (Connection *) this; readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0); if (readCount < 0) { closeSocket(1, -1); @@ -590,9 +694,15 @@ void ConnectionSocket::onEvent(uint32_t events) { } if (tlsState != 0) { while (buffer->hasRemaining()) { - size_t newBytesRead = (tlsBuffer != nullptr ? tlsBuffer->position() : 0) + buffer->remaining(); + size_t newBytesRead = buffer->remaining(); + if (tlsBuffer != nullptr) { + newBytesRead += tlsBuffer->position(); + if (tlsBufferSized) { + newBytesRead += 5; + } + } if (newBytesRead >= 5) { - if (tlsBuffer == nullptr || tlsBuffer->limit() < 5) { + if (tlsBuffer == nullptr || !tlsBufferSized) { uint32_t pos = buffer->position(); uint8_t offset = 0; @@ -601,6 +711,7 @@ void ConnectionSocket::onEvent(uint32_t events) { offset = (uint8_t) tlsBuffer->position(); memcpy(header, tlsBuffer->bytes(), offset); tlsBuffer->reuse(); + tlsBuffer = nullptr; } memcpy(header + offset, buffer->bytes() + pos, (uint8_t) (5 - offset)); @@ -617,6 +728,7 @@ void ConnectionSocket::onEvent(uint32_t events) { return; } else { tlsBuffer = BuffersStorage::getInstance().getFreeBuffer(len1); + tlsBufferSized = true; buffer->position(pos + (5 - offset)); } } else { @@ -639,6 +751,7 @@ void ConnectionSocket::onEvent(uint32_t events) { } else { if (tlsBuffer == nullptr) { tlsBuffer = BuffersStorage::getInstance().getFreeBuffer(4); + tlsBufferSized = false; } tlsBuffer->writeBytes(buffer); if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS response wait for more data, not enough bytes for header, total = %d", this, (int) tlsBuffer->position()); diff --git a/TMessagesProj/jni/tgnet/ConnectionSocket.h b/TMessagesProj/jni/tgnet/ConnectionSocket.h index a9c816ab1f6..16c0371d92f 100644 --- a/TMessagesProj/jni/tgnet/ConnectionSocket.h +++ b/TMessagesProj/jni/tgnet/ConnectionSocket.h @@ -74,6 +74,7 @@ class ConnectionSocket { std::string currentSecretDomain; bool tlsHashMismatch = false; + bool tlsBufferSized = true; NativeByteBuffer *tlsBuffer = nullptr; ByteArray *tempBuffer = nullptr; size_t bytesRead = 0; diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 999f2c275dd..29d25a2907d 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -2721,6 +2721,7 @@ std::string base64UrlDecode(std::string base64) { size_t padding_length = 0; while (!base64.empty() && base64.back() == '=') { + base64.pop_back(); padding_length++; } if (padding_length >= 3 || (padding_length > 0 && ((base64.size() + padding_length) & 3) != 0)) { @@ -2732,10 +2733,9 @@ std::string base64UrlDecode(std::string base64) { } std::string output; - size_t size = base64.size() - padding_length; output.reserve(((base64.size() + 3) >> 2) * 3); - for (size_t i = 0; i < size;) { - size_t left = std::min(size - i, static_cast(4)); + for (size_t i = 0; i < base64.size();) { + size_t left = std::min(base64.size() - i, static_cast(4)); int c = 0; for (size_t t = 0; t < left; t++) { auto value = url_char_to_value[base64.c_str()[i++]]; diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 9c13dfb847f..7ee0458ba76 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -229,6 +229,14 @@ + + + + + + diff --git a/TMessagesProj/src/main/assets/arctic.attheme b/TMessagesProj/src/main/assets/arctic.attheme index 9c738a94d20..382dcba5d57 100644 --- a/TMessagesProj/src/main/assets/arctic.attheme +++ b/TMessagesProj/src/main/assets/arctic.attheme @@ -1,293 +1,294 @@ chat_unreadMessagesStartText=-583890203 chat_editDoneIcon=-15299074 -actionBarDefaultSearchPlaceholder=-2005173381 radioBackgroundChecked=-14638337 -chat_outForwardedNameText=-1 dialogTextBlue=-14709290 -dialogRoundCheckBox=-13653259 -actionBarTabLine=-13655305 -switchThumbChecked=-15299074 windowBackgroundWhiteBlueIcon=-12149256 chat_inSentClockSelected=-7488295 avatar_backgroundActionBarGreen=-1 +chat_goDownButtonCounterBackground=-13459733 +dialogCheckboxSquareBackground=-14380561 +chats_menuPhone=-1006632961 +avatar_actionBarIconOrange=-8684677 +chat_outViews=-1275068417 +avatar_actionBarSelectorCyan=-8684677 +chat_secretTimerBackground=1375731712 +chat_outViaBotNameText=-1 +profile_actionPressedBackground=-13924376 +chat_inPreviewInstantSelectedText=-13464859 +location_sendLocationBackground=-11492107 +avatar_nameInMessageViolet=-8163354 +chat_inAudioSelectedProgress=-2034434 +chats_nameMessage=-13268780 +actionBarDefaultArchived=-1 +chat_messagePanelShadow=-452984832 +chat_inMediaIcon=-1 +avatar_subtitleInProfileViolet=-16777216 +chat_outAudioSeekbarFill=-1 +player_time=-6511440 +chat_outFileProgressSelected=-13332255 +chat_outTimeSelectedText=-1224736769 +switch2Track=-691072 +chat_inContactNameText=-13487566 +chats_menuPhoneCats=-1 +chat_outPreviewLine=-1 +chat_inViaBotNameText=-13464859 +chat_outVoiceSeekbar=1895825407 +chat_outFileIcon=-6113593 +chats_menuTopShadowCats=2924287 +chats_nameMessage_threeLines=-12434359 +chat_inFileProgress=-1 +chat_inContactPhoneSelectedText=-7099204 +chat_outAudioTitleText=-1 +chats_unreadCounter=-15819777 +chat_inReplyMediaMessageSelectedText=-7099204 +avatar_actionBarSelectorOrange=-8684677 +chat_inBubble=-1 +chat_emojiPanelNewTrending=-13329680 +avatar_backgroundActionBarOrange=-1 +windowBackgroundWhiteBlackText=-13421773 +avatar_backgroundActionBarBlue=-1 +dialogTextLink=-14317077 +chat_status=-16478238 +windowBackgroundWhiteBlueHeader=-13723664 +chat_messagePanelVoiceBackground=-14052889 +switchTrackBlueChecked=-16743221 +profile_status=-15033879 +divider=-1644826 +actionBarDefaultIcon=-12562858 +chat_topPanelLine=-364404226 +chat_outInstantSelected=-1 +chat_outSentCheck=-1191182337 +key_graySectionText=-8156525 +chat_outFileSelectedIcon=-7883067 +dialogButton=-13987604 +actionBarDefaultSubtitle=-7630182 +contextProgressInner2=-826024458 +chat_inContactPhoneText=-6182221 +chat_inlineResultIcon=-13328651 +chats_draft=-85777850 +dialogLineProgress=-14508825 +listSelector=1311978291 +chat_serviceLink=-1 +chat_outPreviewInstantText=-1 +chat_inMenuSelected=-6110259 +avatar_actionBarSelectorGreen=-8684677 +chat_inLoaderSelected=-13394195 +chat_outLocationIcon=-452984833 +avatar_actionBarIconViolet=-8684677 +dialogTextRed=-1682082 +chat_inBubbleShadow=1981626195 +chat_outAudioProgress=-10907938 +dialogProgressCircle=-12281108 +avatar_subtitleInProfilePink=-16777216 +player_progress=-14441474 +chat_inReplyLine=-12478487 +dialogLineProgressBackground=-3875601 +chat_inReplyNameText=-13464859 +chat_outAudioPerfomerSelectedText=-1 +profile_title=-13224394 +avatar_actionBarIconRed=-8684677 +chats_onlineCircle=-11810020 +chat_outAudioSelectedProgress=-10907938 +chat_messageTextOut=-1 +chat_inInstant=-14311696 +groupcreate_cursor=-13459475 +avatar_backgroundSaved=-12208385 +returnToCallBackground=-13853967 +chat_fieldOverlayText=-15430146 +chat_messagePanelSend=-12935426 +windowBackgroundWhiteRedText2=-1817262 +avatar_backgroundBlue=-11491866 +chat_inSentClock=-5195068 +chat_outLoaderPhoto=-6113080 +chat_botSwitchToInlineText=-13464859 +chats_nameMessageArchived=-7237231 +dialogTextRed2=-1354403 +avatar_subtitleInProfileOrange=-16777216 +chat_outSentCheckSelected=-1191182337 +chat_inVenueInfoSelectedText=-7099204 +dialogTextBlue2=-14772773 +dialogTextBlue3=-14839830 +dialogTextBlue4=-15625752 +actionBarTabActiveText=-13590803 +calls_callReceivedGreenIcon=-13645978 +chats_pinnedOverlay=100663296 +chat_emojiPanelBadgeBackground=-12276493 +chat_inForwardedNameText=-13464859 +chats_sentError=-65536 +groupcreate_checkbox=-11415476 +chats_actionBackground=-11492107 +chat_outContactNameText=-1 +chat_inSiteNameText=-13464859 +chat_linkSelectBackground=574923242 +windowBackgroundWhiteBlueText=-14579729 +switch2TrackChecked=-11491347 +actionBarDefaultSearch=-16777216 +contextProgressOuter1=-14114562 +contextProgressOuter2=-12213505 +avatar_backgroundActionBarPink=-1 +avatar_actionBarIconCyan=-8291461 +windowBackgroundWhiteLinkText=-13464859 +chat_outVenueInfoText=-256909825 +chat_outContactPhoneText=-1056964609 +chat_inAudioTitleText=-14078928 +actionBarDefaultArchivedIcon=-13815755 +chat_messageLinkIn=-16677912 +chats_menuBackground=-1 +windowBackgroundCheckText=-1 +chat_serviceBackground=1431599255 +chats_secretIcon=-15093466 +chat_inBubbleSelected=-1706753 +chat_outViewsSelected=-1 +chat_outInstant=-1 +actionBarDefaultSearchPlaceholder=-2005173381 +chat_outForwardedNameText=-1 +dialogRoundCheckBox=-13653259 +actionBarTabLine=-13655305 +switchThumbChecked=-15299074 chats_nameMessageArchived_threeLines=-7237231 chat_outSiteNameText=-1 -chat_goDownButtonCounterBackground=-13459733 chat_outUpCall=-4724737 -dialogCheckboxSquareBackground=-14380561 chat_inVoiceSeekbarSelected=-4663576 dialogTextGray=-13460771 -chats_menuPhone=-1006632961 chat_messageLinkOut=-3414273 -avatar_actionBarIconOrange=-8684677 dialogRadioBackgroundChecked=-14311696 picker_badge=-13261833 -chat_outViews=-475472385 -chat_outFileInfoSelectedText=-256909825 -avatar_actionBarSelectorCyan=-8684677 -chat_secretTimerBackground=1375731712 -chat_outAudioDurationSelectedText=-256909825 -chat_outViaBotNameText=-1 +chat_outFileInfoSelectedText=-1056964609 +chat_outAudioDurationSelectedText=-1056964609 avatar_actionBarSelectorPink=-8684677 -profile_actionPressedBackground=-13924376 chat_topPanelTitle=-281900315 chat_inAudioCacheSeekbar=1071179248 -chat_inPreviewInstantSelectedText=-13464859 chat_outContactIcon=-13332255 chat_inFileInfoText=-6182221 avatar_subtitleInProfileBlue=-7500403 chat_inPreviewLine=-12739084 -location_sendLocationBackground=-11492107 profile_creatorIcon=-15626754 -avatar_nameInMessageViolet=-8163354 -chat_inAudioSelectedProgress=-2034434 avatar_subtitleInProfileGreen=-16777216 profile_actionBackground=-12408586 chats_sentCheck=-13915393 chat_outVoiceSeekbarFill=-1 chat_outReplyLine=-1 chat_inAudioSeekbarFill=-11426840 -chats_nameMessage=-13268780 -actionBarDefaultArchived=-1 -chat_messagePanelShadow=-452984832 -chat_inMediaIcon=-1 -avatar_subtitleInProfileViolet=-16777216 progressCircle=-12605954 chat_inContactBackground=-13393417 chat_outVenueInfoSelectedText=-256580097 -chat_outAudioSeekbarFill=-1 -player_time=-6511440 +wallpaperFileOffset=-1 chat_outBubbleShadow=868467 chat_outVenueNameText=-11822380 -chat_outFileProgressSelected=-13332255 -chat_outTimeSelectedText=-424681985 chats_menuCloudBackgroundCats=-12545584 chats_verifiedBackground=-12998152 -switch2Track=-691072 -chat_inContactNameText=-13487566 chat_inTimeSelectedText=-7099204 chat_outFileBackgroundSelected=1351271669 -chats_menuTopBackgroundCats=-2562829 -chats_menuPhoneCats=-1 -chat_outVoiceSeekbarSelected=-1263345153 -chats_menuTopShadowCats=689394308 -chat_outPreviewLine=-1 +chat_outVoiceSeekbarSelected=1895825407 avatar_backgroundActionBarViolet=-1 actionBarDefaultTitle=-13421773 avatar_actionBarIconPink=-8684671 windowBackgroundWhiteBlueButton=-14509832 chats_menuName=-1 listSelectorSDK21=251658240 -chat_inViaBotNameText=-13464859 -chat_outVoiceSeekbar=-1263345153 chat_outFileNameText=-1 picker_enabledButton=-14180619 avatar_nameInMessagePink=-3453050 -chat_outFileIcon=-6113593 windowBackgroundWhiteGrayText=-7629665 musicPicker_buttonBackground=-12212482 -chats_nameMessage_threeLines=-12434359 -chat_inFileProgress=-1 chat_serviceIcon=-1 avatar_actionBarSelectorViolet=-8684677 avatar_nameInMessageBlue=-13464859 -chat_inContactPhoneSelectedText=-7099204 actionBarDefault=-1 -chat_outAudioTitleText=-1 profile_actionIcon=-1 actionBarDefaultSelector=271200053 chats_menuTopShadow=689394308 chat_outAudioPerfomerText=-1 -chats_unreadCounter=-15819777 inappPlayerPlayPause=-14770699 chat_serviceBackgroundSelected=1968470167 chat_inVenueInfoText=-6182221 chat_replyPanelIcons=-12086038 -chat_outSentClockSelected=-1599545857 -chat_inReplyMediaMessageSelectedText=-7099204 +chat_outSentClockSelected=1895825407 featuredStickers_addedIcon=-13325569 -avatar_actionBarSelectorOrange=-8684677 musicPicker_checkbox=-12405250 -chat_inBubble=-1 chat_outFileBackground=1351271669 chat_attachSendBackground=-12608006 -chat_emojiPanelNewTrending=-13329680 dialogBadgeBackground=-13852434 chat_outBubbleSelected=-13332255 -avatar_backgroundActionBarOrange=-1 avatar_backgroundInProfileBlue=-13330708 chat_lockIcon=-9211021 chat_inFileNameText=-14079703 -windowBackgroundWhiteBlackText=-13421773 -avatar_backgroundActionBarBlue=-1 -dialogTextLink=-14317077 chat_inInstantSelected=-13464859 -chat_outFileInfoText=-256909825 -chat_status=-15033879 -windowBackgroundWhiteBlueHeader=-13723664 -chat_outContactPhoneSelectedText=-256909825 -chat_messagePanelVoiceBackground=-14052889 +chat_outFileInfoText=-1056964609 +chat_outContactPhoneSelectedText=-1056964609 chat_inFileInfoSelectedText=-7099204 -switchTrackBlueChecked=-16743221 chat_wallpaper=-2562829 -chat_outMenuSelected=-1063660289 +chat_outMenuSelected=-1862270977 fastScrollActive=-12409618 chat_outLoaderPhotoSelected=-6113593 chat_muteIcon=1718842227 -profile_status=-15033879 -divider=-1644826 -actionBarDefaultIcon=-12562858 chat_selectedBackground=756261375 chat_recordedVoiceBackground=-12675093 -chat_topPanelLine=-364404226 -chat_outInstantSelected=-1 -chat_outSentCheck=-391586305 chats_actionMessage=-13268780 -key_graySectionText=-8156525 avatar_actionBarSelectorBlue=255146562 chat_addContact=-14775579 switchTrackChecked=-12670465 -chat_outFileSelectedIcon=-7883067 chat_inLoader=-12015626 -dialogButton=-13987604 chat_adminSelectedText=-6769974 -actionBarDefaultSubtitle=-7630182 -contextProgressInner2=-826024458 chat_outPreviewInstantSelectedText=-1 -chat_inContactPhoneText=-6182221 -chat_inlineResultIcon=-13328651 -chats_draft=-85777850 avatar_actionBarIconBlue=-12433070 -dialogLineProgress=-14508825 -listSelector=1311978291 -chat_outTimeText=-424681985 -chat_serviceLink=-1 -chat_outPreviewInstantText=-1 +chat_outTimeText=-1224736769 chat_outBubble=-13332245 -chat_inMenuSelected=-6110259 avatar_backgroundActionBarCyan=-1 -avatar_actionBarSelectorGreen=-8684677 -chat_inLoaderSelected=-13394195 -chat_outLocationIcon=-452984833 -avatar_actionBarIconViolet=-8684677 -dialogTextRed=-1682082 -chat_inBubbleShadow=1981626195 actionBarDefaultArchivedTitle=-13420484 -chat_outAudioProgress=-10907938 -dialogProgressCircle=-12281108 -avatar_subtitleInProfilePink=-16777216 -player_progress=-14441474 -chat_inReplyLine=-12478487 +chats_menuTopBackgroundCats=-11299889 chat_outReplyNameText=-1 -chat_outReplyMediaMessageText=-256909825 +chat_outReplyMediaMessageText=-1056964609 chat_textSelectBackground=1027252973 -dialogLineProgressBackground=-3875601 -chat_inReplyNameText=-13464859 -chat_outAudioPerfomerSelectedText=-1 -profile_title=-13224394 actionBarTabSelector=136982325 -avatar_actionBarIconRed=-8684677 player_buttonActive=-13851650 -chats_onlineCircle=-11810020 -chat_outAudioSelectedProgress=-10907938 chat_outLoaderPhotoIcon=-1 -chat_messageTextOut=-1 chat_outContactBackground=-1 sharedMedia_linkPlaceholder=-723724 -chat_inInstant=-14311696 -groupcreate_cursor=-13459475 windowBackgroundWhiteBlueText7=-12149279 -avatar_backgroundSaved=-12208385 -returnToCallBackground=-13853967 chat_outLocationBackground=1352257013 windowBackgroundWhiteBlueText3=-13530406 -chat_fieldOverlayText=-15430146 windowBackgroundWhiteBlueText5=-12935951 windowBackgroundWhiteBlueText4=-12675352 -chat_messagePanelSend=-12935426 chat_replyPanelMessage=-13355980 -windowBackgroundWhiteRedText2=-1817262 chat_inViewsSelected=-6373686 -avatar_backgroundBlue=-11491866 -chat_inSentClock=-5195068 -chat_outLoaderPhoto=-6113080 windowBackgroundWhiteLinkSelection=560114147 chat_outMediaIcon=-13332255 -chat_outAudioCacheSeekbar=1538120191 +chat_outAudioCacheSeekbar=738197503 chats_sentClock=2066650878 -chat_botSwitchToInlineText=-13464859 -chats_nameMessageArchived=-7237231 -dialogTextRed2=-1354403 avatar_subtitleInProfileRed=-16777216 avatar_backgroundActionBarRed=-1 dialogFloatingButton=-12081419 -avatar_subtitleInProfileOrange=-16777216 chats_archiveBackground=-11294989 chat_inPreviewInstantText=-15299362 -chat_outSentCheckSelected=-391586305 -chat_inVenueInfoSelectedText=-7099204 chat_outLoaderSelected=-1 -dialogTextBlue2=-14772773 -dialogTextBlue3=-14839830 -dialogTextBlue4=-15625752 chats_archivePinBackground=-4472113 -actionBarTabActiveText=-13590803 chat_sentError=-65536 avatar_actionBarSelectorRed=-8684677 chat_inAudioDurationSelectedText=-7099204 -calls_callReceivedGreenIcon=-13645978 -chats_pinnedOverlay=100663296 chat_outAudioSeekbarSelected=1487394047 chat_outLoaderPhotoIconSelected=-1314571 -chat_emojiPanelBadgeBackground=-12276493 avatar_actionBarIconGreen=-8291461 -chat_inForwardedNameText=-13464859 -chats_sentError=-65536 -groupcreate_checkbox=-11415476 -chats_actionBackground=-11492107 chat_outReplyMessageText=-1 chat_recordedVoiceDot=-833978 -chat_outContactNameText=-1 chat_inVoiceSeekbarFill=-13132817 chat_outAudioSeekbar=1487394047 graySection=-460552 -chat_inSiteNameText=-13464859 -chat_linkSelectBackground=574923242 -windowBackgroundWhiteBlueText=-14579729 chat_inVoiceSeekbar=-3419430 chat_outFileProgress=-13332255 chat_outLoader=-1 chats_actionPressedBackground=-13466664 -switch2TrackChecked=-11491347 windowBackgroundWhiteGreenText2=-16470987 -actionBarDefaultSearch=-16777216 -contextProgressOuter1=-14114562 chat_replyPanelName=-13464859 -contextProgressOuter2=-12213505 -avatar_backgroundActionBarPink=-1 chat_outMediaIconSelected=-13332255 windowBackgroundWhiteValueText=-12935688 -avatar_actionBarIconCyan=-8291461 -windowBackgroundWhiteLinkText=-13464859 -chat_outAudioDurationText=-256909825 -chat_outMenu=-1063660289 +chat_outAudioDurationText=-1056964609 +chat_outMenu=-1862270977 chats_secretName=-16734706 -chat_outVenueInfoText=-256909825 -chat_outReplyMediaMessageSelectedText=-256909825 -chat_outContactPhoneText=-256909825 -chat_inAudioTitleText=-14078928 +chat_outReplyMediaMessageSelectedText=-1056964609 chat_reportSpam=-704436 -actionBarDefaultArchivedIcon=-13815755 -chat_messageLinkIn=-16677912 -chats_menuBackground=-1 avatar_subtitleInProfileCyan=-16777216 chat_serviceText=-1 -windowBackgroundCheckText=-1 chats_attachMessage=-13268780 -chat_serviceBackground=1431599255 -chats_secretIcon=-15093466 -chat_inBubbleSelected=-1706753 key_changephoneinfo_changeText=-13131798 -chat_outViewsSelected=-1 -chat_outInstant=-1 -chat_outSentClock=-1599545857 +chat_outSentClock=1895825407 diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index 5a9026106a8..0de4f3d2828 100644 Binary files a/TMessagesProj/src/main/assets/bluebubbles.attheme and b/TMessagesProj/src/main/assets/bluebubbles.attheme differ diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index efc566c079f..e7cfb809908 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -99,6 +99,7 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.TextDetailSettingsCell; +import org.telegram.ui.Components.BackgroundGradientDrawable; import org.telegram.ui.Components.ForegroundDetector; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PickerBottomLayout; @@ -248,6 +249,11 @@ public static int[] calcDrawableColor(Drawable drawable) { } } else if (drawable instanceof ColorDrawable) { bitmapColor = ((ColorDrawable) drawable).getColor(); + } else if (drawable instanceof BackgroundGradientDrawable) { + int[] colors = ((BackgroundGradientDrawable) drawable).getColorsList(); + if (colors != null && colors.length > 0) { + bitmapColor = colors[0]; + } } } catch (Exception e) { FileLog.e(e); @@ -267,7 +273,7 @@ public static int[] calcDrawableColor(Drawable drawable) { return result; } - private static double[] rgbToHsv(int r, int g, int b) { + public static double[] rgbToHsv(int r, int g, int b) { double rf = r / 255.0; double gf = g / 255.0; double bf = b / 255.0; @@ -405,7 +411,12 @@ public static boolean isInternalUri(Uri uri) { if (pathString != null && pathString.length() > 4096) { return true; } - String newPath = Utilities.readlink(pathString); + String newPath; + try { + newPath = Utilities.readlink(pathString); + } catch (Throwable e) { + return true; + } if (newPath == null || newPath.equals(pathString)) { break; } @@ -426,6 +437,9 @@ public static boolean isInternalUri(Uri uri) { //igonre } } + if (pathString.endsWith(".attheme")) { + return false; + } return pathString != null && pathString.toLowerCase().contains("/data/data/" + ApplicationLoader.applicationContext.getPackageName()); } @@ -872,7 +886,11 @@ public static ArrayList loadVCardFromStream(Uri uri, int currentAcco user.first_name = vcardData.name; user.last_name = ""; user.id = 0; - user.restriction_reason = vcardData.vcard.toString(); + TLRPC.TL_restrictionReason reason = new TLRPC.TL_restrictionReason(); + reason.text = vcardData.vcard.toString(); + reason.platform = ""; + reason.reason = ""; + user.restriction_reason.add(reason); result.add(user); } } @@ -1232,10 +1250,6 @@ public static float getPixelsInCM(float cm, boolean isX) { return (cm / 2.54f) * (isX ? displayMetrics.xdpi : displayMetrics.ydpi); } - public static long makeBroadcastId(int id) { - return 0x0000000100000000L | ((long) id & 0x00000000FFFFFFFFL); - } - public static int getMyLayerVersion(int layer) { return layer & 0xffff; } @@ -2041,6 +2055,9 @@ public static boolean copyFile(InputStream sourceFile, File destFile) throws IOE } public static boolean copyFile(File sourceFile, File destFile) throws IOException { + if (sourceFile.equals(destFile)) { + return true; + } if (!destFile.exists()) { destFile.createNewFile(); } @@ -2078,9 +2095,9 @@ public static void openDocument(MessageObject message, Activity activity, BaseFr } if (f != null && f.exists()) { if (parentFragment != null && f.getName().toLowerCase().endsWith("attheme")) { - Theme.ThemeInfo themeInfo = Theme.applyThemeFile(f, message.getDocumentName(), true); + Theme.ThemeInfo themeInfo = Theme.applyThemeFile(f, message.getDocumentName(), null, true); if (themeInfo != null) { - parentFragment.presentFragment(new ThemePreviewActivity(f, themeInfo)); + parentFragment.presentFragment(new ThemePreviewActivity(themeInfo)); } else { AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 79ab62ac16d..710afb0db09 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -121,7 +121,7 @@ public void onReceive(Context context, Intent intent) { } try { - PowerManager pm = (PowerManager)ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE); isScreenOn = pm.isScreenOn(); if (BuildVars.LOGS_ENABLED) { FileLog.d("screen state = " + isScreenOn); @@ -146,7 +146,7 @@ public void onReceive(Context context, Intent intent) { } } - ApplicationLoader app = (ApplicationLoader)ApplicationLoader.applicationContext; + ApplicationLoader app = (ApplicationLoader) ApplicationLoader.applicationContext; app.initPlayServices(); if (BuildVars.LOGS_ENABLED) { FileLog.d("app initied"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java index ec5ae77592f..b17b07078ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java @@ -35,7 +35,7 @@ public void onReceive(Context context, Intent intent) { TLRPC.User user1 = accountInstance.getMessagesStorage().getUserSync(lowerId); AndroidUtilities.runOnUIThread(() -> { accountInstance.getMessagesController().putUser(user1, true); - MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); + MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); }); }); return; @@ -47,12 +47,12 @@ public void onReceive(Context context, Intent intent) { TLRPC.Chat chat1 = accountInstance.getMessagesStorage().getChatSync(-lowerId); AndroidUtilities.runOnUIThread(() -> { accountInstance.getMessagesController().putChat(chat1, true); - MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); + MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); }); }); return; } } - MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); + MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java index 443ae1d5a2a..2b34aa3b57b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java @@ -33,7 +33,7 @@ public void onReceive(Context context, Intent intent) { if (dialog_id == 0 || max_id == 0) { return; } - SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialog_id, null, null, true, null, null, null); - MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); + SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialog_id, null, null, true, null, null, null, true, 0); + MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 96aad0dcea8..4d52219da93 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -18,8 +18,8 @@ public class BuildVars { public static boolean LOGS_ENABLED = false; public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = false; - public static int BUILD_VERSION = 1684; - public static String BUILD_VERSION_STRING = "5.10.0"; + public static int BUILD_VERSION = 1710; + public static String BUILD_VERSION_STRING = "5.11.0"; public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index b0f4d4c31c5..0cb0254f6ac 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -13,7 +13,6 @@ public class ChatObject { public static final int CHAT_TYPE_CHAT = 0; - public static final int CHAT_TYPE_BROADCAST = 1; public static final int CHAT_TYPE_CHANNEL = 2; public static final int CHAT_TYPE_USER = 3; public static final int CHAT_TYPE_MEGAGROUP = 4; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java index 2d6ed43d964..213b8cd65e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java @@ -63,6 +63,7 @@ public class ContactsController extends BaseController { private ArrayList profilePhotoPrivacyRules; private ArrayList forwardsPrivacyRules; private ArrayList phonePrivacyRules; + private ArrayList addedByPhonePrivacyRules; public final static int PRIVACY_RULES_TYPE_LASTSEEN = 0; public final static int PRIVACY_RULES_TYPE_INVITE = 1; @@ -71,8 +72,9 @@ public class ContactsController extends BaseController { public final static int PRIVACY_RULES_TYPE_PHOTO = 4; public final static int PRIVACY_RULES_TYPE_FORWARDS = 5; public final static int PRIVACY_RULES_TYPE_PHONE = 6; + public final static int PRIVACY_RULES_TYPE_ADDED_BY_PHONE = 7; - public final static int PRIVACY_RULES_TYPE_COUNT = 7; + public final static int PRIVACY_RULES_TYPE_COUNT = 8; private class MyContentObserver extends ContentObserver { @@ -2325,9 +2327,12 @@ public void loadPrivacySettings() { req.key = new TLRPC.TL_inputPrivacyKeyForwards(); break; case PRIVACY_RULES_TYPE_PHONE: - default: req.key = new TLRPC.TL_inputPrivacyKeyPhoneNumber(); break; + case PRIVACY_RULES_TYPE_ADDED_BY_PHONE: + default: + req.key = new TLRPC.TL_inputPrivacyKeyAddedByPhone(); + break; } getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { @@ -2356,11 +2361,13 @@ public void loadPrivacySettings() { forwardsPrivacyRules = rules.rules; break; case PRIVACY_RULES_TYPE_PHONE: - default: phonePrivacyRules = rules.rules; break; + case PRIVACY_RULES_TYPE_ADDED_BY_PHONE: + default: + addedByPhonePrivacyRules = rules.rules; + break; } - loadingPrivacyInfo[num] = 2; } else { loadingPrivacyInfo[num] = 0; @@ -2403,6 +2410,8 @@ public ArrayList getPrivacyRules(int type) { return forwardsPrivacyRules; case PRIVACY_RULES_TYPE_PHONE: return phonePrivacyRules; + case PRIVACY_RULES_TYPE_ADDED_BY_PHONE: + return addedByPhonePrivacyRules; } return null; } @@ -2430,6 +2439,9 @@ public void setPrivacyRules(ArrayList rules, int type) { case PRIVACY_RULES_TYPE_PHONE: phonePrivacyRules = rules; break; + case PRIVACY_RULES_TYPE_ADDED_BY_PHONE: + addedByPhonePrivacyRules = rules; + break; } getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated); reloadContactsStatuses(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java index f808575eaba..a2fb5bbc24d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java @@ -266,7 +266,7 @@ public DownloadController(int instance) { } AndroidUtilities.runOnUIThread(() -> { - getNotificationCenter().addObserver(DownloadController.this, NotificationCenter.fileDidFailedLoad); + getNotificationCenter().addObserver(DownloadController.this, NotificationCenter.fileDidFailToLoad); getNotificationCenter().addObserver(DownloadController.this, NotificationCenter.fileDidLoad); getNotificationCenter().addObserver(DownloadController.this, NotificationCenter.FileLoadProgressChanged); getNotificationCenter().addObserver(DownloadController.this, NotificationCenter.FileUploadProgressChanged); @@ -892,7 +892,7 @@ private void processLaterArrays() { @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.fileDidFailedLoad || id == NotificationCenter.httpFileDidFailedLoad) { + if (id == NotificationCenter.fileDidFailToLoad || id == NotificationCenter.httpFileDidFailedLoad) { String fileName = (String) args[0]; Integer canceled = (Integer) args[1]; listenerInProgress = true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index f9b62f9875c..c411f75a592 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -41,8 +41,8 @@ public class Emoji { private static boolean inited = false; private static Paint placeholderPaint; private static final int splitCount = 4; - private static Bitmap emojiBmp[][] = new Bitmap[8][splitCount]; - private static boolean loadingEmoji[][] = new boolean[8][splitCount]; + private static Bitmap[][] emojiBmp = new Bitmap[8][splitCount]; + private static boolean[][] loadingEmoji = new boolean[8][splitCount]; public static HashMap emojiUseHistory = new HashMap<>(); public static ArrayList recentEmoji = new ArrayList<>(); @@ -213,7 +213,7 @@ public static EmojiDrawable getEmojiDrawable(CharSequence code) { return ed; } - public static boolean isValidEmoji(String code) { + public static boolean isValidEmoji(CharSequence code) { DrawableInfo info = rects.get(code); if (info == null) { CharSequence newCode = EmojiData.emojiAliasMap.get(code); @@ -629,7 +629,7 @@ public static void loadRecentEmoji() { StringBuilder string = new StringBuilder(); for (int a = 0; a < 4; a++) { char ch = (char) value; - string.insert(0, String.valueOf(ch)); + string.insert(0, ch); value >>= 16; if (value == 0) { break; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 17c978f0340..fb41d5cfc92 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -510,6 +510,7 @@ private int getDownloadedLengthFromOffsetInternal(ArrayList ranges, final } if (range.start <= offset && range.end > offset) { availableLength = 0; + break; } } if (availableLength == 0) { @@ -716,7 +717,12 @@ public boolean start(final FileLoadOperationStream stream, final int streamOffse delayedRequestInfos = new ArrayList<>(currentMaxDownloadRequests - 1); state = stateDownloading; - cacheFileFinal = new File(storePath, fileNameFinal); + if (parentObject instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject; + cacheFileFinal = new File(ApplicationLoader.getFilesDirFixed(), "remote" + theme.id + ".attheme"); + } else { + cacheFileFinal = new File(storePath, fileNameFinal); + } boolean finalFileExist = cacheFileFinal.exists(); if (finalFileExist && totalBytesCount != 0 && totalBytesCount != cacheFileFinal.length()) { cacheFileFinal.delete(); @@ -1127,7 +1133,17 @@ private void onFinishLoadingFile(final boolean increment) { } } if (!ungzip) { - boolean renameResult = cacheFileTemp.renameTo(cacheFileFinal); + boolean renameResult; + if (parentObject instanceof TLRPC.TL_theme) { + try { + renameResult = AndroidUtilities.copyFile(cacheFileTemp, cacheFileFinal); + } catch (Exception e) { + renameResult = false; + FileLog.e(e); + } + } else { + renameResult = cacheFileTemp.renameTo(cacheFileFinal); + } if (!renameResult) { if (BuildVars.LOGS_ENABLED) { FileLog.e("unable to rename temp = " + cacheFileTemp + " to final = " + cacheFileFinal + " retry = " + renameRetryCount); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 11211c44ba1..b9acfae1651 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -479,9 +479,6 @@ public void loadFile(TLRPC.Document document, Object parentObject, int priority, if (cacheType == 0 && document.key != null) { cacheType = 1; } - if (cacheType == 2) { - FileLog.d("test"); - } loadFile(document, null, null, null, null, parentObject, null, 0, priority, cacheType); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 1d45994c477..4a870b5f1d1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -5,6 +5,7 @@ import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; import java.util.ArrayList; import java.util.HashMap; @@ -54,7 +55,7 @@ public static String getKeyForParentObject(Object parentObject) { if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; int channelId = messageObject.getChannelId(); - return "message" + messageObject.getRealId() + "_" + channelId; + return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled; } else if (parentObject instanceof TLRPC.Message) { TLRPC.Message message = (TLRPC.Message) parentObject; int channelId = message.to_id != null ? message.to_id.channel_id : 0; @@ -83,6 +84,9 @@ public static String getKeyForParentObject(Object parentObject) { } else if (parentObject instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) parentObject; return "wallpaper" + wallPaper.id; + } else if (parentObject instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject; + return "theme" + theme.id; } return parentObject != null ? "" + parentObject : null; } @@ -263,7 +267,12 @@ private void requestReferenceFromServer(Object parentObject, String locationKey, if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; int channelId = messageObject.getChannelId(); - if (channelId != 0) { + if (messageObject.scheduled) { + TLRPC.TL_messages_getScheduledMessages req = new TLRPC.TL_messages_getScheduledMessages(); + req.peer = getMessagesController().getInputPeer((int) messageObject.getDialogId()); + req.id.add(messageObject.getRealId()); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); + } else if (channelId != 0) { TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); req.id.add(messageObject.getRealId()); @@ -281,6 +290,15 @@ private void requestReferenceFromServer(Object parentObject, String locationKey, inputWallPaper.access_hash = wallPaper.access_hash; req.wallpaper = inputWallPaper; getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); + } else if (parentObject instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject; + TLRPC.TL_account_getTheme req = new TLRPC.TL_account_getTheme(); + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.id = theme.id; + inputTheme.access_hash = theme.access_hash; + req.theme = inputTheme; + req.format = "android"; + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); } else if (parentObject instanceof TLRPC.WebPage) { TLRPC.WebPage webPage = (TLRPC.WebPage) parentObject; TLRPC.TL_messages_getWebPage req = new TLRPC.TL_messages_getWebPage(); @@ -420,7 +438,7 @@ private void onUpdateObjectReference(Requester requester, byte[] file_reference, } if (done) { multiMediaCache.remove(multiMedia); - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(multiMedia, (ArrayList) objects[1], (ArrayList) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4])); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(multiMedia, (ArrayList) objects[1], (ArrayList) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4], (Boolean) objects[5])); } } else if (requester.args[0] instanceof TLRPC.TL_messages_sendMedia) { TLRPC.TL_messages_sendMedia req = (TLRPC.TL_messages_sendMedia) requester.args[0]; @@ -431,7 +449,7 @@ private void onUpdateObjectReference(Requester requester, byte[] file_reference, TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; mediaPhoto.id.file_reference = file_reference; } - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null)); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, (Boolean) requester.args[6])); } else if (requester.args[0] instanceof TLRPC.TL_messages_editMessage) { TLRPC.TL_messages_editMessage req = (TLRPC.TL_messages_editMessage) requester.args[0]; if (req.media instanceof TLRPC.TL_inputMediaDocument) { @@ -441,7 +459,7 @@ private void onUpdateObjectReference(Requester requester, byte[] file_reference, TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; mediaPhoto.id.file_reference = file_reference; } - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null)); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null, (Boolean) requester.args[6])); } else if (requester.args[0] instanceof TLRPC.TL_messages_saveGif) { TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) requester.args[0]; req.id.file_reference = file_reference; @@ -489,10 +507,10 @@ private void sendErrorToObject(Object[] args, int reason) { Object[] objects = multiMediaCache.get(req); if (objects != null) { multiMediaCache.remove(req); - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(req, (ArrayList) objects[1], (ArrayList) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4])); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(req, (ArrayList) objects[1], (ArrayList) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4], (Boolean) objects[5])); } } else if (args[0] instanceof TLRPC.TL_messages_sendMedia || args[0] instanceof TLRPC.TL_messages_editMessage) { - AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null)); + AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null, (Boolean) args[6])); } else if (args[0] instanceof TLRPC.TL_messages_saveGif) { TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) args[0]; //do nothing @@ -629,6 +647,12 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject wallpapers.add(wallPaper); getMessagesStorage().putWallpapers(wallpapers, 0); } + } else if (response instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) response; + result = getFileReference(theme.document, requester.location, needReplacement, locationReplacement); + if (result != null && cache) { + AndroidUtilities.runOnUIThread(() -> Theme.setThemeFileReference(theme)); + } } else if (response instanceof TLRPC.Vector) { TLRPC.Vector vector = (TLRPC.Vector) response; if (!vector.objects.isEmpty()) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java index 0d69bdbdcd4..63652ab5b43 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java @@ -195,6 +195,7 @@ public void onMessageReceived(RemoteMessage message) { int chat_id; int user_id; long dialog_id = 0; + boolean scheduled; if (custom.has("channel_id")) { channel_id = custom.getInt("channel_id"); dialog_id = -channel_id; @@ -216,17 +217,41 @@ public void onMessageReceived(RemoteMessage message) { if (custom.has("encryption_id")) { dialog_id = ((long) custom.getInt("encryption_id")) << 32; } + if (custom.has("schedule")) { + scheduled = custom.getInt("schedule") == 1; + } else { + scheduled = false; + } if (dialog_id == 0 && "ENCRYPTED_MESSAGE".equals(loc_key)) { dialog_id = -(1L << 32); } if (dialog_id != 0) { - /*int badge; - if (json.has("badge")) { - badge = json.getInt("badge"); - } else { - badge = 1; - }*/ - if ("MESSAGE_DELETED".equals(loc_key)) { + if ("READ_HISTORY".equals(loc_key)) { + int max_id = custom.getInt("max_id"); + final ArrayList updates = new ArrayList<>(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("GCM received read notification max_id = " + max_id + " for dialogId = " + dialog_id); + } + if (channel_id != 0) { + TLRPC.TL_updateReadChannelInbox update = new TLRPC.TL_updateReadChannelInbox(); + update.channel_id = channel_id; + update.max_id = max_id; + updates.add(update); + } else { + TLRPC.TL_updateReadHistoryInbox update = new TLRPC.TL_updateReadHistoryInbox(); + if (user_id != 0) { + update.peer = new TLRPC.TL_peerUser(); + update.peer.user_id = user_id; + } else { + update.peer = new TLRPC.TL_peerChat(); + update.peer.chat_id = chat_id; + } + update.max_id = max_id; + updates.add(update); + } + MessagesController.getInstance(accountFinal).processUpdateArray(updates, null, null, false, 0); + countDownLatch.countDown(); + } else if ("MESSAGE_DELETED".equals(loc_key)) { String messages = custom.getString("messages"); String[] messagesArgs = messages.split(","); SparseArray> deletedMessages = new SparseArray<>(); @@ -313,7 +338,8 @@ public void onMessageReceived(RemoteMessage message) { FileLog.d("GCM received message notification " + loc_key + " for dialogId = " + dialog_id + " mid = " + msg_id); } switch (loc_key) { - case "MESSAGE_TEXT": { + case "MESSAGE_TEXT": + case "CHANNEL_MESSAGE_TEXT": { messageText = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, args[0], args[1]); message1 = args[1]; break; @@ -402,7 +428,8 @@ public void onMessageReceived(RemoteMessage message) { message1 = LocaleController.getString("AttachGame", R.string.AttachGame); break; } - case "MESSAGE_GAME_SCORE": { + case "MESSAGE_GAME_SCORE": + case "CHANNEL_MESSAGE_GAME_SCORE":{ messageText = LocaleController.formatString("NotificationMessageGameScored", R.string.NotificationMessageGameScored, args[0], args[1], args[2]); break; } @@ -431,11 +458,6 @@ public void onMessageReceived(RemoteMessage message) { localMessage = true; break; } - case "CHANNEL_MESSAGE_TEXT": { - messageText = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, args[0], args[1]); - message1 = args[1]; - break; - } case "CHANNEL_MESSAGE_NOTEXT": { messageText = LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, args[0]); message1 = LocaleController.getString("Message", R.string.Message); @@ -506,10 +528,6 @@ public void onMessageReceived(RemoteMessage message) { message1 = LocaleController.getString("AttachGame", R.string.AttachGame); break; } - case "CHANNEL_MESSAGE_GAME_SCORE": { - messageText = LocaleController.formatString("NotificationMessageGameScored", R.string.NotificationMessageGameScored, args[0], args[1], args[2]); - break; - } case "CHANNEL_MESSAGE_FWDS": { messageText = LocaleController.formatString("ChannelMessageFew", R.string.ChannelMessageFew, args[0], LocaleController.formatPluralString("ForwardedMessageCount", Utilities.parseInt(args[1])).toLowerCase()); localMessage = true; @@ -614,7 +632,8 @@ public void onMessageReceived(RemoteMessage message) { message1 = LocaleController.getString("PaymentInvoice", R.string.PaymentInvoice); break; } - case "CHAT_CREATED": { + case "CHAT_CREATED": + case "CHAT_ADD_YOU": { messageText = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, args[0], args[1]); break; } @@ -630,10 +649,6 @@ public void onMessageReceived(RemoteMessage message) { messageText = LocaleController.formatString("NotificationGroupAddMember", R.string.NotificationGroupAddMember, args[0], args[1], args[2]); break; } - case "CHAT_ADD_YOU": { - messageText = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, args[0], args[1]); - break; - } case "CHAT_DELETE_MEMBER": { messageText = LocaleController.formatString("NotificationGroupKickMember", R.string.NotificationGroupKickMember, args[0], args[1]); break; @@ -810,34 +825,20 @@ public void onMessageReceived(RemoteMessage message) { } break; } - case "CONTACT_JOINED": { - //ignored - break; - } - case "AUTH_UNKNOWN": { - //ignored - break; - } - case "AUTH_REGION": { - //ignored - break; - } case "ENCRYPTED_MESSAGE": { messageText = LocaleController.getString("YouHaveNewMessage", R.string.YouHaveNewMessage); name = LocaleController.getString("SecretChatName", R.string.SecretChatName); localMessage = true; break; } + case "CONTACT_JOINED": + case "AUTH_UNKNOWN": + case "AUTH_REGION": + case "LOCKED_MESSAGE": case "ENCRYPTION_REQUEST": case "ENCRYPTION_ACCEPT": - case "LOCKED_MESSAGE": { - //ignored - break; - } - case "PHONE_CALL_REQUEST": { - //ignored - break; - } + case "PHONE_CALL_REQUEST": + case "MESSAGE_MUTED": case "PHONE_CALL_MISSED": { //ignored break; @@ -876,10 +877,11 @@ public void onMessageReceived(RemoteMessage message) { messageOwner.from_id = chat_from_id; messageOwner.mentioned = mention || pinned; messageOwner.silent = silent; + messageOwner.from_scheduled = scheduled; MessageObject messageObject = new MessageObject(currentAccount, messageOwner, messageText, name, userName, localMessage, channel, edited); ArrayList arrayList = new ArrayList<>(); - arrayList.add(messageObject); + arrayList.add(messageObject);//TODO NotificationsController.getInstance(currentAccount).processNewMessages(arrayList, true, true, countDownLatch); } else { countDownLatch.countDown(); @@ -887,31 +889,6 @@ public void onMessageReceived(RemoteMessage message) { } else { countDownLatch.countDown(); } - } else { - int max_id = custom.getInt("max_id"); - final ArrayList updates = new ArrayList<>(); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("GCM received read notification max_id = " + max_id + " for dialogId = " + dialog_id); - } - if (channel_id != 0) { - TLRPC.TL_updateReadChannelInbox update = new TLRPC.TL_updateReadChannelInbox(); - update.channel_id = channel_id; - update.max_id = max_id; - updates.add(update); - } else { - TLRPC.TL_updateReadHistoryInbox update = new TLRPC.TL_updateReadHistoryInbox(); - if (user_id != 0) { - update.peer = new TLRPC.TL_peerUser(); - update.peer.user_id = user_id; - } else { - update.peer = new TLRPC.TL_peerChat(); - update.peer.chat_id = chat_id; - } - update.max_id = max_id; - updates.add(update); - } - MessagesController.getInstance(accountFinal).processUpdateArray(updates, null, null, false, 0); - countDownLatch.countDown(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 4d658451b74..8d5c214a347 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -603,9 +603,9 @@ protected void onPostExecute(final Boolean result) { fileProgresses.remove(cacheImage.url); AndroidUtilities.runOnUIThread(() -> { if (result) { - NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, cacheImage.url); + NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, cacheImage.url, cacheImage.finalFilePath); } else { - NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidFailedLoad, cacheImage.url, 2); + NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidFailToLoad, cacheImage.url, 2); } }); }); @@ -617,7 +617,7 @@ protected void onCancelled() { imageLoadQueue.postRunnable(() -> runHttpTasks(true)); Utilities.stageQueue.postRunnable(() -> { fileProgresses.remove(cacheImage.url); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidFailedLoad, cacheImage.url, 1)); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileDidFailToLoad, cacheImage.url, 1)); }); } } @@ -987,16 +987,24 @@ public void run() { float photoW = opts.outWidth; float photoH = opts.outHeight; float scaleFactor; - if (w_filter > h_filter && photoW > photoH) { + if (w_filter >= h_filter && photoW > photoH) { scaleFactor = Math.max(photoW / w_filter, photoH / h_filter); } else { scaleFactor = Math.min(photoW / w_filter, photoH / h_filter); } - if (scaleFactor < 1) { + if (scaleFactor < 1.2f) { scaleFactor = 1; } opts.inJustDecodeBounds = false; - opts.inSampleSize = (int) scaleFactor; + if (scaleFactor > 1.0f && (photoW > w_filter || photoH > h_filter)) { + int sample = 1; + do { + sample *= 2; + } while (sample * 2 < scaleFactor); + opts.inSampleSize = sample; + } else { + opts.inSampleSize = (int) scaleFactor; + } } } else if (mediaThumbPath != null) { opts.inJustDecodeBounds = true; @@ -1011,11 +1019,15 @@ public void run() { if (scaleFactor < 1) { scaleFactor = 1; } - int sample = 1; - do { - sample *= 2; - } while (sample * 2 < scaleFactor); - opts.inSampleSize = sample; + if (scaleFactor > 1.0f) { + int sample = 1; + do { + sample *= 2; + } while (sample * 2 < scaleFactor); + opts.inSampleSize = sample; + } else { + opts.inSampleSize = (int) scaleFactor; + } } } catch (Throwable e) { FileLog.e(e); @@ -1370,7 +1382,9 @@ private class CacheImage { protected ArrayList imageTypes = new ArrayList<>(); public void addImageReceiver(ImageReceiver imageReceiver, String key, String filter, int type, int guid) { - if (imageReceiverArray.contains(imageReceiver)) { + int index = imageReceiverArray.indexOf(imageReceiver); + if (index >= 0) { + imageReceiverGuidsArray.set(index, guid); return; } imageReceiverArray.add(imageReceiver); @@ -1413,11 +1427,7 @@ public void removeImageReceiver(ImageReceiver imageReceiver) { a--; } } - if (imageReceiverArray.size() == 0) { - for (int a = 0; a < imageReceiverArray.size(); a++) { - imageLoadingByTag.remove(imageReceiverArray.get(a).getTag(currentImageType)); - } - imageReceiverArray.clear(); + if (imageReceiverArray.isEmpty()) { if (imageLocation != null) { if (!forceLoadingImages.containsKey(key)) { if (imageLocation.location != null) { @@ -1627,7 +1637,7 @@ public void fileDidLoaded(final String location, final File finalFile, final int AndroidUtilities.addMediaToGallery(finalFile.toString()); } } - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.fileDidLoad, location); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.fileDidLoad, location, finalFile); ImageLoader.this.fileDidLoaded(location, finalFile, type); }); } @@ -1637,7 +1647,7 @@ public void fileDidFailedLoad(final String location, final int canceled) { fileProgresses.remove(location); AndroidUtilities.runOnUIThread(() -> { ImageLoader.this.fileDidFailedLoad(location, canceled); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.fileDidFailedLoad, location, canceled); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.fileDidFailToLoad, location, canceled); }); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 80795d391f0..c393bbe4481 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -62,6 +62,8 @@ public class LocaleController { public FastDateFormat chatDate; public FastDateFormat chatFullDate; public FastDateFormat formatterScheduleDay; + public FastDateFormat formatterScheduleYear; + public FastDateFormat[] formatterScheduleSend = new FastDateFormat[6]; private HashMap allRules = new HashMap<>(); @@ -1225,13 +1227,18 @@ public void onDeviceConfigurationChange(Configuration newConfig) { } public static String formatDateChat(long date) { + return formatDateChat(date, false); + } + + public static String formatDateChat(long date, boolean checkYear) { try { - Calendar rightNow = Calendar.getInstance(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + int currentYear = calendar.get(Calendar.YEAR); date *= 1000; - rightNow.setTimeInMillis(date); - - if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) { + calendar.setTimeInMillis(date); + if (checkYear && currentYear == calendar.get(Calendar.YEAR) || !checkYear && Math.abs(System.currentTimeMillis() - date) < 31536000000L) { return getInstance().chatDate.format(date); } return getInstance().chatFullDate.format(date); @@ -1435,11 +1442,18 @@ public void recreateFormatters() { chatDate = createFormatter(locale, getStringInternal("chatDate", R.string.chatDate), "d MMMM"); chatFullDate = createFormatter(locale, getStringInternal("chatFullDate", R.string.chatFullDate), "d MMMM yyyy"); formatterWeek = createFormatter(locale, getStringInternal("formatterWeek", R.string.formatterWeek), "EEE"); - formatterScheduleDay = createFormatter(locale, getStringInternal("formatDateScheduleDay", R.string.formatDateScheduleDay), "EEE MMM d"); + formatterScheduleDay = createFormatter(locale, getStringInternal("formatDateSchedule", R.string.formatDateSchedule), "MMM d"); + formatterScheduleYear = createFormatter(locale, getStringInternal("formatDateScheduleYear", R.string.formatDateScheduleYear), "MMM d yyyy"); formatterDay = createFormatter(lang.toLowerCase().equals("ar") || lang.toLowerCase().equals("ko") ? locale : Locale.US, is24HourFormat ? getStringInternal("formatterDay24H", R.string.formatterDay24H) : getStringInternal("formatterDay12H", R.string.formatterDay12H), is24HourFormat ? "HH:mm" : "h:mm a"); formatterStats = createFormatter(locale, is24HourFormat ? getStringInternal("formatterStats24H", R.string.formatterStats24H) : getStringInternal("formatterStats12H", R.string.formatterStats12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a"); formatterBannedUntil = createFormatter(locale, is24HourFormat ? getStringInternal("formatterBannedUntil24H", R.string.formatterBannedUntil24H) : getStringInternal("formatterBannedUntil12H", R.string.formatterBannedUntil12H), is24HourFormat ? "MMM dd yyyy, HH:mm" : "MMM dd yyyy, h:mm a"); formatterBannedUntilThisYear = createFormatter(locale, is24HourFormat ? getStringInternal("formatterBannedUntilThisYear24H", R.string.formatterBannedUntilThisYear24H) : getStringInternal("formatterBannedUntilThisYear12H", R.string.formatterBannedUntilThisYear12H), is24HourFormat ? "MMM dd, HH:mm" : "MMM dd, h:mm a"); + formatterScheduleSend[0] = createFormatter(locale, getStringInternal("SendTodayAt", R.string.SendTodayAt), "'Send today at' HH:mm"); + formatterScheduleSend[1] = createFormatter(locale, getStringInternal("SendDayAt", R.string.SendDayAt), "'Send on' MMM d 'at' HH:mm"); + formatterScheduleSend[2] = createFormatter(locale, getStringInternal("SendDayYearAt", R.string.SendDayYearAt), "'Send on' MMM d yyyy 'at' HH:mm"); + formatterScheduleSend[3] = createFormatter(locale, getStringInternal("RemindTodayAt", R.string.RemindTodayAt), "'Remind today at' HH:mm"); + formatterScheduleSend[4] = createFormatter(locale, getStringInternal("RemindDayAt", R.string.RemindDayAt), "'Remind on' MMM d 'at' HH:mm"); + formatterScheduleSend[5] = createFormatter(locale, getStringInternal("RemindDayYearAt", R.string.RemindDayYearAt), "'Remind on' MMM d yyyy 'at' HH:mm"); } public static boolean isRTLCharacter(char ch) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java index 837750184c7..6459111cbef 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationController.java @@ -175,6 +175,10 @@ public LocationController(int instance) { @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.didReceiveNewMessages) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } long did = (Long) args[0]; if (!isSharingLocation(did)) { return; @@ -206,6 +210,10 @@ public void didReceivedNotification(int id, int account, Object... args) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.liveLocationsCacheChanged, did, currentAccount); } } else if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } if (!sharingLocationsUI.isEmpty()) { ArrayList markAsDeletedMessages = (ArrayList) args[0]; int channelId = (Integer) args[1]; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java index 76b1503c6da..01c75cad643 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java @@ -52,6 +52,7 @@ public IBinder onBind(Intent arg2) { } public void onDestroy() { + super.onDestroy(); if (handler != null) { handler.removeCallbacks(runnable); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 6f95ff7b9ad..8573ace0ba1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -114,7 +114,7 @@ public AudioBuffer(int capacity) { MediaStore.Images.Media.BUCKET_ID, MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.Images.Media.DATA, - MediaStore.Images.Media.DATE_TAKEN, + Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.ORIENTATION }; @@ -123,7 +123,7 @@ public AudioBuffer(int capacity) { MediaStore.Video.Media.BUCKET_ID, MediaStore.Video.Media.BUCKET_DISPLAY_NAME, MediaStore.Video.Media.DATA, - MediaStore.Video.Media.DATE_TAKEN, + Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN, MediaStore.Video.Media.DURATION }; @@ -235,7 +235,6 @@ public static class SearchImage { public String id; public String imageUrl; public String thumbUrl; - public String localUrl; public int width; public int height; public int size; @@ -253,6 +252,8 @@ public static class SearchImage { public boolean isPainted; public boolean isCropped; public int ttl; + public TLRPC.BotInlineResult inlineResult; + public HashMap params; public SavedFilterState savedFilterState; public ArrayList stickers = new ArrayList<>(); @@ -274,13 +275,6 @@ public String getAttachName() { return FileLoader.getAttachFileName(photoSize); } else if (document != null) { return FileLoader.getAttachFileName(document); - } else if (type != 1 && localUrl != null && localUrl.length() > 0) { - File file = new File(localUrl); - if (file.exists()) { - return file.getName(); - } else { - localUrl = ""; - } } return Utilities.MD5(imageUrl) + "." + ImageLoader.getHttpUrlExtension(imageUrl, "jpg"); } @@ -406,6 +400,7 @@ public void run() { private AudioRecord audioRecorder; private TLRPC.TL_document recordingAudio; + private int recordingGuid = -1; private int recordingCurrentAccount; private File recordingAudioFile; private long recordStartTime; @@ -421,6 +416,8 @@ public void run() { private ByteBuffer fileBuffer; private int recordBufferSize = 1280; private int sendAfterDone; + private boolean sendAfterDoneNotify; + private int sendAfterDoneScheduleDate; private Runnable recordStartRunnable; private DispatchQueue recordQueue; @@ -500,10 +497,12 @@ public void run() { }); } recordQueue.postRunnable(recordRunnable); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordProgressChanged, System.currentTimeMillis() - recordStartTime, amplitude)); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordProgressChanged, recordingGuid, System.currentTimeMillis() - recordStartTime, amplitude)); } else { recordBuffers.add(buffer); - stopRecordingInternal(sendAfterDone); + if (sendAfterDone != 3) { + stopRecordingInternal(sendAfterDone, sendAfterDoneNotify, sendAfterDoneScheduleDate); + } } } } @@ -737,7 +736,7 @@ public void onCallStateChanged(final int state, String incomingNumber) { if (isPlayingMessage(playingMessageObject) && !isMessagePaused()) { pauseMessage(playingMessageObject); } else if (recordStartRunnable != null || recordingAudio != null) { - stopRecording(2); + stopRecording(2, false, 0); } EmbedBottomSheet embedBottomSheet = EmbedBottomSheet.getInstance(); if (embedBottomSheet != null) { @@ -783,7 +782,7 @@ public void onCallStateChanged(final int state, String incomingNumber) { MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DISPLAY_NAME, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, - MediaStore.Images.ImageColumns.DATE_TAKEN, + Build.VERSION.SDK_INT > 28 ? MediaStore.Images.ImageColumns.DATE_MODIFIED : MediaStore.Images.ImageColumns.DATE_TAKEN, MediaStore.Images.ImageColumns.TITLE, MediaStore.Images.ImageColumns.WIDTH, MediaStore.Images.ImageColumns.HEIGHT @@ -884,7 +883,7 @@ public void run() { if (videoPlayer != null) { duration = videoPlayer.getDuration(); progress = videoPlayer.getCurrentPosition(); - if (duration == C.TIME_UNSET || progress == C.TIME_UNSET || progress < 0 || duration <= 0) { + if (progress < 0 || duration <= 0) { return; } bufferedValue = videoPlayer.getBufferedPosition() / (float) duration; @@ -895,7 +894,7 @@ public void run() { } else { duration = audioPlayer.getDuration(); progress = audioPlayer.getCurrentPosition(); - value = duration != C.TIME_UNSET && duration >= 0 ? (progress / (float) duration) : 0.0f; + value = duration >= 0 ? (progress / (float) duration) : 0.0f; bufferedValue = audioPlayer.getBufferedPosition() / (float) duration; /*if (audioPlayer.isStreaming()) { bufferedValue = FileLoader.getInstance(currentPlayingMessageObject.currentAccount).getBufferedProgressFromPosition(value, fileName); @@ -1088,6 +1087,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } int channelId = (Integer) args[1]; ArrayList markAsDeletedMessages = (ArrayList) args[0]; if (playingMessageObject != null) { @@ -1117,7 +1120,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.musicDidLoad) { long did = (Long) args[0]; - if (playingMessageObject != null && playingMessageObject.isMusic() && playingMessageObject.getDialogId() == did) { + if (playingMessageObject != null && playingMessageObject.isMusic() && playingMessageObject.getDialogId() == did && !playingMessageObject.scheduled) { ArrayList arrayList = (ArrayList) args[1]; playlist.addAll(0, arrayList); if (SharedConfig.shuffleMusic) { @@ -1128,6 +1131,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.didReceiveNewMessages) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } if (voiceMessagesPlaylist != null && !voiceMessagesPlaylist.isEmpty()) { MessageObject messageObject = voiceMessagesPlaylist.get(0); long did = (Long) args[0]; @@ -1330,7 +1337,7 @@ public void onSensorChanged(SensorEvent event) { if (!raiseChat.playFirstUnreadVoiceMessage()) { raiseToEarRecord = true; useFrontSpeaker = false; - startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null); + startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getClassGuid()); } if (useFrontSpeaker) { setUseFrontSpeaker(true); @@ -1376,7 +1383,7 @@ public void onSensorChanged(SensorEvent event) { if (BuildVars.LOGS_ENABLED) { FileLog.d("stop record"); } - stopRecording(2); + stopRecording(2, false, 0); raiseToEarRecord = false; ignoreOnPause = false; if (proximityHasDifferentValues && proximityWakeLock != null && proximityWakeLock.isHeld()) { @@ -1419,7 +1426,7 @@ public void startRecordingIfFromSpeaker() { return; } raiseToEarRecord = true; - startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null); + startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getClassGuid()); ignoreOnPause = true; } @@ -1505,7 +1512,7 @@ public void stopRaiseToEarSensors(ChatActivity chatActivity, boolean fromChat) { ignoreOnPause = false; return; } - stopRecording(fromChat ? 2 : 0); + stopRecording(fromChat ? 2 : 0, false, 0); if (!sensorsStarted || ignoreOnPause || accelerometerSensor == null && (gravitySensor == null || linearAcceleration == null) || proximitySensor == null || raiseChat != chatActivity) { return; } @@ -1725,7 +1732,7 @@ public boolean setPlaylist(ArrayList messageObjects, MessageObjec currentPlaylistNum = playlist.size(); playlist.add(current); } - if (current.isMusic()) { + if (current.isMusic() && !current.scheduled) { if (SharedConfig.shuffleMusic) { buildShuffledPlayList(); currentPlaylistNum = 0; @@ -2439,7 +2446,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { } }); currentAspectRatioFrameLayoutReady = false; - if (pipRoundVideoView != null || !MessagesController.getInstance(messageObject.currentAccount).isDialogVisible(messageObject.getDialogId())) { + if (pipRoundVideoView != null || !MessagesController.getInstance(messageObject.currentAccount).isDialogVisible(messageObject.getDialogId(), messageObject.scheduled)) { if (pipRoundVideoView == null) { try { pipRoundVideoView = new PipRoundVideoView(); @@ -2457,7 +2464,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { if (exists) { if (!messageObject.mediaExists && cacheFile != file) { - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()))); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile)); } videoPlayer.preparePlayer(Uri.fromFile(cacheFile), "other"); } else { @@ -2538,7 +2545,7 @@ public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { }); if (exists) { if (!messageObject.mediaExists && cacheFile != file) { - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()))); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile)); } audioPlayer.preparePlayer(Uri.fromFile(cacheFile), "other"); } else { @@ -2763,7 +2770,7 @@ public void setReplyingMessage(MessageObject reply_to_msg) { recordReplyingMessageObject = reply_to_msg; } - public void startRecording(final int currentAccount, final long dialog_id, final MessageObject reply_to_msg) { + public void startRecording(final int currentAccount, final long dialog_id, final MessageObject reply_to_msg, int guid) { boolean paused = false; if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) { paused = true; @@ -2780,12 +2787,14 @@ public void startRecording(final int currentAccount, final long dialog_id, final if (audioRecorder != null) { AndroidUtilities.runOnUIThread(() -> { recordStartRunnable = null; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid); }); return; } + sendAfterDone = 0; recordingAudio = new TLRPC.TL_document(); + recordingGuid = guid; recordingAudio.file_reference = new byte[0]; recordingAudio.dc_id = Integer.MIN_VALUE; recordingAudio.id = SharedConfig.getLastLocalId(); @@ -2800,7 +2809,7 @@ public void startRecording(final int currentAccount, final long dialog_id, final if (startRecord(recordingAudioFile.getAbsolutePath()) == 0) { AndroidUtilities.runOnUIThread(() -> { recordStartRunnable = null; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid); }); return; } @@ -2830,7 +2839,7 @@ public void startRecording(final int currentAccount, final long dialog_id, final AndroidUtilities.runOnUIThread(() -> { recordStartRunnable = null; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid); }); return; } @@ -2838,7 +2847,7 @@ public void startRecording(final int currentAccount, final long dialog_id, final recordQueue.postRunnable(recordRunnable); AndroidUtilities.runOnUIThread(() -> { recordStartRunnable = null; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStarted); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStarted, guid); }); }, paused ? 500 : 50); } @@ -2868,7 +2877,7 @@ public void generateWaveform(MessageObject messageObject) { } TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); messagesRes.messages.add(messageObject1.messageOwner); - MessagesStorage.getInstance(messageObject1.currentAccount).putMessages(messagesRes, messageObject1.getDialogId(), -1, 0, false); + MessagesStorage.getInstance(messageObject1.currentAccount).putMessages(messagesRes, messageObject1.getDialogId(), -1, 0, false, messageObject.scheduled); ArrayList arrayList = new ArrayList<>(); arrayList.add(messageObject1); NotificationCenter.getInstance(messageObject1.currentAccount).postNotificationName(NotificationCenter.replaceMessagesObjects, messageObject1.getDialogId(), arrayList); @@ -2877,7 +2886,7 @@ public void generateWaveform(MessageObject messageObject) { }); } - private void stopRecordingInternal(final int send) { + private void stopRecordingInternal(final int send, boolean notify, int scheduleDate) { if (send != 0) { final TLRPC.TL_document audioToSend = recordingAudio; final File recordingAudioFileToSend = recordingAudioFile; @@ -2897,15 +2906,19 @@ private void stopRecordingInternal(final int send) { audioToSend.attributes.add(attributeAudio); if (duration > 700) { if (send == 1) { - SendMessagesHelper.getInstance(recordingCurrentAccount).sendMessage(audioToSend, null, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMessageObject, null, null, null, null, 0, null); + SendMessagesHelper.getInstance(recordingCurrentAccount).sendMessage(audioToSend, null, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMessageObject, null, null, null, null, notify, scheduleDate, 0, null); } - NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, send == 2 ? audioToSend : null, send == 2 ? recordingAudioFileToSend.getAbsolutePath() : null); + NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, send == 2 ? audioToSend : null, send == 2 ? recordingAudioFileToSend.getAbsolutePath() : null); } else { - NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioRecordTooShort, false); + NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioRecordTooShort, recordingGuid, false); recordingAudioFileToSend.delete(); } }); }); + } else { + if (recordingAudioFile != null) { + recordingAudioFile.delete(); + } } try { if (audioRecorder != null) { @@ -2919,17 +2932,24 @@ private void stopRecordingInternal(final int send) { recordingAudioFile = null; } - public void stopRecording(final int send) { + public void stopRecording(final int send, boolean notify, int scheduleDate) { if (recordStartRunnable != null) { recordQueue.cancelRunnable(recordStartRunnable); recordStartRunnable = null; } recordQueue.postRunnable(() -> { + if (sendAfterDone == 3) { + sendAfterDone = 0; + stopRecordingInternal(send, notify, scheduleDate); + return; + } if (audioRecorder == null) { return; } try { sendAfterDone = send; + sendAfterDoneNotify = notify; + sendAfterDoneScheduleDate = scheduleDate; audioRecorder.stop(); } catch (Exception e) { FileLog.e(e); @@ -2938,14 +2958,14 @@ public void stopRecording(final int send) { } } if (send == 0) { - stopRecordingInternal(0); + stopRecordingInternal(0, false, 0); } try { feedbackView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } catch (Exception ignore) { } - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordStopped, send == 2 ? 1 : 0)); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordStopped, recordingGuid, send == 2 ? 1 : 0)); }); } @@ -3216,13 +3236,13 @@ public static void loadGalleryPhotosAlbums(final int guid) { Cursor cursor = null; try { if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, null, null, MediaStore.Images.Media.DATE_TAKEN + " DESC"); + cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, null, null, Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN + " DESC"); if (cursor != null) { int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID); int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID); int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME); int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA); - int dateColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN); + int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_MODIFIED : MediaStore.Images.Media.DATE_TAKEN); int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION); while (cursor.moveToNext()) { @@ -3292,13 +3312,13 @@ public static void loadGalleryPhotosAlbums(final int guid) { try { if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, null, null, MediaStore.Video.Media.DATE_TAKEN + " DESC"); + cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, null, null, Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN + " DESC"); if (cursor != null) { int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID); int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID); int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME); int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA); - int dateColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN); + int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_MODIFIED : MediaStore.Video.Media.DATE_TAKEN); int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION); while (cursor.moveToNext()) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 519b9499244..08dfd9fdb3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -188,6 +188,16 @@ public void cleanup() { recentGifsLoaded = false; currentFetchingEmoji.clear(); + if (Build.VERSION.SDK_INT >= 25) { + Utilities.globalQueue.postRunnable(() -> { + try { + ShortcutManager shortcutManager = ApplicationLoader.applicationContext.getSystemService(ShortcutManager.class); + shortcutManager.removeAllDynamicShortcuts(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } loading = false; loaded = false; @@ -227,6 +237,9 @@ public ArrayList getRecentStickersNoCopy(int type) { } public boolean isStickerInFavorites(TLRPC.Document document) { + if (document == null) { + return false; + } for (int a = 0; a < recentStickers[TYPE_FAVE].size(); a++) { TLRPC.Document d = recentStickers[TYPE_FAVE].get(a); if (d.id == document.id && d.dc_id == document.dc_id) { @@ -237,7 +250,7 @@ public boolean isStickerInFavorites(TLRPC.Document document) { } public void addRecentSticker(final int type, Object parentObject, TLRPC.Document document, int date, boolean remove) { - if (document == null) { + if (!MessageObject.isStickerDocument(document)) { return; } boolean found = false; @@ -3264,7 +3277,7 @@ private static void removeEmptyMessages(ArrayList messages) { } } - public void loadReplyMessagesForMessages(final ArrayList messages, final long dialogId) { + public void loadReplyMessagesForMessages(final ArrayList messages, final long dialogId, boolean scheduled) { if ((int) dialogId == 0) { final ArrayList replyMessages = new ArrayList<>(); final LongSparseArray> replyMessageRandomOwners = new LongSparseArray<>(); @@ -3409,7 +3422,7 @@ public void loadReplyMessagesForMessages(final ArrayList messages ImageLoader.saveMessagesThumbs(messagesRes.messages); broadcastReplyMessages(messagesRes.messages, replyMessageOwners, messagesRes.users, messagesRes.chats, dialogId, false); getMessagesStorage().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true); - saveReplyMessages(replyMessageOwners, messagesRes.messages); + saveReplyMessages(replyMessageOwners, messagesRes.messages, scheduled); } }); } else { @@ -3422,7 +3435,7 @@ public void loadReplyMessagesForMessages(final ArrayList messages ImageLoader.saveMessagesThumbs(messagesRes.messages); broadcastReplyMessages(messagesRes.messages, replyMessageOwners, messagesRes.users, messagesRes.chats, dialogId, false); getMessagesStorage().putUsersAndChats(messagesRes.users, messagesRes.chats, true, true); - saveReplyMessages(replyMessageOwners, messagesRes.messages); + saveReplyMessages(replyMessageOwners, messagesRes.messages, scheduled); } }); } @@ -3434,11 +3447,16 @@ public void loadReplyMessagesForMessages(final ArrayList messages } } - private void saveReplyMessages(final SparseArray> replyMessageOwners, final ArrayList result) { + private void saveReplyMessages(final SparseArray> replyMessageOwners, final ArrayList result, boolean scheduled) { getMessagesStorage().getStorageQueue().postRunnable(() -> { try { getMessagesStorage().getDatabase().beginTransaction(); - SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE messages SET replydata = ? WHERE mid = ?"); + SQLitePreparedStatement state; + if (scheduled) { + state = getMessagesStorage().getDatabase().executeFast("UPDATE scheduled_messages SET replydata = ? WHERE mid = ?"); + } else { + state = getMessagesStorage().getDatabase().executeFast("UPDATE messages SET replydata = ? WHERE mid = ?"); + } for (int a = 0; a < result.size(); a++) { TLRPC.Message message = result.get(a); ArrayList messageObjects = replyMessageOwners.get(message.id); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 94ca618723c..99b7ae277ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -111,11 +111,14 @@ public class MessageObject { public String customReplyName; public boolean useCustomPhoto; public StringBuilder botButtonsLayout; + public boolean isRestrictedMessage; public boolean hadAnimationNotReadyLoading; public boolean cancelEditing; + public boolean scheduled; + public CharSequence editingMessage; public ArrayList editingMessageEntities; @@ -1712,6 +1715,33 @@ public void generatePinMessageText(TLRPC.User fromUser, TLRPC.Chat chat) { } } + public static void updateReactions(TLRPC.Message message, TLRPC.TL_messageReactions reactions) { + if (message == null || reactions == null) { + return; + } + if (reactions.min && message.reactions != null) { + for (int a = 0, N = message.reactions.results.size(); a < N; a++) { + TLRPC.TL_reactionCount reaction = message.reactions.results.get(a); + if (reaction.chosen) { + for (int b = 0, N2 = reactions.results.size(); b < N2; b++) { + TLRPC.TL_reactionCount newReaction = reactions.results.get(b); + if (reaction.reaction.equals(newReaction.reaction)) { + newReaction.chosen = true; + break; + } + } + break; + } + } + } + message.reactions = reactions; + message.flags |= 1048576; + } + + public boolean hasReactions() { + return messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty(); + } + public static void updatePollResults(TLRPC.TL_messageMediaPoll media, TLRPC.TL_pollResults results) { if ((results.flags & 2) != 0) { byte[] chosen = null; @@ -1894,28 +1924,48 @@ public void createMessageSendInfo() { public void measureInlineBotButtons() { wantedBotKeyboardWidth = 0; - if (!(messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup)) { - return; + if (messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageOwner.reactions != null && !messageOwner.reactions.results.isEmpty()) { + Theme.createChatResources(null, true); + if (botButtonsLayout == null) { + botButtonsLayout = new StringBuilder(); + } else { + botButtonsLayout.setLength(0); + } } - Theme.createChatResources(null, true); - if (botButtonsLayout == null) { - botButtonsLayout = new StringBuilder(); - } else { - botButtonsLayout.setLength(0); - } - for (int a = 0; a < messageOwner.reply_markup.rows.size(); a++) { - TLRPC.TL_keyboardButtonRow row = messageOwner.reply_markup.rows.get(a); - int maxButtonSize = 0; - int size = row.buttons.size(); - for (int b = 0; b < size; b++) { - TLRPC.KeyboardButton button = row.buttons.get(b); - botButtonsLayout.append(a).append(b); - CharSequence text; - if (button instanceof TLRPC.TL_keyboardButtonBuy && (messageOwner.media.flags & 4) != 0) { - text = LocaleController.getString("PaymentReceipt", R.string.PaymentReceipt); - } else { - text = Emoji.replaceEmoji(button.text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + + if (messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) { + for (int a = 0; a < messageOwner.reply_markup.rows.size(); a++) { + TLRPC.TL_keyboardButtonRow row = messageOwner.reply_markup.rows.get(a); + int maxButtonSize = 0; + int size = row.buttons.size(); + for (int b = 0; b < size; b++) { + TLRPC.KeyboardButton button = row.buttons.get(b); + botButtonsLayout.append(a).append(b); + CharSequence text; + if (button instanceof TLRPC.TL_keyboardButtonBuy && (messageOwner.media.flags & 4) != 0) { + text = LocaleController.getString("PaymentReceipt", R.string.PaymentReceipt); + } else { + text = Emoji.replaceEmoji(button.text, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + } + StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, AndroidUtilities.dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (staticLayout.getLineCount() > 0) { + float width = staticLayout.getLineWidth(0); + float left = staticLayout.getLineLeft(0); + if (left < width) { + width -= left; + } + maxButtonSize = Math.max(maxButtonSize, (int) Math.ceil(width) + AndroidUtilities.dp(4)); + } } + wantedBotKeyboardWidth = Math.max(wantedBotKeyboardWidth, (maxButtonSize + AndroidUtilities.dp(12)) * size + AndroidUtilities.dp(5) * (size - 1)); + } + } else if (messageOwner.reactions != null) { + int size = messageOwner.reactions.results.size(); + for (int a = 0; a < size; a++) { + TLRPC.TL_reactionCount reactionCount = messageOwner.reactions.results.get(a); + int maxButtonSize = 0; + botButtonsLayout.append(0).append(a); + CharSequence text = Emoji.replaceEmoji(String.format("%d %s", reactionCount.count, reactionCount.reaction), Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, AndroidUtilities.dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (staticLayout.getLineCount() > 0) { float width = staticLayout.getLineWidth(0); @@ -1925,8 +1975,8 @@ public void measureInlineBotButtons() { } maxButtonSize = Math.max(maxButtonSize, (int) Math.ceil(width) + AndroidUtilities.dp(4)); } + wantedBotKeyboardWidth = Math.max(wantedBotKeyboardWidth, (maxButtonSize + AndroidUtilities.dp(12)) * size + AndroidUtilities.dp(5) * (size - 1)); } - wantedBotKeyboardWidth = Math.max(wantedBotKeyboardWidth, (maxButtonSize + AndroidUtilities.dp(12)) * size + AndroidUtilities.dp(5) * (size - 1)); } } @@ -2281,63 +2331,70 @@ private void updateMessageText(AbstractMap users, AbstractM messageText = LocaleController.formatString("ActionBotDocuments", R.string.ActionBotDocuments, UserObject.getFirstName(user), str.toString()); } } - } else if (!isMediaEmpty()) { - if (messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - messageText = LocaleController.getString("Poll", R.string.Poll); - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { - if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { - messageText = LocaleController.getString("AttachDestructingPhoto", R.string.AttachDestructingPhoto); - } else { - messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto); - } - } else if (isVideo() || messageOwner.media instanceof TLRPC.TL_messageMediaDocument && getDocument() instanceof TLRPC.TL_documentEmpty && messageOwner.media.ttl_seconds != 0) { - if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { - messageText = LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo); - } else { - messageText = LocaleController.getString("AttachVideo", R.string.AttachVideo); - } - } else if (isVoice()) { - messageText = LocaleController.getString("AttachAudio", R.string.AttachAudio); - } else if (isRoundVideo()) { - messageText = LocaleController.getString("AttachRound", R.string.AttachRound); - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { - messageText = LocaleController.getString("AttachLocation", R.string.AttachLocation); - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { - messageText = LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation); - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - messageText = LocaleController.getString("AttachContact", R.string.AttachContact); - if (!TextUtils.isEmpty(messageOwner.media.vcard)) { - vCardData = VCardData.parse(messageOwner.media.vcard); - } - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - messageText = messageOwner.message; - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { - messageText = messageOwner.media.description; - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) { - messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia); - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - if (isSticker() || isAnimatedSticker()) { - String sch = getStrickerChar(); - if (sch != null && sch.length() > 0) { - messageText = String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker)); + } else { + isRestrictedMessage = false; + String restrictionReason = MessagesController.getRestrictionReason(messageOwner.restriction_reason); + if (!TextUtils.isEmpty(restrictionReason)) { + messageText = restrictionReason; + isRestrictedMessage = true; + } else if (!isMediaEmpty()) { + if (messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { + messageText = LocaleController.getString("Poll", R.string.Poll); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { + if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { + messageText = LocaleController.getString("AttachDestructingPhoto", R.string.AttachDestructingPhoto); } else { - messageText = LocaleController.getString("AttachSticker", R.string.AttachSticker); + messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto); } - } else if (isMusic()) { - messageText = LocaleController.getString("AttachMusic", R.string.AttachMusic); - } else if (isGif()) { - messageText = LocaleController.getString("AttachGif", R.string.AttachGif); - } else { - String name = FileLoader.getDocumentFileName(getDocument()); - if (name != null && name.length() > 0) { - messageText = name; + } else if (isVideo() || messageOwner.media instanceof TLRPC.TL_messageMediaDocument && getDocument() instanceof TLRPC.TL_documentEmpty && messageOwner.media.ttl_seconds != 0) { + if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { + messageText = LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo); } else { - messageText = LocaleController.getString("AttachDocument", R.string.AttachDocument); + messageText = LocaleController.getString("AttachVideo", R.string.AttachVideo); + } + } else if (isVoice()) { + messageText = LocaleController.getString("AttachAudio", R.string.AttachAudio); + } else if (isRoundVideo()) { + messageText = LocaleController.getString("AttachRound", R.string.AttachRound); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { + messageText = LocaleController.getString("AttachLocation", R.string.AttachLocation); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { + messageText = LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaContact) { + messageText = LocaleController.getString("AttachContact", R.string.AttachContact); + if (!TextUtils.isEmpty(messageOwner.media.vcard)) { + vCardData = VCardData.parse(messageOwner.media.vcard); + } + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { + messageText = messageOwner.message; + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { + messageText = messageOwner.media.description; + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) { + messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + if (isSticker() || isAnimatedSticker()) { + String sch = getStrickerChar(); + if (sch != null && sch.length() > 0) { + messageText = String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker)); + } else { + messageText = LocaleController.getString("AttachSticker", R.string.AttachSticker); + } + } else if (isMusic()) { + messageText = LocaleController.getString("AttachMusic", R.string.AttachMusic); + } else if (isGif()) { + messageText = LocaleController.getString("AttachGif", R.string.AttachGif); + } else { + String name = FileLoader.getDocumentFileName(getDocument()); + if (name != null && name.length() > 0) { + messageText = name; + } else { + messageText = LocaleController.getString("AttachDocument", R.string.AttachDocument); + } } } + } else { + messageText = messageOwner.message; } - } else { - messageText = messageOwner.message; } if (messageText == null) { @@ -2349,7 +2406,9 @@ public void setType() { int oldType = type; isRoundVideoCached = 0; if (messageOwner instanceof TLRPC.TL_message || messageOwner instanceof TLRPC.TL_messageForwarded_old2) { - if (emojiAnimatedSticker != null) { + if (isRestrictedMessage) { + type = 0; + } else if (emojiAnimatedSticker != null) { if (isSticker()) { type = TYPE_STICKER; } else { @@ -3172,11 +3231,20 @@ public void resetPlayingProgress() { } private boolean addEntitiesToText(CharSequence text, boolean useManualParse) { - return addEntitiesToText(text, messageOwner.entities, isOutOwner(), type, true, false, useManualParse); + return addEntitiesToText(text, false, useManualParse); } public boolean addEntitiesToText(CharSequence text, boolean photoViewer, boolean useManualParse) { - return addEntitiesToText(text, messageOwner.entities, isOutOwner(), type, true, photoViewer, useManualParse); + if (isRestrictedMessage) { + ArrayList entities = new ArrayList<>(); + TLRPC.TL_messageEntityItalic entityItalic = new TLRPC.TL_messageEntityItalic(); + entityItalic.offset = 0; + entityItalic.length = text.length(); + entities.add(entityItalic); + return addEntitiesToText(text, entities, isOutOwner(), type, true, photoViewer, useManualParse); + } else { + return addEntitiesToText(text, messageOwner.entities, isOutOwner(), type, true, photoViewer, useManualParse); + } } public static boolean addEntitiesToText(CharSequence text, ArrayList entities, boolean out, int type, boolean usernames, boolean photoViewer, boolean useManualParse) { @@ -3391,7 +3459,9 @@ public static boolean addEntitiesToText(CharSequence text, ArrayList 0 && messageOwner.date < ConnectionsManager.getInstance(currentAccount).getCurrentTime() - 60; } public boolean isSent() { @@ -4473,6 +4541,19 @@ public boolean isNewGif() { return messageOwner.media != null && isNewGifDocument(messageOwner.media.document); } + public boolean isAndroidTheme() { + if (messageOwner.media != null && messageOwner.media.webpage != null) { + ArrayList documents = messageOwner.media.webpage.documents; + for (int a = 0, N = documents.size(); a < N; a++) { + TLRPC.Document document = documents.get(a); + if ("application/x-tgtheme-android".equals(document.mime_type)) { + return true; + } + } + } + return false; + } + public String getMusicTitle() { return getMusicTitle(true); } @@ -4656,7 +4737,11 @@ public static boolean isMediaEmptyWebpage(TLRPC.Message message) { } public boolean canEditMessage(TLRPC.Chat chat) { - return canEditMessage(currentAccount, messageOwner, chat); + return canEditMessage(currentAccount, messageOwner, chat, scheduled); + } + + public boolean canEditMessageScheduleTime(TLRPC.Chat chat) { + return canEditMessageScheduleTime(currentAccount, messageOwner, chat); } public boolean canForwardMessage() { @@ -4698,7 +4783,26 @@ public static boolean canEditMessageAnytime(int currentAccount, TLRPC.Message me return false; } - public static boolean canEditMessage(int currentAccount, TLRPC.Message message, TLRPC.Chat chat) { + public static boolean canEditMessageScheduleTime(int currentAccount, TLRPC.Message message, TLRPC.Chat chat) { + if (chat == null && message.to_id.channel_id != 0) { + chat = MessagesController.getInstance(currentAccount).getChat(message.to_id.channel_id); + if (chat == null) { + return false; + } + } + if (!ChatObject.isChannel(chat) || chat.megagroup || chat.creator) { + return true; + } + if (chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out)) { + return true; + } + return false; + } + + public static boolean canEditMessage(int currentAccount, TLRPC.Message message, TLRPC.Chat chat, boolean scheduled) { + if (scheduled && message.date < ConnectionsManager.getInstance(currentAccount).getCurrentTime() - 60) { + return false; + } if (chat != null && (chat.left || chat.kicked)) { return false; } @@ -4720,7 +4824,7 @@ public static boolean canEditMessage(int currentAccount, TLRPC.Message message, if (message.out && chat != null && chat.megagroup && (chat.creator || chat.admin_rights != null && chat.admin_rights.pin_messages)) { return true; } - if (Math.abs(message.date - ConnectionsManager.getInstance(currentAccount).getCurrentTime()) > MessagesController.getInstance(currentAccount).maxEditTime) { + if (!scheduled && Math.abs(message.date - ConnectionsManager.getInstance(currentAccount).getCurrentTime()) > MessagesController.getInstance(currentAccount).maxEditTime) { return false; } if (message.to_id.channel_id == 0) { @@ -4730,7 +4834,7 @@ public static boolean canEditMessage(int currentAccount, TLRPC.Message message, message.media instanceof TLRPC.TL_messageMediaWebPage || message.media == null); } - if (chat.megagroup && message.out || !chat.megagroup && (chat.creator || chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out)) && message.post) { + if (chat.megagroup && message.out || !chat.megagroup && (chat.creator || chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out && chat.admin_rights.post_messages)) && message.post) { if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument && !isStickerMessage(message) && !isAnimatedStickerMessage(message) || message.media instanceof TLRPC.TL_messageMediaEmpty || @@ -4742,11 +4846,11 @@ public static boolean canEditMessage(int currentAccount, TLRPC.Message message, return false; } - public boolean canDeleteMessage(TLRPC.Chat chat) { - return eventId == 0 && canDeleteMessage(currentAccount, messageOwner, chat); + public boolean canDeleteMessage(boolean inScheduleMode, TLRPC.Chat chat) { + return eventId == 0 && canDeleteMessage(currentAccount, inScheduleMode, messageOwner, chat); } - public static boolean canDeleteMessage(int currentAccount, TLRPC.Message message, TLRPC.Chat chat) { + public static boolean canDeleteMessage(int currentAccount, boolean inScheduleMode, TLRPC.Message message, TLRPC.Chat chat) { if (message.id < 0) { return true; } @@ -4754,9 +4858,12 @@ public static boolean canDeleteMessage(int currentAccount, TLRPC.Message message chat = MessagesController.getInstance(currentAccount).getChat(message.to_id.channel_id); } if (ChatObject.isChannel(chat)) { - return message.id != 1 && (chat.creator || chat.admin_rights != null && (chat.admin_rights.delete_messages || message.out) || chat.megagroup && message.out && message.from_id > 0); + if (inScheduleMode && !chat.megagroup) { + return chat.creator || chat.admin_rights != null && (chat.admin_rights.delete_messages || message.out); + } + return inScheduleMode || message.id != 1 && (chat.creator || chat.admin_rights != null && (chat.admin_rights.delete_messages || message.out && (chat.megagroup || chat.admin_rights.post_messages)) || chat.megagroup && message.out && message.from_id > 0); } - return isOut(message) || !ChatObject.isChannel(chat); + return inScheduleMode || isOut(message) || !ChatObject.isChannel(chat); } public String getForwardedName() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 73e824d4569..8d0500f52bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -91,8 +91,10 @@ public class MessagesController extends BaseController implements NotificationCe private LongSparseArray loadingPeerSettings = new LongSparseArray<>(); private ArrayList createdDialogIds = new ArrayList<>(); + private ArrayList createdScheduledDialogIds = new ArrayList<>(); private ArrayList createdDialogMainThreadIds = new ArrayList<>(); private ArrayList visibleDialogMainThreadIds = new ArrayList<>(); + private ArrayList visibleScheduledDialogMainThreadIds = new ArrayList<>(); private SparseIntArray shortPollChannels = new SparseIntArray(); private SparseIntArray needShortPollChannels = new SparseIntArray(); @@ -142,6 +144,10 @@ public class MessagesController extends BaseController implements NotificationCe private HashMap> reloadingWebpages = new HashMap<>(); private LongSparseArray> reloadingWebpagesPending = new LongSparseArray<>(); + private HashMap> reloadingScheduledWebpages = new HashMap<>(); + private LongSparseArray> reloadingScheduledWebpagesPending = new LongSparseArray<>(); + + private LongSparseArray lastScheduledServerQueryTime = new LongSparseArray<>(); private LongSparseArray> reloadingMessages = new LongSparseArray<>(); @@ -203,6 +209,8 @@ public class MessagesController extends BaseController implements NotificationCe private boolean offlineSent; private String uploadingAvatar; + private HashMap uploadingThemes = new HashMap<>(); + private String uploadingWallpaper; private boolean uploadingWallpaperBlurred; private boolean uploadingWallpaperMotion; @@ -391,7 +399,7 @@ public MessagesController(int num) { getNotificationCenter().addObserver(messagesController, NotificationCenter.FileDidUpload); getNotificationCenter().addObserver(messagesController, NotificationCenter.FileDidFailUpload); getNotificationCenter().addObserver(messagesController, NotificationCenter.fileDidLoad); - getNotificationCenter().addObserver(messagesController, NotificationCenter.fileDidFailedLoad); + getNotificationCenter().addObserver(messagesController, NotificationCenter.fileDidFailToLoad); getNotificationCenter().addObserver(messagesController, NotificationCenter.messageReceivedByServer); getNotificationCenter().addObserver(messagesController, NotificationCenter.updateMessageMedia); }); @@ -525,6 +533,8 @@ public void updateConfig(final TLRPC.TL_config config) { suggestedLangCode = config.suggested_lang_code; LocaleController.getInstance().loadRemoteLanguages(currentAccount); } + Theme.loadRemoteThemes(currentAccount, false); + Theme.checkCurrentRemoteTheme(false); if (config.static_maps_provider == null) { config.static_maps_provider = "google"; @@ -779,6 +789,7 @@ public void didReceivedNotification(int id, int account, Object... args) { SharedPreferences preferences = getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putLong("selectedBackground2", wallPaper.id); + editor.putString("selectedBackgroundSlug", wallPaper.slug); editor.commit(); ArrayList wallpapers = new ArrayList<>(); wallpapers.add(wallPaper); @@ -793,6 +804,85 @@ public void didReceivedNotification(int id, int account, Object... args) { } }); }); + } else { + Theme.ThemeInfo themeInfo = uploadingThemes.get(location); + if (themeInfo != null) { + if (location.equals(themeInfo.uploadingThumb)) { + themeInfo.uploadedThumb = file; + themeInfo.uploadingThumb = null; + } else if (location.equals(themeInfo.uploadingFile)) { + themeInfo.uploadedFile = file; + themeInfo.uploadingFile = null; + } + + if (themeInfo.uploadedFile != null && themeInfo.uploadedThumb != null) { + File f = new File(location); + TLRPC.TL_account_uploadTheme req = new TLRPC.TL_account_uploadTheme(); + req.mime_type = "application/x-tgtheme-android"; + req.file_name = "theme.attheme"; + req.file = themeInfo.uploadedFile; + req.file.name = "theme.attheme"; + req.thumb = themeInfo.uploadedThumb; + req.thumb.name = "theme-preview.jpg"; + req.flags |= 1; + themeInfo.uploadedFile = null; + themeInfo.uploadedThumb = null; + getConnectionsManager().sendRequest(req, (response, error) -> { + int index = themeInfo.name.lastIndexOf(".attheme"); + String n = index > 0 ? themeInfo.name.substring(0, index) : themeInfo.name; + if (response != null) { + TLRPC.Document document = (TLRPC.Document) response; + TLRPC.TL_inputDocument inputDocument = new TLRPC.TL_inputDocument(); + inputDocument.access_hash = document.access_hash; + inputDocument.id = document.id; + inputDocument.file_reference = document.file_reference; + if (themeInfo.info == null || !themeInfo.info.creator) { + TLRPC.TL_account_createTheme req2 = new TLRPC.TL_account_createTheme(); + req2.document = inputDocument; + req2.slug = themeInfo.info != null && !TextUtils.isEmpty(themeInfo.info.slug) ? themeInfo.info.slug : ""; + req2.title = n; + getConnectionsManager().sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + if (response1 instanceof TLRPC.TL_theme) { + Theme.setThemeUploadInfo(themeInfo, (TLRPC.TL_theme) response1, false); + installTheme(themeInfo, themeInfo == Theme.getCurrentNightTheme()); + getNotificationCenter().postNotificationName(NotificationCenter.themeUploadedToServer, themeInfo); + } else { + getNotificationCenter().postNotificationName(NotificationCenter.themeUploadError, themeInfo); + } + })); + } else { + TLRPC.TL_account_updateTheme req2 = new TLRPC.TL_account_updateTheme(); + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.id = themeInfo.info.id; + inputTheme.access_hash = themeInfo.info.access_hash; + req2.theme = inputTheme; + + req2.slug = themeInfo.info.slug; + req2.flags |= 1; + + req2.title = n; + req2.flags |= 2; + + req2.document = inputDocument; + req2.flags |= 4; + + req2.format = "android"; + getConnectionsManager().sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + if (response1 instanceof TLRPC.TL_theme) { + Theme.setThemeUploadInfo(themeInfo, (TLRPC.TL_theme) response1, false); + getNotificationCenter().postNotificationName(NotificationCenter.themeUploadedToServer, themeInfo); + } else { + getNotificationCenter().postNotificationName(NotificationCenter.themeUploadError, themeInfo); + } + })); + } + } else { + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.themeUploadError, themeInfo)); + } + }); + } + uploadingThemes.remove(location); + } } } else if (id == NotificationCenter.FileDidFailUpload) { final String location = (String) args[0]; @@ -800,8 +890,18 @@ public void didReceivedNotification(int id, int account, Object... args) { uploadingAvatar = null; } else if (uploadingWallpaper != null && uploadingWallpaper.equals(location)) { uploadingWallpaper = null; + } else { + Theme.ThemeInfo themeInfo = uploadingThemes.remove(location); + if (themeInfo != null) { + themeInfo.uploadedFile = null; + themeInfo.uploadedThumb = null; + } } } else if (id == NotificationCenter.messageReceivedByServer) { + Boolean scheduled = (Boolean) args[6]; + if (scheduled) { + return; + } Integer msgId = (Integer) args[0]; Integer newMsgId = (Integer) args[1]; Long did = (Long) args[3]; @@ -861,8 +961,11 @@ public void cleanup() { editor = mainPreferences.edit(); editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName2").remove("webFileDatacenterId").commit(); + lastScheduledServerQueryTime.clear(); reloadingWebpages.clear(); reloadingWebpagesPending.clear(); + reloadingScheduledWebpages.clear(); + reloadingScheduledWebpagesPending.clear(); dialogs_dict.clear(); dialogs_read_inbox_max.clear(); loadingPinnedDialogs.clear(); @@ -914,12 +1017,14 @@ public void cleanup() { updatesStartWaitTimePts = 0; updatesStartWaitTimeQts = 0; createdDialogIds.clear(); + createdScheduledDialogIds.clear(); gettingDifference = false; resetDialogsPinned = null; resetDialogsAll = null; }); createdDialogMainThreadIds.clear(); visibleDialogMainThreadIds.clear(); + visibleScheduledDialogMainThreadIds.clear(); blockedUsers.clear(); sendingTypings.clear(); loadingFullUsers.clear(); @@ -960,6 +1065,7 @@ public void cleanup() { getDifferenceFirstSync = true; uploadingAvatar = null; uploadingWallpaper = null; + uploadingThemes.clear(); statusRequest = 0; statusSettingState = 0; @@ -1032,49 +1138,51 @@ public TLRPC.EncryptedChat getEncryptedChatDB(int chat_id, boolean created) { return chat; } - public boolean isDialogCreated(long dialog_id) { - return createdDialogMainThreadIds.contains(dialog_id); - } - - public boolean isDialogVisible(long dialog_id) { - return visibleDialogMainThreadIds.contains(dialog_id); + public boolean isDialogVisible(long dialog_id, boolean scheduled) { + return scheduled ? visibleScheduledDialogMainThreadIds.contains(dialog_id) : visibleDialogMainThreadIds.contains(dialog_id); } - public void setLastVisibleDialogId(final long dialog_id, final boolean set) { + public void setLastVisibleDialogId(final long dialog_id, boolean scheduled, final boolean set) { + ArrayList arrayList = scheduled ? visibleScheduledDialogMainThreadIds : visibleDialogMainThreadIds; if (set) { - if (visibleDialogMainThreadIds.contains(dialog_id)) { + if (arrayList.contains(dialog_id)) { return; } - visibleDialogMainThreadIds.add(dialog_id); + arrayList.add(dialog_id); } else { - visibleDialogMainThreadIds.remove(dialog_id); + arrayList.remove(dialog_id); } } - public void setLastCreatedDialogId(final long dialogId, final boolean set) { - if (set) { - if (createdDialogMainThreadIds.contains(dialogId)) { - return; - } - createdDialogMainThreadIds.add(dialogId); - } else { - createdDialogMainThreadIds.remove(dialogId); - SparseArray array = pollsToCheck.get(dialogId); - if (array != null) { - for (int a = 0, N = array.size(); a < N; a++) { - MessageObject object = array.valueAt(a); - object.pollVisibleOnScreen = false; + public void setLastCreatedDialogId(final long dialogId, boolean scheduled, final boolean set) { + if (!scheduled) { + ArrayList arrayList = createdDialogMainThreadIds; + if (set) { + if (arrayList.contains(dialogId)) { + return; + } + arrayList.add(dialogId); + } else { + arrayList.remove(dialogId); + + SparseArray array = pollsToCheck.get(dialogId); + if (array != null) { + for (int a = 0, N = array.size(); a < N; a++) { + MessageObject object = array.valueAt(a); + object.pollVisibleOnScreen = false; + } } } } Utilities.stageQueue.postRunnable(() -> { + ArrayList arrayList2 = scheduled ? createdScheduledDialogIds : createdDialogIds; if (set) { - if (createdDialogIds.contains(dialogId)) { + if (arrayList2.contains(dialogId)) { return; } - createdDialogIds.add(dialogId); + arrayList2.add(dialogId); } else { - createdDialogIds.remove(dialogId); + arrayList2.remove(dialogId); } }); } @@ -1663,7 +1771,7 @@ public void loadFullUser(final TLRPC.User user, final int classGuid, boolean for getConnectionsManager().bindRequestToGuid(reqId, classGuid); } - private void reloadMessages(final ArrayList mids, final long dialog_id) { + private void reloadMessages(final ArrayList mids, final long dialog_id, boolean scheduled) { if (mids.isEmpty()) { return; } @@ -1730,12 +1838,14 @@ private void reloadMessages(final ArrayList mids, final long dialog_id) message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; } message.dialog_id = dialog_id; - message.unread = (message.out ? outboxValue : inboxValue) < message.id; + if (!scheduled) { + message.unread = (message.out ? outboxValue : inboxValue) < message.id; + } objects.add(new MessageObject(currentAccount, message, usersLocal, chatsLocal, true)); } ImageLoader.saveMessagesThumbs(messagesRes.messages); - getMessagesStorage().putMessages(messagesRes, dialog_id, -1, 0, false); + getMessagesStorage().putMessages(messagesRes, dialog_id, -1, 0, false, scheduled); AndroidUtilities.runOnUIThread(() -> { ArrayList arrayList1 = reloadingMessages.get(dialog_id); @@ -2013,7 +2123,7 @@ private boolean checkDeletingTask(boolean runnable) { if (!mids.isEmpty() && mids.get(0) > 0) { getMessagesStorage().emptyMessagesMedia(mids); } else { - deleteMessages(mids, null, null, 0, false); + deleteMessages(mids, null, null, 0, 0, false, false); } Utilities.stageQueue.postRunnable(() -> { getNewDeleteTask(mids, currentDeletingTaskChannelId); @@ -2316,7 +2426,81 @@ public void uploadAndApplyUserAvatar(TLRPC.FileLocation location) { getFileLoader().uploadFile(uploadingAvatar, false, true, ConnectionsManager.FileTypePhoto); } - public void saveWallpaperToServer(File path, long wallPaperId, long accessHash, boolean isBlurred, boolean isMotion, int backgroundColor, float intesity, boolean install, long taskId) { + public void saveTheme(Theme.ThemeInfo themeInfo, boolean night, boolean unsave) { + if (themeInfo.info != null) { + TLRPC.TL_account_saveTheme req = new TLRPC.TL_account_saveTheme(); + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.id = themeInfo.info.id; + inputTheme.access_hash = themeInfo.info.access_hash; + req.theme = inputTheme; + req.unsave = unsave; + getConnectionsManager().sendRequest(req, (response, error) -> { + + }); + } + if (!unsave) { + installTheme(themeInfo, night); + } + } + + public void installTheme(Theme.ThemeInfo themeInfo, boolean night) { + TLRPC.TL_account_installTheme req = new TLRPC.TL_account_installTheme(); + req.dark = night; + if (themeInfo.info != null) { + req.format = "android"; + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.id = themeInfo.info.id; + inputTheme.access_hash = themeInfo.info.access_hash; + req.theme = inputTheme; + req.flags |= 2; + } + getConnectionsManager().sendRequest(req, (response, error) -> { + + }); + + if (!TextUtils.isEmpty(themeInfo.slug)) { + TLRPC.TL_account_installWallPaper req2 = new TLRPC.TL_account_installWallPaper(); + TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); + inputWallPaperSlug.slug = themeInfo.slug; + req2.wallpaper = inputWallPaperSlug; + req2.settings = new TLRPC.TL_wallPaperSettings(); + req2.settings.blur = themeInfo.isBlured; + req2.settings.motion = themeInfo.isMotion; + getConnectionsManager().sendRequest(req2, (response, error) -> { + + }); + } + } + + public void saveThemeToServer(Theme.ThemeInfo themeInfo) { + if (themeInfo == null) { + return; + } + if (uploadingThemes.containsKey(themeInfo.pathToFile)) { + return; + } + uploadingThemes.put(themeInfo.pathToFile, themeInfo); + Utilities.globalQueue.postRunnable(() -> { + String thumbPath = Theme.createThemePreviewImage(themeInfo); + AndroidUtilities.runOnUIThread(() -> { + if (thumbPath == null) { + uploadingThemes.remove(themeInfo.pathToFile); + return; + } + themeInfo.uploadingFile = themeInfo.pathToFile; + themeInfo.uploadingThumb = thumbPath; + uploadingThemes.put(thumbPath, themeInfo); + File f = new File(themeInfo.pathToFile); + long l = f.length(); + File f2 = new File(thumbPath); + long l2 = f2.length(); + getFileLoader().uploadFile(themeInfo.pathToFile, false, true, ConnectionsManager.FileTypeFile); + getFileLoader().uploadFile(thumbPath, false, true, ConnectionsManager.FileTypePhoto); + }); + }); + } + + public void saveWallpaperToServer(File path, long wallPaperId, String slug, long accessHash, boolean isBlurred, boolean isMotion, int backgroundColor, float intesity, boolean install, long taskId) { if (uploadingWallpaper != null) { File finalPath = new File(ApplicationLoader.getFilesDirFixed(), uploadingWallpaperBlurred ? "wallpaper_original.jpg" : "wallpaper.jpg"); if (path != null && (path.getAbsolutePath().equals(uploadingWallpaper) || path.equals(finalPath))) { @@ -2366,8 +2550,8 @@ public void saveWallpaperToServer(File path, long wallPaperId, long accessHash, } else { NativeByteBuffer data = null; try { - data = new NativeByteBuffer(44); - data.writeInt32(12); + data = new NativeByteBuffer(1024); + data.writeInt32(19); data.writeInt64(wallPaperId); data.writeInt64(accessHash); data.writeBool(isBlurred); @@ -2375,6 +2559,12 @@ public void saveWallpaperToServer(File path, long wallPaperId, long accessHash, data.writeInt32(backgroundColor); data.writeDouble(intesity); data.writeBool(install); + if (slug != null) { + data.writeString(slug); + } else { + data.writeString(""); + } + data.limit(data.position()); } catch (Exception e) { FileLog.e(e); } @@ -2387,6 +2577,11 @@ public void saveWallpaperToServer(File path, long wallPaperId, long accessHash, SharedPreferences preferences = getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putLong("selectedBackground2", wallPaperId); + if (!TextUtils.isEmpty(slug)) { + editor.putString("selectedBackgroundSlug", slug); + } else { + editor.remove("selectedBackgroundSlug"); + } editor.commit(); } }); @@ -2406,27 +2601,16 @@ public void markChannelDialogMessageAsDeleted(ArrayList messages, final } } - public void deleteMessages(ArrayList messages, ArrayList randoms, TLRPC.EncryptedChat encryptedChat, final int channelId, boolean forAll) { - deleteMessages(messages, randoms, encryptedChat, channelId, forAll, 0, null); + public void deleteMessages(ArrayList messages, ArrayList randoms, TLRPC.EncryptedChat encryptedChat, final long dialogId, final int channelId, boolean forAll, boolean scheduled) { + deleteMessages(messages, randoms, encryptedChat, dialogId, channelId, forAll, scheduled, 0, null); } - public void deleteMessages(ArrayList messages, ArrayList randoms, TLRPC.EncryptedChat encryptedChat, final int channelId, boolean forAll, long taskId, TLObject taskRequest) { + public void deleteMessages(ArrayList messages, ArrayList randoms, TLRPC.EncryptedChat encryptedChat, final long dialogId, final int channelId, boolean forAll, boolean scheduled, long taskId, TLObject taskRequest) { if ((messages == null || messages.isEmpty()) && taskRequest == null) { return; } ArrayList toSend = null; if (taskId == 0) { - if (channelId == 0) { - for (int a = 0; a < messages.size(); a++) { - Integer id = messages.get(a); - MessageObject obj = dialogMessagesByIds.get(id); - if (obj != null) { - obj.deleted = true; - } - } - } else { - markChannelDialogMessageAsDeleted(messages, channelId); - } toSend = new ArrayList<>(); for (int a = 0; a < messages.size(); a++) { Integer mid = messages.get(a); @@ -2434,13 +2618,61 @@ public void deleteMessages(ArrayList messages, ArrayList randoms, toSend.add(mid); } } - getMessagesStorage().markMessagesAsDeleted(messages, true, channelId, forAll); - getMessagesStorage().updateDialogsWithDeletedMessages(messages, null, true, channelId); - getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, channelId); + if (scheduled) { + getMessagesStorage().markMessagesAsDeleted(messages, true, channelId, false, true); + } else { + if (channelId == 0) { + for (int a = 0; a < messages.size(); a++) { + Integer id = messages.get(a); + MessageObject obj = dialogMessagesByIds.get(id); + if (obj != null) { + obj.deleted = true; + } + } + } else { + markChannelDialogMessageAsDeleted(messages, channelId); + } + getMessagesStorage().markMessagesAsDeleted(messages, true, channelId, forAll, false); + getMessagesStorage().updateDialogsWithDeletedMessages(messages, null, true, channelId); + } + getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, channelId, scheduled); } final long newTaskId; - if (channelId != 0) { + if (scheduled) { + TLRPC.TL_messages_deleteScheduledMessages req; + + if (taskRequest != null) { + req = (TLRPC.TL_messages_deleteScheduledMessages) taskRequest; + newTaskId = taskId; + } else { + req = new TLRPC.TL_messages_deleteScheduledMessages(); + req.id = toSend; + req.peer = getInputPeer((int) dialogId); + + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(16 + req.getObjectSize()); + data.writeInt32(18); + data.writeInt64(dialogId); + data.writeInt32(channelId); + req.serializeToStream(data); + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + processUpdates(updates, false); + } + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } + }); + } else if (channelId != 0) { TLRPC.TL_channels_deleteMessages req; if (taskRequest != null) { req = (TLRPC.TL_channels_deleteMessages) taskRequest; @@ -2702,8 +2934,8 @@ protected void deleteDialog(final long did, final boolean first, final int onlyH objArr.add(obj); ArrayList arr = new ArrayList<>(); arr.add(message); - updateInterfaceWithMessages(did, objArr); - getMessagesStorage().putMessages(arr, false, true, false, 0); + updateInterfaceWithMessages(did, objArr, false); + getMessagesStorage().putMessages(arr, false, true, false, 0, false); } else { dialog.top_message = 0; } @@ -2720,7 +2952,7 @@ protected void deleteDialog(final long did, final boolean first, final int onlyH getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().removeNotificationsForDialog(did))); } - if (high_id == 1 || onlyHistory == 3) { + if (onlyHistory == 3) { return; } @@ -3599,10 +3831,6 @@ public void sendTyping(final long dialog_id, final int action, int classGuid) { int lower_part = (int) dialog_id; int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { - if (high_id == 1) { - return; - } - TLRPC.TL_messages_setTyping req = new TLRPC.TL_messages_setTyping(); req.peer = getInputPeer(lower_part); if (req.peer instanceof TLRPC.TL_inputPeerChannel) { @@ -3685,111 +3913,141 @@ protected void removeDeletedMessagesFromArray(final long dialog_id, ArrayList { + if (scheduled) { + TLRPC.TL_messages_getScheduledHistory req = new TLRPC.TL_messages_getScheduledHistory(); + req.peer = getInputPeer(lower_part); + req.hash = minDate; + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { - TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; - if (!res.dialogs.isEmpty()) { - TLRPC.Dialog dialog = res.dialogs.get(0); - - if (dialog.top_message != 0) { - TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); - dialogs.chats = res.chats; - dialogs.users = res.users; - dialogs.dialogs = res.dialogs; - dialogs.messages = res.messages; - getMessagesStorage().putDialogs(dialogs, 0); + final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + if (res instanceof TLRPC.TL_messages_messagesNotModified) { + return; + } + int mid = max_id; + if (offset_date != 0 && !res.messages.isEmpty()) { + mid = res.messages.get(res.messages.size() - 1).id; + for (int a = res.messages.size() - 1; a >= 0; a--) { + TLRPC.Message message = res.messages.get(a); + if (message.date > offset_date) { + mid = message.id; + break; + } } - - loadMessagesInternal(dialog_id, count, max_id, offset_date, false, midDate, classGuid, load_type, dialog.top_message, isChannel, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false); } + processLoadedMessages(res, dialog_id, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, true, loadIndex, queryFromServer, mentionsCount); } }); - return; - } - TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory(); - req.peer = getInputPeer(lower_part); - if (load_type == 4) { - req.add_offset = -count + 5; - } else if (load_type == 3) { - req.add_offset = -count / 2; - } else if (load_type == 1) { - req.add_offset = -count - 1; - } else if (load_type == 2 && max_id != 0) { - req.add_offset = -count + 6; + ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); } else { - if (lower_part < 0 && max_id != 0) { - TLRPC.Chat chat = getChat(-lower_part); - if (ChatObject.isChannel(chat)) { - req.add_offset = -1; - req.limit += 1; + if (loadDialog && (load_type == 3 || load_type == 2) && last_message_id == 0) { + TLRPC.TL_messages_getPeerDialogs req = new TLRPC.TL_messages_getPeerDialogs(); + TLRPC.InputPeer inputPeer = getInputPeer((int) dialog_id); + TLRPC.TL_inputDialogPeer inputDialogPeer = new TLRPC.TL_inputDialogPeer(); + inputDialogPeer.peer = inputPeer; + req.peers.add(inputDialogPeer); + + getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; + if (!res.dialogs.isEmpty()) { + TLRPC.Dialog dialog = res.dialogs.get(0); + + if (dialog.top_message != 0) { + TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); + dialogs.chats = res.chats; + dialogs.users = res.users; + dialogs.dialogs = res.dialogs; + dialogs.messages = res.messages; + getMessagesStorage().putDialogs(dialogs, 0); + } + + loadMessagesInternal(dialog_id, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, isChannel, false, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false); + } + } + }); + return; + } + TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory(); + req.peer = getInputPeer(lower_part); + if (load_type == 4) { + req.add_offset = -count + 5; + } else if (load_type == 3) { + req.add_offset = -count / 2; + } else if (load_type == 1) { + req.add_offset = -count - 1; + } else if (load_type == 2 && max_id != 0) { + req.add_offset = -count + 6; + } else { + if (lower_part < 0 && max_id != 0) { + TLRPC.Chat chat = getChat(-lower_part); + if (ChatObject.isChannel(chat)) { + req.add_offset = -1; + req.limit += 1; + } } } - } - req.limit = count; - req.offset_id = max_id; - req.offset_date = offset_date; - int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { - if (response != null) { - final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; - removeDeletedMessagesFromArray(dialog_id, res.messages); - if (res.messages.size() > count) { - res.messages.remove(0); - } - int mid = max_id; - if (offset_date != 0 && !res.messages.isEmpty()) { - mid = res.messages.get(res.messages.size() - 1).id; - for (int a = res.messages.size() - 1; a >= 0; a--) { - TLRPC.Message message = res.messages.get(a); - if (message.date > offset_date) { - mid = message.id; - break; + req.limit = count; + req.offset_id = max_id; + req.offset_date = offset_date; + int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + removeDeletedMessagesFromArray(dialog_id, res.messages); + if (res.messages.size() > count) { + res.messages.remove(0); + } + int mid = max_id; + if (offset_date != 0 && !res.messages.isEmpty()) { + mid = res.messages.get(res.messages.size() - 1).id; + for (int a = res.messages.size() - 1; a >= 0; a--) { + TLRPC.Message message = res.messages.get(a); + if (message.date > offset_date) { + mid = message.id; + break; + } } } + processLoadedMessages(res, dialog_id, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, false, loadIndex, queryFromServer, mentionsCount); } - processLoadedMessages(res, dialog_id, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, loadIndex, queryFromServer, mentionsCount); - } - }); - getConnectionsManager().bindRequestToGuid(reqId, classGuid); + }); + getConnectionsManager().bindRequestToGuid(reqId, classGuid); + } } } - public void reloadWebPages(final long dialog_id, HashMap> webpagesToReload) { + public void reloadWebPages(final long dialog_id, HashMap> webpagesToReload, boolean scheduled) { + HashMap> map = scheduled ? reloadingScheduledWebpages : reloadingWebpages; + LongSparseArray> array = scheduled ? reloadingScheduledWebpagesPending : reloadingWebpagesPending; + for (HashMap.Entry> entry : webpagesToReload.entrySet()) { final String url = entry.getKey(); final ArrayList messages = entry.getValue(); - ArrayList arrayList = reloadingWebpages.get(url); + ArrayList arrayList = map.get(url); if (arrayList == null) { arrayList = new ArrayList<>(); - reloadingWebpages.put(url, arrayList); + map.put(url, arrayList); } arrayList.addAll(messages); TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); req.message = url; getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - ArrayList arrayList1 = reloadingWebpages.remove(url); + ArrayList arrayList1 = map.remove(url); if (arrayList1 == null) { return; } @@ -3810,11 +4068,11 @@ public void reloadWebPages(final long dialog_id, HashMap= 0 && shortPollChannels.indexOfKey(channelId) < 0) { - getChannelDifference(channelId, 2, 0, null); - } else { - getChannelDifference(channelId); + channelPts = getMessagesStorage().getChannelPtsSync(channelId); + if (channelPts == 0) { + channelsPts.put(channelId, messagesRes.pts); + createDialog = true; + if (needShortPollChannels.indexOfKey(channelId) >= 0 && shortPollChannels.indexOfKey(channelId) < 0) { + getChannelDifference(channelId, 2, 0, null); + } else { + getChannelDifference(channelId); + } } } } @@ -3857,9 +4117,28 @@ public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, fin if (!isCache) { ImageLoader.saveMessagesThumbs(messagesRes.messages); } - if (high_id != 1 && lower_id != 0 && isCache && messagesRes.messages.size() == 0) { - AndroidUtilities.runOnUIThread(() -> loadMessages(dialog_id, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, 0, classGuid, load_type, last_message_id, isChannel, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount)); - return; + if (high_id != 1 && lower_id != 0 && isCache && (messagesRes.messages.size() == 0 || scheduled && (SystemClock.uptimeMillis() - lastScheduledServerQueryTime.get(dialog_id, 0L)) > 60 * 1000)) { + int hash; + if (scheduled) { + lastScheduledServerQueryTime.put(dialog_id, SystemClock.uptimeMillis()); + long h = 0; + for (int a = 0, N = messagesRes.messages.size(); a < N; a++) { + TLRPC.Message message = messagesRes.messages.get(a); + if (message.id < 0) { + continue; + } + h = ((h * 20261) + 0x80000000L + message.id) % 0x80000000L; + h = ((h * 20261) + 0x80000000L + message.edit_date) % 0x80000000L; + h = ((h * 20261) + 0x80000000L + message.date) % 0x80000000L; + } + hash = (int) h - 1; + } else { + hash = 0; + } + AndroidUtilities.runOnUIThread(() -> loadMessages(dialog_id, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount)); + if (messagesRes.messages.isEmpty()) { + return; + } } final SparseArray usersDict = new SparseArray<>(); final SparseArray chatsDict = new SparseArray<>(); @@ -3891,22 +4170,26 @@ public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, fin message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; } - if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) { - TLRPC.User user = usersDict.get(message.action.user_id); - if (user != null && user.bot) { - message.reply_markup = new TLRPC.TL_replyKeyboardHide(); - message.flags |= 64; + if (!scheduled) { + if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) { + TLRPC.User user = usersDict.get(message.action.user_id); + if (user != null && user.bot) { + message.reply_markup = new TLRPC.TL_replyKeyboardHide(); + message.flags |= 64; + } + } + + if (message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate) { + message.unread = false; + message.media_unread = false; + } else { + message.unread = (message.out ? outboxValue : inboxValue) < message.id; } - } - if (message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate) { - message.unread = false; - message.media_unread = false; - } else { - message.unread = (message.out ? outboxValue : inboxValue) < message.id; } } - getMessagesStorage().putMessages(messagesRes, dialog_id, load_type, max_id, createDialog); + getMessagesStorage().putMessages(messagesRes, dialog_id, load_type, max_id, createDialog, scheduled); } + final ArrayList objects = new ArrayList<>(); final ArrayList messagesToReload = new ArrayList<>(); final HashMap> webpagesToReload = new HashMap<>(); @@ -3915,6 +4198,7 @@ public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, fin TLRPC.Message message = messagesRes.messages.get(a); message.dialog_id = dialog_id; MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true); + messageObject.scheduled = scheduled; objects.add(messageObject); if (isCache) { if (message.legacy && message.layer < TLRPC.LAYER) { @@ -3941,24 +4225,32 @@ public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, fin AndroidUtilities.runOnUIThread(() -> { putUsers(messagesRes.users, isCache); putChats(messagesRes.chats, isCache); - int first_unread_final = Integer.MAX_VALUE; - if (queryFromServer && load_type == 2) { - for (int a = 0; a < messagesRes.messages.size(); a++) { - TLRPC.Message message = messagesRes.messages.get(a); - if (!message.out && message.id > first_unread && message.id < first_unread_final) { - first_unread_final = message.id; + int first_unread_final; + if (scheduled) { + first_unread_final = 0; + } else { + first_unread_final = Integer.MAX_VALUE; + if (queryFromServer && load_type == 2) { + for (int a = 0; a < messagesRes.messages.size(); a++) { + TLRPC.Message message = messagesRes.messages.get(a); + if ((!message.out || message.from_scheduled) && message.id > first_unread && message.id < first_unread_final) { + first_unread_final = message.id; + } } } + if (first_unread_final == Integer.MAX_VALUE) { + first_unread_final = first_unread; + } } - if (first_unread_final == Integer.MAX_VALUE) { - first_unread_final = first_unread; + if (scheduled && count == 1) { + getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialog_id, objects.size()); } - getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled); if (!messagesToReload.isEmpty()) { - reloadMessages(messagesToReload, dialog_id); + reloadMessages(messagesToReload, dialog_id, scheduled); } if (!webpagesToReload.isEmpty()) { - reloadWebPages(dialog_id, webpagesToReload); + reloadWebPages(dialog_id, webpagesToReload, scheduled); } }); }); @@ -5736,6 +6028,9 @@ public void addToPollsQueue(long dialogId, ArrayList visibleObjec } public void markMessageContentAsRead(final MessageObject messageObject) { + if (messageObject.scheduled) { + return; + } ArrayList arrayList = new ArrayList<>(); long messageId = messageObject.getId(); if (messageObject.messageOwner.to_id.channel_id != 0) { @@ -5954,14 +6249,14 @@ public void markMentionsAsRead(long dialogId) { }); } - public void markDialogAsRead(final long dialogId, final int maxPositiveId, final int maxNegativeId, final int maxDate, final boolean popup, final int countDiff, final boolean readNow) { + public void markDialogAsRead(final long dialogId, final int maxPositiveId, final int maxNegativeId, final int maxDate, final boolean popup, final int countDiff, final boolean readNow, final int scheduledCount) { int lower_part = (int) dialogId; int high_id = (int) (dialogId >> 32); boolean createReadTask; boolean countMessages = getNotificationsController().showBadgeMessages; if (lower_part != 0) { - if (maxPositiveId == 0 || high_id == 1) { + if (maxPositiveId == 0) { return; } long maxMessageId = maxPositiveId; @@ -5981,7 +6276,7 @@ public void markDialogAsRead(final long dialogId, final int maxPositiveId, final } dialogs_read_inbox_max.put(dialogId, Math.max(value, maxPositiveId)); - getMessagesStorage().processPendingRead(dialogId, maxMessageId, minMessageId, isChannel); + getMessagesStorage().processPendingRead(dialogId, maxMessageId, minMessageId, isChannel, scheduledCount); getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { TLRPC.Dialog dialog = dialogs_dict.get(dialogId); if (dialog != null) { @@ -6043,7 +6338,7 @@ public void markDialogAsRead(final long dialogId, final int maxPositiveId, final createReadTask = true; TLRPC.EncryptedChat chat = getEncryptedChat(high_id); - getMessagesStorage().processPendingRead(dialogId, maxPositiveId, maxNegativeId, false); + getMessagesStorage().processPendingRead(dialogId, maxPositiveId, maxNegativeId, false, scheduledCount); getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { getNotificationsController().processReadMessages(null, dialogId, maxDate, 0, popup); TLRPC.Dialog dialog = dialogs_dict.get(dialogId); @@ -6117,63 +6412,7 @@ public void markDialogAsRead(final long dialogId, final int maxPositiveId, final } public int createChat(String title, ArrayList selectedContacts, final String about, int type, Location location, String locationAddress, final BaseFragment fragment) { - if (type == ChatObject.CHAT_TYPE_BROADCAST) { - TLRPC.TL_chat chat = new TLRPC.TL_chat(); - chat.id = getUserConfig().lastBroadcastId; - chat.title = title; - chat.photo = new TLRPC.TL_chatPhotoEmpty(); - chat.participants_count = selectedContacts.size(); - chat.date = (int) (System.currentTimeMillis() / 1000); - chat.version = 1; - getUserConfig().lastBroadcastId--; - putChat(chat, false); - ArrayList chatsArrays = new ArrayList<>(); - chatsArrays.add(chat); - getMessagesStorage().putUsersAndChats(null, chatsArrays, true, true); - - TLRPC.TL_chatFull chatFull = new TLRPC.TL_chatFull(); - chatFull.id = chat.id; - chatFull.chat_photo = new TLRPC.TL_photoEmpty(); - chatFull.notify_settings = new TLRPC.TL_peerNotifySettingsEmpty_layer77(); - chatFull.exported_invite = new TLRPC.TL_chatInviteEmpty(); - chatFull.participants = new TLRPC.TL_chatParticipants(); - chatFull.participants.chat_id = chat.id; - chatFull.participants.admin_id = getUserConfig().getClientUserId(); - chatFull.participants.version = 1; - for (int a = 0; a < selectedContacts.size(); a++) { - TLRPC.TL_chatParticipant participant = new TLRPC.TL_chatParticipant(); - participant.user_id = selectedContacts.get(a); - participant.inviter_id = getUserConfig().getClientUserId(); - participant.date = (int) (System.currentTimeMillis() / 1000); - chatFull.participants.participants.add(participant); - } - getMessagesStorage().updateChatInfo(chatFull, false); - - TLRPC.TL_messageService newMsg = new TLRPC.TL_messageService(); - newMsg.action = new TLRPC.TL_messageActionCreatedBroadcastList(); - newMsg.local_id = newMsg.id = getUserConfig().getNewMessageId(); - newMsg.from_id = getUserConfig().getClientUserId(); - newMsg.dialog_id = AndroidUtilities.makeBroadcastId(chat.id); - newMsg.to_id = new TLRPC.TL_peerChat(); - newMsg.to_id.chat_id = chat.id; - newMsg.date = getConnectionsManager().getCurrentTime(); - newMsg.random_id = 0; - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_FROM_ID; - getUserConfig().saveConfig(false); - MessageObject newMsgObj = new MessageObject(currentAccount, newMsg, users, true); - newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - - ArrayList objArr = new ArrayList<>(); - objArr.add(newMsgObj); - ArrayList arr = new ArrayList<>(); - arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, false, 0); - updateInterfaceWithMessages(newMsg.dialog_id, objArr); - getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); - getNotificationCenter().postNotificationName(NotificationCenter.chatDidCreated, chat.id); - - return 0; - } else if (type == ChatObject.CHAT_TYPE_CHAT) { + if (type == ChatObject.CHAT_TYPE_CHAT) { final TLRPC.TL_messages_createChat req = new TLRPC.TL_messages_createChat(); req.title = title; for (int a = 0; a < selectedContacts.size(); a++) { @@ -7199,7 +7438,7 @@ protected void getChannelDifference(final int channelId, final int newDialogType if (!msgUpdates.isEmpty()) { final SparseArray corrected = new SparseArray<>(); for (TLRPC.TL_updateMessageID update : msgUpdates) { - long[] ids = getMessagesStorage().updateMessageStateAndId(update.random_id, null, update.id, 0, false, channelId); + long[] ids = getMessagesStorage().updateMessageStateAndId(update.random_id, null, update.id, 0, false, channelId, -1); if (ids != null) { corrected.put(update.id, ids); } @@ -7212,7 +7451,7 @@ protected void getChannelDifference(final int channelId, final int newDialogType long[] ids = corrected.valueAt(a); int oldId = (int) ids[1]; getSendMessagesHelper().processSentMessage(oldId); - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1, false); } }); } @@ -7246,7 +7485,7 @@ protected void getChannelDifference(final int channelId, final int newDialogType } MessageObject obj = new MessageObject(currentAccount, message, usersDict, createdDialogIds.contains(dialog_id)); - if (!obj.isOut() && obj.isUnread()) { + if ((!obj.isOut() || obj.messageOwner.from_scheduled) && obj.isUnread()) { pushMessages.add(obj); } @@ -7263,7 +7502,7 @@ protected void getChannelDifference(final int channelId, final int newDialogType for (int a = 0; a < messages.size(); a++) { long key = messages.keyAt(a); ArrayList value = messages.valueAt(a); - updateInterfaceWithMessages(key, value); + updateInterfaceWithMessages(key, value, false); } getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); @@ -7271,7 +7510,7 @@ protected void getChannelDifference(final int channelId, final int newDialogType if (!pushMessages.isEmpty()) { AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, true, false, null)); } - getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask()); + getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask(), false); }); } @@ -7445,7 +7684,7 @@ public void getDifference(int pts, final int date, final int qts, boolean slice) final SparseArray corrected = new SparseArray<>(); for (int a = 0; a < msgUpdates.size(); a++) { TLRPC.TL_updateMessageID update = msgUpdates.get(a); - long[] ids = getMessagesStorage().updateMessageStateAndId(update.random_id, null, update.id, 0, false, 0); + long[] ids = getMessagesStorage().updateMessageStateAndId(update.random_id, null, update.id, 0, false, 0, -1); if (ids != null) { corrected.put(update.id, ids); } @@ -7458,7 +7697,7 @@ public void getDifference(int pts, final int date, final int qts, boolean slice) long[] ids = corrected.valueAt(a); int oldId = (int) ids[1]; getSendMessagesHelper().processSentMessage(oldId); - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null, ids[0], 0L, -1, false); } }); } @@ -7521,7 +7760,7 @@ public void getDifference(int pts, final int date, final int qts, boolean slice) MessageObject obj = new MessageObject(currentAccount, message, usersDict, chatsDict, createdDialogIds.contains(message.dialog_id)); - if (!obj.isOut() && obj.isUnread()) { + if ((!obj.isOut() || obj.messageOwner.from_scheduled) && obj.isUnread()) { pushMessages.add(obj); } @@ -7537,7 +7776,7 @@ public void getDifference(int pts, final int date, final int qts, boolean slice) for (int a = 0; a < messages.size(); a++) { long key = messages.keyAt(a); ArrayList value = messages.valueAt(a); - updateInterfaceWithMessages(key, value); + updateInterfaceWithMessages(key, value, false); } getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); @@ -7545,7 +7784,7 @@ public void getDifference(int pts, final int date, final int qts, boolean slice) if (!pushMessages.isEmpty()) { AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, !(res instanceof TLRPC.TL_updates_differenceSlice), false, null)); } - getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask()); + getMessagesStorage().putMessages(res.new_messages, true, false, false, getDownloadController().getAutodownloadMask(), false); }); getSecretChatHelper().processPendingEncMessages(); @@ -8007,10 +8246,10 @@ public void generateJoinMessage(final int chat_id, boolean ignoreLeft) { pushMessages.add(obj); getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, true, false, null))); - getMessagesStorage().putMessages(messagesArr, true, true, false, 0); + getMessagesStorage().putMessages(messagesArr, true, true, false, 0, false); AndroidUtilities.runOnUIThread(() -> { - updateInterfaceWithMessages(-chat_id, pushMessages); + updateInterfaceWithMessages(-chat_id, pushMessages, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); } @@ -8018,7 +8257,7 @@ public void generateJoinMessage(final int chat_id, boolean ignoreLeft) { protected void deleteMessagesByPush(long dialogId, ArrayList ids, int channelId) { getMessagesStorage().getStorageQueue().postRunnable(() -> { AndroidUtilities.runOnUIThread(() -> { - getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, ids, channelId); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, ids, channelId, false); if (channelId == 0) { for (int b = 0, size2 = ids.size(); b < size2; b++) { Integer id = ids.get(b); @@ -8040,7 +8279,7 @@ protected void deleteMessagesByPush(long dialogId, ArrayList ids, int c } }); getMessagesStorage().deletePushMessages(dialogId, ids); - ArrayList dialogIds = getMessagesStorage().markMessagesAsDeleted(ids, false, channelId, true); + ArrayList dialogIds = getMessagesStorage().markMessagesAsDeleted(ids, false, channelId, true, false); getMessagesStorage().updateDialogsWithDeletedMessages(ids, dialogIds, false, channelId); }); } @@ -8095,10 +8334,10 @@ public void checkChannelInviter(final int chat_id) { pushMessages.add(obj); getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, true, false, null))); - getMessagesStorage().putMessages(messagesArr, true, true, false, 0); + getMessagesStorage().putMessages(messagesArr, true, true, false, 0, false); AndroidUtilities.runOnUIThread(() -> { - updateInterfaceWithMessages(-chat_id, pushMessages); + updateInterfaceWithMessages(-chat_id, pushMessages, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); } @@ -8379,7 +8618,7 @@ public void processUpdates(final TLRPC.Updates updates, boolean fromQueue) { if (printUpdate) { getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); } - updateInterfaceWithMessages(user_id, objArr); + updateInterfaceWithMessages(user_id, objArr, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); } else { @@ -8392,14 +8631,14 @@ public void processUpdates(final TLRPC.Updates updates, boolean fromQueue) { getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); } - updateInterfaceWithMessages(-updates.chat_id, objArr); + updateInterfaceWithMessages(-updates.chat_id, objArr, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); }); } if (!obj.isOut()) { getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(objArr, true, false, null))); } - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, false); } else if (getMessagesStorage().getLastPtsValue() != updates.pts) { if (BuildVars.LOGS_ENABLED) { FileLog.d("need get diff short message, pts: " + getMessagesStorage().getLastPtsValue() + " " + updates.pts + " count = " + updates.pts_count); @@ -8736,9 +8975,11 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi boolean printChanged = false; LongSparseArray> messages = null; + LongSparseArray> scheduledMessages = null; LongSparseArray webPages = null; ArrayList pushMessages = null; ArrayList messagesArr = null; + ArrayList scheduledMessagesArr = null; LongSparseArray> editingMessages = null; SparseArray channelViews = null; SparseLongArray markAsReadMessagesInbox = null; @@ -8746,6 +8987,7 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi ArrayList markAsReadMessages = null; SparseIntArray markAsReadEncrypted = null; SparseArray> deletedMessages = null; + SparseArray> scheduledDeletedMessages = null; SparseIntArray clearHistoryMessages = null; ArrayList chatInfoToUpdate = null; ArrayList updatesOnMainThread = null; @@ -8793,10 +9035,12 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi if (BuildVars.LOGS_ENABLED) { FileLog.d("process update " + baseUpdate); } - if (baseUpdate instanceof TLRPC.TL_updateNewMessage || baseUpdate instanceof TLRPC.TL_updateNewChannelMessage) { + if (baseUpdate instanceof TLRPC.TL_updateNewMessage || baseUpdate instanceof TLRPC.TL_updateNewChannelMessage || baseUpdate instanceof TLRPC.TL_updateNewScheduledMessage) { TLRPC.Message message; if (baseUpdate instanceof TLRPC.TL_updateNewMessage) { message = ((TLRPC.TL_updateNewMessage) baseUpdate).message; + } else if (baseUpdate instanceof TLRPC.TL_updateNewScheduledMessage) { + message = ((TLRPC.TL_updateNewScheduledMessage) baseUpdate).message; } else { message = ((TLRPC.TL_updateNewChannelMessage) baseUpdate).message; if (BuildVars.LOGS_ENABLED) { @@ -8891,11 +9135,8 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi } } - if (messagesArr == null) { - messagesArr = new ArrayList<>(); - } - messagesArr.add(message); ImageLoader.saveMessageThumbs(message); + int clientUserId = getUserConfig().getClientUserId(); if (message.to_id.chat_id != 0) { message.dialog_id = -message.to_id.chat_id; @@ -8908,39 +9149,66 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi message.dialog_id = message.to_id.user_id; } - ConcurrentHashMap read_max = message.out ? dialogs_read_outbox_max : dialogs_read_inbox_max; - Integer value = read_max.get(message.dialog_id); - if (value == null) { - value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); - read_max.put(message.dialog_id, value); - } - message.unread = !(value >= message.id || chat != null && ChatObject.isNotInChat(chat) || message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate); - if (message.dialog_id == clientUserId) { - message.unread = false; - message.media_unread = false; - message.out = true; - } + if (baseUpdate instanceof TLRPC.TL_updateNewScheduledMessage) { + if (scheduledMessagesArr == null) { + scheduledMessagesArr = new ArrayList<>(); + } + scheduledMessagesArr.add(message); - MessageObject obj = new MessageObject(currentAccount, message, usersDict, chatsDict, createdDialogIds.contains(message.dialog_id)); - if (obj.type == 11) { - interfaceUpdateMask |= UPDATE_MASK_CHAT_AVATAR; - } else if (obj.type == 10) { - interfaceUpdateMask |= UPDATE_MASK_CHAT_NAME; - } - if (messages == null) { - messages = new LongSparseArray<>(); - } - ArrayList arr = messages.get(message.dialog_id); - if (arr == null) { - arr = new ArrayList<>(); - messages.put(message.dialog_id, arr); - } - arr.add(obj); - if (!obj.isOut() && obj.isUnread()) { - if (pushMessages == null) { - pushMessages = new ArrayList<>(); + MessageObject obj = new MessageObject(currentAccount, message, usersDict, chatsDict, createdScheduledDialogIds.contains(message.dialog_id)); + obj.scheduled = true; + + if (scheduledMessages == null) { + scheduledMessages = new LongSparseArray<>(); + } + ArrayList arr = scheduledMessages.get(message.dialog_id); + if (arr == null) { + arr = new ArrayList<>(); + scheduledMessages.put(message.dialog_id, arr); + } + arr.add(obj); + } else { + if (messagesArr == null) { + messagesArr = new ArrayList<>(); + } + messagesArr.add(message); + + ConcurrentHashMap read_max = message.out ? dialogs_read_outbox_max : dialogs_read_inbox_max; + Integer value = read_max.get(message.dialog_id); + if (value == null) { + value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); + read_max.put(message.dialog_id, value); + } + message.unread = !(value >= message.id || chat != null && ChatObject.isNotInChat(chat) || message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate); + if (message.dialog_id == clientUserId) { + if (!message.from_scheduled) { + message.unread = false; + } + message.media_unread = false; + message.out = true; + } + + MessageObject obj = new MessageObject(currentAccount, message, usersDict, chatsDict, createdDialogIds.contains(message.dialog_id)); + if (obj.type == 11) { + interfaceUpdateMask |= UPDATE_MASK_CHAT_AVATAR; + } else if (obj.type == 10) { + interfaceUpdateMask |= UPDATE_MASK_CHAT_NAME; + } + if (messages == null) { + messages = new LongSparseArray<>(); + } + ArrayList arr = messages.get(message.dialog_id); + if (arr == null) { + arr = new ArrayList<>(); + messages.put(message.dialog_id, arr); + } + arr.add(obj); + if ((!obj.isOut() || obj.messageOwner.from_scheduled) && obj.isUnread()) { + if (pushMessages == null) { + pushMessages = new ArrayList<>(); + } + pushMessages.add(obj); } - pushMessages.add(obj); } } else if (baseUpdate instanceof TLRPC.TL_updateReadMessagesContents) { TLRPC.TL_updateReadMessagesContents update = (TLRPC.TL_updateReadMessagesContents) baseUpdate; @@ -9008,6 +9276,24 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi deletedMessages.put(0, arrayList); } arrayList.addAll(update.messages); + } else if (baseUpdate instanceof TLRPC.TL_updateDeleteScheduledMessages) { + TLRPC.TL_updateDeleteScheduledMessages update = (TLRPC.TL_updateDeleteScheduledMessages) baseUpdate; + + if (scheduledDeletedMessages == null) { + scheduledDeletedMessages = new SparseArray<>(); + } + ArrayList arrayList; + int id; + if (update.peer instanceof TLRPC.TL_peerChannel) { + arrayList = scheduledDeletedMessages.get(id = update.peer.channel_id); + } else { + arrayList = scheduledDeletedMessages.get(id = 0); + } + if (arrayList == null) { + arrayList = new ArrayList<>(); + scheduledDeletedMessages.put(id, arrayList); + } + arrayList.addAll(update.messages); } else if (baseUpdate instanceof TLRPC.TL_updateUserTyping || baseUpdate instanceof TLRPC.TL_updateChatUserTyping) { int user_id; int chat_id; @@ -9539,13 +9825,15 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi MessageObject obj = new MessageObject(currentAccount, message, usersDict, chatsDict, createdDialogIds.contains(message.dialog_id)); + LongSparseArray> array; if (editingMessages == null) { editingMessages = new LongSparseArray<>(); } - ArrayList arr = editingMessages.get(message.dialog_id); + array = editingMessages; + ArrayList arr = array.get(message.dialog_id); if (arr == null) { arr = new ArrayList<>(); - editingMessages.put(message.dialog_id, arr); + array.put(message.dialog_id, arr); } arr.add(obj); } else if (baseUpdate instanceof TLRPC.TL_updateChannelPinnedMessage) { @@ -9611,11 +9899,31 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi updatesOnMainThread = new ArrayList<>(); } updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateMessageReactions) { + TLRPC.TL_updateMessageReactions update = (TLRPC.TL_updateMessageReactions) baseUpdate; + long dialogId; + if (update.peer.chat_id != 0) { + dialogId = -update.peer.chat_id; + } else if (update.peer.channel_id != 0) { + dialogId = -update.peer.channel_id; + } else { + dialogId = update.peer.user_id; + } + getMessagesStorage().updateMessageReactions(dialogId, update.msg_id, update.peer.channel_id, update.reactions); + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); } else if (baseUpdate instanceof TLRPC.TL_updatePeerLocated) { if (updatesOnMainThread == null) { updatesOnMainThread = new ArrayList<>(); } updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateTheme) { + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); } } if (messages != null) { @@ -9644,9 +9952,13 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessagesFinal, true, false, null))); } + if (scheduledMessagesArr != null) { + getMessagesStorage().putMessages(scheduledMessagesArr, true, true, false, getDownloadController().getAutodownloadMask(), true); + } + if (messagesArr != null) { getStatsController().incrementReceivedItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, messagesArr.size()); - getMessagesStorage().putMessages(messagesArr, true, true, false, getDownloadController().getAutodownloadMask()); + getMessagesStorage().putMessages(messagesArr, true, true, false, getDownloadController().getAutodownloadMask(), false); } if (editingMessages != null) { for (int b = 0, size = editingMessages.size(); b < size; b++) { @@ -9655,7 +9967,7 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi for (int a = 0, size2 = messageObjects.size(); a < size2; a++) { messagesRes.messages.add(messageObjects.get(a).messageOwner); } - getMessagesStorage().putMessages(messagesRes, editingMessages.keyAt(b), -2, 0, false); + getMessagesStorage().putMessages(messagesRes, editingMessages.keyAt(b), -2, 0, false, false); } } @@ -9667,6 +9979,7 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi final SparseArray channelViewsFinal = channelViews; final LongSparseArray webPagesFinal = webPages; final LongSparseArray> messagesFinal = messages; + final LongSparseArray> scheduledMessagesFinal = scheduledMessages; final ArrayList chatInfoToUpdateFinal = chatInfoToUpdate; final ArrayList contactsIdsFinal = contactsIds; final ArrayList updatesOnMainThreadFinal = updatesOnMainThread; @@ -9683,13 +9996,21 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi if (baseUpdate instanceof TLRPC.TL_updatePrivacy) { TLRPC.TL_updatePrivacy update = (TLRPC.TL_updatePrivacy) baseUpdate; if (update.key instanceof TLRPC.TL_privacyKeyStatusTimestamp) { - getContactsController().setPrivacyRules(update.rules, 0); + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_LASTSEEN); } else if (update.key instanceof TLRPC.TL_privacyKeyChatInvite) { - getContactsController().setPrivacyRules(update.rules, 1); + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_INVITE); } else if (update.key instanceof TLRPC.TL_privacyKeyPhoneCall) { - getContactsController().setPrivacyRules(update.rules, 2); + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_CALLS); } else if (update.key instanceof TLRPC.TL_privacyKeyPhoneP2P) { - getContactsController().setPrivacyRules(update.rules, 3); + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_P2P); + } else if (update.key instanceof TLRPC.TL_privacyKeyProfilePhoto) { + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_PHOTO); + } else if (update.key instanceof TLRPC.TL_privacyKeyForwards) { + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_FORWARDS); + } else if (update.key instanceof TLRPC.TL_privacyKeyPhoneNumber) { + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_PHONE); + } else if (update.key instanceof TLRPC.TL_privacyKeyAddedByPhone) { + getContactsController().setPrivacyRules(update.rules, ContactsController.PRIVACY_RULES_TYPE_ADDED_BY_PHONE); } } else if (baseUpdate instanceof TLRPC.TL_updateUserStatus) { TLRPC.TL_updateUserStatus update = (TLRPC.TL_updateUserStatus) baseUpdate; @@ -9787,9 +10108,12 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi if (dialog == null) { continue; } - //TODO folder - dialog.folder_id = folderPeer.folder_id; - ensureFolderDialogExists(folderPeer.folder_id, null); + if (dialog.folder_id != folderPeer.folder_id) { + dialog.pinned = false; + dialog.pinnedNum = 0; + dialog.folder_id = folderPeer.folder_id; + ensureFolderDialogExists(folderPeer.folder_id, null); + } } forceDialogsUpdate = true; } else if (baseUpdate instanceof TLRPC.TL_updateUserPhoto) { @@ -10089,6 +10413,21 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi savePeerSettings(dialogId, update.settings, true); } else if (baseUpdate instanceof TLRPC.TL_updatePeerLocated) { getNotificationCenter().postNotificationName(NotificationCenter.newPeopleNearbyAvailable, baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateMessageReactions) { + TLRPC.TL_updateMessageReactions update = (TLRPC.TL_updateMessageReactions) baseUpdate; + long dialogId; + if (update.peer.chat_id != 0) { + dialogId = -update.peer.chat_id; + } else if (update.peer.channel_id != 0) { + dialogId = -update.peer.channel_id; + } else { + dialogId = update.peer.user_id; + } + getNotificationCenter().postNotificationName(NotificationCenter.didUpdateReactions, dialogId, update.msg_id, update.reactions); + } else if (baseUpdate instanceof TLRPC.TL_updateTheme) { + TLRPC.TL_updateTheme update = (TLRPC.TL_updateTheme) baseUpdate; + TLRPC.TL_theme theme = (TLRPC.TL_theme) update.theme; + Theme.setThemeUploadInfo(null, theme, true); } } if (editor != null) { @@ -10101,29 +10440,34 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi if (webPagesFinal != null) { getNotificationCenter().postNotificationName(NotificationCenter.didReceivedWebpagesInUpdates, webPagesFinal); - for (int b = 0, size = webPagesFinal.size(); b < size; b++) { - long key = webPagesFinal.keyAt(b); - ArrayList arrayList = reloadingWebpagesPending.get(key); - reloadingWebpagesPending.remove(key); - if (arrayList != null) { - TLRPC.WebPage webpage = webPagesFinal.valueAt(b); - ArrayList arr = new ArrayList<>(); - long dialog_id = 0; - if (webpage instanceof TLRPC.TL_webPage || webpage instanceof TLRPC.TL_webPageEmpty) { - for (int a = 0, size2 = arrayList.size(); a < size2; a++) { - arrayList.get(a).messageOwner.media.webpage = webpage; - if (a == 0) { - dialog_id = arrayList.get(a).getDialogId(); - ImageLoader.saveMessageThumbs(arrayList.get(a).messageOwner); + for (int i = 0; i < 2; i++) { + HashMap> map = i == 1 ? reloadingScheduledWebpages : reloadingWebpages; + LongSparseArray> array = i == 1 ? reloadingScheduledWebpagesPending : reloadingWebpagesPending; + + for (int b = 0, size = webPagesFinal.size(); b < size; b++) { + long key = webPagesFinal.keyAt(b); + ArrayList arrayList = array.get(key); + array.remove(key); + if (arrayList != null) { + TLRPC.WebPage webpage = webPagesFinal.valueAt(b); + ArrayList arr = new ArrayList<>(); + long dialog_id = 0; + if (webpage instanceof TLRPC.TL_webPage || webpage instanceof TLRPC.TL_webPageEmpty) { + for (int a = 0, size2 = arrayList.size(); a < size2; a++) { + arrayList.get(a).messageOwner.media.webpage = webpage; + if (a == 0) { + dialog_id = arrayList.get(a).getDialogId(); + ImageLoader.saveMessageThumbs(arrayList.get(a).messageOwner); + } + arr.add(arrayList.get(a).messageOwner); } - arr.add(arrayList.get(a).messageOwner); + } else { + array.put(webpage.id, arrayList); + } + if (!arr.isEmpty()) { + getMessagesStorage().putMessages(arr, true, true, false, getDownloadController().getAutodownloadMask(), i == 1); + getNotificationCenter().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList); } - } else { - reloadingWebpagesPending.put(webpage.id, arrayList); - } - if (!arr.isEmpty()) { - getMessagesStorage().putMessages(arr, true, true, false, getDownloadController().getAutodownloadMask()); - getNotificationCenter().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList); } } } @@ -10134,13 +10478,20 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi for (int a = 0, size = messagesFinal.size(); a < size; a++) { long key = messagesFinal.keyAt(a); ArrayList value = messagesFinal.valueAt(a); - updateInterfaceWithMessages(key, value); + updateInterfaceWithMessages(key, value, false); } updateDialogs = true; } else if (forceDialogsUpdate) { sortDialogs(null); updateDialogs = true; } + if (scheduledMessagesFinal != null) { + for (int a = 0, size = scheduledMessagesFinal.size(); a < size; a++) { + long key = scheduledMessagesFinal.keyAt(a); + ArrayList value = scheduledMessagesFinal.valueAt(a); + updateInterfaceWithMessages(key, value, true); + } + } if (editingMessagesFinal != null) { for (int b = 0, size = editingMessagesFinal.size(); b < size; b++) { long dialog_id = editingMessagesFinal.keyAt(b); @@ -10164,8 +10515,8 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi } } } - getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id); - getNotificationCenter().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList); + getMediaDataController().loadReplyMessagesForMessages(arrayList, dialog_id, false); + getNotificationCenter().postNotificationName(NotificationCenter.replaceMessagesObjects, dialog_id, arrayList, false); } } if (updateDialogs) { @@ -10198,6 +10549,7 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi final ArrayList markAsReadMessagesFinal = markAsReadMessages; final SparseIntArray markAsReadEncryptedFinal = markAsReadEncrypted; final SparseArray> deletedMessagesFinal = deletedMessages; + final SparseArray> scheduledDeletedMessagesFinal = scheduledDeletedMessages; final SparseIntArray clearHistoryMessagesFinal = clearHistoryMessages; getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { int updateMask = 0; @@ -10265,7 +10617,7 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi if (arrayList == null) { continue; } - getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, arrayList, key); + getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, arrayList, key, false); if (key == 0) { for (int b = 0, size2 = arrayList.size(); b < size2; b++) { Integer id = arrayList.get(b); @@ -10288,6 +10640,16 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi } getNotificationsController().removeDeletedMessagesFromNotifications(deletedMessagesFinal); } + if (scheduledDeletedMessagesFinal != null) { + for (int a = 0, size = scheduledDeletedMessagesFinal.size(); a < size; a++) { + int key = scheduledDeletedMessagesFinal.keyAt(a); + ArrayList arrayList = scheduledDeletedMessagesFinal.valueAt(a); + if (arrayList == null) { + continue; + } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messagesDeleted, arrayList, key, true); + } + } if (clearHistoryMessagesFinal != null) { for (int a = 0, size = clearHistoryMessagesFinal.size(); a < size; a++) { int key = clearHistoryMessagesFinal.keyAt(a); @@ -10326,11 +10688,18 @@ public boolean processUpdateArray(ArrayList updates, final ArrayLi final int key = deletedMessages.keyAt(a); final ArrayList arrayList = deletedMessages.valueAt(a); getMessagesStorage().getStorageQueue().postRunnable(() -> { - ArrayList dialogIds = getMessagesStorage().markMessagesAsDeleted(arrayList, false, key, true); + ArrayList dialogIds = getMessagesStorage().markMessagesAsDeleted(arrayList, false, key, true, false); getMessagesStorage().updateDialogsWithDeletedMessages(arrayList, dialogIds, false, key); }); } } + if (scheduledDeletedMessages != null) { + for (int a = 0, size = scheduledDeletedMessages.size(); a < size; a++) { + final int key = scheduledDeletedMessages.keyAt(a); + final ArrayList arrayList = scheduledDeletedMessages.valueAt(a); + MessagesStorage.getInstance(currentAccount).markMessagesAsDeleted(arrayList, true, key, false, true); + } + } if (clearHistoryMessages != null) { for (int a = 0, size = clearHistoryMessages.size(); a < size; a++) { final int key = clearHistoryMessages.keyAt(a); @@ -10404,11 +10773,7 @@ private boolean updatePrintingUsersWithNewMessages(long uid, ArrayList messages) { - updateInterfaceWithMessages(uid, messages, false); - } - - protected void updateInterfaceWithMessages(final long uid, final ArrayList messages, boolean isBroadcast) { + protected void updateInterfaceWithMessages(final long uid, final ArrayList messages, boolean scheduled) { if (messages == null || messages.isEmpty()) { return; } @@ -10418,32 +10783,34 @@ protected void updateInterfaceWithMessages(final long uid, final ArrayList lastMessage.getId() || (isEncryptedChat || message.getId() < 0 && lastMessage.getId() < 0) && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) { - lastMessage = message; - if (message.messageOwner.to_id.channel_id != 0) { - channelId = message.messageOwner.to_id.channel_id; + if (!scheduled) { + for (int a = 0; a < messages.size(); a++) { + MessageObject message = messages.get(a); + if (lastMessage == null || (!isEncryptedChat && message.getId() > lastMessage.getId() || (isEncryptedChat || message.getId() < 0 && lastMessage.getId() < 0) && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) { + lastMessage = message; + if (message.messageOwner.to_id.channel_id != 0) { + channelId = message.messageOwner.to_id.channel_id; + } } - } - if (!hasNotOutMessage && !message.isOut()) { - hasNotOutMessage = true; - } - if (message.isOut() && !message.isSending() && !message.isForwarded()) { - if (message.isNewGif()) { - getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date); - } else if (!message.isAnimatedEmoji() && (message.isSticker() || message.isAnimatedSticker())) { - getMediaDataController().addRecentSticker(MediaDataController.TYPE_IMAGE, message, message.messageOwner.media.document, message.messageOwner.date, false); + if (!hasNotOutMessage && !message.isOut()) { + hasNotOutMessage = true; + } + if (message.isOut() && !message.isSending() && !message.isForwarded()) { + if (message.isNewGif()) { + getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date); + } else if (!message.isAnimatedEmoji() && (message.isSticker() || message.isAnimatedSticker())) { + getMediaDataController().addRecentSticker(MediaDataController.TYPE_IMAGE, message, message.messageOwner.media.document, message.messageOwner.date, false); + } + } + if (message.isOut() && message.isSent()) { + updateRating = true; } - } - if (message.isOut() && message.isSent()) { - updateRating = true; } } - getMediaDataController().loadReplyMessagesForMessages(messages, uid); - getNotificationCenter().postNotificationName(NotificationCenter.didReceiveNewMessages, uid, messages); + getMediaDataController().loadReplyMessagesForMessages(messages, uid, scheduled); + getNotificationCenter().postNotificationName(NotificationCenter.didReceiveNewMessages, uid, messages, scheduled); - if (lastMessage == null) { + if (lastMessage == null || scheduled) { return; } TLRPC.TL_dialog dialog = (TLRPC.TL_dialog) dialogs_dict.get(uid); @@ -10483,50 +10850,48 @@ protected void updateInterfaceWithMessages(final long uid, final ArrayList 0) { - String type = reason.substring(0, index); - if (type.contains("-all") || type.contains("-android")) { - return reason.substring(index + 2); + for (int a = 0, N = reasons.size(); a < N; a++) { + TLRPC.TL_restrictionReason reason = reasons.get(a); + if ("all".equals(reason.platform) || "android".equals(reason.platform)) { + return reason.text; } } return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 5fb23dc4e72..df6da0deaf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -67,7 +67,7 @@ public interface BooleanCallback { private CountDownLatch openSync = new CountDownLatch(1); private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT]; - private final static int LAST_DB_VERSION = 62; + private final static int LAST_DB_VERSION = 63; public static MessagesStorage getInstance(int num) { MessagesStorage localInstance = Instance[num]; @@ -219,6 +219,10 @@ public void openDatabase(int openTries) { database.executeFast("CREATE TABLE media_holes_v2(uid INTEGER, type INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, type, start));").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_end_media_holes_v2 ON media_holes_v2(uid, type, end);").stepThis().dispose(); + database.executeFast("CREATE TABLE scheduled_messages(mid INTEGER PRIMARY KEY, uid INTEGER, send_state INTEGER, date INTEGER, data BLOB, ttl INTEGER, replydata BLOB)").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_scheduled_messages ON scheduled_messages(mid, send_state, date);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_idx_scheduled_messages ON scheduled_messages(uid, date);").stepThis().dispose(); + database.executeFast("CREATE TABLE messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_idx_messages ON messages(uid, mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid);").stepThis().dispose(); @@ -792,6 +796,13 @@ private void updateDbToLastVersion(final int currentVersion) { version = 62; } if (version == 62) { + database.executeFast("CREATE TABLE IF NOT EXISTS scheduled_messages(mid INTEGER PRIMARY KEY, uid INTEGER, send_state INTEGER, date INTEGER, data BLOB, ttl INTEGER, replydata BLOB)").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_scheduled_messages ON scheduled_messages(mid, send_state, date);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_idx_scheduled_messages ON scheduled_messages(uid, date);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 63").stepThis().dispose(); + version = 63; + } + if (version == 63) { } } catch (Exception e) { @@ -1035,7 +1046,7 @@ private void loadPendingTasks() { removePendingTask(taskId); } else { final TLObject finalRequest = request; - AndroidUtilities.runOnUIThread(() -> getMessagesController().deleteMessages(null, null, null, channelId, true, taskId, finalRequest)); + AndroidUtilities.runOnUIThread(() -> getMessagesController().deleteMessages(null, null, null, 0, channelId, true, false, taskId, finalRequest)); } break; } @@ -1058,7 +1069,8 @@ private void loadPendingTasks() { AndroidUtilities.runOnUIThread(() -> getMessagesController().markMessageAsRead(mid, channelId, inputChannel, ttl, taskId)); break; } - case 12: { + case 12: + case 19: { long wallPaperId = data.readInt64(false); long accessHash = data.readInt64(false); boolean isBlurred = data.readBool(false); @@ -1066,7 +1078,13 @@ private void loadPendingTasks() { int backgroundColor = data.readInt32(false); float intesity = (float) data.readDouble(false); boolean install = data.readBool(false); - AndroidUtilities.runOnUIThread(() -> getMessagesController().saveWallpaperToServer(null, wallPaperId, accessHash, isBlurred, isMotion, backgroundColor, intesity, install, taskId)); + final String slug; + if (type == 19) { + slug = data.readString(false); + } else { + slug = null; + } + AndroidUtilities.runOnUIThread(() -> getMessagesController().saveWallpaperToServer(null, wallPaperId, slug, accessHash, isBlurred, isMotion, backgroundColor, intesity, install, taskId)); break; } case 13: { @@ -1106,6 +1124,19 @@ private void loadPendingTasks() { AndroidUtilities.runOnUIThread(() -> getMessagesController().addDialogToFolder(null, folderId, -1, peers, taskId)); break; } + case 18: { + final long dialogId = data.readInt64(false); + final int channelId = data.readInt32(false); + int constructor = data.readInt32(false); + TLObject request = TLRPC.TL_messages_deleteScheduledMessages.TLdeserialize(data, constructor, false); + if (request == null) { + removePendingTask(taskId); + } else { + final TLObject finalRequest = request; + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).deleteMessages(null, null, null, dialogId, channelId, true, true, taskId, finalRequest)); + } + break; + } } data.reuse(); } @@ -1283,7 +1314,7 @@ public void readAllDialogs() { for (int a = 0; a < dialogs.size(); a++) { long did = dialogs.keyAt(a); ReadDialog dialog = dialogs.valueAt(a); - getMessagesController().markDialogAsRead(did, dialog.lastMid, dialog.lastMid, dialog.date, false, dialog.unreadCount, true); + getMessagesController().markDialogAsRead(did, dialog.lastMid, dialog.lastMid, dialog.date, false, dialog.unreadCount, true, 0); } }); } catch (Exception e) { @@ -1685,7 +1716,7 @@ public void putWebRecent(final ArrayList arrayList) state.bindInteger(2, searchImage.type); state.bindString(3, searchImage.imageUrl != null ? searchImage.imageUrl : ""); state.bindString(4, searchImage.thumbUrl != null ? searchImage.thumbUrl : ""); - state.bindString(5, searchImage.localUrl != null ? searchImage.localUrl : ""); + state.bindString(5, ""); state.bindInteger(6, searchImage.width); state.bindInteger(7, searchImage.height); state.bindInteger(8, searchImage.size); @@ -1747,11 +1778,11 @@ public void deleteUserChannelHistory(final int channelId, final int uid) { } cursor.dispose(); AndroidUtilities.runOnUIThread(() -> getMessagesController().markChannelDialogMessageAsDeleted(mids, channelId)); - markMessagesAsDeletedInternal(mids, channelId, false); + markMessagesAsDeletedInternal(mids, channelId, false, false); updateDialogsWithDeletedMessagesInternal(mids, null, channelId); getFileLoader().deleteFiles(filesToDelete, 0); if (!mids.isEmpty()) { - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, channelId)); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, channelId, false)); } } catch (Exception e) { FileLog.e(e); @@ -1832,9 +1863,7 @@ public void deleteDialog(final long did, final int messagesOnly) { int lower_id = (int) did; int high_id = (int) (did >> 32); if (lower_id != 0) { - if (high_id == 1) { - database.executeFast("DELETE FROM chats WHERE uid = " + lower_id).stepThis().dispose(); - } else if (lower_id < 0) { + if (lower_id < 0) { //database.executeFast("DELETE FROM chats WHERE uid = " + (-lower_id)).stepThis().dispose(); } } else { @@ -2154,6 +2183,12 @@ public void emptyMessagesMedia(final ArrayList mids) { if (message.media != null) { if (!addFilesToDelete(message, filesToDelete, true)) { continue; + } else { + if (message.media.document != null) { + message.media.document = new TLRPC.TL_documentEmpty(); + } else if (message.media.photo != null) { + message.media.photo = new TLRPC.TL_photoEmpty(); + } } message.media.flags = message.media.flags &~ 1; message.id = cursor.intValue(1); @@ -2179,7 +2214,7 @@ public void emptyMessagesMedia(final ArrayList mids) { state.bindInteger(4, message.send_state); state.bindInteger(5, message.date); state.bindByteBuffer(6, data); - state.bindInteger(7, (MessageObject.isOut(message) ? 1 : 0)); + state.bindInteger(7, (MessageObject.isOut(message) || message.from_scheduled ? 1 : 0)); state.bindInteger(8, message.ttl); if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { state.bindInteger(9, message.views); @@ -2262,6 +2297,43 @@ public void updateMessagePollResults(long pollId, TLRPC.TL_poll poll, TLRPC.TL_p }); } + public void updateMessageReactions(long dialogId, int msgId, int channelId, TLRPC.TL_messageReactions reactions) { + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + long mid = msgId; + if (channelId != 0) { + mid |= ((long) channelId) << 32; + } + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM messages WHERE mid = %d", mid)); + if (cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.readAttachPath(data, getUserConfig().clientUserId); + data.reuse(); + if (message != null) { + MessageObject.updateReactions(message, reactions); + SQLitePreparedStatement state = database.executeFast("UPDATE messages SET data = ? WHERE mid = ?"); + data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); + state.requery(); + state.bindByteBuffer(1, data); + state.bindLong(2, mid); + state.step(); + data.reuse(); + state.dispose(); + } + } + } + cursor.dispose(); + database.commitTransaction(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + public void getNewTask(final ArrayList oldTask, final int channelId) { storageQueue.postRunnable(() -> { try { @@ -3205,7 +3277,7 @@ public TLRPC.ChatFull loadChatInfo(final int chat_id, final CountDownLatch count return result[0]; } - public void processPendingRead(final long dialog_id, final long maxPositiveId, final long maxNegativeId, final boolean isChannel) { + public void processPendingRead(final long dialog_id, final long maxPositiveId, final long maxNegativeId, final boolean isChannel, final int scheduledCount) { final int maxDate = lastSavedDate; storageQueue.postRunnable(() -> { try { @@ -3244,7 +3316,7 @@ public void processPendingRead(final long dialog_id, final long maxPositiveId, f int updatedCount = 0; cursor = database.queryFinalized("SELECT changes()"); if (cursor.next()) { - updatedCount = cursor.intValue(0); + updatedCount = cursor.intValue(0) + scheduledCount; } cursor.dispose(); unreadCount = Math.max(0, unreadCount - updatedCount); @@ -3279,7 +3351,7 @@ public void processPendingRead(final long dialog_id, final long maxPositiveId, f int updatedCount = 0; cursor = database.queryFinalized("SELECT changes()"); if (cursor.next()) { - updatedCount = cursor.intValue(0); + updatedCount = cursor.intValue(0) + scheduledCount; } cursor.dispose(); unreadCount = Math.max(0, unreadCount - updatedCount); @@ -3594,13 +3666,13 @@ public void getUnsentMessages(final int count) { try { SparseArray messageHashMap = new SparseArray<>(); ArrayList messages = new ArrayList<>(); + ArrayList scheduledMessages = new ArrayList<>(); ArrayList users = new ArrayList<>(); ArrayList chats = new ArrayList<>(); ArrayList encryptedChats = new ArrayList<>(); ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); - ArrayList broadcastIds = new ArrayList<>(); ArrayList encryptedChatIds = new ArrayList<>(); SQLiteCursor cursor = database.queryFinalized("SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.uid, s.seq_in, s.seq_out, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid LEFT JOIN messages_seq as s ON m.mid = s.mid WHERE (m.mid < 0 AND m.send_state = 1) OR (m.mid > 0 AND m.send_state = 3) ORDER BY m.mid DESC LIMIT " + count); @@ -3629,19 +3701,13 @@ public void getUnsentMessages(final int count) { int high_id = (int) (message.dialog_id >> 32); if (lower_id != 0) { - if (high_id == 1) { - if (!broadcastIds.contains(lower_id)) { - broadcastIds.add(lower_id); + if (lower_id < 0) { + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); } } else { - if (lower_id < 0) { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } - } else { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); } } } else { @@ -3655,14 +3721,58 @@ public void getUnsentMessages(final int count) { if (message.send_state != 3 && (message.to_id.channel_id == 0 && !MessageObject.isUnread(message) && lower_id != 0 || message.id > 0)) { message.send_state = 0; } - if (lower_id == 0 && !cursor.isNull(5)) { - message.random_id = cursor.longValue(5); - } } } } cursor.dispose(); + cursor = database.queryFinalized("SELECT m.data, m.send_state, m.mid, m.date, r.random_id, m.uid, m.ttl FROM scheduled_messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE (m.mid < 0 AND m.send_state = 1) OR (m.mid > 0 AND m.send_state = 3) ORDER BY date ASC"); + while (cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.send_state = cursor.intValue(1); + message.readAttachPath(data, getUserConfig().clientUserId); + data.reuse(); + if (messageHashMap.indexOfKey(message.id) < 0) { + message.id = cursor.intValue(2); + message.date = cursor.intValue(3); + if (!cursor.isNull(4)) { + message.random_id = cursor.longValue(4); + } + message.dialog_id = cursor.longValue(5); + message.ttl = cursor.intValue(6); + scheduledMessages.add(message); + messageHashMap.put(message.id, message); + + int lower_id = (int) message.dialog_id; + int high_id = (int) (message.dialog_id >> 32); + + if (lower_id != 0) { + if (lower_id < 0) { + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); + } + } else { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); + } + } + } else { + if (!encryptedChatIds.contains(high_id)) { + encryptedChatIds.add(high_id); + } + } + + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); + + if (message.send_state != 3 && (message.to_id.channel_id == 0 && !MessageObject.isUnread(message) && lower_id != 0 || message.id > 0)) { + message.send_state = 0; + } + } + } + } + cursor.dispose(); if (!encryptedChatIds.isEmpty()) { getEncryptedChatsInternal(TextUtils.join(",", encryptedChatIds), encryptedChats, usersToLoad); @@ -3672,7 +3782,7 @@ public void getUnsentMessages(final int count) { getUsersInternal(TextUtils.join(",", usersToLoad), users); } - if (!chatsToLoad.isEmpty() || !broadcastIds.isEmpty()) { + if (!chatsToLoad.isEmpty()) { StringBuilder stringToLoad = new StringBuilder(); for (int a = 0; a < chatsToLoad.size(); a++) { Integer cid = chatsToLoad.get(a); @@ -3681,17 +3791,10 @@ public void getUnsentMessages(final int count) { } stringToLoad.append(cid); } - for (int a = 0; a < broadcastIds.size(); a++) { - Integer cid = broadcastIds.get(a); - if (stringToLoad.length() != 0) { - stringToLoad.append(","); - } - stringToLoad.append(-cid); - } getChatsInternal(stringToLoad.toString(), chats); } - getSendMessagesHelper().processUnsentMessages(messages, users, chats, encryptedChats); + getSendMessagesHelper().processUnsentMessages(messages, scheduledMessages, users, chats, encryptedChats); } catch (Exception e) { FileLog.e(e); } @@ -3788,10 +3891,10 @@ public void getMessagesCount(final long dialog_id, final IntCallback callback) { }); } - public void getMessages(final long dialog_id, final int count, final int max_id, final int offset_date, final int minDate, final int classGuid, final int load_type, final boolean isChannel, final int loadIndex) { + public void getMessages(final long dialog_id, final int count, final int max_id, final int offset_date, final int minDate, final int classGuid, final int load_type, final boolean isChannel, final boolean scheduled, final int loadIndex) { storageQueue.postRunnable(() -> { - int currentUserId = getUserConfig().clientUserId; TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages(); + int currentUserId = getUserConfig().clientUserId; int count_unread = 0; int mentions_unread = 0; int count_query = count; @@ -3819,254 +3922,353 @@ public void getMessages(final long dialog_id, final int count, final int max_id, ArrayList replyMessages = new ArrayList<>(); SparseArray> replyMessageOwners = new SparseArray<>(); LongSparseArray> replyMessageRandomOwners = new LongSparseArray<>(); - SQLiteCursor cursor; - int lower_id = (int) dialog_id; - if (lower_id != 0) { - if (load_type == 3 && minDate == 0) { - cursor = database.queryFinalized("SELECT inbox_max, unread_count, date, unread_count_i FROM dialogs WHERE did = " + dialog_id); - if (cursor.next()) { - min_unread_id = cursor.intValue(0) + 1; - count_unread = cursor.intValue(1); - max_unread_date = cursor.intValue(2); - mentions_unread = cursor.intValue(3); + if (scheduled) { + isEnd = true; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.ttl FROM scheduled_messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC", dialog_id)); + while (cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(0); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.send_state = cursor.intValue(1); + message.id = cursor.intValue(2); + if (message.id > 0 && message.send_state != 0 && message.send_state != 3) { + message.send_state = 0; + } + if (dialog_id == currentUserId) { + message.out = true; + message.unread = false; + } else { + message.unread = true; + } + message.readAttachPath(data, currentUserId); + data.reuse(); + message.date = cursor.intValue(3); + message.dialog_id = dialog_id; + if (message.ttl == 0) { + message.ttl = cursor.intValue(6); + } + res.messages.add(message); + + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); + + if (message.reply_to_msg_id != 0 || message.reply_to_random_id != 0) { + if (!cursor.isNull(5)) { + data = cursor.byteBufferValue(5); + if (data != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.replyMessage.readAttachPath(data, currentUserId); + data.reuse(); + if (message.replyMessage != null) { + if (MessageObject.isMegagroup(message)) { + message.replyMessage.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad); + } + } + } + if (message.replyMessage == null) { + if (message.reply_to_msg_id != 0) { + long messageId = message.reply_to_msg_id; + if (message.to_id.channel_id != 0) { + messageId |= ((long) message.to_id.channel_id) << 32; + } + if (!replyMessages.contains(messageId)) { + replyMessages.add(messageId); + } + ArrayList messages = replyMessageOwners.get(message.reply_to_msg_id); + if (messages == null) { + messages = new ArrayList<>(); + replyMessageOwners.put(message.reply_to_msg_id, messages); + } + messages.add(message); + } else { + if (!replyMessages.contains(message.reply_to_random_id)) { + replyMessages.add(message.reply_to_random_id); + } + ArrayList messages = replyMessageRandomOwners.get(message.reply_to_random_id); + if (messages == null) { + messages = new ArrayList<>(); + replyMessageRandomOwners.put(message.reply_to_random_id, messages); + } + messages.add(message); + } + } + } } - cursor.dispose(); - } else if (load_type != 1 && load_type != 3 && load_type != 4 && minDate == 0) { - if (load_type == 2) { + } + cursor.dispose(); + } else { + int lower_id = (int) dialog_id; + if (lower_id != 0) { + if (load_type == 3 && minDate == 0) { cursor = database.queryFinalized("SELECT inbox_max, unread_count, date, unread_count_i FROM dialogs WHERE did = " + dialog_id); if (cursor.next()) { - messageMaxId = max_id_query = min_unread_id = cursor.intValue(0); + min_unread_id = cursor.intValue(0) + 1; count_unread = cursor.intValue(1); max_unread_date = cursor.intValue(2); mentions_unread = cursor.intValue(3); - queryFromServer = true; - if (messageMaxId != 0 && channelId != 0) { - messageMaxId |= ((long) channelId) << 32; - } } cursor.dispose(); - if (!queryFromServer) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0", dialog_id)); + } else if (load_type != 1 && load_type != 3 && load_type != 4 && minDate == 0) { + if (load_type == 2) { + cursor = database.queryFinalized("SELECT inbox_max, unread_count, date, unread_count_i FROM dialogs WHERE did = " + dialog_id); if (cursor.next()) { - min_unread_id = cursor.intValue(0); - max_unread_date = cursor.intValue(1); + messageMaxId = max_id_query = min_unread_id = cursor.intValue(0); + count_unread = cursor.intValue(1); + max_unread_date = cursor.intValue(2); + mentions_unread = cursor.intValue(3); + queryFromServer = true; + if (messageMaxId != 0 && channelId != 0) { + messageMaxId |= ((long) channelId) << 32; + } } cursor.dispose(); - if (min_unread_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid >= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id)); + if (!queryFromServer) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0", dialog_id)); if (cursor.next()) { - count_unread = cursor.intValue(0); + min_unread_id = cursor.intValue(0); + max_unread_date = cursor.intValue(1); } cursor.dispose(); - } - } else if (max_id_query == 0) { - int existingUnreadCount = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid > 0 AND out = 0 AND read_state IN(0,2)", dialog_id)); - if (cursor.next()) { - existingUnreadCount = cursor.intValue(0); - } - cursor.dispose(); - if (existingUnreadCount == count_unread) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0", dialog_id)); + if (min_unread_id != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid >= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id)); + if (cursor.next()) { + count_unread = cursor.intValue(0); + } + cursor.dispose(); + } + } else if (max_id_query == 0) { + int existingUnreadCount = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid > 0 AND out = 0 AND read_state IN(0,2)", dialog_id)); if (cursor.next()) { - messageMaxId = max_id_query = min_unread_id = cursor.intValue(0); - if (messageMaxId != 0 && channelId != 0) { - messageMaxId |= ((long) channelId) << 32; + existingUnreadCount = cursor.intValue(0); + } + cursor.dispose(); + if (existingUnreadCount == count_unread) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0", dialog_id)); + if (cursor.next()) { + messageMaxId = max_id_query = min_unread_id = cursor.intValue(0); + if (messageMaxId != 0 && channelId != 0) { + messageMaxId |= ((long) channelId) << 32; + } } + cursor.dispose(); } + } else { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND start < %d AND end > %d", dialog_id, max_id_query, max_id_query)); + boolean containMessage = !cursor.next(); cursor.dispose(); - } - } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND start < %d AND end > %d", dialog_id, max_id_query, max_id_query)); - boolean containMessage = !cursor.next(); - cursor.dispose(); - if (containMessage) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > %d", dialog_id, max_id_query)); - if (cursor.next()) { - messageMaxId = max_id_query = cursor.intValue(0); - if (messageMaxId != 0 && channelId != 0) { - messageMaxId |= ((long) channelId) << 32; + if (containMessage) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > %d", dialog_id, max_id_query)); + if (cursor.next()) { + messageMaxId = max_id_query = cursor.intValue(0); + if (messageMaxId != 0 && channelId != 0) { + messageMaxId |= ((long) channelId) << 32; + } } + cursor.dispose(); } - cursor.dispose(); } } - } - - if (count_query > count_unread || count_unread < num) { - count_query = Math.max(count_query, count_unread + 10); - if (count_unread < num) { - count_unread = 0; - min_unread_id = 0; - messageMaxId = 0; - last_message_id = 0; - queryFromServer = false; - } - } else { - offset_query = count_unread - count_query; - count_query += 10; - } - } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start IN (0, 1)", dialog_id)); - if (cursor.next()) { - isEnd = cursor.intValue(0) == 1; - cursor.dispose(); - } else { - cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); - if (cursor.next()) { - int mid = cursor.intValue(0); - if (mid != 0) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_holes VALUES(?, ?, ?)"); - state.requery(); - state.bindLong(1, dialog_id); - state.bindInteger(2, 0); - state.bindInteger(3, mid); - state.step(); - state.dispose(); + if (count_query > count_unread || count_unread < num) { + count_query = Math.max(count_query, count_unread + 10); + if (count_unread < num) { + count_unread = 0; + min_unread_id = 0; + messageMaxId = 0; + last_message_id = 0; + queryFromServer = false; + } + } else { + offset_query = count_unread - count_query; + count_query += 10; } } - cursor.dispose(); - } - if (load_type == 3 || load_type == 4 || queryFromServer && load_type == 2) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start IN (0, 1)", dialog_id)); if (cursor.next()) { - last_message_id = cursor.intValue(0); - } - cursor.dispose(); - - if (load_type == 4 && offset_date != 0) { - int startMid; - int endMid; - - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND date <= %d AND mid > 0", dialog_id, offset_date)); + isEnd = cursor.intValue(0) == 1; + cursor.dispose(); + } else { + cursor.dispose(); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); if (cursor.next()) { - startMid = cursor.intValue(0); - } else { - startMid = -1; + int mid = cursor.intValue(0); + if (mid != 0) { + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_holes VALUES(?, ?, ?)"); + state.requery(); + state.bindLong(1, dialog_id); + state.bindInteger(2, 0); + state.bindInteger(3, mid); + state.step(); + state.dispose(); + } } cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND date >= %d AND mid > 0", dialog_id, offset_date)); + } + + if (load_type == 3 || load_type == 4 || queryFromServer && load_type == 2) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); if (cursor.next()) { - endMid = cursor.intValue(0); - } else { - endMid = -1; + last_message_id = cursor.intValue(0); } cursor.dispose(); - if (startMid != -1 && endMid != -1) { - if (startMid == endMid) { - max_id_query = startMid; + + if (load_type == 4 && offset_date != 0) { + int startMid; + int endMid; + + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND date <= %d AND mid > 0", dialog_id, offset_date)); + if (cursor.next()) { + startMid = cursor.intValue(0); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d", dialog_id, startMid, startMid)); - if (cursor.next()) { - startMid = -1; - } - cursor.dispose(); - if (startMid != -1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d", dialog_id, endMid, endMid)); + startMid = -1; + } + cursor.dispose(); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND date >= %d AND mid > 0", dialog_id, offset_date)); + if (cursor.next()) { + endMid = cursor.intValue(0); + } else { + endMid = -1; + } + cursor.dispose(); + if (startMid != -1 && endMid != -1) { + if (startMid == endMid) { + max_id_query = startMid; + } else { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d", dialog_id, startMid, startMid)); if (cursor.next()) { - endMid = -1; + startMid = -1; } cursor.dispose(); - if (endMid != -1) { - max_id_override = endMid; - messageMaxId = max_id_query = endMid; - if (messageMaxId != 0 && channelId != 0) { - messageMaxId |= ((long) channelId) << 32; + if (startMid != -1) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d", dialog_id, endMid, endMid)); + if (cursor.next()) { + endMid = -1; + } + cursor.dispose(); + if (endMid != -1) { + max_id_override = endMid; + messageMaxId = max_id_query = endMid; + if (messageMaxId != 0 && channelId != 0) { + messageMaxId |= ((long) channelId) << 32; + } } } } } } - } - boolean containMessage = max_id_query != 0; - if (containMessage) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start < %d AND end > %d", dialog_id, max_id_query, max_id_query)); - if (cursor.next()) { - containMessage = false; + boolean containMessage = max_id_query != 0; + if (containMessage) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start < %d AND end > %d", dialog_id, max_id_query, max_id_query)); + if (cursor.next()) { + containMessage = false; + } + cursor.dispose(); } - cursor.dispose(); - } - if (containMessage) { - long holeMessageMaxId = 0; - long holeMessageMinId = 1; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start >= %d ORDER BY start ASC LIMIT 1", dialog_id, max_id_query)); - if (cursor.next()) { - holeMessageMaxId = cursor.intValue(0); - if (channelId != 0) { - holeMessageMaxId |= ((long) channelId) << 32; + if (containMessage) { + long holeMessageMaxId = 0; + long holeMessageMinId = 1; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM messages_holes WHERE uid = %d AND start >= %d ORDER BY start ASC LIMIT 1", dialog_id, max_id_query)); + if (cursor.next()) { + holeMessageMaxId = cursor.intValue(0); + if (channelId != 0) { + holeMessageMaxId |= ((long) channelId) << 32; + } } - } - cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1", dialog_id, max_id_query)); - if (cursor.next()) { - holeMessageMinId = cursor.intValue(0); - if (channelId != 0) { - holeMessageMinId |= ((long) channelId) << 32; + cursor.dispose(); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1", dialog_id, max_id_query)); + if (cursor.next()) { + holeMessageMinId = cursor.intValue(0); + if (channelId != 0) { + holeMessageMinId |= ((long) channelId) << 32; + } } - } /*if (holeMessageMaxId == holeMessageMinId) { holeMessageMaxId = 0; holeMessageMinId = 1; }*/ - cursor.dispose(); - if (holeMessageMaxId != 0 || holeMessageMinId != 1) { - if (holeMessageMaxId == 0) { - holeMessageMaxId = 1000000000; - if (channelId != 0) { - holeMessageMaxId |= ((long) channelId) << 32; + cursor.dispose(); + if (holeMessageMaxId != 0 || holeMessageMinId != 1) { + if (holeMessageMaxId == 0) { + holeMessageMaxId = 1000000000; + if (channelId != 0) { + holeMessageMaxId |= ((long) channelId) << 32; + } + } + cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + + "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND (m.mid <= %d OR m.mid < 0) ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, holeMessageMinId, count_query / 2, dialog_id, messageMaxId, holeMessageMaxId, count_query / 2)); + } else { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + + "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); + } + } else { + if (load_type == 2) { + int existingUnreadCount = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid != 0 AND out = 0 AND read_state IN(0,2)", dialog_id)); + if (cursor.next()) { + existingUnreadCount = cursor.intValue(0); } + cursor.dispose(); + if (existingUnreadCount == count_unread) { + unreadCountIsLocal = true; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + + "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); + } else { + cursor = null; + } + } else { + cursor = null; } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + - "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND (m.mid <= %d OR m.mid < 0) ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, holeMessageMinId, count_query / 2, dialog_id, messageMaxId, holeMessageMaxId, count_query / 2)); + } + } else if (load_type == 1) { + long holeMessageId = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND start >= %d AND start != 1 AND end != 1 ORDER BY start ASC LIMIT 1", dialog_id, max_id)); + if (cursor.next()) { + holeMessageId = cursor.intValue(0); + if (channelId != 0) { + holeMessageId |= ((long) channelId) << 32; + } + } + cursor.dispose(); + if (holeMessageId != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d AND m.mid <= %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, messageMaxId, holeMessageId, count_query)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + - "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, messageMaxId, count_query)); } - } else { - if (load_type == 2) { - int existingUnreadCount = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid != 0 AND out = 0 AND read_state IN(0,2)", dialog_id)); + } else if (minDate != 0) { + if (messageMaxId != 0) { + long holeMessageId = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1", dialog_id, max_id)); if (cursor.next()) { - existingUnreadCount = cursor.intValue(0); + holeMessageId = cursor.intValue(0); + if (channelId != 0) { + holeMessageId |= ((long) channelId) << 32; + } } cursor.dispose(); - if (existingUnreadCount == count_unread) { - unreadCountIsLocal = true; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + - "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); + if (holeMessageId != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, messageMaxId, holeMessageId, count_query)); } else { - cursor = null; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, messageMaxId, count_query)); } } else { - cursor = null; - } - } - } else if (load_type == 1) { - long holeMessageId = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND start >= %d AND start != 1 AND end != 1 ORDER BY start ASC LIMIT 1", dialog_id, max_id)); - if (cursor.next()) { - holeMessageId = cursor.intValue(0); - if (channelId != 0) { - holeMessageId |= ((long) channelId) << 32; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); } - } - cursor.dispose(); - if (holeMessageId != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d AND m.mid <= %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, messageMaxId, holeMessageId, count_query)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, messageMaxId, count_query)); - } - } else if (minDate != 0) { - if (messageMaxId != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); + if (cursor.next()) { + last_message_id = cursor.intValue(0); + } + cursor.dispose(); + long holeMessageId = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1", dialog_id, max_id)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM messages_holes WHERE uid = %d", dialog_id)); if (cursor.next()) { holeMessageId = cursor.intValue(0); if (channelId != 0) { @@ -4075,249 +4277,237 @@ public void getMessages(final long dialog_id, final int count, final int max_id, } cursor.dispose(); if (holeMessageId != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, messageMaxId, holeMessageId, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, holeMessageId, offset_query, count_query)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, messageMaxId, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, offset_query, count_query)); } - } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); } } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0", dialog_id)); - if (cursor.next()) { - last_message_id = cursor.intValue(0); - } - cursor.dispose(); + isEnd = true; - long holeMessageId = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM messages_holes WHERE uid = %d", dialog_id)); - if (cursor.next()) { - holeMessageId = cursor.intValue(0); - if (channelId != 0) { - holeMessageId |= ((long) channelId) << 32; + if (load_type == 3 && minDate == 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0", dialog_id)); + if (cursor.next()) { + min_unread_id = cursor.intValue(0); } - } - cursor.dispose(); - if (holeMessageId != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, holeMessageId, offset_query, count_query)); - } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, offset_query, count_query)); - } - } - } else { - isEnd = true; - - if (load_type == 3 && minDate == 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0", dialog_id)); - if (cursor.next()) { - min_unread_id = cursor.intValue(0); - } - cursor.dispose(); + cursor.dispose(); - int min_unread_id2 = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0", dialog_id)); - if (cursor.next()) { - min_unread_id2 = cursor.intValue(0); - max_unread_date = cursor.intValue(1); - } - cursor.dispose(); - if (min_unread_id2 != 0) { - min_unread_id = min_unread_id2; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id2)); + int min_unread_id2 = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0", dialog_id)); if (cursor.next()) { - count_unread = cursor.intValue(0); + min_unread_id2 = cursor.intValue(0); + max_unread_date = cursor.intValue(1); } cursor.dispose(); + if (min_unread_id2 != 0) { + min_unread_id = min_unread_id2; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id2)); + if (cursor.next()) { + count_unread = cursor.intValue(0); + } + cursor.dispose(); + } } - } - - if (load_type == 3 || load_type == 4) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0", dialog_id)); - if (cursor.next()) { - last_message_id = cursor.intValue(0); - } - cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.mid DESC LIMIT %d) UNION " + - "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); - } else if (load_type == 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d ORDER BY m.mid DESC LIMIT %d", dialog_id, max_id, count_query)); - } else if (minDate != 0) { - if (max_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d", dialog_id, max_id, count_query)); - } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); - } - } else { - if (load_type == 2) { + if (load_type == 3 || load_type == 4) { cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0", dialog_id)); if (cursor.next()) { last_message_id = cursor.intValue(0); } cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0", dialog_id)); - if (cursor.next()) { - min_unread_id = cursor.intValue(0); - max_unread_date = cursor.intValue(1); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.mid DESC LIMIT %d) UNION " + + "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d)", dialog_id, messageMaxId, count_query / 2, dialog_id, messageMaxId, count_query / 2)); + } else if (load_type == 1) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d ORDER BY m.mid DESC LIMIT %d", dialog_id, max_id, count_query)); + } else if (minDate != 0) { + if (max_id != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d", dialog_id, max_id, count_query)); + } else { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); } - cursor.dispose(); - if (min_unread_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id)); + } else { + if (load_type == 2) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0", dialog_id)); if (cursor.next()) { - count_unread = cursor.intValue(0); + last_message_id = cursor.intValue(0); + } + cursor.dispose(); + + cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0", dialog_id)); + if (cursor.next()) { + min_unread_id = cursor.intValue(0); + max_unread_date = cursor.intValue(1); } cursor.dispose(); + if (min_unread_id != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2)", dialog_id, min_unread_id)); + if (cursor.next()) { + count_unread = cursor.intValue(0); + } + cursor.dispose(); + } } - } - if (count_query > count_unread || count_unread < num) { - count_query = Math.max(count_query, count_unread + 10); - if (count_unread < num) { - count_unread = 0; - min_unread_id = 0; - last_message_id = 0; + if (count_query > count_unread || count_unread < num) { + count_query = Math.max(count_query, count_unread + 10); + if (count_unread < num) { + count_unread = 0; + min_unread_id = 0; + last_message_id = 0; + } + } else { + offset_query = count_unread - count_query; + count_query += 10; } - } else { - offset_query = count_unread - count_query; - count_query += 10; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, offset_query, count_query)); } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, offset_query, count_query)); } - } - int minId = Integer.MAX_VALUE; - int maxId = Integer.MIN_VALUE; - if (cursor != null) { - while (cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(1); - if (data != null) { - TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.send_state = cursor.intValue(2); - if (message.id > 0 && message.send_state != 0 && message.send_state != 3) { - message.send_state = 0; - } - if (dialog_id == currentUserId) { - message.out = true; - } - message.readAttachPath(data, currentUserId); - data.reuse(); - MessageObject.setUnreadFlags(message, cursor.intValue(0)); - message.id = cursor.intValue(3); - if (message.id > 0) { - minId = Math.min(message.id, minId); - maxId = Math.max(message.id, maxId); - } - message.date = cursor.intValue(4); - message.dialog_id = dialog_id; - if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - message.views = cursor.intValue(7); - } - if (lower_id != 0 && message.ttl == 0) { - message.ttl = cursor.intValue(8); - } - if (cursor.intValue(9) != 0) { - message.mentioned = true; - } - res.messages.add(message); + int minId = Integer.MAX_VALUE; + int maxId = Integer.MIN_VALUE; + if (cursor != null) { + while (cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(1); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.send_state = cursor.intValue(2); + message.id = cursor.intValue(3); + if (message.id > 0 && message.send_state != 0 && message.send_state != 3) { + message.send_state = 0; + } + if (dialog_id == currentUserId) { + message.out = true; + } + message.readAttachPath(data, currentUserId); + data.reuse(); + MessageObject.setUnreadFlags(message, cursor.intValue(0)); + if (message.id > 0) { + minId = Math.min(message.id, minId); + maxId = Math.max(message.id, maxId); + } + message.date = cursor.intValue(4); + message.dialog_id = dialog_id; + if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + message.views = cursor.intValue(7); + } + if (lower_id != 0 && message.ttl == 0) { + message.ttl = cursor.intValue(8); + } + if (cursor.intValue(9) != 0) { + message.mentioned = true; + } + res.messages.add(message); - addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); - if (message.reply_to_msg_id != 0 || message.reply_to_random_id != 0) { - if (!cursor.isNull(6)) { - data = cursor.byteBufferValue(6); - if (data != null) { - message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.replyMessage.readAttachPath(data, currentUserId); - data.reuse(); - if (message.replyMessage != null) { - if (MessageObject.isMegagroup(message)) { - message.replyMessage.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + if (message.reply_to_msg_id != 0 || message.reply_to_random_id != 0) { + if (!cursor.isNull(6)) { + data = cursor.byteBufferValue(6); + if (data != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.replyMessage.readAttachPath(data, currentUserId); + data.reuse(); + if (message.replyMessage != null) { + if (MessageObject.isMegagroup(message)) { + message.replyMessage.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad); } - addUsersAndChatsFromMessage(message.replyMessage, usersToLoad, chatsToLoad); } } - } - if (message.replyMessage == null) { - if (message.reply_to_msg_id != 0) { - long messageId = message.reply_to_msg_id; - if (message.to_id.channel_id != 0) { - messageId |= ((long) message.to_id.channel_id) << 32; - } - if (!replyMessages.contains(messageId)) { - replyMessages.add(messageId); - } - ArrayList messages = replyMessageOwners.get(message.reply_to_msg_id); - if (messages == null) { - messages = new ArrayList<>(); - replyMessageOwners.put(message.reply_to_msg_id, messages); - } - messages.add(message); - } else { - if (!replyMessages.contains(message.reply_to_random_id)) { - replyMessages.add(message.reply_to_random_id); - } - ArrayList messages = replyMessageRandomOwners.get(message.reply_to_random_id); - if (messages == null) { - messages = new ArrayList<>(); - replyMessageRandomOwners.put(message.reply_to_random_id, messages); + if (message.replyMessage == null) { + if (message.reply_to_msg_id != 0) { + long messageId = message.reply_to_msg_id; + if (message.to_id.channel_id != 0) { + messageId |= ((long) message.to_id.channel_id) << 32; + } + if (!replyMessages.contains(messageId)) { + replyMessages.add(messageId); + } + ArrayList messages = replyMessageOwners.get(message.reply_to_msg_id); + if (messages == null) { + messages = new ArrayList<>(); + replyMessageOwners.put(message.reply_to_msg_id, messages); + } + messages.add(message); + } else { + if (!replyMessages.contains(message.reply_to_random_id)) { + replyMessages.add(message.reply_to_random_id); + } + ArrayList messages = replyMessageRandomOwners.get(message.reply_to_random_id); + if (messages == null) { + messages = new ArrayList<>(); + replyMessageRandomOwners.put(message.reply_to_random_id, messages); + } + messages.add(message); } - messages.add(message); } } - } - if (lower_id == 0 && !cursor.isNull(5)) { - message.random_id = cursor.longValue(5); - } - if (MessageObject.isSecretMedia(message)) { - try { - SQLiteCursor cursor2 = database.queryFinalized(String.format(Locale.US, "SELECT date FROM enc_tasks_v2 WHERE mid = %d", message.id)); - if (cursor2.next()) { - message.destroyTime = cursor2.intValue(0); + if (lower_id == 0 && !cursor.isNull(5)) { + message.random_id = cursor.longValue(5); + } + if (MessageObject.isSecretMedia(message)) { + try { + SQLiteCursor cursor2 = database.queryFinalized(String.format(Locale.US, "SELECT date FROM enc_tasks_v2 WHERE mid = %d", message.id)); + if (cursor2.next()) { + message.destroyTime = cursor2.intValue(0); + } + cursor2.dispose(); + } catch (Exception e) { + FileLog.e(e); } - cursor2.dispose(); - } catch (Exception e) { - FileLog.e(e); } } } + cursor.dispose(); } - cursor.dispose(); - } - Collections.sort(res.messages, (lhs, rhs) -> { - if (lhs.id > 0 && rhs.id > 0) { - if (lhs.id > rhs.id) { - return -1; - } else if (lhs.id < rhs.id) { - return 1; - } - } else if (lhs.id < 0 && rhs.id < 0) { - if (lhs.id < rhs.id) { - return -1; - } else if (lhs.id > rhs.id) { - return 1; - } - } else { - if (lhs.date > rhs.date) { - return -1; - } else if (lhs.date < rhs.date) { - return 1; + Collections.sort(res.messages, (lhs, rhs) -> { + if (lhs.id > 0 && rhs.id > 0) { + if (lhs.id > rhs.id) { + return -1; + } else if (lhs.id < rhs.id) { + return 1; + } + } else if (lhs.id < 0 && rhs.id < 0) { + if (lhs.id < rhs.id) { + return -1; + } else if (lhs.id > rhs.id) { + return 1; + } + } else { + if (lhs.date > rhs.date) { + return -1; + } else if (lhs.date < rhs.date) { + return 1; + } } - } - return 0; - }); + return 0; + }); - if (lower_id != 0) { - if ((load_type == 3 || load_type == 4 || load_type == 2 && queryFromServer && !unreadCountIsLocal) && !res.messages.isEmpty()) { - if (!(minId <= max_id_query && maxId >= max_id_query)) { - replyMessages.clear(); - usersToLoad.clear(); - chatsToLoad.clear(); + if (lower_id != 0) { + if ((load_type == 3 || load_type == 4 || load_type == 2 && queryFromServer && !unreadCountIsLocal) && !res.messages.isEmpty()) { + if (!(minId <= max_id_query && maxId >= max_id_query)) { + replyMessages.clear(); + usersToLoad.clear(); + chatsToLoad.clear(); + res.messages.clear(); + } + } + if ((load_type == 4 || load_type == 3) && res.messages.size() == 1) { res.messages.clear(); } } - if ((load_type == 4 || load_type == 3) && res.messages.size() == 1) { - res.messages.clear(); + if (mentions_unread != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages WHERE uid = %d AND mention = 1 AND read_state IN(0, 1)", dialog_id)); + if (cursor.next()) { + if (mentions_unread != cursor.intValue(0)) { + mentions_unread *= -1; + } + } else { + mentions_unread *= -1; + } + cursor.dispose(); } } if (!replyMessages.isEmpty()) { @@ -4376,19 +4566,6 @@ public void getMessages(final long dialog_id, final int count, final int max_id, } } } - - if (mentions_unread != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages WHERE uid = %d AND mention = 1 AND read_state IN(0, 1)", dialog_id)); - if (cursor.next()) { - if (mentions_unread != cursor.intValue(0)) { - mentions_unread *= -1; - } - } else { - mentions_unread *= -1; - } - cursor.dispose(); - } - if (!usersToLoad.isEmpty()) { getUsersInternal(TextUtils.join(",", usersToLoad), res.users); } @@ -4401,7 +4578,7 @@ public void getMessages(final long dialog_id, final int count, final int max_id, res.users.clear(); FileLog.e(e); } finally { - getMessagesController().processLoadedMessages(res, dialog_id, count_query, max_id_override, offset_date, true, classGuid, min_unread_id, last_message_id, count_unread, max_unread_date, load_type, isChannel, isEnd, loadIndex, queryFromServer, mentions_unread); + getMessagesController().processLoadedMessages(res, dialog_id, count_query, max_id_override, offset_date, true, classGuid, min_unread_id, last_message_id, count_unread, max_unread_date, load_type, isChannel, isEnd, scheduled, loadIndex, queryFromServer, mentions_unread); } }); } @@ -5346,558 +5523,567 @@ private boolean isValidKeyboardToSave(TLRPC.Message message) { return message.reply_markup != null && !(message.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && (!message.reply_markup.selective || message.mentioned); } - private void putMessagesInternal(final ArrayList messages, final boolean withTransaction, final boolean doNotUpdateDialogDate, final int downloadMask, boolean ifNoLastMessage) { + private void putMessagesInternal(final ArrayList messages, final boolean withTransaction, final boolean doNotUpdateDialogDate, final int downloadMask, boolean ifNoLastMessage, boolean scheduled) { try { - if (ifNoLastMessage) { - TLRPC.Message lastMessage = messages.get(0); - if (lastMessage.dialog_id == 0) { - MessageObject.getDialogId(lastMessage); - } - int lastMid = -1; - SQLiteCursor cursor = database.queryFinalized("SELECT last_mid FROM dialogs WHERE did = " + lastMessage.dialog_id); - if (cursor.next()) { - lastMid = cursor.intValue(0); - } - cursor.dispose(); - if (lastMid != 0) { - return; + if (scheduled) { + if (withTransaction) { + database.beginTransaction(); } - } - if (withTransaction) { - database.beginTransaction(); - } - LongSparseArray messagesMap = new LongSparseArray<>(); - LongSparseArray messagesCounts = new LongSparseArray<>(); - LongSparseArray mentionCounts = new LongSparseArray<>(); - SparseArray> mediaCounts = null; - LongSparseArray botKeyboards = new LongSparseArray<>(); - - LongSparseArray messagesMediaIdsMap = null; - LongSparseArray mediaTypesChange = null; - StringBuilder messageMediaIds = null; - LongSparseArray mediaTypes = null; - StringBuilder messageIds = new StringBuilder(); - LongSparseArray dialogsReadMax = new LongSparseArray<>(); - LongSparseArray messagesIdsMap = new LongSparseArray<>(); - LongSparseArray mentionsIdsMap = new LongSparseArray<>(); - - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)"); - SQLitePreparedStatement state_media = null; - SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms VALUES(?, ?)"); - SQLitePreparedStatement state_download = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?, ?)"); - SQLitePreparedStatement state_webpage = database.executeFast("REPLACE INTO webpage_pending VALUES(?, ?)"); - SQLitePreparedStatement state_polls = null; - - for (int a = 0; a < messages.size(); a++) { - TLRPC.Message message = messages.get(a); - long messageId = message.id; - if (message.dialog_id == 0) { - MessageObject.getDialogId(message); - } - if (message.to_id.channel_id != 0) { - messageId |= ((long) message.to_id.channel_id) << 32; - } - if (message.mentioned && message.media_unread) { - mentionsIdsMap.put(messageId, message.dialog_id); - } + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages VALUES(?, ?, ?, ?, ?, ?, NULL)"); + SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms VALUES(?, ?)"); + ArrayList dialogsToUpdate = new ArrayList<>(); - if (!(message.action instanceof TLRPC.TL_messageActionHistoryClear) && !MessageObject.isOut(message) && (message.id > 0 || MessageObject.isUnread(message))) {Integer currentMaxId = dialogsReadMax.get(message.dialog_id); - if (currentMaxId == null) { - SQLiteCursor cursor = database.queryFinalized("SELECT inbox_max FROM dialogs WHERE did = " + message.dialog_id); - if (cursor.next()) { - currentMaxId = cursor.intValue(0); - } else { - currentMaxId = 0; - } - cursor.dispose(); - dialogsReadMax.put(message.dialog_id, currentMaxId); + for (int a = 0; a < messages.size(); a++) { + TLRPC.Message message = messages.get(a); + fixUnsupportedMedia(message); + + state_messages.requery(); + long messageId = message.id; + if (message.local_id != 0) { + messageId = message.local_id; } - if (message.id < 0 || currentMaxId < message.id) { - if (messageIds.length() > 0) { - messageIds.append(","); - } - messageIds.append(messageId); - messagesIdsMap.put(messageId, message.dialog_id); + if (message.to_id.channel_id != 0) { + messageId |= ((long) message.to_id.channel_id) << 32; } - } - if (MediaDataController.canAddMessageToMedia(message)) { - if (messageMediaIds == null) { - messageMediaIds = new StringBuilder(); - messagesMediaIdsMap = new LongSparseArray<>(); - mediaTypes = new LongSparseArray<>(); + + NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); + + long did = MessageObject.getDialogId(message); + state_messages.bindLong(1, messageId); + state_messages.bindLong(2, did); + state_messages.bindInteger(3, message.send_state); + state_messages.bindInteger(4, message.date); + state_messages.bindByteBuffer(5, data); + state_messages.bindInteger(6, message.ttl); + state_messages.step(); + + if (message.random_id != 0) { + state_randoms.requery(); + state_randoms.bindLong(1, message.random_id); + state_randoms.bindLong(2, messageId); + state_randoms.step(); } - if (messageMediaIds.length() > 0) { - messageMediaIds.append(","); + + data.reuse(); + + if (!dialogsToUpdate.contains(did)) { + dialogsToUpdate.add(did); } - messageMediaIds.append(messageId); - messagesMediaIdsMap.put(messageId, message.dialog_id); - mediaTypes.put(messageId, MediaDataController.getMediaType(message)); } - if (isValidKeyboardToSave(message)) { - TLRPC.Message oldMessage = botKeyboards.get(message.dialog_id); - if (oldMessage == null || oldMessage.id < message.id) { - botKeyboards.put(message.dialog_id, message); + state_messages.dispose(); + state_randoms.dispose(); + + if (withTransaction) { + database.commitTransaction(); + } + for (int a = 0, N = dialogsToUpdate.size(); a < N; a++) { + broadcastScheduledMessagesChange(dialogsToUpdate.get(a)); + } + } else { + if (ifNoLastMessage) { + TLRPC.Message lastMessage = messages.get(0); + if (lastMessage.dialog_id == 0) { + MessageObject.getDialogId(lastMessage); + } + int lastMid = -1; + SQLiteCursor cursor = database.queryFinalized("SELECT last_mid FROM dialogs WHERE did = " + lastMessage.dialog_id); + if (cursor.next()) { + lastMid = cursor.intValue(0); + } + cursor.dispose(); + if (lastMid != 0) { + return; } } - } + if (withTransaction) { + database.beginTransaction(); + } + LongSparseArray messagesMap = new LongSparseArray<>(); + LongSparseArray messagesCounts = new LongSparseArray<>(); + LongSparseArray mentionCounts = new LongSparseArray<>(); + SparseArray> mediaCounts = null; + LongSparseArray botKeyboards = new LongSparseArray<>(); - for (int a = 0; a < botKeyboards.size(); a++) { - getMediaDataController().putBotKeyboard(botKeyboards.keyAt(a), botKeyboards.valueAt(a)); - } + LongSparseArray messagesMediaIdsMap = null; + LongSparseArray mediaTypesChange = null; + StringBuilder messageMediaIds = null; + LongSparseArray mediaTypes = null; + StringBuilder messageIds = new StringBuilder(); + LongSparseArray dialogsReadMax = new LongSparseArray<>(); + LongSparseArray messagesIdsMap = new LongSparseArray<>(); + LongSparseArray mentionsIdsMap = new LongSparseArray<>(); - if (messageMediaIds != null) { - SQLiteCursor cursor = database.queryFinalized("SELECT mid, type FROM media_v2 WHERE mid IN(" + messageMediaIds.toString() + ")"); - while (cursor.next()) { - long mid = cursor.longValue(0); - int type = cursor.intValue(1); - if (type == mediaTypes.get(mid)) { - messagesMediaIdsMap.remove(mid); - } else { - if (mediaTypesChange == null) { - mediaTypesChange = new LongSparseArray<>(); - } - mediaTypesChange.put(mid, type); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)"); + SQLitePreparedStatement state_media = null; + SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms VALUES(?, ?)"); + SQLitePreparedStatement state_download = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_webpage = database.executeFast("REPLACE INTO webpage_pending VALUES(?, ?)"); + SQLitePreparedStatement state_polls = null; + + for (int a = 0; a < messages.size(); a++) { + TLRPC.Message message = messages.get(a); + + long messageId = message.id; + if (message.dialog_id == 0) { + MessageObject.getDialogId(message); } - } - cursor.dispose(); - mediaCounts = new SparseArray<>(); - for (int a = 0; a < messagesMediaIdsMap.size(); a++) { - long key = messagesMediaIdsMap.keyAt(a); - long value = messagesMediaIdsMap.valueAt(a); - Integer type = mediaTypes.get(key); - LongSparseArray counts = mediaCounts.get(type); - Integer count; - if (counts == null) { - counts = new LongSparseArray<>(); - count = 0; - mediaCounts.put(type, counts); - } else { - count = counts.get(value); - } - if (count == null) { - count = 0; - } - count++; - counts.put(value, count); - if (mediaTypesChange != null) { - int previousType = mediaTypesChange.get(key, -1); - if (previousType >= 0) { - counts = mediaCounts.get(previousType); - if (counts == null) { - counts = new LongSparseArray<>(); - count = 0; - mediaCounts.put(previousType, counts); + if (message.to_id.channel_id != 0) { + messageId |= ((long) message.to_id.channel_id) << 32; + } + if (message.mentioned && message.media_unread) { + mentionsIdsMap.put(messageId, message.dialog_id); + } + + if (!(message.action instanceof TLRPC.TL_messageActionHistoryClear) && (!MessageObject.isOut(message) || message.from_scheduled) && (message.id > 0 || MessageObject.isUnread(message))) { + Integer currentMaxId = dialogsReadMax.get(message.dialog_id); + if (currentMaxId == null) { + SQLiteCursor cursor = database.queryFinalized("SELECT inbox_max FROM dialogs WHERE did = " + message.dialog_id); + if (cursor.next()) { + currentMaxId = cursor.intValue(0); } else { - count = counts.get(value); + currentMaxId = 0; } - if (count == null) { - count = 0; + cursor.dispose(); + dialogsReadMax.put(message.dialog_id, currentMaxId); + } + if (message.id < 0 || currentMaxId < message.id) { + if (messageIds.length() > 0) { + messageIds.append(","); } - count--; - counts.put(value, count); + messageIds.append(messageId); + messagesIdsMap.put(messageId, message.dialog_id); + } + } + if (MediaDataController.canAddMessageToMedia(message)) { + if (messageMediaIds == null) { + messageMediaIds = new StringBuilder(); + messagesMediaIdsMap = new LongSparseArray<>(); + mediaTypes = new LongSparseArray<>(); + } + if (messageMediaIds.length() > 0) { + messageMediaIds.append(","); + } + messageMediaIds.append(messageId); + messagesMediaIdsMap.put(messageId, message.dialog_id); + mediaTypes.put(messageId, MediaDataController.getMediaType(message)); + } + if (isValidKeyboardToSave(message)) { + TLRPC.Message oldMessage = botKeyboards.get(message.dialog_id); + if (oldMessage == null || oldMessage.id < message.id) { + botKeyboards.put(message.dialog_id, message); } } } - } - if (messageIds.length() > 0) { - SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM messages WHERE mid IN(" + messageIds.toString() + ")"); - while (cursor.next()) { - long mid = cursor.longValue(0); - messagesIdsMap.remove(mid); - mentionsIdsMap.remove(mid); + for (int a = 0; a < botKeyboards.size(); a++) { + getMediaDataController().putBotKeyboard(botKeyboards.keyAt(a), botKeyboards.valueAt(a)); } - cursor.dispose(); - for (int a = 0; a < messagesIdsMap.size(); a++) { - long dialog_id = messagesIdsMap.valueAt(a); - Integer count = messagesCounts.get(dialog_id); - if (count == null) { - count = 0; + + if (messageMediaIds != null) { + SQLiteCursor cursor = database.queryFinalized("SELECT mid, type FROM media_v2 WHERE mid IN(" + messageMediaIds.toString() + ")"); + while (cursor.next()) { + long mid = cursor.longValue(0); + int type = cursor.intValue(1); + if (type == mediaTypes.get(mid)) { + messagesMediaIdsMap.remove(mid); + } else { + if (mediaTypesChange == null) { + mediaTypesChange = new LongSparseArray<>(); + } + mediaTypesChange.put(mid, type); + } + } + cursor.dispose(); + mediaCounts = new SparseArray<>(); + for (int a = 0; a < messagesMediaIdsMap.size(); a++) { + long key = messagesMediaIdsMap.keyAt(a); + long value = messagesMediaIdsMap.valueAt(a); + Integer type = mediaTypes.get(key); + LongSparseArray counts = mediaCounts.get(type); + Integer count; + if (counts == null) { + counts = new LongSparseArray<>(); + count = 0; + mediaCounts.put(type, counts); + } else { + count = counts.get(value); + } + if (count == null) { + count = 0; + } + count++; + counts.put(value, count); + if (mediaTypesChange != null) { + int previousType = mediaTypesChange.get(key, -1); + if (previousType >= 0) { + counts = mediaCounts.get(previousType); + if (counts == null) { + counts = new LongSparseArray<>(); + count = 0; + mediaCounts.put(previousType, counts); + } else { + count = counts.get(value); + } + if (count == null) { + count = 0; + } + count--; + counts.put(value, count); + } + } } - count++; - messagesCounts.put(dialog_id, count); } - for (int a = 0; a < mentionsIdsMap.size(); a++) { - long dialog_id = mentionsIdsMap.valueAt(a); - Integer count = mentionCounts.get(dialog_id); - if (count == null) { - count = 0; + + if (messageIds.length() > 0) { + SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM messages WHERE mid IN(" + messageIds.toString() + ")"); + while (cursor.next()) { + long mid = cursor.longValue(0); + messagesIdsMap.remove(mid); + mentionsIdsMap.remove(mid); + } + cursor.dispose(); + for (int a = 0; a < messagesIdsMap.size(); a++) { + long dialog_id = messagesIdsMap.valueAt(a); + Integer count = messagesCounts.get(dialog_id); + if (count == null) { + count = 0; + } + count++; + messagesCounts.put(dialog_id, count); + } + for (int a = 0; a < mentionsIdsMap.size(); a++) { + long dialog_id = mentionsIdsMap.valueAt(a); + Integer count = mentionCounts.get(dialog_id); + if (count == null) { + count = 0; + } + count++; + mentionCounts.put(dialog_id, count); } - count++; - mentionCounts.put(dialog_id, count); } - } - int downloadMediaMask = 0; - for (int a = 0; a < messages.size(); a++) { - TLRPC.Message message = messages.get(a); - fixUnsupportedMedia(message); + int downloadMediaMask = 0; + for (int a = 0; a < messages.size(); a++) { + TLRPC.Message message = messages.get(a); + fixUnsupportedMedia(message); - state_messages.requery(); - long messageId = message.id; - if (message.local_id != 0) { - messageId = message.local_id; - } - if (message.to_id.channel_id != 0) { - messageId |= ((long) message.to_id.channel_id) << 32; - } + state_messages.requery(); + long messageId = message.id; + if (message.local_id != 0) { + messageId = message.local_id; + } + if (message.to_id.channel_id != 0) { + messageId |= ((long) message.to_id.channel_id) << 32; + } - NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); - message.serializeToStream(data); + NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); - boolean updateDialog = true; - if (message.action instanceof TLRPC.TL_messageEncryptedAction && !(message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages)) { - updateDialog = false; - } + boolean updateDialog = true; + if (message.action instanceof TLRPC.TL_messageEncryptedAction && !(message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages)) { + updateDialog = false; + } - if (updateDialog) { - TLRPC.Message lastMessage = messagesMap.get(message.dialog_id); - if (lastMessage == null || message.date > lastMessage.date || lastMessage.id > 0 && message.id > lastMessage.id || lastMessage.id < 0 && message.id < lastMessage.id) { - messagesMap.put(message.dialog_id, message); + if (updateDialog) { + TLRPC.Message lastMessage = messagesMap.get(message.dialog_id); + if (lastMessage == null || message.date > lastMessage.date || lastMessage.id > 0 && message.id > lastMessage.id || lastMessage.id < 0 && message.id < lastMessage.id) { + messagesMap.put(message.dialog_id, message); + } } - } - state_messages.bindLong(1, messageId); - state_messages.bindLong(2, message.dialog_id); - state_messages.bindInteger(3, MessageObject.getUnreadFlags(message)); - state_messages.bindInteger(4, message.send_state); - state_messages.bindInteger(5, message.date); - state_messages.bindByteBuffer(6, data); - state_messages.bindInteger(7, (MessageObject.isOut(message) ? 1 : 0)); - state_messages.bindInteger(8, message.ttl); - if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - state_messages.bindInteger(9, message.views); - } else { - state_messages.bindInteger(9, getMessageMediaType(message)); - } - state_messages.bindInteger(10, 0); - state_messages.bindInteger(11, message.mentioned ? 1 : 0); - state_messages.step(); + state_messages.bindLong(1, messageId); + state_messages.bindLong(2, message.dialog_id); + state_messages.bindInteger(3, MessageObject.getUnreadFlags(message)); + state_messages.bindInteger(4, message.send_state); + state_messages.bindInteger(5, message.date); + state_messages.bindByteBuffer(6, data); + state_messages.bindInteger(7, (MessageObject.isOut(message) || message.from_scheduled ? 1 : 0)); + state_messages.bindInteger(8, message.ttl); + if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + state_messages.bindInteger(9, message.views); + } else { + state_messages.bindInteger(9, getMessageMediaType(message)); + } + state_messages.bindInteger(10, 0); + state_messages.bindInteger(11, message.mentioned ? 1 : 0); + state_messages.step(); - if (message.random_id != 0) { - state_randoms.requery(); - state_randoms.bindLong(1, message.random_id); - state_randoms.bindLong(2, messageId); - state_randoms.step(); - } + if (message.random_id != 0) { + state_randoms.requery(); + state_randoms.bindLong(1, message.random_id); + state_randoms.bindLong(2, messageId); + state_randoms.step(); + } - if (MediaDataController.canAddMessageToMedia(message)) { - if (state_media == null) { - state_media = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); - } - state_media.requery(); - state_media.bindLong(1, messageId); - state_media.bindLong(2, message.dialog_id); - state_media.bindInteger(3, message.date); - state_media.bindInteger(4, MediaDataController.getMediaType(message)); - state_media.bindByteBuffer(5, data); - state_media.step(); - } - - if (message.media instanceof TLRPC.TL_messageMediaPoll) { - if (state_polls == null) { - state_polls = database.executeFast("REPLACE INTO polls VALUES(?, ?)"); - } - TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.media; - state_polls.requery(); - state_polls.bindLong(1, messageId); - state_polls.bindLong(2, mediaPoll.poll.id); - state_polls.step(); - } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { - state_webpage.requery(); - state_webpage.bindLong(1, message.media.webpage.id); - state_webpage.bindLong(2, messageId); - state_webpage.step(); - } + if (MediaDataController.canAddMessageToMedia(message)) { + if (state_media == null) { + state_media = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); + } + state_media.requery(); + state_media.bindLong(1, messageId); + state_media.bindLong(2, message.dialog_id); + state_media.bindInteger(3, message.date); + state_media.bindInteger(4, MediaDataController.getMediaType(message)); + state_media.bindByteBuffer(5, data); + state_media.step(); + } - data.reuse(); + if (message.media instanceof TLRPC.TL_messageMediaPoll) { + if (state_polls == null) { + state_polls = database.executeFast("REPLACE INTO polls VALUES(?, ?)"); + } + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.media; + state_polls.requery(); + state_polls.bindLong(1, messageId); + state_polls.bindLong(2, mediaPoll.poll.id); + state_polls.step(); + } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + state_webpage.requery(); + state_webpage.bindLong(1, message.media.webpage.id); + state_webpage.bindLong(2, messageId); + state_webpage.step(); + } + + data.reuse(); - if (downloadMask != 0 && (message.to_id.channel_id == 0 || message.post) && message.date >= getConnectionsManager().getCurrentTime() - 60 * 60 && getDownloadController().canDownloadMedia(message) == 1) { - if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaWebPage) { - int type = 0; - long id = 0; - TLRPC.MessageMedia object = null; - TLRPC.Document document = MessageObject.getDocument(message); - TLRPC.Photo photo = MessageObject.getPhoto(message); - if (MessageObject.isVoiceMessage(message)) { - id = document.id; - type = DownloadController.AUTODOWNLOAD_TYPE_AUDIO; - object = new TLRPC.TL_messageMediaDocument(); - object.document = document; - object.flags |= 1; - } else if (MessageObject.isStickerMessage(message) || MessageObject.isAnimatedStickerMessage(message)) { - id = document.id; - type = DownloadController.AUTODOWNLOAD_TYPE_PHOTO; - object = new TLRPC.TL_messageMediaDocument(); - object.document = document; - object.flags |= 1; - } else if (MessageObject.isVideoMessage(message) || MessageObject.isRoundVideoMessage(message) || MessageObject.isGifMessage(message)) { - id = document.id; - type = DownloadController.AUTODOWNLOAD_TYPE_VIDEO; - object = new TLRPC.TL_messageMediaDocument(); - object.document = document; - object.flags |= 1; - } else if (document != null) { - id = document.id; - type = DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT; - object = new TLRPC.TL_messageMediaDocument(); - object.document = document; - object.flags |= 1; - } else if (photo != null) { - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); - if (photoSize != null) { - id = photo.id; + if (downloadMask != 0 && (message.to_id.channel_id == 0 || message.post) && message.date >= getConnectionsManager().getCurrentTime() - 60 * 60 && getDownloadController().canDownloadMedia(message) == 1) { + if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaWebPage) { + int type = 0; + long id = 0; + TLRPC.MessageMedia object = null; + TLRPC.Document document = MessageObject.getDocument(message); + TLRPC.Photo photo = MessageObject.getPhoto(message); + if (MessageObject.isVoiceMessage(message)) { + id = document.id; + type = DownloadController.AUTODOWNLOAD_TYPE_AUDIO; + object = new TLRPC.TL_messageMediaDocument(); + object.document = document; + object.flags |= 1; + } else if (MessageObject.isStickerMessage(message) || MessageObject.isAnimatedStickerMessage(message)) { + id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_PHOTO; - object = new TLRPC.TL_messageMediaPhoto(); - object.photo = photo; + object = new TLRPC.TL_messageMediaDocument(); + object.document = document; + object.flags |= 1; + } else if (MessageObject.isVideoMessage(message) || MessageObject.isRoundVideoMessage(message) || MessageObject.isGifMessage(message)) { + id = document.id; + type = DownloadController.AUTODOWNLOAD_TYPE_VIDEO; + object = new TLRPC.TL_messageMediaDocument(); + object.document = document; + object.flags |= 1; + } else if (document != null) { + id = document.id; + type = DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT; + object = new TLRPC.TL_messageMediaDocument(); + object.document = document; object.flags |= 1; - if (message.media instanceof TLRPC.TL_messageMediaWebPage) { - object.flags |= 0x80000000; + } else if (photo != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); + if (photoSize != null) { + id = photo.id; + type = DownloadController.AUTODOWNLOAD_TYPE_PHOTO; + object = new TLRPC.TL_messageMediaPhoto(); + object.photo = photo; + object.flags |= 1; + if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + object.flags |= 0x80000000; + } } } - } - if (object != null) { - if (message.media.ttl_seconds != 0) { - object.ttl_seconds = message.media.ttl_seconds; - object.flags |= 4; + if (object != null) { + if (message.media.ttl_seconds != 0) { + object.ttl_seconds = message.media.ttl_seconds; + object.flags |= 4; + } + downloadMediaMask |= type; + state_download.requery(); + data = new NativeByteBuffer(object.getObjectSize()); + object.serializeToStream(data); + state_download.bindLong(1, id); + state_download.bindInteger(2, type); + state_download.bindInteger(3, message.date); + state_download.bindByteBuffer(4, data); + state_download.bindString(5, "sent_" + (message.to_id != null ? message.to_id.channel_id : 0) + "_" + message.id); + state_download.step(); + data.reuse(); } - downloadMediaMask |= type; - state_download.requery(); - data = new NativeByteBuffer(object.getObjectSize()); - object.serializeToStream(data); - state_download.bindLong(1, id); - state_download.bindInteger(2, type); - state_download.bindInteger(3, message.date); - state_download.bindByteBuffer(4, data); - state_download.bindString(5, "sent_" + (message.to_id != null ? message.to_id.channel_id : 0) + "_" + message.id); - state_download.step(); - data.reuse(); } } } - } - state_messages.dispose(); - if (state_media != null) { - state_media.dispose(); - } - if (state_polls != null) { - state_polls.dispose(); - } - state_randoms.dispose(); - state_download.dispose(); - state_webpage.dispose(); + state_messages.dispose(); + if (state_media != null) { + state_media.dispose(); + } + if (state_polls != null) { + state_polls.dispose(); + } + state_randoms.dispose(); + state_download.dispose(); + state_webpage.dispose(); - SQLitePreparedStatement state_dialogs_replace = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - SQLitePreparedStatement state_dialogs_update = database.executeFast("UPDATE dialogs SET date = ?, unread_count = ?, last_mid = ?, unread_count_i = ? WHERE did = ?"); + SQLitePreparedStatement state_dialogs_replace = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_dialogs_update = database.executeFast("UPDATE dialogs SET date = ?, unread_count = ?, last_mid = ?, unread_count_i = ? WHERE did = ?"); - for (int a = 0; a < messagesMap.size(); a++) { - long key = messagesMap.keyAt(a); - if (key == 0) { - continue; - } - TLRPC.Message message = messagesMap.valueAt(a); + for (int a = 0; a < messagesMap.size(); a++) { + long key = messagesMap.keyAt(a); + if (key == 0) { + continue; + } + TLRPC.Message message = messagesMap.valueAt(a); - int channelId = 0; - if (message != null) { - channelId = message.to_id.channel_id; - } + int channelId = 0; + if (message != null) { + channelId = message.to_id.channel_id; + } - SQLiteCursor cursor = database.queryFinalized("SELECT date, unread_count, last_mid, unread_count_i FROM dialogs WHERE did = " + key); - int dialog_date = 0; - int last_mid = 0; - int old_unread_count = 0; - int old_mentions_count = 0; - boolean exists; - if (exists = cursor.next()) { - dialog_date = cursor.intValue(0); - old_unread_count = Math.max(0, cursor.intValue(1)); - last_mid = cursor.intValue(2); - old_mentions_count = Math.max(0, cursor.intValue(3)); - } else if (channelId != 0) { - getMessagesController().checkChannelInviter(channelId); - } - cursor.dispose(); + SQLiteCursor cursor = database.queryFinalized("SELECT date, unread_count, last_mid, unread_count_i FROM dialogs WHERE did = " + key); + int dialog_date = 0; + int last_mid = 0; + int old_unread_count = 0; + int old_mentions_count = 0; + boolean exists; + if (exists = cursor.next()) { + dialog_date = cursor.intValue(0); + old_unread_count = Math.max(0, cursor.intValue(1)); + last_mid = cursor.intValue(2); + old_mentions_count = Math.max(0, cursor.intValue(3)); + } else if (channelId != 0) { + getMessagesController().checkChannelInviter(channelId); + } + cursor.dispose(); - Integer mentions_count = mentionCounts.get(key); - Integer unread_count = messagesCounts.get(key); - if (unread_count == null) { - unread_count = 0; - } else { - messagesCounts.put(key, unread_count + old_unread_count); - } - if (mentions_count == null) { - mentions_count = 0; - } else { - mentionCounts.put(key, mentions_count + old_mentions_count); - } - long messageId = message != null ? message.id : last_mid; - if (message != null) { - if (message.local_id != 0) { - messageId = message.local_id; + Integer mentions_count = mentionCounts.get(key); + Integer unread_count = messagesCounts.get(key); + if (unread_count == null) { + unread_count = 0; + } else { + messagesCounts.put(key, unread_count + old_unread_count); + } + if (mentions_count == null) { + mentions_count = 0; + } else { + mentionCounts.put(key, mentions_count + old_mentions_count); + } + long messageId = message != null ? message.id : last_mid; + if (message != null) { + if (message.local_id != 0) { + messageId = message.local_id; + } + } + + if (channelId != 0) { + messageId |= ((long) channelId) << 32; + } + + if (exists) { + state_dialogs_update.requery(); + state_dialogs_update.bindInteger(1, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); + state_dialogs_update.bindInteger(2, old_unread_count + unread_count); + state_dialogs_update.bindLong(3, messageId); + state_dialogs_update.bindInteger(4, old_mentions_count + mentions_count); + state_dialogs_update.bindLong(5, key); + state_dialogs_update.step(); + } else { + state_dialogs_replace.requery(); + state_dialogs_replace.bindLong(1, key); + state_dialogs_replace.bindInteger(2, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); + state_dialogs_replace.bindInteger(3, old_unread_count + unread_count); + state_dialogs_replace.bindLong(4, messageId); + state_dialogs_replace.bindInteger(5, 0); + state_dialogs_replace.bindInteger(6, 0); + state_dialogs_replace.bindLong(7, 0); + state_dialogs_replace.bindInteger(8, old_mentions_count + mentions_count); + state_dialogs_replace.bindInteger(9, channelId != 0 ? 1 : 0); + state_dialogs_replace.bindInteger(10, 0); + state_dialogs_replace.bindInteger(11, 0); + state_dialogs_replace.bindInteger(12, 0); + state_dialogs_replace.bindInteger(13, 0); + state_dialogs_replace.bindNull(14); + state_dialogs_replace.step(); + } + } + state_dialogs_update.dispose(); + state_dialogs_replace.dispose(); + + if (mediaCounts != null) { + state_randoms = database.executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)"); + for (int a = 0; a < mediaCounts.size(); a++) { + int type = mediaCounts.keyAt(a); + LongSparseArray value = mediaCounts.valueAt(a); + for (int b = 0; b < value.size(); b++) { + long uid = value.keyAt(b); + int lower_part = (int) uid; + int count = -1; + int old = 0; + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type)); + if (cursor.next()) { + count = cursor.intValue(0); + old = cursor.intValue(1); + } + cursor.dispose(); + if (count != -1) { + state_randoms.requery(); + count += value.valueAt(b); + state_randoms.bindLong(1, uid); + state_randoms.bindInteger(2, type); + state_randoms.bindInteger(3, Math.max(0, count)); + state_randoms.bindInteger(4, old); + state_randoms.step(); + } + } } + state_randoms.dispose(); } - - if (channelId != 0) { - messageId |= ((long) channelId) << 32; + if (withTransaction) { + database.commitTransaction(); } + getMessagesController().processDialogsUpdateRead(messagesCounts, mentionCounts); - if (exists) { - state_dialogs_update.requery(); - state_dialogs_update.bindInteger(1, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); - state_dialogs_update.bindInteger(2, old_unread_count + unread_count); - state_dialogs_update.bindLong(3, messageId); - state_dialogs_update.bindInteger(4, old_mentions_count + mentions_count); - state_dialogs_update.bindLong(5, key); - state_dialogs_update.step(); - } else { - state_dialogs_replace.requery(); - state_dialogs_replace.bindLong(1, key); - state_dialogs_replace.bindInteger(2, message != null && (!doNotUpdateDialogDate || dialog_date == 0) ? message.date : dialog_date); - state_dialogs_replace.bindInteger(3, old_unread_count + unread_count); - state_dialogs_replace.bindLong(4, messageId); - state_dialogs_replace.bindInteger(5, 0); - state_dialogs_replace.bindInteger(6, 0); - state_dialogs_replace.bindLong(7, 0); - state_dialogs_replace.bindInteger(8, old_mentions_count + mentions_count); - state_dialogs_replace.bindInteger(9, channelId != 0 ? 1 : 0); - state_dialogs_replace.bindInteger(10, 0); - state_dialogs_replace.bindInteger(11, 0); - state_dialogs_replace.bindInteger(12, 0); - state_dialogs_replace.bindInteger(13, 0); - state_dialogs_replace.bindNull(14); - state_dialogs_replace.step(); - } - } - state_dialogs_update.dispose(); - state_dialogs_replace.dispose(); - - if (mediaCounts != null) { - state_randoms = database.executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)"); - for (int a = 0; a < mediaCounts.size(); a++) { - int type = mediaCounts.keyAt(a); - LongSparseArray value = mediaCounts.valueAt(a); - for (int b = 0; b < value.size(); b++) { - long uid = value.keyAt(b); - int lower_part = (int) uid; - int count = -1; - int old = 0; - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type)); - if (cursor.next()) { - count = cursor.intValue(0); - old = cursor.intValue(1); - } - cursor.dispose(); - if (count != -1) { - state_randoms.requery(); - count += value.valueAt(b); - state_randoms.bindLong(1, uid); - state_randoms.bindInteger(2, type); - state_randoms.bindInteger(3, Math.max(0, count)); - state_randoms.bindInteger(4, old); - state_randoms.step(); - } - } + if (downloadMediaMask != 0) { + final int downloadMediaMaskFinal = downloadMediaMask; + AndroidUtilities.runOnUIThread(() -> getDownloadController().newDownloadObjectsAvailable(downloadMediaMaskFinal)); } - state_randoms.dispose(); - } - if (withTransaction) { - database.commitTransaction(); - } - getMessagesController().processDialogsUpdateRead(messagesCounts, mentionCounts); - - if (downloadMediaMask != 0) { - final int downloadMediaMaskFinal = downloadMediaMask; - AndroidUtilities.runOnUIThread(() -> getDownloadController().newDownloadObjectsAvailable(downloadMediaMaskFinal)); } } catch (Exception e) { FileLog.e(e); } } - public void putMessages(final ArrayList messages, final boolean withTransaction, boolean useQueue, final boolean doNotUpdateDialogDate, final int downloadMask) { - putMessages(messages, withTransaction, useQueue, doNotUpdateDialogDate, downloadMask, false); + public void putMessages(final ArrayList messages, final boolean withTransaction, boolean useQueue, final boolean doNotUpdateDialogDate, final int downloadMask, boolean scheduled) { + putMessages(messages, withTransaction, useQueue, doNotUpdateDialogDate, downloadMask, false, scheduled); } - public void putMessages(final ArrayList messages, final boolean withTransaction, boolean useQueue, final boolean doNotUpdateDialogDate, final int downloadMask, final boolean ifNoLastMessage) { + public void putMessages(final ArrayList messages, final boolean withTransaction, boolean useQueue, final boolean doNotUpdateDialogDate, final int downloadMask, final boolean ifNoLastMessage, boolean scheduled) { if (messages.size() == 0) { return; } if (useQueue) { - storageQueue.postRunnable(() -> putMessagesInternal(messages, withTransaction, doNotUpdateDialogDate, downloadMask, ifNoLastMessage)); + storageQueue.postRunnable(() -> putMessagesInternal(messages, withTransaction, doNotUpdateDialogDate, downloadMask, ifNoLastMessage, scheduled)); } else { - putMessagesInternal(messages, withTransaction, doNotUpdateDialogDate, downloadMask, ifNoLastMessage); + putMessagesInternal(messages, withTransaction, doNotUpdateDialogDate, downloadMask, ifNoLastMessage, scheduled); } } - public void markMessageAsSendError(final TLRPC.Message message) { + public void markMessageAsSendError(final TLRPC.Message message, boolean scheduled) { storageQueue.postRunnable(() -> { try { long messageId = message.id; if (message.to_id.channel_id != 0) { messageId |= ((long) message.to_id.channel_id) << 32; } - database.executeFast("UPDATE messages SET send_state = 2 WHERE mid = " + messageId).stepThis().dispose(); + if (scheduled) { + database.executeFast("UPDATE scheduled_messages SET send_state = 2 WHERE mid = " + messageId).stepThis().dispose(); + } else { + database.executeFast("UPDATE messages SET send_state = 2 WHERE mid = " + messageId).stepThis().dispose(); + } } catch (Exception e) { FileLog.e(e); } }); } - /*public void getHoleMessages() { - storageQueue.postRunnable(new Runnable() { - @Override - public void run() { - try { - - } catch (Exception e) { - FileLog.e(e); - } - } - }); - } - - public void clearHoleMessages(final int enc_id) { - storageQueue.postRunnable(new Runnable() { - @Override - public void run() { - try { - database.executeFast("DELETE FROM secret_holes WHERE uid = " + enc_id).stepThis().dispose(); - } catch (Exception e) { - FileLog.e(e); - } - } - }); - } - - public void putHoleMessage(final int enc_id, final TLRPC.Message message) { - if (message == null) { - return; - } - storageQueue.postRunnable(new Runnable() { - @Override - public void run() { - try { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO secret_holes VALUES(?, ?, ?, ?)"); - - state.requery(); - NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); - message.serializeToStream(data); - state.bindInteger(1, enc_id); - state.bindInteger(2, message.seq_in); - state.bindInteger(3, message.seq_out); - state.bindByteBuffer(4, data); - state.step(); - data.reuse(); - - state.dispose(); - } catch (Exception e) { - FileLog.e(e); - } - } - }); - }*/ - public void setMessageSeq(final int mid, final int seq_in, final int seq_out) { storageQueue.postRunnable(() -> { try { @@ -5914,7 +6100,7 @@ public void setMessageSeq(final int mid, final int seq_in, final int seq_out) { }); } - private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, int newId, int date, int channelId) { + private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, int newId, int date, int channelId, int scheduled) { SQLiteCursor cursor = null; long oldMessageId; long newMessageId = newId; @@ -5943,16 +6129,35 @@ private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, i } long did = 0; - try { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid FROM messages WHERE mid = %d LIMIT 1", oldMessageId)); - if (cursor.next()) { - did = cursor.longValue(0); + if (scheduled == -1 || scheduled == 0) { + try { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid FROM messages WHERE mid = %d LIMIT 1", oldMessageId)); + if (cursor.next()) { + did = cursor.longValue(0); + scheduled = 0; + } + } catch (Exception e) { + FileLog.e(e); + } finally { + if (cursor != null) { + cursor.dispose(); + } } - } catch (Exception e) { - FileLog.e(e); - } finally { - if (cursor != null) { - cursor.dispose(); + } + + if (scheduled == -1 || scheduled == 1) { + try { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid FROM scheduled_messages WHERE mid = %d LIMIT 1", oldMessageId)); + if (cursor.next()) { + did = cursor.longValue(0); + scheduled = 1; + } + } catch (Exception e) { + FileLog.e(e); + } finally { + if (cursor != null) { + cursor.dispose(); + } } } @@ -5962,7 +6167,11 @@ private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, i if (oldMessageId == newMessageId && date != 0) { SQLitePreparedStatement state = null; try { - state = database.executeFast("UPDATE messages SET send_state = 0, date = ? WHERE mid = ?"); + if (scheduled == 0) { + state = database.executeFast("UPDATE messages SET send_state = 0, date = ? WHERE mid = ?"); + } else { + state = database.executeFast("UPDATE scheduled_messages SET send_state = 0, date = ? WHERE mid = ?"); + } state.bindInteger(1, date); state.bindLong(2, newMessageId); state.step(); @@ -5977,53 +6186,73 @@ private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, i return new long[]{did, newId}; } else { SQLitePreparedStatement state = null; - try { - state = database.executeFast("UPDATE messages SET mid = ?, send_state = 0 WHERE mid = ?"); - state.bindLong(1, newMessageId); - state.bindLong(2, oldMessageId); - state.step(); - } catch (Exception e) { + + if (scheduled == 0) { try { - database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid = %d", oldMessageId)).stepThis().dispose(); - database.executeFast(String.format(Locale.US, "DELETE FROM messages_seq WHERE mid = %d", oldMessageId)).stepThis().dispose(); - } catch (Exception e2) { - FileLog.e(e2); - } - } finally { - if (state != null) { - state.dispose(); - state = null; + state = database.executeFast("UPDATE messages SET mid = ?, send_state = 0 WHERE mid = ?"); + state.bindLong(1, newMessageId); + state.bindLong(2, oldMessageId); + state.step(); + } catch (Exception e) { + try { + database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid = %d", oldMessageId)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM messages_seq WHERE mid = %d", oldMessageId)).stepThis().dispose(); + } catch (Exception e2) { + FileLog.e(e2); + } + } finally { + if (state != null) { + state.dispose(); + state = null; + } } - } - try { - state = database.executeFast("UPDATE media_v2 SET mid = ? WHERE mid = ?"); - state.bindLong(1, newMessageId); - state.bindLong(2, oldMessageId); - state.step(); - } catch (Exception e) { try { - database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE mid = %d", oldMessageId)).stepThis().dispose(); - } catch (Exception e2) { - FileLog.e(e2); - } - } finally { - if (state != null) { - state.dispose(); - state = null; + state = database.executeFast("UPDATE media_v2 SET mid = ? WHERE mid = ?"); + state.bindLong(1, newMessageId); + state.bindLong(2, oldMessageId); + state.step(); + } catch (Exception e) { + try { + database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE mid = %d", oldMessageId)).stepThis().dispose(); + } catch (Exception e2) { + FileLog.e(e2); + } + } finally { + if (state != null) { + state.dispose(); + state = null; + } } - } - try { - state = database.executeFast("UPDATE dialogs SET last_mid = ? WHERE last_mid = ?"); - state.bindLong(1, newMessageId); - state.bindLong(2, oldMessageId); - state.step(); - } catch (Exception e) { - FileLog.e(e); - } finally { - if (state != null) { - state.dispose(); + try { + state = database.executeFast("UPDATE dialogs SET last_mid = ? WHERE last_mid = ?"); + state.bindLong(1, newMessageId); + state.bindLong(2, oldMessageId); + state.step(); + } catch (Exception e) { + FileLog.e(e); + } finally { + if (state != null) { + state.dispose(); + } + } + } else if (scheduled == 1) { + try { + state = database.executeFast("UPDATE scheduled_messages SET mid = ?, send_state = 0 WHERE mid = ?"); + state.bindLong(1, newMessageId); + state.bindLong(2, oldMessageId); + state.step(); + } catch (Exception e) { + try { + database.executeFast(String.format(Locale.US, "DELETE FROM scheduled_messages WHERE mid = %d", oldMessageId)).stepThis().dispose(); + } catch (Exception e2) { + FileLog.e(e2); + } + } finally { + if (state != null) { + state.dispose(); + } } } @@ -6031,11 +6260,11 @@ private long[] updateMessageStateAndIdInternal(long random_id, Integer _oldId, i } } - public long[] updateMessageStateAndId(final long random_id, final Integer _oldId, final int newId, final int date, boolean useQueue, final int channelId) { + public long[] updateMessageStateAndId(final long random_id, final Integer _oldId, final int newId, final int date, boolean useQueue, final int channelId, int scheduled) { if (useQueue) { - storageQueue.postRunnable(() -> updateMessageStateAndIdInternal(random_id, _oldId, newId, date, channelId)); + storageQueue.postRunnable(() -> updateMessageStateAndIdInternal(random_id, _oldId, newId, date, channelId, scheduled)); } else { - return updateMessageStateAndIdInternal(random_id, _oldId, newId, date, channelId); + return updateMessageStateAndIdInternal(random_id, _oldId, newId, date, channelId, scheduled); } return null; } @@ -6209,9 +6438,9 @@ public void markMessagesAsDeletedByRandoms(final ArrayList messages) { } cursor.dispose(); if (!mids.isEmpty()) { - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0)); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0, false)); updateDialogsWithReadMessagesInternal(mids, null, null, null); - markMessagesAsDeletedInternal(mids, 0, true); + markMessagesAsDeletedInternal(mids, 0, true, false); updateDialogsWithDeletedMessagesInternal(mids, null, 0); } } catch (Exception e) { @@ -6228,160 +6457,214 @@ protected void deletePushMessages(long dialogId, final ArrayList messag } } - private ArrayList markMessagesAsDeletedInternal(final ArrayList messages, int channelId, boolean deleteFiles) { + private void broadcastScheduledMessagesChange(Long did) { try { - String ids; - final ArrayList temp = new ArrayList<>(messages); - ArrayList dialogsIds = new ArrayList<>(); - LongSparseArray dialogsToUpdate = new LongSparseArray<>(); - if (channelId != 0) { - StringBuilder builder = new StringBuilder(messages.size()); - for (int a = 0; a < messages.size(); a++) { - long messageId = messages.get(a); - messageId |= ((long) channelId) << 32; - if (builder.length() > 0) { - builder.append(','); - } - builder.append(messageId); - } - ids = builder.toString(); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM scheduled_messages WHERE uid = %d", did)); + int count; + if (cursor.next()) { + count = cursor.intValue(0); } else { - ids = TextUtils.join(",", messages); + count = 0; } - ArrayList filesToDelete = new ArrayList<>(); - int currentUser = getUserConfig().getClientUserId(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, data, read_state, out, mention, mid FROM messages WHERE mid IN(%s)", ids)); + cursor.dispose(); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, did, count)); + } catch (Exception e) { + FileLog.e(e); + } + } - try { - while (cursor.next()) { - long did = cursor.longValue(0); - int mid = cursor.intValue(5); - temp.remove((Integer) mid); - if (did == currentUser) { - continue; - } - int read_state = cursor.intValue(2); - if (cursor.intValue(3) == 0) { - Integer[] unread_count = dialogsToUpdate.get(did); - if (unread_count == null) { - unread_count = new Integer[]{0, 0}; - dialogsToUpdate.put(did, unread_count); - } - if (read_state < 2) { - unread_count[1]++; - } - if (read_state == 0 || read_state == 2) { - unread_count[0]++; + private ArrayList markMessagesAsDeletedInternal(final ArrayList messages, int channelId, boolean deleteFiles, boolean scheduled) { + try { + ArrayList dialogsIds = new ArrayList<>(); + if (scheduled) { + String ids; + if (channelId != 0) { + StringBuilder builder = new StringBuilder(messages.size()); + for (int a = 0; a < messages.size(); a++) { + long messageId = messages.get(a); + messageId |= ((long) channelId) << 32; + if (builder.length() > 0) { + builder.append(','); } + builder.append(messageId); } - if ((int) did != 0 && !deleteFiles) { - continue; - } - NativeByteBuffer data = cursor.byteBufferValue(1); - if (data != null) { - TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.readAttachPath(data, getUserConfig().clientUserId); - data.reuse(); - addFilesToDelete(message, filesToDelete, false); - } + ids = builder.toString(); + } else { + ids = TextUtils.join(",", messages); } - } catch (Exception e) { - FileLog.e(e); - } - cursor.dispose(); - getFileLoader().deleteFiles(filesToDelete, 0); + ArrayList dialogsToUpdate = new ArrayList<>(); - for (int a = 0; a < dialogsToUpdate.size(); a++) { - long did = dialogsToUpdate.keyAt(a); - Integer[] counts = dialogsToUpdate.valueAt(a); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid FROM scheduled_messages WHERE mid IN(%s)", ids)); + try { + while (cursor.next()) { + long did = cursor.longValue(0); + if (!dialogsToUpdate.contains(did)) { + dialogsToUpdate.add(did); + } + } + } catch (Exception e) { + FileLog.e(e); + } + cursor.dispose(); - cursor = database.queryFinalized("SELECT unread_count, unread_count_i FROM dialogs WHERE did = " + did); - int old_unread_count = 0; - int old_mentions_count = 0; - if (cursor.next()) { - old_unread_count = cursor.intValue(0); - old_mentions_count = cursor.intValue(1); + database.executeFast(String.format(Locale.US, "DELETE FROM scheduled_messages WHERE mid IN(%s)", ids)).stepThis().dispose(); + for (int a = 0, N = dialogsToUpdate.size(); a < N; a++) { + broadcastScheduledMessagesChange(dialogsToUpdate.get(a)); + } + } else { + String ids; + final ArrayList temp = new ArrayList<>(messages); + LongSparseArray dialogsToUpdate = new LongSparseArray<>(); + if (channelId != 0) { + StringBuilder builder = new StringBuilder(messages.size()); + for (int a = 0; a < messages.size(); a++) { + long messageId = messages.get(a); + messageId |= ((long) channelId) << 32; + if (builder.length() > 0) { + builder.append(','); + } + builder.append(messageId); + } + ids = builder.toString(); + } else { + ids = TextUtils.join(",", messages); + } + ArrayList filesToDelete = new ArrayList<>(); + int currentUser = getUserConfig().getClientUserId(); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, data, read_state, out, mention, mid FROM messages WHERE mid IN(%s)", ids)); + + try { + while (cursor.next()) { + long did = cursor.longValue(0); + int mid = cursor.intValue(5); + temp.remove((Integer) mid); + if (did == currentUser) { + continue; + } + int read_state = cursor.intValue(2); + if (cursor.intValue(3) == 0) { + Integer[] unread_count = dialogsToUpdate.get(did); + if (unread_count == null) { + unread_count = new Integer[]{0, 0}; + dialogsToUpdate.put(did, unread_count); + } + if (read_state < 2) { + unread_count[1]++; + } + if (read_state == 0 || read_state == 2) { + unread_count[0]++; + } + } + if ((int) did != 0 && !deleteFiles) { + continue; + } + NativeByteBuffer data = cursor.byteBufferValue(1); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.readAttachPath(data, getUserConfig().clientUserId); + data.reuse(); + addFilesToDelete(message, filesToDelete, false); + } + } + } catch (Exception e) { + FileLog.e(e); } cursor.dispose(); - dialogsIds.add(did); - SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET unread_count = ?, unread_count_i = ? WHERE did = ?"); - state.requery(); - state.bindInteger(1, Math.max(0, old_unread_count - counts[0])); - state.bindInteger(2, Math.max(0, old_mentions_count - counts[1])); - state.bindLong(3, did); - state.step(); - state.dispose(); - } + getFileLoader().deleteFiles(filesToDelete, 0); - database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid IN(%s)", ids)).stepThis().dispose(); - database.executeFast(String.format(Locale.US, "DELETE FROM polls WHERE mid IN(%s)", ids)).stepThis().dispose(); - database.executeFast(String.format(Locale.US, "DELETE FROM bot_keyboard WHERE mid IN(%s)", ids)).stepThis().dispose(); - database.executeFast(String.format(Locale.US, "DELETE FROM messages_seq WHERE mid IN(%s)", ids)).stepThis().dispose(); - if (temp.isEmpty()) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, type FROM media_v2 WHERE mid IN(%s)", ids)); - SparseArray> mediaCounts = null; - while (cursor.next()) { - long uid = cursor.longValue(0); - int type = cursor.intValue(1); - if (mediaCounts == null) { - mediaCounts = new SparseArray<>(); - } - LongSparseArray counts = mediaCounts.get(type); - Integer count; - if (counts == null) { - counts = new LongSparseArray<>(); - count = 0; - mediaCounts.put(type, counts); - } else { - count = counts.get(uid); - } - if (count == null) { - count = 0; + for (int a = 0; a < dialogsToUpdate.size(); a++) { + long did = dialogsToUpdate.keyAt(a); + Integer[] counts = dialogsToUpdate.valueAt(a); + + cursor = database.queryFinalized("SELECT unread_count, unread_count_i FROM dialogs WHERE did = " + did); + int old_unread_count = 0; + int old_mentions_count = 0; + if (cursor.next()) { + old_unread_count = cursor.intValue(0); + old_mentions_count = cursor.intValue(1); } - count++; - counts.put(uid, count); + cursor.dispose(); + + dialogsIds.add(did); + SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET unread_count = ?, unread_count_i = ? WHERE did = ?"); + state.requery(); + state.bindInteger(1, Math.max(0, old_unread_count - counts[0])); + state.bindInteger(2, Math.max(0, old_mentions_count - counts[1])); + state.bindLong(3, did); + state.step(); + state.dispose(); } - cursor.dispose(); - if (mediaCounts != null) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)"); - for (int a = 0; a < mediaCounts.size(); a++) { - int type = mediaCounts.keyAt(a); - LongSparseArray value = mediaCounts.valueAt(a); - for (int b = 0; b < value.size(); b++) { - long uid = value.keyAt(b); - int lower_part = (int) uid; - int count = -1; - int old = 0; - cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type)); - if (cursor.next()) { - count = cursor.intValue(0); - old = cursor.intValue(1); - } - cursor.dispose(); - if (count != -1) { - state.requery(); - count = Math.max(0, count - value.valueAt(b)); - state.bindLong(1, uid); - state.bindInteger(2, type); - state.bindInteger(3, count); - state.bindInteger(4, old); - state.step(); + + database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid IN(%s)", ids)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM polls WHERE mid IN(%s)", ids)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM bot_keyboard WHERE mid IN(%s)", ids)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM messages_seq WHERE mid IN(%s)", ids)).stepThis().dispose(); + if (temp.isEmpty()) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, type FROM media_v2 WHERE mid IN(%s)", ids)); + SparseArray> mediaCounts = null; + while (cursor.next()) { + long uid = cursor.longValue(0); + int type = cursor.intValue(1); + if (mediaCounts == null) { + mediaCounts = new SparseArray<>(); + } + LongSparseArray counts = mediaCounts.get(type); + Integer count; + if (counts == null) { + counts = new LongSparseArray<>(); + count = 0; + mediaCounts.put(type, counts); + } else { + count = counts.get(uid); + } + if (count == null) { + count = 0; + } + count++; + counts.put(uid, count); + } + cursor.dispose(); + if (mediaCounts != null) { + SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)"); + for (int a = 0; a < mediaCounts.size(); a++) { + int type = mediaCounts.keyAt(a); + LongSparseArray value = mediaCounts.valueAt(a); + for (int b = 0; b < value.size(); b++) { + long uid = value.keyAt(b); + int lower_part = (int) uid; + int count = -1; + int old = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type)); + if (cursor.next()) { + count = cursor.intValue(0); + old = cursor.intValue(1); + } + cursor.dispose(); + if (count != -1) { + state.requery(); + count = Math.max(0, count - value.valueAt(b)); + state.bindLong(1, uid); + state.bindInteger(2, type); + state.bindInteger(3, count); + state.bindInteger(4, old); + state.step(); + } } } + state.dispose(); } - state.dispose(); - } - } else { - if (channelId == 0) { - database.executeFast("UPDATE media_counts_v2 SET old = 1 WHERE 1").stepThis().dispose(); } else { - database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", -channelId)).stepThis().dispose(); + if (channelId == 0) { + database.executeFast("UPDATE media_counts_v2 SET old = 1 WHERE 1").stepThis().dispose(); + } else { + database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", -channelId)).stepThis().dispose(); + } } + database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE mid IN(%s)", ids)).stepThis().dispose(); + getMediaDataController().clearBotKeyboard(0, messages); } - database.executeFast(String.format(Locale.US, "DELETE FROM media_v2 WHERE mid IN(%s)", ids)).stepThis().dispose(); - getMediaDataController().clearBotKeyboard(0, messages); return dialogsIds; } catch (Exception e) { FileLog.e(e); @@ -6494,19 +6777,13 @@ private void updateDialogsWithDeletedMessagesInternal(final ArrayList m int lower_id = (int) dialog.id; int high_id = (int) (dialog.id >> 32); if (lower_id != 0) { - if (high_id == 1) { - if (!chatsToLoad.contains(lower_id)) { - chatsToLoad.add(lower_id); + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); } } else { - if (lower_id > 0) { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); } } } else { @@ -6548,14 +6825,14 @@ public void updateDialogsWithDeletedMessages(final ArrayList messages, } } - public ArrayList markMessagesAsDeleted(final ArrayList messages, boolean useQueue, final int channelId, boolean deleteFiles) { + public ArrayList markMessagesAsDeleted(final ArrayList messages, boolean useQueue, final int channelId, boolean deleteFiles, boolean scheduled) { if (messages.isEmpty()) { return null; } if (useQueue) { - storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId, deleteFiles)); + storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId, deleteFiles, scheduled)); } else { - return markMessagesAsDeletedInternal(messages, channelId, deleteFiles); + return markMessagesAsDeletedInternal(messages, channelId, deleteFiles, scheduled); } return null; } @@ -6914,7 +7191,7 @@ public void replaceMessageIfExists(final TLRPC.Message message, int currentAccou state.bindInteger(4, message.send_state); state.bindInteger(5, message.date); state.bindByteBuffer(6, data); - state.bindInteger(7, (MessageObject.isOut(message) ? 1 : 0)); + state.bindInteger(7, (MessageObject.isOut(message) || message.from_scheduled ? 1 : 0)); state.bindInteger(8, message.ttl); if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { state.bindInteger(9, message.views); @@ -6962,240 +7239,278 @@ public void replaceMessageIfExists(final TLRPC.Message message, int currentAccou }); } - public void putMessages(final TLRPC.messages_Messages messages, final long dialog_id, final int load_type, final int max_id, final boolean createDialog) { + public void putMessages(final TLRPC.messages_Messages messages, final long dialog_id, final int load_type, final int max_id, final boolean createDialog, final boolean scheduled) { storageQueue.postRunnable(() -> { try { - int mentionCountUpdate = Integer.MAX_VALUE; - if (messages.messages.isEmpty()) { - if (load_type == 0) { - doneHolesInTable("messages_holes", dialog_id, max_id); - doneHolesInMedia(dialog_id, max_id, -1); - } - return; - } - database.beginTransaction(); + if (scheduled) { + database.executeFast(String.format(Locale.US, "DELETE FROM scheduled_messages WHERE uid = %d AND mid > 0", dialog_id)).stepThis().dispose(); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages VALUES(?, ?, ?, ?, ?, ?, NULL)"); + int channelId = 0; + int count = messages.messages.size(); + for (int a = 0; a < count; a++) { + TLRPC.Message message = messages.messages.get(a); - if (load_type == 0) { - int minId = messages.messages.get(messages.messages.size() - 1).id; - closeHolesInTable("messages_holes", dialog_id, minId, max_id); - closeHolesInMedia(dialog_id, minId, max_id, -1); - } else if (load_type == 1) { - int maxId = messages.messages.get(0).id; - closeHolesInTable("messages_holes", dialog_id, max_id, maxId); - closeHolesInMedia(dialog_id, max_id, maxId, -1); - } else if (load_type == 3 || load_type == 2 || load_type == 4) { - int maxId = max_id == 0 && load_type != 4 ? Integer.MAX_VALUE : messages.messages.get(0).id; - int minId = messages.messages.get(messages.messages.size() - 1).id; - closeHolesInTable("messages_holes", dialog_id, minId, maxId); - closeHolesInMedia(dialog_id, minId, maxId, -1); - } - int count = messages.messages.size(); - - //load_type == 0 ? backward loading - //load_type == 1 ? forward loading - //load_type == 2 ? load from first unread - //load_type == 3 ? load around message - //load_type == 4 ? load around date + long messageId = message.id; + if (channelId == 0) { + channelId = message.to_id.channel_id; + } + if (message.to_id.channel_id != 0) { + messageId |= ((long) channelId) << 32; + } - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)"); - SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); - SQLitePreparedStatement state_polls = null; - SQLitePreparedStatement state_webpage = null; - TLRPC.Message botKeyboard = null; - int minChannelMessageId = Integer.MAX_VALUE; - int maxChannelMessageId = 0; - int channelId = 0; - ArrayList filesToDelete = new ArrayList<>(); - for (int a = 0; a < count; a++) { - TLRPC.Message message = messages.messages.get(a); + fixUnsupportedMedia(message); + state_messages.requery(); + NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); + state_messages.bindLong(1, messageId); + state_messages.bindLong(2, dialog_id); + state_messages.bindInteger(3, message.send_state); + state_messages.bindInteger(4, message.date); + state_messages.bindByteBuffer(5, data); + state_messages.bindInteger(6, message.ttl); + state_messages.step(); - long messageId = message.id; - if (channelId == 0) { - channelId = message.to_id.channel_id; + data.reuse(); } - if (message.to_id.channel_id != 0) { - messageId |= ((long) channelId) << 32; + state_messages.dispose(); + + putUsersInternal(messages.users); + putChatsInternal(messages.chats); + + database.commitTransaction(); + broadcastScheduledMessagesChange(dialog_id); + } else { + int mentionCountUpdate = Integer.MAX_VALUE; + if (messages.messages.isEmpty()) { + if (load_type == 0) { + doneHolesInTable("messages_holes", dialog_id, max_id); + doneHolesInMedia(dialog_id, max_id, -1); + } + return; } + database.beginTransaction(); - if (load_type == -2) { - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, data, ttl, mention, read_state, send_state FROM messages WHERE mid = %d", messageId)); - boolean exist; - if (exist = cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(1); - if (data != null) { - TLRPC.Message oldMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - oldMessage.readAttachPath(data, getUserConfig().clientUserId); - data.reuse(); - int send_state = cursor.intValue(5); - if (oldMessage != null && send_state != 3) { - message.attachPath = oldMessage.attachPath; - message.ttl = cursor.intValue(2); - } - boolean sameMedia = false; - if (oldMessage.media instanceof TLRPC.TL_messageMediaPhoto && message.media instanceof TLRPC.TL_messageMediaPhoto && oldMessage.media.photo != null && message.media.photo != null) { - sameMedia = oldMessage.media.photo.id == message.media.photo.id; - } else if (oldMessage.media instanceof TLRPC.TL_messageMediaDocument && message.media instanceof TLRPC.TL_messageMediaDocument && oldMessage.media.document != null && message.media.document != null) { - sameMedia = oldMessage.media.document.id == message.media.document.id; - } - if (!sameMedia) { - addFilesToDelete(oldMessage, filesToDelete, false); - } - } - boolean oldMention = cursor.intValue(3) != 0; - int readState = cursor.intValue(4); - if (oldMention != message.mentioned) { - if (mentionCountUpdate == Integer.MAX_VALUE) { - SQLiteCursor cursor2 = database.queryFinalized("SELECT unread_count_i FROM dialogs WHERE did = " + dialog_id); - if (cursor2.next()) { - mentionCountUpdate = cursor2.intValue(0); + if (load_type == 0) { + int minId = messages.messages.get(messages.messages.size() - 1).id; + closeHolesInTable("messages_holes", dialog_id, minId, max_id); + closeHolesInMedia(dialog_id, minId, max_id, -1); + } else if (load_type == 1) { + int maxId = messages.messages.get(0).id; + closeHolesInTable("messages_holes", dialog_id, max_id, maxId); + closeHolesInMedia(dialog_id, max_id, maxId, -1); + } else if (load_type == 3 || load_type == 2 || load_type == 4) { + int maxId = max_id == 0 && load_type != 4 ? Integer.MAX_VALUE : messages.messages.get(0).id; + int minId = messages.messages.get(messages.messages.size() - 1).id; + closeHolesInTable("messages_holes", dialog_id, minId, maxId); + closeHolesInMedia(dialog_id, minId, maxId, -1); + } + int count = messages.messages.size(); + + //load_type == 0 ? backward loading + //load_type == 1 ? forward loading + //load_type == 2 ? load from first unread + //load_type == 3 ? load around message + //load_type == 4 ? load around date + ArrayList filesToDelete = new ArrayList<>(); + + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)"); + SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_polls = null; + SQLitePreparedStatement state_webpage = null; + TLRPC.Message botKeyboard = null; + int channelId = 0; + for (int a = 0; a < count; a++) { + TLRPC.Message message = messages.messages.get(a); + + long messageId = message.id; + if (channelId == 0) { + channelId = message.to_id.channel_id; + } + if (message.to_id.channel_id != 0) { + messageId |= ((long) channelId) << 32; + } + + if (load_type == -2) { + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, data, ttl, mention, read_state, send_state FROM messages WHERE mid = %d", messageId)); + boolean exist; + if (exist = cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(1); + if (data != null) { + TLRPC.Message oldMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + oldMessage.readAttachPath(data, getUserConfig().clientUserId); + data.reuse(); + int send_state = cursor.intValue(5); + if (oldMessage != null && send_state != 3) { + message.attachPath = oldMessage.attachPath; + message.ttl = cursor.intValue(2); + } + if (!message.out) { + boolean sameMedia = false; //TODO check + if (oldMessage.media instanceof TLRPC.TL_messageMediaPhoto && message.media instanceof TLRPC.TL_messageMediaPhoto && oldMessage.media.photo != null && message.media.photo != null) { + sameMedia = oldMessage.media.photo.id == message.media.photo.id; + } else if (oldMessage.media instanceof TLRPC.TL_messageMediaDocument && message.media instanceof TLRPC.TL_messageMediaDocument && oldMessage.media.document != null && message.media.document != null) { + sameMedia = oldMessage.media.document.id == message.media.document.id; + } + if (!sameMedia) { + addFilesToDelete(oldMessage, filesToDelete, false); + } } - cursor2.dispose(); } - if (oldMention) { - if (readState <= 1) { - mentionCountUpdate--; + boolean oldMention = cursor.intValue(3) != 0; + int readState = cursor.intValue(4); + if (oldMention != message.mentioned) { + if (mentionCountUpdate == Integer.MAX_VALUE) { + SQLiteCursor cursor2 = database.queryFinalized("SELECT unread_count_i FROM dialogs WHERE did = " + dialog_id); + if (cursor2.next()) { + mentionCountUpdate = cursor2.intValue(0); + } + cursor2.dispose(); } - } else { - if (message.media_unread) { - mentionCountUpdate++; + if (oldMention) { + if (readState <= 1) { + mentionCountUpdate--; + } + } else { + if (message.media_unread) { + mentionCountUpdate++; + } } } } + cursor.dispose(); + if (!exist) { + continue; + } } - cursor.dispose(); - if (!exist) { - continue; - } - } - if (a == 0 && createDialog) { - int pinned = 0; - int mentions = 0; - int flags = 0; - SQLiteCursor cursor = database.queryFinalized("SELECT pinned, unread_count_i, flags FROM dialogs WHERE did = " + dialog_id); - boolean exist; - if (exist = cursor.next()) { - pinned = cursor.intValue(0); - mentions = cursor.intValue(1); - flags = cursor.intValue(2); + if (a == 0 && createDialog) { + int pinned = 0; + int mentions = 0; + int flags = 0; + SQLiteCursor cursor = database.queryFinalized("SELECT pinned, unread_count_i, flags FROM dialogs WHERE did = " + dialog_id); + boolean exist; + if (exist = cursor.next()) { + pinned = cursor.intValue(0); + mentions = cursor.intValue(1); + flags = cursor.intValue(2); + } + cursor.dispose(); + + SQLitePreparedStatement state3; + if (exist) { + state3 = database.executeFast("UPDATE dialogs SET date = ?, last_mid = ?, inbox_max = ?, last_mid_i = ?, pts = ?, date_i = ? WHERE did = ?"); + state3.bindInteger(1, message.date); + state3.bindLong(2, messageId); + state3.bindInteger(3, message.id); + state3.bindLong(4, messageId); + state3.bindInteger(5, messages.pts); + state3.bindInteger(6, message.date); + state3.bindLong(7, dialog_id); + } else { + state3 = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + state3.bindLong(1, dialog_id); + state3.bindInteger(2, message.date); + state3.bindInteger(3, 0); + state3.bindLong(4, messageId); + state3.bindInteger(5, message.id); + state3.bindInteger(6, 0); + state3.bindLong(7, messageId); + state3.bindInteger(8, mentions); + state3.bindInteger(9, messages.pts); + state3.bindInteger(10, message.date); + state3.bindInteger(11, pinned); + state3.bindInteger(12, flags); + state3.bindInteger(13, 0); + state3.bindNull(14); + } + state3.step(); + state3.dispose(); } - cursor.dispose(); - SQLitePreparedStatement state3; - if (exist) { - state3 = database.executeFast("UPDATE dialogs SET date = ?, last_mid = ?, inbox_max = ?, last_mid_i = ?, pts = ?, date_i = ? WHERE did = ?"); - state3.bindInteger(1, message.date); - state3.bindLong(2, messageId); - state3.bindInteger(3, message.id); - state3.bindLong(4, messageId); - state3.bindInteger(5, messages.pts); - state3.bindInteger(6, message.date); - state3.bindLong(7, dialog_id); + fixUnsupportedMedia(message); + state_messages.requery(); + NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); + message.serializeToStream(data); + state_messages.bindLong(1, messageId); + state_messages.bindLong(2, dialog_id); + state_messages.bindInteger(3, MessageObject.getUnreadFlags(message)); + state_messages.bindInteger(4, message.send_state); + state_messages.bindInteger(5, message.date); + state_messages.bindByteBuffer(6, data); + state_messages.bindInteger(7, (MessageObject.isOut(message) || message.from_scheduled ? 1 : 0)); + state_messages.bindInteger(8, message.ttl); + if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + state_messages.bindInteger(9, message.views); } else { - state3 = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - state3.bindLong(1, dialog_id); - state3.bindInteger(2, message.date); - state3.bindInteger(3, 0); - state3.bindLong(4, messageId); - state3.bindInteger(5, message.id); - state3.bindInteger(6, 0); - state3.bindLong(7, messageId); - state3.bindInteger(8, mentions); - state3.bindInteger(9, messages.pts); - state3.bindInteger(10, message.date); - state3.bindInteger(11, pinned); - state3.bindInteger(12, flags); - state3.bindInteger(13, 0); - state3.bindNull(14); - } - state3.step(); - state3.dispose(); - } - - fixUnsupportedMedia(message); - state_messages.requery(); - NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); - message.serializeToStream(data); - state_messages.bindLong(1, messageId); - state_messages.bindLong(2, dialog_id); - state_messages.bindInteger(3, MessageObject.getUnreadFlags(message)); - state_messages.bindInteger(4, message.send_state); - state_messages.bindInteger(5, message.date); - state_messages.bindByteBuffer(6, data); - state_messages.bindInteger(7, (MessageObject.isOut(message) ? 1 : 0)); - state_messages.bindInteger(8, message.ttl); - if ((message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - state_messages.bindInteger(9, message.views); - } else { - state_messages.bindInteger(9, getMessageMediaType(message)); - } - state_messages.bindInteger(10, 0); - state_messages.bindInteger(11, message.mentioned ? 1 : 0); - state_messages.step(); - - if (MediaDataController.canAddMessageToMedia(message)) { - state_media.requery(); - state_media.bindLong(1, messageId); - state_media.bindLong(2, dialog_id); - state_media.bindInteger(3, message.date); - state_media.bindInteger(4, MediaDataController.getMediaType(message)); - state_media.bindByteBuffer(5, data); - state_media.step(); - } - data.reuse(); + state_messages.bindInteger(9, getMessageMediaType(message)); + } + state_messages.bindInteger(10, 0); + state_messages.bindInteger(11, message.mentioned ? 1 : 0); + state_messages.step(); - if (message.media instanceof TLRPC.TL_messageMediaPoll) { - if (state_polls == null) { - state_polls = database.executeFast("REPLACE INTO polls VALUES(?, ?)"); + if (MediaDataController.canAddMessageToMedia(message)) { + state_media.requery(); + state_media.bindLong(1, messageId); + state_media.bindLong(2, dialog_id); + state_media.bindInteger(3, message.date); + state_media.bindInteger(4, MediaDataController.getMediaType(message)); + state_media.bindByteBuffer(5, data); + state_media.step(); } - TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.media; - state_polls.requery(); - state_polls.bindLong(1, messageId); - state_polls.bindLong(2, mediaPoll.poll.id); - state_polls.step(); - } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { - if (state_webpage == null) { - state_webpage = database.executeFast("REPLACE INTO webpage_pending VALUES(?, ?)"); + data.reuse(); + + if (message.media instanceof TLRPC.TL_messageMediaPoll) { + if (state_polls == null) { + state_polls = database.executeFast("REPLACE INTO polls VALUES(?, ?)"); + } + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.media; + state_polls.requery(); + state_polls.bindLong(1, messageId); + state_polls.bindLong(2, mediaPoll.poll.id); + state_polls.step(); + } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + if (state_webpage == null) { + state_webpage = database.executeFast("REPLACE INTO webpage_pending VALUES(?, ?)"); + } + state_webpage.requery(); + state_webpage.bindLong(1, message.media.webpage.id); + state_webpage.bindLong(2, messageId); + state_webpage.step(); } - state_webpage.requery(); - state_webpage.bindLong(1, message.media.webpage.id); - state_webpage.bindLong(2, messageId); - state_webpage.step(); - } - if (load_type == 0 && isValidKeyboardToSave(message)) { - if (botKeyboard == null || botKeyboard.id < message.id) { - botKeyboard = message; + if (load_type == 0 && isValidKeyboardToSave(message)) { + if (botKeyboard == null || botKeyboard.id < message.id) { + botKeyboard = message; + } } } - } - state_messages.dispose(); - state_media.dispose(); - if (state_webpage != null) { - state_webpage.dispose(); - } - if (state_polls != null) { - state_polls.dispose(); - } - if (botKeyboard != null) { - getMediaDataController().putBotKeyboard(dialog_id, botKeyboard); - } - getFileLoader().deleteFiles(filesToDelete, 0); - - putUsersInternal(messages.users); - putChatsInternal(messages.chats); + state_messages.dispose(); + state_media.dispose(); + if (state_webpage != null) { + state_webpage.dispose(); + } + if (state_polls != null) { + state_polls.dispose(); + } + if (botKeyboard != null) { + getMediaDataController().putBotKeyboard(dialog_id, botKeyboard); + } + getFileLoader().deleteFiles(filesToDelete, 0); + putUsersInternal(messages.users); + putChatsInternal(messages.chats); - if (mentionCountUpdate != Integer.MAX_VALUE) { - database.executeFast(String.format(Locale.US, "UPDATE dialogs SET unread_count_i = %d WHERE did = %d", mentionCountUpdate, dialog_id)).stepThis().dispose(); - LongSparseArray sparseArray = new LongSparseArray<>(1); - sparseArray.put(dialog_id, mentionCountUpdate); - getMessagesController().processDialogsUpdateRead(null, sparseArray); - } + if (mentionCountUpdate != Integer.MAX_VALUE) { + database.executeFast(String.format(Locale.US, "UPDATE dialogs SET unread_count_i = %d WHERE did = %d", mentionCountUpdate, dialog_id)).stepThis().dispose(); + LongSparseArray sparseArray = new LongSparseArray<>(1); + sparseArray.put(dialog_id, mentionCountUpdate); + getMessagesController().processDialogsUpdateRead(null, sparseArray); + } - database.commitTransaction(); + database.commitTransaction(); - if (createDialog) { - updateDialogsWithDeletedMessages(new ArrayList<>(), null, false, channelId); + if (createDialog) { + updateDialogsWithDeletedMessages(new ArrayList<>(), null, false, channelId); + } } } catch (Exception e) { FileLog.e(e); @@ -7416,19 +7731,13 @@ public void getDialogs(final int folderId, final int offset, final int count) { int lower_id = (int) dialog.id; int high_id = (int) (dialog.id >> 32); if (lower_id != 0) { - if (high_id == 1) { - if (!chatsToLoad.contains(lower_id)) { - chatsToLoad.add(lower_id); + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); } } else { - if (lower_id > 0) { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); } } } else { @@ -7567,7 +7876,7 @@ private void putDialogsInternal(final TLRPC.messages_Dialogs dialogs, int check) state_messages.bindInteger(4, message.send_state); state_messages.bindInteger(5, message.date); state_messages.bindByteBuffer(6, data); - state_messages.bindInteger(7, (MessageObject.isOut(message) ? 1 : 0)); + state_messages.bindInteger(7, (MessageObject.isOut(message) || message.from_scheduled ? 1 : 0)); state_messages.bindInteger(8, 0); state_messages.bindInteger(9, (message.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 ? message.views : 0); state_messages.bindInteger(10, 0); @@ -7689,14 +7998,15 @@ public void setDialogsFolderId(final ArrayList peers, Array storageQueue.postRunnable(() -> { try { database.beginTransaction(); - SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET folder_id = ? WHERE did = ?"); + SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET folder_id = ?, pinned = ? WHERE did = ?"); if (peers != null) { for (int a = 0, N = peers.size(); a < N; a++) { TLRPC.TL_folderPeer folderPeer = peers.get(a); long did = DialogObject.getPeerDialogId(folderPeer.peer); state.requery(); state.bindInteger(1, folderPeer.folder_id); - state.bindLong(2, did); + state.bindInteger(2, 0); + state.bindLong(3, did); state.step(); } } else if (inputPeers != null) { @@ -7705,13 +8015,15 @@ public void setDialogsFolderId(final ArrayList peers, Array long did = DialogObject.getPeerDialogId(folderPeer.peer); state.requery(); state.bindInteger(1, folderPeer.folder_id); - state.bindLong(2, did); + state.bindInteger(2, 0); + state.bindLong(3, did); state.step(); } } else { state.requery(); state.bindInteger(1, folderId); - state.bindLong(2, dialogId); + state.bindInteger(2, 0); + state.bindLong(3, dialogId); state.step(); } state.dispose(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java index 211e436d6be..eb4e1983d04 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java @@ -130,6 +130,7 @@ public int onStartCommand(Intent startIntent, int flags, int startId) { @Override public void onDestroy() { + super.onDestroy(); handleStopRequest(null); delayedStopHandler.removeCallbacksAndMessages(null); mediaSession.release(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java index a2166eaa7d2..4bd3b1bed6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java @@ -13,8 +13,6 @@ import android.content.pm.ApplicationInfo; import android.os.Build; -import net.hockeyapp.android.Constants; - import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; @@ -117,8 +115,6 @@ public static synchronized void initNativeLibs(Context context) { return; } - Constants.loadFromContext(context); - try { try { System.loadLibrary(LIB_NAME); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 6069d75df5b..26d8c7ed626 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -94,6 +94,8 @@ public class NotificationCenter { public static final int stopAllHeavyOperations = totalEvents++; public static final int startAllHeavyOperations = totalEvents++; public static final int sendingMessagesChanged = totalEvents++; + public static final int didUpdateReactions = totalEvents++; + public static final int scheduledMessagesUpdated = totalEvents++; public static final int httpFileDidLoad = totalEvents++; public static final int httpFileDidFailedLoad = totalEvents++; @@ -105,7 +107,7 @@ public class NotificationCenter { public static final int FileUploadProgressChanged = totalEvents++; public static final int FileLoadProgressChanged = totalEvents++; public static final int fileDidLoad = totalEvents++; - public static final int fileDidFailedLoad = totalEvents++; + public static final int fileDidFailToLoad = totalEvents++; public static final int filePreparingStarted = totalEvents++; public static final int fileNewChunkAvailable = totalEvents++; public static final int filePreparingFailed = totalEvents++; @@ -140,6 +142,9 @@ public class NotificationCenter { public static final int newEmojiSuggestionsAvailable = totalEvents++; + public static final int themeUploadedToServer = totalEvents++; + public static final int themeUploadError = totalEvents++; + //global public static final int pushMessagesUpdated = totalEvents++; public static final int stopEncodingService = totalEvents++; @@ -154,6 +159,7 @@ public class NotificationCenter { public static final int didSetNewTheme = totalEvents++; public static final int themeListUpdated = totalEvents++; public static final int needSetDayNightTheme = totalEvents++; + public static final int goingToPreviewTheme = totalEvents++; public static final int locationPermissionGranted = totalEvents++; public static final int reloadInterface = totalEvents++; public static final int suggestedLangpack = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java index 47de0b7067f..845de4751c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java @@ -20,6 +20,12 @@ public void onReceive(Context context, Intent intent) { return; } int currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); - MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dismissDate", intent.getIntExtra("messageDate", 0)).commit(); + long dialogId = intent.getLongExtra("dialogId", 0); + int date = intent.getIntExtra("messageDate", 0); + if (dialogId == 0) { + MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dismissDate", date).commit(); + } else { + MessagesController.getNotificationsSettings(currentAccount).edit().putInt("dismissDate" + dialogId, date).commit(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java index 477a5c2b6fa..5a976f2ef89 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java @@ -95,6 +95,7 @@ public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) thr String finalPath = uri.getQueryParameter("final_path"); String fallbackPath = uri.getQueryParameter("fallback"); File finalFile = new File(finalPath); + ApplicationLoader.postInitApplication(); if (AndroidUtilities.isInternalUri(Uri.fromFile(finalFile))) { throw new SecurityException("trying to read internal file"); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 589cfd66e96..6d8abd29f19 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -489,7 +489,7 @@ public void processReadMessages(final SparseLongArray inbox, final long dialog_i long messageId = inbox.get(key); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == key && messageObject.getId() <= (int) messageId) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == key && messageObject.getId() <= (int) messageId) { if (isPersonalMessage(messageObject)) { personal_count--; } @@ -599,6 +599,7 @@ public void processNewMessages(final ArrayList messageObjects, fi SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); boolean allowPinned = preferences.getBoolean("PinnedMessages", true); int popup = 0; + boolean hasScheduled = false; for (int a = 0; a < messageObjects.size(); a++) { MessageObject messageObject = messageObjects.get(a); @@ -683,6 +684,9 @@ public void processNewMessages(final ArrayList messageObjects, fi if (!isFcm) { popup = addToPopupMessages(popupArrayAdd, messageObject, lower_id, dialog_id, isChannel, preferences); } + if (!hasScheduled) { + hasScheduled = messageObject.messageOwner.from_scheduled; + } delayedPushMessages.add(messageObject); pushMessages.add(0, messageObject); if (mid != 0) { @@ -718,7 +722,7 @@ public void processNewMessages(final ArrayList messageObjects, fi } }); } - if (isFcm) { + if (isFcm || hasScheduled) { if (edited) { delayedPushMessages.clear(); showOrUpdateNotification(notifyCheck); @@ -823,7 +827,7 @@ public void processDialogsUpdateRead(final LongSparseArray dialogsToUpd pushDialogsOverrideMention.remove(dialog_id); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialog_id) { + if (!messageObject.messageOwner.from_scheduled && messageObject.getDialogId() == dialog_id) { if (isPersonalMessage(messageObject)) { personal_count--; } @@ -1531,13 +1535,14 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes text[0] = true; return (String) messageObject.messageText; } + int selfUsedId = getUserConfig().getClientUserId(); if (from_id == 0) { if (messageObject.isFromUser() || messageObject.getId() < 0) { from_id = messageObject.messageOwner.from_id; } else { from_id = -chat_id; } - } else if (from_id == getUserConfig().getClientUserId()) { + } else if (from_id == selfUsedId) { from_id = messageObject.messageOwner.from_id; } @@ -1551,9 +1556,17 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes String name = null; if (from_id > 0) { - TLRPC.User user = getMessagesController().getUser(from_id); - if (user != null) { - name = UserObject.getUserName(user); + if (messageObject.messageOwner.from_scheduled) { + if (dialog_id == selfUsedId) { + name = LocaleController.getString("MessageScheduledReminderNotification", R.string.MessageScheduledReminderNotification); + } else { + name = LocaleController.getString("NotificationMessageScheduledName", R.string.NotificationMessageScheduledName); + } + } else { + TLRPC.User user = getMessagesController().getUser(from_id); + if (user != null) { + name = UserObject.getUserName(user); + } } } else { TLRPC.Chat chat = getMessagesController().getChat(-from_id); @@ -1691,7 +1704,7 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes if (messageObject.messageOwner.to_id.channel_id != 0 && !chat.megagroup) { msg = LocaleController.formatString("ChannelAddedByNotification", R.string.ChannelAddedByNotification, name, chat.title); } else { - if (singleUserId == getUserConfig().getClientUserId()) { + if (singleUserId == selfUsedId) { msg = LocaleController.formatString("NotificationInvitedToGroup", R.string.NotificationInvitedToGroup, name, chat.title); } else { TLRPC.User u2 = getMessagesController().getUser(singleUserId); @@ -1734,7 +1747,7 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes msg = LocaleController.formatString("NotificationEditedGroupPhoto", R.string.NotificationEditedGroupPhoto, name, chat.title); } } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser) { - if (messageObject.messageOwner.action.user_id == getUserConfig().getClientUserId()) { + if (messageObject.messageOwner.action.user_id == selfUsedId) { msg = LocaleController.formatString("NotificationGroupKickYou", R.string.NotificationGroupKickYou, name, chat.title); } else if (messageObject.messageOwner.action.user_id == from_id) { msg = LocaleController.formatString("NotificationGroupLeftMember", R.string.NotificationGroupLeftMember, name, chat.title); @@ -2912,11 +2925,17 @@ private void showExtraNotifications(NotificationCompat.Builder notificationBuild return; } + SharedPreferences preferences = getAccountInstance().getNotificationsSettings(); + ArrayList sortedDialogs = new ArrayList<>(); LongSparseArray> messagesByDialogs = new LongSparseArray<>(); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); long dialog_id = messageObject.getDialogId(); + int dismissDate = preferences.getInt("dismissDate" + dialog_id, 0); + if (messageObject.messageOwner.date <= dismissDate) { + continue; + } ArrayList arrayList = messagesByDialogs.get(dialog_id); if (arrayList == null) { @@ -2958,6 +2977,8 @@ void call() { checkOtherNotificationsChannel(); } + int selfUserId = getUserConfig().getClientUserId(); + for (int b = 0, size = sortedDialogs.size(); b < size; b++) { long dialog_id = sortedDialogs.get(b); ArrayList messageObjects = messagesByDialogs.get(dialog_id); @@ -3017,6 +3038,9 @@ void call() { photoPath = user.photo.photo_small; } } + if (lowerId == selfUserId) { + name = LocaleController.getString("MessageScheduledReminderNotification", R.string.MessageScheduledReminderNotification); + } } else { chat = getMessagesController().getChat(-lowerId); if (chat == null) { @@ -3091,7 +3115,7 @@ void call() { NotificationCompat.Action wearReplyAction = null; - if ((!isChannel || isSupergroup) && canReply && !SharedConfig.isWaitingForPasscodeEnter) { + if ((!isChannel || isSupergroup) && canReply && !SharedConfig.isWaitingForPasscodeEnter && selfUserId != lowerId) { Intent replyIntent = new Intent(ApplicationLoader.applicationContext, WearReplyReceiver.class); replyIntent.putExtra("dialog_id", dialog_id); replyIntent.putExtra("max_id", max_id); @@ -3142,6 +3166,11 @@ void call() { for (int a = messageObjects.size() - 1; a >= 0; a--) { MessageObject messageObject = messageObjects.get(a); String message = getShortStringForMessage(messageObject, senderName, preview); + if (dialog_id == selfUserId) { + senderName[0] = name; + } else if (lowerId < 0 && messageObject.messageOwner.from_scheduled) { + senderName[0] = LocaleController.getString("NotificationMessageScheduledName", R.string.NotificationMessageScheduledName); + } if (message == null) { if (BuildVars.LOGS_ENABLED) { FileLog.w("message text is null for " + messageObject.getId() + " did = " + messageObject.getDialogId()); @@ -3151,10 +3180,15 @@ void call() { if (text.length() > 0) { text.append("\n\n"); } - if (senderName[0] != null) { - text.append(String.format("%1$s: %2$s", senderName[0], message)); - } else { + if (dialog_id != selfUserId && messageObject.messageOwner.from_scheduled && lowerId > 0) { + message = String.format("%1$s: %2$s", LocaleController.getString("NotificationMessageScheduledName", R.string.NotificationMessageScheduledName), message); text.append(message); + } else { + if (senderName[0] != null) { + text.append(String.format("%1$s: %2$s", senderName[0], message)); + } else { + text.append(message); + } } //unreadConvBuilder.addMessage(message); @@ -3332,7 +3366,7 @@ void call() { summaryExtender.setDismissalId("summary_" + dismissalID); notificationBuilder.extend(summaryExtender); } - wearableExtender.setBridgeTag("tgaccount" + getUserConfig().getClientUserId()); + wearableExtender.setBridgeTag("tgaccount" + selfUserId); long date = ((long) messageObjects.get(0).messageOwner.date) * 1000; @@ -3353,6 +3387,12 @@ void call() { .setSortKey("" + (Long.MAX_VALUE - date)) .setCategory(NotificationCompat.CATEGORY_MESSAGE); + Intent dismissIntent = new Intent(ApplicationLoader.applicationContext, NotificationDismissReceiver.class); + dismissIntent.putExtra("messageDate", max_date); + dismissIntent.putExtra("dialogId", dialog_id); + dismissIntent.putExtra("currentAccount", currentAccount); + builder.setDeleteIntent(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 1, dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); + if (useSummaryNotification) { builder.setGroup(notificationGroup); builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY); @@ -3457,7 +3497,7 @@ void call() { if (serializedNotifications != null) { try { JSONObject s = new JSONObject(); - s.put("id", getUserConfig().getClientUserId()); + s.put("id", selfUserId); s.put("n", serializedNotifications); WearDataLayerListenerService.sendMessageToWatch("/notify", s.toString().getBytes(), "remote_notifications"); } catch (Exception ignore) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java index 630b5f60c58..61001488f9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java @@ -17,6 +17,7 @@ public class NotificationsService extends Service { @Override public void onCreate() { + super.onCreate(); ApplicationLoader.postInitApplication(); } @@ -31,6 +32,7 @@ public IBinder onBind(Intent intent) { } public void onDestroy() { + super.onDestroy(); SharedPreferences preferences = MessagesController.getGlobalNotificationsSettings(); if (preferences.getBoolean("pushService", true)) { Intent intent = new Intent("org.telegram.start"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index f3424d3ba81..2cca876ae5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -146,7 +146,7 @@ private TLRPC.TL_messageService createServiceSecretMessage(final TLRPC.Encrypted ArrayList arr = new ArrayList<>(); arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, true, 0); + getMessagesStorage().putMessages(arr, false, true, true, 0, false); return newMsg; } @@ -427,7 +427,7 @@ public void sendTTLMessage(TLRPC.EncryptedChat encryptedChat, TLRPC.Message rese newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; ArrayList objArr = new ArrayList<>(); objArr.add(newMsgObj); - getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr); + getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); } reqSend.random_id = message.random_id; @@ -456,7 +456,7 @@ public void sendScreenshotMessage(TLRPC.EncryptedChat encryptedChat, ArrayList objArr = new ArrayList<>(); objArr.add(newMsgObj); - getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr); + getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); } reqSend.random_id = message.random_id; @@ -484,7 +484,7 @@ private void updateMediaPaths(MessageObject newMsgObj, TLRPC.EncryptedFile file, ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForPhoto(size, newMsg.media.photo), true); ArrayList arr = new ArrayList<>(); arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, false); //getMessagesStorage().putSentFile(originalPath, newMsg.media.photo, 3); } else if (newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { @@ -518,7 +518,7 @@ private void updateMediaPaths(MessageObject newMsgObj, TLRPC.EncryptedFile file, ArrayList arr = new ArrayList<>(); arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, false); } } } @@ -541,7 +541,7 @@ protected void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, fin if (req == null || chat.auth_key == null || chat instanceof TLRPC.TL_encryptedChatRequested || chat instanceof TLRPC.TL_encryptedChatWaiting) { return; } - getSendMessagesHelper().putToSendingMessages(newMsgObj); + getSendMessagesHelper().putToSendingMessages(newMsgObj, false); Utilities.stageQueue.postRunnable(() -> { try { TLObject toEncryptObject; @@ -714,19 +714,19 @@ protected void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, fin if (isSecretInvisibleMessage(newMsgObj)) { res.date = 0; } - getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, newMsgObj.id, newMsgObj.id, res.date, false, 0); + getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, newMsgObj.id, newMsgObj.id, res.date, false, 0, 0); AndroidUtilities.runOnUIThread(() -> { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); getSendMessagesHelper().processSentMessage(newMsgObj.id); if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj)) { getSendMessagesHelper().stopVideoService(attachPath); } - getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id); + getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); }); } else { - getMessagesStorage().markMessageAsSendError(newMsgObj); + getMessagesStorage().markMessageAsSendError(newMsgObj, false); AndroidUtilities.runOnUIThread(() -> { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); @@ -734,7 +734,7 @@ protected void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, fin if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj)) { getSendMessagesHelper().stopVideoService(newMsgObj.attachPath); } - getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id); + getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); } } @@ -1370,7 +1370,7 @@ private void resendMessages(final int startSeq, final int endSeq, final TLRPC.En } }); - getSendMessagesHelper().processUnsentMessages(messages, new ArrayList<>(), new ArrayList<>(), encryptedChats); + getSendMessagesHelper().processUnsentMessages(messages, null, new ArrayList<>(), new ArrayList<>(), encryptedChats); getMessagesStorage().getDatabase().executeFast(String.format(Locale.US, "REPLACE INTO requested_holes VALUES(%d, %d, %d)", encryptedChat.id, sSeq, endSeq)).stepThis().dispose(); } catch (Exception e) { FileLog.e(e); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index eba81ed71e3..c9f8ed7b190 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -31,7 +31,6 @@ import android.util.Base64; import android.util.LongSparseArray; import android.util.SparseArray; -import android.util.SparseIntArray; import android.webkit.MimeTypeMap; import android.widget.Toast; @@ -65,7 +64,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCenter.NotificationCenterDelegate { - private TLRPC.ChatFull currentChatInfo = null; private HashMap> delayedMessages = new HashMap<>(); private SparseArray unsentMessages = new SparseArray<>(); private SparseArray sendingMessages = new SparseArray<>(); @@ -121,6 +119,8 @@ public static class SendingMediaInfo { public ArrayList masks; public VideoEditedInfo videoEditedInfo; public MediaController.SearchImage searchImage; + public TLRPC.BotInlineResult inlineResult; + public HashMap params; public boolean isVideo; public boolean canDeleteAfter; } @@ -261,6 +261,7 @@ protected class DelayedMessageSendAfterRequest { public ArrayList parentObjects; public DelayedMessage delayedMessage; public Object parentObject; + public boolean scheduled; } protected class DelayedMessage { @@ -293,6 +294,7 @@ protected class DelayedMessage { public HashMap extraHashMap; public long groupId; public int finalGroupMessage; + public boolean scheduled; public Object parentObject; @@ -314,26 +316,28 @@ public void initForGroup(long id) { videoEditedInfos = new ArrayList<>(); } - public void addDelayedRequest(final TLObject req, final MessageObject msgObj, final String originalPath, Object parentObject, DelayedMessage delayedMessage) { + public void addDelayedRequest(final TLObject req, final MessageObject msgObj, final String originalPath, Object parentObject, DelayedMessage delayedMessage, boolean scheduled) { DelayedMessageSendAfterRequest request = new DelayedMessageSendAfterRequest(); request.request = req; request.msgObj = msgObj; request.originalPath = originalPath; request.delayedMessage = delayedMessage; request.parentObject = parentObject; + request.scheduled = scheduled; if (requests == null) { requests = new ArrayList<>(); } requests.add(request); } - public void addDelayedRequest(final TLObject req, final ArrayList msgObjs, final ArrayList originalPaths, ArrayList parentObjects, DelayedMessage delayedMessage) { + public void addDelayedRequest(final TLObject req, final ArrayList msgObjs, final ArrayList originalPaths, ArrayList parentObjects, DelayedMessage delayedMessage, boolean scheduled) { DelayedMessageSendAfterRequest request = new DelayedMessageSendAfterRequest(); request.request = req; request.msgObjs = msgObjs; request.originalPaths = originalPaths; request.delayedMessage = delayedMessage; request.parentObjects = parentObjects; + request.scheduled = scheduled; if (requests == null) { requests = new ArrayList<>(); } @@ -350,9 +354,9 @@ public void sendDelayedRequests() { if (request.request instanceof TLRPC.TL_messages_sendEncryptedMultiMedia) { getSecretChatHelper().performSendEncryptedRequest((TLRPC.TL_messages_sendEncryptedMultiMedia) request.request, this); } else if (request.request instanceof TLRPC.TL_messages_sendMultiMedia) { - performSendMessageRequestMulti((TLRPC.TL_messages_sendMultiMedia) request.request, request.msgObjs, request.originalPaths, request.parentObjects, request.delayedMessage); + performSendMessageRequestMulti((TLRPC.TL_messages_sendMultiMedia) request.request, request.msgObjs, request.originalPaths, request.parentObjects, request.delayedMessage, request.scheduled); } else { - performSendMessageRequest(request.request, request.msgObj, request.originalPath, request.delayedMessage, request.parentObject); + performSendMessageRequest(request.request, request.msgObj, request.originalPath, request.delayedMessage, request.parentObject, request.scheduled); } } requests = null; @@ -362,19 +366,19 @@ public void markAsError() { if (type == 4) { for (int a = 0; a < messageObjects.size(); a++) { MessageObject obj = messageObjects.get(a); - getMessagesStorage().markMessageAsSendError(obj.messageOwner); + getMessagesStorage().markMessageAsSendError(obj.messageOwner, obj.scheduled); obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId()); processSentMessage(obj.getId()); - removeFromUploadingMessages(obj.getId()); + removeFromUploadingMessages(obj.getId(), scheduled); } delayedMessages.remove( "group_" + groupId); } else { - getMessagesStorage().markMessageAsSendError(obj.messageOwner); + getMessagesStorage().markMessageAsSendError(obj.messageOwner, obj.scheduled); obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId()); processSentMessage(obj.getId()); - removeFromUploadingMessages(obj.getId()); + removeFromUploadingMessages(obj.getId(), scheduled); } sendDelayedRequests(); } @@ -406,7 +410,7 @@ public SendMessagesHelper(int instance) { getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.httpFileDidFailedLoad); getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.httpFileDidLoad); getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.fileDidLoad); - getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.fileDidFailedLoad); + getNotificationCenter().addObserver(SendMessagesHelper.this, NotificationCenter.fileDidFailToLoad); }); } @@ -421,14 +425,9 @@ public void cleanup() { waitingForLocation.clear(); waitingForCallback.clear(); waitingForVote.clear(); - currentChatInfo = null; locationProvider.stop(); } - public void setCurrentChatInfo(TLRPC.ChatFull info) { - currentChatInfo = info; - } - @Override public void didReceivedNotification(int id, int account, final Object... args) { if (id == NotificationCenter.FileDidUpload) { @@ -444,8 +443,6 @@ public void didReceivedNotification(int id, int account, final Object... args) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; } else if (message.sendRequest instanceof TLRPC.TL_messages_editMessage) { media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) { - media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; } else if (message.sendRequest instanceof TLRPC.TL_messages_sendMultiMedia) { media = (TLRPC.InputMedia) message.extraHashMap.get(location); } @@ -453,19 +450,19 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (file != null && media != null) { if (message.type == 0) { media.file = file; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, message, true, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, message, true, null, message.parentObject, message.scheduled); } else if (message.type == 1) { if (media.file == null) { media.file = file; if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); } } else { media.thumb = file; media.flags |= 4; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); } } else if (message.type == 2) { if (media.file == null) { @@ -473,16 +470,16 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); } } else { media.thumb = file; media.flags |= 4; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); } } else if (message.type == 3) { media.file = file; - performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); + performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject, message.scheduled); } else if (message.type == 4) { if (media instanceof TLRPC.TL_inputMediaUploadedDocument) { if (media.file == null) { @@ -622,7 +619,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { ArrayList messages = new ArrayList<>(); messages.add(obj.messageOwner); - getMessagesStorage().putMessages(messages, false, true, false, 0); + getMessagesStorage().putMessages(messages, false, true, false, 0, obj.scheduled); break; } } @@ -633,7 +630,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { ArrayList messages = new ArrayList<>(); messages.add(message.obj.messageOwner); - getMessagesStorage().putMessages(messages, false, true, false, 0); + getMessagesStorage().putMessages(messages, false, true, false, 0, message.obj.scheduled); break; } } @@ -705,7 +702,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { messageObject.messageOwner.attachPath = cacheFile.toString(); ArrayList messages = new ArrayList<>(); messages.add(messageObject.messageOwner); - getMessagesStorage().putMessages(messages, false, true, false, 0); + getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled); getNotificationCenter().postNotificationName(NotificationCenter.updateMessageMedia, messageObject.messageOwner); message.photoSize = photo.sizes.get(photo.sizes.size() - 1); message.locationParent = photo; @@ -751,7 +748,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } ArrayList messages = new ArrayList<>(); messages.add(messageObject.messageOwner); - getMessagesStorage().putMessages(messages, false, true, false, 0); + getMessagesStorage().putMessages(messages, false, true, false, 0, messageObject.scheduled); message.performMediaUpload = true; performSendDelayedMessage(message); getNotificationCenter().postNotificationName(NotificationCenter.updateMessageMedia, message.obj.messageOwner); @@ -770,7 +767,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } delayedMessages.remove(path); } - } else if (id == NotificationCenter.httpFileDidFailedLoad || id == NotificationCenter.fileDidFailedLoad) { + } else if (id == NotificationCenter.httpFileDidFailedLoad || id == NotificationCenter.fileDidFailToLoad) { String path = (String) args[0]; ArrayList arr = delayedMessages.get(path); @@ -803,7 +800,7 @@ private void revertEditingMessageObject(MessageObject object) { ArrayList arr = new ArrayList<>(); arr.add(object.messageOwner); - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, object.scheduled); ArrayList arrayList = new ArrayList<>(); arrayList.add(object); @@ -822,11 +819,17 @@ public void cancelSendingMessage(ArrayList objects) { ArrayList messageIds = new ArrayList<>(); boolean enc = false; int channelId = 0; + boolean scheduled = false; + long scheduledDialogId = 0; for (int c = 0; c < objects.size(); c++) { MessageObject object = objects.get(c); + if (object.scheduled) { + scheduled = true; + scheduledDialogId = object.getDialogId(); + } messageIds.add(object.getId()); channelId = object.messageOwner.to_id.channel_id; - TLRPC.Message sendingMessage = removeFromSendingMessages(object.getId()); + TLRPC.Message sendingMessage = removeFromSendingMessages(object.getId(), object.scheduled); if (sendingMessage != null) { getConnectionsManager().cancelRequest(sendingMessage.reqId, true); } @@ -842,7 +845,7 @@ public void cancelSendingMessage(ArrayList objects) { messageObject = message.messageObjects.get(b); if (messageObject.getId() == object.getId()) { index = b; - removeFromUploadingMessages(object.getId()); + removeFromUploadingMessages(object.getId(), object.scheduled); break; } } @@ -874,7 +877,7 @@ public void cancelSendingMessage(ArrayList objects) { TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); messagesRes.messages.add(prevMessage.messageOwner); - getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false); + getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduled); } if (!checkReadyToSendGroups.contains(message)) { checkReadyToSendGroups.add(message); @@ -883,7 +886,7 @@ public void cancelSendingMessage(ArrayList objects) { } break; } else if (message.obj.getId() == object.getId()) { - removeFromUploadingMessages(object.getId()); + removeFromUploadingMessages(object.getId(), object.scheduled); messages.remove(a); message.sendDelayedRequests(); MediaController.getInstance().cancelVideoConvert(message.obj); @@ -914,7 +917,7 @@ public void cancelSendingMessage(ArrayList objects) { if (objects.size() == 1 && objects.get(0).isEditing() && objects.get(0).previousMedia != null) { revertEditingMessageObject(objects.get(0)); } else { - getMessagesController().deleteMessages(messageIds, null, null, channelId, false); + getMessagesController().deleteMessages(messageIds, null, null, scheduledDialogId, channelId, false, scheduled); } } @@ -929,7 +932,7 @@ public boolean retrySendMessage(MessageObject messageObject, boolean unsent) { int enc_id = (int) (messageObject.getDialogId() >> 32); TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(enc_id); if (encryptedChat == null) { - getMessagesStorage().markMessageAsSendError(messageObject.messageOwner); + getMessagesStorage().markMessageAsSendError(messageObject.messageOwner, messageObject.scheduled); messageObject.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, messageObject.getId()); processSentMessage(messageObject.getId()); @@ -996,22 +999,22 @@ public void processForwardFromMyName(MessageObject messageObject, long did) { params.put("parentObject", "sent_" + messageObject.messageOwner.to_id.channel_id + "_" + messageObject.getId()); } if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo) { - sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, messageObject.messageOwner.media.ttl_seconds, messageObject); + sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject); } else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) { - sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, messageObject.messageOwner.media.ttl_seconds, messageObject); + sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) { - sendMessage(messageObject.messageOwner.media, did, messageObject.replyMessageObject, null, null); + sendMessage(messageObject.messageOwner.media, did, messageObject.replyMessageObject, null, null, true, 0); } else if (messageObject.messageOwner.media.phone_number != null) { TLRPC.User user = new TLRPC.TL_userContact_old2(); user.phone = messageObject.messageOwner.media.phone_number; user.first_name = messageObject.messageOwner.media.first_name; user.last_name = messageObject.messageOwner.media.last_name; user.id = messageObject.messageOwner.media.user_id; - sendMessage(user, did, messageObject.replyMessageObject, null, null); + sendMessage(user, did, messageObject.replyMessageObject, null, null, true, 0); } else if ((int) did != 0) { ArrayList arrayList = new ArrayList<>(); arrayList.add(messageObject); - sendMessage(arrayList, did); + sendMessage(arrayList, did, true, 0); } } else if (messageObject.messageOwner.message != null) { TLRPC.WebPage webPage = null; @@ -1034,11 +1037,11 @@ public void processForwardFromMyName(MessageObject messageObject, long did) { } else { entities = null; } - sendMessage(messageObject.messageOwner.message, did, messageObject.replyMessageObject, webPage, true, entities, null, null); + sendMessage(messageObject.messageOwner.message, did, messageObject.replyMessageObject, webPage, true, entities, null, null, true, 0); } else if ((int) did != 0) { ArrayList arrayList = new ArrayList<>(); arrayList.add(messageObject); - sendMessage(arrayList, did); + sendMessage(arrayList, did, true, 0); } } @@ -1079,16 +1082,16 @@ public void sendScreenshotMessage(TLRPC.User user, int messageId, TLRPC.Message newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; ArrayList objArr = new ArrayList<>(); objArr.add(newMsgObj); - getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr); + getMessagesController().updateInterfaceWithMessages(message.dialog_id, objArr, false); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); ArrayList arr = new ArrayList<>(); arr.add(message); - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, false); - performSendMessageRequest(req, newMsgObj, null, null, null); + performSendMessageRequest(req, newMsgObj, null, null, null, false); } - public void sendSticker(TLRPC.Document document, long peer, MessageObject replyingMessageObject, Object parentObject) { + public void sendSticker(TLRPC.Document document, long peer, MessageObject replyingMessageObject, Object parentObject, boolean notify, int scheduleDate) { if (document == null) { return; } @@ -1150,11 +1153,11 @@ public void sendSticker(TLRPC.Document document, long peer, MessageObject replyi document = newDocument; } if (document instanceof TLRPC.TL_document) { - sendMessage((TLRPC.TL_document) document, null, null, peer, replyingMessageObject, null, null, null, null, 0, parentObject); + sendMessage((TLRPC.TL_document) document, null, null, peer, replyingMessageObject, null, null, null, null, notify, scheduleDate, 0, parentObject); } } - public int sendMessage(ArrayList messages, final long peer) { + public int sendMessage(ArrayList messages, final long peer, boolean notify, int scheduleDate) { if (messages == null || messages.isEmpty()) { return 0; } @@ -1203,7 +1206,7 @@ public int sendMessage(ArrayList messages, final long peer) { if (msgObj.getId() <= 0 || msgObj.needDrawBluredPreview()) { if (msgObj.type == 0 && !TextUtils.isEmpty(msgObj.messageText)) { TLRPC.WebPage webPage = msgObj.messageOwner.media != null ? msgObj.messageOwner.media.webpage : null; - sendMessage(msgObj.messageText.toString(), peer, null, webPage, webPage != null, msgObj.messageOwner.entities, null, null); + sendMessage(msgObj.messageText.toString(), peer, null, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate); } continue; } @@ -1355,14 +1358,18 @@ public int sendMessage(ArrayList messages, final long peer) { randomIds.add(newMsg.random_id); messagesByRandomIds.put(newMsg.random_id, newMsg); ids.add(newMsg.fwd_msg_id); - newMsg.date = getConnectionsManager().getCurrentTime(); + newMsg.date = scheduleDate != 0 ? scheduleDate : getConnectionsManager().getCurrentTime(); if (inputPeer instanceof TLRPC.TL_inputPeerChannel && !isMegagroup) { - newMsg.views = 1; - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; + if (scheduleDate == 0) { + newMsg.views = 1; + newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; + } } else { if ((msgObj.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - newMsg.views = msgObj.messageOwner.views; - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; + if (scheduleDate == 0) { + newMsg.views = msgObj.messageOwner.views; + newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; + } } newMsg.unread = true; } @@ -1379,11 +1386,12 @@ public int sendMessage(ArrayList messages, final long peer) { newMsg.ttl = -msgObj.messageOwner.to_id.channel_id; } MessageObject newMsgObj = new MessageObject(currentAccount, newMsg, true); + newMsgObj.scheduled = scheduleDate != 0; newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; objArr.add(newMsgObj); arr.add(newMsg); - putToSendingMessages(newMsg); + putToSendingMessages(newMsg, scheduleDate != 0); boolean differentDialog = false; if (BuildVars.LOGS_ENABLED) { @@ -1391,15 +1399,19 @@ public int sendMessage(ArrayList messages, final long peer) { } if (groupedIdChanged && arr.size() > 0 || arr.size() == 100 || a == messages.size() - 1 || a != messages.size() - 1 && messages.get(a + 1).getDialogId() != msgObj.getDialogId()) { - getMessagesStorage().putMessages(new ArrayList<>(arr), false, true, false, 0); - getMessagesController().updateInterfaceWithMessages(peer, objArr); + getMessagesStorage().putMessages(new ArrayList<>(arr), false, true, false, 0, scheduleDate != 0); + getMessagesController().updateInterfaceWithMessages(peer, objArr, scheduleDate != 0); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); getUserConfig().saveConfig(false); final TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages(); req.to_peer = inputPeer; req.grouped = lastGroupedId != 0; - req.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + req.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + if (scheduleDate != 0) { + req.schedule_date = scheduleDate; + req.flags |= 1024; + } if (msgObj.messageOwner.to_id instanceof TLRPC.TL_peerChannel) { TLRPC.Chat channel = getMessagesController().getChat(msgObj.messageOwner.to_id.channel_id); req.from_peer = new TLRPC.TL_inputPeerChannel(); @@ -1432,15 +1444,19 @@ public int sendMessage(ArrayList messages, final long peer) { } } Integer value = getMessagesController().dialogs_read_outbox_max.get(peer); - if (value == null) { - value = getMessagesStorage().getDialogReadMax(true, peer); - getMessagesController().dialogs_read_outbox_max.put(peer, value); + if (scheduleDate == 0) { + if (value == null) { + value = getMessagesStorage().getDialogReadMax(true, peer); + getMessagesController().dialogs_read_outbox_max.put(peer, value); + } + } else { + value = 0; } int sentCount = 0; for (int a1 = 0; a1 < updates.updates.size(); a1++) { TLRPC.Update update = updates.updates.get(a1); - if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateNewChannelMessage) { + if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateNewChannelMessage || update instanceof TLRPC.TL_updateNewScheduledMessage) { updates.updates.remove(a1); a1--; final TLRPC.Message message; @@ -1448,6 +1464,9 @@ public int sendMessage(ArrayList messages, final long peer) { TLRPC.TL_updateNewMessage updateNewMessage = (TLRPC.TL_updateNewMessage) update; message = updateNewMessage.message; getMessagesController().processNewDifferenceParams(-1, updateNewMessage.pts, -1, updateNewMessage.pts_count); + } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { + TLRPC.TL_updateNewScheduledMessage updateNewMessage = (TLRPC.TL_updateNewScheduledMessage) update; + message = updateNewMessage.message; } else { TLRPC.TL_updateNewChannelMessage updateNewChannelMessage = (TLRPC.TL_updateNewChannelMessage) update; message = updateNewChannelMessage.message; @@ -1457,7 +1476,9 @@ public int sendMessage(ArrayList messages, final long peer) { } } ImageLoader.saveMessageThumbs(message); - message.unread = value < message.id; + if (scheduleDate == 0) { + message.unread = value < message.id; + } if (toMyself) { message.out = true; message.unread = false; @@ -1485,14 +1506,14 @@ public int sendMessage(ArrayList messages, final long peer) { newMsgObj1.id = message.id; sentCount++; getMessagesStorage().getStorageQueue().postRunnable(() -> { - getMessagesStorage().updateMessageStateAndId(newMsgObj1.random_id, oldId, newMsgObj1.id, 0, false, to_id.channel_id); - getMessagesStorage().putMessages(sentMessages, true, false, false, 0); + getMessagesStorage().updateMessageStateAndId(newMsgObj1.random_id, oldId, newMsgObj1.id, 0, false, to_id.channel_id, scheduleDate != 0 ? 1 : 0); + getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduleDate != 0); AndroidUtilities.runOnUIThread(() -> { newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getMediaDataController().increasePeerRaiting(peer); - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, message.id, message, peer, 0L, existFlags, scheduleDate != 0); processSentMessage(oldId); - removeFromSendingMessages(oldId); + removeFromSendingMessages(oldId, scheduleDate != 0); }); }); } @@ -1507,12 +1528,12 @@ public int sendMessage(ArrayList messages, final long peer) { } for (int a1 = 0; a1 < newMsgObjArr.size(); a1++) { final TLRPC.Message newMsgObj1 = newMsgObjArr.get(a1); - getMessagesStorage().markMessageAsSendError(newMsgObj1); + getMessagesStorage().markMessageAsSendError(newMsgObj1, scheduleDate != 0); AndroidUtilities.runOnUIThread(() -> { newMsgObj1.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj1.id); processSentMessage(newMsgObj1.id); - removeFromSendingMessages(newMsgObj1.id); + removeFromSendingMessages(newMsgObj1.id, scheduleDate != 0); }); } }, ConnectionsManager.RequestFlagCanCompress | ConnectionsManager.RequestFlagInvokeAfter); @@ -1650,7 +1671,7 @@ private void editMessageMedia(MessageObject messageObject, TLRPC.TL_photo photo, ArrayList arr = new ArrayList<>(); arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, false, 0); + getMessagesStorage().putMessages(arr, false, true, false, 0, messageObject.scheduled); messageObject.type = -1; messageObject.setType(); @@ -1751,19 +1772,7 @@ private void editMessageMedia(MessageObject messageObject, TLRPC.TL_photo photo, delayedMessage.videoEditedInfo = videoEditedInfo; } else if (type == 7) { boolean http = false; - TLRPC.InputMedia uploadedDocument; - if (originalPath != null && originalPath.length() > 0 && originalPath.startsWith("http") && params != null) { - http = true; - TLRPC.TL_inputMediaGifExternal gifExternal = new TLRPC.TL_inputMediaGifExternal(); - String args[] = params.get("url").split("\\|"); - if (args.length == 2) { - gifExternal.url = args[0]; - gifExternal.q = args[1]; - } - uploadedDocument = gifExternal; - } else { - uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); - } + TLRPC.InputMedia uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); uploadedDocument.mime_type = document.mime_type; uploadedDocument.attributes = document.attributes; @@ -1803,6 +1812,10 @@ private void editMessageMedia(MessageObject messageObject, TLRPC.TL_photo photo, request.peer = getMessagesController().getInputPeer((int) peer); request.flags |= 16384; request.media = inputMedia; + if (messageObject.scheduled) { + request.schedule_date = messageObject.messageOwner.date; + request.flags |= 32768; + } if (messageObject.editingMessage != null) { request.message = messageObject.editingMessage.toString(); @@ -1828,32 +1841,32 @@ private void editMessageMedia(MessageObject messageObject, TLRPC.TL_photo photo, reqSend = request; if (type == 1) { - performSendMessageRequest(reqSend, messageObject, null, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, null, delayedMessage, parentObject, messageObject.scheduled); } else if (type == 2) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, null, true, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, originalPath, null, true, delayedMessage, parentObject, messageObject.scheduled); } } else if (type == 3) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); } } else if (type == 6) { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); } else if (type == 7) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); } } else if (type == 8) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, messageObject, originalPath, delayedMessage, parentObject, messageObject.scheduled); } } } @@ -1863,28 +1876,36 @@ private void editMessageMedia(MessageObject messageObject, TLRPC.TL_photo photo, } } - public int editMessage(MessageObject messageObject, String message, boolean searchLinks, final BaseFragment fragment, ArrayList entities, final Runnable callback) { - if (fragment == null || fragment.getParentActivity() == null || callback == null) { + public int editMessage(MessageObject messageObject, String message, boolean searchLinks, final BaseFragment fragment, ArrayList entities, int scheduleDate, final Runnable callback) { + if (fragment == null || fragment.getParentActivity() == null) { return 0; } final TLRPC.TL_messages_editMessage req = new TLRPC.TL_messages_editMessage(); req.peer = getMessagesController().getInputPeer((int) messageObject.getDialogId()); - req.message = message; - req.flags |= 2048; + if (message != null) { + req.message = message; + req.flags |= 2048; + req.no_webpage = !searchLinks; + } req.id = messageObject.getId(); - req.no_webpage = !searchLinks; if (entities != null) { req.entities = entities; req.flags |= 8; } + if (scheduleDate != 0) { + req.schedule_date = scheduleDate; + req.flags |= 32768; + } return getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { getMessagesController().processUpdates((TLRPC.Updates) response, false); } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, fragment, req)); } - AndroidUtilities.runOnUIThread(callback); + if (callback != null) { + AndroidUtilities.runOnUIThread(callback); + } }); } @@ -1895,7 +1916,7 @@ private void sendLocation(Location location) { mediaGeo.geo._long = AndroidUtilities.fixLocationCoord(location.getLongitude()); for (HashMap.Entry entry : waitingForLocation.entrySet()) { MessageObject messageObject = entry.getValue(); - sendMessage(mediaGeo, messageObject.getDialogId(), messageObject, null, null); + sendMessage(mediaGeo, messageObject.getDialogId(), messageObject, null, null, true, 0); } } @@ -1949,7 +1970,7 @@ public void sendNotificationCallback(final long dialogId, final int msgId, final req.data = data; } getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> waitingForCallback.remove(key)), ConnectionsManager.RequestFlagFailOnServerErrors); - getMessagesController().markDialogAsRead(dialogId, msgId, msgId, 0, false, 0, true); + getMessagesController().markDialogAsRead(dialogId, msgId, msgId, 0, false, 0, true, 0); }); } @@ -1998,6 +2019,33 @@ protected long getVoteSendTime(long pollId) { return voteSendTime.get(pollId, 0L); } + public void sendReaction(final MessageObject messageObject, CharSequence reaction, final ChatActivity parentFragment) { + if (messageObject == null || parentFragment == null) { + return; + } + TLRPC.TL_messages_sendReaction req = new TLRPC.TL_messages_sendReaction(); + req.peer = getMessagesController().getInputPeer((int) messageObject.getDialogId()); + req.msg_id = messageObject.getId(); + if (reaction != null) { + req.reaction = reaction.toString(); + req.flags |= 1; + } + getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + getMessagesController().processUpdates((TLRPC.Updates) response, false); + } + /*AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + waitingForVote.remove(key); + if (finishRunnable != null) { + finishRunnable.run(); + } + } + });*/ + }); + } + public void sendCallback(final boolean cache, final MessageObject messageObject, final TLRPC.KeyboardButton button, final ChatActivity parentFragment) { if (messageObject == null || button == null || parentFragment == null) { return; @@ -2201,38 +2249,38 @@ public void sendGame(TLRPC.InputPeer peer, TLRPC.TL_inputMediaGame game, long ra } public void sendMessage(MessageObject retryMessageObject) { - sendMessage(null, null, null, null, null, null, null, null, null, retryMessageObject.getDialogId(), retryMessageObject.messageOwner.attachPath, null, null, true, retryMessageObject, null, retryMessageObject.messageOwner.reply_markup, retryMessageObject.messageOwner.params, 0, null); + sendMessage(null, null, null, null, null, null, null, null, null, retryMessageObject.getDialogId(), retryMessageObject.messageOwner.attachPath, null, null, true, retryMessageObject, null, retryMessageObject.messageOwner.reply_markup, retryMessageObject.messageOwner.params, !retryMessageObject.messageOwner.silent, retryMessageObject.scheduled ? retryMessageObject.messageOwner.date : 0, 0, null); } - public void sendMessage(TLRPC.User user, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params) { - sendMessage(null, null, null, null, null, user, null, null, null, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, 0, null); + public void sendMessage(TLRPC.User user, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate) { + sendMessage(null, null, null, null, null, user, null, null, null, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null); } - public void sendMessage(TLRPC.TL_document document, VideoEditedInfo videoEditedInfo, String path, long peer, MessageObject reply_to_msg, String caption, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, int ttl, Object parentObject) { - sendMessage(null, caption, null, null, videoEditedInfo, null, document, null, null, peer, path, reply_to_msg, null, true, null, entities, replyMarkup, params, ttl, parentObject); + public void sendMessage(TLRPC.TL_document document, VideoEditedInfo videoEditedInfo, String path, long peer, MessageObject reply_to_msg, String caption, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate, int ttl, Object parentObject) { + sendMessage(null, caption, null, null, videoEditedInfo, null, document, null, null, peer, path, reply_to_msg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject); } - public void sendMessage(String message, long peer, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params) { - sendMessage(message, null, null, null, null, null, null, null, null, peer, null, reply_to_msg, webPage, searchLinks, null, entities, replyMarkup, params, 0, null); + public void sendMessage(String message, long peer, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate) { + sendMessage(message, null, null, null, null, null, null, null, null, peer, null, reply_to_msg, webPage, searchLinks, null, entities, replyMarkup, params, notify, scheduleDate, 0, null); } - public void sendMessage(TLRPC.MessageMedia location, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params) { - sendMessage(null, null, location, null, null, null, null, null, null, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, 0, null); + public void sendMessage(TLRPC.MessageMedia location, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate) { + sendMessage(null, null, location, null, null, null, null, null, null, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null); } - public void sendMessage(TLRPC.TL_messageMediaPoll poll, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params) { - sendMessage(null, null, null, null, null, null, null, null, poll, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, 0, null); + public void sendMessage(TLRPC.TL_messageMediaPoll poll, long peer, MessageObject reply_to_msg, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate) { + sendMessage(null, null, null, null, null, null, null, null, poll, peer, null, reply_to_msg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null); } - public void sendMessage(TLRPC.TL_game game, long peer, TLRPC.ReplyMarkup replyMarkup, HashMap params) { - sendMessage(null, null, null, null, null, null, null, game, null, peer, null, null, null, true, null, null, replyMarkup, params, 0, null); + public void sendMessage(TLRPC.TL_game game, long peer, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate) { + sendMessage(null, null, null, null, null, null, null, game, null, peer, null, null, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null); } - public void sendMessage(TLRPC.TL_photo photo, String path, long peer, MessageObject reply_to_msg, String caption, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, int ttl, Object parentObject) { - sendMessage(null, caption, null, photo, null, null, null, null, null, peer, path, reply_to_msg, null, true, null, entities, replyMarkup, params, ttl, parentObject); + public void sendMessage(TLRPC.TL_photo photo, String path, long peer, MessageObject reply_to_msg, String caption, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate, int ttl, Object parentObject) { + sendMessage(null, caption, null, photo, null, null, null, null, null, peer, path, reply_to_msg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject); } - private void sendMessage(String message, String caption, TLRPC.MessageMedia location, TLRPC.TL_photo photo, VideoEditedInfo videoEditedInfo, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_game game, TLRPC.TL_messageMediaPoll poll, long peer, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, MessageObject retryMessageObject, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, int ttl, Object parentObject) { + private void sendMessage(String message, String caption, TLRPC.MessageMedia location, TLRPC.TL_photo photo, VideoEditedInfo videoEditedInfo, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_game game, TLRPC.TL_messageMediaPoll poll, long peer, String path, MessageObject reply_to_msg, TLRPC.WebPage webPage, boolean searchLinks, MessageObject retryMessageObject, ArrayList entities, TLRPC.ReplyMarkup replyMarkup, HashMap params, boolean notify, int scheduleDate, int ttl, Object parentObject) { if (user != null && user.phone == null) { return; } @@ -2257,12 +2305,11 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca boolean isChannel = false; TLRPC.EncryptedChat encryptedChat = null; TLRPC.InputPeer sendToPeer = lower_id != 0 ? getMessagesController().getInputPeer(lower_id) : null; - ArrayList sendToPeers = null; if (lower_id == 0) { encryptedChat = getMessagesController().getEncryptedChat(high_id); if (encryptedChat == null) { if (retryMessageObject != null) { - getMessagesStorage().markMessageAsSendError(retryMessageObject.messageOwner); + getMessagesStorage().markMessageAsSendError(retryMessageObject.messageOwner, retryMessageObject.scheduled); retryMessageObject.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, retryMessageObject.getId()); processSentMessage(retryMessageObject.getId()); @@ -2301,7 +2348,11 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca user.phone = newMsg.media.phone_number; user.first_name = newMsg.media.first_name; user.last_name = newMsg.media.last_name; - user.restriction_reason = newMsg.media.vcard; + TLRPC.TL_restrictionReason reason = new TLRPC.TL_restrictionReason(); + reason.platform = ""; + reason.reason = ""; + reason.text = newMsg.media.vcard; + user.restriction_reason.add(reason); user.id = newMsg.media.user_id; type = 6; } else if (retryMessageObject.type == 8 || retryMessageObject.type == 9 || retryMessageObject.type == MessageObject.TYPE_STICKER || retryMessageObject.type == 14 || retryMessageObject.type == MessageObject.TYPE_ANIMATED_STICKER) { @@ -2414,8 +2465,8 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca newMsg.media.first_name = user.first_name; newMsg.media.last_name = user.last_name; newMsg.media.user_id = user.id; - if (user.restriction_reason != null && user.restriction_reason.startsWith("BEGIN:VCARD")) { - newMsg.media.vcard = user.restriction_reason; + if (!user.restriction_reason.isEmpty() && user.restriction_reason.get(0).text.startsWith("BEGIN:VCARD")) { + newMsg.media.vcard = user.restriction_reason.get(0).text; } else { newMsg.media.vcard = ""; } @@ -2531,9 +2582,9 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca } newMsg.params = params; if (retryMessageObject == null || !retryMessageObject.resendAsIs) { - newMsg.date = getConnectionsManager().getCurrentTime(); + newMsg.date = scheduleDate != 0 ? scheduleDate : getConnectionsManager().getCurrentTime(); if (sendToPeer instanceof TLRPC.TL_inputPeerChannel) { - if (isChannel) { + if (scheduleDate == 0 && isChannel) { newMsg.views = 1; newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; } @@ -2569,34 +2620,15 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca newMsg.reply_markup = replyMarkup; } if (lower_id != 0) { - if (high_id == 1) { - if (currentChatInfo == null) { - getMessagesStorage().markMessageAsSendError(newMsg); - getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsg.id); + newMsg.to_id = getMessagesController().getPeer(lower_id); + if (lower_id > 0) { + TLRPC.User sendToUser = getMessagesController().getUser(lower_id); + if (sendToUser == null) { processSentMessage(newMsg.id); return; } - sendToPeers = new ArrayList<>(); - for (TLRPC.ChatParticipant participant : currentChatInfo.participants.participants) { - TLRPC.User sendToUser = getMessagesController().getUser(participant.user_id); - TLRPC.InputUser peerUser = getMessagesController().getInputUser(sendToUser); - if (peerUser != null) { - sendToPeers.add(peerUser); - } - } - newMsg.to_id = new TLRPC.TL_peerChat(); - newMsg.to_id.chat_id = lower_id; - } else { - newMsg.to_id = getMessagesController().getPeer(lower_id); - if (lower_id > 0) { - TLRPC.User sendToUser = getMessagesController().getUser(lower_id); - if (sendToUser == null) { - processSentMessage(newMsg.id); - return; - } - if (sendToUser.bot) { - newMsg.unread = false; - } + if (sendToUser.bot) { + newMsg.unread = false; } } } else { @@ -2645,6 +2677,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; newMsgObj = new MessageObject(currentAccount, newMsg, reply_to_msg, true); + newMsgObj.scheduled = scheduleDate != 0; if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) { newMsgObj.attachPathExists = true; } @@ -2669,9 +2702,11 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca objArr.add(newMsgObj); ArrayList arr = new ArrayList<>(); arr.add(newMsg); - getMessagesStorage().putMessages(arr, false, true, false, 0); - getMessagesController().updateInterfaceWithMessages(peer, objArr); - getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); + MessagesStorage.getInstance(currentAccount).putMessages(arr, false, true, false, 0, scheduleDate != 0); + MessagesController.getInstance(currentAccount).updateInterfaceWithMessages(peer, objArr, scheduleDate != 0); + if (scheduleDate == 0) { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); + } } else { String key = "group_" + groupId; ArrayList arrayList = delayedMessages.get(key); @@ -2682,6 +2717,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage = new DelayedMessage(peer); delayedMessage.initForGroup(groupId); delayedMessage.encryptedChat = encryptedChat; + delayedMessage.scheduled = scheduleDate != 0; } delayedMessage.performMediaUpload = false; delayedMessage.photoSize = null; @@ -2702,39 +2738,30 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca if (type == 0 || type == 9 && message != null && encryptedChat != null) { if (encryptedChat == null) { - if (sendToPeers != null) { - TLRPC.TL_messages_sendBroadcast reqSend = new TLRPC.TL_messages_sendBroadcast(); - ArrayList random_ids = new ArrayList<>(); - for (int a = 0; a < sendToPeers.size(); a++) { - random_ids.add(Utilities.random.nextLong()); - } - reqSend.message = message; - reqSend.contacts = sendToPeers; - reqSend.media = new TLRPC.TL_inputMediaEmpty(); - reqSend.random_id = random_ids; - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject); - } else { - TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage(); - reqSend.message = message; - reqSend.clear_draft = retryMessageObject == null; - reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); - reqSend.peer = sendToPeer; - reqSend.random_id = newMsg.random_id; - if (newMsg.reply_to_msg_id != 0) { - reqSend.flags |= 1; - reqSend.reply_to_msg_id = newMsg.reply_to_msg_id; - } - if (!searchLinks) { - reqSend.no_webpage = true; - } - if (entities != null && !entities.isEmpty()) { - reqSend.entities = entities; - reqSend.flags |= 8; - } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject); - if (retryMessageObject == null) { - getMediaDataController().cleanDraft(peer, false); - } + TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage(); + reqSend.message = message; + reqSend.clear_draft = retryMessageObject == null; + reqSend.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + reqSend.peer = sendToPeer; + reqSend.random_id = newMsg.random_id; + if (newMsg.reply_to_msg_id != 0) { + reqSend.flags |= 1; + reqSend.reply_to_msg_id = newMsg.reply_to_msg_id; + } + if (!searchLinks) { + reqSend.no_webpage = true; + } + if (entities != null && !entities.isEmpty()) { + reqSend.entities = entities; + reqSend.flags |= 8; + } + if (scheduleDate != 0) { + reqSend.schedule_date = scheduleDate; + reqSend.flags |= 1024; + } + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); + if (retryMessageObject == null) { + getMediaDataController().cleanDraft(peer, false); } } else { TLRPC.TL_decryptedMessage reqSend; @@ -2828,6 +2855,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.type = 0; delayedMessage.obj = newMsgObj; delayedMessage.originalPath = originalPath; + delayedMessage.scheduled = scheduleDate != 0; } delayedMessage.inputUploadMedia = uploadedPhoto; delayedMessage.performMediaUpload = performMediaUpload; @@ -2871,6 +2899,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.obj = newMsgObj; delayedMessage.originalPath = originalPath; delayedMessage.parentObject = parentObject; + delayedMessage.scheduled = scheduleDate != 0; } delayedMessage.inputUploadMedia = uploadedDocument; delayedMessage.performMediaUpload = performMediaUpload; @@ -2884,8 +2913,8 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca inputMedia.phone_number = user.phone; inputMedia.first_name = user.first_name; inputMedia.last_name = user.last_name; - if (user.restriction_reason != null && user.restriction_reason.startsWith("BEGIN:VCARD")) { - inputMedia.vcard = user.restriction_reason; + if (!user.restriction_reason.isEmpty() && user.restriction_reason.get(0).text.startsWith("BEGIN:VCARD")) { + inputMedia.vcard = user.restriction_reason.get(0).text; } else { inputMedia.vcard = ""; } @@ -2893,24 +2922,13 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca boolean http = false; TLRPC.InputMedia uploadedMedia; if (originalPath != null || path != null || document.access_hash == 0) { - if (encryptedChat == null && !TextUtils.isEmpty(originalPath) && originalPath.startsWith("http") && params != null) { - TLRPC.TL_inputMediaGifExternal gifExternal = new TLRPC.TL_inputMediaGifExternal(); - String args[] = params.get("url").split("\\|"); - if (args.length == 2) { - gifExternal.url = args[0]; - gifExternal.q = args[1]; - } - http = true; - uploadedMedia = gifExternal; - } else { - uploadedMedia = new TLRPC.TL_inputMediaUploadedDocument(); - if (ttl != 0) { - newMsg.ttl = uploadedMedia.ttl_seconds = ttl; - uploadedMedia.flags |= 2; - } - if (!TextUtils.isEmpty(path) && path.toLowerCase().endsWith("mp4") && (params == null || params.containsKey("forceDocument"))) { - uploadedMedia.nosound_video = true; - } + uploadedMedia = new TLRPC.TL_inputMediaUploadedDocument(); + if (ttl != 0) { + newMsg.ttl = uploadedMedia.ttl_seconds = ttl; + uploadedMedia.flags |= 2; + } + if (!TextUtils.isEmpty(path) && path.toLowerCase().endsWith("mp4") && (params == null || params.containsKey("forceDocument"))) { + uploadedMedia.nosound_video = true; } uploadedMedia.mime_type = document.mime_type; uploadedMedia.attributes = document.attributes; @@ -2944,6 +2962,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.parentObject = parentObject; delayedMessage.inputUploadMedia = uploadedMedia; delayedMessage.performMediaUpload = performMediaUpload; + delayedMessage.scheduled = scheduleDate != 0; } } else if (type == 8) { TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); @@ -2974,6 +2993,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.parentObject = parentObject; delayedMessage.inputUploadMedia = uploadedDocument; delayedMessage.performMediaUpload = performMediaUpload; + delayedMessage.scheduled = scheduleDate != 0; } else if (type == 10) { TLRPC.TL_inputMediaPoll inputMediaPoll = new TLRPC.TL_inputMediaPoll(); inputMediaPoll.poll = poll.poll; @@ -2982,35 +3002,22 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca TLObject reqSend; - if (sendToPeers != null) { - TLRPC.TL_messages_sendBroadcast request = new TLRPC.TL_messages_sendBroadcast(); - ArrayList random_ids = new ArrayList<>(); - for (int a = 0; a < sendToPeers.size(); a++) { - random_ids.add(Utilities.random.nextLong()); - } - request.contacts = sendToPeers; - request.media = inputMedia; - request.random_id = random_ids; - request.message = ""; - if (delayedMessage != null) { - delayedMessage.sendRequest = request; - } - reqSend = request; - if (retryMessageObject == null) { - getMediaDataController().cleanDraft(peer, false); - } - } else if (groupId != 0) { + if (groupId != 0) { TLRPC.TL_messages_sendMultiMedia request; if (delayedMessage.sendRequest != null) { request = (TLRPC.TL_messages_sendMultiMedia) delayedMessage.sendRequest; } else { request = new TLRPC.TL_messages_sendMultiMedia(); request.peer = sendToPeer; - request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + request.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); if (newMsg.reply_to_msg_id != 0) { request.flags |= 1; request.reply_to_msg_id = newMsg.reply_to_msg_id; } + if (scheduleDate != 0) { + request.schedule_date = scheduleDate; + request.flags |= 1024; + } delayedMessage.sendRequest = request; } delayedMessage.messageObjects.add(newMsgObj); @@ -3034,7 +3041,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca } else { TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia(); request.peer = sendToPeer; - request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + request.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); if (newMsg.reply_to_msg_id != 0) { request.flags |= 1; request.reply_to_msg_id = newMsg.reply_to_msg_id; @@ -3046,6 +3053,10 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca request.entities = entities; request.flags |= 8; } + if (scheduleDate != 0) { + request.schedule_date = scheduleDate; + request.flags |= 1024; + } if (delayedMessage != null) { delayedMessage.sendRequest = request; @@ -3055,35 +3066,35 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca if (groupId != 0) { performSendDelayedMessage(delayedMessage); } else if (type == 1) { - performSendMessageRequest(reqSend, newMsgObj, null, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, null, delayedMessage, parentObject, scheduleDate != 0); } else if (type == 2) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, null, true, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, null, true, delayedMessage, parentObject, scheduleDate != 0); } } else if (type == 3) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); } } else if (type == 6) { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); } else if (type == 7) { if (performMediaUpload && delayedMessage != null) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); } } else if (type == 8) { if (performMediaUpload) { performSendDelayedMessage(delayedMessage); } else { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); } } else if (type == 10) { - performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject); + performSendMessageRequest(reqSend, newMsgObj, originalPath, delayedMessage, parentObject, scheduleDate != 0); } } else { TLRPC.TL_decryptedMessage reqSend; @@ -3155,6 +3166,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.parentObject = parentObject; } delayedMessage.performMediaUpload = true; + delayedMessage.scheduled = scheduleDate != 0; } if (!TextUtils.isEmpty(path) && path.startsWith("http")) { delayedMessage.httpLocation = path; @@ -3220,6 +3232,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.parentObject = parentObject; } delayedMessage.performMediaUpload = true; + delayedMessage.scheduled = scheduleDate != 0; } delayedMessage.videoEditedInfo = videoEditedInfo; if (groupId == 0) { @@ -3292,6 +3305,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca if (path != null && path.length() > 0 && path.startsWith("http")) { delayedMessage.httpLocation = path; } + delayedMessage.scheduled = scheduleDate != 0; performSendDelayedMessage(delayedMessage); } else { TLRPC.TL_inputEncryptedFile encryptedFile = new TLRPC.TL_inputEncryptedFile(); @@ -3310,6 +3324,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca delayedMessage.type = 3; delayedMessage.parentObject = parentObject; delayedMessage.performMediaUpload = true; + delayedMessage.scheduled = scheduleDate != 0; reqSend.media = new TLRPC.TL_decryptedMessageMediaDocument(); reqSend.media.attributes = document.attributes; @@ -3366,7 +3381,11 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca } else { reqSend.from_peer = new TLRPC.TL_inputPeerEmpty(); } - reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + reqSend.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + if (scheduleDate != 0) { + reqSend.schedule_date = scheduleDate; + reqSend.flags |= 1024; + } reqSend.random_id.add(newMsg.random_id); if (retryMessageObject.getId() >= 0) { reqSend.id.add(retryMessageObject.getId()); @@ -3377,7 +3396,7 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca reqSend.id.add(retryMessageObject.messageOwner.fwd_from.channel_post); } } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject); + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); } else if (type == 9) { TLRPC.TL_messages_sendInlineBotResult reqSend = new TLRPC.TL_messages_sendInlineBotResult(); reqSend.peer = sendToPeer; @@ -3387,18 +3406,22 @@ private void sendMessage(String message, String caption, TLRPC.MessageMedia loca reqSend.flags |= 1; reqSend.reply_to_msg_id = newMsg.reply_to_msg_id; } - reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + reqSend.silent = !notify || MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false); + if (scheduleDate != 0) { + reqSend.schedule_date = scheduleDate; + reqSend.flags |= 1024; + } reqSend.query_id = Utilities.parseLong(params.get("query_id")); reqSend.id = params.get("id"); if (retryMessageObject == null) { reqSend.clear_draft = true; getMediaDataController().cleanDraft(peer, false); } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject); + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, scheduleDate != 0); } } catch (Exception e) { FileLog.e(e); - getMessagesStorage().markMessageAsSendError(newMsg); + getMessagesStorage().markMessageAsSendError(newMsg, scheduleDate != 0); if (newMsgObj != null) { newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; } @@ -3485,10 +3508,8 @@ private void performSendDelayedMessage(final DelayedMessage message, int index) TLRPC.InputMedia media; if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_editMessage) { - media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } else { - media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; + media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } media.file = message.videoEditedInfo.file; message.videoEditedInfo.file = null; @@ -3506,10 +3527,8 @@ private void performSendDelayedMessage(final DelayedMessage message, int index) TLRPC.InputMedia media; if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_editMessage) { - media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } else { - media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; + media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } if (media.file == null) { String location = message.obj.messageOwner.attachPath; @@ -3562,10 +3581,8 @@ private void performSendDelayedMessage(final DelayedMessage message, int index) TLRPC.InputMedia media; if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) { media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media; - } else if (message.sendRequest instanceof TLRPC.TL_messages_editMessage) { - media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } else { - media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media; + media = ((TLRPC.TL_messages_editMessage) message.sendRequest).media; } if (media.file == null) { String location = message.obj.messageOwner.attachPath; @@ -3711,7 +3728,7 @@ private void uploadMultiMedia(final DelayedMessage message, final TLRPC.InputMed TLRPC.TL_messages_sendMultiMedia multiMedia = (TLRPC.TL_messages_sendMultiMedia) message.sendRequest; for (int a = 0; a < multiMedia.multi_media.size(); a++) { if (multiMedia.multi_media.get(a).media == inputMedia) { - putToSendingMessages(message.messages.get(a)); + putToSendingMessages(message.messages.get(a), message.scheduled); getNotificationCenter().postNotificationName(NotificationCenter.FileUploadProgressChanged, key, 1.0f, false); break; } @@ -3761,7 +3778,7 @@ private void uploadMultiMedia(final DelayedMessage message, final TLRPC.InputMed TLRPC.TL_messages_sendEncryptedMultiMedia multiMedia = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest; for (int a = 0; a < multiMedia.files.size(); a++) { if (multiMedia.files.get(a) == inputEncryptedFile) { - putToSendingMessages(message.messages.get(a)); + putToSendingMessages(message.messages.get(a), message.scheduled); getNotificationCenter().postNotificationName(NotificationCenter.FileUploadProgressChanged, key, 1.0f, false); break; } @@ -3783,9 +3800,11 @@ private void sendReadyToSendGroup(DelayedMessage message, boolean add, boolean c return; } else if (add) { delayedMessages.remove(key); - getMessagesStorage().putMessages(message.messages, false, true, false, 0); - getMessagesController().updateInterfaceWithMessages(message.peer, message.messageObjects); - getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); + getMessagesStorage().putMessages(message.messages, false, true, false, 0, message.scheduled); + getMessagesController().updateInterfaceWithMessages(message.peer, message.messageObjects, message.scheduled); + if (!message.scheduled) { + getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); + } } if (message.sendRequest instanceof TLRPC.TL_messages_sendMultiMedia) { TLRPC.TL_messages_sendMultiMedia request = (TLRPC.TL_messages_sendMultiMedia) message.sendRequest; @@ -3799,7 +3818,7 @@ private void sendReadyToSendGroup(DelayedMessage message, boolean add, boolean c if (check) { DelayedMessage maxDelayedMessage = findMaxDelayedMessageForMessageId(message.finalGroupMessage, message.peer); if (maxDelayedMessage != null) { - maxDelayedMessage.addDelayedRequest(message.sendRequest, message.messageObjects, message.originalPaths, message.parentObjects, message); + maxDelayedMessage.addDelayedRequest(message.sendRequest, message.messageObjects, message.originalPaths, message.parentObjects, message, message.scheduled); if (message.requests != null) { maxDelayedMessage.requests.addAll(message.requests); } @@ -3817,7 +3836,7 @@ private void sendReadyToSendGroup(DelayedMessage message, boolean add, boolean c } if (message.sendRequest instanceof TLRPC.TL_messages_sendMultiMedia) { - performSendMessageRequestMulti((TLRPC.TL_messages_sendMultiMedia) message.sendRequest, message.messageObjects, message.originalPaths, message.parentObjects, message); + performSendMessageRequestMulti((TLRPC.TL_messages_sendMultiMedia) message.sendRequest, message.messageObjects, message.originalPaths, message.parentObjects, message, message.scheduled); } else { getSecretChatHelper().performSendEncryptedRequest((TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest, message); } @@ -3829,15 +3848,15 @@ protected void stopVideoService(final String path) { getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopEncodingService, path, currentAccount))); } - protected void putToSendingMessages(TLRPC.Message message) { + protected void putToSendingMessages(TLRPC.Message message, boolean scheduled) { if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { - AndroidUtilities.runOnUIThread(() -> putToSendingMessages(message, true)); + AndroidUtilities.runOnUIThread(() -> putToSendingMessages(message, scheduled, true)); } else { - putToSendingMessages(message, true); + putToSendingMessages(message, scheduled, true); } } - protected void putToSendingMessages(TLRPC.Message message, boolean notify) { + protected void putToSendingMessages(TLRPC.Message message, boolean scheduled, boolean notify) { if (message == null) { return; } @@ -3845,9 +3864,9 @@ protected void putToSendingMessages(TLRPC.Message message, boolean notify) { editingMessages.put(message.id, message); } else { boolean contains = sendingMessages.indexOfKey(message.id) >= 0; - removeFromUploadingMessages(message.id); + removeFromUploadingMessages(message.id, scheduled); sendingMessages.put(message.id, message); - if (!contains) { + if (!scheduled && !contains) { long did = MessageObject.getDialogId(message); sendingMessagesIdDialogs.put(did, sendingMessagesIdDialogs.get(did, 0) + 1); if (notify) { @@ -3857,7 +3876,7 @@ protected void putToSendingMessages(TLRPC.Message message, boolean notify) { } } - protected TLRPC.Message removeFromSendingMessages(int mid) { + protected TLRPC.Message removeFromSendingMessages(int mid, boolean scheduled) { TLRPC.Message message; if (mid > 0) { message = editingMessages.get(mid); @@ -3868,16 +3887,18 @@ protected TLRPC.Message removeFromSendingMessages(int mid) { message = sendingMessages.get(mid); if (message != null) { sendingMessages.remove(mid); - long did = MessageObject.getDialogId(message); - Integer currentCount = sendingMessagesIdDialogs.get(did); - if (currentCount != null) { - int count = currentCount - 1; - if (count <= 0) { - sendingMessagesIdDialogs.remove(did); - } else { - sendingMessagesIdDialogs.put(did, count); + if (!scheduled) { + long did = MessageObject.getDialogId(message); + Integer currentCount = sendingMessagesIdDialogs.get(did); + if (currentCount != null) { + int count = currentCount - 1; + if (count <= 0) { + sendingMessagesIdDialogs.remove(did); + } else { + sendingMessagesIdDialogs.put(did, count); + } + getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged); } - getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged); } } } @@ -3901,7 +3922,7 @@ public int getSendingMessageId(long did) { } protected void putToUploadingMessages(MessageObject obj) { - if (obj == null || obj.getId() > 0) { + if (obj == null || obj.getId() > 0 || obj.scheduled) { return; } TLRPC.Message message = obj.messageOwner; @@ -3914,8 +3935,8 @@ protected void putToUploadingMessages(MessageObject obj) { } } - protected void removeFromUploadingMessages(int mid) { - if (mid > 0) { + protected void removeFromUploadingMessages(int mid, boolean scheduled) { + if (mid > 0 || scheduled) { return; } TLRPC.Message message = uploadMessages.get(mid); @@ -3947,15 +3968,15 @@ public boolean isUploadingMessageIdDialog(long did) { return uploadingMessagesIdDialogs.get(did, 0) > 0; } - protected void performSendMessageRequestMulti(final TLRPC.TL_messages_sendMultiMedia req, final ArrayList msgObjs, final ArrayList originalPaths, final ArrayList parentObjects, DelayedMessage delayedMessage) { + protected void performSendMessageRequestMulti(final TLRPC.TL_messages_sendMultiMedia req, final ArrayList msgObjs, final ArrayList originalPaths, final ArrayList parentObjects, DelayedMessage delayedMessage, boolean scheduled) { for (int a = 0, size = msgObjs.size(); a < size; a++) { - putToSendingMessages(msgObjs.get(a).messageOwner); + putToSendingMessages(msgObjs.get(a).messageOwner, scheduled); } getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error != null && FileRefController.isFileRefError(error.text)) { if (parentObjects != null) { ArrayList arrayList = new ArrayList<>(parentObjects); - getFileRefController().requestReference(arrayList, req, msgObjs, originalPaths, arrayList, delayedMessage); + getFileRefController().requestReference(arrayList, req, msgObjs, originalPaths, arrayList, delayedMessage, scheduled); return; } else if (delayedMessage != null) { AndroidUtilities.runOnUIThread(new Runnable() { @@ -3965,7 +3986,7 @@ public void run() { if (delayedMessage.parentObjects.get(a) == null) { continue; } - removeFromSendingMessages(msgObjs.get(a).getId()); + removeFromSendingMessages(msgObjs.get(a).getId(), scheduled); TLRPC.TL_inputSingleMedia request = req.multi_media.get(a); if (request.media instanceof TLRPC.TL_inputMediaPhoto) { request.media = delayedMessage.inputMedias.get(a); @@ -4008,6 +4029,11 @@ public void run() { Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.to_id.channel_id)); updatesArr.remove(a); a--; + } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { + final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update; + newMessages.put(newMessage.message.id, newMessage.message); + updatesArr.remove(a); + a--; } } @@ -4034,12 +4060,14 @@ public void run() { } grouped_id = message.grouped_id; - Integer value = getMessagesController().dialogs_read_outbox_max.get(message.dialog_id); - if (value == null) { - value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); - getMessagesController().dialogs_read_outbox_max.put(message.dialog_id, value); + if (!scheduled) { + Integer value = getMessagesController().dialogs_read_outbox_max.get(message.dialog_id); + if (value == null) { + value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); + getMessagesController().dialogs_read_outbox_max.put(message.dialog_id, value); + } + message.unread = value < message.id; } - message.unread = value < message.id; } else { isSentError = true; break; @@ -4052,15 +4080,15 @@ public void run() { if (!isSentError) { getStatsController().incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); getMessagesStorage().getStorageQueue().postRunnable(() -> { - getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, oldId, newMsgObj.id, 0, false, newMsgObj.to_id.channel_id); - getMessagesStorage().putMessages(sentMessages, true, false, false, 0); + getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, oldId, newMsgObj.id, 0, false, newMsgObj.to_id.channel_id, scheduled ? 1 : 0); + getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled); AndroidUtilities.runOnUIThread(() -> { getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, grouped_id, existFlags, scheduled); processSentMessage(oldId); - removeFromSendingMessages(oldId); + removeFromSendingMessages(oldId, scheduled); }); }); } @@ -4073,18 +4101,18 @@ public void run() { if (isSentError) { for (int i = 0; i < msgObjs.size(); i++) { TLRPC.Message newMsgObj = msgObjs.get(i).messageOwner; - getMessagesStorage().markMessageAsSendError(newMsgObj); + getMessagesStorage().markMessageAsSendError(newMsgObj, scheduled); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); processSentMessage(newMsgObj.id); - removeFromSendingMessages(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); } } }), null, ConnectionsManager.RequestFlagCanCompress | ConnectionsManager.RequestFlagInvokeAfter); } - private void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage delayedMessage, Object parentObject) { - performSendMessageRequest(req, msgObj, originalPath, null, false, delayedMessage, parentObject); + private void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage delayedMessage, Object parentObject, boolean scheduled) { + performSendMessageRequest(req, msgObj, originalPath, null, false, delayedMessage, parentObject, scheduled); } private DelayedMessage findMaxDelayedMessageForMessageId(int messageId, long dialogId) { @@ -4114,12 +4142,12 @@ private DelayedMessage findMaxDelayedMessageForMessageId(int messageId, long dia return maxDelayedMessage; } - protected void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage parentMessage, boolean check, DelayedMessage delayedMessage, Object parentObject) { + protected void performSendMessageRequest(final TLObject req, final MessageObject msgObj, final String originalPath, DelayedMessage parentMessage, boolean check, DelayedMessage delayedMessage, Object parentObject, boolean scheduled) { if (!(req instanceof TLRPC.TL_messages_editMessage)) { if (check) { DelayedMessage maxDelayedMessage = findMaxDelayedMessageForMessageId(msgObj.getId(), msgObj.getDialogId()); if (maxDelayedMessage != null) { - maxDelayedMessage.addDelayedRequest(req, msgObj, originalPath, parentObject, delayedMessage); + maxDelayedMessage.addDelayedRequest(req, msgObj, originalPath, parentObject, delayedMessage, parentMessage != null ? parentMessage.scheduled : false); if (parentMessage != null && parentMessage.requests != null) { maxDelayedMessage.requests.addAll(parentMessage.requests); } @@ -4128,17 +4156,17 @@ protected void performSendMessageRequest(final TLObject req, final MessageObject } } final TLRPC.Message newMsgObj = msgObj.messageOwner; - putToSendingMessages(newMsgObj); + putToSendingMessages(newMsgObj, scheduled); newMsgObj.reqId = getConnectionsManager().sendRequest(req, (response, error) -> { if (error != null && (req instanceof TLRPC.TL_messages_sendMedia || req instanceof TLRPC.TL_messages_editMessage) && FileRefController.isFileRefError(error.text)) { if (parentObject != null) { - getFileRefController().requestReference(parentObject, req, msgObj, originalPath, parentMessage, check, delayedMessage); + getFileRefController().requestReference(parentObject, req, msgObj, originalPath, parentMessage, check, delayedMessage, scheduled); return; } else if (delayedMessage != null) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - removeFromSendingMessages(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); if (req instanceof TLRPC.TL_messages_sendMedia) { TLRPC.TL_messages_sendMedia request = (TLRPC.TL_messages_sendMedia) req; if (request.media instanceof TLRPC.TL_inputMediaPhoto) { @@ -4179,6 +4207,10 @@ public void run() { final TLRPC.TL_updateEditChannelMessage newMessage = (TLRPC.TL_updateEditChannelMessage) update; message = newMessage.message; break; + } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { + final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update; + message = newMessage.message; + break; } } if (message != null) { @@ -4189,7 +4221,7 @@ public void run() { getMessagesController().processUpdates(updates, false); AndroidUtilities.runOnUIThread(() -> { processSentMessage(newMsgObj.id); - removeFromSendingMessages(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); }); }); if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { @@ -4200,7 +4232,7 @@ public void run() { if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { stopVideoService(newMsgObj.attachPath); } - removeFromSendingMessages(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); revertEditingMessageObject(msgObj); } }); @@ -4210,7 +4242,6 @@ public void run() { boolean isSentError = false; if (error == null) { final int oldId = newMsgObj.id; - final boolean isBroadcast = req instanceof TLRPC.TL_messages_sendBroadcast; final ArrayList sentMessages = new ArrayList<>(); final String attachPath = newMsgObj.attachPath; final int existFlags; @@ -4256,16 +4287,26 @@ public void run() { Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.to_id.channel_id)); updatesArr.remove(a); break; + } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { + final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update; + sentMessages.add(message = newMessage.message); + if ((newMsgObj.flags & TLRPC.MESSAGE_FLAG_MEGAGROUP) != 0) { + newMessage.message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + updatesArr.remove(a); + break; } } if (message != null) { ImageLoader.saveMessageThumbs(message); - Integer value = getMessagesController().dialogs_read_outbox_max.get(message.dialog_id); - if (value == null) { - value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); - getMessagesController().dialogs_read_outbox_max.put(message.dialog_id, value); + if (!scheduled) { + Integer value = getMessagesController().dialogs_read_outbox_max.get(message.dialog_id); + if (value == null) { + value = getMessagesStorage().getDialogReadMax(message.out, message.dialog_id); + getMessagesController().dialogs_read_outbox_max.put(message.dialog_id, value); + } + message.unread = value < message.id; } - message.unread = value < message.id; updateMediaPaths(msgObj, message, message.id, originalPath, false); existFlags = msgObj.getMediaExistanceFlags(); newMsgObj.id = message.id; @@ -4285,30 +4326,15 @@ public void run() { if (!isSentError) { getStatsController().incrementSentItemsCount(ApplicationLoader.getCurrentNetworkType(), StatsController.TYPE_MESSAGES, 1); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); getMessagesStorage().getStorageQueue().postRunnable(() -> { - getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, oldId, (isBroadcast ? oldId : newMsgObj.id), 0, false, newMsgObj.to_id.channel_id); - getMessagesStorage().putMessages(sentMessages, true, false, isBroadcast, 0); - if (isBroadcast) { - ArrayList currentMessage = new ArrayList<>(); - currentMessage.add(newMsgObj); - getMessagesStorage().putMessages(currentMessage, true, false, false, 0); - } + getMessagesStorage().updateMessageStateAndId(newMsgObj.random_id, oldId, newMsgObj.id, 0, false, newMsgObj.to_id.channel_id, scheduled ? 1 : 0); + getMessagesStorage().putMessages(sentMessages, true, false, false, 0, scheduled); AndroidUtilities.runOnUIThread(() -> { - if (isBroadcast) { - for (int a = 0; a < sentMessages.size(); a++) { - TLRPC.Message message = sentMessages.get(a); - ArrayList arr = new ArrayList<>(); - MessageObject messageObject = new MessageObject(currentAccount, message, false); - arr.add(messageObject); - getMessagesController().updateInterfaceWithMessages(messageObject.getDialogId(), arr, true); - } - getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); - } getMediaDataController().increasePeerRaiting(newMsgObj.dialog_id); - getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id, 0L, existFlags); + getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); processSentMessage(oldId); - removeFromSendingMessages(oldId); + removeFromSendingMessages(oldId, scheduled); }); if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { stopVideoService(attachPath); @@ -4320,14 +4346,14 @@ public void run() { isSentError = true; } if (isSentError) { - getMessagesStorage().markMessageAsSendError(newMsgObj); + getMessagesStorage().markMessageAsSendError(newMsgObj, scheduled); newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); processSentMessage(newMsgObj.id); if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { stopVideoService(newMsgObj.attachPath); } - removeFromSendingMessages(newMsgObj.id); + removeFromSendingMessages(newMsgObj.id, scheduled); } }); } @@ -4401,7 +4427,7 @@ private void updateMediaPaths(MessageObject newMsgObj, TLRPC.Message sentMessage return; } if (sentMessage.media instanceof TLRPC.TL_messageMediaPhoto && sentMessage.media.photo != null && newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) { - if (sentMessage.media.ttl_seconds == 0) { + if (sentMessage.media.ttl_seconds == 0 && !newMsgObj.scheduled) { getMessagesStorage().putSentFile(originalPath, sentMessage.media.photo, 0, "sent_" + sentMessage.to_id.channel_id + "_" + sentMessage.id); } @@ -4448,11 +4474,13 @@ private void updateMediaPaths(MessageObject newMsgObj, TLRPC.Message sentMessage if (sentMessage.media.ttl_seconds == 0) { boolean isVideo = MessageObject.isVideoMessage(sentMessage); if ((isVideo || MessageObject.isGifMessage(sentMessage)) && MessageObject.isGifDocument(sentMessage.media.document) == MessageObject.isGifDocument(newMsg.media.document)) { - getMessagesStorage().putSentFile(originalPath, sentMessage.media.document, 2, "sent_" + sentMessage.to_id.channel_id + "_" + sentMessage.id); + if (!newMsgObj.scheduled) { + getMessagesStorage().putSentFile(originalPath, sentMessage.media.document, 2, "sent_" + sentMessage.to_id.channel_id + "_" + sentMessage.id); + } if (isVideo) { sentMessage.attachPath = newMsg.attachPath; } - } else if (!MessageObject.isVoiceMessage(sentMessage) && !MessageObject.isRoundVideoMessage(sentMessage)) { + } else if (!MessageObject.isVoiceMessage(sentMessage) && !MessageObject.isRoundVideoMessage(sentMessage) && !newMsgObj.scheduled) { getMessagesStorage().putSentFile(originalPath, sentMessage.media.document, 1, "sent_" + sentMessage.to_id.channel_id + "_" + sentMessage.id); } } @@ -4578,16 +4606,22 @@ public void checkUnsentMessages() { getMessagesStorage().getUnsentMessages(1000); } - protected void processUnsentMessages(final ArrayList messages, final ArrayList users, final ArrayList chats, final ArrayList encryptedChats) { + protected void processUnsentMessages(final ArrayList messages, final ArrayList scheduledMessages, final ArrayList users, final ArrayList chats, final ArrayList encryptedChats) { AndroidUtilities.runOnUIThread(() -> { getMessagesController().putUsers(users, true); getMessagesController().putChats(chats, true); getMessagesController().putEncryptedChats(encryptedChats, true); for (int a = 0; a < messages.size(); a++) { - TLRPC.Message message = messages.get(a); - MessageObject messageObject = new MessageObject(currentAccount, message, false); + MessageObject messageObject = new MessageObject(currentAccount, messages.get(a), false); retrySendMessage(messageObject, true); } + if (scheduledMessages != null) { + for (int a = 0; a < scheduledMessages.size(); a++) { + MessageObject messageObject = new MessageObject(currentAccount, scheduledMessages.get(a), false); + messageObject.scheduled = true; + retrySendMessage(messageObject, true); + } + } }); } @@ -4626,7 +4660,7 @@ public TLRPC.TL_photo generatePhotoSizes(TLRPC.TL_photo photo, String path, Uri } } - private static boolean prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, final long dialog_id, final MessageObject reply_to_msg, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, boolean forceDocument) { + private static boolean prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, final long dialog_id, final MessageObject reply_to_msg, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, boolean forceDocument, boolean notify, int scheduleDate) { if ((path == null || path.length() == 0) && uri == null) { return false; } @@ -4861,14 +4895,14 @@ private static boolean prepareSendingDocumentInternal(AccountInstance accountIns if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, null, documentFinal, pathFinal, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialog_id, reply_to_msg, captionFinal, entities, null, params, 0, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialog_id, reply_to_msg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal); } }); return true; } @UiThread - public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialog_id, MessageObject reply_to_msg, InputContentInfoCompat inputContent, MessageObject editingMessageObject) { + public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialog_id, MessageObject reply_to_msg, InputContentInfoCompat inputContent, MessageObject editingMessageObject, boolean notify, int scheduleDate) { if ((path == null || originalPath == null) && uri == null) { return; } @@ -4883,11 +4917,11 @@ public static void prepareSendingDocument(AccountInstance accountInstance, Strin paths.add(path); originalPaths.add(originalPath); } - prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialog_id, reply_to_msg, inputContent, editingMessageObject); + prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialog_id, reply_to_msg, inputContent, editingMessageObject, notify, scheduleDate); } @UiThread - public static void prepareSendingAudioDocuments(AccountInstance accountInstance, final ArrayList messageObjects, final long dialog_id, final MessageObject reply_to_msg, final MessageObject editingMessageObject) { + public static void prepareSendingAudioDocuments(AccountInstance accountInstance, final ArrayList messageObjects, final long dialog_id, final MessageObject reply_to_msg, final MessageObject editingMessageObject, boolean notify, int scheduleDate) { new Thread(() -> { int size = messageObjects.size(); for (int a = 0; a < size; a++) { @@ -4933,7 +4967,7 @@ public static void prepareSendingAudioDocuments(AccountInstance accountInstance, if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, null, documentFinal, messageObject.messageOwner.attachPath, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, messageObject.messageOwner.attachPath, dialog_id, reply_to_msg, null, null, null, params, 0, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, messageObject.messageOwner.attachPath, dialog_id, reply_to_msg, null, null, null, params, notify, scheduleDate, 0, parentFinal); } }); } @@ -4941,7 +4975,7 @@ public static void prepareSendingAudioDocuments(AccountInstance accountInstance, } @UiThread - public static void prepareSendingDocuments(AccountInstance accountInstance, final ArrayList paths, final ArrayList originalPaths, final ArrayList uris, final String caption, final String mime, final long dialog_id, final MessageObject reply_to_msg, final InputContentInfoCompat inputContent, final MessageObject editingMessageObject) { + public static void prepareSendingDocuments(AccountInstance accountInstance, final ArrayList paths, final ArrayList originalPaths, final ArrayList uris, final String caption, final String mime, final long dialog_id, final MessageObject reply_to_msg, final InputContentInfoCompat inputContent, final MessageObject editingMessageObject, boolean notify, int scheduleDate) { if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) { return; } @@ -4949,14 +4983,14 @@ public static void prepareSendingDocuments(AccountInstance accountInstance, fina boolean error = false; if (paths != null) { for (int a = 0; a < paths.size(); a++) { - if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialog_id, reply_to_msg, caption, null, editingMessageObject, false)) { + if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialog_id, reply_to_msg, caption, null, editingMessageObject, false, notify, scheduleDate)) { error = true; } } } if (uris != null) { for (int a = 0; a < uris.size(); a++) { - if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialog_id, reply_to_msg, caption, null, editingMessageObject, false)) { + if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialog_id, reply_to_msg, caption, null, editingMessageObject, false, notify, scheduleDate)) { error = true; } } @@ -4978,7 +5012,7 @@ public static void prepareSendingDocuments(AccountInstance accountInstance, fina } @UiThread - public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialog_id, MessageObject reply_to_msg, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject) { + public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialog_id, MessageObject reply_to_msg, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate) { SendingMediaInfo info = new SendingMediaInfo(); info.path = imageFilePath; info.uri = imageUri; @@ -4992,11 +5026,11 @@ public static void prepareSendingPhoto(AccountInstance accountInstance, String i } ArrayList infos = new ArrayList<>(); infos.add(info); - prepareSendingMedia(accountInstance, infos, dialog_id, reply_to_msg, inputContent, false, false, editingMessageObject); + prepareSendingMedia(accountInstance, infos, dialog_id, reply_to_msg, inputContent, false, false, editingMessageObject, notify, scheduleDate); } @UiThread - public static void prepareSendingBotContextResult(AccountInstance accountInstance, final TLRPC.BotInlineResult result, final HashMap params, final long dialog_id, final MessageObject reply_to_msg) { + public static void prepareSendingBotContextResult(AccountInstance accountInstance, final TLRPC.BotInlineResult result, final HashMap params, final long dialog_id, final MessageObject reply_to_msg, boolean notify, int scheduleDate) { if (result == null) { return; } @@ -5226,11 +5260,11 @@ public static void prepareSendingBotContextResult(AccountInstance accountInstanc } AndroidUtilities.runOnUIThread(() -> { if (finalDocument != null) { - accountInstance.getSendMessagesHelper().sendMessage(finalDocument, null, finalPathFinal, dialog_id, reply_to_msg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, 0, result); + accountInstance.getSendMessagesHelper().sendMessage(finalDocument, null, finalPathFinal, dialog_id, reply_to_msg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result); } else if (finalPhoto != null) { - accountInstance.getSendMessagesHelper().sendMessage(finalPhoto, result.content != null ? result.content.url : null, dialog_id, reply_to_msg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, 0, result); + accountInstance.getSendMessagesHelper().sendMessage(finalPhoto, result.content != null ? result.content.url : null, dialog_id, reply_to_msg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result); } else if (finalGame != null) { - accountInstance.getSendMessagesHelper().sendMessage(finalGame, dialog_id, result.send_message.reply_markup, params); + accountInstance.getSendMessagesHelper().sendMessage(finalGame, dialog_id, result.send_message.reply_markup, params, notify, scheduleDate); } }); }).run(); @@ -5246,7 +5280,7 @@ public static void prepareSendingBotContextResult(AccountInstance accountInstanc } } } - accountInstance.getSendMessagesHelper().sendMessage(result.send_message.message, dialog_id, reply_to_msg, webPage, !result.send_message.no_webpage, result.send_message.entities, result.send_message.reply_markup, params); + accountInstance.getSendMessagesHelper().sendMessage(result.send_message.message, dialog_id, reply_to_msg, webPage, !result.send_message.no_webpage, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate); } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaVenue) { TLRPC.TL_messageMediaVenue venue = new TLRPC.TL_messageMediaVenue(); venue.geo = result.send_message.geo; @@ -5258,25 +5292,29 @@ public static void prepareSendingBotContextResult(AccountInstance accountInstanc if (venue.venue_type == null) { venue.venue_type = ""; } - accountInstance.getSendMessagesHelper().sendMessage(venue, dialog_id, reply_to_msg, result.send_message.reply_markup, params); + accountInstance.getSendMessagesHelper().sendMessage(venue, dialog_id, reply_to_msg, result.send_message.reply_markup, params, notify, scheduleDate); } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaGeo) { if (result.send_message.period != 0) { TLRPC.TL_messageMediaGeoLive location = new TLRPC.TL_messageMediaGeoLive(); location.period = result.send_message.period; location.geo = result.send_message.geo; - accountInstance.getSendMessagesHelper().sendMessage(location, dialog_id, reply_to_msg, result.send_message.reply_markup, params); + accountInstance.getSendMessagesHelper().sendMessage(location, dialog_id, reply_to_msg, result.send_message.reply_markup, params, notify, scheduleDate); } else { TLRPC.TL_messageMediaGeo location = new TLRPC.TL_messageMediaGeo(); location.geo = result.send_message.geo; - accountInstance.getSendMessagesHelper().sendMessage(location, dialog_id, reply_to_msg, result.send_message.reply_markup, params); + accountInstance.getSendMessagesHelper().sendMessage(location, dialog_id, reply_to_msg, result.send_message.reply_markup, params, notify, scheduleDate); } } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaContact) { TLRPC.User user = new TLRPC.TL_user(); user.phone = result.send_message.phone_number; user.first_name = result.send_message.first_name; user.last_name = result.send_message.last_name; - user.restriction_reason = result.send_message.vcard; - accountInstance.getSendMessagesHelper().sendMessage(user, dialog_id, reply_to_msg, result.send_message.reply_markup, params); + TLRPC.TL_restrictionReason reason = new TLRPC.TL_restrictionReason(); + reason.text = result.send_message.vcard; + reason.platform = ""; + reason.reason = ""; + user.restriction_reason.add(reason); + accountInstance.getSendMessagesHelper().sendMessage(user, dialog_id, reply_to_msg, result.send_message.reply_markup, params, notify, scheduleDate); } } @@ -5295,14 +5333,14 @@ private static String getTrimmedString(String src) { } @UiThread - public static void prepareSendingText(AccountInstance accountInstance, final String text, final long dialog_id) { + public static void prepareSendingText(AccountInstance accountInstance, final String text, final long dialog_id, boolean notify, int scheduleDate) { accountInstance.getMessagesStorage().getStorageQueue().postRunnable(() -> Utilities.stageQueue.postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { String textFinal = getTrimmedString(text); if (textFinal.length() != 0) { int count = (int) Math.ceil(textFinal.length() / 4096.0f); for (int a = 0; a < count; a++) { String mess = textFinal.substring(a * 4096, Math.min((a + 1) * 4096, textFinal.length())); - accountInstance.getSendMessagesHelper().sendMessage(mess, dialog_id, null, null, true, null, null, null); + accountInstance.getSendMessagesHelper().sendMessage(mess, dialog_id, null, null, true, null, null, null, notify, scheduleDate); } } }))); @@ -5435,17 +5473,17 @@ private static String getKeyForPhotoSize(TLRPC.PhotoSize photoSize, Bitmap[] bit bitmap[0] = BitmapFactory.decodeStream(is, null, opts); is.close(); } else { - /*opts.inPurgeable = true; TODO - RandomAccessFile f = new RandomAccessFile(file, "r"); - int len = (int) f.length(); - int offset = 0; - byte[] data = bytes != null && bytes.length >= len ? bytes : null; - if (data == null) { - bytes = data = new byte[len]; - } - f.readFully(data, 0, len); - f.close(); - bitmapFinal[0] = BitmapFactory.decodeByteArray(data, offset, len, opts);*/ + /*opts.inPurgeable = true; + RandomAccessFile f = new RandomAccessFile(file, "r"); + int len = (int) f.length(); + int offset = 0; + byte[] data = bytes != null && bytes.length >= len ? bytes : null; + if (data == null) { + bytes = data = new byte[len]; + } + f.readFully(data, 0, len); + f.close(); + bitmapFinal[0] = BitmapFactory.decodeByteArray(data, offset, len, opts);*/ } } catch (Throwable ignore) { @@ -5456,7 +5494,7 @@ private static String getKeyForPhotoSize(TLRPC.PhotoSize photoSize, Bitmap[] bit } @UiThread - public static void prepareSendingMedia(AccountInstance accountInstance, final ArrayList media, final long dialog_id, final MessageObject reply_to_msg, final InputContentInfoCompat inputContent, final boolean forceDocument, final boolean groupPhotos, final MessageObject editingMessageObject) { + public static void prepareSendingMedia(AccountInstance accountInstance, final ArrayList media, final long dialog_id, final MessageObject reply_to_msg, final InputContentInfoCompat inputContent, final boolean forceDocument, final boolean groupPhotos, final MessageObject editingMessageObject, boolean notify, int scheduleDate) { if (media.isEmpty()) { return; } @@ -5576,9 +5614,6 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), md5); } if (document == null) { - if (info.searchImage.localUrl != null) { - params.put("url", info.searchImage.localUrl); - } File thumbFile = null; document = new TLRPC.TL_document(); document.id = 0; @@ -5650,7 +5685,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, null, documentFinal, pathFinal, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialog_id, reply_to_msg, info.caption, info.entities, null, params, 0, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialog_id, reply_to_msg, info.caption, info.entities, null, params, notify, scheduleDate, 0, parentFinal); } }); } else { @@ -5718,7 +5753,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, photoFinal, null, null, needDownloadHttpFinal ? info.searchImage.imageUrl : null, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(photoFinal, needDownloadHttpFinal ? info.searchImage.imageUrl : null, dialog_id, reply_to_msg, info.caption, info.entities, null, params, info.ttl, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(photoFinal, needDownloadHttpFinal ? info.searchImage.imageUrl : null, dialog_id, reply_to_msg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal); } }); } @@ -5858,11 +5893,11 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialog_id, reply_to_msg, info.caption, info.entities, null, params, info.ttl, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialog_id, reply_to_msg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal); } }); } else { - prepareSendingDocumentInternal(accountInstance, info.path, info.path, null, null, dialog_id, reply_to_msg, info.caption, info.entities, editingMessageObject, forceDocument); + prepareSendingDocumentInternal(accountInstance, info.path, info.path, null, null, dialog_id, reply_to_msg, info.caption, info.entities, editingMessageObject, forceDocument, notify, scheduleDate); } } else { String originalPath = info.path; @@ -5998,7 +6033,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, photoFinal, null, null, null, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(photoFinal, null, dialog_id, reply_to_msg, info.caption, info.entities, null, params, info.ttl, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(photoFinal, null, dialog_id, reply_to_msg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal); } }); } else { @@ -6032,7 +6067,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages(); messagesRes.messages.add(prevMessage.messageOwner); - accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false); + accountInstance.getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false, scheduleDate != 0); instance.sendReadyToSendGroup(message, true, true); } }); @@ -6042,7 +6077,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, final Ar } if (sendAsDocuments != null && !sendAsDocuments.isEmpty()) { for (int a = 0; a < sendAsDocuments.size(); a++) { - prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), null, extension, dialog_id, reply_to_msg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, forceDocument); + prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), null, extension, dialog_id, reply_to_msg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, forceDocument, notify, scheduleDate); } } if (BuildVars.LOGS_ENABLED) { @@ -6267,7 +6302,7 @@ private static VideoEditedInfo createCompressionSettings(String videoPath) { } @UiThread - public static void prepareSendingVideo(AccountInstance accountInstance, final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final VideoEditedInfo info, final long dialog_id, final MessageObject reply_to_msg, final CharSequence caption, final ArrayList entities, final int ttl, final MessageObject editingMessageObject) { + public static void prepareSendingVideo(AccountInstance accountInstance, final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final VideoEditedInfo info, final long dialog_id, final MessageObject reply_to_msg, final CharSequence caption, final ArrayList entities, final int ttl, final MessageObject editingMessageObject, boolean notify, int scheduleDate) { if (videoPath == null || videoPath.length() == 0) { return; } @@ -6402,11 +6437,11 @@ public static void prepareSendingVideo(AccountInstance accountInstance, final St if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessageMedia(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal); } else { - accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialog_id, reply_to_msg, captionFinal, entities, null, params, ttl, parentFinal); + accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialog_id, reply_to_msg, captionFinal, entities, null, params, notify, scheduleDate, ttl, parentFinal); } }); } else { - prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialog_id, reply_to_msg, caption, entities, editingMessageObject, false); + prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialog_id, reply_to_msg, caption, entities, editingMessageObject, false, notify, scheduleDate); } }).start(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 19badf614a1..1316065c060 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -734,7 +734,7 @@ public static void checkSaveToGalleryFiles() { new File(videoPath, ".nomedia").createNewFile(); } } - } catch (Exception e) { + } catch (Throwable e) { FileLog.e(e); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SmsReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/SmsReceiver.java new file mode 100644 index 00000000000..b70adb8340e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SmsReceiver.java @@ -0,0 +1,60 @@ +/* + * This is the source code of Telegram for Android v. 5.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2018. + */ + +package org.telegram.messenger; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.text.TextUtils; + +import com.google.android.gms.auth.api.phone.SmsRetriever; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SmsReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null) { + return; + } + try { + String message = ""; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + String hash = preferences.getString("sms_hash", null); + if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) { + if (!AndroidUtilities.isWaitingForSms()) { + return; + } + Bundle bundle = intent.getExtras(); + message = (String) bundle.get(SmsRetriever.EXTRA_SMS_MESSAGE); + } + if (TextUtils.isEmpty(message)) { + return; + } + Pattern pattern = Pattern.compile("[0-9\\-]+"); + final Matcher matcher = pattern.matcher(message); + if (matcher.find()) { + String code = matcher.group(0).replace("-", ""); + if (code.length() >= 3) { + if (preferences != null && hash != null) { + preferences.edit().putString("sms_hash_code", hash + "|" + code).commit(); + } + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReceiveSmsCode, code)); + } + } + } catch (Throwable e) { + FileLog.e(e); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java index dabe339150c..c135834b1a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java @@ -75,17 +75,13 @@ public List onGetChooserTargets(ComponentName targetActivityName, int lower_id = (int) id; int high_id = (int) (id >> 32); if (lower_id != 0) { - if (high_id == 1) { - continue; + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); + } } else { - if (lower_id > 0) { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); } } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 6da013ac464..f3326f40cca 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -102,8 +102,8 @@ public static Integer parseInt(CharSequence value) { String num = matcher.group(0); val = Integer.parseInt(num); } - } catch (Exception e) { - FileLog.e(e); + } catch (Exception ignore) { + } return val; } @@ -119,8 +119,8 @@ public static Long parseLong(String value) { String num = matcher.group(0); val = Long.parseLong(num); } - } catch (Exception e) { - FileLog.e(e); + } catch (Exception ignore) { + } return val; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index ce3c5c0353e..c6ced4fc00d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -31,7 +31,12 @@ public IBinder onBind(Intent arg2) { } public void onDestroy() { - stopForeground(true); + super.onDestroy(); + try { + stopForeground(true); + } catch (Throwable ignore) { + + } NotificationManagerCompat.from(ApplicationLoader.applicationContext).cancel(4); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopEncodingService); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.FileUploadProgressChanged); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java index 06b02dc8d48..03fe6664117 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java @@ -1,11 +1,8 @@ package org.telegram.messenger; -import androidx.annotation.NonNull; import android.text.TextUtils; import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.Task; import com.google.android.gms.wearable.CapabilityClient; import com.google.android.gms.wearable.CapabilityInfo; import com.google.android.gms.wearable.Channel; @@ -81,42 +78,31 @@ public void onChannelOpened(final Channel ch) { final File photo = FileLoader.getPathToAttach(user.photo.photo_small, true); final CyclicBarrier barrier = new CyclicBarrier(2); if (!photo.exists()) { - final NotificationCenter.NotificationCenterDelegate listener = new NotificationCenter.NotificationCenterDelegate() { - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.fileDidLoad) { + final NotificationCenter.NotificationCenterDelegate listener = (id, account, args) -> { + if (id == NotificationCenter.fileDidLoad) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("file loaded: " + args[0] + " " + args[0].getClass().getName()); + } + if (args[0].equals(photo.getName())) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("file loaded: " + args[0] + " " + args[0].getClass().getName()); + FileLog.e("LOADED USER PHOTO"); } - if (args[0].equals(photo.getName())) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("LOADED USER PHOTO"); - } - try { - barrier.await(10, TimeUnit.MILLISECONDS); - } catch (Exception ignore) { - } + try { + barrier.await(10, TimeUnit.MILLISECONDS); + } catch (Exception ignore) { } } } }; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance(currentAccount).addObserver(listener, NotificationCenter.fileDidLoad); - FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForUser(user, false), user, null, 1, 1); - } + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).addObserver(listener, NotificationCenter.fileDidLoad); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForUser(user, false), user, null, 1, 1); }); try { barrier.await(10, TimeUnit.SECONDS); } catch (Exception ignore) { } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance(currentAccount).removeObserver(listener, NotificationCenter.fileDidLoad); - } - }); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).removeObserver(listener, NotificationCenter.fileDidLoad)); } if (photo.exists() && photo.length() <= 50 * 1024 * 1024) { byte[] photoData = new byte[(int) photo.length()]; @@ -140,23 +126,20 @@ public void run() { ConnectionsManager.getInstance(currentAccount).setAppPaused(false, false); final String[] code = {null}; final CyclicBarrier barrier = new CyclicBarrier(2); - final NotificationCenter.NotificationCenterDelegate listener = new NotificationCenter.NotificationCenterDelegate() { - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.didReceiveNewMessages) { - long did = (Long) args[0]; - if (did == 777000) { - ArrayList arr = (ArrayList) args[1]; - if (arr.size() > 0) { - MessageObject msg = arr.get(0); - if (!TextUtils.isEmpty(msg.messageText)) { - Matcher matcher = Pattern.compile("[0-9]+").matcher(msg.messageText); - if (matcher.find()) { - code[0] = matcher.group(); - try { - barrier.await(10, TimeUnit.MILLISECONDS); - } catch (Exception ignore) { - } + final NotificationCenter.NotificationCenterDelegate listener = (id, account, args) -> { + if (id == NotificationCenter.didReceiveNewMessages) { + long did = (Long) args[0]; + if (did == 777000) { + ArrayList arr = (ArrayList) args[1]; + if (arr.size() > 0) { + MessageObject msg = arr.get(0); + if (!TextUtils.isEmpty(msg.messageText)) { + Matcher matcher = Pattern.compile("[0-9]+").matcher(msg.messageText); + if (matcher.find()) { + code[0] = matcher.group(); + try { + barrier.await(10, TimeUnit.MILLISECONDS); + } catch (Exception ignore) { } } } @@ -164,81 +147,67 @@ public void didReceivedNotification(int id, int account, Object... args) { } } }; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance(currentAccount).addObserver(listener, NotificationCenter.didReceiveNewMessages); - } - }); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).addObserver(listener, NotificationCenter.didReceiveNewMessages)); try { barrier.await(30, TimeUnit.SECONDS); } catch (Exception ignore) { } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance(currentAccount).removeObserver(listener, NotificationCenter.didReceiveNewMessages); - } - }); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).removeObserver(listener, NotificationCenter.didReceiveNewMessages)); DataOutputStream out = new DataOutputStream(ch.getOutputStream(apiClient).await().getOutputStream()); - if (code[0] != null) + if (code[0] != null) { out.writeUTF(code[0]); - else + } else { out.writeUTF(""); + } out.flush(); out.close(); ConnectionsManager.getInstance(currentAccount).setAppPaused(true, false); - } else if("/getChatPhoto".equals(path)){ - DataInputStream in=new DataInputStream(ch.getInputStream(apiClient).await().getInputStream()); - DataOutputStream out=new DataOutputStream(ch.getOutputStream(apiClient).await().getOutputStream()); - try{ - String _req=in.readUTF(); - JSONObject req=new JSONObject(_req); - int chatID=req.getInt("chat_id"); - int accountID=req.getInt("account_id"); - int currentAccount=-1; - for(int i=0;i0){ + if (currentAccount != -1) { + TLRPC.FileLocation location = null; + if (chatID > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(chatID); - if(user!=null && user.photo!=null) - location=user.photo.photo_small; - }else{ - TLRPC.Chat chat=MessagesController.getInstance(currentAccount).getChat(-chatID); - if(chat!=null && chat.photo!=null) - location=chat.photo.photo_small; + if (user != null && user.photo != null) + location = user.photo.photo_small; + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-chatID); + if (chat != null && chat.photo != null) + location = chat.photo.photo_small; } - if(location!=null){ - File file=FileLoader.getPathToAttach(location, true); - if(file.exists() && file.length()<102400){ + if (location != null) { + File file = FileLoader.getPathToAttach(location, true); + if (file.exists() && file.length() < 102400) { out.writeInt((int) file.length()); - FileInputStream fin=new FileInputStream(file); - byte[] buf=new byte[10240]; + FileInputStream fin = new FileInputStream(file); + byte[] buf = new byte[10240]; int read; - while((read=fin.read(buf))>0){ + while ((read = fin.read(buf)) > 0) { out.write(buf, 0, read); } fin.close(); - }else{ + } else { out.writeInt(0); } - }else{ + } else { out.writeInt(0); } - }else{ + } else { out.writeInt(0); } out.flush(); - }catch(Exception ignore){ - }finally{ - in.close(); - out.close(); + } catch (Exception ignore) { } } } catch (Exception x) { @@ -256,89 +225,81 @@ public void run() { } @Override - public void onMessageReceived(final MessageEvent messageEvent){ - if("/reply".equals(messageEvent.getPath())){ - AndroidUtilities.runOnUIThread(new Runnable(){ - @Override - public void run(){ - try{ - ApplicationLoader.postInitApplication(); - String data=new String(messageEvent.getData(), "UTF-8"); - JSONObject r=new JSONObject(data); - CharSequence text = r.getString("text"); - if (text == null || text.length() == 0) { - return; - } - long dialog_id = r.getLong("chat_id"); - int max_id = r.getInt("max_id"); - int currentAccount = -1; - int accountID=r.getInt("account_id"); - for(int i=0;i { + try { + ApplicationLoader.postInitApplication(); + String data = new String(messageEvent.getData(), "UTF-8"); + JSONObject r = new JSONObject(data); + CharSequence text = r.getString("text"); + if (text == null || text.length() == 0) { + return; + } + long dialog_id = r.getLong("chat_id"); + int max_id = r.getInt("max_id"); + int currentAccount = -1; + int accountID = r.getInt("account_id"); + for (int i = 0; i < UserConfig.getActivatedAccountsCount(); i++) { + if (UserConfig.getInstance(i).getClientUserId() == accountID) { + currentAccount = i; + break; } - SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialog_id, null, null, true, null, null, null); - MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); - }catch(Exception x){ - if(BuildVars.LOGS_ENABLED) - FileLog.e(x); } + if (dialog_id == 0 || max_id == 0 || currentAccount == -1) { + return; + } + SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialog_id, null, null, true, null, null, null, true, 0); + MessagesController.getInstance(currentAccount).markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); + } catch (Exception x) { + if (BuildVars.LOGS_ENABLED) + FileLog.e(x); } }); } } - public static void sendMessageToWatch(final String path, final byte[] data, String capability){ + public static void sendMessageToWatch(final String path, final byte[] data, String capability) { Wearable.getCapabilityClient(ApplicationLoader.applicationContext) .getCapability(capability, CapabilityClient.FILTER_REACHABLE) - .addOnCompleteListener(new OnCompleteListener(){ - @Override - public void onComplete(@NonNull Task task){ - CapabilityInfo info=task.getResult(); - if(info!=null){ - MessageClient mc=Wearable.getMessageClient(ApplicationLoader.applicationContext); - Set nodes=info.getNodes(); - for(Node node:nodes){ - mc.sendMessage(node.getId(), path, data); - } + .addOnCompleteListener(task -> { + CapabilityInfo info = task.getResult(); + if (info != null) { + MessageClient mc = Wearable.getMessageClient(ApplicationLoader.applicationContext); + Set nodes = info.getNodes(); + for (Node node : nodes) { + mc.sendMessage(node.getId(), path, data); } } }); } @Override - public void onCapabilityChanged(CapabilityInfo capabilityInfo){ - if("remote_notifications".equals(capabilityInfo.getName())){ - watchConnected=false; - for(Node node:capabilityInfo.getNodes()){ - if(node.isNearby()) - watchConnected=true; + public void onCapabilityChanged(CapabilityInfo capabilityInfo) { + if ("remote_notifications".equals(capabilityInfo.getName())) { + watchConnected = false; + for (Node node : capabilityInfo.getNodes()) { + if (node.isNearby()) + watchConnected = true; } } } - public static void updateWatchConnectionState(){ + public static void updateWatchConnectionState() { try { Wearable.getCapabilityClient(ApplicationLoader.applicationContext) .getCapability("remote_notifications", CapabilityClient.FILTER_REACHABLE) - .addOnCompleteListener(new OnCompleteListener(){ - @Override - public void onComplete(@NonNull Task task){ - watchConnected=false; - try{ - CapabilityInfo capabilityInfo=task.getResult(); - if(capabilityInfo==null) - return; - for(Node node : capabilityInfo.getNodes()){ - if(node.isNearby()) - watchConnected=true; - } - }catch(Exception ignore){} + .addOnCompleteListener(task -> { + watchConnected = false; + try { + CapabilityInfo capabilityInfo = task.getResult(); + if (capabilityInfo == null) + return; + for (Node node : capabilityInfo.getNodes()) { + if (node.isNearby()) + watchConnected = true; + } + } catch (Exception ignore) { } }); } catch (Throwable ignore) { @@ -346,7 +307,7 @@ public void onComplete(@NonNull Task task){ } } - public static boolean isWatchConnected(){ + public static boolean isWatchConnected() { return watchConnected; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java index 6903e8cde0f..0da0e1eba42 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java @@ -69,7 +69,7 @@ public void onReceive(Context context, Intent intent) { } private void sendMessage(AccountInstance accountInstance, CharSequence text, long dialog_id, int max_id) { - accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, null, null, true, null, null, null); - accountInstance.getMessagesController().markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true); + accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, null, null, true, null, null, null, true, 0); + accountInstance.getMessagesController().markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, true, 0); } } 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 920ca04571e..6f70784cdcd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -41,6 +41,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.LaunchActivity; import java.lang.ref.WeakReference; @@ -286,7 +287,8 @@ public static void openUrl(final Context context, Uri uri, final boolean allowCu CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession()); builder.addMenuItem(LocaleController.getString("CopyLink", R.string.CopyLink), copy); - builder.setToolbarColor(0xffffffff); + + builder.setToolbarColor(Theme.getColor(Theme.key_actionBarBrowser)); builder.setShowTitle(true); builder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha), LocaleController.getString("ShareFile", R.string.ShareFile), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, share, 0), false); CustomTabsIntent intent = builder.build(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/ArrayUtils.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/ArrayUtils.java index 5f6998fe82f..0aca568f287 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/ArrayUtils.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/ArrayUtils.java @@ -134,6 +134,17 @@ public static boolean contains(int[] array, int value) { return false; } + public static int indexOf(int[] array, int value) { + if (array != null) { + for (int a = 0; a < array.length; a++) { + if (array[a] == value) { + return a; + } + } + } + return -1; + } + public static long total(long[] array) { long total = 0; for (long value : array) { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index e5709674859..b4b284a7a5c 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -61,7 +61,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_EDITED = 0x00008000; public static final int MESSAGE_FLAG_MEGAGROUP = 0x80000000; - public static final int LAYER = 104; + public static final int LAYER = 105; public static class TL_chatBannedRights extends TLObject { public static int constructor = 0x9f120418; @@ -1835,6 +1835,37 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageUserReaction extends TLObject { + public static int constructor = 0xd267dcbc; + + public int user_id; + public String reaction; + + public static TL_messageUserReaction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messageUserReaction.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messageUserReaction", constructor)); + } else { + return null; + } + } + TL_messageUserReaction result = new TL_messageUserReaction(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + user_id = stream.readInt32(exception); + reaction = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(user_id); + stream.writeString(reaction); + } + } + public static abstract class auth_Authorization extends TLObject { public static auth_Authorization TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -2218,6 +2249,9 @@ public static messages_Messages TLdeserialize(AbstractSerializedData stream, int case 0xc8edce1e: result = new TL_messages_messagesSlice(); break; + case 0x74535f21: + result = new TL_messages_messagesNotModified(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in messages_Messages", constructor)); @@ -2474,6 +2508,20 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messages_messagesNotModified extends messages_Messages { + public static int constructor = 0x74535f21; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(count); + } + } + public static class TL_payments_paymentForm extends TLObject { public static int constructor = 0x3f56aea3; @@ -3641,6 +3689,9 @@ public static PrivacyKey TLdeserialize(AbstractSerializedData stream, int constr case 0x500e6dfa: result = new TL_privacyKeyChatInvite(); break; + case 0x42ffd42b: + result = new TL_privacyKeyAddedByPhone(); + break; case 0x3d662b7b: result = new TL_privacyKeyPhoneCall(); break; @@ -3700,6 +3751,15 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_privacyKeyAddedByPhone extends PrivacyKey { + public static int constructor = 0x42ffd42b; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_privacyKeyForwards extends PrivacyKey { public static int constructor = 0x69ec56a3; @@ -6640,6 +6700,88 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageReactionsList extends TLObject { + public static int constructor = 0xe3ae6108; + + public int flags; + public int count; + public ArrayList reactions = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + public String next_offset; + + public static TL_messageReactionsList TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messageReactionsList.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messageReactionsList", constructor)); + } else { + return null; + } + } + TL_messageReactionsList result = new TL_messageReactionsList(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + count = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_messageUserReaction object = TL_messageUserReaction.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + reactions.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); + } + if ((flags & 1) != 0) { + next_offset = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(count); + stream.writeInt32(0x1cb5c415); + int count = reactions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + reactions.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); + } + if ((flags & 1) != 0) { + stream.writeString(next_offset); + } + } + } + public static class TL_messages_stickerSet extends TLObject { public static int constructor = 0xb60a24a6; @@ -7529,6 +7671,9 @@ public static InputPrivacyKey TLdeserialize(AbstractSerializedData stream, int c case 0x352dafa: result = new TL_inputPrivacyKeyPhoneNumber(); break; + case 0xd1219bdd: + result = new TL_inputPrivacyKeyAddedByPhone(); + break; case 0xdb9e70d2: result = new TL_inputPrivacyKeyPhoneP2P(); break; @@ -7588,6 +7733,15 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_inputPrivacyKeyAddedByPhone extends InputPrivacyKey { + public static int constructor = 0xd1219bdd; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_inputPrivacyKeyProfilePhoto extends InputPrivacyKey { public static int constructor = 0x5719bacc; @@ -7606,6 +7760,61 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static abstract class InputTheme extends TLObject { + + public static InputTheme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + InputTheme result = null; + switch (constructor) { + case 0xf5890df1: + result = new TL_inputThemeSlug(); + break; + case 0x3c5693e9: + result = new TL_inputTheme(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputTheme", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_inputThemeSlug extends InputTheme { + public static int constructor = 0xf5890df1; + + public String slug; + + public void readParams(AbstractSerializedData stream, boolean exception) { + slug = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + } + } + + public static class TL_inputTheme extends InputTheme { + public static int constructor = 0x3c5693e9; + + public long id; + public long access_hash; + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + } + } + public static abstract class photos_Photos extends TLObject { public ArrayList photos = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -7751,6 +7960,7 @@ public static abstract class ChatFull extends TLObject { public int flags; public boolean can_view_participants; public boolean can_set_username; + public boolean has_scheduled; public String about; public int participants_count; public int admins_count; @@ -7855,6 +8065,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { hidden_prehistory = (flags & 1024) != 0; can_view_stats = (flags & 4096) != 0; can_set_location = (flags & 65536) != 0; + has_scheduled = (flags & 524288) != 0; id = stream.readInt32(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -7934,6 +8145,7 @@ public void serializeToStream(AbstractSerializedData stream) { 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); stream.writeInt32(flags); stream.writeInt32(id); stream.writeString(about); @@ -8913,6 +9125,7 @@ public static class TL_chatFull extends ChatFull { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); can_set_username = (flags & 128) != 0; + has_scheduled = (flags & 256) != 0; id = stream.readInt32(exception); about = stream.readString(exception); participants = ChatParticipants.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -8949,6 +9162,7 @@ public void readParams(AbstractSerializedData stream, boolean 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.writeInt32(id); stream.writeString(about); @@ -10963,14 +11177,18 @@ public static abstract class WebPage extends TLObject { public int duration; public String author; public Document document; + public ArrayList documents = new ArrayList<>(); public Page cached_page; public int date; public static WebPage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { WebPage result = null; switch (constructor) { + case 0xfa64e172: + result = new TL_webPage(); + break; case 0x5f07b4bc: - result = new TL_webPage(); + result = new TL_webPage_layer104(); break; case 0xa31ea0b5: result = new TL_webPage_old(); @@ -11001,7 +11219,132 @@ public static WebPage TLdeserialize(AbstractSerializedData stream, int construct } } - public static class TL_webPage extends WebPage { + public static class TL_webPage extends WebPage { + public static int constructor = 0xfa64e172; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + id = stream.readInt64(exception); + url = stream.readString(exception); + display_url = stream.readString(exception); + hash = stream.readInt32(exception); + if ((flags & 1) != 0) { + type = stream.readString(exception); + } + if ((flags & 2) != 0) { + site_name = stream.readString(exception); + } + if ((flags & 4) != 0) { + title = stream.readString(exception); + } + if ((flags & 8) != 0) { + description = stream.readString(exception); + } + if ((flags & 16) != 0) { + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + embed_url = stream.readString(exception); + } + if ((flags & 32) != 0) { + embed_type = stream.readString(exception); + } + if ((flags & 64) != 0) { + embed_width = stream.readInt32(exception); + } + if ((flags & 64) != 0) { + embed_height = stream.readInt32(exception); + } + if ((flags & 128) != 0) { + duration = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + author = stream.readString(exception); + } + if ((flags & 512) != 0) { + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2048) != 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; + } + documents.add(object); + } + } + if ((flags & 1024) != 0) { + cached_page = Page.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeString(url); + stream.writeString(display_url); + stream.writeInt32(hash); + if ((flags & 1) != 0) { + stream.writeString(type); + } + if ((flags & 2) != 0) { + stream.writeString(site_name); + } + if ((flags & 4) != 0) { + stream.writeString(title); + } + if ((flags & 8) != 0) { + stream.writeString(description); + } + if ((flags & 16) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + stream.writeString(embed_url); + } + if ((flags & 32) != 0) { + stream.writeString(embed_type); + } + if ((flags & 64) != 0) { + stream.writeInt32(embed_width); + } + if ((flags & 64) != 0) { + stream.writeInt32(embed_height); + } + if ((flags & 128) != 0) { + stream.writeInt32(duration); + } + if ((flags & 256) != 0) { + stream.writeString(author); + } + if ((flags & 512) != 0) { + document.serializeToStream(stream); + } + if ((flags & 2048) != 0) { + stream.writeInt32(0x1cb5c415); + int count = documents.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + documents.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + cached_page.serializeToStream(stream); + } + } + } + + public static class TL_webPage_layer104 extends TL_webPage { public static int constructor = 0x5f07b4bc; @@ -12671,11 +13014,11 @@ public static abstract class User extends TLObject { public boolean support; public boolean scam; public int bot_info_version; - public String restriction_reason; public String bot_inline_placeholder; public String lang_code; public boolean inactive; public boolean explicit_content; + public ArrayList restriction_reason = new ArrayList<>(); public static User TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { User result = null; @@ -12686,8 +13029,11 @@ public static User TLdeserialize(AbstractSerializedData stream, int constructor, case 0xf2fb8319: result = new TL_userContact_old(); break; + case 0x938458c1: + result = new TL_user(); + break; case 0x2e13f4c3: - result = new TL_user(); + result = new TL_user_layer104(); break; case 0x720535ec: result = new TL_userSelf_old(); @@ -12791,6 +13137,133 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_user extends User { + public static int constructor = 0x938458c1; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + self = (flags & 1024) != 0; + contact = (flags & 2048) != 0; + mutual_contact = (flags & 4096) != 0; + deleted = (flags & 8192) != 0; + bot = (flags & 16384) != 0; + bot_chat_history = (flags & 32768) != 0; + bot_nochats = (flags & 65536) != 0; + verified = (flags & 131072) != 0; + restricted = (flags & 262144) != 0; + min = (flags & 1048576) != 0; + bot_inline_geo = (flags & 2097152) != 0; + support = (flags & 8388608) != 0; + scam = (flags & 16777216) != 0; + id = stream.readInt32(exception); + if ((flags & 1) != 0) { + access_hash = stream.readInt64(exception); + } + if ((flags & 2) != 0) { + first_name = stream.readString(exception); + } + if ((flags & 4) != 0) { + last_name = stream.readString(exception); + } + if ((flags & 8) != 0) { + username = stream.readString(exception); + } + if ((flags & 16) != 0) { + phone = stream.readString(exception); + } + if ((flags & 32) != 0) { + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 64) != 0) { + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16384) != 0) { + bot_info_version = stream.readInt32(exception); + } + if ((flags & 262144) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 524288) != 0) { + bot_inline_placeholder = stream.readString(exception); + } + if ((flags & 4194304) != 0) { + lang_code = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = self ? (flags | 1024) : (flags &~ 1024); + flags = contact ? (flags | 2048) : (flags &~ 2048); + flags = mutual_contact ? (flags | 4096) : (flags &~ 4096); + flags = deleted ? (flags | 8192) : (flags &~ 8192); + flags = bot ? (flags | 16384) : (flags &~ 16384); + flags = bot_chat_history ? (flags | 32768) : (flags &~ 32768); + flags = bot_nochats ? (flags | 65536) : (flags &~ 65536); + flags = verified ? (flags | 131072) : (flags &~ 131072); + flags = restricted ? (flags | 262144) : (flags &~ 262144); + flags = min ? (flags | 1048576) : (flags &~ 1048576); + flags = bot_inline_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = support ? (flags | 8388608) : (flags &~ 8388608); + flags = scam ? (flags | 16777216) : (flags &~ 16777216); + stream.writeInt32(flags); + stream.writeInt32(id); + if ((flags & 1) != 0) { + stream.writeInt64(access_hash); + } + if ((flags & 2) != 0) { + stream.writeString(first_name); + } + if ((flags & 4) != 0) { + stream.writeString(last_name); + } + if ((flags & 8) != 0) { + stream.writeString(username); + } + if ((flags & 16) != 0) { + stream.writeString(phone); + } + if ((flags & 32) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 64) != 0) { + status.serializeToStream(stream); + } + if ((flags & 16384) != 0) { + stream.writeInt32(bot_info_version); + } + if ((flags & 262144) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 524288) != 0) { + stream.writeString(bot_inline_placeholder); + } + if ((flags & 4194304) != 0) { + stream.writeString(lang_code); + } + } + } + + public static class TL_user_layer104 extends TL_user { public static int constructor = 0x2e13f4c3; @@ -12835,7 +13308,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { bot_info_version = stream.readInt32(exception); } if ((flags & 262144) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 524288) != 0) { bot_inline_placeholder = stream.readString(exception); @@ -12887,7 +13360,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(bot_info_version); } if ((flags & 262144) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 524288) != 0) { stream.writeString(bot_inline_placeholder); @@ -13149,7 +13622,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { bot_info_version = stream.readInt32(exception); } if ((flags & 262144) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 524288) != 0) { bot_inline_placeholder = stream.readString(exception); @@ -13196,7 +13669,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(bot_info_version); } if ((flags & 262144) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 524288) != 0) { stream.writeString(bot_inline_placeholder); @@ -14683,6 +15156,74 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static abstract class account_Themes extends TLObject { + + public static account_Themes TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + account_Themes result = null; + switch (constructor) { + case 0x7f676421: + result = new TL_account_themes(); + break; + case 0xf41eb622: + result = new TL_account_themesNotModified(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in account_Themes", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_account_themes extends account_Themes { + public static int constructor = 0x7f676421; + + public int hash; + public ArrayList themes = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + hash = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Theme object = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + themes.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(hash); + stream.writeInt32(0x1cb5c415); + int count = themes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + themes.get(a).serializeToStream(stream); + } + } + } + + public static class TL_account_themesNotModified extends account_Themes { + public static int constructor = 0xf41eb622; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_invoice extends TLObject { public static int constructor = 0xc30aa358; @@ -14884,6 +15425,59 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageReactions extends TLObject { + public static int constructor = 0xb87a24d1; + + public int flags; + public boolean min; + public ArrayList results = new ArrayList<>(); + + public static TL_messageReactions TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messageReactions.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messageReactions", constructor)); + } else { + return null; + } + } + TL_messageReactions result = new TL_messageReactions(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + min = (flags & 1) != 0; + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_reactionCount object = TL_reactionCount.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + results.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = min ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(0x1cb5c415); + int count = results.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + results.get(a).serializeToStream(stream); + } + } + } + public static abstract class Video extends TLObject { public long id; public long access_hash; @@ -18601,6 +19195,9 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case 0x1f2b0afd: result = new TL_updateNewMessage(); break; + case 0x39a51dfb: + result = new TL_updateNewScheduledMessage(); + break; case 0x12bcbd9a: result = new TL_updateNewEncryptedMessage(); break; @@ -18685,6 +19282,9 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case 0xab0f6b1e: result = new TL_updatePhoneCall(); break; + case 0x154798c3: + result = new TL_updateMessageReactions(); + break; case 0xfa0f3ca2: result = new TL_updatePinnedDialogs(); break; @@ -18706,6 +19306,9 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case 0x40771900: result = new TL_updateChannelWebPage(); break; + case 0x90866cee: + result = new TL_updateDeleteScheduledMessages(); + break; case 0xc37521c9: result = new TL_updateDeleteChannelMessages(); break; @@ -18727,6 +19330,9 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case 0x46560264: result = new TL_updateLangPackTooLong(); break; + case 0x8216fba3: + result = new TL_updateTheme(); + break; case 0x38fe25b7: result = new TL_updateEncryptedMessagesRead(); break; @@ -19067,6 +19673,21 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_updateNewScheduledMessage extends Update { + public static int constructor = 0x39a51dfb; + + public Message message; + + public void readParams(AbstractSerializedData stream, boolean exception) { + message = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + message.serializeToStream(stream); + } + } + public static class TL_updateNewEncryptedMessage extends Update { public static int constructor = 0x12bcbd9a; @@ -19709,6 +20330,27 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_updateMessageReactions extends Update { + public static int constructor = 0x154798c3; + + public Peer peer; + public int msg_id; + public TL_messageReactions reactions; + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + msg_id = stream.readInt32(exception); + reactions = TL_messageReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + reactions.serializeToStream(stream); + } + } + public static class TL_updatePinnedDialogs extends Update { public static int constructor = 0xfa0f3ca2; @@ -19860,6 +20502,39 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_updateDeleteScheduledMessages extends Update { + public static int constructor = 0x90866cee; + + public Peer peer; + public ArrayList messages = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = Peer.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++) { + messages.add(stream.readInt32(exception)); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(messages.get(a)); + } + } + } + public static class TL_updateDeleteChannelMessages extends Update { public static int constructor = 0xc37521c9; @@ -20026,6 +20701,21 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_updateTheme extends Update { + public static int constructor = 0x8216fba3; + + public Theme theme; + + public void readParams(AbstractSerializedData stream, boolean exception) { + theme = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + theme.serializeToStream(stream); + } + } + public static class TL_updateEncryptedMessagesRead extends Update { public static int constructor = 0x38fe25b7; @@ -23076,6 +23766,80 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static abstract class Theme extends TLObject { + + public static Theme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + Theme result = null; + switch (constructor) { + case 0x483d270c: + result = new TL_themeDocumentNotModified(); + break; + case 0xf7d90ce0: + result = new TL_theme(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Theme", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_themeDocumentNotModified extends Theme { + public static int constructor = 0x483d270c; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_theme extends Theme { + public static int constructor = 0xf7d90ce0; + + public int flags; + public boolean creator; + public boolean isDefault; + public long id; + public long access_hash; + public String slug; + public String title; + public Document document; + public int installs_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + isDefault = (flags & 2) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + slug = stream.readString(exception); + title = stream.readString(exception); + if ((flags & 4) != 0) { + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + } + installs_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = isDefault ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(slug); + stream.writeString(title); + if ((flags & 4) != 0) { + document.serializeToStream(stream); + } + stream.writeInt32(installs_count); + } + } + public static abstract class updates_ChannelDifference extends TLObject { public int flags; public boolean isFinal; @@ -26283,11 +27047,11 @@ public static abstract class Chat extends TLObject { public boolean restricted; public boolean signatures; public String username; - public String restriction_reason; public boolean min; public boolean scam; public boolean has_link; public boolean explicit_content; + public ArrayList restriction_reason = new ArrayList<>(); public TL_channelAdminRights_layer92 admin_rights_layer92; public TL_channelBannedRights_layer92 banned_rights_layer92; public TL_chatAdminRights admin_rights; @@ -26341,6 +27105,9 @@ public static Chat TLdeserialize(AbstractSerializedData stream, int constructor, result = new TL_channel_layer77(); break; case 0x4df30834: + result = new TL_channel_layer104(); + break; + case 0xd31a961e: result = new TL_channel(); break; case 0xc88974ac: @@ -26578,7 +27345,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } } @@ -26604,7 +27371,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } } } @@ -26670,7 +27437,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } } @@ -26699,7 +27466,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } } } @@ -26777,6 +27544,115 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_channel extends Chat { + public static int constructor = 0xd31a961e; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + left = (flags & 4) != 0; + broadcast = (flags & 32) != 0; + verified = (flags & 128) != 0; + megagroup = (flags & 256) != 0; + restricted = (flags & 512) != 0; + signatures = (flags & 2048) != 0; + min = (flags & 4096) != 0; + scam = (flags & 524288) != 0; + has_link = (flags & 1048576) != 0; + has_geo = (flags & 2097152) != 0; + slowmode_enabled = (flags & 4194304) != 0; + id = stream.readInt32(exception); + if ((flags & 8192) != 0) { + access_hash = stream.readInt64(exception); + } + title = stream.readString(exception); + if ((flags & 64) != 0) { + username = stream.readString(exception); + } + photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + date = stream.readInt32(exception); + version = stream.readInt32(exception); + if ((flags & 512) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 16384) != 0) { + admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32768) != 0) { + banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 262144) != 0) { + default_banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 131072) != 0) { + participants_count = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = left ? (flags | 4) : (flags &~ 4); + flags = broadcast ? (flags | 32) : (flags &~ 32); + flags = verified ? (flags | 128) : (flags &~ 128); + flags = megagroup ? (flags | 256) : (flags &~ 256); + flags = restricted ? (flags | 512) : (flags &~ 512); + flags = signatures ? (flags | 2048) : (flags &~ 2048); + flags = min ? (flags | 4096) : (flags &~ 4096); + flags = scam ? (flags | 524288) : (flags &~ 524288); + flags = has_link ? (flags | 1048576) : (flags &~ 1048576); + flags = has_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = slowmode_enabled ? (flags | 4194304) : (flags &~ 4194304); + stream.writeInt32(flags); + stream.writeInt32(id); + if ((flags & 8192) != 0) { + stream.writeInt64(access_hash); + } + stream.writeString(title); + if ((flags & 64) != 0) { + stream.writeString(username); + } + photo.serializeToStream(stream); + stream.writeInt32(date); + stream.writeInt32(version); + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 16384) != 0) { + admin_rights.serializeToStream(stream); + } + if ((flags & 32768) != 0) { + banned_rights.serializeToStream(stream); + } + if ((flags & 262144) != 0) { + default_banned_rights.serializeToStream(stream); + } + if ((flags & 131072) != 0) { + stream.writeInt32(participants_count); + } + } + } + + public static class TL_channel_layer104 extends TL_channel { public static int constructor = 0x4df30834; @@ -26806,7 +27682,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 16384) != 0) { admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -26849,7 +27725,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 16384) != 0) { admin_rights.serializeToStream(stream); @@ -26916,7 +27792,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 16384) != 0) { admin_rights_layer92 = TL_channelAdminRights_layer92.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -26954,7 +27830,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 16384) != 0) { admin_rights_layer92.serializeToStream(stream); @@ -26993,7 +27869,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 16384) != 0) { admin_rights_layer92 = TL_channelAdminRights_layer92.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -27029,7 +27905,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 16384) != 0) { admin_rights_layer92.serializeToStream(stream); @@ -27065,7 +27941,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { date = stream.readInt32(exception); version = stream.readInt32(exception); if ((flags & 512) != 0) { - restriction_reason = stream.readString(exception); + stream.readString(exception); } if ((flags & 16384) != 0) { admin_rights_layer92 = TL_channelAdminRights_layer92.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -27103,7 +27979,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(date); stream.writeInt32(version); if ((flags & 512) != 0) { - stream.writeString(restriction_reason); + stream.writeString(""); } if ((flags & 16384) != 0) { admin_rights_layer92.serializeToStream(stream); @@ -27156,6 +28032,40 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_restrictionReason extends TLObject { + public static int constructor = 0xd072acb4; + + public String platform; + public String reason; + public String text; + + public static TL_restrictionReason TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_restrictionReason.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_restrictionReason", constructor)); + } else { + return null; + } + } + TL_restrictionReason result = new TL_restrictionReason(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + platform = stream.readString(exception); + reason = stream.readString(exception); + text = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(platform); + stream.writeString(reason); + stream.writeString(text); + } + } + public static abstract class StickerSet extends TLObject { public int flags; @@ -28726,6 +29636,43 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_reactionCount extends TLObject { + public static int constructor = 0x6fb250d1; + + public int flags; + public boolean chosen; + public String reaction; + public int count; + + public static TL_reactionCount TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_reactionCount.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_reactionCount", constructor)); + } else { + return null; + } + } + TL_reactionCount result = new TL_reactionCount(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + chosen = (flags & 1) != 0; + reaction = stream.readString(exception); + count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = chosen ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeString(reaction); + stream.writeInt32(count); + } + } + public static abstract class UserFull extends TLObject { public int flags; @@ -28733,6 +29680,7 @@ public static abstract class UserFull extends TLObject { public boolean phone_calls_available; public boolean phone_calls_private; public boolean can_pin_message; + public boolean has_scheduled; public User user; public String about; public TL_contacts_link_layer101 link; @@ -28891,6 +29839,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { phone_calls_available = (flags & 16) != 0; phone_calls_private = (flags & 32) != 0; can_pin_message = (flags & 128) != 0; + has_scheduled = (flags & 4096) != 0; user = User.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 2) != 0) { about = stream.readString(exception); @@ -28918,6 +29867,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = phone_calls_available ? (flags | 16) : (flags &~ 16); flags = phone_calls_private ? (flags | 32) : (flags &~ 32); flags = can_pin_message ? (flags | 128) : (flags &~ 128); + flags = has_scheduled ? (flags | 4096) : (flags &~ 4096); stream.writeInt32(flags); user.serializeToStream(stream); if ((flags & 2) != 0) { @@ -32214,138 +33164,150 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_messages_sendMessage extends TLObject { - public static int constructor = 0xfa88427a; + public static class TL_messages_sendMessage extends TLObject { + public static int constructor = 0x520c3870; - public int flags; - public boolean no_webpage; - public boolean silent; - public boolean background; - public boolean clear_draft; - public InputPeer peer; - public int reply_to_msg_id; - public String message; - public long random_id; - public ReplyMarkup reply_markup; - public ArrayList entities = new ArrayList<>(); + public int flags; + public boolean no_webpage; + public boolean silent; + public boolean background; + public boolean clear_draft; + public InputPeer peer; + public int reply_to_msg_id; + public String message; + public long random_id; + public ReplyMarkup reply_markup; + public ArrayList entities = new ArrayList<>(); + public int schedule_date; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = no_webpage ? (flags | 2) : (flags &~ 2); - flags = silent ? (flags | 32) : (flags &~ 32); - flags = background ? (flags | 64) : (flags &~ 64); - flags = clear_draft ? (flags | 128) : (flags &~ 128); - stream.writeInt32(flags); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeInt32(reply_to_msg_id); - } - stream.writeString(message); - stream.writeInt64(random_id); - if ((flags & 4) != 0) { - reply_markup.serializeToStream(stream); - } - if ((flags & 8) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = no_webpage ? (flags | 2) : (flags &~ 2); + flags = silent ? (flags | 32) : (flags &~ 32); + flags = background ? (flags | 64) : (flags &~ 64); + flags = clear_draft ? (flags | 128) : (flags &~ 128); + stream.writeInt32(flags); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeString(message); + stream.writeInt64(random_id); + if ((flags & 4) != 0) { + reply_markup.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(schedule_date); + } + } + } - public static class TL_messages_sendMedia extends TLObject { - public static int constructor = 0xb8d1262b; + public static class TL_messages_sendMedia extends TLObject { + public static int constructor = 0x3491eba9; - public int flags; - public boolean silent; - public boolean background; - public boolean clear_draft; - public InputPeer peer; - public int reply_to_msg_id; - public InputMedia media; - public String message; - public long random_id; - public ReplyMarkup reply_markup; - public ArrayList entities = new ArrayList<>(); + public int flags; + public boolean silent; + public boolean background; + public boolean clear_draft; + public InputPeer peer; + public int reply_to_msg_id; + public InputMedia media; + public String message; + public long random_id; + public ReplyMarkup reply_markup; + public ArrayList entities = new ArrayList<>(); + public int schedule_date; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = silent ? (flags | 32) : (flags &~ 32); - flags = background ? (flags | 64) : (flags &~ 64); - flags = clear_draft ? (flags | 128) : (flags &~ 128); - stream.writeInt32(flags); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeInt32(reply_to_msg_id); - } - media.serializeToStream(stream); - stream.writeString(message); - stream.writeInt64(random_id); - if ((flags & 4) != 0) { - reply_markup.serializeToStream(stream); - } - if ((flags & 8) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = silent ? (flags | 32) : (flags &~ 32); + flags = background ? (flags | 64) : (flags &~ 64); + flags = clear_draft ? (flags | 128) : (flags &~ 128); + stream.writeInt32(flags); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(reply_to_msg_id); + } + media.serializeToStream(stream); + stream.writeString(message); + stream.writeInt64(random_id); + if ((flags & 4) != 0) { + reply_markup.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(schedule_date); + } + } + } - public static class TL_messages_forwardMessages extends TLObject { - public static int constructor = 0x708e0195; + public static class TL_messages_forwardMessages extends TLObject { + public static int constructor = 0xd9fee60e; - public int flags; - public boolean silent; - public boolean background; - public boolean with_my_score; - public boolean grouped; - public InputPeer from_peer; - public ArrayList id = new ArrayList<>(); - public ArrayList random_id = new ArrayList<>(); - public InputPeer to_peer; + public int flags; + public boolean silent; + public boolean background; + public boolean with_my_score; + public boolean grouped; + public InputPeer from_peer; + public ArrayList id = new ArrayList<>(); + public ArrayList random_id = new ArrayList<>(); + public InputPeer to_peer; + public int schedule_date; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = silent ? (flags | 32) : (flags &~ 32); - flags = background ? (flags | 64) : (flags &~ 64); - flags = with_my_score ? (flags | 256) : (flags &~ 256); - flags = grouped ? (flags | 512) : (flags &~ 512); - stream.writeInt32(flags); - from_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)); - } - stream.writeInt32(0x1cb5c415); - count = random_id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt64(random_id.get(a)); - } - to_peer.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = silent ? (flags | 32) : (flags &~ 32); + flags = background ? (flags | 64) : (flags &~ 64); + flags = with_my_score ? (flags | 256) : (flags &~ 256); + flags = grouped ? (flags | 512) : (flags &~ 512); + stream.writeInt32(flags); + from_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)); + } + stream.writeInt32(0x1cb5c415); + count = random_id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(random_id.get(a)); + } + to_peer.serializeToStream(stream); + if ((flags & 1024) != 0) { + stream.writeInt32(schedule_date); + } + } + } public static class TL_messages_reportSpam extends TLObject { public static int constructor = 0xcf1592db; @@ -32796,37 +33758,6 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_messages_sendBroadcast extends TLObject { - public static int constructor = 0xbf73f4da; - - public ArrayList contacts = new ArrayList<>(); - public ArrayList random_id = new ArrayList<>(); - public String message; - public InputMedia media; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = contacts.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - contacts.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = random_id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt64(random_id.get(a)); - } - stream.writeString(message); - media.serializeToStream(stream); - } - } - public static class TL_messages_getDhConfig extends TLObject { public static int constructor = 0x26cf8950; @@ -33682,6 +34613,159 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_account_uploadTheme extends TLObject { + public static int constructor = 0x1c3db333; + + public int flags; + public InputFile file; + public InputFile thumb; + public String file_name; + public String mime_type; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Document.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + file.serializeToStream(stream); + if ((flags & 1) != 0) { + thumb.serializeToStream(stream); + } + stream.writeString(file_name); + stream.writeString(mime_type); + } + } + + public static class TL_account_createTheme extends TLObject { + public static int constructor = 0x2b7ffd7f; + + public String slug; + public String title; + public InputDocument document; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Theme.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + stream.writeString(title); + document.serializeToStream(stream); + } + } + + public static class TL_account_updateTheme extends TLObject { + public static int constructor = 0x3b8ea202; + + public int flags; + public String format; + public InputTheme theme; + public String slug; + public String title; + public InputDocument document; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Theme.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeString(format); + theme.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeString(slug); + } + if ((flags & 2) != 0) { + stream.writeString(title); + } + if ((flags & 4) != 0) { + document.serializeToStream(stream); + } + } + } + + public static class TL_account_saveTheme extends TLObject { + public static int constructor = 0xf257106c; + + public InputTheme theme; + public boolean unsave; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + theme.serializeToStream(stream); + stream.writeBool(unsave); + } + } + + public static class TL_account_installTheme extends TLObject { + public static int constructor = 0x7ae43737; + + public int flags; + public boolean dark; + public String format; + public InputTheme theme; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = dark ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeString(format); + } + if ((flags & 2) != 0) { + theme.serializeToStream(stream); + } + } + } + + public static class TL_account_getTheme extends TLObject { + public static int constructor = 0x8d9d742b; + + public String format; + public InputTheme theme; + public long document_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Theme.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(format); + theme.serializeToStream(stream); + stream.writeInt64(document_id); + } + } + + public static class TL_account_getThemes extends TLObject { + public static int constructor = 0x285946f8; + + public String format; + public int hash; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return account_Themes.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(format); + stream.writeInt32(hash); + } + } + public static class TL_messages_getAllStickers extends TLObject { public static int constructor = 0x1c9618b1; @@ -34158,7 +35242,7 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_sendInlineBotResult extends TLObject { - public static int constructor = 0xb16e06fe; + public static int constructor = 0x220815b0; public int flags; public boolean silent; @@ -34170,6 +35254,7 @@ public static class TL_messages_sendInlineBotResult extends TLObject { public long random_id; public long query_id; public String id; + public int schedule_date; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Updates.TLdeserialize(stream, constructor, exception); @@ -34189,6 +35274,9 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt64(random_id); stream.writeInt64(query_id); stream.writeString(id); + if ((flags & 1024) != 0) { + stream.writeInt32(schedule_date); + } } } @@ -34210,7 +35298,7 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_editMessage extends TLObject { - public static int constructor = 0xd116f31e; + public static int constructor = 0x48f71778; public int flags; public boolean no_webpage; @@ -34220,6 +35308,7 @@ public static class TL_messages_editMessage extends TLObject { public InputMedia media; public ReplyMarkup reply_markup; public ArrayList entities = new ArrayList<>(); + public int schedule_date; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Updates.TLdeserialize(stream, constructor, exception); @@ -34248,6 +35337,9 @@ public void serializeToStream(AbstractSerializedData stream) { entities.get(a).serializeToStream(stream); } } + if ((flags & 32768) != 0) { + stream.writeInt32(schedule_date); + } } } @@ -34855,39 +35947,43 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_messages_sendMultiMedia extends TLObject { - public static int constructor = 0x2095512f; + public static class TL_messages_sendMultiMedia extends TLObject { + public static int constructor = 0xcc0110cb; - public int flags; - public boolean silent; - public boolean background; - public boolean clear_draft; - public InputPeer peer; - public int reply_to_msg_id; - public ArrayList multi_media = new ArrayList<>(); + public int flags; + public boolean silent; + public boolean background; + public boolean clear_draft; + public InputPeer peer; + public int reply_to_msg_id; + public ArrayList multi_media = new ArrayList<>(); + public int schedule_date; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = silent ? (flags | 32) : (flags &~ 32); - flags = background ? (flags | 64) : (flags &~ 64); - flags = clear_draft ? (flags | 128) : (flags &~ 128); - stream.writeInt32(flags); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeInt32(reply_to_msg_id); - } - stream.writeInt32(0x1cb5c415); - int count = multi_media.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - multi_media.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = silent ? (flags | 32) : (flags &~ 32); + flags = background ? (flags | 64) : (flags &~ 64); + flags = clear_draft ? (flags | 128) : (flags &~ 128); + stream.writeInt32(flags); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeInt32(0x1cb5c415); + int count = multi_media.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + multi_media.get(a).serializeToStream(stream); + } + if ((flags & 1024) != 0) { + stream.writeInt32(schedule_date); + } + } + } public static class TL_messages_clearAllDrafts extends TLObject { public static int constructor = 0x7e58ee9c; @@ -35198,6 +36294,191 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messages_getScheduledHistory extends TLObject { + public static int constructor = 0xe2c2685b; + + public InputPeer peer; + public int hash; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return messages_Messages.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(hash); + } + } + + public static class TL_messages_getScheduledMessages extends TLObject { + public static int constructor = 0xbdbb0464; + + public InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return messages_Messages.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)); + } + } + } + + public static class TL_messages_sendScheduledMessages extends TLObject { + public static int constructor = 0xbd38850a; + + public InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.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)); + } + } + } + + public static class TL_messages_deleteScheduledMessages extends TLObject { + public static int constructor = 0x59ae2b16; + + public InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public static TL_messages_deleteScheduledMessages TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messages_deleteScheduledMessages.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_deleteScheduledMessages", constructor)); + } else { + return null; + } + } + TL_messages_deleteScheduledMessages result = new TL_messages_deleteScheduledMessages(); + result.readParams(stream, exception); + return result; + } + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = InputPeer.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++) { + id.add(stream.readInt32(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)); + } + } + } + + public static class TL_messages_sendReaction extends TLObject { + public static int constructor = 0x25690ce4; + + public int flags; + public InputPeer peer; + public int msg_id; + public String reaction; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + if ((flags & 1) != 0) { + stream.writeString(reaction); + } + } + } + + public static class TL_messages_getMessagesReactions extends TLObject { + public static int constructor = 0x8bba90e6; + + public InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.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)); + } + } + } + + public static class TL_messages_getMessageReactionsList extends TLObject { + public static int constructor = 0x15b1376a; + + public int flags; + public InputPeer peer; + public int id; + public String reaction; + public String offset; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messageReactionsList.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(id); + if ((flags & 1) != 0) { + stream.writeString(reaction); + } + if ((flags & 2) != 0) { + stream.writeString(offset); + } + stream.writeInt32(limit); + } + } + public static class TL_help_getAppChangelog extends TLObject { public static int constructor = 0x9010ef6f; @@ -37244,10 +38525,13 @@ public static abstract class Message extends TLObject { public boolean post; public boolean from_scheduled; public boolean legacy; + public boolean edit_hide; public MessageFwdHeader fwd_from; public int via_bot_id; public String post_author; public long grouped_id; + public TL_messageReactions reactions; + public ArrayList restriction_reason = new ArrayList<>(); public int send_state = 0; //custom public int fwd_msg_id = 0; //custom public String attachPath = ""; //custom @@ -37265,6 +38549,7 @@ public static abstract class Message extends TLObject { public int reqId; //custom public int realId; //custom + public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Message result = null; switch (constructor) { @@ -37305,8 +38590,11 @@ public static Message TLdeserialize(AbstractSerializedData stream, int construct result = new TL_message_old6(); break; case 0x44f9b43d: - result = new TL_message(); + result = new TL_message_layer104(); break; + case 0x1c9b1027: + result = new TL_message_layer104_2(); + break; case 0xa367e716: result = new TL_messageForwarded_old2(); //custom break; @@ -37324,6 +38612,12 @@ public static Message TLdeserialize(AbstractSerializedData stream, int construct break; case 0x555555F8: result = new TL_message_secret_old(); //custom + break; + case 0x9789dac4: + result = new TL_message_layer104_3(); + break; + case 0x452c0e65: + result = new TL_message(); break; case 0x9e19a1f6: result = new TL_messageService(); @@ -38003,7 +39297,465 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_message extends Message { + public static class TL_message extends Message { + public static int constructor = 0x452c0e65; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + out = (flags & 2) != 0; + mentioned = (flags & 16) != 0; + media_unread = (flags & 32) != 0; + silent = (flags & 8192) != 0; + post = (flags & 16384) != 0; + from_scheduled = (flags & 262144) != 0; + legacy = (flags & 524288) != 0; + edit_hide = (flags & 2097152) != 0; + id = stream.readInt32(exception); + if ((flags & 256) != 0) { + from_id = stream.readInt32(exception); + } + to_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + fwd_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2048) != 0) { + via_bot_id = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + reply_to_msg_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + message = stream.readString(exception); + if ((flags & 512) != 0) { + media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (media != null) { + ttl = media.ttl_seconds; //custom + } + if (media != null && !TextUtils.isEmpty(media.captionLegacy)) { + message = media.captionLegacy; + } + } + if ((flags & 64) != 0) { + reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 128) != 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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + if ((flags & 1024) != 0) { + views = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + edit_date = stream.readInt32(exception); + } + if ((flags & 65536) != 0) { + post_author = stream.readString(exception); + } + if ((flags & 131072) != 0) { + grouped_id = stream.readInt64(exception); + } + if ((flags & 4194304) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = out ? (flags | 2) : (flags &~ 2); + flags = mentioned ? (flags | 16) : (flags &~ 16); + flags = media_unread ? (flags | 32) : (flags &~ 32); + flags = silent ? (flags | 8192) : (flags &~ 8192); + flags = post ? (flags | 16384) : (flags &~ 16384); + flags = from_scheduled ? (flags | 262144) : (flags &~ 262144); + flags = legacy ? (flags | 524288) : (flags &~ 524288); + flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152); + stream.writeInt32(flags); + stream.writeInt32(id); + if ((flags & 256) != 0) { + stream.writeInt32(from_id); + } + to_id.serializeToStream(stream); + if ((flags & 4) != 0) { + fwd_from.serializeToStream(stream); + } + if ((flags & 2048) != 0) { + stream.writeInt32(via_bot_id); + } + if ((flags & 8) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeInt32(date); + stream.writeString(message); + if ((flags & 512) != 0) { + media.serializeToStream(stream); + } + if ((flags & 64) != 0) { + reply_markup.serializeToStream(stream); + } + if ((flags & 128) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(views); + } + if ((flags & 32768) != 0) { + stream.writeInt32(edit_date); + } + if ((flags & 65536) != 0) { + stream.writeString(post_author); + } + if ((flags & 131072) != 0) { + stream.writeInt64(grouped_id); + } + if ((flags & 4194304) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + writeAttachPath(stream); + } + } + + public static class TL_message_layer104_3 extends TL_message { + public static int constructor = 0x9789dac4; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + out = (flags & 2) != 0; + mentioned = (flags & 16) != 0; + media_unread = (flags & 32) != 0; + silent = (flags & 8192) != 0; + post = (flags & 16384) != 0; + from_scheduled = (flags & 262144) != 0; + legacy = (flags & 524288) != 0; + edit_hide = (flags & 2097152) != 0; + id = stream.readInt32(exception); + if ((flags & 256) != 0) { + from_id = stream.readInt32(exception); + } + to_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + fwd_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2048) != 0) { + via_bot_id = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + reply_to_msg_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + message = stream.readString(exception); + if ((flags & 512) != 0) { + media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (media != null) { + ttl = media.ttl_seconds; //custom + } + if (media != null && !TextUtils.isEmpty(media.captionLegacy)) { + message = media.captionLegacy; + } + } + if ((flags & 64) != 0) { + reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 128) != 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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + if ((flags & 1024) != 0) { + views = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + edit_date = stream.readInt32(exception); + } + if ((flags & 65536) != 0) { + post_author = stream.readString(exception); + } + if ((flags & 131072) != 0) { + grouped_id = stream.readInt64(exception); + } + if ((flags & 1048576) != 0) { + reactions = TL_messageReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 4194304) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = out ? (flags | 2) : (flags &~ 2); + flags = mentioned ? (flags | 16) : (flags &~ 16); + flags = media_unread ? (flags | 32) : (flags &~ 32); + flags = silent ? (flags | 8192) : (flags &~ 8192); + flags = post ? (flags | 16384) : (flags &~ 16384); + flags = from_scheduled ? (flags | 262144) : (flags &~ 262144); + flags = legacy ? (flags | 524288) : (flags &~ 524288); + flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152); + stream.writeInt32(flags); + stream.writeInt32(id); + if ((flags & 256) != 0) { + stream.writeInt32(from_id); + } + to_id.serializeToStream(stream); + if ((flags & 4) != 0) { + fwd_from.serializeToStream(stream); + } + if ((flags & 2048) != 0) { + stream.writeInt32(via_bot_id); + } + if ((flags & 8) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeInt32(date); + stream.writeString(message); + if ((flags & 512) != 0) { + media.serializeToStream(stream); + } + if ((flags & 64) != 0) { + reply_markup.serializeToStream(stream); + } + if ((flags & 128) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(views); + } + if ((flags & 32768) != 0) { + stream.writeInt32(edit_date); + } + if ((flags & 65536) != 0) { + stream.writeString(post_author); + } + if ((flags & 131072) != 0) { + stream.writeInt64(grouped_id); + } + if ((flags & 1048576) != 0) { + reactions.serializeToStream(stream); + } + if ((flags & 4194304) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + writeAttachPath(stream); + } + } + + public static class TL_message_layer104_2 extends TL_message { + public static int constructor = 0x1c9b1027; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + out = (flags & 2) != 0; + mentioned = (flags & 16) != 0; + media_unread = (flags & 32) != 0; + silent = (flags & 8192) != 0; + post = (flags & 16384) != 0; + from_scheduled = (flags & 262144) != 0; + legacy = (flags & 524288) != 0; + edit_hide = (flags & 2097152) != 0; + id = stream.readInt32(exception); + if ((flags & 256) != 0) { + from_id = stream.readInt32(exception); + } + to_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + fwd_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2048) != 0) { + via_bot_id = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + reply_to_msg_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + message = stream.readString(exception); + if ((flags & 512) != 0) { + media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if (media != null) { + ttl = media.ttl_seconds; //custom + } + if (media != null && !TextUtils.isEmpty(media.captionLegacy)) { + message = media.captionLegacy; + } + } + if ((flags & 64) != 0) { + reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 128) != 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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + if ((flags & 1024) != 0) { + views = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + edit_date = stream.readInt32(exception); + } + if ((flags & 65536) != 0) { + post_author = stream.readString(exception); + } + if ((flags & 131072) != 0) { + grouped_id = stream.readInt64(exception); + } + if ((flags & 1048576) != 0) { + reactions = TL_messageReactions.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 4194304) != 0) { + stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = out ? (flags | 2) : (flags &~ 2); + flags = mentioned ? (flags | 16) : (flags &~ 16); + flags = media_unread ? (flags | 32) : (flags &~ 32); + flags = silent ? (flags | 8192) : (flags &~ 8192); + flags = post ? (flags | 16384) : (flags &~ 16384); + flags = from_scheduled ? (flags | 262144) : (flags &~ 262144); + flags = legacy ? (flags | 524288) : (flags &~ 524288); + flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152); + stream.writeInt32(flags); + stream.writeInt32(id); + if ((flags & 256) != 0) { + stream.writeInt32(from_id); + } + to_id.serializeToStream(stream); + if ((flags & 4) != 0) { + fwd_from.serializeToStream(stream); + } + if ((flags & 2048) != 0) { + stream.writeInt32(via_bot_id); + } + if ((flags & 8) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeInt32(date); + stream.writeString(message); + if ((flags & 512) != 0) { + media.serializeToStream(stream); + } + if ((flags & 64) != 0) { + reply_markup.serializeToStream(stream); + } + if ((flags & 128) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(views); + } + if ((flags & 32768) != 0) { + stream.writeInt32(edit_date); + } + if ((flags & 65536) != 0) { + stream.writeString(post_author); + } + if ((flags & 131072) != 0) { + stream.writeInt64(grouped_id); + } + if ((flags & 1048576) != 0) { + reactions.serializeToStream(stream); + } + if ((flags & 4194304) != 0) { + stream.writeString(""); + } + writeAttachPath(stream); + } + } + + public static class TL_message_layer104 extends TL_message { public static int constructor = 0x44f9b43d; public void readParams(AbstractSerializedData stream, boolean exception) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index 7dfe3fa2ba3..93a94c5fcc8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -929,6 +929,10 @@ public void setItemColor(int item, int color, int icon) { cell.imageView.setColorFilter(new PorterDuffColorFilter(icon, PorterDuff.Mode.MULTIPLY)); } + public int getItemsCount() { + return itemViews.size(); + } + public void setMessage(CharSequence text) { message = text; if (messageTextView != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 4cc3d1b30ce..7ced9d649e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -27,6 +27,7 @@ import org.telegram.messenger.ContactsController; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocationController; @@ -92,6 +93,10 @@ public int getCurrentAccount() { return currentAccount; } + public int getClassGuid() { + return classGuid; + } + protected void setInPreviewMode(boolean value) { inPreviewMode = value; if (actionBar != null) { @@ -506,6 +511,10 @@ public NotificationCenter getNotificationCenter() { return getAccountInstance().getNotificationCenter(); } + public MediaController getMediaController() { + return MediaController.getInstance(); + } + public UserConfig getUserConfig() { return getAccountInstance().getUserConfig(); } 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 99387aaf22e..19197d433cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -25,9 +25,11 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; +import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.NinePatchDrawable; import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.ShapeDrawable; @@ -38,6 +40,7 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.net.Uri; import android.os.Build; import android.os.SystemClock; import android.text.TextPaint; @@ -48,7 +51,9 @@ import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -56,8 +61,13 @@ 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.time.SunDate; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.SerializedData; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.BackgroundGradientDrawable; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.ScamDrawable; @@ -70,27 +80,101 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; + +import androidx.annotation.UiThread; public class Theme { - public static class ThemeInfo { + public static class ThemeInfo implements NotificationCenter.NotificationCenterDelegate { public String name; public String pathToFile; + public String pathToWallpaper; public String assetName; + public String slug; + public boolean badWallpaper; + public boolean isBlured; + public boolean isMotion; + + public int account; + + public TLRPC.TL_theme info; + public boolean loaded = true; + + public String uploadingThumb; + public String uploadingFile; + public TLRPC.InputFile uploadedThumb; + public TLRPC.InputFile uploadedFile; public int previewBackgroundColor; + public int previewBackgroundGradientColor; + public int previewWallpaperOffset; public int previewInColor; public int previewOutColor; + public boolean previewParsed; + public boolean themeLoaded = true; + public int sortIndex; - public JSONObject getSaveJson() { + public int[] accentColorOptions; + public int accentBaseColor; + public int accentColor; + final float[] accentBaseColorHsv = new float[3]; + final float[] accentColorHsv = new float[3]; + + ThemeInfo() { + + } + + public ThemeInfo(ThemeInfo other) { + name = other.name; + pathToFile = other.pathToFile; + assetName = other.assetName; + sortIndex = other.sortIndex; + accentColorOptions = other.accentColorOptions; + accentBaseColor = other.accentBaseColor; + accentColor = other.accentColor; + info = other.info; + loaded = other.loaded; + uploadingThumb = other.uploadingThumb; + uploadingFile = other.uploadingFile; + uploadedThumb = other.uploadedThumb; + uploadedFile = other.uploadedFile; + account = other.account; + pathToWallpaper = other.pathToWallpaper; + slug = other.slug; + badWallpaper = other.badWallpaper; + isBlured = other.isBlured; + isMotion = other.isMotion; + + previewBackgroundColor = other.previewBackgroundColor; + previewBackgroundGradientColor = other.previewBackgroundGradientColor; + previewWallpaperOffset = other.previewWallpaperOffset; + previewInColor = other.previewInColor; + previewOutColor = other.previewOutColor; + previewParsed = other.previewParsed; + themeLoaded = other.themeLoaded; + + Color.colorToHSV(accentBaseColor, accentBaseColorHsv); + Color.colorToHSV(accentColor, accentColorHsv); + } + + JSONObject getSaveJson() { try { JSONObject jsonObject = new JSONObject(); jsonObject.put("name", name); jsonObject.put("path", pathToFile); + jsonObject.put("account", account); + if (info != null) { + SerializedData data = new SerializedData(info.getObjectSize()); + info.serializeToStream(data); + jsonObject.put("info", Utilities.bytesToHex(data.toByteArray())); + } + jsonObject.put("loaded", loaded); return jsonObject; } catch (Exception e) { FileLog.e(e); @@ -103,27 +187,32 @@ public String getName() { return LocaleController.getString("Default", R.string.Default); } else if ("Blue".equals(name)) { return LocaleController.getString("ThemeBlue", R.string.ThemeBlue); - } else if ("Dark".equals(name)) { - return LocaleController.getString("ThemeDark", R.string.ThemeDark); } else if ("Dark Blue".equals(name)) { - return LocaleController.getString("ThemeDarkBlue", R.string.ThemeDarkBlue); + return LocaleController.getString("ThemeDark", R.string.ThemeDark); } else if ("Graphite".equals(name)) { return LocaleController.getString("ThemeGraphite", R.string.ThemeGraphite); } else if ("Arctic Blue".equals(name)) { return LocaleController.getString("ThemeArcticBlue", R.string.ThemeArcticBlue); } - return name; + return info != null ? info.title : name; } public boolean isDark() { - return "Dark".equals(name) || "Dark Blue".equals(name) || "Graphite".equals(name); + return "Dark Blue".equals(name) || "Graphite".equals(name); } public boolean isLight() { return pathToFile == null && !isDark(); } - public static ThemeInfo createWithJson(JSONObject object) { + public String getKey() { + if (info != null) { + return "remote" + info.id; + } + return name; + } + + static ThemeInfo createWithJson(JSONObject object) { if (object == null) { return null; } @@ -131,6 +220,20 @@ public static ThemeInfo createWithJson(JSONObject object) { ThemeInfo themeInfo = new ThemeInfo(); themeInfo.name = object.getString("name"); themeInfo.pathToFile = object.getString("path"); + if (object.has("account")) { + themeInfo.account = object.getInt("account"); + } + if (object.has("info")) { + try { + SerializedData serializedData = new SerializedData(Utilities.hexToBytes(object.getString("info"))); + themeInfo.info = (TLRPC.TL_theme) TLRPC.Theme.TLdeserialize(serializedData, serializedData.readInt32(true), true); + } catch (Throwable e) { + FileLog.e(e); + } + } + if (object.has("loaded")) { + themeInfo.loaded = object.getBoolean("loaded"); + } return themeInfo; } catch (Exception e) { FileLog.e(e); @@ -138,7 +241,7 @@ public static ThemeInfo createWithJson(JSONObject object) { return null; } - public static ThemeInfo createWithString(String string) { + static ThemeInfo createWithString(String string) { if (TextUtils.isEmpty(string)) { return null; } @@ -151,6 +254,53 @@ public static ThemeInfo createWithString(String string) { themeInfo.pathToFile = args[1]; return themeInfo; } + + void setAccentColorOptions(int[] options) { + accentColorOptions = options; + accentBaseColor = options[0]; + Color.colorToHSV(accentBaseColor, accentBaseColorHsv); + setAccentColor(accentBaseColor); + } + + void setAccentColor(int color) { + accentColor = color; + Color.colorToHSV(accentColor, accentColorHsv); + } + + @UiThread + private void loadThemeDocument() { + loaded = false; + NotificationCenter.getInstance(account).addObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(account).addObserver(this, NotificationCenter.fileDidFailToLoad); + FileLoader.getInstance(account).loadFile(info.document, info, 1, 1); + } + + @UiThread + private void removeObservers() { + NotificationCenter.getInstance(account).removeObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(account).removeObserver(this, NotificationCenter.fileDidFailToLoad); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailToLoad) { + String location = (String) args[0]; + if (info != null && info.document != null) { + String name = FileLoader.getAttachFileName(info.document); + if (location.equals(name)) { + removeObservers(); + if (id == NotificationCenter.fileDidLoad) { + loaded = true; + previewParsed = false; + saveOtherThemes(true); + if (this == currentTheme && previousTheme == null) { + applyTheme(this, this == currentNightTheme); + } + } + } + } + } + } } private static final Object sync = new Object(); @@ -208,6 +358,12 @@ public void run() { private static Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private static int loadingCurrentTheme; + private static int lastLoadingCurrentThemeTime; + private static boolean loadingRemoteThemes; + private static int lastLoadingThemesTime; + private static int remoteThemesHash; + public static ArrayList themes; private static ArrayList otherThemes; private static HashMap themesDict; @@ -216,6 +372,8 @@ public void run() { private static ThemeInfo currentDayTheme; private static ThemeInfo defaultTheme; private static ThemeInfo previousTheme; + private static boolean switchingNightTheme; + private static boolean isInNigthMode; public static PorterDuffColorFilter colorFilter; public static PorterDuffColorFilter colorPressedFilter; @@ -234,7 +392,9 @@ public void run() { private static Drawable wallpaper; private static Drawable themedWallpaper; private static int themedWallpaperFileOffset; + private static String themedWallpaperLink; private static boolean isWallpaperMotion; + private static Boolean isWallpaperMotionPrev; private static boolean isPatternWallpaper; public static Paint dividerPaint; @@ -245,7 +405,6 @@ public void run() { public static Paint avatar_backgroundPaint; public static Drawable listSelector; - public static Drawable avatar_broadcastDrawable; public static Drawable avatar_savedDrawable; public static Drawable avatar_ghostDrawable; @@ -270,6 +429,7 @@ public void run() { public static TextPaint dialogs_onlinePaint; public static TextPaint dialogs_offlinePaint; public static Drawable dialogs_checkDrawable; + public static Drawable dialogs_checkReadDrawable; public static Drawable dialogs_halfCheckDrawable; public static Drawable dialogs_clockDrawable; public static Drawable dialogs_errorDrawable; @@ -364,6 +524,8 @@ public void run() { public static Drawable chat_msgOutMediaShadowDrawable; public static Drawable chat_msgOutCheckDrawable; public static Drawable chat_msgOutCheckSelectedDrawable; + public static Drawable chat_msgOutCheckReadDrawable; + public static Drawable chat_msgOutCheckReadSelectedDrawable; public static Drawable chat_msgOutHalfCheckDrawable; public static Drawable chat_msgOutHalfCheckSelectedDrawable; public static Drawable chat_msgOutClockDrawable; @@ -632,6 +794,8 @@ public void run() { public static final String key_actionBarDefaultArchivedSearch = "actionBarDefaultArchivedSearch"; public static final String key_actionBarDefaultArchivedSearchPlaceholder = "actionBarDefaultSearchArchivedPlaceholder"; + public static final String key_actionBarBrowser = "actionBarBrowser"; + public static final String key_chats_onlineCircle = "chats_onlineCircle"; public static final String key_chats_unreadCounter = "chats_unreadCounter"; public static final String key_chats_unreadCounterMuted = "chats_unreadCounterMuted"; @@ -660,6 +824,7 @@ public void run() { public static final String key_chats_pinnedOverlay = "chats_pinnedOverlay"; public static final String key_chats_tabletSelectedOverlay = "chats_tabletSelectedOverlay"; public static final String key_chats_sentCheck = "chats_sentCheck"; + public static final String key_chats_sentReadCheck = "chats_sentReadCheck"; public static final String key_chats_sentClock = "chats_sentClock"; public static final String key_chats_sentError = "chats_sentError"; public static final String key_chats_sentErrorIcon = "chats_sentErrorIcon"; @@ -737,6 +902,8 @@ public void run() { public static final String key_chat_lockIcon = "chat_lockIcon"; public static final String key_chat_outSentCheck = "chat_outSentCheck"; public static final String key_chat_outSentCheckSelected = "chat_outSentCheckSelected"; + public static final String key_chat_outSentCheckRead = "chat_outSentCheckRead"; + public static final String key_chat_outSentCheckReadSelected = "chat_outSentCheckReadSelected"; public static final String key_chat_outSentClock = "chat_outSentClock"; public static final String key_chat_outSentClockSelected = "chat_outSentClockSelected"; public static final String key_chat_inSentClock = "chat_inSentClock"; @@ -861,16 +1028,19 @@ public void run() { public static final String key_chat_linkSelectBackground = "chat_linkSelectBackground"; public static final String key_chat_textSelectBackground = "chat_textSelectBackground"; public static final String key_chat_wallpaper = "chat_wallpaper"; + public static final String key_chat_wallpaper_gradient_to = "chat_wallpaper_gradient_to"; public static final String key_chat_messagePanelBackground = "chat_messagePanelBackground"; public static final String key_chat_messagePanelShadow = "chat_messagePanelShadow"; public static final String key_chat_messagePanelText = "chat_messagePanelText"; public static final String key_chat_messagePanelHint = "chat_messagePanelHint"; + public static final String key_chat_messagePanelCursor = "chat_messagePanelCursor"; public static final String key_chat_messagePanelIcons = "chat_messagePanelIcons"; public static final String key_chat_messagePanelSend = "chat_messagePanelSend"; public static final String key_chat_messagePanelSendPressed = "chat_messagePanelPressedSend"; public static final String key_chat_messagePanelVoiceLock = "key_chat_messagePanelVoiceLock"; public static final String key_chat_messagePanelVoiceLockBackground = "key_chat_messagePanelVoiceLockBackground"; public static final String key_chat_messagePanelVoiceLockShadow = "key_chat_messagePanelVoiceLockShadow"; + public static final String key_chat_messagePanelVideoFrame = "chat_messagePanelVideoFrame"; public static final String key_chat_topPanelBackground = "chat_topPanelBackground"; public static final String key_chat_topPanelClose = "chat_topPanelClose"; public static final String key_chat_topPanelLine = "chat_topPanelLine"; @@ -1073,9 +1243,13 @@ public void run() { private static HashMap defaultColors = new HashMap<>(); private static HashMap fallbackKeys = new HashMap<>(); + private static HashSet themeAccentExclusionKeys = new HashSet<>(); + private static HashMap currentColorsNoAccent; private static HashMap currentColors; private static HashMap animatingColors; + private static float[] hsv = new float[3]; + static { defaultColors.put(key_dialogBackground, 0xffffffff); defaultColors.put(key_dialogBackgroundGray, 0xfff0f0f0); @@ -1250,6 +1424,8 @@ public void run() { defaultColors.put(key_actionBarTabLine, 0xffffffff); defaultColors.put(key_actionBarTabSelector, 0xff406d94); + defaultColors.put(key_actionBarBrowser, 0xffffffff); + defaultColors.put(key_actionBarDefaultArchived, 0xff6f7a87); defaultColors.put(key_actionBarDefaultArchivedSelector, 0xff5e6772); defaultColors.put(key_actionBarDefaultArchivedIcon, 0xffffffff); @@ -1285,6 +1461,7 @@ public void run() { defaultColors.put(key_chats_pinnedOverlay, 0x08000000); defaultColors.put(key_chats_tabletSelectedOverlay, 0x0f000000); defaultColors.put(key_chats_sentCheck, 0xff46aa36); + defaultColors.put(key_chats_sentReadCheck, 0xff46aa36); defaultColors.put(key_chats_sentClock, 0xff75bd5e); defaultColors.put(key_chats_sentError, 0xffd55252); defaultColors.put(key_chats_sentErrorIcon, 0xffffffff); @@ -1363,6 +1540,8 @@ public void run() { defaultColors.put(key_chat_mediaTimeBackground, 0x66000000); defaultColors.put(key_chat_outSentCheck, 0xff5db050); defaultColors.put(key_chat_outSentCheckSelected, 0xff5db050); + defaultColors.put(key_chat_outSentCheckRead, 0xff5db050); + defaultColors.put(key_chat_outSentCheckReadSelected, 0xff5db050); defaultColors.put(key_chat_outSentClock, 0xff75bd5e); defaultColors.put(key_chat_outSentClockSelected, 0xff75bd5e); defaultColors.put(key_chat_inSentClock, 0xffa1aab3); @@ -1534,8 +1713,10 @@ public void run() { defaultColors.put(key_chat_messagePanelBackground, 0xffffffff); defaultColors.put(key_chat_messagePanelText, 0xff000000); defaultColors.put(key_chat_messagePanelHint, 0xffa4acb3); + defaultColors.put(key_chat_messagePanelCursor, 0xff54a1db); defaultColors.put(key_chat_messagePanelShadow, 0xff000000); defaultColors.put(key_chat_messagePanelIcons, 0xff8e959b); + defaultColors.put(key_chat_messagePanelVideoFrame, 0xff4badf7); defaultColors.put(key_chat_recordedVoicePlayPause, 0xffffffff); defaultColors.put(key_chat_recordedVoicePlayPausePressed, 0xffd9eafb); defaultColors.put(key_chat_recordedVoiceDot, 0xffda564d); @@ -1793,10 +1974,19 @@ public void run() { fallbackKeys.put(key_chat_attachPermissionMark, key_chat_sentError); fallbackKeys.put(key_chat_attachPermissionText, key_dialogTextBlack); fallbackKeys.put(key_chat_attachEmptyImage, key_emptyListPlaceholder); + fallbackKeys.put(key_actionBarBrowser, key_actionBarDefault); + fallbackKeys.put(key_chats_sentReadCheck, key_chats_sentCheck); + fallbackKeys.put(key_chat_outSentCheckRead, key_chat_outSentCheck); + fallbackKeys.put(key_chat_outSentCheckReadSelected, key_chat_outSentCheckSelected); + themeAccentExclusionKeys.addAll(Arrays.asList(keys_avatar_background)); + themeAccentExclusionKeys.addAll(Arrays.asList(keys_avatar_nameInMessage)); + themeAccentExclusionKeys.add(key_chat_attachFileBackground); + themeAccentExclusionKeys.add(key_chat_attachGalleryBackground); themes = new ArrayList<>(); otherThemes = new ArrayList<>(); themesDict = new HashMap<>(); + currentColorsNoAccent = new HashMap<>(); currentColors = new HashMap<>(); ThemeInfo themeInfo = new ThemeInfo(); @@ -1808,16 +1998,6 @@ public void run() { themes.add(currentDayTheme = currentTheme = defaultTheme = themeInfo); themesDict.put("Default", defaultTheme); - themeInfo = new ThemeInfo(); - themeInfo.name = "Dark"; - themeInfo.assetName = "dark.attheme"; - themeInfo.previewBackgroundColor = 0xff5a5d61; - themeInfo.previewInColor = 0xff747a84; - themeInfo.previewOutColor = 0xff82a8e3; - themeInfo.sortIndex = 3; - themes.add(themeInfo); - themesDict.put("Dark", themeInfo); - themeInfo = new ThemeInfo(); themeInfo.name = "Blue"; themeInfo.assetName = "bluebubbles.attheme"; @@ -1825,6 +2005,7 @@ public void run() { themeInfo.previewInColor = 0xffffffff; themeInfo.previewOutColor = 0xffd0e6ff; themeInfo.sortIndex = 1; + themeInfo.setAccentColorOptions(new int[] { 0xFF328ACF, 0xFF43ACC7, 0xFF52AC44, 0xFFCD5F93, 0xFFD28036, 0xFF8366CC, 0xFFCE4E57, 0xFFD3AE40, 0xFF7B88AB }); themes.add(themeInfo); themesDict.put("Blue", themeInfo); @@ -1835,6 +2016,7 @@ public void run() { themeInfo.previewInColor = 0xff76869c; themeInfo.previewOutColor = 0xff82a8e3; themeInfo.sortIndex = 2; + themeInfo.setAccentColorOptions(new int[] { 0xff3685fa, 0xff46c8ed, 0xff4ab841, 0xffeb7cb1, 0xffee902a, 0xffa281f0, 0xffd34324, 0xffeebd34, 0xff7f8fab, 0xff3581e3 }); themes.add(themeInfo); themesDict.put("Dark Blue", currentNightTheme = themeInfo); @@ -1845,7 +2027,7 @@ public void run() { themeInfo.previewBackgroundColor = 0xff7a7e89; themeInfo.previewInColor = 0xff989ba3; themeInfo.previewOutColor = 0xffa4bff9; - themeInfo.sortIndex = 4; + themeInfo.sortIndex = 3; themes.add(themeInfo); themesDict.put("Graphite", themeInfo); } @@ -1856,12 +2038,15 @@ public void run() { themeInfo.previewBackgroundColor = 0xffffffff; themeInfo.previewInColor = 0xffebeef4; themeInfo.previewOutColor = 0xff7cb2fe; - themeInfo.sortIndex = 5; + themeInfo.sortIndex = 4; + themeInfo.setAccentColorOptions(new int[] { 0xFF3490EB, 0xFF43ACC7, 0xFF52AC44, 0xFFCD5F93, 0xFFD28036, 0xFF8366CC, 0xFFCE4E57, 0xFFD3AE40, 0xFF7B88AB }); themes.add(themeInfo); themesDict.put("Arctic Blue", themeInfo); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); String themesString = preferences.getString("themes2", null); + remoteThemesHash = preferences.getInt("remoteThemesHash", 0); + lastLoadingThemesTime = preferences.getInt("lastLoadingThemesTime", 0); if (!TextUtils.isEmpty(themesString)) { try { JSONArray jsonArray = new JSONArray(themesString); @@ -1870,7 +2055,7 @@ public void run() { if (themeInfo != null) { otherThemes.add(themeInfo); themes.add(themeInfo); - themesDict.put(themeInfo.name, themeInfo); + themesDict.put(themeInfo.getKey(), themeInfo); } } } catch (Exception e) { @@ -1885,11 +2070,11 @@ public void run() { if (themeInfo != null) { otherThemes.add(themeInfo); themes.add(themeInfo); - themesDict.put(themeInfo.name, themeInfo); + themesDict.put(themeInfo.getKey(), themeInfo); } } } - saveOtherThemes(); + saveOtherThemes(true); preferences.edit().remove("themes").commit(); } @@ -1897,18 +2082,34 @@ public void run() { ThemeInfo applyingTheme = null; try { + final ThemeInfo themeDarkBlue = themesDict.get("Dark Blue"); + preferences = MessagesController.getGlobalMainSettings(); String theme = preferences.getString("theme", null); - if (theme != null) { + if ("Dark".equals(theme)) { // Old theme. Fallback to "Dark Blue" with specific accent. + applyingTheme = themeDarkBlue; + themeDarkBlue.setAccentColor(0xff3581e3); + } else if (theme != null) { applyingTheme = themesDict.get(theme); } + theme = preferences.getString("nighttheme", null); - if (theme != null) { + if ("Dark".equals(theme)) { // Old theme. Fallback to "Dark Blue" with specific accent. + currentNightTheme = themeDarkBlue; + themeDarkBlue.setAccentColor(0xff3581e3); + } else if (theme != null) { ThemeInfo t = themesDict.get(theme); if (t != null) { currentNightTheme = t; } } + + for (ThemeInfo info : themesDict.values()) { + if (info.assetName != null && info.accentBaseColor != 0) { + info.setAccentColor(preferences.getInt("accent_for_" + info.assetName, info.accentColor)); + } + } + selectedAutoNightType = preferences.getInt("selectedAutoNightType", AUTO_NIGHT_TYPE_NONE); autoNightScheduleByLocation = preferences.getBoolean("autoNightScheduleByLocation", false); autoNightBrighnessThreshold = preferences.getFloat("autoNightBrighnessThreshold", 0.25f); @@ -1959,7 +2160,7 @@ public static void saveAutoNightThemeConfig() { editor.putLong("autoNightLocationLongitude3", Double.doubleToRawLongBits(autoNightLocationLongitude)); editor.putInt("autoNightLastSunCheckDay", autoNightLastSunCheckDay); if (currentNightTheme != null) { - editor.putString("nighttheme", currentNightTheme.name); + editor.putString("nighttheme", currentNightTheme.getKey()); } else { editor.remove("nighttheme"); } @@ -2392,7 +2593,16 @@ public static void applyPreviousTheme() { if (previousTheme == null) { return; } - applyTheme(previousTheme, true, false, false); + if (isWallpaperMotionPrev != null) { + SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); + editor.putBoolean("selectedBackgroundMotion", isWallpaperMotion = isWallpaperMotionPrev); + editor.commit(); + } + if (isInNigthMode && currentNightTheme != null) { + applyTheme(currentNightTheme, true, false, true); + } else { + applyTheme(previousTheme, true, false, false); + } previousTheme = null; checkAutoNightThemeConditions(); } @@ -2408,39 +2618,106 @@ private static void sortThemes() { }); } - public static ThemeInfo applyThemeFile(File file, String themeName, boolean temporary) { + public static void applyThemeTemporary(ThemeInfo themeInfo) { + previousTheme = getCurrentTheme(); + applyTheme(themeInfo, false, false, false); + } + + public static ThemeInfo fillThemeValues(File file, String themeName, TLRPC.TL_theme theme) { try { - if (themeName.equals("Default") || themeName.equals("Dark") || themeName.equals("Blue") || themeName.equals("Dark Blue") || themeName.equals("Graphite") || themeName.equals("Arctic Blue")) { - return null; - } - File finalFile = new File(ApplicationLoader.getFilesDirFixed(), themeName); - if (!AndroidUtilities.copyFile(file, finalFile)) { - return null; + ThemeInfo themeInfo = new ThemeInfo(); + themeInfo.name = themeName; + themeInfo.info = theme; + themeInfo.pathToFile = file.getAbsolutePath(); + themeInfo.account = UserConfig.selectedAccount; + + String[] wallpaperLink = new String[1]; + getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink); + + if (!TextUtils.isEmpty(wallpaperLink[0])) { + String ling = wallpaperLink[0]; + themeInfo.pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(ling) + ".wp").getAbsolutePath(); + try { + Uri data = Uri.parse(ling); + themeInfo.slug = data.getQueryParameter("slug"); + String mode = data.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int a = 0; a < modes.length; a++) { + if ("blur".equals(modes[a])) { + themeInfo.isBlured = true; + } else if ("motion".equals(modes[a])) { + themeInfo.isMotion = true; + } + } + } + } + } catch (Throwable e) { + FileLog.e(e); + } + } else { + themedWallpaperLink = null; } - boolean newTheme = false; - ThemeInfo themeInfo = themesDict.get(themeName); - if (themeInfo == null) { - newTheme = true; - themeInfo = new ThemeInfo(); - themeInfo.name = themeName; - themeInfo.pathToFile = finalFile.getAbsolutePath(); + return themeInfo; + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + public static ThemeInfo applyThemeFile(File file, String themeName, TLRPC.TL_theme theme, boolean temporary) { + try { + if (!themeName.toLowerCase().endsWith(".attheme")) { + themeName += ".attheme"; } - if (!temporary) { + if (temporary) { + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.goingToPreviewTheme); + ThemeInfo themeInfo = new ThemeInfo(); + themeInfo.name = themeName; + themeInfo.info = theme; + themeInfo.pathToFile = file.getAbsolutePath(); + themeInfo.account = UserConfig.selectedAccount; + applyThemeTemporary(themeInfo); + return themeInfo; + } else { + String key; + File finalFile; + if (theme != null) { + key = "remote" + theme.id; + finalFile = new File(ApplicationLoader.getFilesDirFixed(), key + ".attheme"); + } else { + key = themeName; + finalFile = new File(ApplicationLoader.getFilesDirFixed(), key); + } + if (!AndroidUtilities.copyFile(file, finalFile)) { + Theme.applyPreviousTheme(); + return null; + } + previousTheme = null; - if (newTheme) { + + ThemeInfo themeInfo = themesDict.get(key); + if (themeInfo == null) { + themeInfo = new ThemeInfo(); + themeInfo.name = themeName; + themeInfo.account = UserConfig.selectedAccount; themes.add(themeInfo); - themesDict.put(themeInfo.name, themeInfo); otherThemes.add(themeInfo); sortThemes(); - saveOtherThemes(); + } else { + themesDict.remove(key); } - } else { - previousTheme = currentTheme; - } + themeInfo.info = theme; + themeInfo.pathToFile = finalFile.getAbsolutePath(); + themesDict.put(themeInfo.getKey(), themeInfo); + saveOtherThemes(true); - applyTheme(themeInfo, !temporary, true, false); - return themeInfo; + applyTheme(themeInfo, true, true, false); + return themeInfo; + } } catch (Exception e) { FileLog.e(e); } @@ -2455,7 +2732,7 @@ public static void applyTheme(ThemeInfo themeInfo, boolean nightTheme) { applyTheme(themeInfo, true, true, nightTheme); } - public static void applyTheme(ThemeInfo themeInfo, boolean save, boolean removeWallpaperOverride, final boolean nightTheme) { + private static void applyTheme(ThemeInfo themeInfo, boolean save, boolean removeWallpaperOverride, final boolean nightTheme) { if (themeInfo == null) { return; } @@ -2468,16 +2745,82 @@ public static void applyTheme(ThemeInfo themeInfo, boolean save, boolean removeW if (!nightTheme && save) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); - editor.putString("theme", themeInfo.name); + editor.putString("theme", themeInfo.getKey()); if (removeWallpaperOverride) { editor.remove("overrideThemeWallpaper"); } editor.commit(); } + String[] wallpaperLink = new String[1]; if (themeInfo.assetName != null) { - currentColors = getThemeFileValues(null, themeInfo.assetName); + currentColorsNoAccent = getThemeFileValues(null, themeInfo.assetName, null); } else { - currentColors = getThemeFileValues(new File(themeInfo.pathToFile), null); + currentColorsNoAccent = getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink); + } + Integer offset = currentColorsNoAccent.get("wallpaperFileOffset"); + themedWallpaperFileOffset = offset != null ? offset : -1; + if (!TextUtils.isEmpty(wallpaperLink[0])) { + themedWallpaperLink = wallpaperLink[0]; + themeInfo.pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(themedWallpaperLink) + ".wp").getAbsolutePath(); + try { + Uri data = Uri.parse(themedWallpaperLink); + themeInfo.slug = data.getQueryParameter("slug"); + long id = Utilities.parseLong(data.getQueryParameter("id")); + long pattern = Utilities.parseLong(data.getQueryParameter("pattern")); + + String mode = data.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int a = 0; a < modes.length; a++) { + if ("blur".equals(modes[a])) { + themeInfo.isBlured = true; + } else if ("motion".equals(modes[a])) { + themeInfo.isMotion = true; + } + } + } + } + int intensity = Utilities.parseInt(data.getQueryParameter("intensity")); + int backgroundColor = 0; + try { + String bgColor = data.getQueryParameter("bg_color"); + if (!TextUtils.isEmpty(bgColor)) { + backgroundColor = Integer.parseInt(bgColor, 16) | 0xff000000; + } + } catch (Exception ignore) { + + } + + if (!TextUtils.isEmpty(themeInfo.slug)) { + SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); + if (save) { + editor.putString("selectedBackgroundSlug", themeInfo.slug); + if (pattern != 0) { + editor.putLong("selectedBackground2", -1); + editor.putLong("selectedPattern", pattern); + isPatternWallpaper = true; + } else { + editor.putLong("selectedBackground2", id); + editor.putLong("selectedPattern", 0); + isPatternWallpaper = false; + } + editor.putBoolean("selectedBackgroundBlurred", themeInfo.isBlured); + editor.putInt("selectedColor", backgroundColor); + editor.putFloat("selectedIntensity", intensity / 100.0f); + isWallpaperMotionPrev = null; + } else { + isWallpaperMotionPrev = isWallpaperMotion; + } + editor.putBoolean("selectedBackgroundMotion", isWallpaperMotion = themeInfo.isMotion); + editor.commit(); + } + } catch (Throwable e) { + FileLog.e(e); + } + } else { + themedWallpaperLink = null; } } else { if (!nightTheme && save) { @@ -2489,37 +2832,130 @@ public static void applyTheme(ThemeInfo themeInfo, boolean save, boolean removeW } editor.commit(); } - currentColors.clear(); + currentColorsNoAccent.clear(); themedWallpaperFileOffset = 0; + themedWallpaperLink = null; wallpaper = null; themedWallpaper = null; } currentTheme = themeInfo; - if (!nightTheme) { + if (!nightTheme && previousTheme == null) { currentDayTheme = currentTheme; } - reloadWallpaper(); - applyCommonTheme(); - applyDialogsTheme(); - applyProfileTheme(); - applyChatTheme(false); - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, nightTheme)); + refreshThemeColors(); } catch (Exception e) { FileLog.e(e); } + if (previousTheme == null && !switchingNightTheme) { + MessagesController.getInstance(themeInfo.account).saveTheme(themeInfo, nightTheme, false); + } } - private static void saveOtherThemes() { + private static void refreshThemeColors() { + currentColors.clear(); + currentColors.putAll(currentColorsNoAccent); + ThemeInfo themeInfo = currentTheme; + + if (themeInfo.accentColor != 0 && themeInfo.accentBaseColor != 0 && themeInfo.accentColor != themeInfo.accentBaseColor) { + HashSet keys = new HashSet<>(currentColorsNoAccent.keySet()); + keys.addAll(defaultColors.keySet()); + keys.removeAll(themeAccentExclusionKeys); + + for (String key: keys) { + Integer color = currentColorsNoAccent.get(key); + if (color == null) { + String fallbackKey = fallbackKeys.get(key); + if (fallbackKey != null && currentColorsNoAccent.get(fallbackKey) != null) { + continue; // We'll fallback to correct color automatically + } + } + if (color == null) { + color = defaultColors.get(key); + } + + int newColor = changeColorAccent(themeInfo.accentBaseColorHsv, themeInfo.accentColorHsv, color); + if (newColor != color) currentColors.put(key, newColor); + } + } + + reloadWallpaper(); + applyCommonTheme(); + applyDialogsTheme(); + applyProfileTheme(); + applyChatTheme(false); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, false)); + } + + public static int changeColorAccent(ThemeInfo themeInfo, int accent, int color) { + if (accent == 0 || themeInfo.accentBaseColor == 0 || accent == themeInfo.accentBaseColor) { + return color; + } + + Color.colorToHSV(accent, hsv); + return changeColorAccent(themeInfo.accentBaseColorHsv, hsv, color); + } + + public static int changeColorAccent(int color) { + return changeColorAccent(currentTheme, currentTheme.accentColor, color); + } + + private static int changeColorAccent(float[] baseHsv, float[] accentHsv, int color) { + final float baseH = baseHsv[0]; + final float baseS = baseHsv[1]; + final float baseV = baseHsv[2]; + + final float accentH = accentHsv[0]; + final float accentS = accentHsv[1]; + final float accentV = accentHsv[2]; + + Color.colorToHSV(color, hsv); + final float colorH = hsv[0]; + final float colorS = hsv[1]; + final float colorV = hsv[2]; + + // Only changing color's accent if its hue is close to base accent + final float diffH = Math.min(Math.abs(colorH - baseH), Math.abs(colorH - baseH - 360f)); + if (diffH > 30f) return color; + + // Calculating saturation distance between the color and its base. To preserve better + // contrast colors closer to base color will receive the most brightness change. + float dist = Math.min(1.5f * colorS / baseS, 1f); + + hsv[0] = colorH + accentH - baseH; + hsv[1] = colorS * accentS / baseS; + hsv[2] = colorV * (1f - dist + dist * accentV / baseV); + + return Color.HSVToColor(Color.alpha(color), hsv); + } + + public static void applyCurrentThemeAccent(int accent) { + currentTheme.setAccentColor(accent); + refreshThemeColors(); + } + + public static void saveThemeAccent(ThemeInfo themeInfo, int accent) { + if (themeInfo.assetName != null) { + MessagesController.getGlobalMainSettings().edit().putInt("accent_for_" + themeInfo.assetName, accent).commit(); + themeInfo.setAccentColor(accent); + } + } + + private static void saveOtherThemes(boolean full) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); - JSONArray array = new JSONArray(); - for (int a = 0; a < otherThemes.size(); a++) { - JSONObject jsonObject = otherThemes.get(a).getSaveJson(); - if (jsonObject != null) { - array.put(jsonObject); + if (full) { + JSONArray array = new JSONArray(); + for (int a = 0; a < otherThemes.size(); a++) { + JSONObject jsonObject = otherThemes.get(a).getSaveJson(); + if (jsonObject != null) { + array.put(jsonObject); + } } + editor.putString("themes2", array.toString()); } - editor.putString("themes2", array.toString()); + editor.putInt("remoteThemesHash", remoteThemesHash); + editor.putInt("lastLoadingThemesTime", lastLoadingThemesTime); + editor.putInt("lastLoadingCurrentThemeTime", lastLoadingCurrentThemeTime); editor.commit(); } @@ -2558,10 +2994,14 @@ public static boolean isCurrentThemeNight() { return currentTheme == currentNightTheme; } - public static boolean isCurrentThemeDefault() { + private static boolean isCurrentThemeDefault() { return currentTheme == defaultTheme; } + public static boolean isThemeDefault(ThemeInfo themeInfo) { + return themeInfo == defaultTheme; + } + private static long getAutoNightSwitchThemeDelay() { long newTime = SystemClock.elapsedRealtime(); if (Math.abs(lastThemeSwitchTime - newTime) >= LIGHT_SENSOR_THEME_SWITCH_NEAR_THRESHOLD) { @@ -2727,15 +3167,25 @@ public static void checkAutoNightThemeConditions(boolean force) { } private static void applyDayNightThemeMaybe(boolean night) { + if (previousTheme != null) { + return; + } + if (night) { if (currentTheme != currentNightTheme) { + isInNigthMode = true; lastThemeSwitchTime = SystemClock.elapsedRealtime(); + switchingNightTheme = true; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentNightTheme, true); + switchingNightTheme = false; } } else { if (currentTheme != currentDayTheme) { + isInNigthMode = false; lastThemeSwitchTime = SystemClock.elapsedRealtime(); + switchingNightTheme = true; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentDayTheme, true); + switchingNightTheme = false; } } } @@ -2749,57 +3199,129 @@ public static boolean deleteTheme(ThemeInfo themeInfo) { applyTheme(defaultTheme, true, false, false); currentThemeDeleted = true; } + if (themeInfo == currentNightTheme) { + currentNightTheme = themesDict.get("Dark Blue"); + } + themeInfo.removeObservers(); otherThemes.remove(themeInfo); themesDict.remove(themeInfo.name); themes.remove(themeInfo); File file = new File(themeInfo.pathToFile); file.delete(); - saveOtherThemes(); + saveOtherThemes(true); return currentThemeDeleted; } - public static void saveCurrentTheme(String name, boolean finalSave) { + public static ThemeInfo createNewTheme(String name) { + ThemeInfo newTheme = new ThemeInfo(); + newTheme.pathToFile = new File(ApplicationLoader.getFilesDirFixed(), "theme" + Utilities.random.nextLong() + ".attheme").getAbsolutePath(); + newTheme.name = name; + newTheme.account = UserConfig.selectedAccount; + saveCurrentTheme(newTheme, true, true, false); + return newTheme; + } + + public static void saveCurrentTheme(ThemeInfo themeInfo, boolean finalSave, boolean newTheme, boolean upload) { + String wallpaperLink = null; + + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean overrideThemeWallpaper = preferences.getBoolean("overrideThemeWallpaper", false); + String slug = preferences.getString("selectedBackgroundSlug", null); + long id = preferences.getLong("selectedBackground2", DEFAULT_BACKGROUND_ID); + long pattern = preferences.getLong("selectedPattern", 0); + if (upload) { + if (!TextUtils.isEmpty(slug) && (id != DEFAULT_BACKGROUND_ID || pattern != 0) && (overrideThemeWallpaper || !hasWallpaperFromTheme())) { + boolean isBlurred = preferences.getBoolean("selectedBackgroundBlurred", false); + boolean isMotion = preferences.getBoolean("selectedBackgroundMotion", false); + int selectedColor = preferences.getInt("selectedColor", 0); + float intensity = preferences.getFloat("selectedIntensity", 1.0f); + StringBuilder modes = new StringBuilder(); + if (isBlurred) { + modes.append("blur"); + } + if (isMotion) { + if (modes.length() > 0) { + modes.append("+"); + } + modes.append("motion"); + } + if (id != -1) { + wallpaperLink = "https://attheme.org?slug=" + slug + "&id=" + id; + } else { + String color = String.format("%02x%02x%02x", (byte) (selectedColor >> 16) & 0xff, (byte) (selectedColor >> 8) & 0xff, (byte) (selectedColor & 0xff)).toLowerCase(); + wallpaperLink = "https://attheme.org?slug=" + slug + "&intensity=" + (int) (intensity * 100) + "&bg_color=" + color + "&pattern=" + pattern; + } + if (modes.length() > 0) { + wallpaperLink += "&mode=" + modes.toString(); + } + } + } else { + wallpaperLink = themedWallpaperLink; + } + + Drawable wallpaperToSave = newTheme ? wallpaper : themedWallpaper; + if (newTheme && wallpaperToSave != null) { + themedWallpaper = wallpaper; + } StringBuilder result = new StringBuilder(); for (HashMap.Entry entry : currentColors.entrySet()) { - result.append(entry.getKey()).append("=").append(entry.getValue()).append("\n"); + String key = entry.getKey(); + if (wallpaperToSave instanceof BitmapDrawable || wallpaperLink != null) { + if (Theme.key_chat_wallpaper.equals(key) || Theme.key_chat_wallpaper_gradient_to.equals(key)) { + continue; + } + } + result.append(key).append("=").append(entry.getValue()).append("\n"); } - File file = new File(ApplicationLoader.getFilesDirFixed(), name); FileOutputStream stream = null; try { - stream = new FileOutputStream(file); + stream = new FileOutputStream(themeInfo.pathToFile); + if (result.length() == 0 && !(wallpaperToSave instanceof BitmapDrawable) && TextUtils.isEmpty(wallpaperLink)) { + result.append(' '); + } stream.write(AndroidUtilities.getStringBytes(result.toString())); - if (themedWallpaper instanceof BitmapDrawable) { - Bitmap bitmap = ((BitmapDrawable) themedWallpaper).getBitmap(); + if (!TextUtils.isEmpty(wallpaperLink)) { + stream.write(AndroidUtilities.getStringBytes("WLS=" + wallpaperLink + "\n")); + if (newTheme) { + try { + Bitmap bitmap = ((BitmapDrawable) wallpaperToSave).getBitmap(); + FileOutputStream wallpaperStream = new FileOutputStream(new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(wallpaperLink) + ".wp")); + bitmap.compress(Bitmap.CompressFormat.JPEG, 87, wallpaperStream); + wallpaperStream.close(); + } catch (Throwable e) { + FileLog.e(e); + } + } + } else if (wallpaperToSave instanceof BitmapDrawable) { + Bitmap bitmap = ((BitmapDrawable) wallpaperToSave).getBitmap(); if (bitmap != null) { stream.write(new byte[]{'W', 'P', 'S', '\n'}); bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); stream.write(new byte[]{'\n', 'W', 'P', 'E', '\n'}); } - if (finalSave) { - wallpaper = themedWallpaper; - calcBackgroundColor(wallpaper, 2); + if (finalSave && !upload) { + wallpaper = wallpaperToSave; + calcBackgroundColor(wallpaperToSave, 2); } } - ThemeInfo newTheme; - if ((newTheme = themesDict.get(name)) == null) { - newTheme = new ThemeInfo(); - newTheme.pathToFile = file.getAbsolutePath(); - newTheme.name = name; - themes.add(newTheme); - themesDict.put(newTheme.name, newTheme); - otherThemes.add(newTheme); - saveOtherThemes(); - sortThemes(); - } - currentTheme = newTheme; - if (currentTheme != currentNightTheme) { - currentDayTheme = currentTheme; + if (!upload) { + if (themesDict.get(themeInfo.getKey()) == null) { + themes.add(themeInfo); + themesDict.put(themeInfo.getKey(), themeInfo); + otherThemes.add(themeInfo); + saveOtherThemes(true); + sortThemes(); + } + currentTheme = themeInfo; + if (currentTheme != currentNightTheme) { + currentDayTheme = currentTheme; + } + preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("theme", currentDayTheme.getKey()); + editor.commit(); } - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("theme", currentDayTheme.name); - editor.commit(); } catch (Exception e) { FileLog.e(e); } finally { @@ -2811,6 +3333,168 @@ public static void saveCurrentTheme(String name, boolean finalSave) { FileLog.e(e); } } + if (finalSave) { + MessagesController.getInstance(themeInfo.account).saveThemeToServer(themeInfo); + } + } + + public static void checkCurrentRemoteTheme(boolean force) { + if (loadingCurrentTheme != 0 || !force && Math.abs(System.currentTimeMillis() / 1000 - lastLoadingCurrentThemeTime) < 60 * 60) { + return; + } + for (int a = 0; a < 2; a++) { + ThemeInfo themeInfo = a == 0 ? currentDayTheme : currentNightTheme; + if (themeInfo == null || themeInfo.info == null || themeInfo.info.document == null || !UserConfig.getInstance(themeInfo.account).isClientActivated()) { + continue; + } + loadingCurrentTheme++; + TLRPC.TL_account_getTheme req = new TLRPC.TL_account_getTheme(); + req.document_id = themeInfo.info.document.id; + req.format = "android"; + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.access_hash = themeInfo.info.access_hash; + inputTheme.id = themeInfo.info.id; + req.theme = inputTheme; + ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + loadingCurrentTheme--; + boolean changed = false; + if (response instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) response; + if (theme.document != null) { + themeInfo.info = theme; + themeInfo.loadThemeDocument(); + changed = true; + } + } + if (loadingCurrentTheme == 0) { + lastLoadingCurrentThemeTime = (int) (System.currentTimeMillis() / 1000); + saveOtherThemes(changed); + } + })); + } + } + + public static void loadRemoteThemes(final int currentAccount, boolean force) { + if (loadingRemoteThemes || !force && Math.abs(System.currentTimeMillis() / 1000 - lastLoadingThemesTime) < 60 * 60 || !UserConfig.getInstance(currentAccount).isClientActivated()) { + return; + } + loadingRemoteThemes = true; + TLRPC.TL_account_getThemes req = new TLRPC.TL_account_getThemes(); + req.format = "android"; + req.hash = remoteThemesHash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + loadingRemoteThemes = false; + if (response instanceof TLRPC.TL_account_themes) { + TLRPC.TL_account_themes res = (TLRPC.TL_account_themes) response; + remoteThemesHash = res.hash; + lastLoadingThemesTime = (int) (System.currentTimeMillis() / 1000); + ArrayList oldServerThemes = new ArrayList<>(); + for (int a = 0, N = otherThemes.size(); a < N; a++) { + ThemeInfo info = otherThemes.get(a); + if (info.info != null && info.account == currentAccount) { + oldServerThemes.add(info); + } + } + boolean added = false; + for (int a = 0, N = res.themes.size(); a < N; a++) { + TLRPC.Theme t = res.themes.get(a); + if (!(t instanceof TLRPC.TL_theme)) { + continue; + } + TLRPC.TL_theme theme = (TLRPC.TL_theme) t; + String key = "remote" + theme.id; + ThemeInfo info = themesDict.get(key); + if (info == null) { + info = new ThemeInfo(); + info.account = currentAccount; + info.pathToFile = new File(ApplicationLoader.getFilesDirFixed(), key + ".attheme").getAbsolutePath(); + themes.add(info); + otherThemes.add(info); + added = true; + } else { + oldServerThemes.remove(info); + } + info.name = theme.title; + info.info = theme; + themesDict.put(info.getKey(), info); + } + for (int a = 0, N = oldServerThemes.size(); a < N; a++) { + ThemeInfo info = oldServerThemes.get(a); + info.removeObservers(); + otherThemes.remove(info); + themesDict.remove(info.name); + themes.remove(info); + File file = new File(info.pathToFile); + file.delete(); + boolean isNightTheme = false; + if (currentDayTheme == info) { + currentDayTheme = defaultTheme; + } else if (currentNightTheme == info) { + currentNightTheme = themesDict.get("Dark Blue"); + isNightTheme = true; + } + if (currentTheme == info) { + applyTheme(isNightTheme ? currentNightTheme : currentDayTheme, true, false, isNightTheme); + } + } + saveOtherThemes(true); + sortThemes(); + if (added) { + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.themeListUpdated); + } + } + })); + } + + public static void setThemeFileReference(TLRPC.TL_theme info) { + for (int a = 0, N = Theme.themes.size(); a < N; a++) { + Theme.ThemeInfo themeInfo = Theme.themes.get(a); + if (themeInfo.info != null && themeInfo.info.id == info.id) { + if (themeInfo.info.document != null && info.document != null) { + themeInfo.info.document.file_reference = info.document.file_reference; + saveOtherThemes(true); + } + break; + } + } + } + + public static boolean isThemeInstalled(ThemeInfo themeInfo) { + return themeInfo != null && themesDict.get(themeInfo.getKey()) != null; + } + + public static void setThemeUploadInfo(ThemeInfo theme, TLRPC.TL_theme info, boolean update) { + if (info == null) { + return; + } + String key = "remote" + info.id; + if (theme != null) { + themesDict.remove(theme.getKey()); + } else { + theme = themesDict.get(key); + } + if (theme == null) { + return; + } + theme.info = info; + theme.name = info.title; + File oldPath = new File(theme.pathToFile); + File newPath = new File(ApplicationLoader.getFilesDirFixed(), key + ".attheme"); + if (!oldPath.equals(newPath)) { + try { + AndroidUtilities.copyFile(oldPath, newPath); + theme.pathToFile = newPath.getAbsolutePath(); + } catch (Exception e) { + FileLog.e(e); + } + } + if (update) { + theme.loadThemeDocument(); + } else { + theme.previewParsed = false; + } + themesDict.put(theme.getKey(), theme); + saveOtherThemes(true); } public static File getAssetFile(String assetName) { @@ -2834,7 +3518,194 @@ public static File getAssetFile(String assetName) { return file; } - private static HashMap getThemeFileValues(File file, String assetName) { + private static int getPreviewColor(HashMap colors, String key) { + Integer color = colors.get(key); + if (color == null) { + color = defaultColors.get(key); + } + return color; + } + + public static String createThemePreviewImage(ThemeInfo themeInfo) { + try { + String[] wallpaperLink = new String[1]; + HashMap colors = getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink); + Integer wallpaperFileOffset = colors.get("wallpaperFileOffset"); + Bitmap bitmap = Bitmaps.createBitmap(560, 678, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + + Paint paint = new Paint(); + + int actionBarColor = getPreviewColor(colors, key_actionBarDefault); + int actionBarIconColor = getPreviewColor(colors, key_actionBarDefaultIcon); + int messageFieldColor = getPreviewColor(colors, key_chat_messagePanelBackground); + int messageFieldIconColor = getPreviewColor(colors, key_chat_messagePanelIcons); + int messageInColor = getPreviewColor(colors, key_chat_inBubble); + int messageOutColor = getPreviewColor(colors, key_chat_outBubble); + Integer backgroundColor = colors.get(key_chat_wallpaper); + Integer serviceColor = colors.get(key_chat_serviceBackground); + Integer gradientToColor = colors.get(key_chat_wallpaper_gradient_to); + + Drawable backDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_back).mutate(); + setDrawableColor(backDrawable, actionBarIconColor); + Drawable otherDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_dots).mutate(); + setDrawableColor(otherDrawable, actionBarIconColor); + Drawable emojiDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_smile).mutate(); + setDrawableColor(emojiDrawable, messageFieldIconColor); + Drawable micDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_mic).mutate(); + setDrawableColor(micDrawable, messageFieldIconColor); + Drawable msgInDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_msg_in).mutate(); + setDrawableColor(msgInDrawable, messageInColor); + Drawable msgOutDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.preview_msg_out).mutate(); + setDrawableColor(msgOutDrawable, messageOutColor); + RectF rect = new RectF(); + + boolean hasBackground = false; + if (backgroundColor != null) { + Drawable wallpaperDrawable; + if (gradientToColor == null) { + wallpaperDrawable = new ColorDrawable(backgroundColor); + } else { + wallpaperDrawable = new BackgroundGradientDrawable(GradientDrawable.Orientation.BL_TR, new int[] { backgroundColor, gradientToColor }); + } + wallpaperDrawable.setBounds(0, 120, bitmap.getWidth(), bitmap.getHeight() - 120); + wallpaperDrawable.draw(canvas); + if (serviceColor == null) { + serviceColor = AndroidUtilities.calcDrawableColor(new ColorDrawable(backgroundColor))[0]; + } + hasBackground = true; + } else if (wallpaperFileOffset != null && wallpaperFileOffset >= 0 || !TextUtils.isEmpty(wallpaperLink[0])) { + FileInputStream stream = null; + File pathToWallpaper = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + if (!TextUtils.isEmpty(wallpaperLink[0])) { + pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(wallpaperLink[0]) + ".wp"); + BitmapFactory.decodeFile(pathToWallpaper.getAbsolutePath(), options); + } else { + stream = new FileInputStream(themeInfo.pathToFile); + stream.getChannel().position(wallpaperFileOffset); + BitmapFactory.decodeStream(stream, null, options); + } + if (options.outWidth > 0 && options.outHeight > 0) { + float scale = Math.min(options.outWidth / 560.0f, options.outHeight / 560.0f); + options.inSampleSize = 1; + if (scale > 1.0f) { + do { + options.inSampleSize *= 2; + } while (options.inSampleSize < scale); + } + options.inJustDecodeBounds = false; + Bitmap wallpaper; + if (pathToWallpaper != null) { + wallpaper = BitmapFactory.decodeFile(pathToWallpaper.getAbsolutePath(), options); + } else { + stream.getChannel().position(wallpaperFileOffset); + wallpaper = BitmapFactory.decodeStream(stream, null, options); + } + if (wallpaper != null) { + Paint bitmapPaint = new Paint(); + bitmapPaint.setFilterBitmap(true); + scale = Math.min(wallpaper.getWidth() / 560.0f, wallpaper.getHeight() / 560.0f); + rect.set(0, 0, wallpaper.getWidth() / scale, wallpaper.getHeight() / scale); + rect.offset((bitmap.getWidth() - rect.width()) / 2, (bitmap.getHeight() - rect.height()) / 2); + canvas.drawBitmap(wallpaper, null, rect, bitmapPaint); + hasBackground = true; + if (serviceColor == null) { + serviceColor = AndroidUtilities.calcDrawableColor(new BitmapDrawable(wallpaper))[0]; + } + } + } + } catch (Throwable e) { + FileLog.e(e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + } + if (!hasBackground) { + BitmapDrawable catsDrawable = (BitmapDrawable) ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.catstile).mutate(); + if (serviceColor == null) { + serviceColor = AndroidUtilities.calcDrawableColor(catsDrawable)[0]; + } + catsDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); + catsDrawable.setBounds(0, 120, bitmap.getWidth(), bitmap.getHeight() - 120); + catsDrawable.draw(canvas); + } + + paint.setColor(actionBarColor); + canvas.drawRect(0, 0, bitmap.getWidth(), 120, paint); + + if (backDrawable != null) { + int x = 13; + int y = (120 - backDrawable.getIntrinsicHeight()) / 2; + backDrawable.setBounds(x, y, x + backDrawable.getIntrinsicWidth(), y + backDrawable.getIntrinsicHeight()); + backDrawable.draw(canvas); + } + if (otherDrawable != null) { + int x = bitmap.getWidth() - otherDrawable.getIntrinsicWidth() - 10; + int y = (120 - otherDrawable.getIntrinsicHeight()) / 2; + otherDrawable.setBounds(x, y, x + otherDrawable.getIntrinsicWidth(), y + otherDrawable.getIntrinsicHeight()); + otherDrawable.draw(canvas); + } + if (msgOutDrawable != null) { + msgOutDrawable.setBounds(161, 216, bitmap.getWidth() - 20, 216 + 92); + msgOutDrawable.draw(canvas); + + msgOutDrawable.setBounds(161, 430, bitmap.getWidth() - 20, 430 + 92); + msgOutDrawable.draw(canvas); + } + if (msgInDrawable != null) { + msgInDrawable.setBounds(20, 323, 399, 323 + 92); + msgInDrawable.draw(canvas); + } + if (serviceColor != null) { + int x = (bitmap.getWidth() - 126) / 2; + int y = 150; + rect.set(x, y, x + 126, y + 42); + paint.setColor(serviceColor); + canvas.drawRoundRect(rect, 21, 21, paint); + } + + paint.setColor(messageFieldColor); + canvas.drawRect(0, bitmap.getHeight() - 120, bitmap.getWidth(), bitmap.getHeight(), paint); + if (emojiDrawable != null) { + int x = 22; + int y = bitmap.getHeight() - 120 + (120 - emojiDrawable.getIntrinsicHeight()) / 2; + emojiDrawable.setBounds(x, y, x + emojiDrawable.getIntrinsicWidth(), y + emojiDrawable.getIntrinsicHeight()); + emojiDrawable.draw(canvas); + } + if (micDrawable != null) { + int x = bitmap.getWidth() - micDrawable.getIntrinsicWidth() - 22; + int y = bitmap.getHeight() - 120 + (120 - micDrawable.getIntrinsicHeight()) / 2; + micDrawable.setBounds(x, y, x + micDrawable.getIntrinsicWidth(), y + micDrawable.getIntrinsicHeight()); + micDrawable.draw(canvas); + } + canvas.setBitmap(null); + + String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg"; + final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + try { + FileOutputStream stream = new FileOutputStream(cacheFile); + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); + SharedConfig.saveConfig(); + return cacheFile.getAbsolutePath(); + } catch (Throwable e) { + FileLog.e(e); + } + } catch (Throwable e) { + FileLog.e(e); + } + return null; + } + + private static HashMap getThemeFileValues(File file, String assetName, String[] wallpaperLink) { FileInputStream stream = null; HashMap stringMap = new HashMap<>(); try { @@ -2847,7 +3718,7 @@ private static HashMap getThemeFileValues(File file, String ass int idx; int read; boolean finished = false; - themedWallpaperFileOffset = -1; + int wallpaperFileOffset = -1; while ((read = stream.read(bytes)) != -1) { int previousPosition = currentPosition; int start = 0; @@ -2855,8 +3726,12 @@ private static HashMap getThemeFileValues(File file, String ass if (bytes[a] == '\n') { int len = a - start + 1; String line = new String(bytes, start, len - 1); - if (line.startsWith("WPS")) { - themedWallpaperFileOffset = currentPosition + len; + if (line.startsWith("WLS=")) { + if (wallpaperLink != null && wallpaperLink.length > 0) { + wallpaperLink[0] = line.substring(4); + } + } else if (line.startsWith("WPS")) { + wallpaperFileOffset = currentPosition + len; finished = true; break; } else { @@ -2888,6 +3763,7 @@ private static HashMap getThemeFileValues(File file, String ass break; } } + stringMap.put("wallpaperFileOffset", wallpaperFileOffset); } catch (Throwable e) { FileLog.e(e); } finally { @@ -2921,7 +3797,6 @@ public static void createCommonResources(Context context) { Resources resources = context.getResources(); - avatar_broadcastDrawable = resources.getDrawable(R.drawable.broadcast_w); avatar_savedDrawable = resources.getDrawable(R.drawable.chats_saved); avatar_ghostDrawable = resources.getDrawable(R.drawable.ghost); @@ -2958,7 +3833,6 @@ public static void applyCommonTheme() { dividerPaint.setColor(getColor(key_divider)); linkSelectionPaint.setColor(getColor(key_windowBackgroundWhiteLinkSelection)); - setDrawableColorByKey(avatar_broadcastDrawable, key_avatar_text); setDrawableColorByKey(avatar_savedDrawable, key_avatar_text); dialogs_archiveAvatarDrawable.setLayerColor("Arrow1.**", getColor(key_avatar_backgroundArchived)); @@ -3018,7 +3892,8 @@ public static void createDialogsResources(Context context) { dialogs_errorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_lockDrawable = resources.getDrawable(R.drawable.list_secret); - dialogs_checkDrawable = resources.getDrawable(R.drawable.list_check); + dialogs_checkDrawable = resources.getDrawable(R.drawable.list_check).mutate(); + dialogs_checkReadDrawable = resources.getDrawable(R.drawable.list_check).mutate(); dialogs_halfCheckDrawable = resources.getDrawable(R.drawable.list_halfcheck); dialogs_clockDrawable = resources.getDrawable(R.drawable.msg_clock).mutate(); dialogs_errorDrawable = resources.getDrawable(R.drawable.list_warning_sign); @@ -3071,7 +3946,8 @@ public static void applyDialogsTheme() { setDrawableColorByKey(dialogs_lockDrawable, key_chats_secretIcon); setDrawableColorByKey(dialogs_checkDrawable, key_chats_sentCheck); - setDrawableColorByKey(dialogs_halfCheckDrawable, key_chats_sentCheck); + setDrawableColorByKey(dialogs_checkReadDrawable, key_chats_sentReadCheck); + setDrawableColorByKey(dialogs_halfCheckDrawable, key_chats_sentReadCheck); setDrawableColorByKey(dialogs_clockDrawable, key_chats_sentClock); setDrawableColorByKey(dialogs_errorDrawable, key_chats_sentErrorIcon); setDrawableColorByKey(dialogs_groupDrawable, key_chats_nameIcon); @@ -3206,6 +4082,8 @@ public static void createChatResources(Context context, boolean fontsOnly) { chat_msgOutCheckDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); chat_msgOutCheckSelectedDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); + chat_msgOutCheckReadDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); + chat_msgOutCheckReadSelectedDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); chat_msgMediaCheckDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); chat_msgStickerCheckDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); chat_msgOutHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck).mutate(); @@ -3466,8 +4344,10 @@ public static void applyChatTheme(boolean fontsOnly) { setDrawableColorByKey(chat_msgOutMediaShadowDrawable, key_chat_outBubbleShadow); setDrawableColorByKey(chat_msgOutCheckDrawable, key_chat_outSentCheck); setDrawableColorByKey(chat_msgOutCheckSelectedDrawable, key_chat_outSentCheckSelected); - setDrawableColorByKey(chat_msgOutHalfCheckDrawable, key_chat_outSentCheck); - setDrawableColorByKey(chat_msgOutHalfCheckSelectedDrawable, key_chat_outSentCheckSelected); + setDrawableColorByKey(chat_msgOutCheckReadDrawable, key_chat_outSentCheckRead); + setDrawableColorByKey(chat_msgOutCheckReadSelectedDrawable, key_chat_outSentCheckReadSelected); + setDrawableColorByKey(chat_msgOutHalfCheckDrawable, key_chat_outSentCheckRead); + setDrawableColorByKey(chat_msgOutHalfCheckSelectedDrawable, key_chat_outSentCheckReadSelected); setDrawableColorByKey(chat_msgOutClockDrawable, key_chat_outSentClock); setDrawableColorByKey(chat_msgOutSelectedClockDrawable, key_chat_outSentClockSelected); setDrawableColorByKey(chat_msgInClockDrawable, key_chat_inSentClock); @@ -3794,7 +4674,7 @@ public static int getColor(String key, boolean[] isDefault) { } public static void setColor(String key, int color, boolean useDefault) { - if (key.equals(key_chat_wallpaper)) { + if (key.equals(key_chat_wallpaper) || key.equals(key_chat_wallpaper_gradient_to)) { color = 0xff000000 | color; } @@ -3806,24 +4686,26 @@ public static void setColor(String key, int color, boolean useDefault) { if (key.equals(key_chat_serviceBackground) || key.equals(key_chat_serviceBackgroundSelected)) { applyChatServiceMessageColor(); - } else if (key.equals(key_chat_wallpaper)) { + } else if (key.equals(key_chat_wallpaper) || key.equals(key_chat_wallpaper_gradient_to)) { reloadWallpaper(); } } - public static void setThemeWallpaper(String themeName, Bitmap bitmap, File path) { + public static void setThemeWallpaper(ThemeInfo themeInfo, Bitmap bitmap, File path) { currentColors.remove(key_chat_wallpaper); + currentColors.remove(key_chat_wallpaper_gradient_to); + themedWallpaperLink = null; MessagesController.getGlobalMainSettings().edit().remove("overrideThemeWallpaper").commit(); if (bitmap != null) { themedWallpaper = new BitmapDrawable(bitmap); - saveCurrentTheme(themeName, false); + saveCurrentTheme(themeInfo, false, false, false); calcBackgroundColor(themedWallpaper, 0); applyChatServiceMessageColor(); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewWallpapper); } else { themedWallpaper = null; wallpaper = null; - saveCurrentTheme(themeName, false); + saveCurrentTheme(themeInfo, false, false, false); reloadWallpaper(); } } @@ -3919,8 +4801,12 @@ public static void setSelectorDrawableColor(Drawable drawable, int color, boolea } } + public static boolean isThemeWallpaperPublic() { + return !TextUtils.isEmpty(themedWallpaperLink); + } + public static boolean hasWallpaperFromTheme() { - return currentColors.containsKey(key_chat_wallpaper) || themedWallpaperFileOffset > 0; + return currentColors.containsKey(key_chat_wallpaper) || themedWallpaperFileOffset > 0 || !TextUtils.isEmpty(themedWallpaperLink); } public static boolean isCustomTheme() { @@ -3959,18 +4845,29 @@ public static void loadWallpaper() { Utilities.searchQueue.postRunnable(() -> { synchronized (wallpaperSync) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - boolean overrideTheme = preferences.getBoolean("overrideThemeWallpaper", false); + boolean overrideTheme = previousTheme == null && preferences.getBoolean("overrideThemeWallpaper", false); isWallpaperMotion = preferences.getBoolean("selectedBackgroundMotion", false); isPatternWallpaper = preferences.getLong("selectedPattern", 0) != 0; if (!overrideTheme) { Integer backgroundColor = currentColors.get(key_chat_wallpaper); if (backgroundColor != null) { - wallpaper = new ColorDrawable(backgroundColor); + Integer gradientToColor = currentColors.get(key_chat_wallpaper_gradient_to); + if (gradientToColor == null) { + wallpaper = new ColorDrawable(backgroundColor); + } else { + wallpaper = new BackgroundGradientDrawable(GradientDrawable.Orientation.BL_TR, new int[] { backgroundColor, gradientToColor }); + } isCustomTheme = true; + } else if (themedWallpaperLink != null) { + File pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(themedWallpaperLink) + ".wp"); + Bitmap bitmap = BitmapFactory.decodeFile(pathToWallpaper.getAbsolutePath()); + if (bitmap != null) { + themedWallpaper = wallpaper = new BitmapDrawable(bitmap); + isCustomTheme = true; + } } else if (themedWallpaperFileOffset > 0 && (currentTheme.pathToFile != null || currentTheme.assetName != null)) { FileInputStream stream = null; try { - int currentPosition = 0; File file; if (currentTheme.assetName != null) { file = Theme.getAssetFile(currentTheme.assetName); @@ -4043,7 +4940,12 @@ public static void loadWallpaper() { public static Drawable getThemedWallpaper(boolean thumb) { Integer backgroundColor = currentColors.get(key_chat_wallpaper); if (backgroundColor != null) { - return new ColorDrawable(backgroundColor); + Integer gradientToColor = currentColors.get(key_chat_wallpaper_gradient_to); + if (gradientToColor == null) { + return new ColorDrawable(backgroundColor); + } else { + return new BackgroundGradientDrawable(GradientDrawable.Orientation.BL_TR, new int[]{backgroundColor, gradientToColor}); + } } else if (themedWallpaperFileOffset > 0 && (currentTheme.pathToFile != null || currentTheme.assetName != null)) { FileInputStream stream = null; try { @@ -4100,7 +5002,11 @@ public static long getSelectedBackgroundId() { } long id = preferences.getLong("selectedBackground2", DEFAULT_BACKGROUND_ID); if (hasWallpaperFromTheme() && !preferences.getBoolean("overrideThemeWallpaper", false)) { - return THEME_BACKGROUND_ID; + if (!TextUtils.isEmpty(themedWallpaperLink)) { + return id; + } else { + return THEME_BACKGROUND_ID; + } } else if (id == THEME_BACKGROUND_ID) { return DEFAULT_BACKGROUND_ID; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java index a7fab240133..e38e1f308c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java @@ -54,6 +54,7 @@ import org.telegram.ui.Components.ScamDrawable; import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.TypefaceSpan; +import org.telegram.ui.Components.VideoTimelineView; import java.lang.reflect.Field; import java.util.ArrayList; @@ -330,6 +331,9 @@ public void setColor(int color, boolean useDefault, boolean save) { ((ActionBar) viewToInvalidate).setPopupBackgroundColor(color); } } + if (viewToInvalidate instanceof VideoTimelineView) { + ((VideoTimelineView) viewToInvalidate).setColor(color); + } if (viewToInvalidate instanceof EmptyTextProgressView) { if ((changeFlags & FLAG_TEXTCOLOR) != 0) { ((EmptyTextProgressView) viewToInvalidate).setTextColor(color); @@ -571,6 +575,8 @@ private void processViewColor(View child, int color) { if ((changeFlags & FLAG_HINTTEXTCOLOR) != 0) { ((EditTextCaption) object).setHintColor(color); ((EditTextCaption) object).setHintTextColor(color); + } else if ((changeFlags & FLAG_CURSORCOLOR) != 0) { + ((EditTextCaption) object).setCursorColor(color); } else { ((EditTextCaption) object).setTextColor(color); } 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 81517db0473..f5995d4bf0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -320,22 +320,15 @@ public void loadRecentSearch() { int lower_id = (int) did; int high_id = (int) (did >> 32); if (lower_id != 0) { - if (high_id == 1) { - if (dialogsType == 0 && !chatsToLoad.contains(lower_id)) { - chatsToLoad.add(lower_id); + if (lower_id > 0) { + if (dialogsType != 2 && !usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); add = true; } } else { - if (lower_id > 0) { - if (dialogsType != 2 && !usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - add = true; - } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - add = true; - } + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); + add = true; } } } else if (dialogsType == 0 || dialogsType == 3) { @@ -370,12 +363,7 @@ public void loadRecentSearch() { MessagesStorage.getInstance(currentAccount).getChatsInternal(TextUtils.join(",", chatsToLoad), chats); for (int a = 0; a < chats.size(); a++) { TLRPC.Chat chat = chats.get(a); - long did; - if (chat.id > 0) { - did = -chat.id; - } else { - did = AndroidUtilities.makeBroadcastId(chat.id); - } + long did = -chat.id; if (chat.migrated_to != null) { RecentSearchObject recentSearchObject = hashMap.get(did); hashMap.remove(did); @@ -515,28 +503,19 @@ private void searchDialogsInternal(final String query, final int searchId) { int lower_id = (int) id; int high_id = (int) (id >> 32); if (lower_id != 0) { - if (high_id == 1) { - if (dialogsType == 4) { + if (lower_id > 0) { + if (dialogsType == 4 && lower_id == selfUserId) { continue; } - if (dialogsType == 0 && !chatsToLoad.contains(lower_id)) { - chatsToLoad.add(lower_id); + if (dialogsType != 2 && !usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); } } else { - if (lower_id > 0) { - if (dialogsType == 4 && lower_id == selfUserId) { - continue; - } - if (dialogsType != 2 && !usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); - } - } else { - if (dialogsType == 4) { - continue; - } - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); - } + if (dialogsType == 4) { + continue; + } + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); } } } else if (dialogsType == 0 || dialogsType == 3) { @@ -616,12 +595,7 @@ private void searchDialogsInternal(final String query, final int searchId) { TLRPC.Chat chat = TLRPC.Chat.TLdeserialize(data, data.readInt32(false), false); data.reuse(); if (!(chat == null || chat.deactivated || ChatObject.isChannel(chat) && ChatObject.isNotInChat(chat))) { - long dialog_id; - if (chat.id > 0) { - dialog_id = -chat.id; - } else { - dialog_id = AndroidUtilities.makeBroadcastId(chat.id); - } + long dialog_id = -chat.id; DialogSearchResult dialogSearchResult = dialogsResult.get(dialog_id); dialogSearchResult.name = AndroidUtilities.generateSearchName(chat.title, null, q); dialogSearchResult.object = chat; @@ -905,7 +879,7 @@ public void searchDialogs(String text) { if (needMessagesSearch != 2) { searchAdapterHelper.queryServerSearch(query, true, dialogsType != 4, true, dialogsType != 4, 0, dialogsType == 0, 0); } - searchMessagesInternal(query); + searchMessagesInternal(text); }); }, 300); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 81719ca8f92..27f2f434509 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -74,18 +74,18 @@ public StickersAdapter(Context context, StickersAdapterDelegate delegate) { MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_MASK); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailToLoad); } public void onDestroy() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailToLoad); } @Override public void didReceivedNotification(int id, int account, final Object... args) { - if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailedLoad) { + if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailToLoad) { if (stickers != null && !stickers.isEmpty() && !stickersToLoad.isEmpty() && visible) { String fileName = (String) args[0]; stickersToLoad.remove(fileName); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 351ea0e2aa0..d67ac5940d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -159,7 +159,6 @@ import org.telegram.ui.Components.TextPaintUrlSpan; import org.telegram.ui.Components.TextPaintWebpageUrlSpan; import org.telegram.ui.Components.TypefaceSpan; -import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.Components.WebPlayerView; @@ -2750,7 +2749,7 @@ private TLRPC.Document getDocumentWithId(long id) { @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.fileDidFailedLoad) { + if (id == NotificationCenter.fileDidFailToLoad) { String location = (String) args[0]; for (int a = 0; a < 3; a++) { if (currentFileNames[a] != null && currentFileNames[a].equals(location)) { @@ -6479,7 +6478,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (avatarVisible = (currentBlock.author_photo_id != 0)) { TLRPC.Photo photo = getPhotoWithId(currentBlock.author_photo_id); if (avatarVisible = (photo instanceof TLRPC.TL_photo)) { - avatarDrawable.setInfo(0, currentBlock.author, null, false); + avatarDrawable.setInfo(0, currentBlock.author, null); TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(40), true); avatarImageView.setImage(ImageLocation.getForPhoto(image, photo), "40_40", avatarDrawable, 0, null, currentPage, 1); } @@ -11455,7 +11454,7 @@ public boolean openPhoto(TLRPC.PageBlock block) { return false; } - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.FileLoadProgressChanged); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); @@ -11636,7 +11635,7 @@ public void closePhoto(boolean animated) { } releasePlayer(); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.FileLoadProgressChanged); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.needSetDayNightTheme); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java index 7f527195cd1..8636611dc11 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java @@ -26,6 +26,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -34,6 +35,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.AudioCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PickerBottomLayout; @@ -52,6 +54,7 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen private PickerBottomLayout bottomLayout; private RecyclerListView listView; private View shadow; + private ChatActivity parentFragment; private boolean loadingAudio; @@ -63,7 +66,12 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen private MessageObject playingAudio; public interface AudioSelectActivityDelegate { - void didSelectAudio(ArrayList audios); + void didSelectAudio(ArrayList audios, boolean notify, int scheduleDate); + } + + public AudioSelectActivity(ChatActivity chatActivity) { + super(); + parentFragment = chatActivity; } @Override @@ -135,14 +143,19 @@ public void onItemClick(int id) { frameLayout.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); bottomLayout.cancelButton.setOnClickListener(view -> finishFragment()); bottomLayout.doneButton.setOnClickListener(view -> { - if (delegate != null) { - ArrayList audios = new ArrayList<>(); - for (int a = 0; a < selectedAudios.size(); a++) { - audios.add(selectedAudios.valueAt(a).messageObject); - } - delegate.didSelectAudio(audios); + ArrayList audios = new ArrayList<>(); + for (int a = 0; a < selectedAudios.size(); a++) { + audios.add(selectedAudios.valueAt(a).messageObject); + } + if (parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectAudio(audios, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.didSelectAudio(audios, true, 0); + finishFragment(); } - finishFragment(); }); View shadow = new View(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java index 323a8ffd073..d00640818a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java @@ -24,7 +24,6 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; @@ -88,6 +87,10 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. @SuppressWarnings("unchecked") public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.didReceiveNewMessages && firstLoaded) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } ArrayList arr = (ArrayList) args[1]; for (MessageObject msg : arr) { if (msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { @@ -115,6 +118,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.messagesDeleted && firstLoaded) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } boolean didChange = false; ArrayList ids = (ArrayList) args[0]; Iterator itrtr = calls.iterator(); @@ -445,7 +452,7 @@ private void confirmAndDelete(final CallLogRow row) { for (TLRPC.Message msg : row.calls) { ids.add(msg.id); } - MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, false); + MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, 0, false, false); }) .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) .show() @@ -625,7 +632,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{CustomCell.class}, Theme.dialogs_onlinePaint, null, null, Theme.key_windowBackgroundWhiteBlueText3), new ThemeDescription(listView, 0, new Class[]{CustomCell.class}, null, new Paint[]{Theme.dialogs_namePaint, Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name), new ThemeDescription(listView, 0, new Class[]{CustomCell.class}, null, new Paint[]{Theme.dialogs_nameEncryptedPaint, Theme.dialogs_searchNameEncryptedPaint}, null, null, Theme.key_chats_secretName), - new ThemeDescription(listView, 0, new Class[]{CustomCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{CustomCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java index 5e4ff585c10..dd7245fa989 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java @@ -13,9 +13,11 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.graphics.Canvas; import android.graphics.Paint; @@ -46,6 +48,7 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; @@ -383,6 +386,12 @@ public void onNextPressed() { req.settings = new TLRPC.TL_codeSettings(); req.settings.allow_flashcall = false;//simcardAvailable && allowCall; req.settings.allow_app_hash = ApplicationLoader.hasPlayServices; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + if (req.settings.allow_app_hash) { + preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).commit(); + } else { + preferences.edit().remove("sms_hash").commit(); + } if (req.settings.allow_flashcall) { try { @SuppressLint("HardwareIds") String number = tm.getLine1Number(); 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 be5e3c21a6d..aaba63474f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -91,11 +91,16 @@ public void setDelegate(ChatActionCellDelegate delegate) { this.delegate = delegate; } - public void setCustomDate(int date) { + public void setCustomDate(int date, boolean scheduled) { if (customDate == date) { return; } - CharSequence newText = LocaleController.formatDateChat(date); + CharSequence newText; + if (scheduled) { + newText = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(date)); + } else { + newText = LocaleController.formatDateChat(date); + } if (customText != null && TextUtils.equals(newText, customText)) { return; } @@ -133,7 +138,7 @@ public void setMessageObject(MessageObject messageObject) { } } } - avatarDrawable.setInfo(id, null, null, false); + avatarDrawable.setInfo(id, null, null); if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { imageReceiver.setImage(null, null, avatarDrawable, null, currentMessageObject, 0); } else { 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 c6851e36194..b8799f9e99c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -53,6 +53,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.Interpolator; +import android.widget.Toast; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; @@ -151,6 +152,9 @@ default void didPressOther(ChatMessageCell cell, float otherX, float otherY) { default void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { } + default void didPressReaction(ChatMessageCell cell, TLRPC.TL_reactionCount reaction) { + } + default void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button) { } @@ -192,6 +196,7 @@ default void setShouldNotRepeatSticker(MessageObject message) { private final static int DOCUMENT_ATTACH_TYPE_STICKER = 6; private final static int DOCUMENT_ATTACH_TYPE_ROUND = 7; private final static int DOCUMENT_ATTACH_TYPE_WALLPAPER = 8; + private final static int DOCUMENT_ATTACH_TYPE_THEME = 9; private class BotButton { private int x; @@ -200,6 +205,7 @@ private class BotButton { private int height; private StaticLayout title; private TLRPC.KeyboardButton button; + private TLRPC.TL_reactionCount reaction; private int angle; private float progressAlpha; private long lastUpdateTime; @@ -428,6 +434,8 @@ private class PollButton { private ArrayList lastPollResults; private int lastPollResultsVoters; + private TLRPC.TL_messageReactions lastReactions; + private boolean autoPlayingMedia; private ArrayList botButtons = new ArrayList<>(); @@ -1128,13 +1136,17 @@ private boolean checkPollButtonMotionEvent(MotionEvent event) { if (Build.VERSION.SDK_INT >= 21 && selectorDrawable != null) { selectorDrawable.setState(StateSet.NOTHING); } - pollVoteInProgressNum = pressedVoteButton; - pollVoteInProgress = true; - voteCurrentProgressTime = 0.0f; - firstCircleLength = true; - voteCurrentCircleLength = 360; - voteRisingCircleLength = false; - delegate.didPressVoteButton(this, pollButtons.get(pressedVoteButton).answer); + if (currentMessageObject.scheduled) { + Toast.makeText(getContext(), LocaleController.getString("MessageScheduledVote", R.string.MessageScheduledVote), Toast.LENGTH_LONG).show(); + } else { + pollVoteInProgressNum = pressedVoteButton; + pollVoteInProgress = true; + voteCurrentProgressTime = 0.0f; + firstCircleLength = true; + voteCurrentCircleLength = 360; + voteRisingCircleLength = false; + delegate.didPressVoteButton(this, pollButtons.get(pressedVoteButton).answer); + } pressedVoteButton = -1; invalidate(); } @@ -1434,7 +1446,16 @@ private boolean checkBotButtonMotionEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (pressedBotButton != -1) { playSoundEffect(SoundEffectConstants.CLICK); - delegate.didPressBotButton(this, botButtons.get(pressedBotButton).button); + if (currentMessageObject.scheduled) { + Toast.makeText(getContext(), LocaleController.getString("MessageScheduledBotAction", R.string.MessageScheduledBotAction), Toast.LENGTH_LONG).show(); + } else { + BotButton button = botButtons.get(pressedBotButton); + if (button.button != null) { + delegate.didPressBotButton(this, button.button); + } else if (button.reaction != null) { + delegate.didPressReaction(this, button.reaction); + } + } pressedBotButton = -1; invalidate(); } @@ -1977,6 +1998,9 @@ private boolean isUserDataChanged() { if (lastViewsCount != currentMessageObject.messageOwner.views) { return true; } + if (lastReactions != currentMessageObject.messageOwner.reactions) { + return true; + } updateCurrentUserAndChat(); TLRPC.FileLocation newPhoto = null; @@ -2284,6 +2308,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } int captionNewLine = 0; availableTimeWidth = 0; + lastReactions = messageObject.messageOwner.reactions; photoImage.setForceLoading(false); photoImage.setNeedsQualityThumb(false); photoImage.setShouldGenerateQualityThumb(false); @@ -2336,6 +2361,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe boolean slideshow = false; String siteName = hasLinkPreview ? messageObject.messageOwner.media.webpage.site_name : null; String webpageType = hasLinkPreview ? messageObject.messageOwner.media.webpage.type : null; + TLRPC.Document androidThemeDocument = null; if (!drawInstantView) { if ("telegram_channel".equals(webpageType)) { drawInstantView = true; @@ -2346,6 +2372,17 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } else if ("telegram_message".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 3; + } else if ("telegram_theme".equals(webpageType)) { + ArrayList documents = messageObject.messageOwner.media.webpage.documents; + for (int a = 0, N = documents.size(); a < N; a++) { + TLRPC.Document document = documents.get(a); + if ("application/x-tgtheme-android".equals(document.mime_type)) { + drawInstantView = true; + drawInstantViewType = 7; + androidThemeDocument = document; + break; + } + } } else if ("telegram_background".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 6; @@ -2470,12 +2507,16 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe if (hasLinkPreview) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) messageObject.messageOwner.media.webpage; site_name = webPage.site_name; - title = drawInstantViewType != 6 ? webPage.title : null; - author = drawInstantViewType != 6 ? webPage.author : null; - description = drawInstantViewType != 6 ? webPage.description : null; + title = drawInstantViewType != 6 && drawInstantViewType != 7 ? webPage.title : null; + author = drawInstantViewType != 6 && drawInstantViewType != 7 ? webPage.author : null; + description = drawInstantViewType != 6 && drawInstantViewType != 7 ? webPage.description : null; photo = webPage.photo; webDocument = null; - document = webPage.document; + if (drawInstantViewType == 7) { + document = androidThemeDocument; + } else { + document = webPage.document; + } type = webPage.type; duration = webPage.duration; if (site_name != null && photo != null && site_name.toLowerCase().equals("instagram")) { @@ -2517,6 +2558,8 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } if (drawInstantViewType == 6) { site_name = LocaleController.getString("ChatBackground", R.string.ChatBackground); + } else if ("telegram_theme".equals(webpageType)) { + site_name = LocaleController.getString("ColorTheme", R.string.ColorTheme); } int additinalWidth = hasInvoicePreview ? 0 : AndroidUtilities.dp(10); @@ -2808,6 +2851,25 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe String str = AndroidUtilities.formatFileSize(documentAttach.size); durationWidth = (int) Math.ceil(Theme.chat_durationPaint.measureText(str)); videoInfoLayout = new StaticLayout(str, Theme.chat_durationPaint, durationWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } else if (drawInstantViewType == 7) { + currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 700); + currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 40); + photoParentObject = document; + if (currentPhotoObject != null && (currentPhotoObject.w == 0 || currentPhotoObject.h == 0)) { + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { + currentPhotoObject.w = attribute.w; + currentPhotoObject.h = attribute.h; + break; + } + } + if (currentPhotoObject.w == 0 || currentPhotoObject.h == 0) { + currentPhotoObject.w = currentPhotoObject.h = AndroidUtilities.dp(150); + } + } + documentAttach = document; + documentAttachType = DOCUMENT_ATTACH_TYPE_THEME; } else { calcBackgroundWidth(maxWidth, timeMore, maxChildWidth); if (backgroundWidth < maxWidth + AndroidUtilities.dp(20)) { @@ -2890,7 +2952,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe maxPhotoWidth = AndroidUtilities.dp(208); } else if (currentPhotoObject instanceof TLRPC.TL_photoSizeEmpty && currentPhotoObject.w != 0) { maxPhotoWidth = currentPhotoObject.w; - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { if (AndroidUtilities.isTablet()) { maxPhotoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); } else { @@ -2979,6 +3041,8 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } else { photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { + photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, document), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), "b1", 0, "jpg", messageObject, 1); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { boolean isWebpSticker = messageObject.isSticker(); if (SharedConfig.loopStickers || isWebpSticker) { @@ -3551,7 +3615,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } else { locationImageReceiver.setImage(null, null, contactAvatarDrawable, null, null, 0); } - infoLayout = new StaticLayout(LocaleController.formatLocationUpdateDate(messageObject.messageOwner.edit_date != 0 ? messageObject.messageOwner.edit_date : messageObject.messageOwner.date), Theme.chat_locationAddressPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + infoLayout = new StaticLayout(LocaleController.formatLocationUpdateDate(messageObject.messageOwner.edit_date != 0 && !messageObject.messageOwner.edit_hide ? messageObject.messageOwner.edit_date : messageObject.messageOwner.date), Theme.chat_locationAddressPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else if (!TextUtils.isEmpty(messageObject.messageOwner.media.title)) { if (AndroidUtilities.isTablet()) { backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(isChat && messageObject.needDrawAvatar() && !messageObject.isOutOwner() ? 102 : 50), AndroidUtilities.dp(252 + 37)); @@ -4312,10 +4376,15 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe botButtonsByPosition.clear(); botButtonsLayout = null; } - if (currentPosition == null && messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) { - int rows = messageObject.messageOwner.reply_markup.rows.size(); - substractBackgroundHeight = keyboardHeight = AndroidUtilities.dp(44 + 4) * rows + AndroidUtilities.dp(1); + if (currentPosition == null && (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup || messageObject.messageOwner.reactions != null && !messageObject.messageOwner.reactions.results.isEmpty())) { + int rows; + if (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) { + rows = messageObject.messageOwner.reply_markup.rows.size(); + } else { + rows = 1; + } + substractBackgroundHeight = keyboardHeight = AndroidUtilities.dp(44 + 4) * rows + AndroidUtilities.dp(1); widthForButtons = backgroundWidth - AndroidUtilities.dp(mediaBackground ? 0 : 9); boolean fullWidth = false; if (messageObject.wantedBotKeyboardWidth > widthForButtons) { @@ -4340,18 +4409,61 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe oldByPosition = null; } botButtonsByData.clear(); - for (int a = 0; a < rows; a++) { - TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(a); - int buttonsCount = row.buttons.size(); - if (buttonsCount == 0) { - continue; + if (messageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) { + for (int a = 0; a < rows; a++) { + TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(a); + int buttonsCount = row.buttons.size(); + if (buttonsCount == 0) { + continue; + } + int buttonWidth = (widthForButtons - AndroidUtilities.dp(5) * (buttonsCount - 1) - AndroidUtilities.dp(2)) / buttonsCount; + for (int b = 0; b < row.buttons.size(); b++) { + BotButton botButton = new BotButton(); + botButton.button = row.buttons.get(b); + String key = Utilities.bytesToHex(botButton.button.data); + String position = a + "" + b; + BotButton oldButton; + if (oldByPosition != null) { + oldButton = oldByPosition.get(position); + } else { + oldButton = oldByData.get(key); + } + if (oldButton != null) { + botButton.progressAlpha = oldButton.progressAlpha; + botButton.angle = oldButton.angle; + botButton.lastUpdateTime = oldButton.lastUpdateTime; + } else { + botButton.lastUpdateTime = System.currentTimeMillis(); + } + botButtonsByData.put(key, botButton); + botButtonsByPosition.put(position, botButton); + botButton.x = b * (buttonWidth + AndroidUtilities.dp(5)); + botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(5); + botButton.width = buttonWidth; + botButton.height = AndroidUtilities.dp(44); + CharSequence buttonText; + if (botButton.button instanceof TLRPC.TL_keyboardButtonBuy && (messageObject.messageOwner.media.flags & 4) != 0) { + buttonText = LocaleController.getString("PaymentReceipt", R.string.PaymentReceipt); + } else { + buttonText = Emoji.replaceEmoji(botButton.button.text, Theme.chat_botButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + buttonText = TextUtils.ellipsize(buttonText, Theme.chat_botButtonPaint, buttonWidth - AndroidUtilities.dp(10), TextUtils.TruncateAt.END); + } + botButton.title = new StaticLayout(buttonText, Theme.chat_botButtonPaint, buttonWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + botButtons.add(botButton); + if (b == row.buttons.size() - 1) { + maxButtonsWidth = Math.max(maxButtonsWidth, botButton.x + botButton.width); + } + } } + } else { + int buttonsCount = messageObject.messageOwner.reactions.results.size(); int buttonWidth = (widthForButtons - AndroidUtilities.dp(5) * (buttonsCount - 1) - AndroidUtilities.dp(2)) / buttonsCount; - for (int b = 0; b < row.buttons.size(); b++) { + for (int b = 0; b < buttonsCount; b++) { + TLRPC.TL_reactionCount reaction = messageObject.messageOwner.reactions.results.get(b); BotButton botButton = new BotButton(); - botButton.button = row.buttons.get(b); - String key = Utilities.bytesToHex(botButton.button.data); - String position = a + "" + b; + botButton.reaction = reaction; + String key = reaction.reaction; + String position = 0 + "" + b; BotButton oldButton; if (oldByPosition != null) { oldButton = oldByPosition.get(position); @@ -4368,19 +4480,16 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe botButtonsByData.put(key, botButton); botButtonsByPosition.put(position, botButton); botButton.x = b * (buttonWidth + AndroidUtilities.dp(5)); - botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(5); + botButton.y = AndroidUtilities.dp(5); botButton.width = buttonWidth; botButton.height = AndroidUtilities.dp(44); - CharSequence buttonText; - if (botButton.button instanceof TLRPC.TL_keyboardButtonBuy && (messageObject.messageOwner.media.flags & 4) != 0) { - buttonText = LocaleController.getString("PaymentReceipt", R.string.PaymentReceipt); - } else { - buttonText = Emoji.replaceEmoji(botButton.button.text, Theme.chat_botButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); - buttonText = TextUtils.ellipsize(buttonText, Theme.chat_botButtonPaint, buttonWidth - AndroidUtilities.dp(10), TextUtils.TruncateAt.END); - } + + CharSequence buttonText = Emoji.replaceEmoji(String.format("%d %s", reaction.count, reaction.reaction), Theme.chat_botButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + buttonText = TextUtils.ellipsize(buttonText, Theme.chat_botButtonPaint, buttonWidth - AndroidUtilities.dp(10), TextUtils.TruncateAt.END); + botButton.title = new StaticLayout(buttonText, Theme.chat_botButtonPaint, buttonWidth - AndroidUtilities.dp(10), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); botButtons.add(botButton); - if (b == row.buttons.size() - 1) { + if (b == buttonsCount - 1) { maxButtonsWidth = Math.max(maxButtonsWidth, botButton.x + botButton.width); } } @@ -4399,6 +4508,8 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } if (messageObject.isAnyKindOfSticker() && totalHeight < AndroidUtilities.dp(70)) { totalHeight = AndroidUtilities.dp(70); + } else if (messageObject.isAnimatedEmoji()) { + totalHeight += AndroidUtilities.dp(16); } if (!drawPhotoImage) { photoImage.setImageBitmap((Drawable) null); @@ -4987,6 +5098,8 @@ private void createInstantViewButton() { str = LocaleController.getString("ViewContact", R.string.ViewContact); } else if (drawInstantViewType == 6) { str = LocaleController.getString("OpenBackground", R.string.OpenBackground); + } else if (drawInstantViewType == 7) { + str = LocaleController.getString("OpenTheme", R.string.OpenTheme); } else { str = LocaleController.getString("InstantView", R.string.InstantView); } @@ -6013,7 +6126,7 @@ private void drawContent(Canvas canvas) { if (currentMessageObject.isOutOwner()) { addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); } else { - addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground ? 1 : 7); + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground || drawPinnedBottom ? 1 : 7); } for (int a = 0; a < botButtons.size(); a++) { BotButton button = botButtons.get(a); @@ -6314,7 +6427,13 @@ public void updateButtonState(boolean ifSame, boolean animated, boolean fromSet) } } updatePlayingMessageProgress(); - } else if (currentMessageObject.type == 0 && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && documentAttachType != DOCUMENT_ATTACH_TYPE_GIF && documentAttachType != DOCUMENT_ATTACH_TYPE_ROUND && documentAttachType != DOCUMENT_ATTACH_TYPE_VIDEO && documentAttachType != DOCUMENT_ATTACH_TYPE_WALLPAPER) { + } else if (currentMessageObject.type == 0 && + documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && + documentAttachType != DOCUMENT_ATTACH_TYPE_GIF && + documentAttachType != DOCUMENT_ATTACH_TYPE_ROUND && + documentAttachType != DOCUMENT_ATTACH_TYPE_VIDEO && + documentAttachType != DOCUMENT_ATTACH_TYPE_WALLPAPER && + documentAttachType != DOCUMENT_ATTACH_TYPE_THEME) { if (currentPhotoObject == null || !drawImageButton) { return; } @@ -6839,7 +6958,9 @@ public void setAllowAssistant(boolean value) { private void measureTime(MessageObject messageObject) { CharSequence signString; - if (messageObject.messageOwner.post_author != null) { + if (messageObject.scheduled) { + signString = null; + } else if (messageObject.messageOwner.post_author != null) { signString = messageObject.messageOwner.post_author.replace("\n", ""); } else if (messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.post_author != null) { signString = messageObject.messageOwner.fwd_from.post_author.replace("\n", ""); @@ -6859,7 +6980,7 @@ private void measureTime(MessageObject messageObject) { author = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.from_id); } boolean edited; - if (messageObject.isLiveLocation() || messageObject.getDialogId() == 777000 || messageObject.messageOwner.via_bot_id != 0 || messageObject.messageOwner.via_bot_name != null || author != null && author.bot) { + if (messageObject.scheduled || messageObject.isLiveLocation() || messageObject.messageOwner.edit_hide || messageObject.getDialogId() == 777000 || messageObject.messageOwner.via_bot_id != 0 || messageObject.messageOwner.via_bot_name != null || author != null && author.bot) { edited = false; } else if (currentPosition == null || currentMessagesGroup == null) { edited = (messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || messageObject.isEditing(); @@ -6889,6 +7010,9 @@ private void measureTime(MessageObject messageObject) { viewsTextWidth = (int) Math.ceil(Theme.chat_timePaint.measureText(currentViewsString)); timeWidth += viewsTextWidth + Theme.chat_msgInViewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } + if (messageObject.scheduled && messageObject.isSendError()) { + timeWidth += AndroidUtilities.dp(18); + } if (signString != null) { if (availableTimeWidth == 0) { availableTimeWidth = AndroidUtilities.dp(1000); @@ -6979,7 +7103,7 @@ private void updateCurrentUserAndChat() { } private void setMessageObjectInternal(MessageObject messageObject) { - if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 && !currentMessageObject.scheduled) { if (!currentMessageObject.viewsReloaded) { MessagesController.getInstance(currentAccount).addToViewsQueue(currentMessageObject); currentMessageObject.viewsReloaded = true; @@ -7007,7 +7131,7 @@ private void setMessageObjectInternal(MessageObject messageObject) { avatarImage.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, null, currentChat, 0); } else { currentPhoto = null; - avatarDrawable.setInfo(messageObject.messageOwner.from_id, null, null, false); + avatarDrawable.setInfo(messageObject.messageOwner.from_id, null, null); avatarImage.setImage(null, null, avatarDrawable, null, null, 0); } } else { @@ -7753,7 +7877,7 @@ public void drawNamesLayout(Canvas canvas) { Theme.chat_namePaint.setColor(AvatarDrawable.getNameColorForId(currentUser.id)); } else if (currentChat != null) { if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - Theme.chat_namePaint.setColor(AvatarDrawable.getNameColorForId(5)); + Theme.chat_namePaint.setColor(Theme.changeColorAccent(AvatarDrawable.getNameColorForId(5))); } else { Theme.chat_namePaint.setColor(AvatarDrawable.getNameColorForId(currentChat.id)); } @@ -7999,24 +8123,24 @@ public void drawTime(Canvas canvas) { paint.setAlpha(oldAlpha); int additionalX = (int) (-timeLayout.getLineLeft(0)); - if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { additionalX += (int) (timeWidth - timeLayout.getLineWidth(0)); if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { if (!currentMessageObject.isOutOwner()) { - setDrawableBounds(Theme.chat_msgMediaClockDrawable, timeX + AndroidUtilities.dp(11), layoutHeight - AndroidUtilities.dp(14.0f) - Theme.chat_msgMediaClockDrawable.getIntrinsicHeight()); + setDrawableBounds(Theme.chat_msgMediaClockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), layoutHeight - AndroidUtilities.dp(14.0f) - Theme.chat_msgMediaClockDrawable.getIntrinsicHeight()); Theme.chat_msgMediaClockDrawable.draw(canvas); } } else if (currentMessageObject.isSendError()) { if (!currentMessageObject.isOutOwner()) { - int x = timeX + AndroidUtilities.dp(11); - int y = layoutHeight - AndroidUtilities.dp(27.5f); + int x = timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)); + int y = layoutHeight - AndroidUtilities.dp(26.5f); rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); Theme.chat_msgErrorDrawable.draw(canvas); } - } else { + } else if (viewsLayout != null) { Drawable viewsDrawable; if (currentMessageObject.shouldDrawWithoutBackground()) { viewsDrawable = Theme.chat_msgStickerViewsDrawable; @@ -8029,12 +8153,10 @@ public void drawTime(Canvas canvas) { viewsDrawable.draw(canvas); viewsDrawable.setAlpha(oldAlpha); - if (viewsLayout != null) { - canvas.save(); - canvas.translate(timeX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(12.3f) - timeLayout.getHeight()); - viewsLayout.draw(canvas); - canvas.restore(); - } + canvas.save(); + canvas.translate(timeX + viewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(12.3f) - timeLayout.getHeight()); + viewsLayout.draw(canvas); + canvas.restore(); } } @@ -8045,25 +8167,25 @@ public void drawTime(Canvas canvas) { Theme.chat_timePaint.setAlpha(255); } else { int additionalX = (int) (-timeLayout.getLineLeft(0)); - if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup || (currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { additionalX += (int) (timeWidth - timeLayout.getLineWidth(0)); if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { if (!currentMessageObject.isOutOwner()) { Drawable clockDrawable = isDrawSelectionBackground() ? Theme.chat_msgInSelectedClockDrawable : Theme.chat_msgInClockDrawable; - setDrawableBounds(clockDrawable, timeX + AndroidUtilities.dp(11), layoutHeight - AndroidUtilities.dp(8.5f) - clockDrawable.getIntrinsicHeight()); + setDrawableBounds(clockDrawable, timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)), layoutHeight - AndroidUtilities.dp(8.5f) - clockDrawable.getIntrinsicHeight()); clockDrawable.draw(canvas); } } else if (currentMessageObject.isSendError()) { if (!currentMessageObject.isOutOwner()) { - int x = timeX + AndroidUtilities.dp(11); + int x = timeX + (currentMessageObject.scheduled ? 0 : AndroidUtilities.dp(11)); int y = layoutHeight - AndroidUtilities.dp(20.5f); rect.set(x, y, x + AndroidUtilities.dp(14), y + AndroidUtilities.dp(14)); canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), Theme.chat_msgErrorPaint); setDrawableBounds(Theme.chat_msgErrorDrawable, x + AndroidUtilities.dp(6), y + AndroidUtilities.dp(2)); Theme.chat_msgErrorDrawable.draw(canvas); } - } else { + } else if (viewsLayout != null) { if (!currentMessageObject.isOutOwner()) { Drawable viewsDrawable = isDrawSelectionBackground() ? Theme.chat_msgInViewsSelectedDrawable : Theme.chat_msgInViewsDrawable; setDrawableBounds(viewsDrawable, timeX, layoutHeight - AndroidUtilities.dp(4.5f) - timeLayout.getHeight()); @@ -8074,12 +8196,10 @@ public void drawTime(Canvas canvas) { viewsDrawable.draw(canvas); } - if (viewsLayout != null) { - canvas.save(); - canvas.translate(timeX + Theme.chat_msgInViewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(6.5f) - timeLayout.getHeight()); - viewsLayout.draw(canvas); - canvas.restore(); - } + canvas.save(); + canvas.translate(timeX + Theme.chat_msgInViewsDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(6.5f) - timeLayout.getHeight()); + viewsLayout.draw(canvas); + canvas.restore(); } } @@ -8107,7 +8227,7 @@ public void drawTime(Canvas canvas) { drawClock = false; drawError = true; } else if (currentMessageObject.isSent()) { - if (!currentMessageObject.isUnread()) { + if (!currentMessageObject.scheduled && !currentMessageObject.isUnread()) { drawCheck1 = true; drawCheck2 = true; } else { @@ -8166,10 +8286,12 @@ public void drawTime(Canvas canvas) { Theme.chat_msgMediaCheckDrawable.setAlpha(255); } } else { - Drawable drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; + Drawable drawable; if (drawCheck1) { + drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckReadSelectedDrawable : Theme.chat_msgOutCheckReadDrawable; setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - drawable.getIntrinsicHeight()); } else { + drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - drawable.getIntrinsicHeight()); } drawable.draw(canvas); @@ -9057,7 +9179,11 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) { } BotButton button = botButtons.get(buttonIndex); if (delegate != null) { - delegate.didPressBotButton(ChatMessageCell.this, button.button); + if (button.button != null) { + delegate.didPressBotButton(ChatMessageCell.this, button.button); + } else if (button.reaction != null) { + delegate.didPressReaction(ChatMessageCell.this, button.reaction); + } } sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED); } else if (virtualViewId >= POLL_BUTTONS_START) { 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 4831f7c2449..4096a62eb11 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -316,6 +316,7 @@ protected void onAttachedToWindow() { attachedToWindow = true; cornerProgress = 0.0f; setTranslationX(0); + setTranslationY(0); } @Override @@ -1434,7 +1435,7 @@ public void update(int mask) { unreadCount = customDialog.unread_count; drawPin = customDialog.pinned; dialogMuted = customDialog.muted; - avatarDrawable.setInfo(customDialog.id, customDialog.name, null, false); + avatarDrawable.setInfo(customDialog.id, customDialog.name, null); avatarImage.setImage(null, "50_50", avatarDrawable, null, 0); } else { if (isDialogCell) { @@ -1553,20 +1554,16 @@ public void update(int mask) { int lower_id = (int) dialogId; int high_id = (int) (dialogId >> 32); if (lower_id != 0) { - if (high_id == 1) { - chat = MessagesController.getInstance(currentAccount).getChat(lower_id); - } else { - if (lower_id < 0) { - chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); - if (!isDialogCell && chat != null && chat.migrated_to != null) { - TLRPC.Chat chat2 = MessagesController.getInstance(currentAccount).getChat(chat.migrated_to.channel_id); - if (chat2 != null) { - chat = chat2; - } + if (lower_id < 0) { + chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); + if (!isDialogCell && chat != null && chat.migrated_to != null) { + TLRPC.Chat chat2 = MessagesController.getInstance(currentAccount).getChat(chat.migrated_to.channel_id); + if (chat2 != null) { + chat = chat2; } - } else { - user = MessagesController.getInstance(currentAccount).getUser(lower_id); } + } else { + user = MessagesController.getInstance(currentAccount).getUser(lower_id); } } else { encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); @@ -1877,8 +1874,8 @@ protected void onDraw(Canvas canvas) { if (drawCheck1) { setDrawableBounds(Theme.dialogs_halfCheckDrawable, halfCheckDrawLeft, checkDrawTop); Theme.dialogs_halfCheckDrawable.draw(canvas); - setDrawableBounds(Theme.dialogs_checkDrawable, checkDrawLeft, checkDrawTop); - Theme.dialogs_checkDrawable.draw(canvas); + setDrawableBounds(Theme.dialogs_checkReadDrawable, checkDrawLeft, checkDrawTop); + Theme.dialogs_checkReadDrawable.draw(canvas); } else { setDrawableBounds(Theme.dialogs_checkDrawable, checkDrawLeft, checkDrawTop); Theme.dialogs_checkDrawable.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java index dadce8f688d..bfa8a22a1ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java @@ -161,7 +161,7 @@ public void buildLayout() { nameLeft = AndroidUtilities.dp(14); } nameString = recentMeUrl.set.set.title; - avatarDrawable.setInfo(5, recentMeUrl.set.set.title, null, false); + avatarDrawable.setInfo(5, recentMeUrl.set.set.title, null); avatarImage.setImage(ImageLocation.getForDocument(recentMeUrl.set.cover), null, avatarDrawable, null, recentMeUrl, 0); } else if (recentMeUrl instanceof TLRPC.TL_recentMeUrlChatInvite) { if (!LocaleController.isRTL) { @@ -183,7 +183,7 @@ public void buildLayout() { avatarImage.setImage(ImageLocation.getForChat(recentMeUrl.chat_invite.chat, false), "50_50", avatarDrawable, null, recentMeUrl, 0); } else { nameString = recentMeUrl.chat_invite.title; - avatarDrawable.setInfo(5, recentMeUrl.chat_invite.title, null, false); + avatarDrawable.setInfo(5, recentMeUrl.chat_invite.title, null); if (recentMeUrl.chat_invite.broadcast || recentMeUrl.chat_invite.channel) { drawNameBroadcast = true; nameLockTop = AndroidUtilities.dp(16.5f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index 27d545443f4..cf8a9781e8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -18,6 +18,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; @@ -113,7 +114,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onDraw(Canvas canvas) { Drawable backgroundDrawable = Theme.getCachedWallpaper(); String backgroundKey = applyBackground(false); - boolean useImageBackground = !backgroundKey.equals(Theme.key_chats_menuTopBackground) && Theme.isCustomTheme() && !Theme.isPatternWallpaper() && backgroundDrawable != null; + boolean useImageBackground = !backgroundKey.equals(Theme.key_chats_menuTopBackground) && Theme.isCustomTheme() && !Theme.isPatternWallpaper() && backgroundDrawable != null && !(backgroundDrawable instanceof ColorDrawable); boolean drawCatsShadow = false; int color; if (!useImageBackground && Theme.hasThemeKey(Theme.key_chats_menuTopShadowCats)) { @@ -136,7 +137,7 @@ protected void onDraw(Canvas canvas) { if (shadowView.getVisibility() != VISIBLE) { shadowView.setVisibility(VISIBLE); } - if (backgroundDrawable instanceof ColorDrawable) { + if (backgroundDrawable instanceof ColorDrawable || backgroundDrawable instanceof GradientDrawable) { backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); backgroundDrawable.draw(canvas); } else if (backgroundDrawable instanceof BitmapDrawable) { 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 1d6bbbe3077..67d38a45252 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -66,7 +66,7 @@ public HeaderCell(Context context, boolean dialog, int padding, int topMargin, b } public void setHeight(int value) { - textView.setMinHeight(AndroidUtilities.dp(height) - ((LayoutParams) textView.getLayoutParams()).topMargin); + textView.setMinHeight(AndroidUtilities.dp(height = value) - ((LayoutParams) textView.getLayoutParams()).topMargin); } public void setEnabled(boolean value, ArrayList animators) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/InviteUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/InviteUserCell.java index 8905fcbf6f0..6c46d193a94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/InviteUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/InviteUserCell.java @@ -90,7 +90,7 @@ public void update(int mask) { } String newName = null; - avatarDrawable.setInfo(currentContact.contact_id, currentContact.first_name, currentContact.last_name, false); + avatarDrawable.setInfo(currentContact.contact_id, currentContact.first_name, currentContact.last_name); if (currentName != null) { nameTextView.setText(currentName, true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java index c33ad1902fb..35902ea58da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java @@ -63,7 +63,7 @@ public void setUser(TLRPC.User user) { public void setCount(int count) { nameTextView.setText(""); - avatarDrawable.setInfo(0, null, null, false, "+" + LocaleController.formatShortNumber(count, result)); + avatarDrawable.setInfo(0, null, null, "+" + LocaleController.formatShortNumber(count, result)); imageView.setImage(null, "50_50", avatarDrawable, null); } } 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 af7a7f156ba..99b20c57596 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -17,6 +17,7 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; @@ -33,9 +34,13 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox2; @@ -59,6 +64,10 @@ public class PhotoAttachPhotoCell extends FrameLayout { private boolean needCheckShow; private int itemSize; private boolean isVertical; + private boolean zoomOnSelect = true; + + private MediaController.PhotoEntry photoEntry; + private MediaController.SearchImage searchEntry; private Paint backgroundPaint = new Paint(); private AnimatorSet animator; @@ -67,8 +76,6 @@ public interface PhotoAttachPhotoCellDelegate { void onCheckClick(PhotoAttachPhotoCell v); } - private MediaController.PhotoEntry photoEntry; - public PhotoAttachPhotoCell(Context context) { super(context); @@ -210,6 +217,37 @@ public void setPhotoEntry(MediaController.PhotoEntry entry, boolean needCheckSho requestLayout(); } + public void setPhotoEntry(MediaController.SearchImage searchImage, boolean needCheckShow, boolean last) { + pressed = false; + searchEntry = searchImage; + isLast = last; + + Drawable thumb = zoomOnSelect ? Theme.chat_attachEmptyDrawable : getResources().getDrawable(R.drawable.nophotos); + if (searchImage.thumbPhotoSize != null) { + imageView.setImage(ImageLocation.getForPhoto(searchImage.thumbPhotoSize, searchImage.photo), null, thumb, searchImage); + } else if (searchImage.photoSize != null) { + imageView.setImage(ImageLocation.getForPhoto(searchImage.photoSize, searchImage.photo), "80_80", thumb, searchImage); + } else if (searchImage.thumbPath != null) { + imageView.setImage(searchImage.thumbPath, null, thumb); + } else if (searchImage.thumbUrl != null && searchImage.thumbUrl.length() > 0) { + imageView.setImage(searchImage.thumbUrl, null, thumb); + } else if (MessageObject.isDocumentHasThumb(searchImage.document)) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320); + imageView.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage); + } else { + imageView.setImageDrawable(thumb); + } + boolean showing = needCheckShow && PhotoViewer.isShowingImage(searchImage.getPathToAttach()); + imageView.getImageReceiver().setVisible(!showing, true); + checkBox.setAlpha(showing ? 0.0f : 1.0f); + videoInfoContainer.setAlpha(showing ? 0.0f : 1.0f); + requestLayout(); + } + + public boolean isChecked() { + return checkBox.isChecked(); + } + public void setChecked(int num, boolean checked, boolean animated) { checkBox.setChecked(num, checked, animated); if (itemSizeChanged) { @@ -344,7 +382,7 @@ public boolean onTouchEvent(MotionEvent event) { @Override protected void onDraw(Canvas canvas) { - if (checkBox.isChecked() || container.getScaleX() != 1.0f || !imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f || PhotoViewer.isShowingImage(photoEntry.path)) { + if (checkBox.isChecked() || container.getScaleX() != 1.0f || !imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f || photoEntry != null && PhotoViewer.isShowingImage(photoEntry.path) || searchEntry != null && PhotoViewer.isShowingImage(searchEntry.getPathToAttach())) { backgroundPaint.setColor(Theme.getColor(Theme.key_chat_attachPhotoBackground)); canvas.drawRect(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight(), backgroundPaint); } @@ -354,7 +392,7 @@ protected void onDraw(Canvas canvas) { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setEnabled(true); - if (photoEntry.isVideo) { + if (photoEntry != null && photoEntry.isVideo) { info.setText(LocaleController.getString("AttachVideo", R.string.AttachVideo) + ", " + LocaleController.formatCallDuration(photoEntry.duration)); } else { info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 7765cf5d28a..1a126475297 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -232,22 +232,14 @@ public void buildLayout() { nameLockTop = AndroidUtilities.dp(20.5f); } else { if (chat != null) { - if (chat.id < 0) { - dialog_id = AndroidUtilities.makeBroadcastId(chat.id); - if (SharedConfig.drawDialogIcons) { + dialog_id = -chat.id; + if (SharedConfig.drawDialogIcons) { + if (ChatObject.isChannel(chat) && !chat.megagroup) { drawNameBroadcast = true; - } - nameLockTop = AndroidUtilities.dp(22.5f); - } else { - dialog_id = -chat.id; - if (SharedConfig.drawDialogIcons) { - if (ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(22.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(24); - } + nameLockTop = AndroidUtilities.dp(22.5f); + } else { + drawNameGroup = true; + nameLockTop = AndroidUtilities.dp(24); } } drawCheck = chat.verified; @@ -496,7 +488,7 @@ public void update(int mask) { avatarDrawable.setInfo(chat); avatarImage.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, null, chat, 0); } else { - avatarDrawable.setInfo(0, null, null, false); + avatarDrawable.setInfo(0, null, null); avatarImage.setImage(null, null, avatarDrawable, null, null, 0); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java index 3ddf4ce9e3b..f339385b0cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java @@ -40,6 +40,7 @@ public class ThemeCell extends FrameLayout { private ImageView optionsButton; private boolean needDivider; private Paint paint; + private Paint paintStroke; private Theme.ThemeInfo currentThemeInfo; private boolean isNightTheme; private static byte[] bytes = new byte[1024]; @@ -52,6 +53,9 @@ public ThemeCell(Context context, boolean nightTheme) { isNightTheme = nightTheme; paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG); + paintStroke.setStyle(Paint.Style.STROKE); + paintStroke.setStrokeWidth(AndroidUtilities.dp(2)); textView = new TextView(context); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); @@ -122,16 +126,14 @@ public void setTheme(Theme.ThemeInfo themeInfo, boolean divider) { updateCurrentThemeCheck(); boolean finished = false; - if (themeInfo.pathToFile != null || themeInfo.assetName != null) { + if (Theme.isThemeDefault(themeInfo) || themeInfo.assetName != null) { + paint.setColor(Theme.changeColorAccent(themeInfo, themeInfo.accentColor, themeInfo.previewBackgroundColor)); + finished = true; + } else if (themeInfo.pathToFile != null) { FileInputStream stream = null; try { int currentPosition = 0; - File file; - if (themeInfo.assetName != null) { - file = Theme.getAssetFile(themeInfo.assetName); - } else { - file = new File(themeInfo.pathToFile); - } + File file = new File(themeInfo.pathToFile); stream = new FileInputStream(file); int idx; int read; @@ -194,6 +196,10 @@ public void setTheme(Theme.ThemeInfo themeInfo, boolean divider) { if (!finished) { paint.setColor(Theme.getDefaultColor(Theme.key_actionBarDefault)); } + paintStroke.setColor(themeInfo.accentColor); + if (themeInfo.accentColor != 0) { + paintStroke.setAlpha(180); + } } public void updateCurrentThemeCheck() { @@ -219,6 +225,7 @@ protected void onDraw(Canvas canvas) { x = getWidth() - x; } canvas.drawCircle(x, AndroidUtilities.dp(13 + 11), AndroidUtilities.dp(11), paint); + canvas.drawCircle(x, AndroidUtilities.dp(13 + 11), AndroidUtilities.dp(10), paintStroke); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java new file mode 100644 index 00000000000..c32e22b0572 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java @@ -0,0 +1,204 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.view.MotionEvent; +import android.widget.LinearLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBarLayout; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class ThemePreviewMessagesCell extends LinearLayout { + + private Drawable backgroundDrawable; + private Drawable oldBackgroundDrawable; + private ChatMessageCell[] cells = new ChatMessageCell[2]; + private Drawable shadowDrawable; + private ActionBarLayout parentLayout; + + public ThemePreviewMessagesCell(Context context, ActionBarLayout layout, int type) { + super(context); + + parentLayout = layout; + + setWillNotDraw(false); + setOrientation(LinearLayout.VERTICAL); + setPadding(0, AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11)); + + shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); + + int date = (int) (System.currentTimeMillis() / 1000) - 60 * 60; + TLRPC.Message message = new TLRPC.TL_message(); + if (type == 0) { + message.message = LocaleController.getString("FontSizePreviewReply", R.string.FontSizePreviewReply); + } else { + message.message = LocaleController.getString("NewThemePreviewReply", R.string.NewThemePreviewReply); + } + message.date = date + 60; + message.dialog_id = 1; + message.flags = 259; + message.from_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = true; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = 0; + MessageObject replyMessageObject = new MessageObject(UserConfig.selectedAccount, message, true); + + message = new TLRPC.TL_message(); + if (type == 0) { + message.message = LocaleController.getString("FontSizePreviewLine2", R.string.FontSizePreviewLine2); + } else { + message.message = LocaleController.getString("NewThemePreviewLine2", R.string.NewThemePreviewLine2); + } + message.date = date + 960; + message.dialog_id = 1; + message.flags = 259; + message.from_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = true; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = 0; + MessageObject message1 = new MessageObject(UserConfig.selectedAccount, message, true); + message1.resetLayout(); + message1.eventId = 1; + + message = new TLRPC.TL_message(); + if (type == 0) { + message.message = LocaleController.getString("FontSizePreviewLine1", R.string.FontSizePreviewLine1); + } else { + message.message = LocaleController.getString("NewThemePreviewLine1", R.string.NewThemePreviewLine1); + } + message.date = date + 60; + message.dialog_id = 1; + message.flags = 257 + 8; + message.from_id = 0; + message.id = 1; + message.reply_to_msg_id = 5; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = false; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + MessageObject message2 = new MessageObject(UserConfig.selectedAccount, message, true); + if (type == 0) { + message2.customReplyName = LocaleController.getString("FontSizePreviewName", R.string.FontSizePreviewName); + } else { + message2.customReplyName = LocaleController.getString("NewThemePreviewName", R.string.NewThemePreviewName); + } + message2.eventId = 1; + message2.resetLayout(); + message2.replyMessageObject = replyMessageObject; + + for (int a = 0; a < cells.length; a++) { + cells[a] = new ChatMessageCell(context); + cells[a].setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + + }); + cells[a].isChat = false; + cells[a].setFullyDraw(true); + cells[a].setMessageObject(a == 0 ? message2 : message1, null, false, false); + addView(cells[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + } + + public ChatMessageCell[] getCells() { + return cells; + } + + @Override + public void invalidate() { + super.invalidate(); + for (int a = 0; a < cells.length; a++) { + cells[a].invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + Drawable newDrawable = Theme.getCachedWallpaperNonBlocking(); + if (newDrawable != backgroundDrawable && newDrawable != null) { + if (Theme.isAnimatingColor()) { + oldBackgroundDrawable = backgroundDrawable; + } + backgroundDrawable = newDrawable; + } + float themeAnimationValue = parentLayout.getThemeAnimationValue(); + for (int a = 0; a < 2; a++) { + Drawable drawable = a == 0 ? oldBackgroundDrawable : backgroundDrawable; + if (drawable == null) { + continue; + } + if (a == 1 && oldBackgroundDrawable != null && parentLayout != null) { + drawable.setAlpha((int) (255 * themeAnimationValue)); + } else { + drawable.setAlpha(255); + } + if (drawable instanceof ColorDrawable || drawable instanceof GradientDrawable) { + drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + drawable.draw(canvas); + } else if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) { + canvas.save(); + float scale = 2.0f / AndroidUtilities.density; + canvas.scale(scale, scale); + drawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale)); + drawable.draw(canvas); + canvas.restore(); + } else { + int viewHeight = getMeasuredHeight(); + float scaleX = (float) getMeasuredWidth() / (float) drawable.getIntrinsicWidth(); + float scaleY = (float) (viewHeight) / (float) drawable.getIntrinsicHeight(); + float scale = scaleX < scaleY ? scaleY : scaleX; + int width = (int) Math.ceil(drawable.getIntrinsicWidth() * scale); + int height = (int) Math.ceil(drawable.getIntrinsicHeight() * scale); + int x = (getMeasuredWidth() - width) / 2; + int y = (viewHeight - height) / 2; + canvas.save(); + canvas.clipRect(0, 0, width, getMeasuredHeight()); + drawable.setBounds(x, y, x + width, y + height); + drawable.draw(canvas); + canvas.restore(); + } + } + if (a == 0 && oldBackgroundDrawable != null && themeAnimationValue >= 1.0f) { + oldBackgroundDrawable = null; + } + } + shadowDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + shadowDrawable.draw(canvas); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return false; + } + + @Override + protected void dispatchSetPressed(boolean pressed) { + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java new file mode 100644 index 00000000000..b32cdc7b01d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java @@ -0,0 +1,847 @@ +package org.telegram.ui.Cells; + +import android.animation.ArgbEvaluator; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.net.Uri; +import android.os.SystemClock; +import android.text.TextPaint; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.BackgroundGradientDrawable; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RadioButton; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.ThemeActivity; +import org.telegram.ui.ThemeSetUrlActivity; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.HashMap; + +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +public class ThemesHorizontalListCell extends RecyclerListView implements NotificationCenter.NotificationCenterDelegate { + + private static byte[] bytes = new byte[1024]; + + private boolean drawDivider; + private LinearLayoutManager horizontalLayoutManager; + private HashMap loadingThemes = new HashMap<>(); + private HashMap loadingWallpapers = new HashMap<>(); + private Theme.ThemeInfo prevThemeInfo; + private ThemesListAdapter adapter; + + private ArrayList darkThemes; + private ArrayList defaultThemes; + private int currentType; + + private class ThemesListAdapter extends RecyclerListView.SelectionAdapter { + + private Context mContext; + + ThemesListAdapter(Context context) { + mContext = context; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new RecyclerListView.Holder(new InnerThemeView(mContext)); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + InnerThemeView view = (InnerThemeView) holder.itemView; + ArrayList arrayList; + int p = position; + if (position < defaultThemes.size()) { + arrayList = defaultThemes; + } else { + arrayList = darkThemes; + p -= defaultThemes.size(); + } + view.setTheme(arrayList.get(p), position == getItemCount() - 1, position == 0); + } + + @Override + public int getItemCount() { + return defaultThemes.size() + darkThemes.size(); + } + } + + private class InnerThemeView extends FrameLayout { + + private RadioButton button; + private Theme.ThemeInfo themeInfo; + private RectF rect = new RectF(); + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Drawable optionsDrawable; + + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private Drawable inDrawable; + private Drawable outDrawable; + private boolean isLast; + private boolean isFirst; + + private float placeholderAlpha; + + private int accentColor; + private int oldAccentColor; + private boolean accentColorChanged; + + private ObjectAnimator accentAnimator; + private float accentState; + private final ArgbEvaluator evaluator = new ArgbEvaluator(); + + private Drawable backgroundDrawable; + private Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + private BitmapShader bitmapShader; + private boolean hasWhiteBackground; + private Matrix shaderMatrix = new Matrix(); + + private Drawable loadingDrawable; + private int loadingColor; + + private long lastDrawTime; + + private boolean pressed; + + public InnerThemeView(Context context) { + super(context); + setWillNotDraw(false); + + inDrawable = context.getResources().getDrawable(R.drawable.minibubble_in).mutate(); + outDrawable = context.getResources().getDrawable(R.drawable.minibubble_out).mutate(); + + textPaint.setTextSize(AndroidUtilities.dp(13)); + + button = new RadioButton(context) { + @Override + public void invalidate() { + super.invalidate(); + //ListView.this.invalidate(); + } + }; + button.setSize(AndroidUtilities.dp(20)); + addView(button, LayoutHelper.createFrame(22, 22, Gravity.LEFT | Gravity.TOP, 27, 75, 0, 0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(76 + (isLast ? 22 : 15) + (isFirst ? 22 : 0)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148), MeasureSpec.EXACTLY)); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (optionsDrawable == null || themeInfo == null || themeInfo.info != null && !themeInfo.themeLoaded || currentType != ThemeActivity.THEME_TYPE_BASIC) { + return super.onTouchEvent(event); + } + int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) { + float x = event.getX(); + float y = event.getY(); + if (x > rect.centerX() && y < rect.centerY() - AndroidUtilities.dp(10)) { + if (action == MotionEvent.ACTION_DOWN) { + pressed = true; + } else { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + showOptionsForTheme(themeInfo); + } + } + if (action == MotionEvent.ACTION_UP) { + pressed = false; + } + } + return pressed; + } + + private boolean parseTheme() { + boolean finished = false; + File file = new File(themeInfo.pathToFile); + try (FileInputStream stream = new FileInputStream(file)) { + int currentPosition = 0; + int idx; + int read; + int linesRead = 0; + while ((read = stream.read(bytes)) != -1) { + int previousPosition = currentPosition; + int start = 0; + for (int a = 0; a < read; a++) { + if (bytes[a] == '\n') { + linesRead++; + int len = a - start + 1; + String line = new String(bytes, start, len - 1, "UTF-8"); + if (line.startsWith("WLS=")) { + String wallpaperLink = line.substring(4); + Uri uri = Uri.parse(wallpaperLink); + themeInfo.slug = uri.getQueryParameter("slug"); + themeInfo.pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(wallpaperLink) + ".wp").getAbsolutePath(); + + String mode = uri.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int b = 0; b < modes.length; b++) { + if ("blur".equals(modes[b])) { + themeInfo.isBlured = true; + } + } + } + } + } else if (line.startsWith("WPS")) { + themeInfo.previewWallpaperOffset = currentPosition + len; + finished = true; + break; + } else { + if ((idx = line.indexOf('=')) != -1) { + String key = line.substring(0, idx); + if (key.equals(Theme.key_chat_inBubble) || key.equals(Theme.key_chat_outBubble) || key.equals(Theme.key_chat_wallpaper) || key.equals(Theme.key_chat_wallpaper_gradient_to)) { + String param = line.substring(idx + 1); + int value; + if (param.length() > 0 && param.charAt(0) == '#') { + try { + value = Color.parseColor(param); + } catch (Exception ignore) { + value = Utilities.parseInt(param); + } + } else { + value = Utilities.parseInt(param); + } + switch (key) { + case Theme.key_chat_inBubble: + themeInfo.previewInColor = value; + break; + case Theme.key_chat_outBubble: + themeInfo.previewOutColor = value; + break; + case Theme.key_chat_wallpaper: + themeInfo.previewBackgroundColor = value; + break; + case Theme.key_chat_wallpaper_gradient_to: + themeInfo.previewBackgroundGradientColor = value; + break; + } + } + } + } + start += len; + currentPosition += len; + } + } + if (finished || previousPosition == currentPosition) { + break; + } + stream.getChannel().position(currentPosition); + } + } catch (Throwable e) { + FileLog.e(e); + } + + if (themeInfo.pathToWallpaper != null && !themeInfo.badWallpaper) { + file = new File(themeInfo.pathToWallpaper); + if (!file.exists()) { + if (!loadingWallpapers.containsKey(themeInfo)) { + loadingWallpapers.put(themeInfo, themeInfo.slug); + TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper(); + TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); + inputWallPaperSlug.slug = themeInfo.slug; + req.wallpaper = inputWallPaperSlug; + ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; + String name = FileLoader.getAttachFileName(wallPaper.document); + if (!loadingThemes.containsKey(name)) { + loadingThemes.put(name, themeInfo); + FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1); + } + } else { + themeInfo.badWallpaper = true; + } + })); + } + return false; + } + } + themeInfo.previewParsed = true; + return true; + } + + private void applyTheme() { + inDrawable.setColorFilter(new PorterDuffColorFilter(themeInfo.previewInColor, PorterDuff.Mode.MULTIPLY)); + outDrawable.setColorFilter(new PorterDuffColorFilter(themeInfo.previewOutColor, PorterDuff.Mode.MULTIPLY)); + if (themeInfo.pathToFile == null) { + updateAccentColor(themeInfo.accentColor, false); + optionsDrawable = null; + } else { + optionsDrawable = getResources().getDrawable(R.drawable.preview_dots).mutate(); + } + + bitmapShader = null; + backgroundDrawable = null; + double[] hsv = null; + if (themeInfo.previewBackgroundGradientColor != 0) { + BackgroundGradientDrawable drawable = new BackgroundGradientDrawable(GradientDrawable.Orientation.BL_TR, new int[]{themeInfo.previewBackgroundColor, themeInfo.previewBackgroundGradientColor}); + drawable.setCornerRadius(AndroidUtilities.dp(6)); + backgroundDrawable = drawable; + hsv = AndroidUtilities.rgbToHsv(Color.red(themeInfo.previewBackgroundColor), Color.green(themeInfo.previewBackgroundColor), Color.blue(themeInfo.previewBackgroundColor)); + } else if (themeInfo.previewWallpaperOffset > 0 || themeInfo.pathToWallpaper != null) { + Bitmap wallpaper = getScaledBitmap(AndroidUtilities.dp(76), AndroidUtilities.dp(97), themeInfo.pathToWallpaper, themeInfo.pathToFile, themeInfo.previewWallpaperOffset); + if (wallpaper != null) { + backgroundDrawable = new BitmapDrawable(wallpaper); + bitmapShader = new BitmapShader(wallpaper, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + bitmapPaint.setShader(bitmapShader); + int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable); + hsv = AndroidUtilities.rgbToHsv(Color.red(colors[0]), Color.green(colors[0]), Color.blue(colors[0])); + } + } else if (themeInfo.previewBackgroundColor != 0) { + hsv = AndroidUtilities.rgbToHsv(Color.red(themeInfo.previewBackgroundColor), Color.green(themeInfo.previewBackgroundColor), Color.blue(themeInfo.previewBackgroundColor)); + } + if (hsv != null && hsv[1] <= 0.1f && hsv[2] >= 0.96f) { + hasWhiteBackground = true; + } else { + hasWhiteBackground = false; + } + if (themeInfo.previewBackgroundColor == 0 && themeInfo.previewParsed && backgroundDrawable == null) { + BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.catstile).mutate(); + bitmapShader = new BitmapShader(drawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); + bitmapPaint.setShader(bitmapShader); + backgroundDrawable = drawable; + } + invalidate(); + } + + public void setTheme(Theme.ThemeInfo theme, boolean last, boolean first) { + themeInfo = theme; + isFirst = first; + isLast = last; + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) button.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(isFirst ? 22 + 27 : 27); + button.setLayoutParams(layoutParams); + placeholderAlpha = 0.0f; + + if (themeInfo.pathToFile != null && !themeInfo.previewParsed) { + themeInfo.previewInColor = Theme.getDefaultColor(Theme.key_chat_inBubble); + themeInfo.previewOutColor = Theme.getDefaultColor(Theme.key_chat_outBubble); + File file = new File(themeInfo.pathToFile); + boolean fileExists = file.exists(); + boolean parsed = fileExists && parseTheme(); + if ((!parsed || !fileExists) && themeInfo.info != null) { + if (themeInfo.info.document != null) { + themeInfo.themeLoaded = false; + placeholderAlpha = 1.0f; + loadingDrawable = getResources().getDrawable(R.drawable.msg_theme).mutate(); + Theme.setDrawableColor(loadingDrawable, loadingColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7)); + if (!fileExists) { + String name = FileLoader.getAttachFileName(themeInfo.info.document); + if (!loadingThemes.containsKey(name)) { + loadingThemes.put(name, themeInfo); + FileLoader.getInstance(themeInfo.account).loadFile(themeInfo.info.document, themeInfo.info, 1, 1); + } + } + } else { + loadingDrawable = getResources().getDrawable(R.drawable.preview_custom).mutate(); + Theme.setDrawableColor(loadingDrawable, loadingColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7)); + } + } + } + applyTheme(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + button.setChecked(themeInfo == t, false); + if (themeInfo != null && themeInfo.info != null && !themeInfo.themeLoaded) { + String name = FileLoader.getAttachFileName(themeInfo.info.document); + if (!loadingThemes.containsKey(name) && !loadingWallpapers.containsKey(themeInfo)) { + themeInfo.themeLoaded = true; + placeholderAlpha = 0.0f; + parseTheme(); + applyTheme(); + } + } + } + + public void updateCurrentThemeCheck() { + Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + button.setChecked(themeInfo == t, true); + } + + void updateAccentColor(int accent, boolean animate) { + oldAccentColor = accentColor; + accentColor = accent; + + if (accentAnimator != null) { + accentAnimator.cancel(); + } + + if (animate) { + accentAnimator = ObjectAnimator.ofFloat(this, "accentState", 0f, 1f); + accentAnimator.setDuration(200); + accentAnimator.start(); + } else { + setAccentState(1f); + } + } + + @Keep + public float getAccentState() { + return accentColor; + } + + @Keep + public void setAccentState(float state) { + accentState = state; + accentColorChanged = true; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + if (accentColor != themeInfo.accentColor) { + updateAccentColor(themeInfo.accentColor, true); + } + + int x = isFirst ? AndroidUtilities.dp(22) : 0; + int y = AndroidUtilities.dp(11); + rect.set(x, y, x + AndroidUtilities.dp(76), y + AndroidUtilities.dp(97)); + + String name = themeInfo.getName(); + if (name.toLowerCase().endsWith(".attheme")) { + name = name.substring(0, name.lastIndexOf('.')); + } + int maxWidth = getMeasuredWidth() - AndroidUtilities.dp(isFirst ? 10 : 15) - (isLast ? AndroidUtilities.dp(7) : 0); + String text = TextUtils.ellipsize(name, textPaint, maxWidth, TextUtils.TruncateAt.END).toString(); + int width = (int) Math.ceil(textPaint.measureText(text)); + textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + canvas.drawText(text, x + (AndroidUtilities.dp(76) - width) / 2, AndroidUtilities.dp(131), textPaint); + + boolean drawContent = themeInfo.info == null || themeInfo.info.document != null && themeInfo.themeLoaded; + + if (drawContent) { + paint.setColor(tint(themeInfo.previewBackgroundColor)); + + if (accentColorChanged) { + inDrawable.setColorFilter(new PorterDuffColorFilter(tint(themeInfo.previewInColor), PorterDuff.Mode.MULTIPLY)); + outDrawable.setColorFilter(new PorterDuffColorFilter(tint(themeInfo.previewOutColor), PorterDuff.Mode.MULTIPLY)); + accentColorChanged = false; + } + + if (backgroundDrawable != null) { + if (bitmapShader != null) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable; + float bitmapW = bitmapDrawable.getBitmap().getWidth(); + float bitmapH = bitmapDrawable.getBitmap().getHeight(); + float scaleW = bitmapW / rect.width(); + float scaleH = bitmapH / rect.height(); + + shaderMatrix.reset(); + float scale = 1.0f / Math.min(scaleW, scaleH); + if (bitmapW / scaleH > rect.width()) { + bitmapW /= scaleH; + shaderMatrix.setTranslate(x - (bitmapW - rect.width()) / 2, y); + } else { + bitmapH /= scaleW; + shaderMatrix.setTranslate(x, y - (bitmapH - rect.height()) / 2); + } + shaderMatrix.preScale(scale, scale); + bitmapShader.setLocalMatrix(shaderMatrix); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), bitmapPaint); + } else { + backgroundDrawable.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); + backgroundDrawable.draw(canvas); + } + } else { + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); + } + + button.setColor(0x66ffffff, 0xffffffff); + + if (themeInfo.accentBaseColor != 0) { + if ("Arctic Blue".equals(themeInfo.name)) { + button.setColor(0xffb3b3b3, tint(themeInfo.accentBaseColor)); + Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint); + } + } else if (hasWhiteBackground) { + button.setColor(0xffb3b3b3, themeInfo.previewOutColor); + Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint); + } + + inDrawable.setBounds(x + AndroidUtilities.dp(6), AndroidUtilities.dp(22), x + AndroidUtilities.dp(6 + 43), AndroidUtilities.dp(22 + 14)); + inDrawable.draw(canvas); + + outDrawable.setBounds(x + AndroidUtilities.dp(27), AndroidUtilities.dp(41), x + AndroidUtilities.dp(27 + 43), AndroidUtilities.dp(41 + 14)); + outDrawable.draw(canvas); + + if (optionsDrawable != null && currentType == ThemeActivity.THEME_TYPE_BASIC) { + x = (int) rect.right - AndroidUtilities.dp(16); + y = (int) rect.top + AndroidUtilities.dp(6); + optionsDrawable.setBounds(x, y, x + optionsDrawable.getIntrinsicWidth(), y + optionsDrawable.getIntrinsicHeight()); + optionsDrawable.draw(canvas); + } + } + + if (themeInfo.info != null && themeInfo.info.document == null) { + button.setAlpha(0.0f); + Theme.chat_instantViewRectPaint.setColor(0x2bb0b5ba); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint); + if (loadingDrawable != null) { + int newColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7); + if (loadingColor != newColor) { + Theme.setDrawableColor(loadingDrawable, loadingColor = newColor); + } + x = (int) (rect.centerX() - loadingDrawable.getIntrinsicWidth() / 2); + y = (int) (rect.centerY() - loadingDrawable.getIntrinsicHeight() / 2); + loadingDrawable.setBounds(x, y, x + loadingDrawable.getIntrinsicWidth(), y + loadingDrawable.getIntrinsicHeight()); + loadingDrawable.draw(canvas); + } + } else if (themeInfo.info != null && !themeInfo.themeLoaded || placeholderAlpha > 0.0f) { + button.setAlpha(1.0f - placeholderAlpha); + paint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + paint.setAlpha((int) (placeholderAlpha * 255)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); + if (loadingDrawable != null) { + int newColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7); + if (loadingColor != newColor) { + Theme.setDrawableColor(loadingDrawable, loadingColor = newColor); + } + x = (int) (rect.centerX() - loadingDrawable.getIntrinsicWidth() / 2); + y = (int) (rect.centerY() - loadingDrawable.getIntrinsicHeight() / 2); + loadingDrawable.setAlpha((int) (placeholderAlpha * 255)); + loadingDrawable.setBounds(x, y, x + loadingDrawable.getIntrinsicWidth(), y + loadingDrawable.getIntrinsicHeight()); + loadingDrawable.draw(canvas); + } + if (themeInfo.themeLoaded) { + long newTime = SystemClock.uptimeMillis(); + long dt = Math.min(17, newTime - lastDrawTime); + lastDrawTime = newTime; + placeholderAlpha -= dt / 180.0f; + if (placeholderAlpha < 0.0f) { + placeholderAlpha = 0.0f; + } + invalidate(); + } + } else if (button.getAlpha() != 1.0f) { + button.setAlpha(1.0f); + } + } + + private int tint(int color) { + if (accentState == 1.0f) { + return Theme.changeColorAccent(themeInfo, accentColor, color); + } else { + int oldColor = Theme.changeColorAccent(themeInfo, oldAccentColor, color); + int newColor = Theme.changeColorAccent(themeInfo, accentColor, color); + return (int) evaluator.evaluate(accentState, oldColor, newColor); + } + } + } + + public ThemesHorizontalListCell(Context context, int type, ArrayList def, ArrayList dark) { + super(context); + + darkThemes = dark; + defaultThemes = def; + currentType = type; + + if (type == ThemeActivity.THEME_TYPE_OTHER) { + setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + } else { + setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } + setItemAnimator(null); + setLayoutAnimation(null); + horizontalLayoutManager = new LinearLayoutManager(context) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + setPadding(0, 0, 0, 0); + setClipToPadding(false); + horizontalLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + setLayoutManager(horizontalLayoutManager); + setAdapter(adapter = new ThemesListAdapter(context)); + setOnItemClickListener((view1, position) -> { + InnerThemeView innerThemeView = (InnerThemeView) view1; + Theme.ThemeInfo themeInfo = innerThemeView.themeInfo; + if (themeInfo.info != null) { + if (!themeInfo.themeLoaded) { + return; + } + if (themeInfo.info.document == null) { + presentFragment(new ThemeSetUrlActivity(themeInfo, true)); + return; + } + } + if (currentType == ThemeActivity.THEME_TYPE_NIGHT) { + if (themeInfo == Theme.getCurrentNightTheme()) { + return; + } + Theme.setCurrentNightTheme(themeInfo); + } else { + if (themeInfo == Theme.getCurrentTheme()) { + return; + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false); + } + updateRows(); + + int left = view1.getLeft(); + int right = view1.getRight(); + if (left < 0) { + smoothScrollBy(left - AndroidUtilities.dp(8), 0); + } else if (right > getMeasuredWidth()) { + smoothScrollBy(right - getMeasuredWidth(), 0); + } + + int count = getChildCount(); + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (child instanceof InnerThemeView) { + ((InnerThemeView) child).updateCurrentThemeCheck(); + } + } + }); + setOnItemLongClickListener((view12, position) -> { + InnerThemeView innerThemeView = (InnerThemeView) view12; + showOptionsForTheme(innerThemeView.themeInfo); + return true; + }); + } + + public void setDrawDivider(boolean draw) { + drawDivider = draw; + } + + public void notifyDataSetChanged(int width) { + adapter.notifyDataSetChanged(); + Theme.ThemeInfo t = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + if (prevThemeInfo != t) { + scrollToCurrentTheme(width, false); + } + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (getParent() != null && getParent().getParent() != null) { + getParent().getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(e); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (drawDivider) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + } + + public static Bitmap getScaledBitmap(float w, float h, String path, String streamPath, int streamOffset) { + FileInputStream stream = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + + if (path != null) { + BitmapFactory.decodeFile(path, options); + } else { + stream = new FileInputStream(streamPath); + stream.getChannel().position(streamOffset); + BitmapFactory.decodeStream(stream, null, options); + } + if (options.outWidth > 0 && options.outHeight > 0) { + if (w > h && options.outWidth < options.outHeight) { + float temp = w; + w = h; + h = temp; + } + float scale = Math.min(options.outWidth / w, options.outHeight / h); + options.inSampleSize = 1; + if (scale > 1.0f) { + do { + options.inSampleSize *= 2; + } while (options.inSampleSize < scale); + } + options.inJustDecodeBounds = false; + Bitmap wallpaper; + if (path != null) { + wallpaper = BitmapFactory.decodeFile(path, options); + } else { + stream.getChannel().position(streamOffset); + wallpaper = BitmapFactory.decodeStream(stream, null, options); + } + return wallpaper; + } + } catch (Throwable e) { + FileLog.e(e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (Exception e2) { + FileLog.e(e2); + } + } + return null; + } + + @Override + public void setBackgroundColor(int color) { + super.setBackgroundColor(color); + invalidateViews(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(a).addObserver(this, NotificationCenter.fileDidFailToLoad); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(a).removeObserver(this, NotificationCenter.fileDidFailToLoad); + } + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.fileDidLoad) { + String fileName = (String) args[0]; + File file = (File) args[1]; + Theme.ThemeInfo info = loadingThemes.get(fileName); + if (info != null) { + loadingThemes.remove(fileName); + if (loadingWallpapers.remove(info) != null) { + Utilities.globalQueue.postRunnable(() -> { + try { + Bitmap bitmap = getScaledBitmap(AndroidUtilities.dp(640), AndroidUtilities.dp(360), file.getAbsolutePath(), null, 0); + if (info.isBlured) { + bitmap = Utilities.blurWallpaper(bitmap); + } + FileOutputStream stream = new FileOutputStream(info.pathToWallpaper); + bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); + stream.close(); + } catch (Throwable e) { + FileLog.e(e); + info.badWallpaper = true; + } + AndroidUtilities.runOnUIThread(() -> checkVisibleTheme(info)); + }); + } else { + checkVisibleTheme(info); + } + } + } else if (id == NotificationCenter.fileDidFailToLoad) { + String fileName = (String) args[0]; + loadingThemes.remove(fileName); + } + } + + private void checkVisibleTheme(Theme.ThemeInfo info) { + int count = getChildCount(); + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (child instanceof InnerThemeView) { + InnerThemeView view = (InnerThemeView) child; + if (view.themeInfo == info) { + if (view.parseTheme()) { + view.themeInfo.themeLoaded = true; + view.applyTheme(); + } + } + } + } + } + + public void scrollToCurrentTheme(int width, boolean animated) { + if (width == 0) { + View parent = (View) getParent(); + if (parent != null) { + width = parent.getMeasuredWidth(); + } + } + if (width == 0) { + return; + } + prevThemeInfo = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + int index = defaultThemes.indexOf(prevThemeInfo); + if (index < 0) { + index = darkThemes.indexOf(prevThemeInfo) + defaultThemes.size(); + if (index < 0) { + return; + } + } + if (animated) { + smoothScrollToPosition(index); + } else { + horizontalLayoutManager.scrollToPositionWithOffset(index, (width - AndroidUtilities.dp(76)) / 2); + } + } + + protected void showOptionsForTheme(Theme.ThemeInfo themeInfo) { + + } + + protected void presentFragment(BaseFragment fragment) { + + } + + protected void updateRows() { + + } +} 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 018cedf753f..b286724ff8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -395,9 +395,9 @@ public void update(int mask) { } else if (currentChat != null) { avatarDrawable.setInfo(currentChat); } else if (currentName != null) { - avatarDrawable.setInfo(currentId, currentName.toString(), null, false); + avatarDrawable.setInfo(currentId, currentName.toString(), null); } else { - avatarDrawable.setInfo(currentId, "#", null, false); + avatarDrawable.setInfo(currentId, "#", null); } if (currentName != null) { @@ -406,8 +406,10 @@ public void update(int mask) { } else { if (currentUser != null) { lastName = newName == null ? UserObject.getUserName(currentUser) : newName; - } else { + } else if (currentChat != null) { lastName = newName == null ? currentChat.title : newName; + } else { + lastName = ""; } nameTextView.setText(lastName); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java index 0f5c76739b3..86c747fd11e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java @@ -224,9 +224,9 @@ public void update(int mask) { } else if (currentChat != null) { avatarDrawable.setInfo(currentChat); } else if (currentName != null) { - avatarDrawable.setInfo(currentId, currentName.toString(), null, false); + avatarDrawable.setInfo(currentId, currentName.toString(), null); } else { - avatarDrawable.setInfo(currentId, "#", null, false); + avatarDrawable.setInfo(currentId, "#", null); } if (currentName != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index cb414b8ba10..7979b21881e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -14,6 +14,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; @@ -50,6 +51,7 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -751,6 +753,12 @@ public void onNextPressed() { req.settings = new TLRPC.TL_codeSettings(); req.settings.allow_flashcall = simcardAvailable && allowCall; req.settings.allow_app_hash = ApplicationLoader.hasPlayServices; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + if (req.settings.allow_app_hash) { + preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).commit(); + } else { + preferences.edit().remove("sms_hash").commit(); + } if (req.settings.allow_flashcall) { try { @SuppressLint("HardwareIds") String number = tm.getLine1Number(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 9f32de5cb1f..c3352143052 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -1309,9 +1309,9 @@ private void processSelectedOption(int option) { scrollToPositionOnRecreate = -1; } } - Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, selectedObject.getDocumentName(), true); + Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, selectedObject.getDocumentName(), null, true); if (themeInfo != null) { - presentFragment(new ThemePreviewActivity(locFile, themeInfo)); + presentFragment(new ThemePreviewActivity(themeInfo)); } else { scrollToPositionOnRecreate = -1; if (getParentActivity() == null) { @@ -1695,7 +1695,7 @@ private void updateMessagesVisisblePart() { } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } - floatingDateView.setCustomDate(messageObject.messageOwner.date); + floatingDateView.setCustomDate(messageObject.messageOwner.date, false); } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); @@ -1978,16 +1978,6 @@ public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touc } } - @Override - public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { - - } - - @Override - public void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button) { - - } - @Override public void didPressCancelSendButton(ChatMessageCell cell) { @@ -2145,9 +2135,9 @@ public void didPressImage(ChatMessageCell cell, float x, float y) { scrollToPositionOnRecreate = -1; } } - Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), true); + Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), null, true); if (themeInfo != null) { - presentFragment(new ThemePreviewActivity(locFile, themeInfo)); + presentFragment(new ThemePreviewActivity(themeInfo)); return; } else { scrollToPositionOnRecreate = -1; @@ -2436,7 +2426,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(avatarContainer.getSubtitleTextView(), ThemeDescription.FLAG_TEXTCOLOR, null, new Paint[]{Theme.chat_statusPaint, Theme.chat_statusRecordPaint}, null, null, Theme.key_actionBarDefaultSubtitle, null), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundRed), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundOrange), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundViolet), @@ -2468,8 +2458,10 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextOut), new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageLinkIn, null), new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageLinkOut, null), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutClockDrawable}, null, Theme.key_chat_outSentClock), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutSelectedClockDrawable}, null, Theme.key_chat_outSentClockSelected), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInClockDrawable}, null, Theme.key_chat_inSentClock), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java index c345a0d0411..fa18b40d093 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java @@ -434,7 +434,7 @@ public void invalidate(int l, int t, int r, int b) { } }; avatarImage.setRoundRadius(AndroidUtilities.dp(32)); - avatarDrawable.setInfo(5, null, null, false); + avatarDrawable.setInfo(5, null, null); avatarImage.setImageDrawable(avatarDrawable); frameLayout.addView(avatarImage, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12)); @@ -1147,7 +1147,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_LINKCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText), new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"deleteButton"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 96bd6da2720..faf1775a76c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -315,6 +315,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private UndoView undoView; private boolean openKeyboardOnAttachMenuClose; + private boolean inScheduleMode; + private int scheduledMessagesCount = -1; + private ArrayList animatingMessageObjects = new ArrayList<>(); private MessageObject needAnimateToMessage; @@ -397,7 +400,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean scrollToTopUnReadOnResume; private long dialog_id; private int lastLoadIndex; - private boolean isBroadcast; private SparseArray[] selectedMessagesIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray[] selectedMessagesCanCopyIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private SparseArray[] selectedMessagesCanStarIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; @@ -484,6 +486,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet scrimAnimatorSet; private ActionBarPopupWindow scrimPopupWindow; + private ChatActivityDelegate chatActivityDelegate; + + private interface ChatActivityDelegate { + void openReplyMessage(int mid); + } + private class UnreadCounterTextView extends TextView { private int currentCounter; @@ -656,11 +664,11 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { if (index < 0 || index >= botContextResults.size()) { return; } - sendBotInlineResult((TLRPC.BotInlineResult) botContextResults.get(index)); + sendBotInlineResult((TLRPC.BotInlineResult) botContextResults.get(index), notify, scheduleDate); } }; @@ -755,6 +763,7 @@ public boolean onFragmentCreate() { final int chatId = arguments.getInt("chat_id", 0); final int userId = arguments.getInt("user_id", 0); final int encId = arguments.getInt("enc_id", 0); + inScheduleMode = arguments.getBoolean("scheduled", false); inlineReturn = arguments.getLong("inline_return", 0); String inlineQuery = arguments.getString("inline_query"); startLoadFromMessageId = arguments.getInt("message_id", 0); @@ -781,12 +790,7 @@ public boolean onFragmentCreate() { return false; } } - if (chatId > 0) { - dialog_id = -chatId; - } else { - isBroadcast = true; - dialog_id = AndroidUtilities.makeBroadcastId(chatId); - } + dialog_id = -chatId; if (ChatObject.isChannel(currentChat)) { getMessagesController().startShortPoll(currentChat, false); } @@ -864,13 +868,30 @@ public boolean onFragmentCreate() { MediaController.getInstance().startMediaObserver(); } + if (!inScheduleMode) { + getNotificationCenter().addObserver(this, NotificationCenter.messagesRead); + getNotificationCenter().addObserver(this, NotificationCenter.screenshotTook); + getNotificationCenter().addObserver(this, NotificationCenter.encryptedChatUpdated); + getNotificationCenter().addObserver(this, NotificationCenter.messagesReadEncrypted); + getNotificationCenter().addObserver(this, NotificationCenter.removeAllMessagesFromDialog); + getNotificationCenter().addObserver(this, NotificationCenter.messagesReadContent); + getNotificationCenter().addObserver(this, NotificationCenter.botKeyboardDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsAvailable); + getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsLoading); + getNotificationCenter().addObserver(this, NotificationCenter.didUpdatedMessagesViews); + getNotificationCenter().addObserver(this, NotificationCenter.pinnedMessageDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.peerSettingsDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.newDraftReceived); + getNotificationCenter().addObserver(this, NotificationCenter.updateMentionsCount); + getNotificationCenter().addObserver(this, NotificationCenter.didUpdatePollResults); + getNotificationCenter().addObserver(this, NotificationCenter.chatOnlineCountDidLoad); + } getNotificationCenter().addObserver(this, NotificationCenter.messagesDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.didUpdateConnectionState); getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().addObserver(this, NotificationCenter.closeChats); - getNotificationCenter().addObserver(this, NotificationCenter.messagesRead); getNotificationCenter().addObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().addObserver(this, NotificationCenter.historyCleared); getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByServer); @@ -878,14 +899,10 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.messageSendError); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.contactsDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.encryptedChatUpdated); - getNotificationCenter().addObserver(this, NotificationCenter.messagesReadEncrypted); - getNotificationCenter().addObserver(this, NotificationCenter.removeAllMessagesFromDialog); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingProgressDidChanged); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidReset); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingGoingToStop); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingPlayStateChanged); - getNotificationCenter().addObserver(this, NotificationCenter.screenshotTook); getNotificationCenter().addObserver(this, NotificationCenter.blockedUsersDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.fileNewChunkAvailable); getNotificationCenter().addObserver(this, NotificationCenter.didCreatedNewDeleteTask); @@ -896,61 +913,57 @@ public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.replyMessagesDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.didReceivedWebpages); getNotificationCenter().addObserver(this, NotificationCenter.didReceivedWebpagesInUpdates); - getNotificationCenter().addObserver(this, NotificationCenter.messagesReadContent); getNotificationCenter().addObserver(this, NotificationCenter.botInfoDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.botKeyboardDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsAvailable); - getNotificationCenter().addObserver(this, NotificationCenter.chatSearchResultsLoading); - getNotificationCenter().addObserver(this, NotificationCenter.didUpdatedMessagesViews); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoCantLoad); - getNotificationCenter().addObserver(this, NotificationCenter.pinnedMessageDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.peerSettingsDidLoad); - getNotificationCenter().addObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.goingToPreviewTheme); getNotificationCenter().addObserver(this, NotificationCenter.channelRightsUpdated); - getNotificationCenter().addObserver(this, NotificationCenter.updateMentionsCount); getNotificationCenter().addObserver(this, NotificationCenter.audioRecordTooShort); - getNotificationCenter().addObserver(this, NotificationCenter.didUpdatePollResults); - getNotificationCenter().addObserver(this, NotificationCenter.chatOnlineCountDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.didUpdateReactions); getNotificationCenter().addObserver(this, NotificationCenter.videoLoadingStateChanged); + getNotificationCenter().addObserver(this, NotificationCenter.scheduledMessagesUpdated); super.onFragmentCreate(); - if (currentEncryptedChat == null && !isBroadcast) { - getMediaDataController().loadBotKeyboard(dialog_id); - } - loading = true; - getMessagesController().loadPeerSettings(currentUser, currentChat); - getMessagesController().setLastCreatedDialogId(dialog_id, true); + if (!inScheduleMode) { + if (currentEncryptedChat == null) { + getMediaDataController().loadBotKeyboard(dialog_id); + } + getMessagesController().loadPeerSettings(currentUser, currentChat); + getMessagesController().setLastCreatedDialogId(dialog_id, inScheduleMode, true); - if (startLoadFromMessageId == 0) { - SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); - int messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); - if (messageId != 0) { - wasManualScroll = true; - loadingFromOldPosition = true; - startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + dialog_id, 0); - startLoadFromMessageId = messageId; + if (startLoadFromMessageId == 0) { + SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); + int messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); + if (messageId != 0) { + wasManualScroll = true; + loadingFromOldPosition = true; + startLoadFromMessageOffset = sharedPreferences.getInt("diditemo" + dialog_id, 0); + startLoadFromMessageId = messageId; + } + } else { + showScrollToMessageError = true; + needSelectFromMessageId = true; } - } else { - showScrollToMessageError = true; - needSelectFromMessageId = true; } + waitingForLoad.add(lastLoadIndex); if (startLoadFromMessageId != 0) { startLoadFromMessageIdSaved = startLoadFromMessageId; - waitingForLoad.add(lastLoadIndex); if (migrated_to != 0) { mergeDialogId = migrated_to; - getMessagesController().loadMessages(mergeDialogId, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(mergeDialogId, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } else { - getMessagesController().loadMessages(dialog_id, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, loadingFromOldPosition ? 50 : (AndroidUtilities.isTablet() ? 30 : 20), startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } } else { + getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); + } + if (!inScheduleMode) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 1, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), true, lastLoadIndex++); } if (currentChat != null) { @@ -958,11 +971,11 @@ public boolean onFragmentCreate() { if (currentChat.megagroup && !getMessagesController().isChannelAdminsLoaded(currentChat.id)) { getMessagesController().loadChannelAdmins(currentChat.id, true); } - TLRPC.ChatFull info = getMessagesStorage().loadChatInfo(currentChat.id, isBroadcast ? new CountDownLatch(1) : null, true, false); + TLRPC.ChatFull info = getMessagesStorage().loadChatInfo(currentChat.id, null, true, false); if (chatInfo == null) { chatInfo = info; } - if (chatInfo != null && ChatObject.isChannel(currentChat) && chatInfo.migrated_from_chat_id != 0) { + if (!inScheduleMode && chatInfo != null && ChatObject.isChannel(currentChat) && chatInfo.migrated_from_chat_id != 0) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; } @@ -970,28 +983,29 @@ public boolean onFragmentCreate() { getMessagesController().loadUserInfo(currentUser, true, classGuid); } - if (userId != 0 && currentUser.bot) { - getMediaDataController().loadBotInfo(userId, true, classGuid); - } else if (chatInfo instanceof TLRPC.TL_chatFull) { - for (int a = 0; a < chatInfo.participants.participants.size(); a++) { - TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); - TLRPC.User user = getMessagesController().getUser(participant.user_id); - if (user != null && user.bot) { - getMediaDataController().loadBotInfo(user.id, true, classGuid); + if (!inScheduleMode) { + if (userId != 0 && currentUser.bot) { + getMediaDataController().loadBotInfo(userId, true, classGuid); + } else if (chatInfo instanceof TLRPC.TL_chatFull) { + for (int a = 0; a < chatInfo.participants.participants.size(); a++) { + TLRPC.ChatParticipant participant = chatInfo.participants.participants.get(a); + TLRPC.User user = getMessagesController().getUser(participant.user_id); + if (user != null && user.bot) { + getMediaDataController().loadBotInfo(user.id, true, classGuid); + } } } - } - - if (currentUser != null) { - userBlocked = getMessagesController().blockedUsers.indexOfKey(currentUser.id) >= 0; - } + if (AndroidUtilities.isTablet()) { + getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, false); + } - if (AndroidUtilities.isTablet()) { - getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, false); - } + if (currentUser != null) { + userBlocked = getMessagesController().blockedUsers.indexOfKey(currentUser.id) >= 0; + } - if (currentEncryptedChat != null && AndroidUtilities.getMyLayerVersion(currentEncryptedChat.layer) != SecretChatHelper.CURRENT_SECRET_CHAT_LAYER) { - getSecretChatHelper().sendNotifyLayerMessage(currentEncryptedChat, null); + if (currentEncryptedChat != null && AndroidUtilities.getMyLayerVersion(currentEncryptedChat.layer) != SecretChatHelper.CURRENT_SECRET_CHAT_LAYER) { + getSecretChatHelper().sendNotifyLayerMessage(currentEncryptedChat, null); + } } return true; @@ -1012,7 +1026,7 @@ public void onFragmentDestroy() { if (undoView != null) { undoView.hide(true, 0); } - getMessagesController().setLastCreatedDialogId(dialog_id, false); + getMessagesController().setLastCreatedDialogId(dialog_id, inScheduleMode, false); getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateConnectionState); @@ -1057,14 +1071,17 @@ public void onFragmentDestroy() { getNotificationCenter().removeObserver(this, NotificationCenter.newDraftReceived); getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.goingToPreviewTheme); getNotificationCenter().removeObserver(this, NotificationCenter.channelRightsUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.updateMentionsCount); getNotificationCenter().removeObserver(this, NotificationCenter.audioRecordTooShort); getNotificationCenter().removeObserver(this, NotificationCenter.didUpdatePollResults); + getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateReactions); getNotificationCenter().removeObserver(this, NotificationCenter.chatOnlineCountDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.videoLoadingStateChanged); + getNotificationCenter().removeObserver(this, NotificationCenter.scheduledMessagesUpdated); - if (AndroidUtilities.isTablet()) { + if (!inScheduleMode && AndroidUtilities.isTablet()) { getNotificationCenter().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); } if (currentUser != null) { @@ -1112,6 +1129,7 @@ public View createView(Context context) { cantForwardMessagesCount = 0; canForwardMessagesCount = 0; videoPlayerContainer = null; + voiceHintTextView = null; hasOwnBackground = true; if (chatAttachAlert != null) { @@ -1315,9 +1333,9 @@ public void onItemClick(final int id) { } openAttachMenu(); } else if (id == bot_help) { - getSendMessagesHelper().sendMessage("/help", dialog_id, null, null, false, null, null, null); + getSendMessagesHelper().sendMessage("/help", dialog_id, null, null, false, null, null, null, true, 0); } else if (id == bot_settings) { - getSendMessagesHelper().sendMessage("/settings", dialog_id, null, null, false, null, null, null); + getSendMessagesHelper().sendMessage("/settings", dialog_id, null, null, false, null, null, null, true, 0); } else if (id == search) { openSearchWithText(null); } else if(id == call) { @@ -1383,7 +1401,7 @@ public void onItemClick(final int id) { ActionBarMenu menu = actionBar.createMenu(); - if (currentEncryptedChat == null && !isBroadcast) { + if (currentEncryptedChat == null && !inScheduleMode) { searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { boolean searchWas; @@ -1407,19 +1425,31 @@ public void onSearchCollapse() { if (editTextItem.getTag() != null) { if (headerItem != null) { headerItem.setVisibility(View.GONE); + } + if (editTextItem != null) { editTextItem.setVisibility(View.VISIBLE); + } + if (attachItem != null) { attachItem.setVisibility(View.GONE); } } else if (chatActivityEnterView.hasText()) { if (headerItem != null) { headerItem.setVisibility(View.GONE); + } + if (editTextItem != null) { editTextItem.setVisibility(View.GONE); + } + if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } } else { if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); + } + if (editTextItem != null) { editTextItem.setVisibility(View.GONE); + } + if (attachItem != null) { attachItem.setVisibility(View.GONE); } } @@ -1484,85 +1514,88 @@ public boolean forceShowClear() { searchItem.setVisibility(View.GONE); } - headerItem = menu.addItem(0, R.drawable.ic_ab_other); - headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - if (currentUser != null) { - headerItem.addSubItem(call, R.drawable.msg_callback, LocaleController.getString("Call", R.string.Call)); - TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); - if (userFull != null && userFull.phone_calls_available) { - headerItem.showSubItem(call); - } else { - headerItem.hideSubItem(call); + if (!inScheduleMode) { + headerItem = menu.addItem(0, R.drawable.ic_ab_other); + headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + if (currentUser != null) { + headerItem.addSubItem(call, R.drawable.msg_callback, LocaleController.getString("Call", R.string.Call)); + TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); + if (userFull != null && userFull.phone_calls_available) { + headerItem.showSubItem(call); + } else { + headerItem.hideSubItem(call); + } } - } - editTextItem = menu.addItem(0, R.drawable.ic_ab_other); - editTextItem.setTag(null); - editTextItem.setVisibility(View.GONE); - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_bold, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_italic, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); - stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_mono, stringBuilder); - if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); - TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); - run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; - stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_strike, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); - run = new TextStyleSpan.TextStyleRun(); - run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; - stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_underline, stringBuilder); - } - editTextItem.addSubItem(text_link, LocaleController.getString("CreateLink", R.string.CreateLink)); - editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); + editTextItem = menu.addItem(0, R.drawable.ic_ab_other); + editTextItem.setTag(null); + editTextItem.setVisibility(View.GONE); - if (searchItem != null) { - headerItem.addSubItem(search, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search)); - } - if (currentChat != null && !currentChat.creator) { - headerItem.addSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); - } - if (currentUser != null) { - addContactItem = headerItem.addSubItem(share_contact, R.drawable.msg_addcontact, ""); - } - if (currentEncryptedChat != null) { - timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.msg_timer, LocaleController.getString("SetTimer", R.string.SetTimer)); - } - if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup && TextUtils.isEmpty(currentChat.username)) { - headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); - } - if (currentUser == null || !currentUser.self) { - muteItem = headerItem.addSubItem(mute, R.drawable.msg_mute, null); - } - if (ChatObject.isChannel(currentChat) && !currentChat.creator) { - if (!ChatObject.isNotInChat(currentChat)) { - if (currentChat.megagroup) { + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_bold, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_italic, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); + stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_mono, stringBuilder); + if (currentEncryptedChat == null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); + TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_strike, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); + run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_underline, stringBuilder); + } + editTextItem.addSubItem(text_link, LocaleController.getString("CreateLink", R.string.CreateLink)); + editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); + + if (searchItem != null) { + headerItem.addSubItem(search, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search)); + } + if (currentChat != null && !currentChat.creator) { + headerItem.addSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); + } + if (currentUser != null) { + addContactItem = headerItem.addSubItem(share_contact, R.drawable.msg_addcontact, ""); + } + if (currentEncryptedChat != null) { + timeItem2 = headerItem.addSubItem(chat_enc_timer, R.drawable.msg_timer, LocaleController.getString("SetTimer", R.string.SetTimer)); + } + if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup && TextUtils.isEmpty(currentChat.username)) { + headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); + } + if (currentUser == null || !currentUser.self) { + muteItem = headerItem.addSubItem(mute, R.drawable.msg_mute, null); + } + if (ChatObject.isChannel(currentChat) && !currentChat.creator) { + if (!ChatObject.isNotInChat(currentChat)) { + if (currentChat.megagroup) { + headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + } else { + headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); + } + } + } else if (!ChatObject.isChannel(currentChat)) { + if (currentChat != null) { headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); } else { - headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); + headerItem.addSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); } } - } else if (!ChatObject.isChannel(currentChat)) { - if (currentChat != null && !isBroadcast) { - headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); - } else { - headerItem.addSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); + if (currentUser != null && currentUser.self) { + headerItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + } + if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { + headerItem.addSubItem(bot_settings, R.drawable.menu_settings, LocaleController.getString("BotSettings", R.string.BotSettings)); + headerItem.addSubItem(bot_help, R.drawable.menu_help, LocaleController.getString("BotHelp", R.string.BotHelp)); + updateBotButtons(); } - } - if (currentUser != null && currentUser.self) { - headerItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); - } - if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { - headerItem.addSubItem(bot_settings, R.drawable.menu_settings, LocaleController.getString("BotSettings", R.string.BotSettings)); - headerItem.addSubItem(bot_help, R.drawable.menu_help, LocaleController.getString("BotHelp", R.string.BotHelp)); - updateBotButtons(); } updateTitle(); @@ -1570,8 +1603,10 @@ public boolean forceShowClear() { avatarContainer.updateSubtitle(); updateTitleIcons(); - attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false); - attachItem.setVisibility(View.GONE); + if (!inScheduleMode) { + attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false); + attachItem.setVisibility(View.GONE); + } actionModeViews.clear(); @@ -1652,7 +1687,7 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean isRoundVideo = false; boolean isVideo = messageObject != null && messageObject.eventId == 0 && ((isRoundVideo = messageObject.isRoundVideo()) || messageObject.isVideo()); if (child == videoPlayerContainer) { - if (messageObject != null && messageObject.type == 5) { + if (messageObject != null && messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { if (Theme.chat_roundVideoShadow != null && aspectRatioFrameLayout.isDrawingReady()) { int x = (int) child.getX() - AndroidUtilities.dp(3); int y = (int) child.getY() - AndroidUtilities.dp(2); @@ -1992,10 +2027,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (scrollToPositionOnRecreate != -1) { final int scrollTo = scrollToPositionOnRecreate; AndroidUtilities.runOnUIThread(() -> chatLayoutManager.scrollToPositionWithOffset(scrollTo, scrollToOffsetOnRecreate)); - globalIgnoreLayout = true; - scrollToPositionOnRecreate = -1; - globalIgnoreLayout = false; } } @@ -2127,7 +2159,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { emptyViewContainer.setOnTouchListener((v, event) -> true); if (currentEncryptedChat == null) { - if (currentUser != null && currentUser.self || currentChat != null && currentChat.creator) { + if (!inScheduleMode && (currentUser != null && currentUser.self || currentChat != null && currentChat.creator)) { bigEmptyView = new ChatBigEmptyView(context, currentChat != null ? ChatBigEmptyView.EMPTY_VIEW_TYPE_GROUP : ChatBigEmptyView.EMPTY_VIEW_TYPE_SAVED); emptyViewContainer.addView(bigEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); if (currentChat != null) { @@ -2135,7 +2167,9 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } } else { emptyView = new TextView(context); - if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { + if (inScheduleMode) { + emptyView.setText(LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages)); + } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); } else { emptyView.setText(LocaleController.getString("NoMessages", R.string.NoMessages)); @@ -2331,11 +2365,11 @@ private void processTouchEvent(MotionEvent e) { if (view instanceof ChatMessageCell) { slidingView = (ChatMessageCell) view; MessageObject message = slidingView.getMessageObject(); - if (currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || + if (inScheduleMode || + currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || getMessageType(message) == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || - isBroadcast || currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { slidingView = null; return; @@ -3312,497 +3346,507 @@ public void onClick(View view) { return true; }); - if (!isBroadcast) { - mentionContainer = new FrameLayout(context) { + mentionContainer = new FrameLayout(context) { - @Override - public void onDraw(Canvas canvas) { - if (mentionListView.getChildCount() <= 0) { - return; - } - if (mentionLayoutManager.getReverseLayout()) { - int top = mentionListViewScrollOffsetY + AndroidUtilities.dp(2); - int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); - Theme.chat_composeShadowDrawable.setBounds(0, bottom, getMeasuredWidth(), top); - Theme.chat_composeShadowDrawable.draw(canvas); - canvas.drawRect(0, 0, getMeasuredWidth(), top, Theme.chat_composeBackgroundPaint); + @Override + public void onDraw(Canvas canvas) { + if (mentionListView.getChildCount() <= 0) { + return; + } + if (mentionLayoutManager.getReverseLayout()) { + int top = mentionListViewScrollOffsetY + AndroidUtilities.dp(2); + int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + Theme.chat_composeShadowDrawable.setBounds(0, bottom, getMeasuredWidth(), top); + Theme.chat_composeShadowDrawable.draw(canvas); + canvas.drawRect(0, 0, getMeasuredWidth(), top, Theme.chat_composeBackgroundPaint); + } else { + int top; + if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout() && mentionsAdapter.getBotContextSwitch() == null) { + top = mentionListViewScrollOffsetY - AndroidUtilities.dp(4); } else { - int top; - if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout() && mentionsAdapter.getBotContextSwitch() == null) { - top = mentionListViewScrollOffsetY - AndroidUtilities.dp(4); - } else { - top = mentionListViewScrollOffsetY - AndroidUtilities.dp(2); - } - int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); - Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom); - Theme.chat_composeShadowDrawable.draw(canvas); - canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), Theme.chat_composeBackgroundPaint); + top = mentionListViewScrollOffsetY - AndroidUtilities.dp(2); } + int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom); + Theme.chat_composeShadowDrawable.draw(canvas); + canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), Theme.chat_composeBackgroundPaint); } + } - @Override - public void requestLayout() { - if (mentionListViewIgnoreLayout) { - return; - } - super.requestLayout(); + @Override + public void requestLayout() { + if (mentionListViewIgnoreLayout) { + return; } - }; - mentionContainer.setVisibility(View.GONE); - updateMessageListAccessibilityVisibility(); - mentionContainer.setWillNotDraw(false); - contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); + super.requestLayout(); + } + }; + mentionContainer.setVisibility(View.GONE); + updateMessageListAccessibilityVisibility(); + mentionContainer.setWillNotDraw(false); + contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); - mentionListView = new RecyclerListView(context) { + mentionListView = new RecyclerListView(context) { - private int lastWidth; - private int lastHeight; + private int lastWidth; + private int lastHeight; - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (mentionLayoutManager.getReverseLayout()) { - if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { - return false; - } - } else { - if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { - return false; - } + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (mentionLayoutManager.getReverseLayout()) { + if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { + return false; + } + } else { + if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { + return false; } - boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, mentionListView, 0, null); - return super.onInterceptTouchEvent(event) || result; } + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, mentionListView, 0, null); + return super.onInterceptTouchEvent(event) || result; + } - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mentionLayoutManager.getReverseLayout()) { - if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { - return false; - } - } else { - if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { - return false; - } + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mentionLayoutManager.getReverseLayout()) { + if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { + return false; + } + } else { + if (!mentionListViewIsScrolling && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { + return false; } - //supress warning - return super.onTouchEvent(event); } + //supress warning + return super.onTouchEvent(event); + } - @Override - public void requestLayout() { - if (mentionListViewIgnoreLayout) { - return; - } - super.requestLayout(); + @Override + public void requestLayout() { + if (mentionListViewIgnoreLayout) { + return; } + super.requestLayout(); + } - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int width = r - l; - int height = b - t; + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int width = r - l; + int height = b - t; - int newPosition = -1; - int newTop = 0; - if (!mentionLayoutManager.getReverseLayout() && mentionListView != null && mentionListViewLastViewPosition >= 0 && width == lastWidth && height - lastHeight != 0) { - newPosition = mentionListViewLastViewPosition; - newTop = mentionListViewLastViewTop + height - lastHeight - getPaddingTop(); - } + int newPosition = -1; + int newTop = 0; + if (!mentionLayoutManager.getReverseLayout() && mentionListView != null && mentionListViewLastViewPosition >= 0 && width == lastWidth && height - lastHeight != 0) { + newPosition = mentionListViewLastViewPosition; + newTop = mentionListViewLastViewTop + height - lastHeight - getPaddingTop(); + } - super.onLayout(changed, l, t, r, b); + super.onLayout(changed, l, t, r, b); - if (newPosition != -1) { - mentionListViewIgnoreLayout = true; - if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { - mentionGridLayoutManager.scrollToPositionWithOffset(newPosition, newTop); - } else { - mentionLayoutManager.scrollToPositionWithOffset(newPosition, newTop); - } - super.onLayout(false, l, t, r, b); - mentionListViewIgnoreLayout = false; + if (newPosition != -1) { + mentionListViewIgnoreLayout = true; + if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { + mentionGridLayoutManager.scrollToPositionWithOffset(newPosition, newTop); + } else { + mentionLayoutManager.scrollToPositionWithOffset(newPosition, newTop); } - - lastHeight = height; - lastWidth = width; - mentionListViewUpdateLayout(); + super.onLayout(false, l, t, r, b); + mentionListViewIgnoreLayout = false; } - }; - mentionListView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, mentionListView, 0, mentionsOnItemClickListener, null)); - mentionListView.setTag(2); - mentionLayoutManager = new LinearLayoutManager(context) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - }; - mentionLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - mentionGridLayoutManager = new ExtendedGridLayoutManager(context, 100) { - private Size size = new Size(); + lastHeight = height; + lastWidth = width; + mentionListViewUpdateLayout(); + } + }; + mentionListView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, mentionListView, 0, mentionsOnItemClickListener, null)); + mentionListView.setTag(2); + mentionLayoutManager = new LinearLayoutManager(context) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + mentionLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + mentionGridLayoutManager = new ExtendedGridLayoutManager(context, 100) { - @Override - protected Size getSizeForItem(int i) { - if (mentionsAdapter.getBotContextSwitch() != null) { - i++; - } - size.width = 0; - size.height = 0; - Object object = mentionsAdapter.getItem(i); - if (object instanceof TLRPC.BotInlineResult) { - TLRPC.BotInlineResult inlineResult = (TLRPC.BotInlineResult) object; - if (inlineResult.document != null) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(inlineResult.document.thumbs, 90); - size.width = thumb != null ? thumb.w : 100; - size.height = thumb != null ? thumb.h : 100; - for (int b = 0; b < inlineResult.document.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.document.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } - } - } else if (inlineResult.content != null) { - for (int b = 0; b < inlineResult.content.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.content.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } + private Size size = new Size(); + + @Override + protected Size getSizeForItem(int i) { + if (mentionsAdapter.getBotContextSwitch() != null) { + i++; + } + size.width = 0; + size.height = 0; + Object object = mentionsAdapter.getItem(i); + if (object instanceof TLRPC.BotInlineResult) { + TLRPC.BotInlineResult inlineResult = (TLRPC.BotInlineResult) object; + if (inlineResult.document != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(inlineResult.document.thumbs, 90); + size.width = thumb != null ? thumb.w : 100; + size.height = thumb != null ? thumb.h : 100; + for (int b = 0; b < inlineResult.document.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.document.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; } - } else if (inlineResult.thumb != null) { - for (int b = 0; b < inlineResult.thumb.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.thumb.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } + } + } else if (inlineResult.content != null) { + for (int b = 0; b < inlineResult.content.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.content.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; } - } else if (inlineResult.photo != null) { - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.photoSize); - if (photoSize != null) { - size.width = photoSize.w; - size.height = photoSize.h; + } + } else if (inlineResult.thumb != null) { + for (int b = 0; b < inlineResult.thumb.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.thumb.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; } } + } else if (inlineResult.photo != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.photoSize); + if (photoSize != null) { + size.width = photoSize.w; + size.height = photoSize.h; + } } - return size; } + return size; + } - @Override - protected int getFlowItemCount() { + @Override + protected int getFlowItemCount() { + if (mentionsAdapter.getBotContextSwitch() != null) { + return getItemCount() - 1; + } + return super.getFlowItemCount(); + } + }; + mentionGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + Object object = mentionsAdapter.getItem(position); + if (object instanceof TLRPC.TL_inlineBotSwitchPM) { + return 100; + } else { if (mentionsAdapter.getBotContextSwitch() != null) { - return getItemCount() - 1; + position--; } - return super.getFlowItemCount(); + return mentionGridLayoutManager.getSpanSizeForItem(position); } - }; - mentionGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - Object object = mentionsAdapter.getItem(position); - if (object instanceof TLRPC.TL_inlineBotSwitchPM) { - return 100; - } else { - if (mentionsAdapter.getBotContextSwitch() != null) { - position--; + } + }); + mentionListView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.left = 0; + outRect.right = 0; + outRect.top = 0; + outRect.bottom = 0; + if (parent.getLayoutManager() == mentionGridLayoutManager) { + int position = parent.getChildAdapterPosition(view); + if (mentionsAdapter.getBotContextSwitch() != null) { + if (position == 0) { + return; } - return mentionGridLayoutManager.getSpanSizeForItem(position); - } - } - }); - mentionListView.addItemDecoration(new RecyclerView.ItemDecoration() { - @Override - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - outRect.left = 0; - outRect.right = 0; - outRect.top = 0; - outRect.bottom = 0; - if (parent.getLayoutManager() == mentionGridLayoutManager) { - int position = parent.getChildAdapterPosition(view); - if (mentionsAdapter.getBotContextSwitch() != null) { - if (position == 0) { - return; - } - position--; - if (!mentionGridLayoutManager.isFirstRow(position)) { - outRect.top = AndroidUtilities.dp(2); - } - } else { + position--; + if (!mentionGridLayoutManager.isFirstRow(position)) { outRect.top = AndroidUtilities.dp(2); } - outRect.right = mentionGridLayoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2); - } - } - }); - mentionListView.setItemAnimator(null); - mentionListView.setLayoutAnimation(null); - mentionListView.setClipToPadding(false); - mentionListView.setLayoutManager(mentionLayoutManager); - mentionListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); - mentionContainer.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(context, false, dialog_id, new MentionsAdapter.MentionsAdapterDelegate() { - @Override - public void needChangePanelVisibility(boolean show) { - if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { - mentionListView.setLayoutManager(mentionGridLayoutManager); } else { - mentionListView.setLayoutManager(mentionLayoutManager); + outRect.top = AndroidUtilities.dp(2); } - if (show && bottomOverlay.getVisibility() == View.VISIBLE) { - show = false; + outRect.right = mentionGridLayoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2); + } + } + }); + mentionListView.setItemAnimator(null); + mentionListView.setLayoutAnimation(null); + mentionListView.setClipToPadding(false); + mentionListView.setLayoutManager(mentionLayoutManager); + mentionListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + mentionContainer.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(context, false, dialog_id, new MentionsAdapter.MentionsAdapterDelegate() { + @Override + public void needChangePanelVisibility(boolean show) { + if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { + mentionListView.setLayoutManager(mentionGridLayoutManager); + } else { + mentionListView.setLayoutManager(mentionLayoutManager); + } + if (show && bottomOverlay.getVisibility() == View.VISIBLE) { + show = false; + } + if (show) { + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; } - if (show) { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - mentionListAnimation = null; - } - if (mentionContainer.getVisibility() == View.VISIBLE) { - mentionContainer.setAlpha(1.0f); - return; + if (mentionContainer.getVisibility() == View.VISIBLE) { + mentionContainer.setAlpha(1.0f); + return; + } + if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { + mentionGridLayoutManager.scrollToPositionWithOffset(0, 10000); + } else if (!mentionLayoutManager.getReverseLayout()) { + mentionLayoutManager.scrollToPositionWithOffset(0, mentionLayoutManager.getReverseLayout() ? -10000 : 10000); + } + if (allowStickersPanel && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { + if (currentEncryptedChat != null && mentionsAdapter.isBotContext()) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + if (!preferences.getBoolean("secretbot", false)) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); + preferences.edit().putBoolean("secretbot", true).commit(); + } } - if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { - mentionGridLayoutManager.scrollToPositionWithOffset(0, 10000); - } else if (!mentionLayoutManager.getReverseLayout()) { - mentionLayoutManager.scrollToPositionWithOffset(0, mentionLayoutManager.getReverseLayout() ? -10000 : 10000); - } - if (allowStickersPanel && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { - if (currentEncryptedChat != null && mentionsAdapter.isBotContext()) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - if (!preferences.getBoolean("secretbot", false)) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - preferences.edit().putBoolean("secretbot", true).commit(); + mentionContainer.setVisibility(View.VISIBLE); + updateMessageListAccessibilityVisibility(); + mentionContainer.setTag(null); + mentionListAnimation = new AnimatorSet(); + mentionListAnimation.playTogether( + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListAnimation = null; } } - mentionContainer.setVisibility(View.VISIBLE); - updateMessageListAccessibilityVisibility(); - mentionContainer.setTag(null); - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } + @Override + public void onAnimationCancel(Animator animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListAnimation = null; } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.start(); - } else { - mentionContainer.setAlpha(1.0f); - mentionContainer.setVisibility(View.INVISIBLE); - updateMessageListAccessibilityVisibility(); - } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); } else { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - mentionListAnimation = null; - } + mentionContainer.setAlpha(1.0f); + mentionContainer.setVisibility(View.INVISIBLE); + updateMessageListAccessibilityVisibility(); + } + } else { + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; + } - if (mentionContainer.getVisibility() == View.GONE) { - return; - } - if (allowStickersPanel) { - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionContainer.setVisibility(View.GONE); - mentionContainer.setTag(null); - updateMessageListAccessibilityVisibility(); - mentionListAnimation = null; - } + if (mentionContainer.getVisibility() == View.GONE) { + return; + } + if (allowStickersPanel) { + mentionListAnimation = new AnimatorSet(); + mentionListAnimation.playTogether( + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionContainer.setVisibility(View.GONE); + mentionContainer.setTag(null); + updateMessageListAccessibilityVisibility(); + mentionListAnimation = null; } + } - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } + @Override + public void onAnimationCancel(Animator animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListAnimation = null; } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.start(); - } else { - mentionContainer.setTag(null); - mentionContainer.setVisibility(View.GONE); - updateMessageListAccessibilityVisibility(); - } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } else { + mentionContainer.setTag(null); + mentionContainer.setVisibility(View.GONE); + updateMessageListAccessibilityVisibility(); } } + } - @Override - public void onContextSearch(boolean searching) { - if (chatActivityEnterView != null) { - chatActivityEnterView.setCaption(mentionsAdapter.getBotCaption()); - chatActivityEnterView.showContextProgress(searching); - } + @Override + public void onContextSearch(boolean searching) { + if (chatActivityEnterView != null) { + chatActivityEnterView.setCaption(mentionsAdapter.getBotCaption()); + chatActivityEnterView.showContextProgress(searching); } + } - @Override - public void onContextClick(TLRPC.BotInlineResult result) { - if (getParentActivity() == null || result.content == null) { + @Override + public void onContextClick(TLRPC.BotInlineResult result) { + if (getParentActivity() == null || result.content == null) { + return; + } + if (result.type.equals("video") || result.type.equals("web_player_video")) { + int[] size = MessageObject.getInlineResultWidthAndHeight(result); + EmbedBottomSheet.show(getParentActivity(), result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1]); + } else { + Browser.openUrl(getParentActivity(), result.content.url); + } + } + })); + if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { + mentionsAdapter.setBotInfo(botInfo); + } + mentionsAdapter.setParentFragment(this); + mentionsAdapter.setChatInfo(chatInfo); + mentionsAdapter.setNeedUsernames(currentChat != null); + mentionsAdapter.setNeedBotContext(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); + mentionsAdapter.setBotsCount(currentChat != null ? botsCount : 1); + mentionListView.setOnItemClickListener(mentionsOnItemClickListener = (view, position) -> { + if (mentionsAdapter.isBannedInline()) { + return; + } + Object object = mentionsAdapter.getItem(position); + int start = mentionsAdapter.getResultStartPosition(); + int len = mentionsAdapter.getResultLength(); + if (object instanceof TLRPC.User) { + if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { + searchingUserMessages = (TLRPC.User) object; + if (searchingUserMessages == null) { return; } - if (result.type.equals("video") || result.type.equals("web_player_video")) { - int[] size = MessageObject.getInlineResultWidthAndHeight(result); - EmbedBottomSheet.show(getParentActivity(), result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1]); - } else { - Browser.openUrl(getParentActivity(), result.content.url); + String name = searchingUserMessages.first_name; + if (TextUtils.isEmpty(name)) { + name = searchingUserMessages.last_name; + } + searchingForUser = false; + String from = LocaleController.getString("SearchFrom", R.string.SearchFrom); + Spannable spannable = new SpannableString(from + " " + name); + spannable.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_actionBarDefaultSubtitle)), from.length() + 1, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + searchItem.setSearchFieldCaption(spannable); + mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false); + searchItem.setSearchFieldHint(null); + searchItem.clearSearchText(); + getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, searchingUserMessages); + } else { + TLRPC.User user = (TLRPC.User) object; + if (user != null) { + if (user.username != null) { + chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); + } else { + String name = UserObject.getFirstName(user, false); + Spannable spannable = new SpannableString(name + " "); + spannable.setSpan(new URLSpanUserMention("" + user.id, 1), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + chatActivityEnterView.replaceWithText(start, len, spannable, false); + } } } - })); - if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { - mentionsAdapter.setBotInfo(botInfo); - } - mentionsAdapter.setParentFragment(this); - mentionsAdapter.setChatInfo(chatInfo); - mentionsAdapter.setNeedUsernames(currentChat != null); - mentionsAdapter.setNeedBotContext(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); - mentionsAdapter.setBotsCount(currentChat != null ? botsCount : 1); - mentionListView.setOnItemClickListener(mentionsOnItemClickListener = (view, position) -> { - if (mentionsAdapter.isBannedInline()) { - return; - } - Object object = mentionsAdapter.getItem(position); - int start = mentionsAdapter.getResultStartPosition(); - int len = mentionsAdapter.getResultLength(); - if (object instanceof TLRPC.User) { - if (searchingForUser && searchContainer.getVisibility() == View.VISIBLE) { - searchingUserMessages = (TLRPC.User) object; - if (searchingUserMessages == null) { - return; - } - String name = searchingUserMessages.first_name; - if (TextUtils.isEmpty(name)) { - name = searchingUserMessages.last_name; - } - searchingForUser = false; - String from = LocaleController.getString("SearchFrom", R.string.SearchFrom); - Spannable spannable = new SpannableString(from + " " + name); - spannable.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_actionBarDefaultSubtitle)), from.length() + 1, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - searchItem.setSearchFieldCaption(spannable); - mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false); - searchItem.setSearchFieldHint(null); - searchItem.clearSearchText(); - getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, searchingUserMessages); + } else if (object instanceof String) { + if (mentionsAdapter.isBotCommands()) { + if (inScheduleMode) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(currentUser), (notify, scheduleDate) -> { + getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, null, false, null, null, null, notify, scheduleDate); + chatActivityEnterView.setFieldText(""); + hideFieldPanel(false); + }); } else { - TLRPC.User user = (TLRPC.User) object; - if (user != null) { - if (user.username != null) { - chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " ", false); - } else { - String name = UserObject.getFirstName(user, false); - Spannable spannable = new SpannableString(name + " "); - spannable.setSpan(new URLSpanUserMention("" + user.id, 1), 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - chatActivityEnterView.replaceWithText(start, len, spannable, false); - } - } - } - } else if (object instanceof String) { - if (mentionsAdapter.isBotCommands()) { if (checkSlowMode(view)) { return; } - getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, null, false, null, null, null); + getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, null, false, null, null, null, true, 0); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); - } else { - chatActivityEnterView.replaceWithText(start, len, object + " ", false); } - } else if (object instanceof TLRPC.BotInlineResult) { - if (chatActivityEnterView.getFieldText() == null || checkSlowMode(view)) { - return; - } - TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) object; - if ((result.type.equals("photo") && (result.photo != null || result.content != null) || - result.type.equals("gif") && (result.document != null || result.content != null) || - result.type.equals("video") && (result.document != null/* || result.content_url != null*/))) { - ArrayList arrayList = botContextResults = new ArrayList<>(mentionsAdapter.getSearchResultBotContext()); - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionsAdapter.getItemPosition(position), 3, botContextProvider, null); + } else { + chatActivityEnterView.replaceWithText(start, len, object + " ", false); + } + } else if (object instanceof TLRPC.BotInlineResult) { + if (chatActivityEnterView.getFieldText() == null || !inScheduleMode && checkSlowMode(view)) { + return; + } + TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) object; + if ((result.type.equals("photo") && (result.photo != null || result.content != null) || + result.type.equals("gif") && (result.document != null || result.content != null) || + result.type.equals("video") && (result.document != null/* || result.content_url != null*/))) { + ArrayList arrayList = botContextResults = new ArrayList<>(mentionsAdapter.getSearchResultBotContext()); + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionsAdapter.getItemPosition(position), 3, botContextProvider, ChatActivity.this); + } else { + if (inScheduleMode) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(currentUser), (notify, scheduleDate) -> sendBotInlineResult(result, notify, scheduleDate)); } else { - sendBotInlineResult(result); + sendBotInlineResult(result, true, 0); } - } else if (object instanceof TLRPC.TL_inlineBotSwitchPM) { - processInlineBotContextPM((TLRPC.TL_inlineBotSwitchPM) object); - } else if (object instanceof MediaDataController.KeywordResult) { - String code = ((MediaDataController.KeywordResult) object).emoji; - chatActivityEnterView.addEmojiToRecent(code); - chatActivityEnterView.replaceWithText(start, len, code, true); } - }); + } else if (object instanceof TLRPC.TL_inlineBotSwitchPM) { + processInlineBotContextPM((TLRPC.TL_inlineBotSwitchPM) object); + } else if (object instanceof MediaDataController.KeywordResult) { + String code = ((MediaDataController.KeywordResult) object).emoji; + chatActivityEnterView.addEmojiToRecent(code); + chatActivityEnterView.replaceWithText(start, len, code, true); + } + }); - mentionListView.setOnItemLongClickListener((view, position) -> { - if (getParentActivity() == null || !mentionsAdapter.isLongClickEnabled()) { - return false; - } - Object object = mentionsAdapter.getItem(position); - if (object instanceof String) { - if (mentionsAdapter.isBotCommands()) { - if (URLSpanBotCommand.enabled) { - chatActivityEnterView.setFieldText(""); - chatActivityEnterView.setCommand(null, (String) object, true, currentChat != null && currentChat.megagroup); - return true; - } - return false; - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); - builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionsAdapter.clearRecentHashtags()); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); + mentionListView.setOnItemLongClickListener((view, position) -> { + if (getParentActivity() == null || !mentionsAdapter.isLongClickEnabled()) { + return false; + } + Object object = mentionsAdapter.getItem(position); + if (object instanceof String) { + if (mentionsAdapter.isBotCommands()) { + if (URLSpanBotCommand.enabled) { + chatActivityEnterView.setFieldText(""); + chatActivityEnterView.setCommand(null, (String) object, true, currentChat != null && currentChat.megagroup); return true; } + return false; + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionsAdapter.clearRecentHashtags()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + return true; } - return false; - }); + } + return false; + }); + + mentionListView.setOnScrollListener(new RecyclerView.OnScrollListener() { - mentionListView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + mentionListViewIsScrolling = newState == RecyclerView.SCROLL_STATE_DRAGGING; + } - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - mentionListViewIsScrolling = newState == RecyclerView.SCROLL_STATE_DRAGGING; + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int lastVisibleItem; + if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { + lastVisibleItem = mentionGridLayoutManager.findLastVisibleItemPosition(); + } else { + lastVisibleItem = mentionLayoutManager.findLastVisibleItemPosition(); } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - int lastVisibleItem; - if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { - lastVisibleItem = mentionGridLayoutManager.findLastVisibleItemPosition(); - } else { - lastVisibleItem = mentionLayoutManager.findLastVisibleItemPosition(); - } - int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; - if (visibleItemCount > 0 && lastVisibleItem > mentionsAdapter.getItemCount() - 5) { - mentionsAdapter.searchForContextBotForNextOffset(); - } - mentionListViewUpdateLayout(); + int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; + if (visibleItemCount > 0 && lastVisibleItem > mentionsAdapter.getItemCount() - 5) { + mentionsAdapter.searchForContextBotForNextOffset(); } - }); - } + mentionListViewUpdateLayout(); + } + }); pagedownButtonImage = new ImageView(context); pagedownButtonImage.setImageResource(R.drawable.pagedown); @@ -3922,26 +3966,28 @@ public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } }; - chatActivityEnterView.setDialogId(dialog_id, currentAccount); - if (chatInfo != null) { - chatActivityEnterView.setChatInfo(chatInfo); - } - chatActivityEnterView.setId(id_chat_compose_panel); - chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands); - chatActivityEnterView.setMinimumHeight(AndroidUtilities.dp(51)); - chatActivityEnterView.setAllowStickersAndGifs(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 23, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); - if (inPreviewMode) { - chatActivityEnterView.setVisibility(View.INVISIBLE); - } - contentView.addView(chatActivityEnterView, contentView.getChildCount() - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override - public void onMessageSend(CharSequence message) { - moveScrollToLastMessage(); - hideFieldPanel(false); + public void onMessageSend(CharSequence message, boolean notify, int scheduleDate) { + if (!inScheduleMode) { + moveScrollToLastMessage(); + } if (mentionsAdapter != null) { mentionsAdapter.addHashtagsFromMessage(message); } + if (scheduleDate != 0) { + if (scheduledMessagesCount == -1) { + scheduledMessagesCount = 0; + } + if (message != null) { + scheduledMessagesCount++; + } + if (forwardingMessages != null && !forwardingMessages.isEmpty()) { + scheduledMessagesCount += forwardingMessages.size(); + } + updateScheduledInterface(false); + } + hideFieldPanel(notify, scheduleDate, false); } @Override @@ -4036,7 +4082,11 @@ public void onAttachButtonHidden() { } if (headerItem != null) { headerItem.setVisibility(View.GONE); + } + if (editTextItem != null) { editTextItem.setVisibility(View.GONE); + } + if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } } @@ -4048,7 +4098,11 @@ public void onAttachButtonShow() { } if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); + } + if (editTextItem != null) { editTextItem.setVisibility(View.GONE); + } + if (attachItem != null) { attachItem.setVisibility(View.GONE); } } @@ -4116,12 +4170,12 @@ public void didPressedAttachButton() { } @Override - public void needStartRecordVideo(int state) { + public void needStartRecordVideo(int state, boolean notify, int scheduleDate) { if (instantCameraView != null) { if (state == 0) { instantCameraView.showCamera(); } else if (state == 1 || state == 3 || state == 4) { - instantCameraView.send(state); + instantCameraView.send(state, notify, scheduleDate); } else if (state == 2) { instantCameraView.cancel(); } @@ -4160,7 +4214,29 @@ public void scrollToSendingMessage() { scrollToMessageId(id, 0, true, 0, false); } } + + @Override + public boolean hasScheduledMessages() { + return scheduledMessagesCount > 0 && !inScheduleMode; + } + + @Override + public void openScheduledMessages() { + ChatActivity.this.openScheduledMessages(); + } }); + chatActivityEnterView.setDialogId(dialog_id, currentAccount); + if (chatInfo != null) { + chatActivityEnterView.setChatInfo(chatInfo); + } + chatActivityEnterView.setId(id_chat_compose_panel); + chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands); + chatActivityEnterView.setMinimumHeight(AndroidUtilities.dp(51)); + chatActivityEnterView.setAllowStickersAndGifs(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 23, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); + if (inPreviewMode) { + chatActivityEnterView.setVisibility(View.INVISIBLE); + } + contentView.addView(chatActivityEnterView, contentView.getChildCount() - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); FrameLayout replyLayout = new FrameLayout(context) { @Override @@ -4262,7 +4338,7 @@ public void setVisibility(int visibility) { if (forwardingMessages != null) { forwardingMessages.clear(); } - showFieldPanel(false, null, null, null, foundWebPage, true, true); + showFieldPanel(false, null, null, null, foundWebPage, true, 0, true, true); }); replyNameTextView = new SimpleTextView(context); @@ -4285,8 +4361,8 @@ public void setVisibility(int visibility) { final ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override - public void sendSticker(TLRPC.Document sticker, Object parent) { - + public void sendSticker(TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate) { + chatActivityEnterView.onStickerSelected(sticker, parent, true, notify, scheduleDate); } @Override @@ -4294,6 +4370,16 @@ public boolean needSend() { return false; } + @Override + public boolean canSchedule() { + return ChatActivity.this.canScheduleMessage(); + } + + @Override + public boolean isInScheduleMode() { + return inScheduleMode; + } + @Override public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null || getParentActivity() == null) { @@ -4410,7 +4496,7 @@ public void onDraw(Canvas canvas) { int date = (int) (calendar1.getTime().getTime() / 1000); clearChatData(); waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); }, year, monthOfYear, dayOfMonth); final DatePicker datePicker = dialog.getDatePicker(); datePicker.setMinDate(1375315200000L); @@ -4518,7 +4604,7 @@ public void onDraw(Canvas canvas) { if (botUserLast != null && botUserLast.length() != 0) { getMessagesController().sendBotStart(currentUser, botUserLast); } else { - getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, false, null, null, null); + getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, false, null, null, null, true, 0); } } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -4532,7 +4618,7 @@ public void onDraw(Canvas canvas) { if (botUser.length() != 0) { getMessagesController().sendBotStart(currentUser, botUser); } else { - getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, false, null, null, null); + getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, false, null, null, null, true, 0); } botUser = null; updateBottomOverlay(); @@ -4590,38 +4676,36 @@ public void onDraw(Canvas canvas) { bottomOverlayProgress.setAlpha(1.0f); bottomOverlayChat.addView(bottomOverlayProgress, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); - if (!isBroadcast) { - replyButton = new TextView(context); - replyButton.setText(LocaleController.getString("Reply", R.string.Reply)); - replyButton.setGravity(Gravity.CENTER_VERTICAL); - replyButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - replyButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(21), 0); - replyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 3)); - replyButton.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); - replyButton.setCompoundDrawablePadding(AndroidUtilities.dp(7)); - replyButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - Drawable image = context.getResources().getDrawable(R.drawable.input_reply).mutate(); - image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); - replyButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); - replyButton.setOnClickListener(v -> { - MessageObject messageObject = null; - for (int a = 1; a >= 0; a--) { - if (messageObject == null && selectedMessagesIds[a].size() != 0) { - messageObject = messagesDict[a].get(selectedMessagesIds[a].keyAt(0)); - } - selectedMessagesIds[a].clear(); - selectedMessagesCanCopyIds[a].clear(); - selectedMessagesCanStarIds[a].clear(); - } - hideActionMode(); - if (messageObject != null && (messageObject.messageOwner.id > 0 || messageObject.messageOwner.id < 0 && currentEncryptedChat != null)) { - showFieldPanelForReply(messageObject); + replyButton = new TextView(context); + replyButton.setText(LocaleController.getString("Reply", R.string.Reply)); + replyButton.setGravity(Gravity.CENTER_VERTICAL); + replyButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + replyButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(21), 0); + replyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 3)); + replyButton.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + replyButton.setCompoundDrawablePadding(AndroidUtilities.dp(7)); + replyButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + Drawable image = context.getResources().getDrawable(R.drawable.input_reply).mutate(); + image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + replyButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); + replyButton.setOnClickListener(v -> { + MessageObject messageObject = null; + for (int a = 1; a >= 0; a--) { + if (messageObject == null && selectedMessagesIds[a].size() != 0) { + messageObject = messagesDict[a].get(selectedMessagesIds[a].keyAt(0)); } - updatePinnedMessageView(true); - updateVisibleRows(); - }); - bottomMessagesActionContainer.addView(replyButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); - } + selectedMessagesIds[a].clear(); + selectedMessagesCanCopyIds[a].clear(); + selectedMessagesCanStarIds[a].clear(); + } + hideActionMode(); + if (messageObject != null && (messageObject.messageOwner.id > 0 || messageObject.messageOwner.id < 0 && currentEncryptedChat != null)) { + showFieldPanelForReply(messageObject); + } + updatePinnedMessageView(true); + updateVisibleRows(); + }); + bottomMessagesActionContainer.addView(replyButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); forwardButton = new TextView(context); forwardButton.setText(LocaleController.getString("Forward", R.string.Forward)); @@ -4632,7 +4716,7 @@ public void onDraw(Canvas canvas) { forwardButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 3)); forwardButton.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); forwardButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - Drawable image = context.getResources().getDrawable(R.drawable.input_forward).mutate(); + image = context.getResources().getDrawable(R.drawable.input_forward).mutate(); image.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); forwardButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); forwardButton.setOnClickListener(v -> openForward()); @@ -4870,14 +4954,14 @@ public void onAnimationCancel(Animator animation) { } } - private void sendBotInlineResult(TLRPC.BotInlineResult result) { + private void sendBotInlineResult(TLRPC.BotInlineResult result, boolean notify, int scheduleDate) { int uid = mentionsAdapter.getContextBotId(); HashMap params = new HashMap<>(); params.put("id", result.id); params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); params.put("bot_name", mentionsAdapter.getContextBotName()); - SendMessagesHelper.prepareSendingBotContextResult(getAccountInstance(), result, params, dialog_id, replyingMessageObject); + SendMessagesHelper.prepareSendingBotContextResult(getAccountInstance(), result, params, dialog_id, replyingMessageObject, notify, scheduleDate); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); getMediaDataController().increaseInlineRaiting(uid); @@ -4974,7 +5058,7 @@ private void jumpToDate(int date) { } else if ((int) dialog_id != 0) { clearChatData(); waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 30, 0, date, true, 0, classGuid, 4, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); floatingDateView.setAlpha(0.0f); floatingDateView.setTag(null); } @@ -5027,7 +5111,7 @@ public void dismissInternal() { }; chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { @Override - public void didPressedButton(int button, boolean arg) { + public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate) { if (getParentActivity() == null || chatAttachAlert == null) { return; } @@ -5064,10 +5148,15 @@ public void didPressedButton(int button, boolean arg) { photoEntry.reset(); } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, null, button == 4, arg, editingMessageObject); - - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, null, button == 4, arg, editingMessageObject, notify, scheduleDate); + afterMessageSend(); + } + if (scheduleDate != 0) { + if (scheduledMessagesCount == -1) { + scheduledMessagesCount = 0; + } + scheduledMessagesCount += selectedPhotos.size(); + updateScheduledInterface(true); } return; } else if (chatAttachAlert != null) { @@ -5125,6 +5214,13 @@ public void setBotUser(String value) { } } + private void afterMessageSend() { + hideFieldPanel(false); + if (!inScheduleMode) { + getMediaDataController().cleanDraft(dialog_id, true); + } + } + public boolean playFirstUnreadVoiceMessage() { if (chatActivityEnterView != null && chatActivityEnterView.isRecordingAudioVideo()) { return true; @@ -5145,6 +5241,24 @@ public boolean playFirstUnreadVoiceMessage() { return false; } + private void openScheduledMessages() { + if (parentLayout == null || parentLayout.getLastFragment() != this) { + return; + } + Bundle bundle = new Bundle(); + if (currentEncryptedChat != null) { + bundle.putInt("enc_id", currentEncryptedChat.id); + } else if (currentChat != null) { + bundle.putInt("chat_id", currentChat.id); + } else { + bundle.putInt("user_id", currentUser.id); + } + bundle.putBoolean("scheduled", true); + ChatActivity fragment = new ChatActivity(bundle); + fragment.chatActivityDelegate = mid -> scrollToMessageId(mid, 0, true, 0, false); + presentFragment(fragment, false); + } + private void initStickers() { if (chatActivityEnterView == null || getParentActivity() == null || stickersAdapter != null || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 23) { return; @@ -5214,11 +5328,15 @@ public void onAnimationCancel(Animator animation) { Object item = stickersAdapter.getItem(position); Object parent = stickersAdapter.getItemParent(position); if (item instanceof TLRPC.TL_document) { - if (checkSlowMode(view)) { + if (!inScheduleMode && checkSlowMode(view)) { return; } TLRPC.TL_document document = (TLRPC.TL_document) item; - getSendMessagesHelper().sendSticker(document, dialog_id, replyingMessageObject, parent); + if (inScheduleMode) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(currentUser), (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, parent, notify, scheduleDate)); + } else { + getSendMessagesHelper().sendSticker(document, dialog_id, replyingMessageObject, parent, true, 0); + } hideFieldPanel(false); chatActivityEnterView.addStickerToRecent(document); chatActivityEnterView.setFieldText(""); @@ -5255,8 +5373,10 @@ public void shareMyContact(int type, MessageObject messageObject) { getMessagesController().processUpdates((TLRPC.Updates) response, false); }); } else { - SendMessagesHelper.getInstance(currentAccount).sendMessage(getUserConfig().getCurrentUser(), dialog_id, messageObject, null, null); - moveScrollToLastMessage(); + SendMessagesHelper.getInstance(currentAccount).sendMessage(getUserConfig().getCurrentUser(), dialog_id, messageObject, null, null, true, 0); + if (!inScheduleMode) { + moveScrollToLastMessage(); + } hideFieldPanel(false); } }); @@ -5265,6 +5385,9 @@ public void shareMyContact(int type, MessageObject messageObject) { } private void hideVoiceHint() { + if (voiceHintTextView == null) { + return; + } voiceHintAnimation = new AnimatorSet(); voiceHintAnimation.playTogether( ObjectAnimator.ofFloat(voiceHintTextView, View.ALPHA, 0.0f) @@ -5294,7 +5417,7 @@ public void onAnimationCancel(Animator animation) { } private void showVoiceHint(boolean hide, boolean video) { - if (getParentActivity() == null || fragmentView == null || hide && voiceHintTextView == null) { + if (getParentActivity() == null || fragmentView == null || hide && voiceHintTextView == null || inScheduleMode) { return; } if (voiceHintTextView == null) { @@ -5852,24 +5975,24 @@ private void checkScrollForLoad(boolean scroll) { loading = true; waitingForLoad.add(lastLoadIndex); if (messagesByDays.size() != 0) { - getMessagesController().loadMessages(dialog_id, 50, maxMessageId[0], 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 50, maxMessageId[0], 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } else { - getMessagesController().loadMessages(dialog_id, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 50, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } } else if (mergeDialogId != 0 && !endReached[1]) { loading = true; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(mergeDialogId, 50, maxMessageId[1], 0, !cacheEndReached[1], minDate[1], classGuid, 0, 0, false, lastLoadIndex++); + getMessagesController().loadMessages(mergeDialogId, 50, maxMessageId[1], 0, !cacheEndReached[1], minDate[1], classGuid, 0, 0, false, inScheduleMode, lastLoadIndex++); } } if (visibleItemCount > 0 && !loadingForward && firstVisibleItem <= 10) { if (mergeDialogId != 0 && !forwardEndReached[1]) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(mergeDialogId, 50, minMessageId[1], 0, true, maxDate[1], classGuid, 1, 0, false, lastLoadIndex++); + getMessagesController().loadMessages(mergeDialogId, 50, minMessageId[1], 0, true, maxDate[1], classGuid, 1, 0, false, inScheduleMode, lastLoadIndex++); loadingForward = true; } else if (!forwardEndReached[0]) { waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 50, minMessageId[0], 0, true, maxDate[0], classGuid, 1, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 50, minMessageId[0], 0, true, maxDate[0], classGuid, 1, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); loadingForward = true; } } @@ -5921,14 +6044,42 @@ private void processSelectedAttach(int which) { } fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { + public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { + if (photos.isEmpty()) { + return; + } + boolean hasNoGifs = false; + for (int a = 0; a < photos.size(); a++) { + SendMessagesHelper.SendingMediaInfo info = photos.get(a); + if (info.inlineResult == null) { + hasNoGifs = true; + break; + } + } + if (!hasNoGifs && !TextUtils.isEmpty(photos.get(0).caption)) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(photos.get(0).caption, dialog_id, replyingMessageObject, null, false, photos.get(0).entities, null, null, notify, scheduleDate); + } + for (int a = 0; a < photos.size(); a++) { + SendMessagesHelper.SendingMediaInfo info = photos.get(a); + if (info.inlineResult != null) { + SendMessagesHelper.prepareSendingBotContextResult(getAccountInstance(), info.inlineResult, info.params, dialog_id, replyingMessageObject, notify, scheduleDate); + photos.remove(a); + a--; + } + } if (photos.isEmpty()) { return; } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, null, false, true, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, null, false, true, editingMessageObject, notify, scheduleDate); + afterMessageSend(); + if (scheduleDate != 0) { + if (scheduledMessagesCount == -1) { + scheduledMessagesCount = 0; + } + scheduledMessagesCount += photos.size(); + updateScheduledInterface(true); + } } @Override @@ -5982,7 +6133,8 @@ public void startPhotoSelectActivity() { if (!AndroidUtilities.isGoogleMapsInstalled(ChatActivity.this)) { return; } - LocationActivity fragment = new LocationActivity(currentEncryptedChat == null ? 1 : 0); + LocationActivity fragment = new LocationActivity(currentEncryptedChat == null && !inScheduleMode ? 1 : 0); + fragment.setChatActivity(ChatActivity.this); fragment.setDialogId(dialog_id); fragment.setDelegate(this); presentFragment(fragment); @@ -5996,15 +6148,16 @@ public void startPhotoSelectActivity() { return; } DocumentSelectActivity fragment = new DocumentSelectActivity(true); + fragment.setChatActivity(ChatActivity.this); fragment.setMaxSelectedFiles(currentChat != null && !ChatObject.hasAdminRights(currentChat) && currentChat.slowmode_enabled || editingMessageObject != null ? 1 : -1); fragment.setDelegate(new DocumentSelectActivity.DocumentSelectActivityDelegate() { + @Override - public void didSelectFiles(DocumentSelectActivity activity, ArrayList files) { + public void didSelectFiles(DocumentSelectActivity activity, ArrayList files, boolean notify, int scheduleDate) { activity.finishFragment(); fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject, notify, scheduleDate); + afterMessageSend(); } @Override @@ -6023,13 +6176,12 @@ public void startDocumentSelectActivity() { @Override public void startMusicSelectActivity(BaseFragment parentFragment) { - AudioSelectActivity fragment = new AudioSelectActivity(); - fragment.setDelegate(audios -> { + AudioSelectActivity fragment = new AudioSelectActivity(ChatActivity.this); + fragment.setDelegate((audios, notify, scheduleDate) -> { parentFragment.removeSelfFromStack(); fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, dialog_id, replyingMessageObject, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, dialog_id, replyingMessageObject, editingMessageObject, notify, scheduleDate); + afterMessageSend(); }); presentFragment(fragment); } @@ -6040,12 +6192,11 @@ public void startMusicSelectActivity(BaseFragment parentFragment) { getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); return; } - AudioSelectActivity fragment = new AudioSelectActivity(); - fragment.setDelegate(audios -> { + AudioSelectActivity fragment = new AudioSelectActivity(ChatActivity.this); + fragment.setDelegate((audios, notify, scheduleDate) -> { fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, dialog_id, replyingMessageObject, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, dialog_id, replyingMessageObject, editingMessageObject, notify, scheduleDate); + afterMessageSend(); }); presentFragment(fragment); } else if (which == attach_contact) { @@ -6055,22 +6206,20 @@ public void startMusicSelectActivity(BaseFragment parentFragment) { return; } } - PhonebookSelectActivity activity = new PhonebookSelectActivity(); - activity.setDelegate(user -> { - getSendMessagesHelper().sendMessage(user, dialog_id, replyingMessageObject, null, null); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + PhonebookSelectActivity activity = new PhonebookSelectActivity(ChatActivity.this); + activity.setDelegate((user, notify, scheduleDate) -> { + getSendMessagesHelper().sendMessage(user, dialog_id, replyingMessageObject, null, null, notify, scheduleDate); + afterMessageSend(); }); presentFragment(activity); } else if (which == attach_poll) { if (currentChat == null || !ChatObject.canSendPolls(currentChat)) { return; } - PollCreateActivity pollCreateActivity = new PollCreateActivity(); - pollCreateActivity.setDelegate(poll -> { - getSendMessagesHelper().sendMessage(poll, dialog_id, replyingMessageObject, null, null); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + PollCreateActivity pollCreateActivity = new PollCreateActivity(ChatActivity.this); + pollCreateActivity.setDelegate((poll, notify, scheduleDate) -> { + getSendMessagesHelper().sendMessage(poll, dialog_id, replyingMessageObject, null, null, notify, scheduleDate); + afterMessageSend(); }); presentFragment(pollCreateActivity); } @@ -6235,12 +6384,12 @@ private void searchLinks(final CharSequence charSequence, final boolean force) { }); } - private void forwardMessages(ArrayList arrayList, boolean fromMyName) { + private void forwardMessages(ArrayList arrayList, boolean fromMyName, boolean notify, int scheduleDate) { if (arrayList == null || arrayList.isEmpty()) { return; } if (!fromMyName) { - AlertsCreator.showSendMediaAlert(getSendMessagesHelper().sendMessage(arrayList, dialog_id), this); + AlertsCreator.showSendMediaAlert(getSendMessagesHelper().sendMessage(arrayList, dialog_id, notify, scheduleDate), this); } else { for (MessageObject object : arrayList) { getSendMessagesHelper().processForwardFromMyName(object, dialog_id); @@ -6269,26 +6418,30 @@ private void checkBotKeyboard() { } public void hideFieldPanel(boolean animated) { - showFieldPanel(false, null, null, null, null, false, animated); + showFieldPanel(false, null, null, null, null, true, 0, false, animated); + } + + public void hideFieldPanel(boolean notify, int scheduleDate, boolean animated) { + showFieldPanel(false, null, null, null, null, notify, scheduleDate, false, animated); } public void showFieldPanelForWebPage(boolean show, TLRPC.WebPage webPage, boolean cancel) { - showFieldPanel(show, null, null, null, webPage, cancel, true); + showFieldPanel(show, null, null, null, webPage, true, 0, cancel, true); } public void showFieldPanelForForward(boolean show, ArrayList messageObjectsToForward) { - showFieldPanel(show, null, null, messageObjectsToForward, null, false, true); + showFieldPanel(show, null, null, messageObjectsToForward, null, true, 0, false, true); } public void showFieldPanelForReply(MessageObject messageObjectToReply) { - showFieldPanel(true, messageObjectToReply, null, null, null, false, true); + showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, false, true); } public void showFieldPanelForEdit(boolean show, MessageObject messageObjectToEdit) { - showFieldPanel(show, null, messageObjectToEdit, null, null, false, true); + showFieldPanel(show, null, messageObjectToEdit, null, null, true, 0, false, true); } - public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean cancel, boolean animated) { + public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, boolean cancel, boolean animated) { if (chatActivityEnterView == null) { return; } @@ -6517,7 +6670,7 @@ public void showFieldPanel(boolean show, MessageObject messageObjectToReply, Mes replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedContact", messageObjectsToForward.size())); } else if (type == 2) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedAudio", messageObjectsToForward.size())); - } else if (type == 5) { + } else if (type == MessageObject.TYPE_ROUND_VIDEO) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedRound", messageObjectsToForward.size())); } else if (type == 14) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedMusic", messageObjectsToForward.size())); @@ -6640,12 +6793,14 @@ public void showFieldPanel(boolean show, MessageObject messageObjectToReply, Mes foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); if (webPage != null && (replyingMessageObject != null || forwardingMessages != null || editingMessageObject != null)) { - showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages, null, false, true); + showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages, null, notify, scheduleDate, false, true); return; } } if (forwardingMessages != null) { - forwardMessages(forwardingMessages, false); + ArrayList messagesToForward = forwardingMessages; + forwardingMessages = null; + forwardMessages(messagesToForward, false, notify, scheduleDate != 0 ? scheduleDate + 1 : 0); } chatActivityEnterView.setForceShowSendButton(false, false); chatActivityEnterView.hideTopView(animated); @@ -6654,7 +6809,6 @@ public void showFieldPanel(boolean show, MessageObject messageObjectToReply, Mes topViewWasVisible = 0; replyingMessageObject = null; editingMessageObject = null; - forwardingMessages = null; replyImageLocation = null; replyImageLocationObject = null; } @@ -6729,7 +6883,7 @@ private void scrollToLastMessage(boolean pagedown) { } else { clearChatData(); waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 30, 0, 0, true, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 30, 0, 0, true, 0, classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } } @@ -6814,6 +6968,10 @@ private void updateMessagesVisiblePart(boolean inLayout) { View minMessageChild = null; boolean foundTextureViewMessage = false; + Integer currentReadMaxId = getMessagesController().dialogs_read_inbox_max.get(dialog_id); + if (currentReadMaxId == null) { + currentReadMaxId = 0; + } int maxPositiveUnreadId = Integer.MIN_VALUE; int maxNegativeUnreadId = Integer.MAX_VALUE; int maxUnreadDate = Integer.MIN_VALUE; @@ -6850,8 +7008,8 @@ private void updateMessagesVisiblePart(boolean inLayout) { } else if (view instanceof ChatActionCell) { messageObject = ((ChatActionCell) view).getMessageObject(); } - if (messageObject != null) { - if (!messageObject.isOut() && messageObject.isUnread()) { + if (!inScheduleMode && messageObject != null) { + if (!messageObject.isOut() && messageObject.isUnread() || messageObject.messageOwner.from_scheduled && messageObject.getId() > currentReadMaxId) { int id = messageObject.getId(); if (id > 0) { maxPositiveUnreadId = Math.max(maxPositiveUnreadId, messageObject.getId()); @@ -6912,7 +7070,7 @@ private void updateMessagesVisiblePart(boolean inLayout) { } else { messageObject = ((ChatActionCell) minMessageChild).getMessageObject(); } - floatingDateView.setCustomDate(messageObject.messageOwner.date); + floatingDateView.setCustomDate(messageObject.messageOwner.date, inScheduleMode); } currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); @@ -6949,29 +7107,34 @@ private void updateMessagesVisiblePart(boolean inLayout) { floatingDateView.setTranslationY(0); } - if (!firstLoading && !paused && !inPreviewMode) { + if (!firstLoading && !paused && !inPreviewMode && !inScheduleMode) { + int scheduledRead = 0; if ((maxPositiveUnreadId != Integer.MIN_VALUE || maxNegativeUnreadId != Integer.MAX_VALUE)) { - int counterDicrement = 0; + int counterDecrement = 0; for (int a = 0; a < messages.size(); a++) { MessageObject messageObject = messages.get(a); int id = messageObject.getId(); if (maxPositiveUnreadId != Integer.MIN_VALUE) { - if (id > 0 && id <= maxPositiveUnreadId && messageObject.isUnread()) { - messageObject.setIsRead(); - counterDicrement++; + if (id > 0 && id <= maxPositiveUnreadId && (messageObject.messageOwner.from_scheduled && id > currentReadMaxId || messageObject.isUnread())) { + if (messageObject.messageOwner.from_scheduled) { + scheduledRead++; + } else { + messageObject.setIsRead(); + } + counterDecrement++; } } if (maxNegativeUnreadId != Integer.MAX_VALUE) { if (id < 0 && id >= maxNegativeUnreadId && messageObject.isUnread()) { messageObject.setIsRead(); - counterDicrement++; + counterDecrement++; } } } if (forwardEndReached[0] && maxPositiveUnreadId == minMessageId[0] || maxNegativeUnreadId == minMessageId[0]) { newUnreadMessageCount = 0; } else { - newUnreadMessageCount -= counterDicrement; + newUnreadMessageCount -= counterDecrement; if (newUnreadMessageCount < 0) { newUnreadMessageCount = 0; } @@ -6981,7 +7144,7 @@ private void updateMessagesVisiblePart(boolean inLayout) { } else { inlineUpdate1(); } - getMessagesController().markDialogAsRead(dialog_id, maxPositiveUnreadId, maxNegativeUnreadId, maxUnreadDate, false, counterDicrement, maxPositiveUnreadId == minMessageId[0] || maxNegativeUnreadId == minMessageId[0]); + getMessagesController().markDialogAsRead(dialog_id, maxPositiveUnreadId, maxNegativeUnreadId, maxUnreadDate, false, counterDecrement, maxPositiveUnreadId == minMessageId[0] || maxNegativeUnreadId == minMessageId[0], scheduledRead); firstUnreadSent = true; } else if (!firstUnreadSent) { if (chatLayoutManager.findFirstVisibleItemPosition() == 0) { @@ -6991,7 +7154,7 @@ private void updateMessagesVisiblePart(boolean inLayout) { } else { inlineUpdate2(); } - getMessagesController().markDialogAsRead(dialog_id, minMessageId[0], minMessageId[0], maxDate[0], false, 0, true); + getMessagesController().markDialogAsRead(dialog_id, minMessageId[0], minMessageId[0], maxDate[0], false, 0, true, scheduledRead); firstUnreadSent = true; } } @@ -7195,10 +7358,13 @@ public void scrollToMessageId(int id, int fromMessageId, boolean select, int loa createUnreadMessageAfterIdLoading = true; } waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); //emptyViewContainer.setVisibility(View.INVISIBLE); } else { - showFloatingDateView(false); + View child = chatListView.getChildAt(0); + if (child != null && child.getTop() <= 0) { + showFloatingDateView(false); + } } returnToMessageId = fromMessageId; returnToLoadIndex = loadIndex; @@ -7464,10 +7630,9 @@ private int getMessageType(MessageObject messageObject) { return -1; } if (currentEncryptedChat == null) { - boolean isBroadcastError = isBroadcast && messageObject.getId() <= 0 && messageObject.isSendError(); if (messageObject.isEditing()) { return -1; - } else if (!isBroadcast && messageObject.getId() <= 0 && messageObject.isOut() || isBroadcastError) { + } else if (messageObject.getId() <= 0 && messageObject.isOut()) { if (messageObject.isSendError()) { if (!messageObject.isMediaEmpty()) { return 0; @@ -7649,10 +7814,10 @@ private void addToSelectedMessages(MessageObject messageObject, boolean outside, if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount--; } - if (!messageObject.canDeleteMessage(currentChat)) { + if (!messageObject.canDeleteMessage(inScheduleMode, currentChat)) { cantDeleteMessagesCount--; } - if (!messageObject.canForwardMessage()) { + if (inScheduleMode || !messageObject.canForwardMessage()) { cantForwardMessagesCount--; } else { canForwardMessagesCount--; @@ -7671,10 +7836,10 @@ private void addToSelectedMessages(MessageObject messageObject, boolean outside, if (messageObject.canEditMessage(currentChat)) { canEditMessagesCount++; } - if (!messageObject.canDeleteMessage(currentChat)) { + if (!messageObject.canDeleteMessage(inScheduleMode, currentChat)) { cantDeleteMessagesCount++; } - if (!messageObject.canForwardMessage()) { + if (inScheduleMode || !messageObject.canForwardMessage()) { cantForwardMessagesCount++; } else { canForwardMessagesCount++; @@ -7752,7 +7917,6 @@ public void onAnimationEnd(Animator animation) { if (replyButton != null) { boolean allowChatActions = true; if (currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || - isBroadcast || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { allowChatActions = false; @@ -7760,7 +7924,7 @@ public void onAnimationEnd(Animator animation) { int newVisibility; - if (!allowChatActions || selectedCount == 0 || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { + if (inScheduleMode || !allowChatActions || selectedCount == 0 || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { newVisibility = View.GONE; } else if (selectedCount == 1) { newVisibility = View.VISIBLE; @@ -7908,7 +8072,13 @@ private void updateTitle() { if (avatarContainer == null) { return; } - if (currentChat != null) { + if (inScheduleMode) { + if (UserObject.isUserSelf(currentUser)) { + avatarContainer.setTitle(LocaleController.getString("Reminders", R.string.Reminders)); + } else { + avatarContainer.setTitle(LocaleController.getString("ScheduledMessages", R.string.ScheduledMessages)); + } + } else if (currentChat != null) { avatarContainer.setTitle(currentChat.title, currentChat.scam); } else if (currentUser != null) { if (currentUser.self) { @@ -7961,7 +8131,7 @@ private void updateBotButtons() { } private void updateTitleIcons() { - if (avatarContainer == null) { + if (avatarContainer == null || inScheduleMode) { return; } Drawable rightIcon = getMessagesController().isDialogMuted(dialog_id) ? Theme.chat_muteIconDrawable : null; @@ -8009,8 +8179,8 @@ public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { - sendMedia((MediaController.PhotoEntry) cameraPhoto.get(0), videoEditedInfo); + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { + sendMedia((MediaController.PhotoEntry) cameraPhoto.get(0), videoEditedInfo, notify, scheduleDate); } @Override @@ -8020,9 +8190,8 @@ public boolean canScrollAway() { }, this); } else { fillEditingMediaWithCaption(caption, null); - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, null, null, 0, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, null, null, 0, editingMessageObject, true, 0); + afterMessageSend(); } } @@ -8078,7 +8247,7 @@ private void sendUriAsDocument(Uri uri) { return; } fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject); + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject, true, 0); hideFieldPanel(false); } @@ -8113,11 +8282,17 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat openVideoEditor(videoPath, null); } } else { - fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, null, null, null, null, 0, editingMessageObject); + if (editingMessageObject == null && inScheduleMode) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(currentUser), (notify, scheduleDate) -> { + fillEditingMediaWithCaption(null, null); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, null, null, null, null, 0, editingMessageObject, notify, scheduleDate); + }); + } else { + fillEditingMediaWithCaption(null, null); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, null, null, null, null, 0, editingMessageObject, true, 0); + } } - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + afterMessageSend(); } else if (requestCode == 21) { if (data == null) { showAttachmentError(); @@ -8133,8 +8308,7 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat } else { showAttachmentError(); } - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + afterMessageSend(); } } } @@ -8165,10 +8339,6 @@ private void removeUnreadPlane(boolean scrollToEnd) { } } - public boolean processSendingText(String text) { - return chatActivityEnterView.processSendingText(text); - } - @Override public void didReceivedNotification(int id, int account, final Object... args) { if (id == NotificationCenter.messagesDidLoad) { @@ -8176,22 +8346,36 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (guid == classGuid) { setItemAnimationsEnabled(false); if (!openAnimationEnded) { - getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, + getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } int queryLoadIndex = (Integer) args[11]; int index = waitingForLoad.indexOf(queryLoadIndex); int currentUserId = getUserConfig().getClientUserId(); + boolean schedule = (Boolean) args[14]; + boolean isCache = (Boolean) args[3]; if (index == -1) { + if (inScheduleMode && schedule && !isCache) { + waitingForReplyMessageLoad = true; + waitingForLoad.add(lastLoadIndex); + getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); + } return; } else { waitingForLoad.remove(index); } ArrayList messArr = (ArrayList) args[2]; + if (inScheduleMode != schedule) { + if (!inScheduleMode) { + scheduledMessagesCount = messArr.size(); + updateScheduledInterface(true); + } + return; + } boolean createUnreadLoading = false; boolean showDateAfter = waitingForReplyMessageLoad; if (waitingForReplyMessageLoad) { - if (!createUnreadMessageAfterIdLoading) { + if (!inScheduleMode && !createUnreadMessageAfterIdLoading) { boolean found = false; for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); @@ -8218,16 +8402,17 @@ public void didReceivedNotification(int id, int account, final Object... args) { int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; clearChatData(); - createUnreadMessageAfterId = unreadAfterId; - startLoadFromMessageId = startLoadFrom; - needSelectFromMessageId = needSelect; + if (!inScheduleMode) { + createUnreadMessageAfterId = unreadAfterId; + startLoadFromMessageId = startLoadFrom; + needSelectFromMessageId = needSelect; + } } loadsCount++; long did = (Long) args[0]; int loadIndex = did == dialog_id ? 0 : 1; int count = (Integer) args[1]; - boolean isCache = (Boolean) args[3]; int fnid = (Integer) args[4]; int last_unread_date = (Integer) args[7]; int load_type = (Integer) args[8]; @@ -8280,6 +8465,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { forwardEndReached[0] = false; minMessageId[0] = 0; } + if (inScheduleMode) { + endReached[0] = cacheEndReached[0] = true; + forwardEndReached[0] = forwardEndReached[0] = true; + } if (loadsCount == 1 && messArr.size() > 20) { loadsCount++; @@ -8315,7 +8504,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { Collections.reverse(messArr); } if (currentEncryptedChat == null) { - getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id); + getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, inScheduleMode); } int approximateHeightSum = 0; if ((load_type == 2 || load_type == 1) && messArr.isEmpty() && !isCache) { @@ -8346,7 +8535,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (currentUser.self) { obj.messageOwner.out = true; } - if (currentUser.bot && obj.isOut() || currentUser.id == currentUserId) { + if (!inScheduleMode && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } } @@ -8397,7 +8586,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { continue; } - if (needAnimateToMessage != null && needAnimateToMessage.getId() == messageId && messageId < 0 && obj.type == 5) { + if (needAnimateToMessage != null && needAnimateToMessage.getId() == messageId && messageId < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { obj = needAnimateToMessage; animatingMessageObjects.add(obj); needAnimateToMessage = null; @@ -8410,9 +8599,17 @@ public void didReceivedNotification(int id, int account, final Object... args) { dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); - dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); + if (inScheduleMode) { + dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); + } else { + dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); + } dateMsg.id = 0; - dateMsg.date = obj.messageOwner.date; + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false); dateObj.type = 10; dateObj.contentType = 1; @@ -8482,7 +8679,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { if (currentEncryptedChat == null) { if (createUnreadMessageAfterId != 0 && load_type != 1 && a + 1 < messArr.size()) { prevObj = messArr.get(a + 1); - if (obj.isOut() || prevObj.getId() >= createUnreadMessageAfterId) { + if (obj.isOut() && !obj.messageOwner.from_scheduled || prevObj.getId() >= createUnreadMessageAfterId) { prevObj = null; } } else { @@ -8491,7 +8688,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else { if (createUnreadMessageAfterId != 0 && load_type != 1 && a - 1 >= 0) { prevObj = messArr.get(a - 1); - if (obj.isOut() || prevObj.getId() >= createUnreadMessageAfterId) { + if (obj.isOut() && !obj.messageOwner.from_scheduled || prevObj.getId() >= createUnreadMessageAfterId) { prevObj = null; } } else { @@ -8527,7 +8724,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } if (load_type != 2 && unreadMessageObject == null && createUnreadMessageAfterId != 0 && - (currentEncryptedChat == null && !obj.isOut() && messageId >= createUnreadMessageAfterId || currentEncryptedChat != null && !obj.isOut() && messageId <= createUnreadMessageAfterId) && + (currentEncryptedChat == null && (!obj.isOut() || obj.messageOwner.from_scheduled) && messageId >= createUnreadMessageAfterId || currentEncryptedChat != null && (!obj.isOut() || obj.messageOwner.from_scheduled) && messageId <= createUnreadMessageAfterId) && (load_type == 1 || prevObj != null || prevObj == null && createUnreadLoading && a == messArr.size() - 1)) { TLRPC.Message dateMsg = new TLRPC.TL_message(); dateMsg.message = ""; @@ -8621,7 +8818,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else { if (messArr.size() < count && load_type != 3 && load_type != 4) { if (isCache) { - if (currentEncryptedChat != null || isBroadcast || loadIndex == 1 && mergeDialogId != 0 && isEnd) { + if (currentEncryptedChat != null || loadIndex == 1 && mergeDialogId != 0 && isEnd) { endReached[loadIndex] = true; } if (load_type != 2) { @@ -8791,7 +8988,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } if (newRowsCount == 0 && mergeDialogId != 0 && loadIndex == 0) { - getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, + getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } if (showDateAfter) { @@ -8890,6 +9087,16 @@ public void didReceivedNotification(int id, int account, final Object... args) { } else if (id == NotificationCenter.didReceiveNewMessages) { long did = (Long) args[0]; if (did == dialog_id) { + boolean scheduled = (Boolean) args[2]; + if (scheduled != inScheduleMode) { + if (!inScheduleMode && !isPaused && forwardingMessages == null) { + ArrayList arr = (ArrayList) args[1]; + if (!arr.isEmpty() && arr.get(0).getId() < 0) { + openScheduledMessages(); + } + } + return; + } int currentUserId = getUserConfig().getClientUserId(); boolean updateChat = false; boolean hasFromMe = false; @@ -8917,7 +9124,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi notifiedSearch = true; NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); } - if (currentChat != null && currentChat.slowmode_enabled && messageObject.isSent()) { + if (currentChat != null && currentChat.slowmode_enabled && messageObject.isSent() && !inScheduleMode) { if (chatInfo != null) { int date = messageObject.messageOwner.date + chatInfo.slowmode_seconds; int currentTime = getConnectionsManager().getCurrentTime(); @@ -8973,6 +9180,10 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } + if (inScheduleMode && !arr.isEmpty()) { + replaceMessageObjects(arr, 0, true); + } + boolean reloadMegagroup = false; if (!forwardEndReached[0]) { int currentMaxDate = Integer.MIN_VALUE; @@ -8984,7 +9195,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi for (int a = 0; a < arr.size(); a++) { MessageObject obj = arr.get(a); int messageId = obj.getId(); - if (currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { + if (!inScheduleMode && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } TLRPC.MessageAction action = obj.messageOwner.action; @@ -8997,7 +9208,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } else if (currentChat != null && currentChat.megagroup && (action instanceof TLRPC.TL_messageActionChatAddUser || action instanceof TLRPC.TL_messageActionChatDeleteUser)) { reloadMegagroup = true; } - if (a == 0 && obj.messageOwner.id < 0 && obj.type == 5) { + if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { needAnimateToMessage = obj; } if (obj.isOut() && obj.isSending()) { @@ -9053,13 +9264,35 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi FileLog.d("received new messages " + arr.size() + " in dialog " + dialog_id); } for (int a = 0; a < arr.size(); a++) { - int placeToPaste = -1; MessageObject obj = arr.get(a); + if (obj.scheduled != inScheduleMode) { + continue; + } + int placeToPaste = -1; int messageId = obj.getId(); + if (inScheduleMode && messagesDict[0].indexOfKey(messageId) >= 0) { + MessageObject removed = messagesDict[0].get(messageId); + messagesDict[0].remove(messageId); + if (removed != null) { + int index = messages.indexOf(removed); + messages.remove(index); + ArrayList dayArr = messagesByDays.get(removed.dateKey); + dayArr.remove(removed); + if (dayArr.isEmpty()) { + messagesByDays.remove(removed.dateKey); + if (index >= 0 && index < messages.size()) { + messages.remove(index); + } + } + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(); + } + } + } if (isSecretChat()) { checkSecretMessageForLocation(obj); } - if (currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { + if (!inScheduleMode && currentUser != null && (currentUser.bot && obj.isOut() || currentUser.id == currentUserId)) { obj.setIsRead(); } TLRPC.MessageAction action = obj.messageOwner.action; @@ -9076,7 +9309,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi continue; } addToPolls(obj, null); - if (a == 0 && obj.messageOwner.id < 0 && obj.type == 5) { + if (a == 0 && obj.messageOwner.id < 0 && obj.type == MessageObject.TYPE_ROUND_VIDEO && !inScheduleMode) { animatingMessageObjects.add(obj); } @@ -9106,14 +9339,14 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } if (placeToPaste == -1) { - if (obj.messageOwner.id < 0 || messages.isEmpty()) { + if (!obj.scheduled && obj.messageOwner.id < 0 || messages.isEmpty()) { placeToPaste = 0; } else { int size = messages.size(); for (int b = 0; b < size; b++) { MessageObject lastMessage = messages.get(b); if (lastMessage.type >= 0 && lastMessage.messageOwner.date > 0) { - if (lastMessage.messageOwner.id > 0 && obj.messageOwner.id > 0 && lastMessage.messageOwner.id < obj.messageOwner.id || lastMessage.messageOwner.date < obj.messageOwner.date) { + if (!inScheduleMode && lastMessage.messageOwner.id > 0 && obj.messageOwner.id > 0 && lastMessage.messageOwner.id < obj.messageOwner.id || lastMessage.messageOwner.date <= obj.messageOwner.date) { MessageObject.GroupedMessages lastGroupedMessages; if (lastMessage.getGroupId() != 0) { lastGroupedMessages = groupedMessagesMap.get(lastMessage.getGroupId()); @@ -9164,7 +9397,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi minDate[0] = obj.messageOwner.date; } - if (obj.isOut()) { + if (obj.isOut() && !obj.messageOwner.from_scheduled) { removeUnreadPlane(true); hasFromMe = true; } @@ -9186,9 +9419,17 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi dayArray = new ArrayList<>(); messagesByDays.put(obj.dateKey, dayArray); TLRPC.Message dateMsg = new TLRPC.TL_message(); - dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); + if (inScheduleMode) { + dateMsg.message = LocaleController.formatString("MessageScheduledOn", R.string.MessageScheduledOn, LocaleController.formatDateChat(obj.messageOwner.date, true)); + } else { + dateMsg.message = LocaleController.formatDateChat(obj.messageOwner.date); + } dateMsg.id = 0; - dateMsg.date = obj.messageOwner.date; + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(((long) obj.messageOwner.date) * 1000); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + dateMsg.date = (int) (calendar.getTimeInMillis() / 1000); MessageObject dateObj = new MessageObject(currentAccount, dateMsg, false); dateObj.type = 10; dateObj.contentType = 1; @@ -9198,7 +9439,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi chatAdapter.notifyItemInserted(placeToPaste); } } - if (!obj.isOut()) { + if (!obj.isOut() || obj.messageOwner.from_scheduled) { if (paused && placeToPaste == 0) { if (!scrollToTopUnReadOnResume && unreadMessageObject != null) { removeMessageObject(unreadMessageObject); @@ -9242,7 +9483,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } if (webpagesToReload != null) { - getMessagesController().reloadWebPages(dialog_id, webpagesToReload); + getMessagesController().reloadWebPages(dialog_id, webpagesToReload, inScheduleMode); } if (newGroups != null) { for (int a = 0; a < newGroups.size(); a++) { @@ -9280,7 +9521,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } if (lastVisible == 0 && diff <= AndroidUtilities.dp(5) || hasFromMe) { newUnreadMessageCount = 0; - if (!firstLoading) { + if (!firstLoading && !inScheduleMode) { if (paused) { scrollToTopOnResume = true; } else { @@ -9307,6 +9548,12 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi scrollToTopOnResume = true; } } + if (inScheduleMode && !arr.isEmpty()) { + int mid = arr.get(0).getId(); + if (mid < 0) { + scrollToMessageId(mid, 0, false, 0, true); + } + } if (!messages.isEmpty() && botUser != null && botUser.length() == 0) { botUser = null; updateBottomOverlay(); @@ -9329,6 +9576,9 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi removeSelfFromStack(); } } else if (id == NotificationCenter.messagesRead) { + if (inScheduleMode) { + return; + } SparseLongArray inbox = (SparseLongArray) args[0]; SparseLongArray outbox = (SparseLongArray) args[1]; boolean updated = false; @@ -9460,7 +9710,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi maxDate[0] = maxDate[1] = Integer.MIN_VALUE; minDate[0] = minDate[1] = 0; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); loading = true; } else { if (botButtons != null) { @@ -9482,6 +9732,10 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi chatAdapter.notifyDataSetChanged(); } } else if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled != inScheduleMode) { + return; + } ArrayList markAsDeletedMessages = (ArrayList) args[0]; int channelId = (Integer) args[1]; int loadIndex = 0; @@ -9501,6 +9755,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi int size = markAsDeletedMessages.size(); boolean updatedSelected = false; boolean updatedSelectedLast = false; + boolean updateScheduled = false; for (int a = 0; a < size; a++) { Integer ids = markAsDeletedMessages.get(a); MessageObject obj = messagesDict[loadIndex].get(ids); @@ -9520,6 +9775,10 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } int index = messages.indexOf(obj); if (index != -1) { + if (obj.scheduled) { + scheduledMessagesCount--; + updateScheduled = true; + } removeUnreadPlane(false); if (selectedMessagesIds[loadIndex].indexOfKey(ids) >= 0) { updatedSelected = true; @@ -9592,7 +9851,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi maxDate[0] = maxDate[1] = Integer.MIN_VALUE; minDate[0] = minDate[1] = 0; waitingForLoad.add(lastLoadIndex); - getMessagesController().loadMessages(dialog_id, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, 30, 0, 0, !cacheEndReached[0], minDate[0], classGuid, 0, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); loading = true; } else { if (botButtons != null) { @@ -9647,7 +9906,14 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } } + if (updateScheduled) { + updateScheduledInterface(true); + } } else if (id == NotificationCenter.messageReceivedByServer) { + Boolean scheduled = (Boolean) args[6]; + if (scheduled != inScheduleMode) { + return; + } Integer msgId = (Integer) args[0]; MessageObject obj = messagesDict[0].get(msgId); if (obj != null) { @@ -9725,7 +9991,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi ArrayList messArr = new ArrayList<>(); messArr.add(obj); if (currentEncryptedChat == null) { - getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id); + getMediaDataController().loadReplyMessagesForMessages(messArr, dialog_id, inScheduleMode); } if (chatAdapter != null) { chatAdapter.updateRowWithMessageObject(obj, true); @@ -9789,9 +10055,6 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi avatarContainer.updateOnlineCount(); avatarContainer.updateSubtitle(); } - if (isBroadcast) { - getSendMessagesHelper().setCurrentChatInfo(chatInfo); - } if (chatInfo instanceof TLRPC.TL_chatFull) { hasBotsCommands = false; botInfo.clear(); @@ -9838,7 +10101,7 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi if (mentionsAdapter != null) { mentionsAdapter.setBotsCount(botsCount); } - if (ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0) { + if (!inScheduleMode && ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0) { mergeDialogId = -chatInfo.migrated_from_chat_id; maxMessageId[1] = chatInfo.migrated_from_max_id; if (chatAdapter != null) { @@ -10142,6 +10405,17 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } } + } else if (id == NotificationCenter.didUpdateReactions) { + long did = (Long) args[0]; + if (did == dialog_id || did == mergeDialogId) { + int msgId = (Integer) args[1]; + MessageObject messageObject = messagesDict[did == dialog_id ? 0 : 1].get(msgId); + if (messageObject != null) { + MessageObject.updateReactions(messageObject.messageOwner, (TLRPC.TL_messageReactions) args[2]); + messageObject.measureInlineBotButtons(); + chatAdapter.updateRowWithMessageObject(messageObject, true); + } + } } else if (id == NotificationCenter.updateMessageMedia) { TLRPC.Message message = (TLRPC.Message) args[0]; MessageObject existMessageObject = messagesDict[0].get(message.id); @@ -10175,153 +10449,34 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi if (messageObject == null) { messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); } - groupedMessages.calculate(); - int index = messages.indexOf(messageObject); - if (index >= 0) { - if (chatAdapter != null) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); - } - } - } - } - } - } - if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { - existMessageObject.setType(); - if (chatAdapter != null) { - chatAdapter.updateRowWithMessageObject(existMessageObject, false); - } - } else { - updateVisibleRows(); - } - } - } else if (id == NotificationCenter.replaceMessagesObjects) { - long did = (long) args[0]; - if (did != dialog_id && did != mergeDialogId) { - return; - } - int loadIndex = did == dialog_id ? 0 : 1; - ArrayList messageObjects = (ArrayList) args[1]; - LongSparseArray newGroups = null; - for (int a = 0; a < messageObjects.size(); a++) { - MessageObject messageObject = messageObjects.get(a); - MessageObject old = messagesDict[loadIndex].get(messageObject.getId()); - if (pinnedMessageObject != null && pinnedMessageObject.getId() == messageObject.getId()) { - pinnedMessageObject = messageObject; - updatePinnedMessageView(true); - } - if (old != null) { - addToPolls(messageObject, old); - if (messageObject.type >= 0) { - if (old.replyMessageObject != null) { - messageObject.replyMessageObject = old.replyMessageObject; - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { - messageObject.generateGameMessageText(null); - } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { - messageObject.generatePaymentSentMessageText(null); - } - } - if (!old.isEditing()) { - if (old.getFileName().equals(messageObject.getFileName())) { - messageObject.messageOwner.attachPath = old.messageOwner.attachPath; - messageObject.attachPathExists = old.attachPathExists; - messageObject.mediaExists = old.mediaExists; - } else { - messageObject.checkMediaExistance(); - } - } - messagesDict[loadIndex].put(old.getId(), messageObject); - } else { - messagesDict[loadIndex].remove(old.getId()); - } - int index = messages.indexOf(old); - if (index >= 0) { - ArrayList dayArr = messagesByDays.get(old.dateKey); - int index2 = -1; - if (dayArr != null) { - index2 = dayArr.indexOf(old); - } - if (old.getGroupId() != 0) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(old.getGroupId()); - if (groupedMessages != null) { - int idx = groupedMessages.messages.indexOf(old); - if (idx >= 0) { - if (old.getGroupId() != messageObject.getGroupId()) { - groupedMessagesMap.put(messageObject.getGroupId(), groupedMessages); - } - if (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty()) { - if (newGroups == null) { - newGroups = new LongSparseArray<>(); - } - newGroups.put(groupedMessages.groupId, groupedMessages); - if (idx > 0 && idx < groupedMessages.messages.size() - 1) { - MessageObject.GroupedMessages slicedGroup = new MessageObject.GroupedMessages(); - slicedGroup.groupId = Utilities.random.nextLong(); - slicedGroup.messages.addAll(groupedMessages.messages.subList(idx + 1, groupedMessages.messages.size())); - for (int b = 0; b < slicedGroup.messages.size(); b++) { - slicedGroup.messages.get(b).localGroupId = slicedGroup.groupId; - groupedMessages.messages.remove(idx + 1); - } - newGroups.put(slicedGroup.groupId, slicedGroup); - groupedMessagesMap.put(slicedGroup.groupId, slicedGroup); - } - groupedMessages.messages.remove(idx); - } else { - groupedMessages.messages.set(idx, messageObject); - MessageObject.GroupedMessagePosition oldPosition = groupedMessages.positions.remove(old); - if (oldPosition != null) { - groupedMessages.positions.put(messageObject, oldPosition); - } - if (newGroups == null) { - newGroups = new LongSparseArray<>(); - } - newGroups.put(groupedMessages.groupId, groupedMessages); - } - } - } - } - if (messageObject.type >= 0) { - messages.set(index, messageObject); - if (chatAdapter != null) { - chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); - } - if (index2 >= 0) { - dayArr.set(index2, messageObject); - } - } else { - messages.remove(index); - if (chatAdapter != null) { - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); - } - if (index2 >= 0) { - dayArr.remove(index2); - if (dayArr.isEmpty()) { - messagesByDays.remove(old.dateKey); - messages.remove(index); - chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow); + groupedMessages.calculate(); + int index = messages.indexOf(messageObject); + if (index >= 0) { + if (chatAdapter != null) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, updateCount); + } } } } } } - } - if (newGroups != null) { - for (int b = 0; b < newGroups.size(); b++) { - MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); - if (groupedMessages.messages.isEmpty()) { - groupedMessagesMap.remove(groupedMessages.groupId); - } else { - groupedMessages.calculate(); - MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); - int index = messages.indexOf(messageObject); - if (index >= 0) { - if (chatAdapter != null) { - chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); - } - } + if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) { + existMessageObject.setType(); + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(existMessageObject, false); } + } else { + updateVisibleRows(); } } + } else if (id == NotificationCenter.replaceMessagesObjects) { + long did = (long) args[0]; + if (did != dialog_id && did != mergeDialogId) { + return; + } + int loadIndex = did == dialog_id ? 0 : 1; + ArrayList messageObjects = (ArrayList) args[1]; + replaceMessageObjects(messageObjects, loadIndex, false); } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTitleIcons(); if (ChatObject.isChannel(currentChat)) { @@ -10523,6 +10678,21 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } chatListView.invalidateViews(); } + } else if (id == NotificationCenter.goingToPreviewTheme) { + if (chatLayoutManager != null) { + int lastPosition = chatLayoutManager.findFirstVisibleItemPosition(); + if (lastPosition != 0) { + scrollToPositionOnRecreate = lastPosition; + RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(scrollToPositionOnRecreate); + if (holder != null) { + scrollToOffsetOnRecreate = chatListView.getMeasuredHeight() - holder.itemView.getBottom() - chatListView.getPaddingBottom(); + } else { + scrollToPositionOnRecreate = -1; + } + } else { + scrollToPositionOnRecreate = -1; + } + } } else if (id == NotificationCenter.channelRightsUpdated) { TLRPC.Chat chat = (TLRPC.Chat) args[0]; if (currentChat != null && chat.id == currentChat.id && chatActivityEnterView != null) { @@ -10546,7 +10716,11 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } } else if (id == NotificationCenter.audioRecordTooShort) { - showVoiceHint(false, (Boolean) args[0]); + int guid = (Integer) args[0]; + if (guid != classGuid) { + return; + } + showVoiceHint(false, (Boolean) args[1]); } else if (id == NotificationCenter.videoLoadingStateChanged) { if (chatListView != null) { String fileName = (String) args[0]; @@ -10566,6 +10740,12 @@ obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActi } } } + } else if (id == NotificationCenter.scheduledMessagesUpdated) { + long did = (Long) args[0]; + if (dialog_id == did) { + scheduledMessagesCount = (Integer) args[1]; + updateScheduledInterface(openAnimationEnded); + } } } @@ -10637,9 +10817,9 @@ private void clearHistory(boolean overwrite) { if (startLoadFromMessageIdSaved != 0) { startLoadFromMessageId = startLoadFromMessageIdSaved; startLoadFromMessageIdSaved = 0; - getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } else { - getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + getMessagesController().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), inScheduleMode, lastLoadIndex++); } } else { if (progressView != null) { @@ -10696,6 +10876,135 @@ public boolean processSwitchButton(TLRPC.TL_keyboardButtonSwitchInline button) { return true; } + private void replaceMessageObjects(ArrayList messageObjects, int loadIndex, boolean remove) { + LongSparseArray newGroups = null; + for (int a = 0; a < messageObjects.size(); a++) { + MessageObject messageObject = messageObjects.get(a); + MessageObject old = messagesDict[loadIndex].get(messageObject.getId()); + if (pinnedMessageObject != null && pinnedMessageObject.getId() == messageObject.getId()) { + pinnedMessageObject = messageObject; + updatePinnedMessageView(true); + } + if (old == null || remove && old.messageOwner.date != messageObject.messageOwner.date) { + continue; + } + if (remove) { + messageObjects.remove(a); + a--; + } + + addToPolls(messageObject, old); + if (messageObject.type >= 0) { + if (old.replyMessageObject != null) { + messageObject.replyMessageObject = old.replyMessageObject; + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { + messageObject.generateGameMessageText(null); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { + messageObject.generatePaymentSentMessageText(null); + } + } + if (!old.isEditing()) { + if (old.getFileName().equals(messageObject.getFileName())) { + messageObject.messageOwner.attachPath = old.messageOwner.attachPath; + messageObject.attachPathExists = old.attachPathExists; + messageObject.mediaExists = old.mediaExists; + } else { + messageObject.checkMediaExistance(); + } + } + messagesDict[loadIndex].put(old.getId(), messageObject); + } else { + messagesDict[loadIndex].remove(old.getId()); + } + int index = messages.indexOf(old); + if (index >= 0) { + ArrayList dayArr = messagesByDays.get(old.dateKey); + int index2 = -1; + if (dayArr != null) { + index2 = dayArr.indexOf(old); + } + if (old.getGroupId() != 0) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(old.getGroupId()); + if (groupedMessages != null) { + int idx = groupedMessages.messages.indexOf(old); + if (idx >= 0) { + if (old.getGroupId() != messageObject.getGroupId()) { + groupedMessagesMap.put(messageObject.getGroupId(), groupedMessages); + } + if (messageObject.photoThumbs == null || messageObject.photoThumbs.isEmpty()) { + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + if (idx > 0 && idx < groupedMessages.messages.size() - 1) { + MessageObject.GroupedMessages slicedGroup = new MessageObject.GroupedMessages(); + slicedGroup.groupId = Utilities.random.nextLong(); + slicedGroup.messages.addAll(groupedMessages.messages.subList(idx + 1, groupedMessages.messages.size())); + for (int b = 0; b < slicedGroup.messages.size(); b++) { + slicedGroup.messages.get(b).localGroupId = slicedGroup.groupId; + groupedMessages.messages.remove(idx + 1); + } + newGroups.put(slicedGroup.groupId, slicedGroup); + groupedMessagesMap.put(slicedGroup.groupId, slicedGroup); + } + groupedMessages.messages.remove(idx); + } else { + groupedMessages.messages.set(idx, messageObject); + MessageObject.GroupedMessagePosition oldPosition = groupedMessages.positions.remove(old); + if (oldPosition != null) { + groupedMessages.positions.put(messageObject, oldPosition); + } + if (newGroups == null) { + newGroups = new LongSparseArray<>(); + } + newGroups.put(groupedMessages.groupId, groupedMessages); + } + } + } + } + if (messageObject.type >= 0) { + messages.set(index, messageObject); + if (chatAdapter != null) { + chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); + } + if (index2 >= 0) { + dayArr.set(index2, messageObject); + } + } else { + messages.remove(index); + if (chatAdapter != null) { + chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow + index); + } + if (index2 >= 0) { + dayArr.remove(index2); + if (dayArr.isEmpty()) { + messagesByDays.remove(old.dateKey); + messages.remove(index); + chatAdapter.notifyItemRemoved(chatAdapter.messagesStartRow); + } + } + } + } + } + if (newGroups != null) { + for (int b = 0; b < newGroups.size(); b++) { + MessageObject.GroupedMessages groupedMessages = newGroups.valueAt(b); + if (groupedMessages.messages.isEmpty()) { + groupedMessagesMap.remove(groupedMessages.groupId); + } else { + groupedMessages.calculate(); + MessageObject messageObject = groupedMessages.messages.get(groupedMessages.messages.size() - 1); + int index = messages.indexOf(messageObject); + if (index >= 0) { + if (chatAdapter != null) { + chatAdapter.notifyItemRangeChanged(index + chatAdapter.messagesStartRow, groupedMessages.messages.size()); + } + } + } + } + } + } + private void migrateToNewChat(MessageObject obj) { if (parentLayout == null) { return; @@ -10794,7 +11103,7 @@ protected void onBecomeFullyHidden() { @Override public void onTransitionAnimationStart(boolean isOpen, boolean backward) { if (isOpen) { - getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, + getNotificationCenter().setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); openAnimationEnded = false; } else { @@ -10834,7 +11143,7 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { BaseFragment fragment = parentLayout.fragmentsStack.get(a); if (fragment != this && fragment instanceof ChatActivity) { ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.dialog_id == dialog_id) { + if (chatActivity.dialog_id == dialog_id && chatActivity.inScheduleMode == inScheduleMode) { fragment.removeSelfFromStack(); break; } @@ -10898,8 +11207,14 @@ public boolean extendActionMode(Menu menu) { return true; } + private void updateScheduledInterface(boolean animated) { + if (chatActivityEnterView != null) { + chatActivityEnterView.updateScheduleButton(animated); + } + } + private void updateBottomOverlay() { - if (bottomOverlayChatText == null) { + if (bottomOverlayChatText == null || inScheduleMode) { return; } if (currentChat != null) { @@ -10999,9 +11314,15 @@ private void updateBottomOverlay() { stickersAdapter.hide(); } } - attachItem.setVisibility(View.GONE); - editTextItem.setVisibility(View.GONE); - headerItem.setVisibility(View.VISIBLE); + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } + if (editTextItem != null) { + editTextItem.setVisibility(View.GONE); + } + if (headerItem != null) { + headerItem.setVisibility(View.VISIBLE); + } } else { if (botUser != null && currentUser.bot) { bottomOverlayChat.setVisibility(View.VISIBLE); @@ -11130,7 +11451,7 @@ public void onAnimationCancel(Animator animation) { } private void updatePinnedMessageView(boolean animated) { - if (pinnedMessageView == null) { + if (pinnedMessageView == null || inScheduleMode) { return; } int pinned_msg_id; @@ -11284,7 +11605,7 @@ public void onAnimationCancel(Animator animation) { } private void updateTopPanel(boolean animated) { - if (topChatPanelView == null) { + if (topChatPanelView == null || inScheduleMode) { return; } @@ -11608,8 +11929,10 @@ public void onResume() { pinnedMessageImageView.setImage(ImageLocation.getForObject(pinnedImageLocation, pinnedImageLocationObject), "50_50", ImageLocation.getForObject(pinnedImageThumbLocation, pinnedImageLocationObject), "50_50_b", null, pinnedImageSize, pinnedImageCacheType, pinnedMessageObject); } - getNotificationsController().setOpenedDialogId(dialog_id); - getMessagesController().setLastVisibleDialogId(dialog_id, true); + if (!inScheduleMode) { + getNotificationsController().setOpenedDialogId(dialog_id); + } + getMessagesController().setLastVisibleDialogId(dialog_id, inScheduleMode, true); if (scrollToTopOnResume) { if (scrollToTopUnReadOnResume && scrollToMessage != null) { if (chatListView != null) { @@ -11690,8 +12013,10 @@ public void onPause() { MediaController.getInstance().stopRaiseToEarSensors(this, true); paused = true; wasPaused = true; - getNotificationsController().setOpenedDialogId(0); - getMessagesController().setLastVisibleDialogId(dialog_id, false); + if (!inScheduleMode) { + getNotificationsController().setOpenedDialogId(0); + } + getMessagesController().setLastVisibleDialogId(dialog_id, inScheduleMode, false); CharSequence draftMessage = null; MessageObject replyMessage = null; boolean searchWebpage = true; @@ -11714,86 +12039,88 @@ public void onPause() { if (contentView != null) { contentView.onPause(); } - CharSequence[] message = new CharSequence[] {draftMessage}; - ArrayList entities = getMediaDataController().getEntities(message); - getMediaDataController().saveDraft(dialog_id, message[0], entities, replyMessage != null ? replyMessage.messageOwner : null, !searchWebpage); + if (!inScheduleMode) { + CharSequence[] message = new CharSequence[]{draftMessage}; + ArrayList entities = getMediaDataController().getEntities(message); + getMediaDataController().saveDraft(dialog_id, message[0], entities, replyMessage != null ? replyMessage.messageOwner : null, !searchWebpage); + getMessagesController().cancelTyping(0, dialog_id); - getMessagesController().cancelTyping(0, dialog_id); - - if (!pausedOnLastMessage) { - SharedPreferences.Editor editor = MessagesController.getNotificationsSettings(currentAccount).edit(); - int messageId = 0; - int offset = 0; - if (chatLayoutManager != null) { - int position = chatLayoutManager.findFirstVisibleItemPosition(); - if (position != 0) { - RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position); - if (holder != null) { - int mid = 0; - if (holder.itemView instanceof ChatMessageCell) { - mid = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); - } else if (holder.itemView instanceof ChatActionCell) { - mid = ((ChatActionCell) holder.itemView).getMessageObject().getId(); - } - if (mid == 0) { - holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position + 1); - } - boolean ignore = false; - for (int a = position - 1; a >= chatAdapter.messagesStartRow; a--) { - int num = a - chatAdapter.messagesStartRow; - if (num < 0 || num >= messages.size()) { - continue; - } - MessageObject messageObject = messages.get(num); - if (messageObject.getId() == 0) { - continue; - } - if (!messageObject.isOut() && messageObject.isUnread()) { - ignore = true; - messageId = 0; - } - break; - } - if (holder != null && !ignore) { + if (!pausedOnLastMessage) { + SharedPreferences.Editor editor = MessagesController.getNotificationsSettings(currentAccount).edit(); + int messageId = 0; + int offset = 0; + if (chatLayoutManager != null) { + int position = chatLayoutManager.findFirstVisibleItemPosition(); + if (position != 0) { + RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position); + if (holder != null) { + int mid = 0; if (holder.itemView instanceof ChatMessageCell) { - messageId = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); + mid = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); } else if (holder.itemView instanceof ChatActionCell) { - messageId = ((ChatActionCell) holder.itemView).getMessageObject().getId(); + mid = ((ChatActionCell) holder.itemView).getMessageObject().getId(); + } + if (mid == 0) { + holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(position + 1); } - if (messageId > 0 && currentEncryptedChat == null || messageId < 0 && currentEncryptedChat != null) { - offset = holder.itemView.getBottom() - chatListView.getMeasuredHeight(); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("save offset = " + offset + " for mid " + messageId); + boolean ignore = false; + for (int a = position - 1; a >= chatAdapter.messagesStartRow; a--) { + int num = a - chatAdapter.messagesStartRow; + if (num < 0 || num >= messages.size()) { + continue; + } + MessageObject messageObject = messages.get(num); + if (messageObject.getId() == 0) { + continue; + } + if ((!messageObject.isOut() || messageObject.messageOwner.from_scheduled) && messageObject.isUnread()) { + ignore = true; + messageId = 0; + } + break; + } + if (holder != null && !ignore) { + if (holder.itemView instanceof ChatMessageCell) { + messageId = ((ChatMessageCell) holder.itemView).getMessageObject().getId(); + } else if (holder.itemView instanceof ChatActionCell) { + messageId = ((ChatActionCell) holder.itemView).getMessageObject().getId(); + } + if (messageId > 0 && currentEncryptedChat == null || messageId < 0 && currentEncryptedChat != null) { + offset = holder.itemView.getBottom() - chatListView.getMeasuredHeight(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("save offset = " + offset + " for mid " + messageId); + } + } else { + messageId = 0; } - } else { - messageId = 0; } } } } + if (messageId != 0) { + editor.putInt("diditem" + dialog_id, messageId); + editor.putInt("diditemo" + dialog_id, offset); + } else { + pausedOnLastMessage = true; + editor.remove("diditem" + dialog_id); + editor.remove("diditemo" + dialog_id); + } + editor.commit(); } - if (messageId != 0) { - editor.putInt("diditem" + dialog_id, messageId); - editor.putInt("diditemo" + dialog_id, offset); - } else { - pausedOnLastMessage = true; - editor.remove("diditem" + dialog_id); - editor.remove("diditemo" + dialog_id); + + if (currentUser != null) { + chatLeaveTime = System.currentTimeMillis(); + updateInformationForScreenshotDetector(); } - editor.commit(); - } - if (currentUser != null) { - chatLeaveTime = System.currentTimeMillis(); - updateInformationForScreenshotDetector(); - } - if (undoView != null) { - undoView.hide(true, 0); + if (undoView != null) { + undoView.hide(true, 0); + } } } private void applyDraftMaybe(boolean canClear) { - if (chatActivityEnterView == null) { + if (chatActivityEnterView == null || inScheduleMode) { return; } TLRPC.DraftMessage draftMessage = getMediaDataController().getDraft(dialog_id); @@ -12089,7 +12416,7 @@ private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant) { - AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, loadParticipant, () -> { + AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, inScheduleMode, loadParticipant, () -> { hideActionMode(); updatePinnedMessageView(true); }); @@ -12116,6 +12443,26 @@ private void createMenu(View v, boolean single, boolean listView, float x, float createMenu(v, single, listView, x, y, true); } + private CharSequence getMessageCaption(MessageObject messageObject, MessageObject.GroupedMessages group) { + if (messageObject.caption != null) { + return messageObject.caption; + } + if (group == null) { + return null; + } + CharSequence caption = null; + for (int a = 0, N = group.messages.size(); a < N; a++) { + MessageObject message = group.messages.get(a); + if (message.caption != null) { + if (caption != null) { + return null; + } + caption = message.caption; + } + } + return caption; + } + private void createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup) { if (actionBar.isActionModeShowed()) { return; @@ -12160,7 +12507,9 @@ private void createMenu(View v, boolean single, boolean listView, float x, float boolean allowChatActions = true; boolean allowPin; - if (currentChat != null) { + if (inScheduleMode) { + allowPin = false; + } else if (currentChat != null) { allowPin = message.getDialogId() != mergeDialogId && ChatObject.canPinMessages(currentChat); } else if (currentEncryptedChat == null) { if (userInfo != null) { @@ -12187,12 +12536,11 @@ private void createMenu(View v, boolean single, boolean listView, float x, float } allowEdit = captionsCount < 2; } - if (currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || + if (inScheduleMode || currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || type == 1 && (message.getDialogId() == mergeDialogId || message.needDrawBluredPreview()) || message.messageOwner.action instanceof TLRPC.TL_messageActionSecureValuesSent || currentEncryptedChat == null && message.getId() < 0 || bottomOverlayChat != null && bottomOverlayChat.getVisibility() == View.VISIBLE || - isBroadcast || currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { allowChatActions = false; } @@ -12210,7 +12558,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float selectedObjectGroup = groupedMessages; if (type == -1) { - if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || selectedObject.caption != null) { + if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); icons.add(R.drawable.msg_copy); @@ -12226,7 +12574,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(1); icons.add(R.drawable.msg_delete); } else if (type == 1) { - if (currentChat != null && !isBroadcast) { + if (currentChat != null) { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); @@ -12241,7 +12589,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(13); icons.add(R.drawable.msg_pin); } - if (allowEdit) { + if (message.canEditMessage(currentChat)) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(12); icons.add(R.drawable.msg_edit); @@ -12251,7 +12599,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(23); icons.add(R.drawable.msg_report); } - if (message.canDeleteMessage(currentChat)) { + if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); icons.add(R.drawable.msg_delete); @@ -12262,7 +12610,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(8); icons.add(R.drawable.msg_reply); } - if (message.canDeleteMessage(currentChat)) { + if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); icons.add(R.drawable.msg_delete); @@ -12280,6 +12628,11 @@ private void createMenu(View v, boolean single, boolean listView, float x, float icons.add(R.drawable.msg_delete); } else { if (currentEncryptedChat == null) { + if (inScheduleMode) { + items.add(LocaleController.getString("MessageScheduleSend", R.string.MessageScheduleSend)); + options.add(100); + icons.add(R.drawable.outline_send); + } if (selectedObject.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { TLRPC.TL_messageActionPhoneCall call = (TLRPC.TL_messageActionPhoneCall) message.messageOwner.action; items.add((call.reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || call.reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy) && !message.isOutOwner() ? LocaleController.getString("CallBack", R.string.CallBack) : LocaleController.getString("CallAgain", R.string.CallAgain)); @@ -12296,29 +12649,31 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(8); icons.add(R.drawable.msg_reply); } - if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || selectedObject.caption != null) { + if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); icons.add(R.drawable.msg_copy); } - if (ChatObject.isChannel(currentChat) && currentChat.megagroup) { + if (!inScheduleMode && ChatObject.isChannel(currentChat) && currentChat.megagroup) { items.add(LocaleController.getString("CopyLink", R.string.CopyLink)); options.add(22); icons.add(R.drawable.msg_link); } if (type == 2) { - if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { - if (message.isVoted()) { - items.add(LocaleController.getString("Unvote", R.string.Unvote)); - options.add(25); - icons.add(R.drawable.msg_unvote); - } - if (!message.isForwarded() && ( - message.isOut() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) || - ChatObject.isChannel(currentChat) && !currentChat.megagroup && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.edit_messages))) { - items.add(LocaleController.getString("StopPoll", R.string.StopPoll)); - options.add(26); - icons.add(R.drawable.msg_pollstop); + if (!inScheduleMode) { + if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { + if (message.isVoted()) { + items.add(LocaleController.getString("Unvote", R.string.Unvote)); + options.add(25); + icons.add(R.drawable.msg_unvote); + } + if (!message.isForwarded() && ( + message.isOut() && (!ChatObject.isChannel(currentChat) || currentChat.megagroup) || + ChatObject.isChannel(currentChat) && !currentChat.megagroup && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.edit_messages))) { + items.add(LocaleController.getString("StopPoll", R.string.StopPoll)); + options.add(26); + icons.add(R.drawable.msg_pollstop); + } } } } else if (type == 3) { @@ -12440,7 +12795,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float icons.add(R.drawable.msg_unfave); } } - if (!selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { + if (!inScheduleMode && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(2); icons.add(R.drawable.msg_forward); @@ -12459,12 +12814,17 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(12); icons.add(R.drawable.msg_edit); } - if (selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { + if (inScheduleMode && selectedObject.canEditMessageScheduleTime(currentChat)) { + items.add(LocaleController.getString("MessageScheduleEditTime", R.string.MessageScheduleEditTime)); + options.add(102); + icons.add(R.drawable.msg_schedule); + } + if (!inScheduleMode && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); options.add(23); icons.add(R.drawable.msg_report); } - if (message.canDeleteMessage(currentChat)) { + if (message.canDeleteMessage(inScheduleMode, currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); icons.add(R.drawable.msg_delete); @@ -12475,7 +12835,7 @@ private void createMenu(View v, boolean single, boolean listView, float x, float options.add(8); icons.add(R.drawable.msg_reply); } - if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || selectedObject.caption != null) { + if (selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); icons.add(R.drawable.msg_copy); @@ -12820,28 +13180,35 @@ private void startEditingMessageObject(MessageObject messageObject) { updatePinnedMessageView(true); updateVisibleRows(); - TLRPC.TL_messages_getMessageEditData req = new TLRPC.TL_messages_getMessageEditData(); - req.peer = getMessagesController().getInputPeer((int) dialog_id); - req.id = messageObject.getId(); - editingMessageObjectReqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - editingMessageObjectReqId = 0; - if (response == null) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("EditMessageError", R.string.EditMessageError)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); + if (!messageObject.scheduled) { + TLRPC.TL_messages_getMessageEditData req = new TLRPC.TL_messages_getMessageEditData(); + req.peer = getMessagesController().getInputPeer((int) dialog_id); + req.id = messageObject.getId(); + editingMessageObjectReqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + editingMessageObjectReqId = 0; + if (response == null) { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("EditMessageError", R.string.EditMessageError)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); - if (chatActivityEnterView != null) { - chatActivityEnterView.setEditingMessageObject(null, false); - hideFieldPanel(true); - } - } else { - if (chatActivityEnterView != null) { - chatActivityEnterView.showEditDoneProgress(false, true); + if (chatActivityEnterView != null) { + chatActivityEnterView.setEditingMessageObject(null, false); + hideFieldPanel(true); + } + } else { + if (chatActivityEnterView != null) { + chatActivityEnterView.showEditDoneProgress(false, true); + } } - } - })); + })); + } else { + chatActivityEnterView.showEditDoneProgress(false, true); + } } private void restartSticker(ChatMessageCell cell) { @@ -12923,13 +13290,15 @@ private void processSelectedOption(int option) { success = false; } } - if (success) { + if (success && !inScheduleMode) { moveScrollToLastMessage(); } } else { if (getSendMessagesHelper().retrySendMessage(selectedObject, false)) { updateVisibleRows(); - moveScrollToLastMessage(); + if (!inScheduleMode) { + moveScrollToLastMessage(); + } } } break; @@ -12957,7 +13326,12 @@ private void processSelectedOption(int option) { break; } case 3: { - AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, false)); + CharSequence caption = getMessageCaption(selectedObject, selectedObjectGroup); + if (caption != null) { + AndroidUtilities.addToClipboard(caption); + } else { + AndroidUtilities.addToClipboard(getMessageContent(selectedObject, 0, false)); + } break; } case 4: { @@ -12993,24 +13367,9 @@ private void processSelectedOption(int option) { } if (locFile != null) { if (locFile.getName().toLowerCase().endsWith("attheme")) { - if (chatLayoutManager != null) { - int lastPosition = chatLayoutManager.findFirstVisibleItemPosition(); - if (lastPosition != 0) { - scrollToPositionOnRecreate = lastPosition; - RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(scrollToPositionOnRecreate); - if (holder != null) { - scrollToOffsetOnRecreate = chatListView.getMeasuredHeight() - holder.itemView.getBottom() - chatListView.getPaddingBottom(); - } else { - scrollToPositionOnRecreate = -1; - } - } else { - scrollToPositionOnRecreate = -1; - } - } - - Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, selectedObject.getDocumentName(), true); + Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, selectedObject.getDocumentName(), null, true); if (themeInfo != null) { - presentFragment(new ThemePreviewActivity(locFile, themeInfo)); + presentFragment(new ThemePreviewActivity(themeInfo)); } else { scrollToPositionOnRecreate = -1; if (getParentActivity() == null) { @@ -13339,6 +13698,52 @@ private void processSelectedOption(int option) { showDialog(builder.create()); break; } + case 100: { + if (!checkSlowMode(chatActivityEnterView.getSendButton())) { + if (getMediaController().isPlayingMessage(selectedObject)) { + getMediaController().cleanupPlayer(true, true); + } + TLRPC.TL_messages_sendScheduledMessages req = new TLRPC.TL_messages_sendScheduledMessages(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer((int) dialog_id); + if (selectedObjectGroup != null) { + for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { + req.id.add(selectedObjectGroup.messages.get(a).getId()); + } + } else { + req.id.add(selectedObject.getId()); + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + MessagesController.getInstance(currentAccount).processUpdates(updates, false); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messagesDeleted, req.id, (int) -dialog_id, true)); + } else if (error.text != null) { + AndroidUtilities.runOnUIThread(() -> { + if (error.text.startsWith("SLOWMODE_WAIT_")) { + AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString("SlowmodeSendError", R.string.SlowmodeSendError)); + } else if (error.text.equals("CHAT_SEND_MEDIA_FORBIDDEN")) { + AlertsCreator.showSimpleToast(ChatActivity.this, LocaleController.getString("AttachMediaRestrictedForever", R.string.AttachMediaRestrictedForever)); + } else { + AlertsCreator.showSimpleToast(ChatActivity.this, error.text); + } + }); + } + }); + break; + } + } + case 102: { + MessageObject message = selectedObject; + MessageObject.GroupedMessages group = selectedObjectGroup; + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(currentUser), message.messageOwner.date, (notify, scheduleDate) -> { + if (group != null) { + SendMessagesHelper.getInstance(currentAccount).editMessage(group.messages.get(0), null, false, ChatActivity.this, null, scheduleDate, null); + } else { + SendMessagesHelper.getInstance(currentAccount).editMessage(message, null, false, ChatActivity.this, null, scheduleDate, null); + } + }, null); + break; + } } selectedObject = null; selectedObjectGroup = null; @@ -13385,9 +13790,9 @@ public void didSelectDialogs(DialogsActivity fragment, ArrayList dids, Cha for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { - getSendMessagesHelper().sendMessage(message.toString(), did, null, null, true, null, null, null); + getSendMessagesHelper().sendMessage(message.toString(), did, null, null, true, null, null, null, true, 0); } - getSendMessagesHelper().sendMessage(fmessages, did); + getSendMessagesHelper().sendMessage(fmessages, did, true, 0); } fragment.finishFragment(); } else { @@ -13547,7 +13952,7 @@ private void checkEditTimer() { return; } MessageObject messageObject = chatActivityEnterView.getEditingMessageObject(); - if (messageObject == null) { + if (messageObject == null || messageObject.scheduled) { return; } if (currentUser != null && currentUser.self) { @@ -13623,12 +14028,13 @@ private void openSearchWithText(String text) { } @Override - public void didSelectLocation(TLRPC.MessageMedia location, int live) { - getSendMessagesHelper().sendMessage(location, dialog_id, replyingMessageObject, null, null); - moveScrollToLastMessage(); + public void didSelectLocation(TLRPC.MessageMedia location, int live, boolean notify, int scheduleDate) { + getSendMessagesHelper().sendMessage(location, dialog_id, replyingMessageObject, null, null, notify, scheduleDate); + if (!inScheduleMode) { + moveScrollToLastMessage(); + } if (live == 1) { - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + afterMessageSend(); } if (paused) { scrollToTopOnResume = true; @@ -13643,6 +14049,14 @@ public boolean isSecretChat() { return currentEncryptedChat != null; } + public boolean canScheduleMessage() { + return currentEncryptedChat == null && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE); + } + + public boolean isInScheduleMode() { + return inScheduleMode; + } + public TLRPC.User getCurrentUser() { return currentUser; } @@ -13667,28 +14081,25 @@ public TLRPC.UserFull getCurrentUserInfo() { return userInfo; } - public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo videoEditedInfo) { + public void sendMedia(MediaController.PhotoEntry photoEntry, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { if (photoEntry == null) { return; } fillEditingMediaWithCaption(photoEntry.caption, photoEntry.entities); if (photoEntry.isVideo) { if (videoEditedInfo != null) { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo.estimatedSize, videoEditedInfo.estimatedDuration, videoEditedInfo.resultWidth, videoEditedInfo.resultHeight, videoEditedInfo, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo.estimatedSize, videoEditedInfo.estimatedDuration, videoEditedInfo.resultWidth, videoEditedInfo.resultHeight, videoEditedInfo, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate); } else { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate); } - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + afterMessageSend(); } else { if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, notify, scheduleDate); + afterMessageSend(); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject); - hideFieldPanel(false); - getMediaDataController().cleanDraft(dialog_id, true); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, notify, scheduleDate); + afterMessageSend(); } } } @@ -13938,7 +14349,7 @@ public void updateRows() { rowCount += messages.size(); messagesEndRow = rowCount; - if (currentUser != null && currentUser.bot) { + if (currentUser != null && currentUser.bot && !inScheduleMode) { botInfoRow = rowCount++; } else { botInfoRow = -1; @@ -13955,7 +14366,7 @@ public void updateRows() { messagesStartRow = -1; messagesEndRow = -1; - if (currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser)) { + if (currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && !inScheduleMode) { botInfoRow = rowCount++; } else { botInfoRow = -1; @@ -14111,6 +14522,11 @@ public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) chatActivityEnterView.didPressedBotButton(button, cell.getMessageObject(), cell.getMessageObject()); } + @Override + public void didPressReaction(ChatMessageCell cell, TLRPC.TL_reactionCount reaction) { + getSendMessagesHelper().sendReaction(cell.getMessageObject(), reaction.reaction, ChatActivity.this); + } + @Override public void didPressVoteButton(ChatMessageCell cell, TLRPC.TL_pollAnswer button) { getSendMessagesHelper().sendVote(cell.getMessageObject(), button, null); @@ -14259,7 +14675,12 @@ public void needOpenWebView(String url, String title, String description, String @Override public void didPressReplyMessage(ChatMessageCell cell, int id) { MessageObject messageObject = cell.getMessageObject(); - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, false); + if (inScheduleMode) { + chatActivityDelegate.openReplyMessage(id); + finishFragment(); + } else { + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, false); + } } @Override @@ -14319,8 +14740,20 @@ void openPhotoViewerForMessage(ChatMessageCell cell, MessageObject message) { } MediaController.getInstance().cleanupPlayer(true, true, false, playingObject.equals(message)); } - if (PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider)) { + if (inScheduleMode && (message.isVideo() || message.type == 1)) { PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); + ArrayList arrayList = new ArrayList<>(); + for (int a = 0, N = messages.size(); a < N; a++) { + MessageObject m = messages.get(a); + if (m.isVideo() || m.type == 1) { + arrayList.add(0, m); + } + } + PhotoViewer.getInstance().openPhoto(arrayList, arrayList.indexOf(message), dialog_id, 0, photoViewerProvider); + } else { + if (PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider)) { + PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); + } } if (noSoundHintView != null) { noSoundHintView.hide(); @@ -14407,23 +14840,9 @@ public void didPressImage(ChatMessageCell cell, float x, float y) { locFile = f; } } - if (chatLayoutManager != null) { - int lastPosition = chatLayoutManager.findFirstVisibleItemPosition(); - if (lastPosition != 0) { - scrollToPositionOnRecreate = lastPosition; - RecyclerListView.Holder holder = (RecyclerListView.Holder) chatListView.findViewHolderForAdapterPosition(scrollToPositionOnRecreate); - if (holder != null) { - scrollToOffsetOnRecreate = chatListView.getMeasuredHeight() - holder.itemView.getBottom() - chatListView.getPaddingBottom(); - } else { - scrollToPositionOnRecreate = -1; - } - } else { - scrollToPositionOnRecreate = -1; - } - } - Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), true); + Theme.ThemeInfo themeInfo = Theme.applyThemeFile(locFile, message.getDocumentName(), null, true); if (themeInfo != null) { - presentFragment(new ThemePreviewActivity(locFile, themeInfo)); + presentFragment(new ThemePreviewActivity(themeInfo)); return; } else { scrollToPositionOnRecreate = -1; @@ -14614,7 +15033,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } int nextType = getItemViewType(nextPosition); int prevType = getItemViewType(prevPosition); - if (!(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { + if (!message.hasReactions() && !(message.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && nextType == holder.getItemViewType()) { MessageObject nextMessage = messages.get(nextPosition - messagesStartRow); pinnedBottom = nextMessage.isOutOwner() == message.isOutOwner() && Math.abs(nextMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; if (pinnedBottom) { @@ -14627,7 +15046,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } if (prevType == holder.getItemViewType()) { MessageObject prevMessage = messages.get(prevPosition - messagesStartRow); - pinnedTop = !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; + pinnedTop = !prevMessage.hasReactions() && !(prevMessage.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) && prevMessage.isOutOwner() == message.isOutOwner() && Math.abs(prevMessage.messageOwner.date - message.messageOwner.date) <= 5 * 60; if (pinnedTop) { if (currentChat != null) { pinnedTop = prevMessage.messageOwner.from_id == message.messageOwner.from_id; @@ -14810,7 +15229,7 @@ public boolean onPreDraw() { MessageObject message = messages.get(position - messagesStartRow); View view = holder.itemView; if (message != null && message.messageOwner != null && message.messageOwner.media_unread && message.messageOwner.mentioned) { - if (!inPreviewMode) { + if (!inPreviewMode && !inScheduleMode) { if (!message.isVoice() && !message.isRoundVideo()) { newMentionsCount--; if (newMentionsCount <= 0) { @@ -14969,6 +15388,7 @@ public ThemeDescription[] getThemeDescriptions() { }; return new ThemeDescription[]{ new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper), + new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_chat_wallpaper_gradient_to), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), new ThemeDescription(chatListView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault), @@ -14998,7 +15418,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, 0, null, null, new Drawable[]{Theme.chat_muteIconDrawable}, null, Theme.key_chat_muteIcon), new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, 0, null, null, new Drawable[]{Theme.chat_lockIconDrawable}, null, Theme.key_chat_lockIcon), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundRed), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundOrange), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_avatar_backgroundViolet), @@ -15031,8 +15451,10 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class, BotHelpCell.class}, null, null, null, Theme.key_chat_messageLinkIn, null), new ThemeDescription(chatListView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageLinkOut, null), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgNoSoundDrawable}, null, Theme.key_chat_mediaTimeText), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck), - new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead), + new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutClockDrawable}, null, Theme.key_chat_outSentClock), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutSelectedClockDrawable}, null, Theme.key_chat_outSentClockSelected), new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgInClockDrawable}, null, Theme.key_chat_inSentClock), @@ -15204,6 +15626,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(chatActivityEnterView, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_BACKGROUND, new Class[]{ChatActivityEnterView.class}, new String[]{"audioVideoButtonContainer"}, null, null, null, Theme.key_chat_messagePanelBackground), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelText), + new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_CURSORCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelCursor), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"recordSendText"}, null, null, null, Theme.key_chat_fieldOverlayText), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_HINTTEXTCOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"messageEditText"}, null, null, null, Theme.key_chat_messagePanelHint), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"sendButton"}, null, null, null, Theme.key_chat_messagePanelSend), @@ -15212,10 +15635,13 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"emojiButton"}, null, null, null, Theme.key_chat_messagePanelIcons), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"botButton"}, null, null, null, Theme.key_chat_messagePanelIcons), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"notifyButton"}, null, null, null, Theme.key_chat_messagePanelIcons), + new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_chat_messagePanelIcons), + new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"scheduledButton"}, null, null, null, Theme.key_chat_recordedVoiceDot), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"attachButton"}, null, null, null, Theme.key_chat_messagePanelIcons), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"audioSendButton"}, null, null, null, Theme.key_chat_messagePanelIcons), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"videoSendButton"}, null, null, null, Theme.key_chat_messagePanelIcons), - new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR | ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonImage"}, null, null, null, Theme.key_chat_messagePanelSend), + new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"notifyButton"}, null, null, null, Theme.key_chat_messagePanelVideoFrame), + new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"videoTimelineView"}, null, null, null, Theme.key_chat_messagePanelSend), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonImage"}, null, null, null, Theme.key_chat_messagePanelBackground), new ThemeDescription(chatActivityEnterView, ThemeDescription.FLAG_BACKGROUND, new Class[]{ChatActivityEnterView.class}, new String[]{"recordedAudioPanel"}, null, null, null, Theme.key_chat_messagePanelBackground), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"micDrawable"}, null, null, null, Theme.key_chat_messagePanelVoicePressed), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index 933d7ad6dc8..1b67c8f5d10 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -391,7 +391,7 @@ public void invalidate(int l, int t, int r, int b) { frameLayout.addView(avatarImage, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12)); if (ChatObject.canChangeChatInfo(currentChat)) { - avatarDrawable.setInfo(5, null, null, false); + avatarDrawable.setInfo(5, null, null); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(0x55000000); @@ -441,7 +441,7 @@ public void invalidate() { showAvatarProgress(false, false); } else { - avatarDrawable.setInfo(5, currentChat.title, null, false); + avatarDrawable.setInfo(5, currentChat.title, null); } nameTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT); @@ -526,7 +526,7 @@ public void afterTextChanged(Editable editable) { if (info != null && info.location instanceof TLRPC.TL_channelLocation) { fragment.setInitialLocation((TLRPC.TL_channelLocation) info.location); } - fragment.setDelegate((location, live) -> { + fragment.setDelegate((location, live, notify, scheduleDate) -> { TLRPC.TL_channelLocation channelLocation = new TLRPC.TL_channelLocation(); channelLocation.address = location.address; channelLocation.geo_point = location.geo; @@ -1199,7 +1199,7 @@ private void updateFields(boolean updateChat) { public ThemeDescription[] getThemeDescriptions() { ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { if (avatarImage != null) { - avatarDrawable.setInfo(5, null, null, false); + avatarDrawable.setInfo(5, null, null); avatarImage.invalidate(); } }; @@ -1266,7 +1266,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(stickersInfoCell3, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), new ThemeDescription(stickersInfoCell3, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java index ac654a6658a..528839fba82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java @@ -803,7 +803,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_LINKCOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText), new ThemeDescription(adminnedChannelsLayout, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{AdminedChannelCell.class}, new String[]{"deleteButton"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java index 69f4a134ed9..3bf08541556 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java @@ -856,7 +856,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index b160faab0d7..6a53fadcb0f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -732,7 +732,7 @@ private void initTransfer(TLRPC.InputCheckPasswordSRP srp, TwoStepVerificationAc passwordFragment.needHideProgress(); passwordFragment.finishFragment(); } - AlertsCreator.showAddUserAlert(error.text, ChatRightsEditActivity.this, isChannel); + AlertsCreator.showAddUserAlert(error.text, ChatRightsEditActivity.this, isChannel, req); } } else { if (srp != null) { @@ -1314,7 +1314,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 07d92627dd0..52d20dc06db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -2845,7 +2845,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java index 7c73847b61f..7c610bd3874 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java @@ -278,7 +278,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Paint[]{Theme.dialogs_namePaint, Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name), new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Paint[]{Theme.dialogs_nameEncryptedPaint, Theme.dialogs_searchNameEncryptedPaint}, null, null, Theme.key_chats_secretName), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), 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 611735eb8c8..47809f43004 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -106,7 +106,7 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base request instanceof TLRPC.TL_messages_editChatAdmin || request instanceof TLRPC.TL_messages_migrateChat) { if (fragment != null) { - AlertsCreator.showAddUserAlert(error.text, fragment, args != null && args.length > 0 ? (Boolean) args[0] : false); + AlertsCreator.showAddUserAlert(error.text, fragment, args != null && args.length > 0 ? (Boolean) args[0] : false, request); } else { if (error.text.equals("PEER_FLOOD")) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 1); @@ -116,13 +116,13 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base if (error.text.startsWith("FLOOD_WAIT")) { AlertsCreator.showFloodWaitAlert(error.text, fragment); } else { - AlertsCreator.showAddUserAlert(error.text, fragment, false); + AlertsCreator.showAddUserAlert(error.text, fragment, false, request); } } else if (request instanceof TLRPC.TL_channels_createChannel) { if (error.text.startsWith("FLOOD_WAIT")) { AlertsCreator.showFloodWaitAlert(error.text, fragment); } else { - AlertsCreator.showAddUserAlert(error.text, fragment, false); + AlertsCreator.showAddUserAlert(error.text, fragment, false, request); } } else if (request instanceof TLRPC.TL_messages_editMessage) { if (!error.text.equals("MESSAGE_NOT_MODIFIED")) { @@ -134,14 +134,20 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base } } else if (request instanceof TLRPC.TL_messages_sendMessage || request instanceof TLRPC.TL_messages_sendMedia || - request instanceof TLRPC.TL_messages_sendBroadcast || request instanceof TLRPC.TL_messages_sendInlineBotResult || request instanceof TLRPC.TL_messages_forwardMessages || - request instanceof TLRPC.TL_messages_sendMultiMedia) { - if (error.text.equals("PEER_FLOOD")) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 0); - } else if (error.text.equals("USER_BANNED_IN_CHANNEL")) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 5); + request instanceof TLRPC.TL_messages_sendMultiMedia || + request instanceof TLRPC.TL_messages_sendScheduledMessages) { + switch (error.text) { + case "PEER_FLOOD": + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 0); + break; + case "USER_BANNED_IN_CHANNEL": + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 5); + break; + case "SCHEDULE_TOO_MUCH": + showSimpleToast(fragment, LocaleController.getString("MessageScheduledLimitReached", R.string.MessageScheduledLimitReached)); + break; } } else if (request instanceof TLRPC.TL_messages_importChatInvite) { if (error.text.startsWith("FLOOD_WAIT")) { @@ -1174,6 +1180,218 @@ public static AlertDialog.Builder createDatePickerDialog(Context context, int mi return builder; } + private static boolean checkScheduleDate(TextView button, boolean reminder, NumberPicker dayPicker, NumberPicker hourPicker, NumberPicker minutePicker) { + int day = dayPicker.getValue(); + int hour = hourPicker.getValue(); + int minute = minutePicker.getValue(); + + Calendar calendar = Calendar.getInstance(); + long systemTime = System.currentTimeMillis(); + calendar.setTimeInMillis(systemTime); + int currentYear = calendar.get(Calendar.YEAR); + int currentDay = calendar.get(Calendar.DAY_OF_YEAR); + + calendar.setTimeInMillis(System.currentTimeMillis() + (long) day * 24 * 3600 * 1000); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + long currentTime = calendar.getTimeInMillis(); + + if (currentTime <= systemTime + 60000L) { + calendar.setTimeInMillis(systemTime + 60000L); + if (currentDay != calendar.get(Calendar.DAY_OF_YEAR)) { + dayPicker.setValue(day = 1); + } + hourPicker.setValue(hour = calendar.get(Calendar.HOUR_OF_DAY)); + minutePicker.setValue(minute = calendar.get(Calendar.MINUTE)); + } + int selectedYear = calendar.get(Calendar.YEAR); + + calendar.setTimeInMillis(System.currentTimeMillis() + (long) day * 24 * 3600 * 1000); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + + if (button != null) { + long time = calendar.getTimeInMillis(); + int num; + if (day == 0) { + num = 0; + } else if (currentYear == selectedYear) { + num = 1; + } else { + num = 2; + } + if (reminder) { + num += 3; + } + button.setText(LocaleController.getInstance().formatterScheduleSend[num].format(time)); + } + return currentTime - systemTime > 60000L; + } + + public interface ScheduleDatePickerDelegate { + void didSelectDate(boolean notify, int scheduleDate); + } + + public static BottomSheet.Builder createScheduleDatePickerDialog(Context context, boolean reminder, final ScheduleDatePickerDelegate datePickerDelegate) { + return createScheduleDatePickerDialog(context, reminder, -1, datePickerDelegate, null); + } + + public static BottomSheet.Builder createScheduleDatePickerDialog(Context context, boolean reminder, final ScheduleDatePickerDelegate datePickerDelegate, final Runnable cancelRunnable) { + return createScheduleDatePickerDialog(context, reminder, -1, datePickerDelegate, cancelRunnable); + } + + public static BottomSheet.Builder createScheduleDatePickerDialog(Context context, boolean reminder, long currentDate, final ScheduleDatePickerDelegate datePickerDelegate, final Runnable cancelRunnable) { + if (context == null) { + return null; + } + + BottomSheet.Builder builder = new BottomSheet.Builder(context, false, 1); + builder.setApplyBottomPadding(false); + + final NumberPicker dayPicker = new NumberPicker(context); + dayPicker.setTextOffset(AndroidUtilities.dp(10)); + dayPicker.setItemCount(5); + final NumberPicker hourPicker = new NumberPicker(context); + hourPicker.setItemCount(5); + hourPicker.setTextOffset(-AndroidUtilities.dp(10)); + final NumberPicker minutePicker = new NumberPicker(context); + minutePicker.setItemCount(5); + minutePicker.setTextOffset(-AndroidUtilities.dp(34)); + + LinearLayout container = new LinearLayout(context) { + + boolean ignoreLayout = false; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + ignoreLayout = true; + int count; + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + count = 3; + } else { + count = 5; + } + dayPicker.setItemCount(count); + hourPicker.setItemCount(count); + minutePicker.setItemCount(count); + dayPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count; + hourPicker.getLayoutParams().height = AndroidUtilities.dp(54) * count; + minutePicker.getLayoutParams().height = AndroidUtilities.dp(54) * count; + ignoreLayout = false; + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + container.setOrientation(LinearLayout.VERTICAL); + + TextView titleView = new TextView(context); + titleView.setText(reminder ? LocaleController.getString("SetReminder", R.string.SetReminder) : LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage)); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + container.addView(titleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 12, 22, 4)); + titleView.setOnTouchListener((v, event) -> true); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + linearLayout.setWeightSum(1.0f); + container.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + + long currentTime = System.currentTimeMillis(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(currentTime); + int currentYear = calendar.get(Calendar.YEAR); + + TextView buttonTextView = new TextView(context); + + linearLayout.addView(dayPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f)); + dayPicker.setMinValue(0); + dayPicker.setMaxValue(365); + dayPicker.setWrapSelectorWheel(false); + dayPicker.setFormatter(value -> { + if (value == 0) { + return LocaleController.getString("MessageScheduleToday", R.string.MessageScheduleToday); + } else { + long date = currentTime + (long) value * 86400000L; + calendar.setTimeInMillis(date); + int year = calendar.get(Calendar.YEAR); + if (year == currentYear) { + return LocaleController.getInstance().formatterScheduleDay.format(date); + } else { + return LocaleController.getInstance().formatterScheduleYear.format(date); + } + } + }); + final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> checkScheduleDate(buttonTextView, reminder, dayPicker, hourPicker, minutePicker); + dayPicker.setOnValueChangedListener(onValueChangeListener); + + hourPicker.setMinValue(0); + hourPicker.setMaxValue(23); + linearLayout.addView(hourPicker, LayoutHelper.createLinear(0, 54 * 5, 0.2f)); + hourPicker.setFormatter(value -> String.format("%02d", value)); + hourPicker.setOnValueChangedListener(onValueChangeListener); + + minutePicker.setMinValue(0); + minutePicker.setMaxValue(59); + minutePicker.setValue(0); + minutePicker.setFormatter(value -> String.format("%02d", value)); + linearLayout.addView(minutePicker, LayoutHelper.createLinear(0, 54 * 5, 0.3f)); + minutePicker.setOnValueChangedListener(onValueChangeListener); + + if (currentDate > 0) { + currentDate *= 1000; + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.HOUR_OF_DAY, 0); + int days = (int) ((currentDate - calendar.getTimeInMillis()) / (24 * 60 * 60 * 1000)); + calendar.setTimeInMillis(currentDate); + if (days >= 0) { + minutePicker.setValue(calendar.get(Calendar.MINUTE)); + hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY)); + dayPicker.setValue(days); + } + } + final boolean[] canceled = {true}; + + checkScheduleDate(buttonTextView, reminder, dayPicker, hourPicker, minutePicker); + + buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16)); + buttonTextView.setOnClickListener(v -> { + canceled[0] = false; + boolean setSeconds = checkScheduleDate(null, reminder, dayPicker, hourPicker, minutePicker); + calendar.setTimeInMillis(System.currentTimeMillis() + (long) dayPicker.getValue() * 24 * 3600 * 1000); + calendar.set(Calendar.HOUR_OF_DAY, hourPicker.getValue()); + calendar.set(Calendar.MINUTE, minutePicker.getValue()); + if (setSeconds) { + calendar.set(Calendar.SECOND, 0); + } + datePickerDelegate.didSelectDate(true, (int) (calendar.getTimeInMillis() / 1000)); + builder.getDismissRunnable().run(); + }); + + builder.setCustomView(container); + builder.show().setOnDismissListener(dialog -> { + if (cancelRunnable != null && canceled[0]) { + cancelRunnable.run(); + } + }); + return builder; + } + public static Dialog createMuteAlert(Context context, final long dialog_id) { if (context == null) { return null; @@ -1320,7 +1538,7 @@ public static void showSendMediaAlert(int result, final BaseFragment fragment) { fragment.showDialog(builder.create(), true, null); } - public static void showAddUserAlert(String error, final BaseFragment fragment, boolean isChannel) { + public static void showAddUserAlert(String error, final BaseFragment fragment, boolean isChannel, TLObject request) { if (error == null || fragment == null || fragment.getParentActivity() == null) { return; } @@ -1401,7 +1619,11 @@ public static void showAddUserAlert(String error, final BaseFragment fragment, b builder.setMessage(LocaleController.getString("LocatedChannelsTooMuch", R.string.LocatedChannelsTooMuch)); break; case "CHANNELS_TOO_MUCH": - builder.setMessage(LocaleController.getString("ChannelTooMuch", R.string.ChannelTooMuch)); + if (request instanceof TLRPC.TL_channels_createChannel) { + builder.setMessage(LocaleController.getString("ChannelTooMuch", R.string.ChannelTooMuch)); + } else { + builder.setMessage(LocaleController.getString("ChannelTooMuchJoin", R.string.ChannelTooMuchJoin)); + } break; default: builder.setMessage(LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error); @@ -2080,7 +2302,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 loadParticipant, Runnable onDelete) { + 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, boolean scheduled, int loadParticipant, Runnable onDelete) { if (fragment == null || user == null && chat == null && encryptedChat == null) { return; } @@ -2100,6 +2322,15 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u count = selectedMessages[0].size() + selectedMessages[1].size(); } + long dialogId; + if (encryptedChat != null) { + dialogId = ((long) encryptedChat.id) << 32; + } else if (user != null) { + dialogId = user.id; + } else { + dialogId = -chat.id; + } + final boolean[] checks = new boolean[3]; final boolean[] deleteForAll = new boolean[1]; TLRPC.User actionUser = null; @@ -2114,7 +2345,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u boolean hasNotOut = false; int myMessagesCount = 0; boolean canDeleteInbox = encryptedChat == null && user != null && canRevokeInbox && revokeTimeLimit == 0x7fffffff; - if (chat != null && chat.megagroup) { + if (chat != null && chat.megagroup && !scheduled) { boolean canBan = ChatObject.canBlockUsers(chat); int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); if (selectedMessage != null) { @@ -2183,7 +2414,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u loadType = 0; } } - createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, loadType, onDelete); + createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, scheduled, loadType, onDelete); })); AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { @@ -2246,7 +2477,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u } else { actionUser = null; } - } else if (!ChatObject.isChannel(chat) && encryptedChat == null) { + } else if (!scheduled && !ChatObject.isChannel(chat) && encryptedChat == null) { int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && !user.bot || chat != null) { if (selectedMessage != null) { @@ -2321,7 +2552,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u random_ids.add(selectedMessage.messageOwner.random_id); } } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, selectedMessage.messageOwner.to_id.channel_id, deleteForAll[0]); + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, dialogId, selectedMessage.messageOwner.to_id.channel_id, deleteForAll[0], scheduled); } else { for (int a = 1; a >= 0; a--) { ids = new ArrayList<>(); @@ -2345,7 +2576,7 @@ public static void createDeleteMessagesAlert(BaseFragment fragment, TLRPC.User u } } } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, channelId, deleteForAll[0]); + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, dialogId, channelId, deleteForAll[0], scheduled); selectedMessages[a].clear(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java index 8c6a775cc0b..92e310612db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -736,9 +736,9 @@ private void onSubItemClick(int id) { for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, true, 0); } fragment1.finishFragment(); } else { @@ -821,19 +821,15 @@ private void onSubItemClick(int id) { int lower_part = (int) did; int high_id = (int) (did >> 32); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); - if (chat != null && chat.migrated_to != null) { - args.putInt("migrated_to", lower_part); - lower_part = -chat.migrated_to.channel_id; - } - args.putInt("chat_id", -lower_part); + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); + if (chat != null && chat.migrated_to != null) { + args.putInt("migrated_to", lower_part); + lower_part = -chat.migrated_to.channel_id; } + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index 5325ed8db47..d8c71ed2f4c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -29,12 +29,12 @@ public class AvatarDrawable extends Drawable { private TextPaint namePaint; private int color; + private boolean needApplyColorAccent; private StaticLayout textLayout; private float textWidth; private float textHeight; private float textLeft; private boolean isProfile; - private boolean drawBrodcast; private boolean drawDeleted; private int avatarType; private float archivedAvatarProgress; @@ -65,7 +65,7 @@ public AvatarDrawable(TLRPC.User user, boolean profile) { this(); isProfile = profile; if (user != null) { - setInfo(user.id, user.first_name, user.last_name, false, null); + setInfo(user.id, user.first_name, user.last_name, null); drawDeleted = UserObject.isDeleted(user); } } @@ -74,7 +74,7 @@ public AvatarDrawable(TLRPC.Chat chat, boolean profile) { this(); isProfile = profile; if (chat != null) { - setInfo(chat.id, chat.title, null, chat.id < 0, null); + setInfo(chat.id, chat.title, null, null); } } @@ -82,7 +82,7 @@ public void setProfile(boolean value) { isProfile = value; } - public static int getColorIndex(int id) { + private static int getColorIndex(int id) { if (id >= 0 && id < 7) { return id; } @@ -119,7 +119,7 @@ public static int getNameColorForId(int id) { public void setInfo(TLRPC.User user) { if (user != null) { - setInfo(user.id, user.first_name, user.last_name, false, null); + setInfo(user.id, user.first_name, user.last_name, null); drawDeleted = UserObject.isDeleted(user); } } @@ -131,6 +131,7 @@ public void setAvatarType(int value) { } else { color = Theme.getColor(Theme.key_avatar_backgroundSaved); } + needApplyColorAccent = false; } public void setArchivedAvatarHiddenProgress(float progress) { @@ -143,34 +144,35 @@ public int getAvatarType() { public void setInfo(TLRPC.Chat chat) { if (chat != null) { - setInfo(chat.id, chat.title, null, chat.id < 0, null); + setInfo(chat.id, chat.title, null, null); } } public void setColor(int value) { color = value; + needApplyColorAccent = false; } public void setTextSize(int size) { namePaint.setTextSize(size); } - public void setInfo(int id, String firstName, String lastName, boolean isBroadcast) { - setInfo(id, firstName, lastName, isBroadcast, null); + public void setInfo(int id, String firstName, String lastName) { + setInfo(id, firstName, lastName, null); } public int getColor() { - return color; + return needApplyColorAccent ? Theme.changeColorAccent(color) : color; } - public void setInfo(int id, String firstName, String lastName, boolean isBroadcast, String custom) { + public void setInfo(int id, String firstName, String lastName, String custom) { if (isProfile) { color = getProfileColorForId(id); } else { color = getColorForId(id); } + needApplyColorAccent = id == 5; // Tinting manually set blue color - drawBrodcast = isBroadcast; avatarType = AVATAR_TYPE_NORMAL; drawDeleted = false; @@ -238,7 +240,7 @@ public void draw(Canvas canvas) { } int size = bounds.width(); namePaint.setColor(Theme.getColor(Theme.key_avatar_text)); - Theme.avatar_backgroundPaint.setColor(color); + Theme.avatar_backgroundPaint.setColor(getColor()); canvas.save(); canvas.translate(bounds.left, bounds.top); canvas.drawCircle(size / 2.0f, size / 2.0f, size / 2.0f, Theme.avatar_backgroundPaint); @@ -282,11 +284,6 @@ public void draw(Canvas canvas) { int y = (size - h) / 2; Theme.avatar_savedDrawable.setBounds(x, y, x + w, y + h); Theme.avatar_savedDrawable.draw(canvas); - } else if (drawBrodcast && Theme.avatar_broadcastDrawable != null) { - int x = (size - Theme.avatar_broadcastDrawable.getIntrinsicWidth()) / 2; - int y = (size - Theme.avatar_broadcastDrawable.getIntrinsicHeight()) / 2; - Theme.avatar_broadcastDrawable.setBounds(x, y, x + Theme.avatar_broadcastDrawable.getIntrinsicWidth(), y + Theme.avatar_broadcastDrawable.getIntrinsicHeight()); - Theme.avatar_broadcastDrawable.draw(canvas); } else if (drawDeleted && Theme.avatar_ghostDrawable != null) { int x = (size - Theme.avatar_ghostDrawable.getIntrinsicWidth()) / 2; int y = (size - Theme.avatar_ghostDrawable.getIntrinsicHeight()) / 2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackgroundGradientDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackgroundGradientDrawable.java new file mode 100644 index 00000000000..efb4eeedf6d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackgroundGradientDrawable.java @@ -0,0 +1,20 @@ +package org.telegram.ui.Components; + +import android.graphics.drawable.GradientDrawable; + +import androidx.annotation.Nullable; + +public class BackgroundGradientDrawable extends GradientDrawable { + + private int[] colors; + + public BackgroundGradientDrawable(Orientation orientation, int[] colors) { + super(orientation, colors); + this.colors = colors; + } + + @Nullable + public int[] getColorsList() { + return colors; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java index 611757886ff..ac6638b9528 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java @@ -170,7 +170,7 @@ public void setVisibility(int visibility) { super.setVisibility(visibility); if (visibility == GONE) { NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.FileLoadProgressChanged); } } @@ -183,7 +183,7 @@ public void didReceivedNotification(int id, int account, Object... args) { showProgress(false); openApkInstall((Activity) getContext(), appUpdate.document); } - } else if (id == NotificationCenter.fileDidFailedLoad) { + } else if (id == NotificationCenter.fileDidFailToLoad) { String location = (String) args[0]; if (fileName != null && fileName.equals(location)) { showProgress(false); @@ -311,7 +311,7 @@ public void show(int account, TLRPC.TL_help_appUpdate update, boolean check) { acceptTextView.setText(LocaleController.getString("Update", R.string.Update).toUpperCase()); } NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.FileLoadProgressChanged); if (check) { TLRPC.TL_help_getAppUpdate req = new TLRPC.TL_help_getAppUpdate(); 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 41457a5250a..9ec4d00baa1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -40,6 +40,7 @@ import androidx.core.os.BuildCompat; import androidx.core.view.ViewCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.core.view.inputmethod.InputContentInfoCompat; import androidx.customview.widget.ExploreByTouchHelper; import android.os.SystemClock; @@ -114,7 +115,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { public interface ChatActivityEnterViewDelegate { - void onMessageSend(CharSequence message); + void onMessageSend(CharSequence message, boolean notify, int scheduleDate); void needSendTyping(); void onTextChanged(CharSequence text, boolean bigChange); void onTextSelectionChanged(int start, int end); @@ -125,7 +126,7 @@ public interface ChatActivityEnterViewDelegate { void onStickersTab(boolean opened); void onMessageEditEnd(boolean loading); void didPressedAttachButton(); - void needStartRecordVideo(int state); + void needStartRecordVideo(int state, boolean notify, int scheduleDate); void needChangeVideoPreviewState(int state, float seekProgress); void onSwitchRecordMode(boolean video); void onPreAudioVideoRecord(); @@ -136,6 +137,12 @@ public interface ChatActivityEnterViewDelegate { default void scrollToSendingMessage() { } + default void openScheduledMessages() { + + } + default boolean hasScheduledMessages() { + return true; + } } private int currentAccount = UserConfig.selectedAccount; @@ -261,6 +268,9 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo i private View topLineView; private BotKeyboardView botKeyboardView; private ImageView notifyButton; + private ImageView scheduledButton; + private boolean scheduleButtonHidden; + private AnimatorSet scheduledButtonAnimation; private RecordCircle recordCircle; private CloseProgressDrawable2 progressDrawable; private Paint dotPaint; @@ -311,6 +321,7 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo i private float startedDraggingX = -1; private float distCanMove = AndroidUtilities.dp(80); private boolean recordingAudioVideo; + private int recordingGuid; private boolean forceShowSendButton; private boolean allowStickers; private boolean allowGifs; @@ -431,7 +442,7 @@ public void set(RecordCircle object, Float value) { @Override public void run() { if (delegate != null) { - delegate.needStartRecordVideo(0); + delegate.needStartRecordVideo(0, true, 0); } } }; @@ -483,7 +494,7 @@ public void run() { } delegate.needStartRecordAudio(1); startedDraggingX = -1; - MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject); + MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, recordingGuid); updateRecordIntefrace(); audioVideoButtonContainer.getParent().requestDisallowInterceptTouchEvent(true); } @@ -657,9 +668,9 @@ public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (lockBackgroundDrawable.getBounds().contains(x, y)) { if (videoSendButton != null && videoSendButton.getTag() != null) { - delegate.needStartRecordVideo(3); + delegate.needStartRecordVideo(3, true, 0); } else { - MediaController.getInstance().stopRecording(2); + MediaController.getInstance().stopRecording(2, true, 0); delegate.needStartRecordAudio(0); } } @@ -851,6 +862,9 @@ public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, C parentActivity = context; parentFragment = fragment; + if (fragment != null) { + recordingGuid = parentFragment.getClassGuid(); + } sizeNotifierLayout = parent; sizeNotifierLayout.setDelegate(this); SharedPreferences preferences = MessagesController.getGlobalMainSettings(); @@ -862,7 +876,16 @@ public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, C textFieldContainer.setClipToPadding(false); addView(textFieldContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 0, 2, 0, 0)); - FrameLayout frameLayout = new FrameLayout(context); + FrameLayout frameLayout = new FrameLayout(context) { + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (scheduledButton != null) { + int x = getMeasuredWidth() - AndroidUtilities.dp(botButton != null && botButton.getVisibility() == VISIBLE ? 96 : 48) - AndroidUtilities.dp(48); + scheduledButton.layout(x, scheduledButton.getTop(), x + scheduledButton.getMeasuredWidth(), scheduledButton.getBottom()); + } + } + }; textFieldContainer.addView(frameLayout, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1.0f, Gravity.BOTTOM)); for (int a = 0; a < 2; a++) { @@ -904,6 +927,19 @@ protected void onDraw(Canvas canvas) { setEmojiButtonImage(false, false); messageEditText = new EditTextCaption(context) { + + private void send(InputContentInfoCompat inputContentInfo, boolean notify, int scheduleDate) { + ClipDescription description = inputContentInfo.getDescription(); + if (description.hasMimeType("image/gif")) { + SendMessagesHelper.prepareSendingDocument(accountInstance, null, null, inputContentInfo.getContentUri(), null, "image/gif", dialog_id, replyingMessageObject, inputContentInfo, null, notify, 0); + } else { + SendMessagesHelper.prepareSendingPhoto(accountInstance, null, inputContentInfo.getContentUri(), dialog_id, replyingMessageObject, null, null, null, inputContentInfo, 0, null, notify, 0); + } + if (delegate != null) { + delegate.onMessageSend(null, true, scheduleDate); + } + } + @Override public InputConnection onCreateInputConnection(EditorInfo editorInfo) { final InputConnection ic = super.onCreateInputConnection(editorInfo); @@ -918,14 +954,11 @@ public InputConnection onCreateInputConnection(EditorInfo editorInfo) { return false; } } - ClipDescription description = inputContentInfo.getDescription(); - if (description.hasMimeType("image/gif")) { - SendMessagesHelper.prepareSendingDocument(accountInstance, null, null, inputContentInfo.getContentUri(), null, "image/gif", dialog_id, replyingMessageObject, inputContentInfo, null); + + if (isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> send(inputContentInfo, notify, scheduleDate)); } else { - SendMessagesHelper.prepareSendingPhoto(accountInstance, null, inputContentInfo.getContentUri(), dialog_id, replyingMessageObject, null, null, null, inputContentInfo, 0, null); - } - if (delegate != null) { - delegate.onMessageSend(null); + send(inputContentInfo, true, 0); } return true; }; @@ -985,6 +1018,7 @@ protected void onSelectionChanged(int selStart, int selEnd) { messageEditText.setTextColor(Theme.getColor(Theme.key_chat_messagePanelText)); messageEditText.setHintColor(Theme.getColor(Theme.key_chat_messagePanelHint)); messageEditText.setHintTextColor(Theme.getColor(Theme.key_chat_messagePanelHint)); + messageEditText.setCursorColor(Theme.getColor(Theme.key_chat_messagePanelCursor)); frameLayout.addView(messageEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 52, 0, isChat ? 50 : 2, 0)); messageEditText.setOnKeyListener(new OnKeyListener() { @@ -1008,7 +1042,7 @@ public boolean onKey(View view, int i, KeyEvent keyEvent) { } return true; } else if (i == KeyEvent.KEYCODE_ENTER && (ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && editingMessageObject == null) { - sendMessage(false); + sendMessage(); return true; } else if (i == KeyEvent.KEYCODE_CTRL_LEFT || i == KeyEvent.KEYCODE_CTRL_RIGHT) { ctrlPressed = keyEvent.getAction() == KeyEvent.ACTION_DOWN; @@ -1024,11 +1058,11 @@ public boolean onKey(View view, int i, KeyEvent keyEvent) { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { if (i == EditorInfo.IME_ACTION_SEND) { - sendMessage(false); + sendMessage(); return true; } else if (keyEvent != null && i == EditorInfo.IME_NULL) { if ((ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && editingMessageObject == null) { - sendMessage(false); + sendMessage(); return true; } else if (i == KeyEvent.KEYCODE_CTRL_LEFT || i == KeyEvent.KEYCODE_CTRL_RIGHT) { ctrlPressed = keyEvent.getAction() == KeyEvent.ACTION_DOWN; @@ -1061,7 +1095,7 @@ public void onTextChanged(CharSequence charSequence, int start, int before, int delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2); } } - if (innerTextChange != 2 && before != count && (count - before) > 1) { + if (innerTextChange != 2 && (count - before) > 1) { processChange = true; } if (editingMessageObject == null && !canWriteToChannel && message.length() != 0 && lastTypingTimeSend < System.currentTimeMillis() - 5000 && !ignoreTextChange) { @@ -1086,7 +1120,7 @@ public void afterTextChanged(Editable editable) { return; } if (sendByEnter && editable.length() > 0 && editable.charAt(editable.length() - 1) == '\n' && editingMessageObject == null) { - sendMessage(false); + sendMessage(); } if (processChange) { ImageSpan[] spans = editable.getSpans(0, editable.length(), ImageSpan.class); @@ -1100,6 +1134,26 @@ public void afterTextChanged(Editable editable) { }); if (isChat) { + if (parentFragment != null) { + Drawable drawable1 = context.getResources().getDrawable(R.drawable.input_calendar1).mutate(); + Drawable drawable2 = context.getResources().getDrawable(R.drawable.input_calendar2).mutate(); + drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_recordedVoiceDot), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2); + + scheduledButton = new ImageView(context); + scheduledButton.setImageDrawable(combinedDrawable); + scheduledButton.setVisibility(GONE); + scheduledButton.setContentDescription(LocaleController.getString("ScheduledMessages", R.string.ScheduledMessages)); + scheduledButton.setScaleType(ImageView.ScaleType.CENTER); + frameLayout.addView(scheduledButton, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT)); + scheduledButton.setOnClickListener(v -> { + if (delegate != null) { + delegate.openScheduledMessages(); + } + }); + } + attachLayout = new LinearLayout(context); attachLayout.setOrientation(LinearLayout.HORIZONTAL); attachLayout.setEnabled(false); @@ -1145,7 +1199,7 @@ public void afterTextChanged(Editable editable) { notifyButton.setContentDescription(silent ? LocaleController.getString("AccDescrChanSilentOn", R.string.AccDescrChanSilentOn) : LocaleController.getString("AccDescrChanSilentOff", R.string.AccDescrChanSilentOff)); notifyButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); notifyButton.setScaleType(ImageView.ScaleType.CENTER); - notifyButton.setVisibility(canWriteToChannel ? VISIBLE : GONE); + notifyButton.setVisibility(canWriteToChannel && (delegate == null || !delegate.hasScheduledMessages()) ? VISIBLE : GONE); attachLayout.addView(notifyButton, LayoutHelper.createLinear(48, 48)); notifyButton.setOnClickListener(new OnClickListener() { @@ -1205,7 +1259,7 @@ public void onClick(View v) { recordDeleteImageView.setOnClickListener(v -> { if (videoToSendMessageObject != null) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2); + delegate.needStartRecordVideo(2, true, 0); } else { MessageObject playing = MediaController.getInstance().getPlayingMessageObject(); if (playing != null && playing == audioToSendMessageObject) { @@ -1220,7 +1274,7 @@ public void onClick(View v) { }); videoTimelineView = new VideoTimelineView(context); - videoTimelineView.setColor(0xff4badf7); + videoTimelineView.setColor(Theme.getColor(Theme.key_chat_messagePanelVideoFrame)); videoTimelineView.setRoundFrames(true); videoTimelineView.setDelegate(new VideoTimelineView.VideoTimelineViewDelegate() { @Override @@ -1320,10 +1374,10 @@ public void didStopDragging() { recordSendText.setOnClickListener(v -> { if (hasRecordVideo && videoSendButton.getTag() != null) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2); + delegate.needStartRecordVideo(2, true, 0); } else { delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0); + MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; updateRecordIntefrace(); @@ -1359,10 +1413,13 @@ public void didStopDragging() { if (!hasRecordVideo || calledRecordRunnable) { startedDraggingX = -1; if (hasRecordVideo && videoSendButton.getTag() != null) { - delegate.needStartRecordVideo(1); + delegate.needStartRecordVideo(1, true, 0); } else { + if (recordingAudioVideo && isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0)); + } delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(1); + MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); } recordingAudioVideo = false; updateRecordIntefrace(); @@ -1397,10 +1454,13 @@ public void didStopDragging() { startedDraggingX = -1; if (hasRecordVideo && videoSendButton.getTag() != null) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(1); + delegate.needStartRecordVideo(1, true, 0); } else { + if (recordingAudioVideo && isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0)); + } delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(1); + MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); } recordingAudioVideo = false; updateRecordIntefrace(); @@ -1426,10 +1486,10 @@ public void didStopDragging() { if (x < -distCanMove) { if (hasRecordVideo && videoSendButton.getTag() != null) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2); + delegate.needStartRecordVideo(2, true, 0); } else { delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0); + MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; updateRecordIntefrace(); @@ -1518,10 +1578,15 @@ public void didStopDragging() { } }); - - sendButtonDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); - sendButtonInverseDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); - inactinveSendButtonDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); + if (isInScheduleMode()) { + sendButtonDrawable = context.getResources().getDrawable(R.drawable.input_schedule).mutate(); + sendButtonInverseDrawable = context.getResources().getDrawable(R.drawable.input_schedule).mutate(); + inactinveSendButtonDrawable = context.getResources().getDrawable(R.drawable.input_schedule).mutate(); + } else { + sendButtonDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); + sendButtonInverseDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); + inactinveSendButtonDrawable = context.getResources().getDrawable(R.drawable.ic_send).mutate(); + } sendButton = new View(context) { private int drawableColor; @@ -1532,13 +1597,18 @@ public void didStopDragging() { @Override protected void onDraw(Canvas canvas) { - int x = (getMeasuredWidth() - sendButtonDrawable.getIntrinsicWidth()) / 2 + AndroidUtilities.dp(2); + int x = (getMeasuredWidth() - sendButtonDrawable.getIntrinsicWidth()) / 2; int y = (getMeasuredHeight() - sendButtonDrawable.getIntrinsicHeight()) / 2; + if (isInScheduleMode()) { + y -= AndroidUtilities.dp(1); + } else { + x += AndroidUtilities.dp(2); + } int color; boolean showingPopup; if (showingPopup = (sendPopupWindow != null && sendPopupWindow.isShowing())) { - color = Theme.getColor(Theme.key_chat_messagePanelBackground); + color = Theme.getColor(Theme.key_chat_messagePanelVoicePressed); } else { color = Theme.getColor(Theme.key_chat_messagePanelSend); } @@ -1570,7 +1640,7 @@ protected void onDraw(Canvas canvas) { invalidate(); } if (!showingPopup) { - if (slowModeTimer == Integer.MAX_VALUE) { + if (slowModeTimer == Integer.MAX_VALUE && !isInScheduleMode()) { inactinveSendButtonDrawable.setBounds(x, y, x + sendButtonDrawable.getIntrinsicWidth(), y + sendButtonDrawable.getIntrinsicHeight()); inactinveSendButtonDrawable.draw(canvas); } else { @@ -1620,88 +1690,8 @@ protected void onDraw(Canvas canvas) { sendButton.setBackgroundDrawable(Theme.createSelectorDrawable(Color.argb(24, Color.red(color), Color.green(color), Color.blue(color)), 1)); } sendButtonContainer.addView(sendButton, LayoutHelper.createFrame(48, 48)); - sendButton.setOnClickListener(view -> sendMessage(false)); - sendButton.setOnLongClickListener(view -> { - if (parentFragment == null) { - return false; - } - TLRPC.Chat chat = parentFragment.getCurrentChat(); - TLRPC.User user = parentFragment.getCurrentUser(); - if (slowModeTimer > 0 || parentFragment.getCurrentEncryptedChat() != null || ChatObject.isChannel(chat) && !chat.megagroup || UserObject.isUserSelf(user)) { - return false; - } - - if (sendPopupLayout == null) { - sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity); - sendPopupLayout.setAnimationEnabled(false); - sendPopupLayout.setOnTouchListener(new OnTouchListener() { - - private android.graphics.Rect popupRect = new android.graphics.Rect(); - - @Override - public boolean onTouch(View v, MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - if (sendPopupWindow != null && sendPopupWindow.isShowing()) { - v.getHitRect(popupRect); - if (!popupRect.contains((int) event.getX(), (int) event.getY())) { - sendPopupWindow.dismiss(); - } - } - } - return false; - } - }); - sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { - if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { - sendPopupWindow.dismiss(); - } - }); - sendPopupLayout.setShowedFromBotton(false); - - ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext()); - cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); - cell.setMinimumWidth(AndroidUtilities.dp(196)); - sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - cell.setOnClickListener(v -> { - if (sendPopupWindow != null && sendPopupWindow.isShowing()) { - sendPopupWindow.dismiss(); - } - sendMessage(true); - }); - - sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - sendButton.invalidate(); - } - }; - sendPopupWindow.setAnimationEnabled(false); - sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); - sendPopupWindow.setOutsideTouchable(true); - sendPopupWindow.setClippingEnabled(true); - sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - sendPopupWindow.getContentView().setFocusableInTouchMode(true); - } - - sendPopupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST)); - sendPopupWindow.setFocusable(true); - int[] location = new int[2]; - view.getLocationInWindow(location); - int y; - if (keyboardVisible && ChatActivityEnterView.this.getMeasuredHeight() > AndroidUtilities.dp(topView != null && topView.getVisibility() == VISIBLE ? 48 + 58 : 58)) { - y = location[1] + view.getMeasuredHeight(); - } else { - y = location[1] - sendPopupLayout.getMeasuredHeight() - AndroidUtilities.dp(2); - } - sendPopupWindow.showAtLocation(view, Gravity.LEFT | Gravity.TOP, location[0] + view.getMeasuredWidth() - sendPopupLayout.getMeasuredWidth() + AndroidUtilities.dp(8), y); - sendPopupWindow.dimBehind(); - sendButton.invalidate(); - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - - return false; - }); + sendButton.setOnClickListener(view -> sendMessage()); + sendButton.setOnLongClickListener(this::onSendLongClick); slowModeButton = new SimpleTextView(context); slowModeButton.setTextSize(18); @@ -1719,6 +1709,12 @@ public void dismiss() { delegate.onUpdateSlowModeButton(slowModeButton, true, slowModeButton.getText()); } }); + slowModeButton.setOnLongClickListener(v -> { + if (messageEditText.length() == 0) { + return false; + } + return onSendLongClick(v); + }); expandStickersButton = new ImageView(context); expandStickersButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); @@ -1812,6 +1808,103 @@ public boolean hasOverlappingRendering() { return false; } + private boolean onSendLongClick(View view) { + if (parentFragment == null || isInScheduleMode() || parentFragment.getCurrentEncryptedChat() != null) { + return false; + } + TLRPC.Chat chat = parentFragment.getCurrentChat(); + TLRPC.User user = parentFragment.getCurrentUser(); + + if (sendPopupLayout == null) { + sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity); + sendPopupLayout.setAnimationEnabled(false); + sendPopupLayout.setOnTouchListener(new OnTouchListener() { + + private android.graphics.Rect popupRect = new android.graphics.Rect(); + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + v.getHitRect(popupRect); + if (!popupRect.contains((int) event.getX(), (int) event.getY())) { + sendPopupWindow.dismiss(); + } + } + } + return false; + } + }); + sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + }); + sendPopupLayout.setShowedFromBotton(false); + + for (int a = 0; a < 2; a++) { + if (a == 1 && (UserObject.isUserSelf(user) || slowModeTimer > 0 && !isInScheduleMode())) { + continue; + } + int num = a; + ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext()); + if (num == 0) { + if (UserObject.isUserSelf(user)) { + cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); + } else { + cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); + } + } else if (num == 1) { + cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + } + cell.setMinimumWidth(AndroidUtilities.dp(196)); + sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + cell.setOnClickListener(v -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + if (num == 0) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(user), this::sendMessageInternal); + } else if (num == 1) { + sendMessageInternal(false, 0); + } + }); + } + + sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + sendButton.invalidate(); + } + }; + sendPopupWindow.setAnimationEnabled(false); + sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); + sendPopupWindow.setOutsideTouchable(true); + sendPopupWindow.setClippingEnabled(true); + sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + sendPopupWindow.getContentView().setFocusableInTouchMode(true); + } + + sendPopupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST)); + sendPopupWindow.setFocusable(true); + int[] location = new int[2]; + view.getLocationInWindow(location); + int y; + if (keyboardVisible && ChatActivityEnterView.this.getMeasuredHeight() > AndroidUtilities.dp(topView != null && topView.getVisibility() == VISIBLE ? 48 + 58 : 58)) { + y = location[1] + view.getMeasuredHeight(); + } else { + y = location[1] - sendPopupLayout.getMeasuredHeight() - AndroidUtilities.dp(2); + } + sendPopupWindow.showAtLocation(view, Gravity.LEFT | Gravity.TOP, location[0] + view.getMeasuredWidth() - sendPopupLayout.getMeasuredWidth() + AndroidUtilities.dp(8), y); + sendPopupWindow.dimBehind(); + sendButton.invalidate(); + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + + return false; + } + public boolean isSendButtonVisible() { return sendButton.getVisibility() == VISIBLE; } @@ -1874,10 +1967,10 @@ public boolean isRecordLocked() { public void cancelRecordingAudioVideo() { if (hasRecordVideo && videoSendButton.getTag() != null) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2); + delegate.needStartRecordVideo(2, true, 0); } else { delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0); + MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; updateRecordIntefrace(); @@ -1948,7 +2041,9 @@ private void updateSlowModeText() { } else { slowModeTimer = 0; } - checkSendButton(true); + if (!isInScheduleMode()) { + checkSendButton(true); + } } public void addTopView(View view, View lineView, int height) { @@ -2333,21 +2428,7 @@ public void setDialogId(long id, int account) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.sendingMessagesChanged); } - int lower_id = (int) dialog_id; - int high_id = (int) (dialog_id >> 32); - if ((int) dialog_id < 0) { - TLRPC.Chat currentChat = accountInstance.getMessagesController().getChat(-(int) dialog_id); - silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + dialog_id, false); - canWriteToChannel = ChatObject.isChannel(currentChat) && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.post_messages) && !currentChat.megagroup; - if (notifyButton != null) { - notifyButton.setVisibility(canWriteToChannel ? VISIBLE : GONE); - notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on); - attachLayout.setPivotX(AndroidUtilities.dp((botButton == null || botButton.getVisibility() == GONE) && (notifyButton == null || notifyButton.getVisibility() == GONE) ? 48 : 96)); - } - if (attachLayout != null) { - updateFieldRight(attachLayout.getVisibility() == VISIBLE ? 1 : 0); - } - } + updateScheduleButton(false); checkRoundVideo(); updateFieldHint(); } @@ -2476,21 +2557,26 @@ public void onAnimationEnd(Animator animation) { AnimatorSet.start(); } - private void sendMessage(boolean forceSilent) { - if (slowModeTimer == Integer.MAX_VALUE) { + private void sendMessage() { + if (isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), this::sendMessageInternal); + } else { + sendMessageInternal(true, 0); + } + } + + private void sendMessageInternal(boolean notify, int scheduleDate) { + if (slowModeTimer == Integer.MAX_VALUE && !isInScheduleMode()) { if (delegate != null) { delegate.scrollToSendingMessage(); } return; - } - if (forceShowSendButton && messageEditText.length() > 0) { - } if (parentFragment != null) { TLRPC.Chat chat = parentFragment.getCurrentChat(); TLRPC.User user = parentFragment.getCurrentUser(); if (user != null || ChatObject.isChannel(chat) && chat.megagroup || !ChatObject.isChannel(chat)) { - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + dialog_id, forceSilent).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + dialog_id, !notify).commit(); } } if (stickersExpanded) { @@ -2501,7 +2587,7 @@ private void sendMessage(boolean forceSilent) { } } if (videoToSendMessageObject != null) { - delegate.needStartRecordVideo(4); + delegate.needStartRecordVideo(4, notify, scheduleDate); hideRecordedAudioPanel(); checkSendButton(true); return; @@ -2510,9 +2596,9 @@ private void sendMessage(boolean forceSilent) { if (playing != null && playing == audioToSendMessageObject) { MediaController.getInstance().cleanupPlayer(true, true); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(audioToSend, null, audioToSendPath, dialog_id, replyingMessageObject, null, null, null, null, 0, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(audioToSend, null, audioToSendPath, dialog_id, replyingMessageObject, null, null, null, null, notify, scheduleDate, 0, null); if (delegate != null) { - delegate.onMessageSend(null); + delegate.onMessageSend(null, notify, scheduleDate); } hideRecordedAudioPanel(); checkSendButton(true); @@ -2531,15 +2617,15 @@ private void sendMessage(boolean forceSilent) { } } } - if (processSendingText(message)) { + if (processSendingText(message, notify, scheduleDate)) { messageEditText.setText(""); lastTypingTimeSend = 0; if (delegate != null) { - delegate.onMessageSend(message); + delegate.onMessageSend(message, notify, scheduleDate); } } else if (forceShowSendButton) { if (delegate != null) { - delegate.onMessageSend(null); + delegate.onMessageSend(null, notify, scheduleDate); } } } @@ -2550,26 +2636,31 @@ public void doneEditingMessage() { showEditDoneProgress(true, true); CharSequence[] message = new CharSequence[]{messageEditText.getText()}; ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(message); - editingMessageReqId = SendMessagesHelper.getInstance(currentAccount).editMessage(editingMessageObject, message[0].toString(), messageWebPageSearch, parentFragment, entities, () -> { + editingMessageReqId = SendMessagesHelper.getInstance(currentAccount).editMessage(editingMessageObject, message[0].toString(), messageWebPageSearch, parentFragment, entities, editingMessageObject.scheduled ? editingMessageObject.messageOwner.date : 0, () -> { editingMessageReqId = 0; setEditingMessageObject(null, false); }); } } - public boolean processSendingText(CharSequence text) { + public boolean processSendingText(CharSequence text, boolean notify, int scheduleDate) { text = AndroidUtilities.getTrimmedString(text); - int maxLength = accountInstance.getMessagesController().maxMessageLength; - if (text.length() != 0) { - int count = (int) Math.ceil(text.length() / (float) maxLength); - for (int a = 0; a < count; a++) { - CharSequence[] message = new CharSequence[]{text.subSequence(a * maxLength, Math.min((a + 1) * maxLength, text.length()))}; - ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(message); - SendMessagesHelper.getInstance(currentAccount).sendMessage(message[0].toString(), dialog_id, replyingMessageObject, messageWebPage, messageWebPageSearch, entities, null, null); - } + /*if (text.length() > 0 && text.length() <= 14 && replyingMessageObject != null && Emoji.isValidEmoji(text.toString()) && parentFragment != null) { + SendMessagesHelper.getInstance(currentAccount).sendReaction(replyingMessageObject, text, parentFragment); return true; - } - return false; + } else {*/ + int maxLength = accountInstance.getMessagesController().maxMessageLength; + if (text.length() != 0) { + int count = (int) Math.ceil(text.length() / (float) maxLength); + for (int a = 0; a < count; a++) { + CharSequence[] message = new CharSequence[]{text.subSequence(a * maxLength, Math.min((a + 1) * maxLength, text.length()))}; + ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(message); + SendMessagesHelper.getInstance(currentAccount).sendMessage(message[0].toString(), dialog_id, replyingMessageObject, messageWebPage, messageWebPageSearch, entities, null, null, notify, scheduleDate); + } + return true; + } + return false; + //} } private void checkSendButton(boolean animated) { @@ -2580,8 +2671,8 @@ private void checkSendButton(boolean animated) { animated = false; } CharSequence message = AndroidUtilities.getTrimmedString(messageEditText.getText()); - if (slowModeTimer > 0 && slowModeTimer != Integer.MAX_VALUE) { - if (audioVideoButtonContainer.getVisibility() == VISIBLE || expandStickersButton.getVisibility() == VISIBLE || sendButton.getVisibility() == VISIBLE || cancelBotButton.getVisibility() == VISIBLE) { + if (slowModeTimer > 0 && slowModeTimer != Integer.MAX_VALUE && !isInScheduleMode()) { + if (slowModeButton.getVisibility() != VISIBLE) { if (animated) { if (runningAnimationType == 5) { return; @@ -2597,22 +2688,40 @@ private void checkSendButton(boolean animated) { if (attachLayout != null) { runningAnimation2 = new AnimatorSet(); - runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 0.0f), - ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 0.0f) - ); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 0.0f)); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 0.0f)); + scheduleButtonHidden = false; + boolean hasScheduled = delegate != null && delegate.hasScheduledMessages(); + if (scheduledButton != null) { + scheduledButton.setScaleY(1.0f); + if (hasScheduled) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + scheduledButton.setPivotX(AndroidUtilities.dp(48)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.TRANSLATION_X, AndroidUtilities.dp(botButton != null && botButton.getVisibility() == VISIBLE ? 96 : 48))); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.SCALE_X, 1.0f)); + } else { + scheduledButton.setTranslationX(AndroidUtilities.dp(botButton != null && botButton.getVisibility() == VISIBLE ? 96 : 48)); + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + } + } + runningAnimation2.playTogether(animators); runningAnimation2.setDuration(100); runningAnimation2.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation2 != null && runningAnimation2.equals(animation)) { + if (animation.equals(runningAnimation2)) { attachLayout.setVisibility(GONE); + runningAnimation2 = null; } } @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation2 != null && runningAnimation2.equals(animation)) { + if (animation.equals(runningAnimation2)) { runningAnimation2 = null; } } @@ -2654,7 +2763,7 @@ public void onAnimationCancel(Animator animation) { runningAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { sendButton.setVisibility(GONE); cancelBotButton.setVisibility(GONE); audioVideoButtonContainer.setVisibility(GONE); @@ -2666,7 +2775,7 @@ public void onAnimationEnd(Animator animation) { @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { runningAnimation = null; } } @@ -2703,14 +2812,25 @@ public void onAnimationCancel(Animator animation) { attachLayout.setVisibility(GONE); updateFieldRight(0); } + scheduleButtonHidden = false; + if (scheduledButton != null) { + if (delegate != null && delegate.hasScheduledMessages()) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + } + scheduledButton.setTranslationX(AndroidUtilities.dp(botButton != null && botButton.getVisibility() == VISIBLE ? 96 : 48)); + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + scheduledButton.setScaleY(1.0f); + } } } - } else if (message.length() > 0 || forceShowSendButton || audioToSend != null || videoToSendMessageObject != null || slowModeTimer == Integer.MAX_VALUE) { + } else if (message.length() > 0 || forceShowSendButton || audioToSend != null || videoToSendMessageObject != null || slowModeTimer == Integer.MAX_VALUE && !isInScheduleMode()) { final String caption = messageEditText.getCaption(); boolean showBotButton = caption != null && (sendButton.getVisibility() == VISIBLE || expandStickersButton.getVisibility() == VISIBLE); boolean showSendButton = caption == null && (cancelBotButton.getVisibility() == VISIBLE || expandStickersButton.getVisibility() == VISIBLE); int color; - if (slowModeTimer == Integer.MAX_VALUE) { + if (slowModeTimer == Integer.MAX_VALUE && !isInScheduleMode()) { color = Theme.getColor(Theme.key_chat_messagePanelIcons); } else { color = Theme.getColor(Theme.key_chat_messagePanelSend); @@ -2732,22 +2852,41 @@ public void onAnimationCancel(Animator animation) { if (attachLayout != null) { runningAnimation2 = new AnimatorSet(); - runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 0.0f), - ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 0.0f) - ); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 0.0f)); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 0.0f)); + boolean hasScheduled = delegate != null && delegate.hasScheduledMessages(); + scheduleButtonHidden = true; + if (scheduledButton != null) { + scheduledButton.setScaleY(1.0f); + if (hasScheduled) { + scheduledButton.setTag(null); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.ALPHA, 0.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.SCALE_X, 0.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.TRANSLATION_X, AndroidUtilities.dp(botButton == null || botButton.getVisibility() == GONE ? 48 : 96))); + } else { + scheduledButton.setAlpha(0.0f); + scheduledButton.setScaleX(0.0f); + scheduledButton.setTranslationX(AndroidUtilities.dp(botButton == null || botButton.getVisibility() == GONE ? 48 : 96)); + } + } + runningAnimation2.playTogether(animators); runningAnimation2.setDuration(100); runningAnimation2.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation2 != null && runningAnimation2.equals(animation)) { + if (animation.equals(runningAnimation2)) { attachLayout.setVisibility(GONE); + if (hasScheduled) { + scheduledButton.setVisibility(GONE); + } + runningAnimation2 = null; } } @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation2 != null && runningAnimation2.equals(animation)) { + if (animation.equals(runningAnimation2)) { runningAnimation2 = null; } } @@ -2805,7 +2944,7 @@ public void onAnimationCancel(Animator animation) { runningAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { if (caption != null) { cancelBotButton.setVisibility(VISIBLE); sendButton.setVisibility(GONE); @@ -2823,7 +2962,7 @@ public void onAnimationEnd(Animator animation) { @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { runningAnimation = null; } } @@ -2872,6 +3011,17 @@ public void onAnimationCancel(Animator animation) { } updateFieldRight(0); } + scheduleButtonHidden = true; + if (scheduledButton != null) { + if (delegate != null && delegate.hasScheduledMessages()) { + scheduledButton.setVisibility(GONE); + scheduledButton.setTag(null); + } + scheduledButton.setAlpha(0.0f); + scheduledButton.setScaleX(0.0f); + scheduledButton.setScaleY(1.0f); + scheduledButton.setTranslationX(AndroidUtilities.dp(botButton == null || botButton.getVisibility() == GONE ? 48 : 96)); + } } } } else if (emojiView != null && emojiViewVisible && (stickersTabOpen || emojiTabOpen && searchingType == 2) && !AndroidUtilities.isInMultiwindow) { @@ -2892,11 +3042,43 @@ public void onAnimationCancel(Animator animation) { if (attachLayout != null) { attachLayout.setVisibility(VISIBLE); runningAnimation2 = new AnimatorSet(); - runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f), - ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f) - ); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f)); + boolean hasScheduled = delegate != null && delegate.hasScheduledMessages(); + scheduleButtonHidden = false; + if (scheduledButton != null) { + scheduledButton.setScaleY(1.0f); + if (hasScheduled) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + scheduledButton.setPivotX(AndroidUtilities.dp(48)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.TRANSLATION_X, 0)); + } else { + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + scheduledButton.setTranslationX(0); + } + } + runningAnimation2.playTogether(animators); runningAnimation2.setDuration(100); + runningAnimation2.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(runningAnimation2)) { + runningAnimation2 = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (animation.equals(runningAnimation2)) { + runningAnimation2 = null; + } + } + }); runningAnimation2.start(); updateFieldRight(1); if (getVisibility() == VISIBLE) { @@ -2935,7 +3117,7 @@ public void onAnimationCancel(Animator animation) { runningAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { sendButton.setVisibility(GONE); cancelBotButton.setVisibility(GONE); slowModeButton.setVisibility(GONE); @@ -2948,7 +3130,7 @@ public void onAnimationEnd(Animator animation) { @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { runningAnimation = null; } } @@ -2982,6 +3164,17 @@ public void onAnimationCancel(Animator animation) { attachLayout.setVisibility(VISIBLE); updateFieldRight(1); } + scheduleButtonHidden = false; + if (scheduledButton != null) { + if (delegate != null && delegate.hasScheduledMessages()) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + } + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + scheduledButton.setScaleY(1.0f); + scheduledButton.setTranslationX(0); + } } } else if (sendButton.getVisibility() == VISIBLE || cancelBotButton.getVisibility() == VISIBLE || expandStickersButton.getVisibility() == VISIBLE || slowModeButton.getVisibility() == VISIBLE) { if (animated) { @@ -3001,11 +3194,43 @@ public void onAnimationCancel(Animator animation) { if (attachLayout != null) { attachLayout.setVisibility(VISIBLE); runningAnimation2 = new AnimatorSet(); - runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f), - ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f) - ); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f)); + boolean hasScheduled = delegate != null && delegate.hasScheduledMessages(); + scheduleButtonHidden = false; + if (scheduledButton != null) { + if (hasScheduled) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + scheduledButton.setPivotX(AndroidUtilities.dp(48)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(scheduledButton, View.TRANSLATION_X, 0)); + } else { + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + scheduledButton.setScaleY(1.0f); + scheduledButton.setTranslationX(0); + } + } + runningAnimation2.playTogether(animators); runningAnimation2.setDuration(100); + runningAnimation2.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(runningAnimation2)) { + runningAnimation2 = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (animation.equals(runningAnimation2)) { + runningAnimation2 = null; + } + } + }); runningAnimation2.start(); updateFieldRight(1); if (getVisibility() == VISIBLE) { @@ -3044,7 +3269,7 @@ public void onAnimationCancel(Animator animation) { runningAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { sendButton.setVisibility(GONE); cancelBotButton.setVisibility(GONE); slowModeButton.setVisibility(GONE); @@ -3056,7 +3281,7 @@ public void onAnimationEnd(Animator animation) { @Override public void onAnimationCancel(Animator animation) { - if (runningAnimation != null && runningAnimation.equals(animation)) { + if (animation.equals(runningAnimation)) { runningAnimation = null; } } @@ -3092,6 +3317,17 @@ public void onAnimationCancel(Animator animation) { attachLayout.setVisibility(VISIBLE); updateFieldRight(1); } + scheduleButtonHidden = false; + if (scheduledButton != null) { + if (delegate != null && delegate.hasScheduledMessages()) { + scheduledButton.setVisibility(VISIBLE); + scheduledButton.setTag(1); + } + scheduledButton.setAlpha(1.0f); + scheduledButton.setScaleX(1.0f); + scheduledButton.setScaleY(1.0f); + scheduledButton.setTranslationX(0); + } } } } @@ -3102,21 +3338,25 @@ private void updateFieldRight(int attachVisible) { } FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); if (attachVisible == 1) { - if (botButton != null && botButton.getVisibility() == VISIBLE || notifyButton != null && notifyButton.getVisibility() == VISIBLE) { + if (botButton != null && botButton.getVisibility() == VISIBLE || notifyButton != null && notifyButton.getVisibility() == VISIBLE || scheduledButton != null && scheduledButton.getTag() != null) { layoutParams.rightMargin = AndroidUtilities.dp(98); } else { layoutParams.rightMargin = AndroidUtilities.dp(50); } } else if (attachVisible == 2) { if (layoutParams.rightMargin != AndroidUtilities.dp(2)) { - if (botButton != null && botButton.getVisibility() == VISIBLE || notifyButton != null && notifyButton.getVisibility() == VISIBLE) { + if (botButton != null && botButton.getVisibility() == VISIBLE || notifyButton != null && notifyButton.getVisibility() == VISIBLE || scheduledButton != null && scheduledButton.getTag() != null) { layoutParams.rightMargin = AndroidUtilities.dp(98); } else { layoutParams.rightMargin = AndroidUtilities.dp(50); } } } else { - layoutParams.rightMargin = AndroidUtilities.dp(2); + if (scheduledButton != null && scheduledButton.getTag() != null) { + layoutParams.rightMargin = AndroidUtilities.dp(50); + } else { + layoutParams.rightMargin = AndroidUtilities.dp(2); + } } messageEditText.setLayoutParams(layoutParams); } @@ -3165,7 +3405,7 @@ private void updateRecordIntefrace() { runningAnimationAudio.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { - if (runningAnimationAudio != null && runningAnimationAudio.equals(animator)) { + if (animator.equals(runningAnimationAudio)) { recordPanel.setX(0); runningAnimationAudio = null; } @@ -3199,7 +3439,7 @@ public void onAnimationEnd(Animator animator) { runningAnimationAudio.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { - if (runningAnimationAudio != null && runningAnimationAudio.equals(animator)) { + if (animator.equals(runningAnimationAudio)) { FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) slideText.getLayoutParams(); params.leftMargin = AndroidUtilities.dp(30); slideText.setLayoutParams(params); @@ -3251,11 +3491,17 @@ public void setCommand(MessageObject messageObject, String command, boolean long openKeyboard(); } } else { + if (slowModeTimer > 0 && !isInScheduleMode()) { + if (delegate != null) { + delegate.onUpdateSlowModeButton(slowModeButton, true, slowModeButton.getText()); + } + return; + } TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? accountInstance.getMessagesController().getUser(messageObject.messageOwner.from_id) : null; if ((botCount != 1 || username) && user != null && user.bot && !command.contains("@")) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, replyingMessageObject, null, false, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, replyingMessageObject, null, false, null, null, null, true, 0); } else { - SendMessagesHelper.getInstance(currentAccount).sendMessage(command, dialog_id, replyingMessageObject, null, false, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(command, dialog_id, replyingMessageObject, null, false, null, null, null, true, 0); } } } @@ -3357,6 +3603,9 @@ public void setEditingMessageObject(MessageObject messageObject, boolean caption audioVideoButtonContainer.setVisibility(GONE); attachLayout.setVisibility(GONE); sendButtonContainer.setVisibility(GONE); + if (scheduledButton != null) { + scheduledButton.setVisibility(GONE); + } } else { doneButtonContainer.setVisibility(View.GONE); messageEditText.setFilters(new InputFilter[0]); @@ -3366,7 +3615,7 @@ public void setEditingMessageObject(MessageObject messageObject, boolean caption cancelBotButton.setScaleY(0.1f); cancelBotButton.setAlpha(0.0f); cancelBotButton.setVisibility(GONE); - if (slowModeTimer > 0) { + if (slowModeTimer > 0 && !isInScheduleMode()) { if (slowModeTimer == Integer.MAX_VALUE) { sendButton.setScaleX(1.0f); sendButton.setScaleY(1.0f); @@ -3410,6 +3659,12 @@ public void setEditingMessageObject(MessageObject messageObject, boolean caption audioVideoButtonContainer.setAlpha(1.0f); audioVideoButtonContainer.setVisibility(VISIBLE); } + if (scheduledButton.getTag() != null) { + scheduledButton.setScaleX(1.0f); + scheduledButton.setScaleY(1.0f); + scheduledButton.setAlpha(1.0f); + scheduledButton.setVisibility(VISIBLE); + } messageEditText.setText(""); if (getVisibility() == VISIBLE) { delegate.onAttachButtonShow(); @@ -3423,6 +3678,10 @@ public ImageView getAttachButton() { return attachButton; } + public View getSendButton() { + return sendButton.getVisibility() == VISIBLE ? sendButton : audioVideoButtonContainer; + } + public EmojiView getEmojiView() { return emojiView; } @@ -3551,6 +3810,77 @@ public CharSequence getFieldText() { return null; } + public void updateScheduleButton(boolean animated) { + boolean notifyVisible = false; + if ((int) dialog_id < 0) { + TLRPC.Chat currentChat = accountInstance.getMessagesController().getChat(-(int) dialog_id); + silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + dialog_id, false); + canWriteToChannel = ChatObject.isChannel(currentChat) && (currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.post_messages) && !currentChat.megagroup; + if (notifyButton != null) { + notifyVisible = canWriteToChannel; + notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on); + } + if (attachLayout != null) { + updateFieldRight(attachLayout.getVisibility() == VISIBLE ? 1 : 0); + } + } + boolean hasScheduled = delegate != null && !isInScheduleMode() && delegate.hasScheduledMessages(); + boolean visible = hasScheduled && !scheduleButtonHidden; + if (scheduledButton != null) { + if (scheduledButton.getTag() != null && visible || scheduledButton.getTag() == null && !visible) { + if (notifyButton != null) { + int newVisibility = !hasScheduled && notifyVisible && scheduledButton.getVisibility() != VISIBLE ? VISIBLE : GONE; + if (newVisibility != notifyButton.getVisibility()) { + notifyButton.setVisibility(newVisibility); + if (attachLayout != null) { + attachLayout.setPivotX(AndroidUtilities.dp((botButton == null || botButton.getVisibility() == GONE) && (notifyButton == null || notifyButton.getVisibility() == GONE) ? 48 : 96)); + } + } + } + return; + } + scheduledButton.setTag(visible ? 1 : null); + } + if (scheduledButtonAnimation != null) { + scheduledButtonAnimation.cancel(); + scheduledButtonAnimation = null; + } + if (!animated || notifyVisible) { + if (scheduledButton != null) { + scheduledButton.setVisibility(visible ? VISIBLE : GONE); + scheduledButton.setAlpha(visible ? 1.0f : 0.0f); + scheduledButton.setScaleX(visible ? 1.0f : 0.1f); + scheduledButton.setScaleY(visible ? 1.0f : 0.1f); + } + if (notifyButton != null) { + notifyButton.setVisibility(notifyVisible && scheduledButton.getVisibility() != VISIBLE ? VISIBLE : GONE); + } + } else { + if (visible) { + scheduledButton.setVisibility(VISIBLE); + } + scheduledButton.setPivotX(AndroidUtilities.dp(24)); + scheduledButtonAnimation = new AnimatorSet(); + scheduledButtonAnimation.playTogether(ObjectAnimator.ofFloat(scheduledButton, View.ALPHA, visible ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(scheduledButton, View.SCALE_X, visible ? 1.0f : 0.1f), + ObjectAnimator.ofFloat(scheduledButton, View.SCALE_Y, visible ? 1.0f : 0.1f)); + scheduledButtonAnimation.setDuration(180); + scheduledButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + scheduledButtonAnimation = null; + if (!visible) { + scheduledButton.setVisibility(GONE); + } + } + }); + scheduledButtonAnimation.start(); + } + if (attachLayout != null) { + attachLayout.setPivotX(AndroidUtilities.dp((botButton == null || botButton.getVisibility() == GONE) && (notifyButton == null || notifyButton.getVisibility() == GONE) ? 48 : 96)); + } + } + private void updateBotButton() { if (botButton == null) { return; @@ -3622,7 +3952,7 @@ public void setButtons(MessageObject messageObject, boolean openKeyboard) { preferences.edit().putInt("answered_" + dialog_id, botButtonsMessageObject.getId()).commit(); } if (delegate != null) { - delegate.onMessageSend(null); + delegate.onMessageSend(null, true, 0); } }); sizeNotifierLayout.addView(botKeyboardView, sizeNotifierLayout.getChildCount() - 1); @@ -3661,7 +3991,7 @@ public void didPressedBotButton(final TLRPC.KeyboardButton button, final Message return; } if (button instanceof TLRPC.TL_keyboardButton) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(button.text, dialog_id, replyMessageObject, null, false, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(button.text, dialog_id, replyMessageObject, null, false, null, null, null, true, 0); } else if (button instanceof TLRPC.TL_keyboardButtonUrl) { parentFragment.showOpenUrlAlert(button.url, true); } else if (button instanceof TLRPC.TL_keyboardButtonRequestPhone) { @@ -3791,8 +4121,8 @@ public void onEmojiSelected(String symbol) { } @Override - public void onStickerSelected(View view, TLRPC.Document sticker, Object parent) { - if (slowModeTimer > 0) { + public void onStickerSelected(View view, TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate) { + if (slowModeTimer > 0 && !isInScheduleMode()) { if (delegate != null) { delegate.onUpdateSlowModeButton(view != null ? view : slowModeButton, true, slowModeButton.getText()); } @@ -3806,7 +4136,7 @@ public void onStickerSelected(View view, TLRPC.Document sticker, Object parent) } setStickersExpanded(false, true, false); } - ChatActivityEnterView.this.onStickerSelected(sticker, parent, false); + ChatActivityEnterView.this.onStickerSelected(sticker, parent, false, notify, scheduleDate); if ((int) dialog_id == 0 && MessageObject.isGifDocument(sticker)) { accountInstance.getMessagesController().saveGif(parent, sticker); } @@ -3820,52 +4150,56 @@ public void onStickersSettingsClick() { } @Override - public void onGifSelected(View view, Object gif, Object parent) { - if (slowModeTimer > 0) { - if (delegate != null) { - delegate.onUpdateSlowModeButton(view != null ? view : slowModeButton, true, slowModeButton.getText()); - } - return; - } - if (stickersExpanded) { - if (searchingType != 0) { - emojiView.hideSearchKeyboard(); + public void onGifSelected(View view, Object gif, Object parent, boolean notify, int scheduleDate) { + if (isInScheduleMode() && scheduleDate == 0) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), (n, s) -> onGifSelected(view, gif, parent, n, s)); + } else { + if (slowModeTimer > 0 && !isInScheduleMode()) { + if (delegate != null) { + delegate.onUpdateSlowModeButton(view != null ? view : slowModeButton, true, slowModeButton.getText()); + } + return; } - setStickersExpanded(false, true, false); - } - if (gif instanceof TLRPC.Document) { - TLRPC.Document document = (TLRPC.Document) gif; - SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, parent); - MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); - if ((int) dialog_id == 0) { - accountInstance.getMessagesController().saveGif(parent, document); + if (stickersExpanded) { + if (searchingType != 0) { + emojiView.hideSearchKeyboard(); + } + setStickersExpanded(false, true, false); } - } else if (gif instanceof TLRPC.BotInlineResult) { - TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) gif; - - if (result.document != null) { - MediaDataController.getInstance(currentAccount).addRecentGif(result.document, (int) (System.currentTimeMillis() / 1000)); + if (gif instanceof TLRPC.Document) { + TLRPC.Document document = (TLRPC.Document) gif; + SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, parent, notify, scheduleDate); + MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); if ((int) dialog_id == 0) { - accountInstance.getMessagesController().saveGif(parent, result.document); + accountInstance.getMessagesController().saveGif(parent, document); } - } + } else if (gif instanceof TLRPC.BotInlineResult) { + TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) gif; - TLRPC.User bot = (TLRPC.User) parent; + if (result.document != null) { + MediaDataController.getInstance(currentAccount).addRecentGif(result.document, (int) (System.currentTimeMillis() / 1000)); + if ((int) dialog_id == 0) { + accountInstance.getMessagesController().saveGif(parent, result.document); + } + } - HashMap params = new HashMap<>(); - params.put("id", result.id); - params.put("query_id", "" + result.query_id); + TLRPC.User bot = (TLRPC.User) parent; - SendMessagesHelper.prepareSendingBotContextResult(accountInstance, result, params, dialog_id, replyingMessageObject); + HashMap params = new HashMap<>(); + params.put("id", result.id); + params.put("query_id", "" + result.query_id); - if (searchingType != 0) { - searchingType = 0; - emojiView.closeSearch(true); - emojiView.hideSearchKeyboard(); + SendMessagesHelper.prepareSendingBotContextResult(accountInstance, result, params, dialog_id, replyingMessageObject, notify, scheduleDate); + + if (searchingType != 0) { + searchingType = 0; + emojiView.closeSearch(true); + emojiView.hideSearchKeyboard(); + } + } + if (delegate != null) { + delegate.onMessageSend(null, notify, scheduleDate); } - } - if (delegate != null) { - delegate.onMessageSend(null); } } @@ -3941,6 +4275,16 @@ public boolean isSearchOpened() { public boolean isExpanded() { return stickersExpanded; } + + @Override + public boolean canSchedule() { + return parentFragment != null && parentFragment.canScheduleMessage(); + } + + @Override + public boolean isInScheduleMode() { + return parentFragment != null && parentFragment.isInScheduleMode(); + } }); emojiView.setDragListener(new EmojiView.DragListener() { @@ -4018,27 +4362,41 @@ private boolean allowDragging() { } @Override - public void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField) { - if (slowModeTimer > 0) { + public void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField, boolean notify, int scheduleDate) { + if (isInScheduleMode() && scheduleDate == 0) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentFragment.getCurrentUser()), (n, s) -> onStickerSelected(sticker, parent, clearsInputField, n, s)); + } else { + if (slowModeTimer > 0 && !isInScheduleMode()) { + if (delegate != null) { + delegate.onUpdateSlowModeButton(slowModeButton, true, slowModeButton.getText()); + } + return; + } + if (searchingType != 0) { + searchingType = 0; + emojiView.closeSearch(true); + emojiView.hideSearchKeyboard(); + } + setStickersExpanded(false, true, false); + SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, dialog_id, replyingMessageObject, parent, notify, scheduleDate); if (delegate != null) { - delegate.onUpdateSlowModeButton(slowModeButton, true, slowModeButton.getText()); + delegate.onMessageSend(null, true, scheduleDate); } - return; - } - if (searchingType != 0) { - searchingType = 0; - emojiView.closeSearch(true); - emojiView.hideSearchKeyboard(); - } - setStickersExpanded(false, true, false); - SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, dialog_id, replyingMessageObject, parent); - if (delegate != null) { - delegate.onMessageSend(null); - } - if (clearsInputField) { - setFieldText(""); + if (clearsInputField) { + setFieldText(""); + } + MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_IMAGE, parent, sticker, (int) (System.currentTimeMillis() / 1000), false); } - MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_IMAGE, parent, sticker, (int) (System.currentTimeMillis() / 1000), false); + } + + @Override + public boolean canSchedule() { + return parentFragment != null && parentFragment.canScheduleMessage(); + } + + @Override + public boolean isInScheduleMode() { + return parentFragment != null && parentFragment.isInScheduleMode(); } public void addStickerToRecent(TLRPC.Document sticker) { @@ -4393,12 +4751,16 @@ public void didReceivedNotification(int id, int account, Object... args) { botKeyboardView.invalidateViews(); } } else if (id == NotificationCenter.recordProgressChanged) { - long t = (Long) args[0]; + int guid = (Integer) args[0]; + if (guid != recordingGuid) { + return; + } + long t = (Long) args[1]; long time = t / 1000; int ms = (int) (t % 1000L) / 10; String str = String.format("%02d:%02d.%02d", time / 60, time % 60, ms); if (lastTimeString == null || !lastTimeString.equals(str)) { - if (lastTypingSendTime != time && time % 5 == 0) { + if (lastTypingSendTime != time && time % 5 == 0 && !isInScheduleMode()) { lastTypingSendTime = time; accountInstance.getMessagesController().sendTyping(dialog_id, videoSendButton != null && videoSendButton.getTag() != null ? 7 : 1, 0); } @@ -4407,24 +4769,28 @@ public void didReceivedNotification(int id, int account, Object... args) { } } if (recordCircle != null) { - recordCircle.setAmplitude((Double) args[1]); + recordCircle.setAmplitude((Double) args[2]); } if (videoSendButton != null && videoSendButton.getTag() != null && t >= 59500) { startedDraggingX = -1; - delegate.needStartRecordVideo(3); + delegate.needStartRecordVideo(3, true, 0); } } else if (id == NotificationCenter.closeChats) { if (messageEditText != null && messageEditText.isFocused()) { AndroidUtilities.hideKeyboard(messageEditText); } } else if (id == NotificationCenter.recordStartError || id == NotificationCenter.recordStopped) { + int guid = (Integer) args[0]; + if (guid != recordingGuid) { + return; + } if (recordingAudioVideo) { accountInstance.getMessagesController().sendTyping(dialog_id, 2, 0); recordingAudioVideo = false; updateRecordIntefrace(); } if (id == NotificationCenter.recordStopped) { - Integer reason = (Integer) args[0]; + Integer reason = (Integer) args[1]; if (reason == 2) { videoTimelineView.setVisibility(VISIBLE); recordedAudioBackground.setVisibility(GONE); @@ -4444,16 +4810,24 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.recordStarted) { + int guid = (Integer) args[0]; + if (guid != recordingGuid) { + return; + } if (!recordingAudioVideo) { recordingAudioVideo = true; updateRecordIntefrace(); } } else if (id == NotificationCenter.audioDidSent) { - Object audio = args[0]; + int guid = (Integer) args[0]; + if (guid != recordingGuid) { + return; + } + Object audio = args[1]; if (audio instanceof VideoEditedInfo) { videoToSendMessageObject = (VideoEditedInfo) audio; - audioToSendPath = (String) args[1]; + audioToSendPath = (String) args[2]; videoTimelineView.setVideoPath(audioToSendPath); videoTimelineView.setVisibility(VISIBLE); @@ -4468,8 +4842,8 @@ public void didReceivedNotification(int id, int account, Object... args) { hidePopup(false); checkSendButton(false); } else { - audioToSend = (TLRPC.TL_document) args[0]; - audioToSendPath = (String) args[1]; + audioToSend = (TLRPC.TL_document) args[1]; + audioToSendPath = (String) args[2]; if (audioToSend != null) { if (recordedAudioPanel == null) { return; @@ -4522,7 +4896,7 @@ public void didReceivedNotification(int id, int account, Object... args) { checkSendButton(false); } else { if (delegate != null) { - delegate.onMessageSend(null); + delegate.onMessageSend(null, true, 0); } } } @@ -4554,6 +4928,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.messageReceivedByServer) { + Boolean scheduled = (Boolean) args[6]; + if (scheduled) { + return; + } long did = (Long) args[3]; if (did == dialog_id && info != null && info.slowmode_seconds != 0) { TLRPC.Chat chat = accountInstance.getMessagesController().getChat(info.id); 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 54ad4759e45..80809f51f13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -109,7 +109,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate, BottomSheet.BottomSheetDelegateInterface { public interface ChatAttachViewDelegate { - void didPressedButton(int button, boolean arg); + void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate); View getRevealView(); @@ -128,7 +128,7 @@ private class InnerAnimator { private BaseFragment baseFragment; private ActionBarPopupWindow sendPopupWindow; private ActionBarPopupWindow.ActionBarPopupWindowLayout sendPopupLayout; - private ActionBarMenuSubItem itemCell; + private ActionBarMenuSubItem[] itemCells; private View shadow; @@ -142,6 +142,7 @@ private class InnerAnimator { private RectF rect = new RectF(); private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private AnimatorSet animatorSet; + private MediaController.AlbumEntry selectedAlbumEntry; private MediaController.AlbumEntry galleryAlbumEntry; @@ -168,7 +169,10 @@ private class InnerAnimator { private RecyclerListView gridView; private GridLayoutManager layoutManager; private PhotoAttachAdapter adapter; + private RecyclerViewItemRangeSelector itemRangeSelector; private int gridExtraSpace; + private boolean shouldSelect; + private int alertOnlyOnce; private RecyclerListView cameraPhotoRecyclerView; private LinearLayoutManager cameraPhotoLayoutManager; @@ -431,7 +435,7 @@ public boolean cancelButtonPressed() { } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { MediaController.PhotoEntry photoEntry = getPhotoEntryAtPosition(index); if (photoEntry != null) { photoEntry.editedInfo = videoEditedInfo; @@ -440,7 +444,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { addToSelectedPhotos(photoEntry, -1); } applyCaption(); - delegate.didPressedButton(7, true); + delegate.didPressedButton(7, true, notify, scheduleDate); } }; @@ -974,11 +978,25 @@ public void onItemClick(int id) { } } if (id == group) { - applyCaption(); - delegate.didPressedButton(7, false); + if (editingMessageObject == null && parentFragment instanceof ChatActivity && ((ChatActivity) parentFragment).isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getContext(), UserObject.isUserSelf(((ChatActivity) parentFragment).getCurrentUser()), (notify, scheduleDate) -> { + applyCaption(); + delegate.didPressedButton(7, false, notify, scheduleDate); + }); + } else { + applyCaption(); + delegate.didPressedButton(7, false, true, 0); + } } else if (id == compress) { - applyCaption(); - delegate.didPressedButton(4, true); + if (editingMessageObject == null && parentFragment instanceof ChatActivity && ((ChatActivity) parentFragment).isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getContext(), UserObject.isUserSelf(((ChatActivity) parentFragment).getCurrentUser()), (notify, scheduleDate) -> { + applyCaption(); + delegate.didPressedButton(4, true, notify, scheduleDate); + }); + } else { + applyCaption(); + delegate.didPressedButton(4, true, true, 0); + } } else if (id >= 10) { selectedAlbumEntry = dropDownAlbums.get(id - 10); if (selectedAlbumEntry == galleryAlbumEntry) { @@ -1136,7 +1154,7 @@ public int getSpanSize(int position) { openCamera(true); } else { if (delegate != null) { - delegate.didPressedButton(0, false); + delegate.didPressedButton(0, false, true, 0); } } } @@ -1144,12 +1162,48 @@ public int getSpanSize(int position) { gridView.setOnItemLongClickListener((view, position) -> { if (position == 0 && selectedAlbumEntry == galleryAlbumEntry) { if (delegate != null) { - delegate.didPressedButton(0, false); + delegate.didPressedButton(0, false, true, 0); } return true; + } else if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + itemRangeSelector.setIsActive(view, true, position, shouldSelect = !cell.isChecked()); } return false; }); + itemRangeSelector = new RecyclerViewItemRangeSelector(new RecyclerViewItemRangeSelector.RecyclerViewItemRangeSelectorDelegate() { + @Override + public int getItemCount() { + return adapter.getItemCount(); + } + + @Override + public void setSelected(View view, int index, boolean selected) { + if (selected != shouldSelect || !(view instanceof PhotoAttachPhotoCell)) { + return; + } + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + cell.callDelegate(); + } + + @Override + public boolean isSelected(int index) { + MediaController.PhotoEntry entry = adapter.getPhoto(index); + return entry != null && selectedPhotos.containsKey(entry.imageId); + } + + @Override + public boolean isIndexSelectable(int index) { + return adapter.getItemViewType(index) == 0; + } + + @Override + public void onStartStopSelection(boolean start) { + alertOnlyOnce = start ? 1 : 0; + gridView.hideSelector(); + } + }); + gridView.addOnItemTouchListener(itemRangeSelector); ActionBarMenu menu = actionBar.createMenu(); @@ -1213,7 +1267,7 @@ public void setTranslationY(float translationY) { buttonsRecyclerView.setOnItemClickListener((view, position) -> { if (view instanceof AttachButton) { AttachButton attachButton = (AttachButton) view; - delegate.didPressedButton((Integer) attachButton.getTag(), true); + delegate.didPressedButton((Integer) attachButton.getTag(), true, true, 0); } else if (view instanceof AttachBotButton) { AttachBotButton button = (AttachBotButton) view; delegate.didSelectBot(button.currentUser); @@ -1273,7 +1327,13 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { writeButtonContainer.setAlpha(0.0f); writeButtonContainer.setContentDescription(LocaleController.getString("Send", R.string.Send)); containerView.addView(writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10)); - writeButtonContainer.setOnClickListener(v -> sendPressed(false)); + writeButtonContainer.setOnClickListener(v -> { + if (editingMessageObject == null && parentFragment instanceof ChatActivity && ((ChatActivity) parentFragment).isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getContext(), UserObject.isUserSelf(((ChatActivity) parentFragment).getCurrentUser()), this::sendPressed); + } else { + sendPressed(true, 0); + } + }); writeButtonContainer.setOnLongClickListener(view -> { if (!(baseFragment instanceof ChatActivity) || editingMessageObject != null) { return false; @@ -1281,59 +1341,99 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { ChatActivity chatActivity = (ChatActivity) baseFragment; TLRPC.Chat chat = chatActivity.getCurrentChat(); TLRPC.User user = chatActivity.getCurrentUser(); - if (chatActivity.getCurrentEncryptedChat() != null || ChatObject.isChannel(chat) && !chat.megagroup || UserObject.isUserSelf(user)) { + if (chatActivity.getCurrentEncryptedChat() != null || chatActivity.isInScheduleMode()) { return false; } - if (sendPopupLayout == null) { - sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext()); - sendPopupLayout.setAnimationEnabled(false); - sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { + sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext()); + sendPopupLayout.setAnimationEnabled(false); + sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { - private android.graphics.Rect popupRect = new android.graphics.Rect(); + private android.graphics.Rect popupRect = new android.graphics.Rect(); - @Override - public boolean onTouch(View v, MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - if (sendPopupWindow != null && sendPopupWindow.isShowing()) { - v.getHitRect(popupRect); - if (!popupRect.contains((int) event.getX(), (int) event.getY())) { - sendPopupWindow.dismiss(); - } + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + v.getHitRect(popupRect); + if (!popupRect.contains((int) event.getX(), (int) event.getY())) { + sendPopupWindow.dismiss(); } } - return false; } - }); - sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { - if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { - sendPopupWindow.dismiss(); - } - }); - sendPopupLayout.setShowedFromBotton(false); + return false; + } + }); + sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + }); + sendPopupLayout.setShowedFromBotton(false); - itemCell = new ActionBarMenuSubItem(getContext()); - itemCell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); - itemCell.setMinimumWidth(AndroidUtilities.dp(196)); + itemCells = new ActionBarMenuSubItem[2]; + int i = 0; + for (int a = 0; a < 2; a++) { + if (a == 0) { + boolean hasTtl = false; + for (HashMap.Entry entry : selectedPhotos.entrySet()) { + Object object = entry.getValue(); + if (object instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; + if (photoEntry.ttl != 0) { + hasTtl = true; + break; + } + } else if (object instanceof MediaController.SearchImage) { + MediaController.SearchImage searchImage = (MediaController.SearchImage) object; + if (searchImage.ttl != 0) { + hasTtl = true; + break; + } + } + } + if (hasTtl) { + continue; + } + } else if (a == 1 && UserObject.isUserSelf(user)) { + continue; + } + int num = a; + itemCells[a] = new ActionBarMenuSubItem(getContext()); + if (num == 0) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); + } + } else if (num == 1) { + itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + } + itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); - sendPopupLayout.addView(itemCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - itemCell.setOnClickListener(v -> { + sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * i, 0, 0)); + itemCells[a].setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } - sendPressed(true); + if (num == 0) { + AlertsCreator.createScheduleDatePickerDialog(getContext(), UserObject.isUserSelf(user), this::sendPressed); + } else if (num == 1) { + sendPressed(true, 0); + } }); - - sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); - sendPopupWindow.setAnimationEnabled(false); - sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); - sendPopupWindow.setOutsideTouchable(true); - sendPopupWindow.setClippingEnabled(true); - sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - sendPopupWindow.getContentView().setFocusableInTouchMode(true); + i++; } + sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + sendPopupWindow.setAnimationEnabled(false); + sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); + sendPopupWindow.setOutsideTouchable(true); + sendPopupWindow.setClippingEnabled(true); + sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + sendPopupWindow.getContentView().setFocusableInTouchMode(true); + sendPopupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); sendPopupWindow.setFocusable(true); int[] location = new int[2]; @@ -1603,7 +1703,9 @@ public boolean onTranslationChanged(float x, float y) { zoomingWas = true; return false; } - zoomControlView.setZoom(0, true); + if (zoomingWas) { + zoomControlView.setZoom(0, true); + } if (x == 0 && y == 0) { zoomingWas = false; } @@ -1754,7 +1856,7 @@ private void applyCaption() { } } - private void sendPressed(boolean forceSilent) { + private void sendPressed(boolean notify, int scheduleDate) { if (buttonPressed) { return; } @@ -1763,12 +1865,12 @@ private void sendPressed(boolean forceSilent) { TLRPC.Chat chat = chatActivity.getCurrentChat(); TLRPC.User user = chatActivity.getCurrentUser(); if (user != null || ChatObject.isChannel(chat) && chat.megagroup || !ChatObject.isChannel(chat)) { - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + chatActivity.getDialogId(), forceSilent).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + chatActivity.getDialogId(), !notify).commit(); } } applyCaption(); buttonPressed = true; - delegate.didPressedButton(7, true); + delegate.didPressedButton(7, true, notify, scheduleDate); } private void updatePhotosCounter(boolean added) { @@ -2034,7 +2136,7 @@ public boolean cancelButtonPressed() { public void needAddMorePhotos() { cancelTakingPhotos = false; if (mediaFromExternalCamera) { - delegate.didPressedButton(0, true); + delegate.didPressedButton(0, true, true, 0); return; } if (!cameraOpened) { @@ -2047,7 +2149,7 @@ public void needAddMorePhotos() { } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { if (cameraPhotos.isEmpty() || baseFragment == null) { return; } @@ -2061,7 +2163,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { } } applyCaption(); - delegate.didPressedButton(8, true); + delegate.didPressedButton(8, true, notify, scheduleDate); cameraPhotos.clear(); selectedPhotosOrder.clear(); selectedPhotos.clear(); @@ -2289,7 +2391,9 @@ public void checkColors() { if (sendPopupLayout != null) { sendPopupLayout.getBackgroundDrawable().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); - itemCell.setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem), Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + for (int a = 0; a < itemCells.length; a++) { + itemCells[a].setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem), Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + } } Theme.setSelectorDrawableColor(writeButtonDrawable, Theme.getColor(Theme.key_dialogFloatingButton), false); @@ -3296,7 +3400,7 @@ public void updatePhotosButton(int animated) { showCommentTextView(false, animated != 0); } else { selectedCountView.invalidate(); - if (animated != 0 && !showCommentTextView(true, animated != 0)) { + if (!showCommentTextView(true, animated != 0) && animated != 0) { selectedCountView.setPivotX(AndroidUtilities.dp(21)); selectedCountView.setPivotY(AndroidUtilities.dp(12)); AnimatorSet animatorSet = new AnimatorSet(); @@ -3788,7 +3892,12 @@ public void getOutline(View view, Outline outline) { ChatActivity chatActivity = (ChatActivity) baseFragment; TLRPC.Chat chat = chatActivity.getCurrentChat(); if (chat != null && !ChatObject.hasAdminRights(chat) && chat.slowmode_enabled) { - AlertsCreator.createSimpleAlert(getContext(), LocaleController.getString("Slowmode", R.string.Slowmode), LocaleController.getString("SlowmodeSelectSendError", R.string.SlowmodeSelectSendError)).show(); + if (alertOnlyOnce != 2) { + AlertsCreator.createSimpleAlert(getContext(), LocaleController.getString("Slowmode", R.string.Slowmode), LocaleController.getString("SlowmodeSelectSendError", R.string.SlowmodeSelectSendError)).show(); + if (alertOnlyOnce == 1) { + alertOnlyOnce = 2; + } + } } } return; @@ -3814,6 +3923,13 @@ public void getOutline(View view, Outline outline) { return new RecyclerListView.Holder(cell); } + private MediaController.PhotoEntry getPhoto(int position) { + if (needCamera && selectedAlbumEntry == galleryAlbumEntry) { + position--; + } + return getPhotoEntryAtPosition(position); + } + @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index 6fbcf394203..1e9a1420cf0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -89,7 +89,7 @@ public ChatAvatarContainer(Context context, ChatActivity chatActivity, boolean n timeItem.setContentDescription(LocaleController.getString("SetTimer", R.string.SetTimer)); } - if (parentFragment != null) { + if (parentFragment != null && !parentFragment.isInScheduleMode()) { setOnClickListener(v -> { TLRPC.User user = parentFragment.getCurrentUser(); TLRPC.Chat chat = parentFragment.getCurrentChat(); @@ -265,7 +265,7 @@ public void updateSubtitle() { return; } TLRPC.User user = parentFragment.getCurrentUser(); - if (UserObject.isUserSelf(user)) { + if (UserObject.isUserSelf(user) || parentFragment.isInScheduleMode()) { if (subtitleTextView.getVisibility() != GONE) { subtitleTextView.setVisibility(GONE); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java new file mode 100644 index 00000000000..c7c220e2640 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java @@ -0,0 +1,414 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ComposeShader; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.graphics.SweepGradient; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.inputmethod.EditorInfo; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; + +import java.util.List; + +public class ColorPicker extends FrameLayout { + + private final ColorPickerDelegate delegate; + + private LinearLayout linearLayout; + + private final int paramValueSliderWidth = AndroidUtilities.dp(20); + + private Paint colorWheelPaint; + private Paint valueSliderPaint; + private Paint circlePaint; + private Drawable circleDrawable; + + private int centerX; + private int centerY; + private int lx; + private int ly; + + boolean ignoreTextChange; + + private Bitmap colorWheelBitmap; + + private EditTextBoldCursor[] colorEditText = new EditTextBoldCursor[2]; + + private int colorWheelRadius; + + private float[] colorHSV = new float[] { 0.0f, 0.0f, 1.0f }; + + private float[] hsvTemp = new float[3]; + private LinearGradient colorGradient; + + private boolean circlePressed; + private boolean colorPressed; + + private BrightnessLimit minBrightness; + private BrightnessLimit maxBrightness; + + public ColorPicker(Context context, ColorPickerDelegate delegate) { + super(context); + + this.delegate = delegate; + + setWillNotDraw(false); + + circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + circleDrawable = context.getResources().getDrawable(R.drawable.knob_shadow).mutate(); + + colorWheelPaint = new Paint(); + colorWheelPaint.setAntiAlias(true); + colorWheelPaint.setDither(true); + + valueSliderPaint = new Paint(); + valueSliderPaint.setAntiAlias(true); + valueSliderPaint.setDither(true); + + linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 46, Gravity.LEFT | Gravity.TOP, 12, 20, 21, 14)); + for (int a = 0; a < 2; a++) { + final int num = a; + + colorEditText[a] = new EditTextBoldCursor(context); + colorEditText[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + colorEditText[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); + colorEditText[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + colorEditText[a].setBackgroundDrawable(Theme.createEditTextDrawable(context, false)); + colorEditText[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + colorEditText[a].setCursorSize(AndroidUtilities.dp(20)); + colorEditText[a].setCursorWidth(1.5f); + colorEditText[a].setSingleLine(true); + colorEditText[a].setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + colorEditText[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); + colorEditText[a].setTransformHintToHeader(true); + if (a == 0) { + colorEditText[a].setInputType(InputType.TYPE_CLASS_TEXT); + colorEditText[a].setHintText( + LocaleController.getString("BackgroundHexColorCode", R.string.BackgroundHexColorCode)); + } else { + colorEditText[a].setInputType(InputType.TYPE_CLASS_NUMBER); + colorEditText[a].setHintText(LocaleController.getString("BackgroundBrightness", R.string.BackgroundBrightness)); + } + colorEditText[a].setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(a == 0 ? 7 : 3); + colorEditText[a].setFilters(inputFilters); + colorEditText[a].setPadding(0, AndroidUtilities.dp(6), 0, 0); + linearLayout.addView(colorEditText[a], LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, a == 0 ? 0.67f : 0.31f, 0, 0, a != 1 ? 23 : 0, 0)); + colorEditText[a].addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if (ignoreTextChange) { + return; + } + ignoreTextChange = true; + if (num == 0) { + for (int a = 0; a < editable.length(); a++) { + char ch = editable.charAt(a); + if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F' || ch == '#' && a == 0)) { + editable.replace(a, a + 1, ""); + a--; + } + } + if (editable.length() == 0) { + editable.append("#"); + } else if (editable.charAt(0) != '#') { + editable.insert(0, "#"); + } + if (editable.length() != 7) { + ignoreTextChange = false; + return; + } + + try { + setColor(Integer.parseInt(editable.toString().substring(1), 16) | 0xff000000); + } catch (Exception e) { + setColor(0xffffffff); + } + } else { + int value = Utilities.parseInt(editable.toString()); + if (value > 255 || value < 0) { + if (value > 255) { + value = 255; + } else { + value = 0; + } + editable.replace(0, editable.length(), "" + value); + } + colorHSV[2] = value / 255.0f; + } + + int color = getColor(); + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + colorEditText[0].setTextKeepState(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue).toUpperCase()); + colorEditText[1].setTextKeepState(String.valueOf((int) (255 * getBrightness()))); + delegate.setColor(color); + + ignoreTextChange = false; + } + }); + colorEditText[a].setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_DONE) { + AndroidUtilities.hideKeyboard(textView); + return true; + } + return false; + }); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int size = Math.min(widthSize, heightSize); + measureChild(linearLayout, MeasureSpec.makeMeasureSpec(widthSize - AndroidUtilities.dp(42), MeasureSpec.EXACTLY), heightMeasureSpec); + setMeasuredDimension(size, size); + } + + @Override + protected void onDraw(Canvas canvas) { + centerX = getWidth() / 2 - paramValueSliderWidth * 2 + AndroidUtilities.dp(11); + centerY = getHeight() / 2 + AndroidUtilities.dp(34); + + canvas.drawBitmap(colorWheelBitmap, centerX - colorWheelRadius, centerY - colorWheelRadius, null); + + float hueAngle = (float) Math.toRadians(colorHSV[0]); + int colorPointX = (int) (-Math.cos(hueAngle) * colorHSV[1] * colorWheelRadius) + centerX; + int colorPointY = (int) (-Math.sin(hueAngle) * colorHSV[1] * colorWheelRadius) + centerY; + + hsvTemp[0] = colorHSV[0]; + hsvTemp[1] = colorHSV[1]; + hsvTemp[2] = 1.0f; + + drawPointerArrow(canvas, colorPointX, colorPointY, Color.HSVToColor(hsvTemp)); + + lx = centerX + colorWheelRadius + paramValueSliderWidth * 2; + ly = centerY - colorWheelRadius; + int width = AndroidUtilities.dp(9); + int height = colorWheelRadius * 2; + if (colorGradient == null) { + colorGradient = new LinearGradient(lx, ly, lx + width, ly + height, new int[]{Color.BLACK, Color.HSVToColor(hsvTemp)}, null, Shader.TileMode.CLAMP); + } + valueSliderPaint.setShader(colorGradient); + canvas.drawRect(lx, ly, lx + width, ly + height, valueSliderPaint); + drawPointerArrow(canvas, lx + width / 2, (int) (ly + getBrightness() * height), getColor()); + } + + private void drawPointerArrow(Canvas canvas, int x, int y, int color) { + int side = AndroidUtilities.dp(13); + circleDrawable.setBounds(x - side, y - side, x + side, y + side); + circleDrawable.draw(canvas); + + circlePaint.setColor(0xffffffff); + canvas.drawCircle(x, y, AndroidUtilities.dp(11), circlePaint); + circlePaint.setColor(color); + canvas.drawCircle(x, y, AndroidUtilities.dp(9), circlePaint); + } + + @Override + protected void onSizeChanged(int width, int height, int oldw, int oldh) { + if (colorWheelRadius != AndroidUtilities.dp(120)) { + colorWheelRadius = AndroidUtilities.dp(120);//Math.max(1, width / 2 - paramValueSliderWidth - AndroidUtilities.dp(20)); + colorWheelBitmap = createColorWheelBitmap(colorWheelRadius * 2, colorWheelRadius * 2); + colorGradient = null; + } + } + + private Bitmap createColorWheelBitmap(int width, int height) { + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + + int colorCount = 12; + int colorAngleStep = 360 / 12; + int[] colors = new int[colorCount + 1]; + float[] hsv = new float[]{0.0f, 1.0f, 1.0f}; + for (int i = 0; i < colors.length; i++) { + hsv[0] = (i * colorAngleStep + 180) % 360; + colors[i] = Color.HSVToColor(hsv); + } + colors[colorCount] = colors[0]; + + SweepGradient sweepGradient = new SweepGradient(0.5f * width, 0.5f * height, colors, null); + RadialGradient radialGradient = new RadialGradient(0.5f * width, 0.5f * height, colorWheelRadius, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP); + ComposeShader composeShader = new ComposeShader(sweepGradient, radialGradient, PorterDuff.Mode.SRC_OVER); + + colorWheelPaint.setShader(composeShader); + + Canvas canvas = new Canvas(bitmap); + canvas.drawCircle(0.5f * width, 0.5f * height, colorWheelRadius, colorWheelPaint); + + return bitmap; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + + int x = (int) event.getX(); + int y = (int) event.getY(); + int cx = x - centerX; + int cy = y - centerY; + double d = Math.sqrt(cx * cx + cy * cy); + + if (circlePressed || !colorPressed && d <= colorWheelRadius) { + if (d > colorWheelRadius) { + d = colorWheelRadius; + } + if (!circlePressed) { + getParent().requestDisallowInterceptTouchEvent(true); + } + circlePressed = true; + colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180.0f); + colorHSV[1] = Math.max(0.0f, Math.min(1.0f, (float) (d / colorWheelRadius))); + colorGradient = null; + } + if (colorPressed || !circlePressed && x >= lx && x <= lx + paramValueSliderWidth && y >= ly && y <= ly + colorWheelRadius * 2) { + float value = (y - ly) / (colorWheelRadius * 2.0f); + if (value < 0.0f) { + value = 0.0f; + } else if (value > 1.0f) { + value = 1.0f; + } + colorHSV[2] = value; + if (!colorPressed) { + getParent().requestDisallowInterceptTouchEvent(true); + } + colorPressed = true; + } + if (colorPressed || circlePressed) { + int color = getColor(); + if (!ignoreTextChange) { + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + ignoreTextChange = true; + colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue).toUpperCase()); + colorEditText[1].setText(String.valueOf((int) (255 * getBrightness()))); + for (int b = 0; b < 2; b++) { + colorEditText[b].setSelection(colorEditText[b].length()); + } + ignoreTextChange = false; + } + delegate.setColor(color); + invalidate(); + } + + return true; + case MotionEvent.ACTION_UP: + colorPressed = false; + circlePressed = false; + break; + } + return super.onTouchEvent(event); + } + + public void setColor(int color) { + if (!ignoreTextChange) { + ignoreTextChange = true; + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + Color.colorToHSV(color, colorHSV); + colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue).toUpperCase()); + colorEditText[1].setText(String.valueOf((int) (255 * getBrightness()))); + for (int b = 0; b < 2; b++) { + colorEditText[b].setSelection(colorEditText[b].length()); + } + ignoreTextChange = false; + } else { + Color.colorToHSV(color, colorHSV); + } + colorGradient = null; + invalidate(); + } + + public int getColor() { + hsvTemp[0] = colorHSV[0]; + hsvTemp[1] = colorHSV[1]; + hsvTemp[2] = getBrightness(); + return (Color.HSVToColor(hsvTemp) & 0x00ffffff) | 0xff000000; + } + + private float getBrightness() { + float brightness = colorHSV[2]; + colorHSV[2] = 1f; + int color = Color.HSVToColor(colorHSV); + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + colorHSV[2] = brightness; + + float min = minBrightness == null ? 0f : minBrightness.getLimit(red, green, blue); + float max = maxBrightness == null ? 1f : maxBrightness.getLimit(red, green, blue); + return Math.max(min, Math.min(brightness, max)); + } + + public void setMinBrightness(BrightnessLimit limit) { + minBrightness = limit; + } + + public void setMaxBrightness(BrightnessLimit limit) { + maxBrightness = limit; + } + + + public void provideThemeDescriptions(List arrayList) { + for (int a = 0; a < colorEditText.length; a++) { + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); + arrayList.add(new ThemeDescription(colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); + } + } + + + public interface ColorPickerDelegate { + void setColor(int color); + } + + public interface BrightnessLimit { + float getLimit(int r, int g, int b); + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java index 30765b65ec6..52b84278926 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -106,11 +106,11 @@ public boolean onTouchEvent(MotionEvent event) { editText.setFocusable(editText.isEnabled()); editText.setCursorSize(AndroidUtilities.dp(20)); editText.setCursorWidth(1.5f); + editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); if (style == STYLE_FRAGMENT) { editText.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); editText.setBackgroundDrawable(Theme.createEditTextDrawable(context, false)); editText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), AndroidUtilities.dp(8)); addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 11 : 0, 1, LocaleController.isRTL ? 0 : 11, 0)); @@ -149,6 +149,11 @@ public boolean onTouchEvent(MotionEvent event) { emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); } + public void setSizeNotifierLayout(SizeNotifierFrameLayout layout) { + sizeNotifierLayout = layout; + sizeNotifierLayout.setDelegate(this); + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.emojiDidLoad) { 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 66c8d114962..46724d5c6b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -228,7 +228,7 @@ default void onEmojiSelected(String emoji) { } - default void onStickerSelected(View view, TLRPC.Document sticker, Object parent) { + default void onStickerSelected(View view, TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate) { } @@ -240,7 +240,7 @@ default void onStickersGroupClick(int chatId) { } - default void onGifSelected(View view, Object gif, Object parent) { + default void onGifSelected(View view, Object gif, Object parent, boolean notify, int scheduleDate) { } @@ -252,7 +252,7 @@ default void onClearEmojiRecent() { } - default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet){ + default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { } @@ -275,6 +275,14 @@ default boolean isSearchOpened() { default boolean isExpanded() { return false; } + + default boolean canSchedule() { + return false; + } + + default boolean isInScheduleMode() { + return false; + } } public interface DragListener { @@ -286,8 +294,8 @@ public interface DragListener { private ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override - public void sendSticker(TLRPC.Document sticker, Object parent) { - delegate.onStickerSelected(null, sticker, parent); + public void sendSticker(TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate) { + delegate.onStickerSelected(null, sticker, parent, notify, scheduleDate); } @Override @@ -295,6 +303,16 @@ public boolean needSend() { return true; } + @Override + public boolean canSchedule() { + return delegate.canSchedule(); + } + + @Override + public boolean isInScheduleMode() { + return delegate.isInScheduleMode(); + } + @Override public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null) { @@ -304,11 +322,11 @@ public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { } @Override - public void sendGif(Object gif) { + public void sendGif(Object gif, boolean notify, int scheduleDate) { if (gifGridView.getAdapter() == gifAdapter) { - delegate.onGifSelected(null, gif, "gif"); + delegate.onGifSelected(null, gif, "gif", notify, scheduleDate); } else if (gifGridView.getAdapter() == gifSearchAdapter) { - delegate.onGifSelected(null, gif, gifSearchAdapter.bot); + delegate.onGifSelected(null, gif, gifSearchAdapter.bot, notify, scheduleDate); } } @@ -1264,12 +1282,12 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (position < 0 || position >= recentGifs.size()) { return; } - delegate.onGifSelected(view, recentGifs.get(position), "gif"); + delegate.onGifSelected(view, recentGifs.get(position), "gif", true, 0); } else if (gifGridView.getAdapter() == gifSearchAdapter) { if (position < 0 || position >= gifSearchAdapter.results.size()) { return; } - delegate.onGifSelected(view, gifSearchAdapter.results.get(position), gifSearchAdapter.bot); + delegate.onGifSelected(view, gifSearchAdapter.results.get(position), gifSearchAdapter.bot, true, 0); recentGifs = MediaDataController.getInstance(currentAccount).getRecentGifs(); if (gifAdapter != null) { gifAdapter.notifyDataSetChanged(); @@ -1377,7 +1395,7 @@ public int getSpanSize(int position) { return; } cell.disable(); - delegate.onStickerSelected(cell, cell.getSticker(), cell.getParentObject()); + delegate.onStickerSelected(cell, cell.getSticker(), cell.getParentObject(), true, 0); }; stickersGridView.setOnItemClickListener(stickersOnItemClickListener); stickersGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index 0de9bf642e6..31413968a5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -206,14 +206,10 @@ public FragmentContextView(Context context, BaseFragment parentFragment, boolean int lower_part = (int) dialog_id; int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - args.putInt("chat_id", -lower_part); - } + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); @@ -278,7 +274,7 @@ private void openSharingLocation(final LocationController.SharingLocationInfo in LocationActivity locationActivity = new LocationActivity(2); locationActivity.setMessageObject(info.messageObject); final long dialog_id = info.messageObject.getDialogId(); - locationActivity.setDelegate((location, live) -> SendMessagesHelper.getInstance(info.messageObject.currentAccount).sendMessage(location, dialog_id, null, null, null)); + locationActivity.setDelegate((location, live, notify, scheduleDate) -> SendMessagesHelper.getInstance(info.messageObject.currentAccount).sendMessage(location, dialog_id, null, null, null, notify, scheduleDate)); launchActivity.presentFragment(locationActivity); } @@ -614,7 +610,7 @@ private void checkLocationString() { } } } - if (lastString != null && fullString.equals(lastString)) { + if (fullString.equals(lastString)) { return; } lastString = fullString; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java index c853e451c86..4fa242851f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java @@ -91,7 +91,7 @@ public GroupCreateSpan(Context context, TLObject object, ContactsController.Cont imageLocation = ImageLocation.getForChat(chat, false); imageParent = chat; } else { - avatarDrawable.setInfo(0, contact.first_name, contact.last_name, false); + avatarDrawable.setInfo(0, contact.first_name, contact.last_name); uid = contact.contact_id; key = contact.key; if (!TextUtils.isEmpty(contact.first_name)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java index 62e70810555..dd3fb88333e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -168,12 +168,12 @@ public void selectedPhotosChanged() { } - private void sendSelectedPhotos(HashMap photos, ArrayList order) { + private void sendSelectedPhotos(HashMap photos, ArrayList order, boolean notify, int scheduleDate) { } @Override - public void actionButtonPressed(boolean canceled) { + public void actionButtonPressed(boolean canceled, boolean notify, int scheduleDate) { if (photos.isEmpty() || delegate == null || sendPressed || canceled) { return; } @@ -199,6 +199,11 @@ public void actionButtonPressed(boolean canceled) { } didSelectPhotos(media); } + + @Override + public void onCaptionChanged(CharSequence caption) { + + } }); fragment.setInitialSearchString(delegate.getInitialSearchString()); parentFragment.presentFragment(fragment); @@ -226,7 +231,7 @@ private void didSelectPhotos(ArrayList phot bitmap = ImageLoader.loadBitmap(path.getAbsolutePath(), null, 800, 800, true); } else { NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileDidFailToLoad); uploadingImage = FileLoader.getAttachFileName(photoSize.location); imageReceiver.setImage(ImageLocation.getForPhoto(photoSize, info.searchImage.photo), null, null, "jpg", null, 1); } @@ -291,7 +296,7 @@ public void openGallery() { PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(1, false, false, null); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { + public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { ImageUpdater.this.didSelectPhotos(photos); } @@ -357,7 +362,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { arrayList.add(new MediaController.PhotoEntry(0, 0, 0, currentPicturePath, orientation, false)); PhotoViewer.getInstance().openPhotoForSelect(arrayList, 0, PhotoViewer.SELECT_TYPE_AVATAR, new PhotoViewer.EmptyPhotoViewerProvider() { @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { String path = null; MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) arrayList.get(0); if (photoEntry.imagePath != null) { @@ -454,11 +459,11 @@ public void didReceivedNotification(int id, int account, Object... args) { delegate = null; } } - } else if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailedLoad || id == NotificationCenter.httpFileDidLoad || id == NotificationCenter.httpFileDidFailedLoad) { + } else if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailToLoad || id == NotificationCenter.httpFileDidLoad || id == NotificationCenter.httpFileDidFailedLoad) { String path = (String) args[0]; if (path.equals(uploadingImage)) { NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.httpFileDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.httpFileDidFailedLoad); 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 1f8073ba63e..ccd659950c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -70,6 +70,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.camera.CameraController; @@ -126,6 +127,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private VideoEditedInfo videoEditedInfo; private VideoPlayer videoPlayer; private Bitmap lastBitmap; + private int recordingGuid; private int[] position = new int[2]; private int[] cameraTexture = new int[1]; @@ -149,7 +151,7 @@ public void run() { if (!recording) { return; } - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordProgressChanged, duration = System.currentTimeMillis() - recordStartTime, 0.0); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordProgressChanged, recordingGuid, duration = System.currentTimeMillis() - recordStartTime, 0.0); AndroidUtilities.runOnUIThread(timerRunnable, 50); } }; @@ -240,6 +242,7 @@ public void onAnimationEnd(Animator animation) { setWillNotDraw(false); setBackgroundColor(0xc0000000); baseFragment = parentFragment; + recordingGuid = baseFragment.getClassGuid(); isSecretChat = baseFragment.getCurrentEncryptedChat() != null; paint = new Paint(Paint.ANTI_ALIAS_FLAG) { @Override @@ -381,7 +384,11 @@ protected void onDetachedFromWindow() { @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.recordProgressChanged) { - long t = (Long) args[0]; + int guid = (Integer) args[0]; + if (guid != recordingGuid) { + return; + } + long t = (Long) args[1]; progress = t / 60000.0f; recordedTime = t; invalidate(); @@ -610,7 +617,7 @@ public void changeVideoPreviewState(int state, float progress) { } } - public void send(int state) { + public void send(int state, boolean notify, int scheduleDate) { if (textureView == null) { return; } @@ -645,13 +652,16 @@ public void send(int state) { videoEditedInfo.encryptedFile = encryptedFile; videoEditedInfo.key = key; videoEditedInfo.iv = iv; - baseFragment.sendMedia(new MediaController.PhotoEntry(0, 0, 0, cameraFile.getAbsolutePath(), 0, true), videoEditedInfo); + baseFragment.sendMedia(new MediaController.PhotoEntry(0, 0, 0, cameraFile.getAbsolutePath(), 0, true), videoEditedInfo, notify, scheduleDate); + if (scheduleDate != 0) { + startAnimation(false); + } } else { cancelled = recordedTime < 800; recording = false; AndroidUtilities.cancelRunOnUIThread(timerRunnable); if (cameraThread != null) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStopped, !cancelled && state == 3 ? 2 : 0); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStopped, recordingGuid, !cancelled && state == 3 ? 2 : 0); int send; if (cancelled) { send = 0; @@ -665,7 +675,7 @@ public void send(int state) { cameraThread = null; } if (cancelled) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.audioRecordTooShort, true); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.audioRecordTooShort, recordingGuid, true); startAnimation(false); } } @@ -700,7 +710,7 @@ public void cancel() { cancelled = true; recording = false; AndroidUtilities.cancelRunOnUIThread(timerRunnable); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStopped, 0); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStopped, recordingGuid, 0); if (cameraThread != null) { saveLastCameraBitmap(); cameraThread.shutdown(0); @@ -1850,7 +1860,14 @@ private void handleStopRecording(final int send) { videoEditedInfo.resultHeight = videoEditedInfo.originalHeight = 240; videoEditedInfo.originalPath = videoFile.getAbsolutePath(); if (send == 1) { - baseFragment.sendMedia(new MediaController.PhotoEntry(0, 0, 0, videoFile.getAbsolutePath(), 0, true), videoEditedInfo); + if (baseFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(baseFragment.getParentActivity(), UserObject.isUserSelf(baseFragment.getCurrentUser()), (notify, scheduleDate) -> { + baseFragment.sendMedia(new MediaController.PhotoEntry(0, 0, 0, videoFile.getAbsolutePath(), 0, true), videoEditedInfo, notify, scheduleDate); + startAnimation(false); + }); + } else { + baseFragment.sendMedia(new MediaController.PhotoEntry(0, 0, 0, videoFile.getAbsolutePath(), 0, true), videoEditedInfo, true, 0); + } } else { videoPlayer = new VideoPlayer(); videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { @@ -1904,7 +1921,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.start(); videoEditedInfo.estimatedDuration = duration; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.audioDidSent, videoEditedInfo, videoFile.getAbsolutePath()); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, videoEditedInfo, videoFile.getAbsolutePath()); } didWriteData(videoFile, 0, true); }); @@ -2005,7 +2022,7 @@ private void prepareEncoder() { recording = true; recordStartTime = System.currentTimeMillis(); AndroidUtilities.runOnUIThread(timerRunnable); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStarted); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStarted, recordingGuid); }); } catch (Exception ioe) { throw new RuntimeException(ioe); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java index 9aca0a8a808..c54c1d0a0af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java @@ -70,7 +70,7 @@ public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String gro avatarImageView.setImage(ImageLocation.getForChat(invite.chat, false), "50_50", avatarDrawable, invite); } else { avatarDrawable = new AvatarDrawable(); - avatarDrawable.setInfo(0, invite.title, null, false); + avatarDrawable.setInfo(0, invite.title, null); title = invite.title; participants_count = invite.participants_count; TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(invite.photo.sizes, 50); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java index 4bb97e77b7b..75508844150 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -23,7 +23,6 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.text.TextUtils; -import android.util.AttributeSet; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; @@ -45,9 +44,9 @@ public class NumberPicker extends LinearLayout { - private static final int SELECTOR_WHEEL_ITEM_COUNT = 3; + private int SELECTOR_WHEEL_ITEM_COUNT = 3; private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300; - private static final int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; + private int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; private static final int SNAP_SCROLL_DURATION = 300; @@ -57,6 +56,7 @@ public class NumberPicker extends LinearLayout { private static final int DEFAULT_LAYOUT_RESOURCE_ID = 0; private static final int SIZE_UNSPECIFIED = -1; + private int textOffset; private TextView mInputText; private int mSelectionDividersDistance; private int mMinHeight; @@ -75,7 +75,7 @@ public class NumberPicker extends LinearLayout { private Formatter mFormatter; private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; private final SparseArray mSelectorIndexToStringCache = new SparseArray<>(); - private final int[] mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT]; + private int[] mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT]; private Paint mSelectorWheelPaint; private int mSelectorElementHeight; private int mInitialScrollOffset = Integer.MIN_VALUE; @@ -121,6 +121,16 @@ public interface Formatter { String format(int value); } + public void setItemCount(int count) { + if (SELECTOR_WHEEL_ITEM_COUNT == count) { + return; + } + SELECTOR_WHEEL_ITEM_COUNT = count; + SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; + mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT]; + initializeSelectorWheelIndices(); + } + private void init() { mSolidColor = 0; mSelectionDivider = new Paint(); @@ -155,6 +165,7 @@ private void init() { mInputText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); mInputText.setBackgroundResource(0); mInputText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + mInputText.setVisibility(INVISIBLE); addView(mInputText, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); ViewConfiguration configuration = ViewConfiguration.get(getContext()); @@ -193,16 +204,6 @@ public NumberPicker(Context context) { init(); } - public NumberPicker(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public NumberPicker(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { final int msrdWdth = getMeasuredWidth(); @@ -260,37 +261,35 @@ public boolean onInterceptTouchEvent(MotionEvent event) { return false; } final int action = event.getActionMasked(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - removeAllCallbacks(); - mInputText.setVisibility(View.INVISIBLE); - mLastDownOrMoveEventY = mLastDownEventY = event.getY(); - mLastDownEventTime = event.getEventTime(); - mIngonreMoveEvents = false; - if (mLastDownEventY < mTopSelectionDividerTop) { - if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { - mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_DECREMENT); - } - } else if (mLastDownEventY > mBottomSelectionDividerBottom) { - if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { - mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_INCREMENT); - } + if (action == MotionEvent.ACTION_DOWN) { + removeAllCallbacks(); + mInputText.setVisibility(View.INVISIBLE); + mLastDownOrMoveEventY = mLastDownEventY = event.getY(); + mLastDownEventTime = event.getEventTime(); + mIngonreMoveEvents = false; + if (mLastDownEventY < mTopSelectionDividerTop) { + if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { + mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_DECREMENT); } - getParent().requestDisallowInterceptTouchEvent(true); - if (!mFlingScroller.isFinished()) { - mFlingScroller.forceFinished(true); - mAdjustScroller.forceFinished(true); - onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); - } else if (!mAdjustScroller.isFinished()) { - mFlingScroller.forceFinished(true); - mAdjustScroller.forceFinished(true); - } else if (mLastDownEventY < mTopSelectionDividerTop) { - postChangeCurrentByOneFromLongPress(false, ViewConfiguration.getLongPressTimeout()); - } else if (mLastDownEventY > mBottomSelectionDividerBottom) { - postChangeCurrentByOneFromLongPress(true, ViewConfiguration.getLongPressTimeout()); + } else if (mLastDownEventY > mBottomSelectionDividerBottom) { + if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { + mPressedStateHelper.buttonPressDelayed(PressedStateHelper.BUTTON_INCREMENT); } - return true; } + getParent().requestDisallowInterceptTouchEvent(true); + if (!mFlingScroller.isFinished()) { + mFlingScroller.forceFinished(true); + mAdjustScroller.forceFinished(true); + onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + } else if (!mAdjustScroller.isFinished()) { + mFlingScroller.forceFinished(true); + mAdjustScroller.forceFinished(true); + } else if (mLastDownEventY < mTopSelectionDividerTop) { + postChangeCurrentByOneFromLongPress(false, ViewConfiguration.getLongPressTimeout()); + } else if (mLastDownEventY > mBottomSelectionDividerBottom) { + postChangeCurrentByOneFromLongPress(true, ViewConfiguration.getLongPressTimeout()); + } + return true; } return false; } @@ -461,11 +460,11 @@ public void setEnabled(boolean enabled) { @Override public void scrollBy(int x, int y) { int[] selectorIndices = mSelectorIndices; - if (!mWrapSelectorWheel && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { + if (!mWrapSelectorWheel && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue && mCurrentScrollOffset + y > mInitialScrollOffset) { mCurrentScrollOffset = mInitialScrollOffset; return; } - if (!mWrapSelectorWheel && y < 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { + if (!mWrapSelectorWheel && y < 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue && mCurrentScrollOffset + y < mInitialScrollOffset) { mCurrentScrollOffset = mInitialScrollOffset; return; } @@ -474,7 +473,7 @@ public void scrollBy(int x, int y) { mCurrentScrollOffset -= mSelectorElementHeight; decrementSelectorIndices(selectorIndices); setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); - if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue && mCurrentScrollOffset > mInitialScrollOffset) { mCurrentScrollOffset = mInitialScrollOffset; } } @@ -482,7 +481,7 @@ public void scrollBy(int x, int y) { mCurrentScrollOffset += mSelectorElementHeight; incrementSelectorIndices(selectorIndices); setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); - if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue && mCurrentScrollOffset < mInitialScrollOffset) { mCurrentScrollOffset = mInitialScrollOffset; } } @@ -529,6 +528,11 @@ public void setValue(int value) { setValueInternal(value, false); } + public void setTextOffset(int value) { + textOffset = value; + invalidate(); + } + private void tryComputeMaxWidth() { if (!mComputeMaxWidth) { return; @@ -665,7 +669,7 @@ protected void onDetachedFromWindow() { @Override protected void onDraw(Canvas canvas) { - float x = (getRight() - getLeft()) / 2; + float x = (getRight() - getLeft()) / 2 + textOffset; float y = mCurrentScrollOffset; // draw the selector wheel @@ -678,7 +682,7 @@ protected void onDraw(Canvas canvas) { // item. Otherwise, if the user starts editing the text via the // IME he may see a dimmed version of the old value intermixed // with the new one. - if (i != SELECTOR_MIDDLE_ITEM_INDEX || mInputText.getVisibility() != VISIBLE) { + if (scrollSelectorValue != null && (i != SELECTOR_MIDDLE_ITEM_INDEX || mInputText.getVisibility() != VISIBLE)) { canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint); } y += mSelectorElementHeight; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java index f939b7fa902..4f996459acf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -20,6 +20,7 @@ import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.os.SystemClock; import android.os.Vibrator; @@ -1236,7 +1237,7 @@ protected void onDraw(Canvas canvas) { return; } if (backgroundDrawable != null) { - if (backgroundDrawable instanceof ColorDrawable) { + if (backgroundDrawable instanceof ColorDrawable || backgroundDrawable instanceof GradientDrawable) { backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); backgroundDrawable.draw(canvas); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerViewItemRangeSelector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerViewItemRangeSelector.java new file mode 100644 index 00000000000..a4445880b50 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerViewItemRangeSelector.java @@ -0,0 +1,190 @@ +package org.telegram.ui.Components; + +import android.view.MotionEvent; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; + +import androidx.recyclerview.widget.RecyclerView; + +public class RecyclerViewItemRangeSelector implements RecyclerView.OnItemTouchListener { + + private RecyclerView recyclerView; + + private int lastDraggedIndex = -1; + private int initialSelection; + private boolean dragSelectActive; + + private int hotspotTopBoundStart; + private int hotspotTopBoundEnd; + private int hotspotBottomBoundStart; + private int hotspotBottomBoundEnd; + private boolean inTopHotspot; + private boolean inBottomHotspot; + + private int autoScrollVelocity; + private boolean isAutoScrolling; + + private int hotspotHeight = AndroidUtilities.dp(80); + private int hotspotOffsetTop; + private int hotspotOffsetBottom; + + private RecyclerViewItemRangeSelectorDelegate delegate; + + private static final int AUTO_SCROLL_DELAY = 15; + + public interface RecyclerViewItemRangeSelectorDelegate { + int getItemCount(); + void setSelected(View view, int index, boolean selected); + boolean isSelected(int index); + boolean isIndexSelectable(int index); + void onStartStopSelection(boolean start); + } + + private Runnable autoScrollRunnable = new Runnable() { + @Override + public void run() { + if (recyclerView == null) { + return; + } + if (inTopHotspot) { + recyclerView.scrollBy(0, -autoScrollVelocity); + AndroidUtilities.runOnUIThread(this); + } else if (inBottomHotspot) { + recyclerView.scrollBy(0, autoScrollVelocity); + AndroidUtilities.runOnUIThread(this); + } + } + }; + + public RecyclerViewItemRangeSelector(RecyclerViewItemRangeSelectorDelegate recyclerViewItemRangeSelectorDelegate) { + delegate = recyclerViewItemRangeSelectorDelegate; + } + + private void disableAutoScroll() { + hotspotHeight = -1; + hotspotOffsetTop = -1; + hotspotOffsetBottom = -1; + } + + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + boolean adapterIsEmpty = rv.getAdapter() == null || rv.getAdapter().getItemCount() == 0; + boolean result = dragSelectActive && !adapterIsEmpty; + + if (result) { + recyclerView = rv; + + if (hotspotHeight > -1) { + hotspotTopBoundStart = hotspotOffsetTop; + hotspotTopBoundEnd = hotspotOffsetTop + hotspotHeight; + hotspotBottomBoundStart = rv.getMeasuredHeight() - hotspotHeight - hotspotOffsetBottom; + hotspotBottomBoundEnd = rv.getMeasuredHeight() - hotspotOffsetBottom; + } + } + + if (result && e.getAction() == MotionEvent.ACTION_UP) { + onDragSelectionStop(); + } + return result; + } + + @Override + public void onTouchEvent(RecyclerView rv, MotionEvent e) { + View v = rv.findChildViewUnder(e.getX(), e.getY()); + int itemPosition; + if (v != null) { + itemPosition = rv.getChildAdapterPosition(v); + } else { + itemPosition = RecyclerView.NO_POSITION; + } + float y = e.getY(); + switch (e.getAction()) { + case MotionEvent.ACTION_UP: { + onDragSelectionStop(); + return; + } + case MotionEvent.ACTION_MOVE: { + if (hotspotHeight > -1) { + if (y >= hotspotTopBoundStart && y <= hotspotTopBoundEnd) { + inBottomHotspot = false; + if (!inTopHotspot) { + inTopHotspot = true; + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + AndroidUtilities.runOnUIThread(autoScrollRunnable); + } + float simulatedFactor = (hotspotTopBoundEnd - hotspotTopBoundStart); + float simulatedY = y - hotspotTopBoundStart; + autoScrollVelocity = (int) (simulatedFactor - simulatedY) / 2; + } else if (y >= hotspotBottomBoundStart && y <= hotspotBottomBoundEnd) { + inTopHotspot = false; + if (!inBottomHotspot) { + inBottomHotspot = true; + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + AndroidUtilities.runOnUIThread(autoScrollRunnable); + } + float simulatedY = y + hotspotBottomBoundEnd; + float simulatedFactor = (hotspotBottomBoundStart + hotspotBottomBoundEnd); + autoScrollVelocity = (int) (simulatedY - simulatedFactor) / 2; + } else if (inTopHotspot || inBottomHotspot) { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + inTopHotspot = false; + inBottomHotspot = false; + } + } + + if (itemPosition != RecyclerView.NO_POSITION) { + if (lastDraggedIndex == itemPosition) { + return; + } + lastDraggedIndex = itemPosition; + delegate.setSelected(v, lastDraggedIndex, !delegate.isSelected(lastDraggedIndex)); + return; + } + break; + } + } + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + + } + + public boolean setIsActive(View view, boolean active, int selection, boolean select) { + if (active && dragSelectActive) { + return false; + } + + lastDraggedIndex = -1; + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + inTopHotspot = false; + inBottomHotspot = false; + + if (!active) { + initialSelection = -1; + return false; + } + + if (!delegate.isIndexSelectable(selection)) { + dragSelectActive = false; + initialSelection = -1; + return false; + } + + delegate.onStartStopSelection(true); + delegate.setSelected(view, initialSelection, select); + dragSelectActive = active; + lastDraggedIndex = initialSelection = selection; + + return true; + } + + private void onDragSelectionStop() { + dragSelectActive = false; + inTopHotspot = false; + inBottomHotspot = false; + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + delegate.onStartStopSelection(false); + } +} 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 44e627e238f..54fa56b25de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -671,17 +671,17 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { for (int a = 0; a < selectedDialogs.size(); a++) { long key = selectedDialogs.keyAt(a); if (frameLayout2.getTag() != null && commentTextView.length() > 0) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key); + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key, true, 0); } } else if (sendingText != null) { for (int a = 0; a < selectedDialogs.size(); a++) { long key = selectedDialogs.keyAt(a); if (frameLayout2.getTag() != null && commentTextView.length() > 0) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, true, null, null, null, true, 0); } } dismiss(); @@ -932,7 +932,7 @@ public void updateSelectedCount(int animated) { showCommentTextView(false); } else { selectedCountView.invalidate(); - if (animated != 0 && !showCommentTextView(true)) { + if (!showCommentTextView(true) && animated != 0) { selectedCountView.setPivotX(AndroidUtilities.dp(21)); selectedCountView.setPivotY(AndroidUtilities.dp(12)); AnimatorSet animatorSet = new AnimatorSet(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index c8992dfded6..dc84e628b8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -15,6 +15,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.view.View; import android.widget.FrameLayout; @@ -136,7 +137,7 @@ public void setBottomClip(int value) { @Override protected void onDraw(Canvas canvas) { if (backgroundDrawable != null) { - if (backgroundDrawable instanceof ColorDrawable) { + if (backgroundDrawable instanceof ColorDrawable || backgroundDrawable instanceof GradientDrawable) { if (bottomClip != 0) { canvas.save(); canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - bottomClip); 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 60efb9976d6..6884bafcac3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -67,7 +67,9 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { public interface StickersAlertDelegate { - void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField); + void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField, boolean notify, int scheduleDate); + boolean canSchedule(); + boolean isInScheduleMode(); } public interface StickersAlertInstallDelegate { @@ -128,11 +130,24 @@ public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event private ContentPreviewViewer.ContentPreviewViewerDelegate previewDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override - public void sendSticker(TLRPC.Document sticker, Object parent) { - delegate.onStickerSelected(sticker, parent, clearsInputField); + public void sendSticker(TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate) { + if (delegate == null) { + return; + } + delegate.onStickerSelected(sticker, parent, clearsInputField, notify, scheduleDate); dismiss(); } + @Override + public boolean canSchedule() { + return delegate != null && delegate.canSchedule(); + } + + @Override + public boolean isInScheduleMode() { + return delegate != null && delegate.isInScheduleMode(); + } + @Override public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { @@ -572,7 +587,7 @@ public void requestLayout() { previewSendButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); stickerPreviewLayout.addView(previewSendButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT)); previewSendButton.setOnClickListener(v -> { - delegate.onStickerSelected(selectedSticker, stickerSet, clearsInputField); + delegate.onStickerSelected(selectedSticker, stickerSet, clearsInputField, true, 0); dismiss(); }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java index be1c7cce5e5..f836bf1a8f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java @@ -97,7 +97,7 @@ public class ThemeEditorView { private WallpaperUpdater wallpaperUpdater; private EditorAlert editorAlert; - private String currentThemeName; + private Theme.ThemeInfo themeInfo; @SuppressLint("StaticFieldLeak") private static volatile ThemeEditorView Instance = null; @@ -142,8 +142,6 @@ public class EditorAlert extends BottomSheet { private FrameLayout bottomLayout; private View[] shadow = new View[2]; private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; - private TextView cancelButton; - private TextView defaultButtom; private TextView saveButton; private Drawable shadowDrawable; @@ -160,21 +158,18 @@ public class EditorAlert extends BottomSheet { private class SearchField extends FrameLayout { - private View searchBackground; - private ImageView searchIconImageView; private ImageView clearSearchImageView; - private CloseProgressDrawable2 progressDrawable; private EditTextBoldCursor searchEditText; private View backgroundView; public SearchField(Context context) { super(context); - searchBackground = new View(context); + View searchBackground = new View(context); searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(18), 0xfff2f4f5)); addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 11, 14, 0)); - searchIconImageView = new ImageView(context); + ImageView searchIconImageView = new ImageView(context); searchIconImageView.setScaleType(ImageView.ScaleType.CENTER); searchIconImageView.setImageResource(R.drawable.smiles_inputsearch); searchIconImageView.setColorFilter(new PorterDuffColorFilter(0xffa1a8af, PorterDuff.Mode.MULTIPLY)); @@ -182,6 +177,7 @@ public SearchField(Context context) { clearSearchImageView = new ImageView(context); clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER); + CloseProgressDrawable2 progressDrawable; clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); progressDrawable.setSide(AndroidUtilities.dp(7)); clearSearchImageView.setScaleX(0.1f); @@ -854,7 +850,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { saveButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); bottomSaveLayout.addView(saveButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); saveButton.setOnClickListener(v -> { - Theme.saveCurrentTheme(currentThemeName, true); + Theme.saveCurrentTheme(themeInfo, true, false, false); setOnDismissListener(null); dismiss(); close(); @@ -865,7 +861,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { bottomLayout.setBackgroundColor(0xffffffff); containerView.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - cancelButton = new TextView(context); + TextView cancelButton = new TextView(context); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); cancelButton.setTextColor(0xff19a7e8); cancelButton.setGravity(Gravity.CENTER); @@ -885,7 +881,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { linearLayout.setOrientation(LinearLayout.HORIZONTAL); bottomLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); - defaultButtom = new TextView(context); + TextView defaultButtom = new TextView(context); defaultButtom.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); defaultButtom.setTextColor(0xff19a7e8); defaultButtom.setGravity(Gravity.CENTER); @@ -990,7 +986,7 @@ public void onAnimationEnd(Animator animation) { if (parentActivity != null) { ((LaunchActivity) parentActivity).rebuildAllFragments(false); } - Theme.saveCurrentTheme(currentThemeName, false); + Theme.saveCurrentTheme(themeInfo, false, false, false); if (listView.getAdapter() == listAdapter) { AndroidUtilities.hideKeyboard(getCurrentFocus()); } @@ -1284,10 +1280,10 @@ private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context context; private int currentCount; private ArrayList> items = new ArrayList<>(); - private HashMap> itemsMap = new HashMap<>(); public ListAdapter(Context context, ThemeDescription[] descriptions) { this.context = context; + HashMap> itemsMap = new HashMap<>(); for (int a = 0; a < descriptions.length; a++) { ThemeDescription description = descriptions[a]; String key = description.getCurrentKey(); @@ -1360,12 +1356,12 @@ public int getItemViewType(int i) { } } - public void show(Activity activity, final String themeName) { + public void show(Activity activity, final Theme.ThemeInfo theme) { if (Instance != null) { Instance.destroy(); } hidden = false; - currentThemeName = themeName; + themeInfo = theme; windowView = new FrameLayout(activity) { private float startX; @@ -1504,7 +1500,7 @@ public boolean onTouchEvent(MotionEvent event) { wallpaperUpdater = new WallpaperUpdater(activity, null, new WallpaperUpdater.WallpaperUpdaterDelegate() { @Override public void didSelectWallpaper(File file, Bitmap bitmap, boolean gallery) { - Theme.setThemeWallpaper(themeName, bitmap, file); + Theme.setThemeWallpaper(themeInfo, bitmap, file); } @Override @@ -1697,7 +1693,7 @@ private void animateToBoundsMaybe() { animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - Theme.saveCurrentTheme(currentThemeName, true); + Theme.saveCurrentTheme(themeInfo, true, false, false); destroy(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java index 57f6397a4e0..99cf0519697 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java @@ -104,7 +104,7 @@ public void didReceivedNotification(int id, int account, Object... args) { showProgress(false); BlockingUpdateView.openApkInstall(parentActivity, appUpdate.document); } - } else if (id == NotificationCenter.fileDidFailedLoad) { + } else if (id == NotificationCenter.fileDidFailToLoad) { String location = (String) args[0]; if (fileName != null && fileName.equals(location)) { showProgress(false); @@ -122,7 +122,7 @@ public void didReceivedNotification(int id, int account, Object... args) { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.FileLoadProgressChanged); buttonsLayout.addView(radialProgressView, LayoutHelper.createFrame(36, 36)); } @@ -131,7 +131,7 @@ protected void onCreate(Bundle savedInstanceState) { public void dismiss() { super.dismiss(); NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidLoad); - NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(accountNum).removeObserver(this, NotificationCenter.FileLoadProgressChanged); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java index edd2e022ae9..886bde5b20a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -8,7 +8,6 @@ package org.telegram.ui.Components; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -24,7 +23,6 @@ import java.util.ArrayList; -@TargetApi(10) public class VideoTimelineView extends View { private long videoLength; @@ -192,6 +190,7 @@ public boolean onTouchEvent(MotionEvent event) { public void setColor(int color) { paint.setColor(color); + invalidate(); } public void setVideoPath(String path) { @@ -209,8 +208,8 @@ public void setVideoPath(String path) { invalidate(); } - public void setDelegate(VideoTimelineViewDelegate delegate) { - this.delegate = delegate; + public void setDelegate(VideoTimelineViewDelegate videoTimelineViewDelegate) { + delegate = videoTimelineViewDelegate; } private void reloadFrames(int frameNum) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java index 2577e92132f..2c98474eea9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java @@ -118,7 +118,7 @@ public void openGallery() { fragment.setAllowSearchImages(false); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { + public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { WallpaperUpdater.this.didSelectPhotos(photos); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java index 0d3f5af018a..3184d34c3bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPHelper.java @@ -79,12 +79,7 @@ public static void startCall(TLRPC.User user, final Activity activity, TLRPC.Use if (isAirplaneMode) { final Intent settingsIntent = new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS); if (settingsIntent.resolveActivity(activity.getPackageManager()) != null) { - bldr.setNeutralButton(LocaleController.getString("VoipOfflineOpenSettings", R.string.VoipOfflineOpenSettings), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - activity.startActivity(settingsIntent); - } - }); + bldr.setNeutralButton(LocaleController.getString("VoipOfflineOpenSettings", R.string.VoipOfflineOpenSettings), (dialog, which) -> activity.startActivity(settingsIntent)); } } bldr.show(); @@ -109,19 +104,11 @@ private static void initiateCall(final TLRPC.User user, final Activity activity) .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("VoipOngoingAlert", R.string.VoipOngoingAlert, ContactsController.formatName(callUser.first_name, callUser.last_name), ContactsController.formatName(user.first_name, user.last_name)))) - .setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (VoIPService.getSharedInstance() != null) { - VoIPService.getSharedInstance().hangUp(new Runnable() { - @Override - public void run() { - doInitiateCall(user, activity); - } - }); - } else { - doInitiateCall(user, activity); - } + .setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { + if (VoIPService.getSharedInstance() != null) { + VoIPService.getSharedInstance().hangUp(() -> doInitiateCall(user, activity)); + } else { + doInitiateCall(user, activity); } }) .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) @@ -160,22 +147,16 @@ public static void permissionDenied(final Activity activity, final Runnable onFi .setTitle(LocaleController.getString("AppName", R.string.AppName)) .setMessage(LocaleController.getString("VoipNeedMicPermission", R.string.VoipNeedMicPermission)) .setPositiveButton(LocaleController.getString("OK", R.string.OK), null) - .setNegativeButton(LocaleController.getString("Settings", R.string.Settings), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", activity.getPackageName(), null); - intent.setData(uri); - activity.startActivity(intent); - } + .setNegativeButton(LocaleController.getString("Settings", R.string.Settings), (dialog, which) -> { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", activity.getPackageName(), null); + intent.setData(uri); + activity.startActivity(intent); }) .show(); - dlg.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - if (onFinish != null) - onFinish.run(); - } + dlg.setOnDismissListener(dialog -> { + if (onFinish != null) + onFinish.run(); }); } } @@ -215,7 +196,7 @@ public static void showRateAlert(Context context, TLRPC.TL_messageActionPhoneCal try { long accessHash = Long.parseLong(d[1]); showRateAlert(context, null, call.call_id, accessHash, UserConfig.selectedAccount, true); - } catch (Exception x) { + } catch (Exception ignore) { } return; } @@ -410,7 +391,7 @@ public void run(TLObject response, TLRPC.TL_error error) { } if (includeLogs[0] && log.exists() && req.rating < 4) { AccountInstance accountInstance = AccountInstance.getInstance(UserConfig.selectedAccount); - SendMessagesHelper.prepareSendingDocument(accountInstance, log.getAbsolutePath(), log.getAbsolutePath(), null, TextUtils.join(" ", problemTags), "text/plain", VOIP_SUPPORT_ID, null, null, null); + SendMessagesHelper.prepareSendingDocument(accountInstance, log.getAbsolutePath(), log.getAbsolutePath(), null, TextUtils.join(" ", problemTags), "text/plain", VOIP_SUPPORT_ID, null, null, null, true, 0); Toast.makeText(context, LocaleController.getString("CallReportSent", R.string.CallReportSent), Toast.LENGTH_LONG).show(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 4175f88660d..a7e428c9f69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -351,7 +351,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(infoTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index d5a27fc2238..c2b492264ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -936,7 +936,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index 8fa4ec554d2..3230cea7b3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -51,6 +51,7 @@ import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Cells.StickerEmojiCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -71,14 +72,17 @@ protected void onDraw(Canvas canvas) { } public interface ContentPreviewViewerDelegate { - void sendSticker(TLRPC.Document sticker, Object parent); + void sendSticker(TLRPC.Document sticker, Object parent, boolean notify, int scheduleDate); void openSet(TLRPC.InputStickerSet set, boolean clearInputField); boolean needSend(); + boolean canSchedule(); + boolean isInScheduleMode(); + default boolean needOpen() { return true; } - default void sendGif(Object gif) { + default void sendGif(Object gif, boolean notify, int scheduleDate) { } @@ -138,11 +142,16 @@ public void run() { final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); if (delegate != null) { - if (delegate.needSend()) { + if (delegate.needSend() && !delegate.isInScheduleMode()) { items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); icons.add(R.drawable.outline_send); actions.add(0); } + if (delegate.canSchedule()) { + items.add(LocaleController.getString("Schedule", R.string.Schedule)); + icons.add(R.drawable.photo_timer); + actions.add(3); + } if (currentStickerSet != null && delegate.needOpen()) { items.add(LocaleController.formatString("ViewPackPreview", R.string.ViewPackPreview)); icons.add(R.drawable.outline_pack); @@ -167,7 +176,7 @@ public void run() { } if (actions.get(which) == 0) { if (delegate != null) { - delegate.sendSticker(currentDocument, parentObject); + delegate.sendSticker(currentDocument, parentObject, true, 0); } } else if (actions.get(which) == 1) { if (delegate != null) { @@ -175,6 +184,11 @@ public void run() { } } else if (actions.get(which) == 2) { MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_FAVE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); + } else if (actions.get(which) == 3) { + TLRPC.Document sticker = currentDocument; + Object parent = parentObject; + ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; + AlertsCreator.createScheduleDatePickerDialog(parentActivity, false, (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendSticker(sticker, parent, notify, scheduleDate)); } }); builder.setDimBehind(false); @@ -209,11 +223,16 @@ protected void onContainerTranslationYChanged(float translationY) { final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); - if (delegate.needSend()) { + if (delegate.needSend() && !delegate.isInScheduleMode()) { items.add(LocaleController.getString("SendGifPreview", R.string.SendGifPreview)); icons.add(R.drawable.outline_send); actions.add(0); } + if (delegate.canSchedule()) { + items.add(LocaleController.getString("Schedule", R.string.Schedule)); + icons.add(R.drawable.photo_timer); + actions.add(3); + } boolean canDelete; if (currentDocument != null) { @@ -239,9 +258,7 @@ protected void onContainerTranslationYChanged(float translationY) { return; } if (actions.get(which) == 0) { - if (delegate != null) { - delegate.sendGif(currentDocument != null ? currentDocument : inlineResult); - } + delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, true, 0); } else if (actions.get(which) == 1) { MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument); delegate.gifAddedOrDeleted(); @@ -249,6 +266,12 @@ protected void onContainerTranslationYChanged(float translationY) { MediaDataController.getInstance(currentAccount).addRecentGif(currentDocument, (int) (System.currentTimeMillis() / 1000)); MessagesController.getInstance(currentAccount).saveGif("gif", currentDocument); delegate.gifAddedOrDeleted(); + } else if (actions.get(which) == 3) { + TLRPC.Document document = currentDocument; + TLRPC.BotInlineResult result = inlineResult; + Object parent = parentObject; + ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; + AlertsCreator.createScheduleDatePickerDialog(parentActivity, false, (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendGif(document != null ? document : result, notify, scheduleDate)); } }); visibleDialog.setDimBehind(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 52e5c8782c4..bc48278bc94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -170,10 +170,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private ArrayList actionModeViews = new ArrayList<>(); private ActionBarMenuItem deleteItem; private ActionBarMenuItem pinItem; - private ActionBarMenuItem archiveItem; + private ActionBarMenuItem muteItem; + private ActionBarMenuSubItem archiveItem; private ActionBarMenuSubItem clearItem; private ActionBarMenuSubItem readItem; - private ActionBarMenuSubItem muteItem; private float additionalFloatingTranslation; @@ -691,7 +691,6 @@ public boolean onFragmentCreate() { getMediaDataController().checkFeaturedStickers(); dialogsLoaded[currentAccount] = true; } - getMediaDataController().checkStickers(MediaDataController.TYPE_EMOJI); getMessagesController().loadPinnedDialogs(folderId, 0, null); return true; } @@ -948,15 +947,15 @@ public void onItemClick(int id) { selectedDialogsCountTextView.setOnTouchListener((v, event) -> true); pinItem = actionMode.addItemWithWidth(pin, R.drawable.msg_pin, AndroidUtilities.dp(54)); - archiveItem = actionMode.addItemWithWidth(archive, R.drawable.msg_archive, AndroidUtilities.dp(54)); + muteItem = actionMode.addItemWithWidth(mute, R.drawable.msg_archive, AndroidUtilities.dp(54)); deleteItem = actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete)); ActionBarMenuItem otherItem = actionMode.addItemWithWidth(0, R.drawable.ic_ab_other, AndroidUtilities.dp(54), LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - muteItem = otherItem.addSubItem(mute, R.drawable.msg_mute, LocaleController.getString("ChatsMute", R.string.ChatsMute)); + archiveItem = otherItem.addSubItem(archive, R.drawable.msg_archive, LocaleController.getString("Archive", R.string.Archive)); readItem = otherItem.addSubItem(read, R.drawable.msg_markread, LocaleController.getString("MarkAsRead", R.string.MarkAsRead)); clearItem = otherItem.addSubItem(clear, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); actionModeViews.add(pinItem); - actionModeViews.add(archiveItem); + actionModeViews.add(muteItem); actionModeViews.add(deleteItem); actionModeViews.add(otherItem); @@ -1234,11 +1233,7 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi searchObject = (TLRPC.User) obj; } } else if (obj instanceof TLRPC.Chat) { - if (((TLRPC.Chat) obj).id > 0) { - dialog_id = -((TLRPC.Chat) obj).id; - } else { - dialog_id = AndroidUtilities.makeBroadcastId(((TLRPC.Chat) obj).id); - } + dialog_id = -((TLRPC.Chat) obj).id; if (!onlySelect) { searchDialogId = dialog_id; searchObject = (TLRPC.Chat) obj; @@ -1285,21 +1280,17 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi int lower_part = (int) dialog_id; int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - if (message_id != 0) { - TLRPC.Chat chat = getMessagesController().getChat(-lower_part); - if (chat != null && chat.migrated_to != null) { - args.putInt("migrated_to", lower_part); - lower_part = -chat.migrated_to.channel_id; - } + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + if (message_id != 0) { + TLRPC.Chat chat = getMessagesController().getChat(-lower_part); + if (chat != null && chat.migrated_to != null) { + args.putInt("migrated_to", lower_part); + lower_part = -chat.migrated_to.channel_id; } - args.putInt("chat_id", -lower_part); } + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); @@ -1350,21 +1341,17 @@ public boolean onItemClick(View view, int position, float x, float y) { int high_id = (int) (dialog_id >> 32); int message_id = cell.getMessageId(); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - if (message_id != 0) { - TLRPC.Chat chat = getMessagesController().getChat(-lower_part); - if (chat != null && chat.migrated_to != null) { - args.putInt("migrated_to", lower_part); - lower_part = -chat.migrated_to.channel_id; - } + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + if (message_id != 0) { + TLRPC.Chat chat = getMessagesController().getChat(-lower_part); + if (chat != null && chat.migrated_to != null) { + args.putInt("migrated_to", lower_part); + lower_part = -chat.migrated_to.channel_id; } - args.putInt("chat_id", -lower_part); } + args.putInt("chat_id", -lower_part); } } else { return false; @@ -1811,7 +1798,7 @@ public void needClearList() { contentView.addView(commentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); commentView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override - public void onMessageSend(CharSequence message) { + public void onMessageSend(CharSequence message, boolean notify, int scheduleDate) { if (delegate == null) { return; } @@ -1888,7 +1875,7 @@ public void didPressedAttachButton() { } @Override - public void needStartRecordVideo(int state) { + public void needStartRecordVideo(int state, boolean notify, int scheduleDate) { } @@ -1962,6 +1949,9 @@ public void onResume() { if (commentView != null) { commentView.onResume(); } + if (!onlySelect && folderId == 0) { + getMediaDataController().checkStickers(MediaDataController.TYPE_EMOJI); + } if (dialogsSearchAdapter != null) { dialogsSearchAdapter.notifyDataSetChanged(); } @@ -2293,7 +2283,7 @@ private void perfromSelectedDialogsAction(int action, boolean alert) { } else if (action == read) { if (canReadCount != 0) { getMessagesController().markMentionsAsRead(selectedDialog); - getMessagesController().markDialogAsRead(selectedDialog, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, true); + getMessagesController().markDialogAsRead(selectedDialog, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, true, 0); } else { getMessagesController().markDialogAsUnread(selectedDialog, null, 0); } @@ -2496,13 +2486,13 @@ private void updateCounters(boolean hide) { } } if (canUnarchiveCount != 0) { - archiveItem.setIcon(R.drawable.msg_unarchive); - archiveItem.setContentDescription(LocaleController.getString("Unarchive", R.string.Unarchive)); + archiveItem.setTextAndIcon(LocaleController.getString("Unarchive", R.string.Unarchive), R.drawable.msg_unarchive); + archiveItem.setVisibility(View.VISIBLE); + } else if (canArchiveCount != 0) { + archiveItem.setTextAndIcon(LocaleController.getString("Archive", R.string.Archive), R.drawable.msg_archive); + archiveItem.setVisibility(View.VISIBLE); } else { - archiveItem.setIcon(R.drawable.msg_archive); - archiveItem.setContentDescription(LocaleController.getString("Archive", R.string.Archive)); - archiveItem.setEnabled(canArchiveCount != 0); - archiveItem.setAlpha(canArchiveCount != 0 ? 1.0f : 0.5f); + archiveItem.setVisibility(View.GONE); } if (canPinCount + canUnpinCount != count) { pinItem.setVisibility(View.GONE); @@ -2510,9 +2500,11 @@ private void updateCounters(boolean hide) { pinItem.setVisibility(View.VISIBLE); } if (canUnmuteCount != 0) { - muteItem.setTextAndIcon(LocaleController.getString("ChatsUnmute", R.string.ChatsUnmute), R.drawable.msg_unmute); + muteItem.setIcon(R.drawable.msg_unmute); + muteItem.setContentDescription(LocaleController.getString("ChatsUnmute", R.string.ChatsUnmute)); } else { - muteItem.setTextAndIcon(LocaleController.getString("ChatsMute", R.string.ChatsMute), R.drawable.msg_mute); + muteItem.setIcon(R.drawable.msg_mute); + muteItem.setContentDescription(LocaleController.getString("ChatsMute", R.string.ChatsMute)); } if (canReadCount != 0) { readItem.setTextAndIcon(LocaleController.getString("MarkAsRead", R.string.MarkAsRead), R.drawable.msg_markread); @@ -3000,6 +2992,7 @@ public void onAnimationEnd(Animator animation) { } else { getMessagesController().deleteDialog(dialogId, 0, revoke); } + MessagesController.getInstance(currentAccount).checkIfFolderEmpty(folderId); }; if (undoView[0] != null) { getUndoView().showWithAction(dialogId, UndoView.ACTION_DELETE, deleteRunnable); @@ -3200,31 +3193,23 @@ private void didSelectResult(final long dialog_id, boolean useAlert, final boole int lower_part = (int) dialog_id; int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { - if (high_id == 1) { - TLRPC.Chat chat = getMessagesController().getChat(lower_part); + if (lower_part == getUserConfig().getClientUserId()) { + builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, LocaleController.getString("SavedMessages", R.string.SavedMessages))); + } else if (lower_part > 0) { + TLRPC.User user = getMessagesController().getUser(lower_part); + if (user == null) { + return; + } + builder.setMessage(LocaleController.formatStringSimple(selectAlertString, UserObject.getUserName(user))); + } else if (lower_part < 0) { + TLRPC.Chat chat = getMessagesController().getChat(-lower_part); if (chat == null) { return; } - builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, chat.title)); - } else { - if (lower_part == getUserConfig().getClientUserId()) { - builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, LocaleController.getString("SavedMessages", R.string.SavedMessages))); - } else if (lower_part > 0) { - TLRPC.User user = getMessagesController().getUser(lower_part); - if (user == null) { - return; - } - builder.setMessage(LocaleController.formatStringSimple(selectAlertString, UserObject.getUserName(user))); - } else if (lower_part < 0) { - TLRPC.Chat chat = getMessagesController().getChat(-lower_part); - if (chat == null) { - return; - } - if (addToGroupAlertString != null) { - builder.setMessage(LocaleController.formatStringSimple(addToGroupAlertString, chat.title)); - } else { - builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, chat.title)); - } + if (addToGroupAlertString != null) { + builder.setMessage(LocaleController.formatStringSimple(addToGroupAlertString, chat.title)); + } else { + builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, chat.title)); } } } else { @@ -3340,7 +3325,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(unreadFloatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chats_actionUnreadBackground)); new ThemeDescription(unreadFloatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chats_actionUnreadPressedBackground));*/ - arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text)); arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed)); arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange)); arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet)); @@ -3380,7 +3365,8 @@ public ThemeDescription[] getThemeDescriptions() { arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_timePaint, null, null, Theme.key_chats_date)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_pinnedPaint, null, null, Theme.key_chats_pinnedOverlay)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_tabletSeletedPaint, null, null, Theme.key_chats_tabletSelectedOverlay)); - arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkDrawable, Theme.dialogs_halfCheckDrawable}, null, Theme.key_chats_sentCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkDrawable}, null, Theme.key_chats_sentCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkReadDrawable, Theme.dialogs_halfCheckDrawable}, null, Theme.key_chats_sentReadCheck)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_clockDrawable}, null, Theme.key_chats_sentClock)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_errorPaint, null, null, Theme.key_chats_sentError)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_errorDrawable}, null, Theme.key_chats_sentErrorIcon)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index 514c5c4bd97..65de6a2538a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -30,6 +30,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.Theme; @@ -39,6 +40,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.SharedDocumentCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.NumberTextView; @@ -60,7 +62,7 @@ public class DocumentSelectActivity extends BaseFragment { public interface DocumentSelectActivityDelegate { - void didSelectFiles(DocumentSelectActivity activity, ArrayList files); + void didSelectFiles(DocumentSelectActivity activity, ArrayList files, boolean notify, int scheduleDate); void startDocumentSelectActivity(); default void startMusicSelectActivity(BaseFragment parentFragment) {} } @@ -70,6 +72,7 @@ default void startMusicSelectActivity(BaseFragment parentFragment) {} private NumberTextView selectedMessagesCountTextView; private EmptyTextProgressView emptyView; private LinearLayoutManager layoutManager; + private ChatActivity parentFragment; private File currentDir; private ArrayList items = new ArrayList<>(); @@ -94,7 +97,6 @@ private class ListItem { String ext = ""; String thumb; File file; - long date; } private class HistoryEntry { @@ -189,9 +191,12 @@ public void onItemClick(int id) { } else if (id == done) { if (delegate != null) { ArrayList files = new ArrayList<>(selectedFiles.keySet()); - delegate.didSelectFiles(DocumentSelectActivity.this, files); - for (ListItem item : selectedFiles.values()) { - item.date = System.currentTimeMillis(); + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectFiles(DocumentSelectActivity.this, files, notify, scheduleDate); + }); + } else { + delegate.didSelectFiles(DocumentSelectActivity.this, files, true, 0); } } } @@ -365,7 +370,13 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (delegate != null) { ArrayList files = new ArrayList<>(); files.add(file.getAbsolutePath()); - delegate.didSelectFiles(DocumentSelectActivity.this, files); + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectFiles(DocumentSelectActivity.this, files, notify, scheduleDate); + }); + } else { + delegate.didSelectFiles(DocumentSelectActivity.this, files, true, 0); + } } } } @@ -376,6 +387,10 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { return fragmentView; } + public void setChatActivity(ChatActivity chatActivity) { + parentFragment = chatActivity; + } + public void setMaxSelectedFiles(int value) { maxSelectedFiles = value; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 6ba55ba6e18..5eb8a5f7be1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -1477,7 +1477,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{GroupCreateUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkboxCheck), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{GroupCreateUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueText), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{GroupCreateUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), - new ThemeDescription(listView, 0, new Class[]{GroupCreateUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{GroupCreateUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index 23fa1f4c3b0..02606446da2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -391,7 +391,7 @@ public void invalidate(int l, int t, int r, int b) { } }; avatarImage.setRoundRadius(AndroidUtilities.dp(32)); - avatarDrawable.setInfo(5, null, null, chatType == ChatObject.CHAT_TYPE_BROADCAST); + avatarDrawable.setInfo(5, null, null); avatarImage.setImageDrawable(avatarDrawable); avatarImage.setContentDescription(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto)); editTextContainer.addView(avatarImage, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 16, LocaleController.isRTL ? 16 : 0, 16)); @@ -488,7 +488,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { } LocationActivity fragment = new LocationActivity(LocationActivity.LOCATION_TYPE_GROUP); fragment.setDialogId(0); - fragment.setDelegate((location, live) -> { + fragment.setDelegate((location, live, notify, scheduleDate) -> { currentGroupCreateLocation.setLatitude(location.geo.lat); currentGroupCreateLocation.setLongitude(location.geo._long); currentGroupCreateAddress = location.address; @@ -944,7 +944,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{GroupCreateUserCell.class}, new String[]{"textView"}, null, null, null, Theme.key_groupcreate_sectionText), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{GroupCreateUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueText), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{GroupCreateUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), - new ThemeDescription(listView, 0, new Class[]{GroupCreateUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{GroupCreateUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java index c8e3bb5c88b..0177c7f146d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java @@ -936,7 +936,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{InviteUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkboxCheck), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{InviteUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueText), new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{InviteUserCell.class}, new String[]{"statusTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText), - new ThemeDescription(listView, 0, new Class[]{InviteUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{InviteUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 786c41baaa7..80955eff006 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -18,6 +18,7 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.Cursor; +import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; @@ -79,6 +80,7 @@ import org.telegram.ui.Cells.DrawerAddCell; import org.telegram.ui.Cells.DrawerUserCell; import org.telegram.ui.Cells.LanguageCell; +import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BlockingUpdateView; @@ -96,6 +98,7 @@ import org.telegram.ui.Components.UpdateAppAlertDialog; import java.io.File; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -152,6 +155,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa private boolean tabletFullSize; + private String loadingThemeFileName; + private String loadingThemeWallpaperName; + private Theme.ThemeInfo loadingThemeInfo; + private TLRPC.TL_theme loadingTheme; + private AlertDialog loadingThemeProgressDialog; + private Runnable lockRunnable; private static final int PLAY_SERVICES_REQUEST_CHECK_SETTINGS = 140; @@ -699,6 +708,8 @@ private void checkCurrentAccount() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.openArticle); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.hasNewContactsToImport); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.needShowPlayServicesAlert); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailToLoad); } currentAccount = UserConfig.selectedAccount; NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); @@ -709,6 +720,8 @@ private void checkCurrentAccount() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.openArticle); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.hasNewContactsToImport); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.needShowPlayServicesAlert); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailToLoad); updateCurrentConnectionState(currentAccount); } @@ -1086,6 +1099,7 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool String game = null; String phoneHash = null; String lang = null; + String theme = null; String code = null; TLRPC.TL_wallPaper wallPaper = null; Integer messageId = null; @@ -1171,6 +1185,8 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool phoneHash = data.getQueryParameter("hash"); } else if (path.startsWith("setlanguage/")) { lang = path.substring(12); + } else if (path.startsWith("addtheme/")) { + theme = path.substring(9); } else if (path.startsWith("c/")) { List segments = data.getPathSegments(); if (segments.size() == 3) { @@ -1360,6 +1376,10 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool url = url.replace("tg:setlanguage", "tg://telegram.org").replace("tg://setlanguage", "tg://telegram.org"); data = Uri.parse(url); lang = data.getQueryParameter("lang"); + } else if (url.startsWith("tg:addtheme") || url.startsWith("tg://addtheme")) { + url = url.replace("tg:addtheme", "tg://telegram.org").replace("tg://addtheme", "tg://telegram.org"); + data = Uri.parse(url); + theme = data.getQueryParameter("slug"); } else { unsupportedUrl = url.replace("tg://", "").replace("tg:", ""); int index; @@ -1375,11 +1395,11 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool args.putString("phone", phone); args.putString("hash", phoneHash); AndroidUtilities.runOnUIThread(() -> presentFragment(new CancelAccountDeletionActivity(args))); - } else if (username != null || group != null || sticker != null || message != null || game != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null || channelId != null) { + } else if (username != null || group != null || sticker != null || message != null || game != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null || channelId != null || theme != null) { if (message != null && message.startsWith("@")) { message = " " + message; } - runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, 0); + runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, theme, 0); } else { try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { @@ -1491,7 +1511,7 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool LocationActivity locationActivity = new LocationActivity(2); locationActivity.setMessageObject(info.messageObject); final long dialog_id = info.messageObject.getDialogId(); - locationActivity.setDelegate((location, live) -> SendMessagesHelper.getInstance(intentAccount[0]).sendMessage(location, dialog_id, null, null, null)); + locationActivity.setDelegate((location, live, notify, scheduleDate) -> SendMessagesHelper.getInstance(intentAccount[0]).sendMessage(location, dialog_id, null, null, null, notify, scheduleDate)); presentFragment(locationActivity); })); } @@ -1626,13 +1646,14 @@ private void runLinkRequest(final int intentAccount, final String unsupportedUrl, final String code, final TLRPC.TL_wallPaper wallPaper, + final String theme, final int state) { if (state == 0 && UserConfig.getActivatedAccountsCount() >= 2 && auth != null) { AlertsCreator.createAccountSelectDialog(this, account -> { if (account != intentAccount) { switchToAccount(account, true); } - runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, 1); + runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, theme, 1); }).show(); return; } else if (code != null) { @@ -1649,6 +1670,7 @@ private void runLinkRequest(final int intentAccount, } final AlertDialog progressDialog = new AlertDialog(this, 3); final int[] requestId = new int[]{0}; + Runnable cancelRunnable = null; if (username != null) { TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); @@ -1686,14 +1708,10 @@ private void runLinkRequest(final int intentAccount, int lower_part = (int) did; int high_id = (int) (did >> 32); if (lower_part != 0) { - if (high_id == 1) { - args1.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args1.putInt("user_id", lower_part); - } else if (lower_part < 0) { - args1.putInt("chat_id", -lower_part); - } + if (lower_part > 0) { + args1.putInt("user_id", lower_part); + } else if (lower_part < 0) { + args1.putInt("chat_id", -lower_part); } } else { args1.putInt("enc_id", high_id); @@ -1821,7 +1839,7 @@ private void runLinkRequest(final int intentAccount, AlertDialog.Builder builder = new AlertDialog.Builder(LaunchActivity.this); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.formatString("ChannelJoinTo", R.string.ChannelJoinTo, invite.chat != null ? invite.chat.title : invite.title)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> runLinkRequest(intentAccount, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, 1)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> runLinkRequest(intentAccount, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, theme, 1)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); } @@ -1909,14 +1927,10 @@ private void runLinkRequest(final int intentAccount, int lower_part = (int) did; int high_id = (int) (did >> 32); if (lower_part != 0) { - if (high_id == 1) { - args13.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args13.putInt("user_id", lower_part); - } else if (lower_part < 0) { - args13.putInt("chat_id", -lower_part); - } + if (lower_part > 0) { + args13.putInt("user_id", lower_part); + } else if (lower_part < 0) { + args13.putInt("chat_id", -lower_part); } } else { args13.putInt("enc_id", high_id); @@ -2048,6 +2062,48 @@ private void runLinkRequest(final int intentAccount, } })); } + } else if (theme != null) { + cancelRunnable = () -> { + loadingThemeFileName = null; + loadingThemeWallpaperName = null; + loadingThemeInfo = null; + loadingThemeProgressDialog = null; + loadingTheme = null; + }; + TLRPC.TL_account_getTheme req = new TLRPC.TL_account_getTheme(); + req.format = "android"; + TLRPC.TL_inputThemeSlug inputThemeSlug = new TLRPC.TL_inputThemeSlug(); + inputThemeSlug.slug = theme; + req.theme = inputThemeSlug; + requestId[0] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + int notFound = 2; + if (response instanceof TLRPC.TL_theme) { + TLRPC.TL_theme t = (TLRPC.TL_theme) response; + if (t.document != null) { + loadingTheme = t; + loadingThemeFileName = FileLoader.getAttachFileName(loadingTheme.document); + loadingThemeProgressDialog = progressDialog; + FileLoader.getInstance(currentAccount).loadFile(loadingTheme.document, t, 1, 1); + notFound = 0; + } else { + notFound = 1; + } + } else if (error != null && "THEME_FORMAT_INVALID".equals(error.text)) { + notFound = 1; + } + if (notFound != 0) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } + if (notFound == 1) { + showAlertDialog(AlertsCreator.createSimpleAlert(LaunchActivity.this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("ThemeNotSupported", R.string.ThemeNotSupported))); + } else { + showAlertDialog(AlertsCreator.createSimpleAlert(LaunchActivity.this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("ThemeNotFound", R.string.ThemeNotFound))); + } + } + })); } else if (channelId != null && messageId != null) { Bundle args = new Bundle(); args.putInt("chat_id", channelId); @@ -2088,7 +2144,13 @@ private void runLinkRequest(final int intentAccount, } if (requestId[0] != 0) { - progressDialog.setOnCancelListener(dialog -> ConnectionsManager.getInstance(intentAccount).cancelRequest(requestId[0], true)); + final Runnable cancelRunnableFinal = cancelRunnable; + progressDialog.setOnCancelListener(dialog -> { + ConnectionsManager.getInstance(intentAccount).cancelRequest(requestId[0], true); + if (cancelRunnableFinal != null) { + cancelRunnableFinal.run(); + } + }); try { progressDialog.show(); } catch (Exception ignore) { @@ -2228,14 +2290,10 @@ public void didSelectDialogs(DialogsActivity dialogsFragment, ArrayList di NotificationCenter.getInstance(account).postNotificationName(NotificationCenter.closeChats); } if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - args.putInt("chat_id", -lower_part); - } + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); @@ -2247,9 +2305,9 @@ public void didSelectDialogs(DialogsActivity dialogsFragment, ArrayList di if (contactsToSend != null && contactsToSend.size() == 1) { if (contactsToSend.size() == 1) { PhonebookShareActivity contactFragment = new PhonebookShareActivity(null, contactsToSendUri, null, null); - contactFragment.setDelegate(user -> { + contactFragment.setDelegate((user, notify, scheduleDate) -> { actionBarLayout.presentFragment(fragment, true, false, true, false); - SendMessagesHelper.getInstance(account).sendMessage(user, did, null, null, null); + SendMessagesHelper.getInstance(account).sendMessage(user, did, null, null, null, notify, scheduleDate); }); actionBarLayout.presentFragment(contactFragment, dialogsFragment != null, dialogsFragment == null, true, false); } @@ -2265,7 +2323,7 @@ public void didSelectDialogs(DialogsActivity dialogsFragment, ArrayList di photoPathsArray.get(0).caption = sendingText; sendingText = null; } - SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, null, null, false, false, null); + SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, null, null, false, false, null, true, 0); } if (documentsPathsArray != null || documentsUrisArray != null) { String caption = null; @@ -2273,15 +2331,15 @@ public void didSelectDialogs(DialogsActivity dialogsFragment, ArrayList di caption = sendingText; sendingText = null; } - SendMessagesHelper.prepareSendingDocuments(accountInstance, documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, caption, documentsMimeType, did, null, null, null); + SendMessagesHelper.prepareSendingDocuments(accountInstance, documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, caption, documentsMimeType, did, null, null, null, true, 0); } if (sendingText != null) { - SendMessagesHelper.prepareSendingText(accountInstance, sendingText, did); + SendMessagesHelper.prepareSendingText(accountInstance, sendingText, did, true, 0); } if (contactsToSend != null && !contactsToSend.isEmpty()) { for (int a = 0; a < contactsToSend.size(); a++) { TLRPC.User user = contactsToSend.get(a); - SendMessagesHelper.getInstance(account).sendMessage(user, did, null, null, null); + SendMessagesHelper.getInstance(account).sendMessage(user, did, null, null, null, true, 0); } } } @@ -2549,11 +2607,7 @@ protected void onDestroy() { @Override protected void onResume() { - try { - super.onResume(); - } catch (Throwable e) { - FileLog.e(e); - } + super.onResume(); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 4096); MediaController.getInstance().setFeedbackView(actionBarLayout, true); ApplicationLoader.mainInterfacePaused = false; @@ -2709,10 +2763,10 @@ public void didReceivedNotification(int id, final int account, Object... args) { return; } LocationActivity fragment = new LocationActivity(0); - fragment.setDelegate((location, live) -> { + fragment.setDelegate((location, live, notify, scheduleDate) -> { for (HashMap.Entry entry : waitingForLocation.entrySet()) { MessageObject messageObject = entry.getValue(); - SendMessagesHelper.getInstance(account).sendMessage(location, messageObject.getDialogId(), messageObject, null, null); + SendMessagesHelper.getInstance(account).sendMessage(location, messageObject.getDialogId(), messageObject, null, null, notify, scheduleDate); } }); presentFragment(fragment); @@ -2819,6 +2873,74 @@ public void didReceivedNotification(int id, final int account, Object... args) { } catch (Throwable ignore) { } + } else if (id == NotificationCenter.fileDidLoad) { + if (loadingThemeFileName != null) { + String path = (String) args[0]; + if (loadingThemeFileName.equals(path)) { + loadingThemeFileName = null; + File locFile = new File(ApplicationLoader.getFilesDirFixed(), "remote" + loadingTheme.id + ".attheme"); + Theme.ThemeInfo themeInfo = Theme.fillThemeValues(locFile, loadingTheme.title, loadingTheme); + if (themeInfo != null) { + if (themeInfo.pathToWallpaper != null) { + File file = new File(themeInfo.pathToWallpaper); + if (!file.exists()) { + TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper(); + TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); + inputWallPaperSlug.slug = themeInfo.slug; + req.wallpaper = inputWallPaperSlug; + ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_wallPaper) { + TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; + loadingThemeInfo = themeInfo; + loadingThemeWallpaperName = FileLoader.getAttachFileName(wallPaper.document); + FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1); + } else { + onThemeLoadFinish(); + } + })); + return; + } + } + Theme.ThemeInfo finalThemeInfo = Theme.applyThemeFile(locFile, loadingTheme.title, loadingTheme, true); + if (finalThemeInfo != null) { + presentFragment(new ThemePreviewActivity(finalThemeInfo, true, ThemePreviewActivity.SCREEN_TYPE_PREVIEW, false)); + } + } + onThemeLoadFinish(); + } + } else if (loadingThemeWallpaperName != null) { + String path = (String) args[0]; + if (loadingThemeWallpaperName.equals(path)) { + loadingThemeWallpaperName = null; + File file = (File) args[1]; + Utilities.globalQueue.postRunnable(() -> { + try { + Bitmap bitmap = ThemesHorizontalListCell.getScaledBitmap(AndroidUtilities.dp(640), AndroidUtilities.dp(360), file.getAbsolutePath(), null, 0); + if (loadingThemeInfo.isBlured) { + bitmap = Utilities.blurWallpaper(bitmap); + } + FileOutputStream stream = new FileOutputStream(loadingThemeInfo.pathToWallpaper); + bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); + stream.close(); + } catch (Throwable e) { + FileLog.e(e); + } + AndroidUtilities.runOnUIThread(() -> { + File locFile = new File(ApplicationLoader.getFilesDirFixed(), "remote" + loadingTheme.id + ".attheme"); + Theme.ThemeInfo finalThemeInfo = Theme.applyThemeFile(locFile, loadingTheme.title, loadingTheme, true); + if (finalThemeInfo != null) { + presentFragment(new ThemePreviewActivity(finalThemeInfo, true, ThemePreviewActivity.SCREEN_TYPE_PREVIEW, false)); + } + onThemeLoadFinish(); + }); + }); + } + } + } else if (id == NotificationCenter.fileDidFailToLoad) { + String path = (String) args[0]; + if (path.equals(loadingThemeFileName) || path.equals(loadingThemeWallpaperName)) { + onThemeLoadFinish(); + } } } @@ -2830,6 +2952,20 @@ private String getStringForLanguageAlert(HashMap map, String key return value; } + private void onThemeLoadFinish() { + if (loadingThemeProgressDialog != null) { + try { + loadingThemeProgressDialog.dismiss(); + } finally { + loadingThemeProgressDialog = null; + } + } + loadingThemeWallpaperName = null; + loadingThemeInfo = null; + loadingThemeFileName = null; + loadingTheme = null; + } + private void checkFreeDiscSpace() { SharedConfig.checkKeepMedia(); if (Build.VERSION.SDK_INT >= 26) { @@ -3352,7 +3488,7 @@ public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, bo return false; } } - if (fragment instanceof ChatActivity) { + if (fragment instanceof ChatActivity && !((ChatActivity) fragment).isInScheduleMode()) { if (!tabletFullSize && layout == rightActionBarLayout || tabletFullSize && layout == actionBarLayout) { boolean result = !(tabletFullSize && layout == actionBarLayout && actionBarLayout.fragmentsStack.size() == 1); if (!layersActionBarLayout.fragmentsStack.isEmpty()) { @@ -3450,7 +3586,7 @@ public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout lay } return false; } - } else if (fragment instanceof ChatActivity) { + } else if (fragment instanceof ChatActivity && !((ChatActivity) fragment).isInScheduleMode()) { if (!tabletFullSize && layout != rightActionBarLayout) { rightActionBarLayout.setVisibility(View.VISIBLE); backgroundTablet.setVisibility(View.GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index 467570ea7c6..eeabba5687b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -65,6 +65,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; @@ -124,6 +125,7 @@ public class LiveLocation { private LinearLayoutManager layoutManager; private AvatarDrawable avatarDrawable; private ActionBarMenuItem otherItem; + private ChatActivity parentFragment; private boolean checkGpsEnabled = true; @@ -174,7 +176,7 @@ public class LiveLocation { public final static int LOCATION_TYPE_GROUP_VIEW = 5; public interface LocationActivityDelegate { - void didSelectLocation(TLRPC.MessageMedia location, int live); + void didSelectLocation(TLRPC.MessageMedia location, int live, boolean notify, int scheduleDate); } public LocationActivity(int type) { @@ -190,7 +192,6 @@ public boolean onFragmentCreate() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.locationPermissionGranted); if (messageObject != null && messageObject.isLiveLocation()) { getNotificationCenter().addObserver(this, NotificationCenter.didReceiveNewMessages); - getNotificationCenter().addObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().addObserver(this, NotificationCenter.replaceMessagesObjects); } return true; @@ -202,7 +203,6 @@ public void onFragmentDestroy() { NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.locationPermissionGranted); getNotificationCenter().removeObserver(this, NotificationCenter.closeChats); getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages); - getNotificationCenter().removeObserver(this, NotificationCenter.messagesDeleted); getNotificationCenter().removeObserver(this, NotificationCenter.replaceMessagesObjects); try { if (googleMap != null) { @@ -442,7 +442,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { return; } if (dialogId == 0) { - delegate.didSelectLocation(venue, LOCATION_TYPE_GROUP); + delegate.didSelectLocation(venue, LOCATION_TYPE_GROUP, true, 0); finishFragment(); } else { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3)}; @@ -459,7 +459,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { } progressDialog[0] = null; - delegate.didSelectLocation(venue, LOCATION_TYPE_GROUP); + delegate.didSelectLocation(venue, LOCATION_TYPE_GROUP, true, 0); finishFragment(); })); progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(requestId, true)); @@ -480,9 +480,16 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { location.geo = new TLRPC.TL_geoPoint(); location.geo.lat = AndroidUtilities.fixLocationCoord(userLocation.getLatitude()); location.geo._long = AndroidUtilities.fixLocationCoord(userLocation.getLongitude()); - delegate.didSelectLocation(location, locationType); + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectLocation(location, locationType, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.didSelectLocation(location, locationType, true, 0); + finishFragment(); + } } - finishFragment(); } else if (position == 2 && locationType == 1 || position == 1 && locationType == 2 || position == 3 && locationType == 3) { if (getLocationController().isSharingLocation(dialogId)) { getLocationController().removeSharingLocation(dialogId); @@ -502,7 +509,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { location.geo.lat = AndroidUtilities.fixLocationCoord(myLocation.getLatitude()); location.geo._long = AndroidUtilities.fixLocationCoord(myLocation.getLongitude()); location.period = param; - delegate.didSelectLocation(location, locationType); + delegate.didSelectLocation(location, locationType, true, 0); finishFragment(); })); } @@ -510,10 +517,15 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { } else { Object object = adapter.getItem(position); if (object instanceof TLRPC.TL_messageMediaVenue) { - if (object != null && delegate != null) { - delegate.didSelectLocation((TLRPC.TL_messageMediaVenue) object, locationType); + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectLocation((TLRPC.TL_messageMediaVenue) object, locationType, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.didSelectLocation((TLRPC.TL_messageMediaVenue) object, locationType, true, 0); + finishFragment(); } - finishFragment(); } else if (object instanceof LiveLocation) { LiveLocation liveLocation = (LiveLocation) object; googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(liveLocation.marker.getPosition(), googleMap.getMaxZoomLevel() - 4)); @@ -651,9 +663,16 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { searchListView.setOnItemClickListener((view, position) -> { TLRPC.TL_messageMediaVenue object = searchAdapter.getItem(position); if (object != null && delegate != null) { - delegate.didSelectLocation(object, locationType); + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectLocation(object, locationType, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.didSelectLocation(object, locationType, true, 0); + finishFragment(); + } } - finishFragment(); }); } else if (messageObject != null && !messageObject.isLiveLocation() || chatLocation != null) { routeButton = new ImageView(context); @@ -1279,6 +1298,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.didReceiveNewMessages) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } long did = (Long) args[0]; if (did != dialogId || messageObject == null) { return; @@ -1295,8 +1318,6 @@ public void didReceivedNotification(int id, int account, Object... args) { if (added && adapter != null) { adapter.setLiveLocations(markers); } - } else if (id == NotificationCenter.messagesDeleted) { - } else if (id == NotificationCenter.replaceMessagesObjects) { long did = (long) args[0]; if (did != dialogId || messageObject == null) { @@ -1381,6 +1402,10 @@ public void setDelegate(LocationActivityDelegate delegate) { this.delegate = delegate; } + public void setChatActivity(ChatActivity chatActivity) { + parentFragment = chatActivity; + } + private void updateSearchInterface() { if (adapter != null) { adapter.notifyDataSetChanged(); @@ -1424,7 +1449,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText), new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 7dc849d1e1c..fa8a71a57db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -520,22 +520,22 @@ private void showEditDoneProgress(final boolean show) { doneProgressView.setTag(1); doneProgressView.setVisibility(View.VISIBLE); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 0.0f), - ObjectAnimator.ofFloat(doneProgressView, "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneProgressView, "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneProgressView, "alpha", 1.0f)); + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(doneProgressView, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(doneProgressView, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(doneProgressView, View.ALPHA, 1.0f)); } else { doneProgressView.setTag(null); doneItem.getContentView().setVisibility(View.VISIBLE); doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(doneProgressView, "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneProgressView, "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneProgressView, "alpha", 0.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 1.0f)); + ObjectAnimator.ofFloat(doneProgressView, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(doneProgressView, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(doneProgressView, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(doneItem.getContentView(), View.ALPHA, 1.0f)); } doneItemAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -1247,6 +1247,12 @@ public void onNextPressed() { req.settings = new TLRPC.TL_codeSettings(); req.settings.allow_flashcall = simcardAvailable && allowCall && allowCancelCall && allowReadCallLog; req.settings.allow_app_hash = ApplicationLoader.hasPlayServices; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + if (req.settings.allow_app_hash) { + preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).commit(); + } else { + preferences.edit().remove("sms_hash").commit(); + } if (req.settings.allow_flashcall) { try { String number = tm.getLine1Number(); @@ -2039,7 +2045,7 @@ private String getCode() { @Override public void onNextPressed() { - if (nextPressed) { + if (nextPressed || currentViewNum < 1 || currentViewNum > 4) { return; } @@ -2063,9 +2069,9 @@ public void onNextPressed() { req.phone_code_hash = phoneHash; destroyTimer(); int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - nextPressed = false; boolean ok = false; if (error == null) { + nextPressed = false; ok = true; needHideProgress(false); destroyTimer(); @@ -2089,6 +2095,7 @@ public void onNextPressed() { ok = true; TLRPC.TL_account_getPassword req2 = new TLRPC.TL_account_getPassword(); ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; needHideProgress(false); if (error1 == null) { TLRPC.TL_account_password password = (TLRPC.TL_account_password) response1; @@ -3174,7 +3181,7 @@ public void invalidate(int l, int t, int r, int b) { } }; avatarImage.setRoundRadius(AndroidUtilities.dp(32)); - avatarDrawable.setInfo(5, null, null, false); + avatarDrawable.setInfo(5, null, null); avatarImage.setImageDrawable(avatarDrawable); editTextContainer.addView(avatarImage, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 0, 16, 0, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index 0da9347efa0..24e15a9343e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -64,7 +64,6 @@ import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BottomSheet; @@ -475,7 +474,7 @@ public void onItemClick(int id) { } else { currentEncryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (dialog_id >> 32)); } - AlertsCreator.createDeleteMessagesAlert(MediaActivity.this, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 1, () -> { + AlertsCreator.createDeleteMessagesAlert(MediaActivity.this, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, false, 1, () -> { actionBar.hideActionMode(); actionBar.closeSearchField(); cantDeleteMessagesCount = 0; @@ -508,9 +507,9 @@ public void onItemClick(int id) { for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, true, 0); } fragment1.finishFragment(); } else { @@ -554,19 +553,15 @@ public void onItemClick(int id) { int lower_part = (int) dialog_id; int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); - if (chat != null && chat.migrated_to != null) { - args.putInt("migrated_to", lower_part); - lower_part = -chat.migrated_to.channel_id; - } - args.putInt("chat_id", -lower_part); + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); + if (chat != null && chat.migrated_to != null) { + args.putInt("migrated_to", lower_part); + lower_part = -chat.migrated_to.channel_id; } + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); @@ -1390,6 +1385,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } TLRPC.Chat currentChat = null; if ((int) dialog_id < 0) { currentChat = MessagesController.getInstance(currentAccount).getChat(-(int) dialog_id); @@ -1435,6 +1434,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.didReceiveNewMessages) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } long uid = (Long) args[0]; if (uid == dialog_id) { ArrayList arr = (ArrayList) args[1]; @@ -1485,6 +1488,10 @@ public void didReceivedNotification(int id, int account, Object... args) { } } } else if (id == NotificationCenter.messageReceivedByServer) { + Boolean scheduled = (Boolean) args[6]; + if (scheduled) { + return; + } Integer msgId = (Integer) args[0]; Integer newMsgId = (Integer) args[1]; for (SharedMediaData data : sharedMediaData) { @@ -1939,7 +1946,7 @@ private boolean onItemLongClick(MessageObject item, View view, int a) { } AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); selectedFiles[item.getDialogId() == dialog_id ? 0 : 1].put(item.getId(), item); - if (!item.canDeleteMessage(null)) { + if (!item.canDeleteMessage(false, null)) { cantDeleteMessagesCount++; } actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); @@ -1982,7 +1989,7 @@ private void onItemClick(int index, View view, MessageObject message, int a, int int loadIndex = message.getDialogId() == dialog_id ? 0 : 1; if (selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0) { selectedFiles[loadIndex].remove(message.getId()); - if (!message.canDeleteMessage(null)) { + if (!message.canDeleteMessage(false, null)) { cantDeleteMessagesCount--; } } else { @@ -1990,7 +1997,7 @@ private void onItemClick(int index, View view, MessageObject message, int a, int return; } selectedFiles[loadIndex].put(message.getId(), message); - if (!message.canDeleteMessage(null)) { + if (!message.canDeleteMessage(false, null)) { cantDeleteMessagesCount++; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MrzCameraActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MrzCameraActivity.java index f84e6154888..b1c54f9a189 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MrzCameraActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MrzCameraActivity.java @@ -169,10 +169,6 @@ public void destroy(boolean async, final Runnable beforeDestroyRunnable) { backgroundHandlerThread.quitSafely(); } - public void cancel() { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStopped, 0); - } - public void hideCamera(boolean async) { destroy(async, null); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java index cfc1b4f7ebb..b28f2341327 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java @@ -182,7 +182,7 @@ public void onItemClick(int id) { }); avatarDrawable = new AvatarDrawable(); - avatarDrawable.setInfo(5, "", "", false); + avatarDrawable.setInfo(5, "", ""); ActionBarMenu menu = actionBar.createMenu(); editDoneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); @@ -244,7 +244,7 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @Override public void afterTextChanged(Editable editable) { - avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString(), false); + avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString()); avatarImage.invalidate(); } }); @@ -286,7 +286,7 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @Override public void afterTextChanged(Editable editable) { - avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString(), false); + avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString()); avatarImage.invalidate(); } }); @@ -720,7 +720,7 @@ public void onAnimationCancel(Animator animation) { public ThemeDescription[] getThemeDescriptions() { ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { if (avatarImage != null) { - avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString(), false); + avatarDrawable.setInfo(5, firstNameField.getText().toString(), lastNameField.getText().toString()); avatarImage.invalidate(); } }; @@ -762,7 +762,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(editDoneItemProgress, 0, null, null, null, null, Theme.key_contextProgressInner2), new ThemeDescription(editDoneItemProgress, 0, null, null, null, null, Theme.key_contextProgressOuter2), - new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), + new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, cellDelegate, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index d4041825cee..f82cd717cf2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -1432,7 +1432,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index 78ec5cbc43c..3dff567c58b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -10,6 +10,7 @@ import android.app.Dialog; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -67,6 +68,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -6277,6 +6279,12 @@ private void startPhoneVerification(boolean checkPermissions, final String phone req.settings = new TLRPC.TL_codeSettings(); req.settings.allow_flashcall = simcardAvailable && allowCall; req.settings.allow_app_hash = ApplicationLoader.hasPlayServices; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + if (req.settings.allow_app_hash) { + preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).commit(); + } else { + preferences.edit().remove("sms_hash").commit(); + } if (req.settings.allow_flashcall) { try { @SuppressLint("HardwareIds") @@ -6804,7 +6812,7 @@ private void createChatAttachView() { chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { @Override - public void didPressedButton(int button, boolean arg) { + public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate) { if (getParentActivity() == null || chatAttachAlert == null) { return; } @@ -6904,7 +6912,7 @@ private void processSelectedAttach(int which) { fragment.setAllowSearchImages(false); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { + public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { processSelectedFiles(photos); } @@ -6930,8 +6938,9 @@ public void startPhotoSelectActivity() { fragment.setCanSelectOnlyImageFiles(true); fragment.setMaxSelectedFiles(getMaxSelectedDocuments()); fragment.setDelegate(new DocumentSelectActivity.DocumentSelectActivityDelegate() { + @Override - public void didSelectFiles(DocumentSelectActivity activity, ArrayList files) { + public void didSelectFiles(DocumentSelectActivity activity, ArrayList files, boolean notify, int scheduleDate) { activity.finishFragment(); ArrayList arrayList = new ArrayList<>(); for (int a = 0, count = files.size(); a < count; a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java index b80c970c37e..b2c5207e54c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java @@ -780,7 +780,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java index 41a634eb04b..e912f914d7b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java @@ -44,6 +44,7 @@ public class PhonebookSelectActivity extends BaseFragment implements Notificatio private EmptyTextProgressView emptyView; private PhonebookAdapter listViewAdapter; private PhonebookSearchAdapter searchListViewAdapter; + private ChatActivity parentFragment; private boolean searchWas; private boolean searching; @@ -51,12 +52,13 @@ public class PhonebookSelectActivity extends BaseFragment implements Notificatio private final static int search_button = 0; - public PhonebookSelectActivity() { + public PhonebookSelectActivity(ChatActivity chatActivity) { super(); + parentFragment = chatActivity; } public interface PhonebookSelectActivityDelegate { - void didSelectContact(TLRPC.User user); + void didSelectContact(TLRPC.User user, boolean notify, int scheduleDate); } @Override @@ -215,9 +217,10 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } PhonebookShareActivity activity = new PhonebookShareActivity(contact, null, null, name); - activity.setDelegate(user -> { + activity.setChatActivity(parentFragment); + activity.setDelegate((user, notify, scheduleDate) -> { removeSelfFromStack(); - delegate.didSelectContact(user); + delegate.didSelectContact(user, notify, scheduleDate); }); presentFragment(activity); } @@ -311,7 +314,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java index dfa7a233d55..f6cb0c2e183 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java @@ -28,6 +28,7 @@ import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -38,6 +39,7 @@ import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBoxSquare; @@ -155,6 +157,7 @@ public boolean isChecked() { private View shadowView; private FrameLayout bottomLayout; private TextView shareTextView; + private ChatActivity parentFragment; private int extraHeight; @@ -734,8 +737,8 @@ public void onClick(DialogInterface dialog, int which) { builder.show(); } else { StringBuilder builder; - if (currentUser.restriction_reason != null) { - builder = new StringBuilder(currentUser.restriction_reason); + if (!currentUser.restriction_reason.isEmpty()) { + builder = new StringBuilder(currentUser.restriction_reason.get(0).text); } else { builder = new StringBuilder(String.format(Locale.US, "BEGIN:VCARD\nVERSION:3.0\nFN:%1$s\nEND:VCARD", ContactsController.formatName(currentUser.first_name, currentUser.last_name))); } @@ -763,10 +766,21 @@ public void onClick(DialogInterface dialog, int which) { builder.insert(idx, item.vcardData.get(b) + "\n"); } } - currentUser.restriction_reason = builder.toString(); + TLRPC.TL_restrictionReason reason = new TLRPC.TL_restrictionReason(); + reason.text = builder.toString(); + reason.reason = ""; + reason.platform = ""; + currentUser.restriction_reason.add(reason); + } + if (parentFragment != null && parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.didSelectContact(currentUser, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.didSelectContact(currentUser, true, 0); + finishFragment(); } - delegate.didSelectContact(currentUser); - finishFragment(); } }); @@ -789,7 +803,7 @@ public void onClick(DialogInterface dialog, int which) { AvatarDrawable avatarDrawable = new AvatarDrawable(); avatarDrawable.setProfile(true); - avatarDrawable.setInfo(5, currentUser.first_name, currentUser.last_name, false); + avatarDrawable.setInfo(5, currentUser.first_name, currentUser.last_name); avatarDrawable.setColor(Theme.getColor(Theme.key_avatar_backgroundInProfileBlue)); avatarImage.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); @@ -798,6 +812,9 @@ public void onClick(DialogInterface dialog, int which) { return fragmentView; } + public void setChatActivity(ChatActivity chatActivity) { + parentFragment = chatActivity; + } @Override public void onResume() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 9723d13a6c3..17760944517 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -8,36 +8,61 @@ package org.telegram.ui; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.InputFilter; +import android.text.TextPaint; import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; +import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; -import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.PhotoPickerAlbumsCell; +import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EditTextEmoji; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.HashMap; @@ -48,19 +73,15 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoAlbumPickerActivityDelegate { - void didSelectPhotos(ArrayList photos); - + void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate); void startPhotoSelectActivity(); } + private CharSequence caption; private HashMap selectedPhotos = new HashMap<>(); private ArrayList selectedPhotosOrder = new ArrayList<>(); private ArrayList albumsSorted = null; - private HashMap recentImagesWebKeys = new HashMap<>(); - private HashMap recentImagesGifKeys = new HashMap<>(); - private ArrayList recentWebImages = new ArrayList<>(); - private ArrayList recentGifImages = new ArrayList<>(); private boolean loading = false; @@ -68,9 +89,7 @@ public interface PhotoAlbumPickerActivityDelegate { private RecyclerListView listView; private ListAdapter listAdapter; private FrameLayout progressView; - private View shadowView; private TextView emptyView; - private PickerBottomLayout pickerBottomLayout; private boolean sendPressed; private int selectPhotoType; private boolean allowSearchImages = true; @@ -80,6 +99,22 @@ public interface PhotoAlbumPickerActivityDelegate { private int maxSelectedPhotos; private boolean allowOrder = true; + private ActionBarPopupWindow sendPopupWindow; + private ActionBarPopupWindow.ActionBarPopupWindowLayout sendPopupLayout; + private ActionBarMenuSubItem[] itemCells; + + private FrameLayout frameLayout2; + private EditTextEmoji commentTextView; + private FrameLayout writeButtonContainer; + private ImageView writeButton; + private Drawable writeButtonDrawable; + private SizeNotifierFrameLayout sizeNotifierFrameLayout; + private View selectedCountView; + private View shadow; + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private RectF rect = new RectF(); + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private PhotoAlbumPickerActivityDelegate delegate; public PhotoAlbumPickerActivity(int selectPhotoType, boolean allowGifs, boolean allowCaption, ChatActivity chatActivity) { @@ -100,15 +135,16 @@ public boolean onFragmentCreate() { loading = albumsSorted == null; MediaController.loadGalleryPhotosAlbums(classGuid); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.albumsDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentImagesDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.closeChats); return super.onFragmentCreate(); } @Override public void onFragmentDestroy() { + if (commentTextView != null) { + commentTextView.onDestroy(); + } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.albumsDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentImagesDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.closeChats); super.onFragmentDestroy(); } @@ -142,21 +178,146 @@ public void onItemClick(int id) { } menu.addItem(1, R.drawable.ic_ab_other).setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - fragmentView = new FrameLayout(context); + sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + + private int lastNotifyWidth; + private boolean ignoreLayout; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + + int keyboardSize = getKeyboardHeight(); + if (keyboardSize <= AndroidUtilities.dp(20)) { + if (!AndroidUtilities.isInMultiwindow) { + heightSize -= commentTextView.getEmojiPadding(); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } + } else { + ignoreLayout = true; + commentTextView.hideEmojiView(); + ignoreLayout = false; + } + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE) { + continue; + } + if (commentTextView != null && commentTextView.isPopupView(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 { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (lastNotifyWidth != r - l) { + lastNotifyWidth = r - l; + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + } + final int count = getChildCount(); + + int paddingBottom = getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.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(); - FrameLayout frameLayout = (FrameLayout) fragmentView; - frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + 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 - l) - width - lp.rightMargin - getPaddingRight(); + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin + getPaddingLeft(); + } + + 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 (commentTextView != null && commentTextView.isPopupView(child)) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + getKeyboardHeight() - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + sizeNotifierFrameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + fragmentView = sizeNotifierFrameLayout; actionBar.setTitle(LocaleController.getString("Gallery", R.string.Gallery)); listView = new RecyclerListView(context); - listView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), AndroidUtilities.dp(4)); + listView.setPadding(AndroidUtilities.dp(6), AndroidUtilities.dp(4), AndroidUtilities.dp(6), AndroidUtilities.dp(54)); listView.setClipToPadding(false); listView.setHorizontalScrollBarEnabled(false); listView.setVerticalScrollBarEnabled(false); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setDrawingCacheEnabled(false); - frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); + sizeNotifierFrameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); listView.setAdapter(listAdapter = new ListAdapter(context)); listView.setGlowColor(Theme.getColor(Theme.key_dialogBackground)); @@ -166,28 +327,211 @@ public void onItemClick(int id) { emptyView.setGravity(Gravity.CENTER); emptyView.setVisibility(View.GONE); emptyView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); - frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); + sizeNotifierFrameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); emptyView.setOnTouchListener((v, event) -> true); progressView = new FrameLayout(context); progressView.setVisibility(View.GONE); - frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); + sizeNotifierFrameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); RadialProgressView progressBar = new RadialProgressView(context); progressBar.setProgressColor(0xff527da3); progressView.addView(progressBar, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - shadowView = new View(context); - shadowView.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); - frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48)); + shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + shadow.setTranslationY(AndroidUtilities.dp(48)); + sizeNotifierFrameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); - pickerBottomLayout = new PickerBottomLayout(context); - frameLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - pickerBottomLayout.cancelButton.setOnClickListener(view -> finishFragment()); - pickerBottomLayout.doneButton.setOnClickListener(view -> { - sendSelectedPhotos(selectedPhotos, selectedPhotosOrder); - finishFragment(); + frameLayout2 = new FrameLayout(context); + frameLayout2.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + frameLayout2.setVisibility(View.INVISIBLE); + frameLayout2.setTranslationY(AndroidUtilities.dp(48)); + sizeNotifierFrameLayout.addView(frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + frameLayout2.setOnTouchListener((v, event) -> true); + + if (commentTextView != null) { + commentTextView.onDestroy(); + } + commentTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, null, EditTextEmoji.STYLE_DIALOG); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(MessagesController.getInstance(UserConfig.selectedAccount).maxCaptionLength); + commentTextView.setFilters(inputFilters); + commentTextView.setHint(LocaleController.getString("AddCaption", R.string.AddCaption)); + EditTextBoldCursor editText = commentTextView.getEditText(); + editText.setMaxLines(1); + editText.setSingleLine(true); + frameLayout2.addView(commentTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 84, 0)); + if (caption != null) { + commentTextView.setText(caption); + } + + writeButtonContainer = new FrameLayout(context); + writeButtonContainer.setVisibility(View.INVISIBLE); + writeButtonContainer.setScaleX(0.2f); + writeButtonContainer.setScaleY(0.2f); + writeButtonContainer.setAlpha(0.0f); + writeButtonContainer.setContentDescription(LocaleController.getString("Send", R.string.Send)); + sizeNotifierFrameLayout.addView(writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10)); + writeButtonContainer.setOnClickListener(v -> { + if (chatActivity != null && chatActivity.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(chatActivity.getCurrentUser()), (notify, scheduleDate) -> { + sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, notify, scheduleDate); + finishFragment(); + }); + } else { + sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, true, 0); + finishFragment(); + } }); + writeButtonContainer.setOnLongClickListener(view -> { + if (chatActivity == null || maxSelectedPhotos == 1) { + return false; + } + TLRPC.Chat chat = chatActivity.getCurrentChat(); + TLRPC.User user = chatActivity.getCurrentUser(); + if (chatActivity.getCurrentEncryptedChat() != null) { + return false; + } + + if (sendPopupLayout == null) { + sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity()); + sendPopupLayout.setAnimationEnabled(false); + sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { + + private android.graphics.Rect popupRect = new android.graphics.Rect(); + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + v.getHitRect(popupRect); + if (!popupRect.contains((int) event.getX(), (int) event.getY())) { + sendPopupWindow.dismiss(); + } + } + } + return false; + } + }); + sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + }); + sendPopupLayout.setShowedFromBotton(false); + + itemCells = new ActionBarMenuSubItem[2]; + for (int a = 0; a < 2; a++) { + if (a == 1 && UserObject.isUserSelf(user)) { + continue; + } + int num = a; + itemCells[a] = new ActionBarMenuSubItem(getParentActivity()); + if (num == 0) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); + } + } else if (num == 1) { + itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + } + itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); + + sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + itemCells[a].setOnClickListener(v -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + if (num == 0) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(chatActivity.getCurrentUser()), (notify, scheduleDate) -> { + sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, notify, scheduleDate); + finishFragment(); + }); + } else if (num == 1) { + sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, true, 0); + finishFragment(); + } + }); + } + + sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + sendPopupWindow.setAnimationEnabled(false); + sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); + sendPopupWindow.setOutsideTouchable(true); + sendPopupWindow.setClippingEnabled(true); + sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + sendPopupWindow.getContentView().setFocusableInTouchMode(true); + } + + sendPopupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + sendPopupWindow.setFocusable(true); + int[] location = new int[2]; + view.getLocationInWindow(location); + sendPopupWindow.showAtLocation(view, Gravity.LEFT | Gravity.TOP, location[0] + view.getMeasuredWidth() - sendPopupLayout.getMeasuredWidth() + AndroidUtilities.dp(8), location[1] - sendPopupLayout.getMeasuredHeight() - AndroidUtilities.dp(2)); + sendPopupWindow.dimBehind(); + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + + return false; + }); + + writeButton = new ImageView(context); + writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Theme.key_dialogFloatingButtonPressed)); + 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, writeButtonDrawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + writeButtonDrawable = combinedDrawable; + } + writeButton.setBackgroundDrawable(writeButtonDrawable); + writeButton.setImageResource(R.drawable.attach_send); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setScaleType(ImageView.ScaleType.CENTER); + if (Build.VERSION.SDK_INT >= 21) { + writeButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + } + }); + } + writeButtonContainer.addView(writeButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.LEFT | Gravity.TOP, Build.VERSION.SDK_INT >= 21 ? 2 : 0, 0, 0, 0)); + + textPaint.setTextSize(AndroidUtilities.dp(12)); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + selectedCountView = new View(context) { + @Override + protected void onDraw(Canvas canvas) { + String text = String.format("%d", Math.max(1, selectedPhotosOrder.size())); + int textSize = (int) Math.ceil(textPaint.measureText(text)); + int size = Math.max(AndroidUtilities.dp(16) + textSize, AndroidUtilities.dp(24)); + int cx = getMeasuredWidth() / 2; + int cy = getMeasuredHeight() / 2; + + textPaint.setColor(Theme.getColor(Theme.key_dialogRoundCheckBoxCheck)); + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + rect.set(cx - size / 2, 0, cx + size / 2, getMeasuredHeight()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(12), AndroidUtilities.dp(12), paint); + + paint.setColor(Theme.getColor(Theme.key_dialogRoundCheckBox)); + rect.set(cx - size / 2 + AndroidUtilities.dp(2), AndroidUtilities.dp(2), cx + size / 2 - AndroidUtilities.dp(2), getMeasuredHeight() - AndroidUtilities.dp(2)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(10), AndroidUtilities.dp(10), paint); + + canvas.drawText(text, cx - textSize / 2, AndroidUtilities.dp(16.2f), textPaint); + } + }; + selectedCountView.setAlpha(0.0f); + selectedCountView.setScaleX(0.2f); + selectedCountView.setScaleY(0.2f); + sizeNotifierFrameLayout.addView(selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -8, 9)); + if (selectPhotoType != 0) { + commentTextView.setVisibility(View.GONE); + } if (loading && (albumsSorted == null || albumsSorted != null && albumsSorted.isEmpty())) { progressView.setVisibility(View.VISIBLE); @@ -196,7 +540,6 @@ public void onItemClick(int id) { progressView.setVisibility(View.GONE); listView.setEmptyView(emptyView); } - pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); return fragmentView; } @@ -207,9 +550,17 @@ public void onResume() { if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + if (commentTextView != null) { + commentTextView.onResume(); + } fixLayout(); } + @Override + public void onPause() { + super.onPause(); + } + @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -240,21 +591,6 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.closeChats) { removeSelfFromStack(); - } else if (id == NotificationCenter.recentImagesDidLoad) { - int type = (Integer) args[0]; - if (type == 0) { - recentWebImages = (ArrayList) args[1]; - recentImagesWebKeys.clear(); - for (MediaController.SearchImage searchImage : recentWebImages) { - recentImagesWebKeys.put(searchImage.id, searchImage); - } - } else if (type == 1) { - recentGifImages = (ArrayList) args[1]; - recentImagesGifKeys.clear(); - for (MediaController.SearchImage searchImage : recentGifImages) { - recentImagesGifKeys.put(searchImage.id, searchImage); - } - } } } @@ -271,13 +607,11 @@ public void setDelegate(PhotoAlbumPickerActivityDelegate delegate) { this.delegate = delegate; } - private void sendSelectedPhotos(HashMap photos, ArrayList order) { + private void sendSelectedPhotos(HashMap photos, ArrayList order, boolean notify, int scheduleDate) { if (photos.isEmpty() || delegate == null || sendPressed) { return; } sendPressed = true; - boolean gifChanged = false; - boolean webChange = false; ArrayList media = new ArrayList<>(); for (int a = 0; a < order.size(); a++) { @@ -311,38 +645,16 @@ private void sendSelectedPhotos(HashMap photos, ArrayList(searchImage.stickers) : null; info.ttl = searchImage.ttl; + if (searchImage.inlineResult != null && searchImage.type == 1) { + info.inlineResult = searchImage.inlineResult; + info.params = searchImage.params; + } searchImage.date = (int) (System.currentTimeMillis() / 1000); - if (searchImage.type == 0) { - webChange = true; - MediaController.SearchImage recentImage = recentImagesWebKeys.get(searchImage.id); - if (recentImage != null) { - recentWebImages.remove(recentImage); - recentWebImages.add(0, recentImage); - } else { - recentWebImages.add(0, searchImage); - } - } else if (searchImage.type == 1) { - gifChanged = true; - MediaController.SearchImage recentImage = recentImagesGifKeys.get(searchImage.id); - if (recentImage != null) { - recentGifImages.remove(recentImage); - recentGifImages.add(0, recentImage); - } else { - recentGifImages.add(0, searchImage); - } - } } } - if (webChange) { - MessagesStorage.getInstance(currentAccount).putWebRecent(recentWebImages); - } - if (gifChanged) { - MessagesStorage.getInstance(currentAccount).putWebRecent(recentGifImages); - } - - delegate.didSelectPhotos(media); + delegate.didSelectPhotos(media, notify, scheduleDate); } private void fixLayout() { @@ -361,6 +673,21 @@ public boolean onPreDraw() { } } + private void applyCaption() { + if (commentTextView.length() <= 0) { + return; + } + int imageId = (Integer) selectedPhotosOrder.get(0); + Object entry = selectedPhotos.get(imageId); + if (entry instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) entry; + photoEntry.caption = commentTextView.getText().toString(); + } else if (entry instanceof MediaController.SearchImage) { + MediaController.SearchImage searchImage = (MediaController.SearchImage) entry; + searchImage.caption = commentTextView.getText().toString(); + } + } + private void fixLayoutInternal() { if (getParentActivity() == null) { return; @@ -375,32 +702,68 @@ private void fixLayoutInternal() { listAdapter.notifyDataSetChanged(); } - private void openPhotoPicker(MediaController.AlbumEntry albumEntry, int type) { - ArrayList recentImages = null; - if (albumEntry == null) { - if (type == 0) { - recentImages = recentWebImages; - } else if (type == 1) { - recentImages = recentGifImages; - } + private boolean showCommentTextView(boolean show) { + if (show == (frameLayout2.getTag() != null)) { + return false; + } + frameLayout2.setTag(show ? 1 : null); + if (commentTextView.getEditText().isFocused()) { + AndroidUtilities.hideKeyboard(commentTextView.getEditText()); + } + commentTextView.hidePopup(true); + if (show) { + frameLayout2.setVisibility(View.VISIBLE); + writeButtonContainer.setVisibility(View.VISIBLE); + } else { + frameLayout2.setVisibility(View.INVISIBLE); + writeButtonContainer.setVisibility(View.INVISIBLE); } + writeButtonContainer.setScaleX(show ? 1.0f : 0.2f); + writeButtonContainer.setScaleY(show ? 1.0f : 0.2f); + writeButtonContainer.setAlpha(show ? 1.0f : 0.0f); + selectedCountView.setScaleX(show ? 1.0f : 0.2f); + selectedCountView.setScaleY(show ? 1.0f : 0.2f); + selectedCountView.setAlpha(show ? 1.0f : 0.0f); + frameLayout2.setTranslationY(show ? 0 : AndroidUtilities.dp(48)); + shadow.setTranslationY(show ? 0 : AndroidUtilities.dp(48)); + return true; + } + + private void updatePhotosButton() { + int count = selectedPhotos.size(); + + if (count == 0) { + selectedCountView.setPivotX(0); + selectedCountView.setPivotY(0); + showCommentTextView(false); + } else { + selectedCountView.invalidate(); + showCommentTextView(true); + } + } + + private void openPhotoPicker(MediaController.AlbumEntry albumEntry, int type) { if (albumEntry != null) { - PhotoPickerActivity fragment = new PhotoPickerActivity(type, albumEntry, selectedPhotos, selectedPhotosOrder, recentImages, selectPhotoType, allowCaption, chatActivity); + PhotoPickerActivity fragment = new PhotoPickerActivity(type, albumEntry, selectedPhotos, selectedPhotosOrder, null, selectPhotoType, allowCaption, chatActivity); + fragment.setCaption(caption = commentTextView.getText()); fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { - if (pickerBottomLayout != null) { - pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); - } + updatePhotosButton(); } @Override - public void actionButtonPressed(boolean canceled) { + public void actionButtonPressed(boolean canceled, boolean notify, int scheduleDate) { removeSelfFromStack(); if (!canceled) { - sendSelectedPhotos(selectedPhotos, selectedPhotosOrder); + sendSelectedPhotos(selectedPhotos, selectedPhotosOrder, notify, scheduleDate); } } + + @Override + public void onCaptionChanged(CharSequence text) { + commentTextView.setText(caption = text); + } }); fragment.setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); presentFragment(fragment); @@ -408,7 +771,8 @@ public void actionButtonPressed(boolean canceled) { final HashMap photos = new HashMap<>(); final ArrayList order = new ArrayList<>(); if (allowGifs) { - PhotoPickerSearchActivity fragment = new PhotoPickerSearchActivity(photos, order, recentImages, selectPhotoType, allowCaption, chatActivity); + PhotoPickerSearchActivity fragment = new PhotoPickerSearchActivity(photos, order, null, selectPhotoType, allowCaption, chatActivity); + fragment.setCaption(caption = commentTextView.getText()); fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { @@ -416,17 +780,23 @@ public void selectedPhotosChanged() { } @Override - public void actionButtonPressed(boolean canceled) { + public void actionButtonPressed(boolean canceled, boolean notify, int scheduleDate) { removeSelfFromStack(); if (!canceled) { - sendSelectedPhotos(photos, order); + sendSelectedPhotos(photos, order, notify, scheduleDate); } } + + @Override + public void onCaptionChanged(CharSequence text) { + commentTextView.setText(caption = text); + } }); fragment.setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); presentFragment(fragment); } else { - PhotoPickerActivity fragment = new PhotoPickerActivity(0, albumEntry, photos, order, recentImages, selectPhotoType, allowCaption, chatActivity); + PhotoPickerActivity fragment = new PhotoPickerActivity(0, albumEntry, photos, order, null, selectPhotoType, allowCaption, chatActivity); + fragment.setCaption(caption = commentTextView.getText()); fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { @@ -434,12 +804,17 @@ public void selectedPhotosChanged() { } @Override - public void actionButtonPressed(boolean canceled) { + public void actionButtonPressed(boolean canceled, boolean notify, int scheduleDate) { removeSelfFromStack(); if (!canceled) { - sendSelectedPhotos(photos, order); + sendSelectedPhotos(photos, order, notify, scheduleDate); } } + + @Override + public void onCaptionChanged(CharSequence text) { + commentTextView.setText(caption = text); + } }); fragment.setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); presentFragment(fragment); @@ -506,15 +881,6 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_dialogBackground), - new ThemeDescription(shadowView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_dialogShadowLine), - - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_dialogBackground), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{PickerBottomLayout.class}, new String[]{"cancelButton"}, null, null, null, Theme.key_picker_enabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonTextView"}, null, null, null, Theme.key_picker_enabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonTextView"}, null, null, null, Theme.key_picker_disabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonBadgeTextView"}, null, null, null, Theme.key_picker_badgeText), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonBadgeTextView"}, null, null, null, Theme.key_picker_badge), - new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{Theme.chat_attachEmptyDrawable}, null, Theme.key_chat_attachEmptyImage), new ThemeDescription(listView, 0, new Class[]{View.class}, null, null, null, Theme.key_chat_attachPhotoBackground), }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index ecc8b9e49e5..987ae9418ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -8,20 +8,38 @@ package org.telegram.ui; -import android.app.Activity; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.Rect; +import android.graphics.Canvas; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Build; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextPaint; import android.text.TextUtils; +import android.text.TextWatcher; import android.view.Gravity; -import android.view.Surface; +import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; +import android.view.ViewOutlineProvider; import android.view.WindowManager; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.OvershootInterpolator; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -32,8 +50,9 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.messenger.VideoEditedInfo; -import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; @@ -41,20 +60,24 @@ import org.telegram.messenger.MessageObject; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Cells.PhotoPickerPhotoCell; +import org.telegram.ui.Cells.PhotoAttachPhotoCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EditTextEmoji; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.RecyclerViewItemRangeSelector; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.HashMap; @@ -66,12 +89,14 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen public interface PhotoPickerActivityDelegate { void selectedPhotosChanged(); - void actionButtonPressed(boolean canceled); + void actionButtonPressed(boolean canceled, boolean notify, int scheduleDate); + void onCaptionChanged(CharSequence caption); } private int type; private HashMap selectedPhotos; private ArrayList selectedPhotosOrder; + private CharSequence caption; private boolean allowIndices; private ArrayList recentImages; @@ -98,14 +123,33 @@ public interface PhotoPickerActivityDelegate { private RecyclerListView listView; private ListAdapter listAdapter; private GridLayoutManager layoutManager; - private PickerBottomLayout pickerBottomLayout; private EmptyTextProgressView emptyView; - private View shadowView; private ActionBarMenuItem searchItem; - private int itemWidth = 100; + private int itemSize = 100; private boolean sendPressed; private int selectPhotoType; private ChatActivity chatActivity; + private RecyclerViewItemRangeSelector itemRangeSelector; + private int alertOnlyOnce; + private boolean shouldSelect; + + protected FrameLayout frameLayout2; + protected FrameLayout writeButtonContainer; + protected View selectedCountView; + protected View shadow; + protected EditTextEmoji commentTextView; + private ImageView writeButton; + private Drawable writeButtonDrawable; + private SizeNotifierFrameLayout sizeNotifierFrameLayout; + private int itemsPerRow = 3; + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private RectF rect = new RectF(); + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private AnimatorSet animatorSet; + + private ActionBarPopupWindow sendPopupWindow; + private ActionBarPopupWindow.ActionBarPopupWindowLayout sendPopupLayout; + private ActionBarMenuSubItem[] itemCells; private String initialSearchString; @@ -121,17 +165,18 @@ public boolean scaleToFill() { @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { - PhotoPickerPhotoCell cell = getCellForIndex(index); + PhotoAttachPhotoCell cell = getCellForIndex(index); if (cell != null) { + BackupImageView imageView = cell.getImageView(); int[] coords = new int[2]; - cell.imageView.getLocationInWindow(coords); + imageView.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight); object.parentView = listView; - object.imageReceiver = cell.imageView.getImageReceiver(); + object.imageReceiver = imageView.getImageReceiver(); object.thumb = object.imageReceiver.getBitmapSafe(); - object.scale = cell.imageView.getScaleX(); + object.scale = cell.getScale(); cell.showCheck(false); return object; } @@ -140,22 +185,23 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj @Override public void updatePhotoAtIndex(int index) { - PhotoPickerPhotoCell cell = getCellForIndex(index); + PhotoAttachPhotoCell cell = getCellForIndex(index); if (cell != null) { if (selectedAlbum != null) { - cell.imageView.setOrientation(0, true); + BackupImageView imageView = cell.getImageView(); + imageView.setOrientation(0, true); MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index); if (photoEntry.thumbPath != null) { - cell.imageView.setImage(photoEntry.thumbPath, null, Theme.chat_attachEmptyDrawable); + imageView.setImage(photoEntry.thumbPath, null, Theme.chat_attachEmptyDrawable); } else if (photoEntry.path != null) { - cell.imageView.setOrientation(photoEntry.orientation, true); + imageView.setOrientation(photoEntry.orientation, true); if (photoEntry.isVideo) { - cell.imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable); + imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable); } else { - cell.imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable); + imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable); } } else { - cell.imageView.setImageDrawable(Theme.chat_attachEmptyDrawable); + imageView.setImageDrawable(Theme.chat_attachEmptyDrawable); } } else { ArrayList array; @@ -164,7 +210,7 @@ public void updatePhotoAtIndex(int index) { } else { array = searchResult; } - cell.setImage(array.get(index)); + cell.setPhotoEntry(array.get(index), true, false); } } } @@ -176,9 +222,9 @@ public boolean allowCaption() { @Override public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { - PhotoPickerPhotoCell cell = getCellForIndex(index); + PhotoAttachPhotoCell cell = getCellForIndex(index); if (cell != null) { - return cell.imageView.getImageReceiver().getBitmapSafe(); + return cell.getImageView().getImageReceiver().getBitmapSafe(); } return null; } @@ -191,7 +237,7 @@ public void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation if (view.getTag() == null) { continue; } - PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; int num = (Integer) view.getTag(); if (selectedAlbum != null) { if (num < 0 || num >= selectedAlbum.photos.size()) { @@ -220,8 +266,8 @@ public void willHidePhotoViewer() { int count = listView.getChildCount(); for (int a = 0; a < count; a++) { View view = listView.getChildAt(a); - if (view instanceof PhotoPickerPhotoCell) { - PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; cell.showCheck(true); } } @@ -305,18 +351,18 @@ public int setPhotoChecked(int index, VideoEditedInfo videoEditedInfo) { View view = listView.getChildAt(a); int tag = (Integer) view.getTag(); if (tag == index) { - ((PhotoPickerPhotoCell) view).setChecked(allowIndices ? num : -1, add, false); + ((PhotoAttachPhotoCell) view).setChecked(allowIndices ? num : -1, add, false); break; } } - pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); + updatePhotosButton(add ? 1 : 2); delegate.selectedPhotosChanged(); return num; } @Override public boolean cancelButtonPressed() { - delegate.actionButtonPressed(true); + delegate.actionButtonPressed(true, true, 0); finishFragment(); return true; } @@ -327,7 +373,7 @@ public int getSelectedCount() { } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { if (selectedPhotos.isEmpty()) { if (selectedAlbum != null) { if (index < 0 || index >= selectedAlbum.photos.size()) { @@ -349,7 +395,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { addToSelectedPhotos(array.get(index), -1); } } - sendSelectedPhotos(); + sendSelectedPhotos(notify, scheduleDate); } @Override @@ -369,7 +415,7 @@ public PhotoPickerActivity(int type, MediaController.AlbumEntry selectedAlbum, H this.selectedPhotos = selectedPhotos; this.selectedPhotosOrder = selectedPhotosOrder; this.type = type; - this.recentImages = recentImages; + this.recentImages = recentImages != null ? recentImages : new ArrayList<>(); this.selectPhotoType = selectPhotoType; this.chatActivity = chatActivity; this.allowCaption = allowCaption; @@ -396,6 +442,9 @@ public void onFragmentDestroy() { ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); imageReqId = 0; } + if (commentTextView != null) { + commentTextView.onDestroy(); + } super.onFragmentDestroy(); } @@ -478,12 +527,167 @@ public void onSearchPressed(EditText editText) { } } - FrameLayout frameLayout = new FrameLayout(context); - frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); - fragmentView = frameLayout; + sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + + private int lastNotifyWidth; + private boolean ignoreLayout; + private int lastItemSize; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int totalHeight = MeasureSpec.getSize(heightMeasureSpec); + + int availableWidth = MeasureSpec.getSize(widthMeasureSpec); + if (AndroidUtilities.isTablet()) { + itemsPerRow = 4; + } else if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + itemsPerRow = 4; + } else { + itemsPerRow = 3; + } + + ignoreLayout = true; + itemSize = (availableWidth - AndroidUtilities.dp(6 * 2) - AndroidUtilities.dp(5 * 2)) / itemsPerRow; + + if (lastItemSize != itemSize) { + lastItemSize = itemSize; + AndroidUtilities.runOnUIThread(() -> listAdapter.notifyDataSetChanged()); + } + layoutManager.setSpanCount(itemSize * itemsPerRow + AndroidUtilities.dp(5) * (itemsPerRow - 1)); + + ignoreLayout = false; + onMeasureInternal(widthMeasureSpec, MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY)); + } + + private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + + int keyboardSize = getKeyboardHeight(); + if (keyboardSize <= AndroidUtilities.dp(20)) { + if (!AndroidUtilities.isInMultiwindow && commentTextView != null && frameLayout2.getParent() == this) { + heightSize -= commentTextView.getEmojiPadding(); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } + } else if (commentTextView != null) { + ignoreLayout = true; + commentTextView.hideEmojiView(); + ignoreLayout = false; + } + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE) { + continue; + } + if (commentTextView != null && commentTextView.isPopupView(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 { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (lastNotifyWidth != r - l) { + lastNotifyWidth = r - l; + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + } + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + } + final int count = getChildCount(); + + int paddingBottom = commentTextView != null && frameLayout2.getParent() == this && getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.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 - l) - width - lp.rightMargin - getPaddingRight(); + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin + getPaddingLeft(); + } + + 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 (commentTextView != null && commentTextView.isPopupView(child)) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + getKeyboardHeight() - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + sizeNotifierFrameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + fragmentView = sizeNotifierFrameLayout; listView = new RecyclerListView(context); - listView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4)); + listView.setPadding(AndroidUtilities.dp(6), AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(50)); listView.setClipToPadding(false); listView.setHorizontalScrollBarEnabled(false); listView.setVerticalScrollBarEnabled(false); @@ -495,21 +699,13 @@ public boolean supportsPredictiveItemAnimations() { return false; } }); - listView.addItemDecoration(new RecyclerView.ItemDecoration() { + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - super.getItemOffsets(outRect, view, parent, state); - int total = state.getItemCount(); - int position = parent.getChildAdapterPosition(view); - int spanCount = layoutManager.getSpanCount(); - int rowsCOunt = (int) Math.ceil(total / (float) spanCount); - int row = position / spanCount; - int col = position % spanCount; - outRect.right = col != spanCount - 1 ? AndroidUtilities.dp(4) : 0; - outRect.bottom = row != rowsCOunt - 1 ? AndroidUtilities.dp(4) : 0; + public int getSpanSize(int position) { + return itemSize + (position % itemsPerRow != itemsPerRow - 1 ? AndroidUtilities.dp(5) : 0); } }); - frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, selectPhotoType != 0 ? 0 : 48)); + sizeNotifierFrameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); listView.setAdapter(listAdapter = new ListAdapter(context)); listView.setGlowColor(Theme.getColor(Theme.key_dialogBackground)); listView.setOnItemClickListener((view, position) -> { @@ -543,8 +739,63 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle PhotoViewer.getInstance().setMaxSelectedPhotos(maxSelectedPhotos, allowOrder); PhotoViewer.getInstance().openPhotoForSelect(arrayList, position, type, provider, chatActivity); }); + listView.setOnItemLongClickListener((view, position) -> { + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + itemRangeSelector.setIsActive(view, true, position, shouldSelect = !cell.isChecked()); + } + return false; + }); + itemRangeSelector = new RecyclerViewItemRangeSelector(new RecyclerViewItemRangeSelector.RecyclerViewItemRangeSelectorDelegate() { + @Override + public int getItemCount() { + return listAdapter.getItemCount(); + } - if (selectedAlbum == null) { + @Override + public void setSelected(View view, int index, boolean selected) { + if (selected != shouldSelect || !(view instanceof PhotoAttachPhotoCell)) { + return; + } + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + cell.callDelegate(); + } + + @Override + public boolean isSelected(int index) { + Object key; + if (selectedAlbum != null) { + MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index); + key = photoEntry.imageId; + } else { + MediaController.SearchImage photoEntry; + if (searchResult.isEmpty() && lastSearchString == null) { + photoEntry = recentImages.get(index); + } else { + photoEntry = searchResult.get(index); + } + key = photoEntry.id; + } + return selectedPhotos.containsKey(key); + } + + @Override + public boolean isIndexSelectable(int index) { + return listAdapter.getItemViewType(index) == 0; + } + + @Override + public void onStartStopSelection(boolean start) { + alertOnlyOnce = start ? 1 : 0; + if (start) { + parentLayout.requestDisallowInterceptTouchEvent(true); + } + listView.hideSelector(); + } + }); + listView.addOnItemTouchListener(itemRangeSelector); + + /*if (selectedAlbum == null) { listView.setOnItemLongClickListener((view, position) -> { if (searchResult.isEmpty() && lastSearchString == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -563,7 +814,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle } return false; }); - } + }*/ emptyView = new EmptyTextProgressView(context); emptyView.setTextColor(0xff808080); @@ -579,7 +830,7 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle emptyView.setText(LocaleController.getString("NoRecentGIFs", R.string.NoRecentGIFs)); }*/ } - frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, selectPhotoType != 0 ? 0 : 48)); + sizeNotifierFrameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, selectPhotoType != 0 ? 0 : 48)); if (selectedAlbum == null) { listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @@ -609,37 +860,242 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { } if (needsBottomLayout) { - shadowView = new View(context); - shadowView.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); - frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48)); - - pickerBottomLayout = new PickerBottomLayout(context); - frameLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); - pickerBottomLayout.cancelButton.setOnClickListener(view -> { - delegate.actionButtonPressed(true); - finishFragment(); + shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + shadow.setTranslationY(AndroidUtilities.dp(48)); + sizeNotifierFrameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); + + frameLayout2 = new FrameLayout(context); + frameLayout2.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + frameLayout2.setVisibility(View.INVISIBLE); + frameLayout2.setTranslationY(AndroidUtilities.dp(48)); + sizeNotifierFrameLayout.addView(frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + frameLayout2.setOnTouchListener((v, event) -> true); + + if (commentTextView != null) { + commentTextView.onDestroy(); + } + commentTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, null, EditTextEmoji.STYLE_DIALOG); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(MessagesController.getInstance(UserConfig.selectedAccount).maxCaptionLength); + commentTextView.setFilters(inputFilters); + commentTextView.setHint(LocaleController.getString("AddCaption", R.string.AddCaption)); + commentTextView.onResume(); + EditTextBoldCursor editText = commentTextView.getEditText(); + editText.setMaxLines(1); + editText.setSingleLine(true); + frameLayout2.addView(commentTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 84, 0)); + if (caption != null) { + commentTextView.setText(caption); + } + commentTextView.getEditText().addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (delegate != null) { + delegate.onCaptionChanged(s); + } + } + }); + + writeButtonContainer = new FrameLayout(context); + writeButtonContainer.setVisibility(View.INVISIBLE); + writeButtonContainer.setScaleX(0.2f); + writeButtonContainer.setScaleY(0.2f); + writeButtonContainer.setAlpha(0.0f); + writeButtonContainer.setContentDescription(LocaleController.getString("Send", R.string.Send)); + sizeNotifierFrameLayout.addView(writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10)); + writeButtonContainer.setOnClickListener(v -> { + if (chatActivity != null && chatActivity.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(chatActivity.getCurrentUser()), this::sendSelectedPhotos); + } else { + sendSelectedPhotos(true, 0); + } }); - pickerBottomLayout.doneButton.setOnClickListener(view -> sendSelectedPhotos()); + writeButtonContainer.setOnLongClickListener(view -> { + if (chatActivity == null || maxSelectedPhotos == 1) { + return false; + } + TLRPC.Chat chat = chatActivity.getCurrentChat(); + TLRPC.User user = chatActivity.getCurrentUser(); + if (chatActivity.getCurrentEncryptedChat() != null) { + return false; + } + + if (sendPopupLayout == null) { + sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity()); + sendPopupLayout.setAnimationEnabled(false); + sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { + + private android.graphics.Rect popupRect = new android.graphics.Rect(); + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + v.getHitRect(popupRect); + if (!popupRect.contains((int) event.getX(), (int) event.getY())) { + sendPopupWindow.dismiss(); + } + } + } + return false; + } + }); + sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + }); + sendPopupLayout.setShowedFromBotton(false); + + itemCells = new ActionBarMenuSubItem[2]; + for (int a = 0; a < 2; a++) { + if (a == 1 && UserObject.isUserSelf(user)) { + continue; + } + int num = a; + itemCells[a] = new ActionBarMenuSubItem(getParentActivity()); + if (num == 0) { + if (UserObject.isUserSelf(user)) { + itemCells[a].setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); + } else { + itemCells[a].setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); + } + } else if (num == 1) { + itemCells[a].setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + } + itemCells[a].setMinimumWidth(AndroidUtilities.dp(196)); + + sendPopupLayout.addView(itemCells[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a, 0, 0)); + itemCells[a].setOnClickListener(v -> { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + if (num == 0) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(chatActivity.getCurrentUser()), this::sendSelectedPhotos); + } else if (num == 1) { + sendSelectedPhotos(true, 0); + } + }); + } + + sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + sendPopupWindow.setAnimationEnabled(false); + sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); + sendPopupWindow.setOutsideTouchable(true); + sendPopupWindow.setClippingEnabled(true); + sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + sendPopupWindow.getContentView().setFocusableInTouchMode(true); + } + + sendPopupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + sendPopupWindow.setFocusable(true); + int[] location = new int[2]; + view.getLocationInWindow(location); + sendPopupWindow.showAtLocation(view, Gravity.LEFT | Gravity.TOP, location[0] + view.getMeasuredWidth() - sendPopupLayout.getMeasuredWidth() + AndroidUtilities.dp(8), location[1] - sendPopupLayout.getMeasuredHeight() - AndroidUtilities.dp(2)); + sendPopupWindow.dimBehind(); + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + + return false; + }); + + writeButton = new ImageView(context); + writeButtonDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_dialogFloatingButton), Theme.getColor(Theme.key_dialogFloatingButtonPressed)); + 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, writeButtonDrawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + writeButtonDrawable = combinedDrawable; + } + writeButton.setBackgroundDrawable(writeButtonDrawable); + writeButton.setImageResource(R.drawable.attach_send); + writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); + writeButton.setScaleType(ImageView.ScaleType.CENTER); + if (Build.VERSION.SDK_INT >= 21) { + writeButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + } + }); + } + writeButtonContainer.addView(writeButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.LEFT | Gravity.TOP, Build.VERSION.SDK_INT >= 21 ? 2 : 0, 0, 0, 0)); + + textPaint.setTextSize(AndroidUtilities.dp(12)); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + selectedCountView = new View(context) { + @Override + protected void onDraw(Canvas canvas) { + String text = String.format("%d", Math.max(1, selectedPhotosOrder.size())); + int textSize = (int) Math.ceil(textPaint.measureText(text)); + int size = Math.max(AndroidUtilities.dp(16) + textSize, AndroidUtilities.dp(24)); + int cx = getMeasuredWidth() / 2; + int cy = getMeasuredHeight() / 2; + + textPaint.setColor(Theme.getColor(Theme.key_dialogRoundCheckBoxCheck)); + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + rect.set(cx - size / 2, 0, cx + size / 2, getMeasuredHeight()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(12), AndroidUtilities.dp(12), paint); + + paint.setColor(Theme.getColor(Theme.key_dialogRoundCheckBox)); + rect.set(cx - size / 2 + AndroidUtilities.dp(2), AndroidUtilities.dp(2), cx + size / 2 - AndroidUtilities.dp(2), getMeasuredHeight() - AndroidUtilities.dp(2)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(10), AndroidUtilities.dp(10), paint); + + canvas.drawText(text, cx - textSize / 2, AndroidUtilities.dp(16.2f), textPaint); + } + }; + selectedCountView.setAlpha(0.0f); + selectedCountView.setScaleX(0.2f); + selectedCountView.setScaleY(0.2f); + sizeNotifierFrameLayout.addView(selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -8, 9)); if (selectPhotoType != 0) { - pickerBottomLayout.setVisibility(View.GONE); - shadowView.setVisibility(View.GONE); + commentTextView.setVisibility(View.GONE); } } allowIndices = (selectedAlbum != null || type == 0) && allowOrder; listView.setEmptyView(emptyView); - pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); + updatePhotosButton(0); return fragmentView; } - public void setPickerBottomLayout(PickerBottomLayout bottomLayout) { - pickerBottomLayout = bottomLayout; + public void setLayoutViews(FrameLayout f2, FrameLayout button, View count, View s, EditTextEmoji emoji) { + frameLayout2 = f2; + writeButtonContainer = button; + commentTextView = emoji; + selectedCountView = count; + shadow = s; needsBottomLayout = false; } - public PickerBottomLayout getPickerBottomLayout() { - return pickerBottomLayout; + private void applyCaption() { + if (commentTextView == null || commentTextView.length() <= 0) { + return; + } + Object imageId = selectedPhotosOrder.get(0); + Object entry = selectedPhotos.get(imageId); + if (entry instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) entry; + photoEntry.caption = commentTextView.getText().toString(); + } else if (entry instanceof MediaController.SearchImage) { + MediaController.SearchImage searchImage = (MediaController.SearchImage) entry; + searchImage.caption = commentTextView.getText().toString(); + } } @Override @@ -648,6 +1104,9 @@ public void onResume() { if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + if (commentTextView != null) { + commentTextView.onResume(); + } if (searchItem != null) { searchItem.openSearch(true); if (!TextUtils.isEmpty(initialSearchString)) { @@ -655,15 +1114,13 @@ public void onResume() { initialSearchString = null; processSearch(searchItem.getSearchField()); } - getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } - fixLayout(); } @Override - public void onConfigurationChanged(android.content.res.Configuration newConfig) { - super.onConfigurationChanged(newConfig); - fixLayout(); + public void onPause() { + super.onPause(); } @SuppressWarnings("unchecked") @@ -684,6 +1141,13 @@ public RecyclerListView getListView() { return listView; } + public void setCaption(CharSequence text) { + caption = text; + if (commentTextView != null) { + commentTextView.setText(caption); + } + } + public void setInitialSearchString(String text) { initialSearchString = text; } @@ -711,10 +1175,81 @@ private void processSearch(EditText editText) { updateSearchInterface(); } + private boolean showCommentTextView(boolean show, boolean animated) { + if (commentTextView == null) { + return false; + } + if (show == (frameLayout2.getTag() != null)) { + return false; + } + if (animatorSet != null) { + animatorSet.cancel(); + } + frameLayout2.setTag(show ? 1 : null); + if (commentTextView.getEditText().isFocused()) { + AndroidUtilities.hideKeyboard(commentTextView.getEditText()); + } + commentTextView.hidePopup(true); + if (show) { + frameLayout2.setVisibility(View.VISIBLE); + writeButtonContainer.setVisibility(View.VISIBLE); + } + if (animated) { + animatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(writeButtonContainer, View.SCALE_X, show ? 1.0f : 0.2f)); + animators.add(ObjectAnimator.ofFloat(writeButtonContainer, View.SCALE_Y, show ? 1.0f : 0.2f)); + animators.add(ObjectAnimator.ofFloat(writeButtonContainer, View.ALPHA, show ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(selectedCountView, View.SCALE_X, show ? 1.0f : 0.2f)); + animators.add(ObjectAnimator.ofFloat(selectedCountView, View.SCALE_Y, show ? 1.0f : 0.2f)); + animators.add(ObjectAnimator.ofFloat(selectedCountView, View.ALPHA, show ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(frameLayout2, View.TRANSLATION_Y, show ? 0 : AndroidUtilities.dp(48))); + animators.add(ObjectAnimator.ofFloat(shadow, View.TRANSLATION_Y, show ? 0 : AndroidUtilities.dp(48))); + + animatorSet.playTogether(animators); + animatorSet.setInterpolator(new DecelerateInterpolator()); + animatorSet.setDuration(180); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(animatorSet)) { + if (!show) { + frameLayout2.setVisibility(View.INVISIBLE); + writeButtonContainer.setVisibility(View.INVISIBLE); + } + animatorSet = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (animation.equals(animatorSet)) { + animatorSet = null; + } + } + }); + animatorSet.start(); + } else { + writeButtonContainer.setScaleX(show ? 1.0f : 0.2f); + writeButtonContainer.setScaleY(show ? 1.0f : 0.2f); + writeButtonContainer.setAlpha(show ? 1.0f : 0.0f); + selectedCountView.setScaleX(show ? 1.0f : 0.2f); + selectedCountView.setScaleY(show ? 1.0f : 0.2f); + selectedCountView.setAlpha(show ? 1.0f : 0.0f); + frameLayout2.setTranslationY(show ? 0 : AndroidUtilities.dp(48)); + shadow.setTranslationY(show ? 0 : AndroidUtilities.dp(48)); + if (!show) { + frameLayout2.setVisibility(View.INVISIBLE); + writeButtonContainer.setVisibility(View.INVISIBLE); + } + } + return true; + } + public void setMaxSelectedPhotos(int value, boolean order) { maxSelectedPhotos = value; allowOrder = order; - if (value >= 0 && type == 1) { + if (value > 0 && type == 1) { maxSelectedPhotos = 1; } } @@ -726,8 +1261,8 @@ private void updateCheckedPhotoIndices() { int count = listView.getChildCount(); for (int a = 0; a < count; a++) { View view = listView.getChildAt(a); - if (view instanceof PhotoPickerPhotoCell) { - PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; Integer index = (Integer) cell.getTag(); if (selectedAlbum != null) { MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index); @@ -745,14 +1280,14 @@ private void updateCheckedPhotoIndices() { } } - private PhotoPickerPhotoCell getCellForIndex(int index) { + private PhotoAttachPhotoCell getCellForIndex(int index) { int count = listView.getChildCount(); for (int a = 0; a < count; a++) { View view = listView.getChildAt(a); - if (view instanceof PhotoPickerPhotoCell) { - PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) view; - int num = (Integer) cell.imageView.getTag(); + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + int num = (Integer) cell.getTag(); if (selectedAlbum != null) { if (num < 0 || num >= selectedAlbum.photos.size()) { continue; @@ -818,6 +1353,32 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { } } + public void updatePhotosButton(int animated) { + int count = selectedPhotos.size(); + + if (count == 0) { + selectedCountView.setPivotX(0); + selectedCountView.setPivotY(0); + showCommentTextView(false, animated != 0); + } else { + selectedCountView.invalidate(); + if (!showCommentTextView(true, animated != 0) && animated != 0) { + selectedCountView.setPivotX(AndroidUtilities.dp(21)); + selectedCountView.setPivotY(AndroidUtilities.dp(12)); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether( + ObjectAnimator.ofFloat(selectedCountView, View.SCALE_X, animated == 1 ? 1.1f : 0.9f, 1.0f), + ObjectAnimator.ofFloat(selectedCountView, View.SCALE_Y, animated == 1 ? 1.1f : 0.9f, 1.0f)); + animatorSet.setInterpolator(new OvershootInterpolator()); + animatorSet.setDuration(180); + animatorSet.start(); + } else { + selectedCountView.setPivotX(0); + selectedCountView.setPivotY(0); + } + } + } + private void updateSearchInterface() { if (listAdapter != null) { listAdapter.notifyDataSetChanged(); @@ -898,6 +1459,7 @@ private void searchImages(boolean gif, final String query, final String offset, int addedCount = 0; int oldCount = searchResult.size(); if (response != null) { + TLRPC.messages_BotResults res = (TLRPC.messages_BotResults) response; nextImagesSearchOffset = res.next_offset; @@ -924,7 +1486,7 @@ private void searchImages(boolean gif, final String query, final String offset, image.document = result.document; image.size = 0; if (result.photo != null && result.document != null) { - TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, itemWidth, true); + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, itemSize, true); if (size != null) { result.document.thumbs.add(size); result.document.flags |= 1; @@ -965,7 +1527,11 @@ private void searchImages(boolean gif, final String query, final String offset, image.id = result.id; image.type = gif ? 1 : 0; - image.localUrl = ""; + image.inlineResult = result; + image.params = new HashMap<>(); + image.params.put("id", result.id); + image.params.put("query_id", "" + res.query_id); + image.params.put("bot_name", user.username); searchResult.add(image); @@ -993,62 +1559,18 @@ public void setDelegate(PhotoPickerActivityDelegate delegate) { this.delegate = delegate; } - private void sendSelectedPhotos() { + private void sendSelectedPhotos(boolean notify, int scheduleDate) { if (selectedPhotos.isEmpty() || delegate == null || sendPressed) { return; } + applyCaption(); sendPressed = true; - delegate.actionButtonPressed(false); + delegate.actionButtonPressed(false, notify, scheduleDate); if (selectPhotoType != 2) { finishFragment(); } } - private void fixLayout() { - if (listView != null) { - ViewTreeObserver obs = listView.getViewTreeObserver(); - obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - fixLayoutInternal(); - if (listView != null) { - listView.getViewTreeObserver().removeOnPreDrawListener(this); - } - return true; - } - }); - } - } - - private void fixLayoutInternal() { - if (getParentActivity() == null) { - return; - } - int position = layoutManager.findFirstVisibleItemPosition(); - WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); - int rotation = manager.getDefaultDisplay().getRotation(); - - int columnsCount; - if (AndroidUtilities.isTablet()) { - columnsCount = 3; - } else { - if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { - columnsCount = 5; - } else { - columnsCount = 3; - } - } - layoutManager.setSpanCount(columnsCount); - if (AndroidUtilities.isTablet()) { - itemWidth = (AndroidUtilities.dp(490) - ((columnsCount + 1) * AndroidUtilities.dp(4))) / columnsCount; - } else { - itemWidth = (AndroidUtilities.displaySize.x - ((columnsCount + 1) * AndroidUtilities.dp(4))) / columnsCount; - } - - listAdapter.notifyDataSetChanged(); - layoutManager.scrollToPosition(position); - } - private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -1092,50 +1614,59 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType View view; switch (viewType) { case 0: - PhotoPickerPhotoCell cell = new PhotoPickerPhotoCell(mContext, true); - cell.checkFrame.setOnClickListener(v -> { - int index = (Integer) ((View) v.getParent()).getTag(); - if (selectedAlbum != null) { - MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index); - boolean added = !selectedPhotos.containsKey(photoEntry.imageId); - if (added && maxSelectedPhotos > 0 && selectedPhotos.size() >= maxSelectedPhotos) { - if (allowOrder && chatActivity != null) { - TLRPC.Chat chat = chatActivity.getCurrentChat(); - if (chat != null && !ChatObject.hasAdminRights(chat) && chat.slowmode_enabled) { + PhotoAttachPhotoCell cell = new PhotoAttachPhotoCell(mContext); + cell.setDelegate(new PhotoAttachPhotoCell.PhotoAttachPhotoCellDelegate() { + + private void checkSlowMode() { + if (allowOrder && chatActivity != null) { + TLRPC.Chat chat = chatActivity.getCurrentChat(); + if (chat != null && !ChatObject.hasAdminRights(chat) && chat.slowmode_enabled) { + if (alertOnlyOnce != 2) { AlertsCreator.showSimpleAlert(PhotoPickerActivity.this, LocaleController.getString("Slowmode", R.string.Slowmode), LocaleController.getString("SlowmodeSelectSendError", R.string.SlowmodeSelectSendError)); + if (alertOnlyOnce == 1) { + alertOnlyOnce = 2; + } } } - return; } - int num = allowIndices && added ? selectedPhotosOrder.size() : -1; - ((PhotoPickerPhotoCell) v.getParent()).setChecked(num, added, true); - addToSelectedPhotos(photoEntry, index); - } else { - AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); - MediaController.SearchImage photoEntry; - if (searchResult.isEmpty() && lastSearchString == null) { - photoEntry = recentImages.get((Integer) ((View) v.getParent()).getTag()); + } + + @Override + public void onCheckClick(PhotoAttachPhotoCell v) { + int index = (Integer) v.getTag(); + boolean added; + if (selectedAlbum != null) { + MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(index); + added = !selectedPhotos.containsKey(photoEntry.imageId); + if (added && maxSelectedPhotos > 0 && selectedPhotos.size() >= maxSelectedPhotos) { + checkSlowMode(); + return; + } + int num = allowIndices && added ? selectedPhotosOrder.size() : -1; + v.setChecked(num, added, true); + addToSelectedPhotos(photoEntry, index); } else { - photoEntry = searchResult.get((Integer) ((View) v.getParent()).getTag()); - } - boolean added = !selectedPhotos.containsKey(photoEntry.id); - if (added && maxSelectedPhotos > 0 && selectedPhotos.size() >= maxSelectedPhotos) { - if (allowOrder && chatActivity != null) { - TLRPC.Chat chat = chatActivity.getCurrentChat(); - if (chat != null && !ChatObject.hasAdminRights(chat) && chat.slowmode_enabled) { - AlertsCreator.showSimpleAlert(PhotoPickerActivity.this, LocaleController.getString("Slowmode", R.string.Slowmode), LocaleController.getString("SlowmodeSelectSendError", R.string.SlowmodeSelectSendError)); - } + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + MediaController.SearchImage photoEntry; + if (searchResult.isEmpty() && lastSearchString == null) { + photoEntry = recentImages.get(index); + } else { + photoEntry = searchResult.get(index); + } + added = !selectedPhotos.containsKey(photoEntry.id); + if (added && maxSelectedPhotos > 0 && selectedPhotos.size() >= maxSelectedPhotos) { + checkSlowMode(); + return; } - return; + int num = allowIndices && added ? selectedPhotosOrder.size() : -1; + v.setChecked(num, added, true); + addToSelectedPhotos(photoEntry, index); } - int num = allowIndices && added ? selectedPhotosOrder.size() : -1; - ((PhotoPickerPhotoCell) v.getParent()).setChecked(num, added, true); - addToSelectedPhotos(photoEntry, index); + updatePhotosButton(added ? 1 : 2); + delegate.selectedPhotosChanged(); } - pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); - delegate.selectedPhotosChanged(); }); - cell.checkFrame.setVisibility(selectPhotoType != 0 ? View.GONE : View.VISIBLE); + cell.getCheckFrame().setVisibility(selectPhotoType != 0 ? View.GONE : View.VISIBLE); view = cell; break; case 1: @@ -1154,17 +1685,17 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { case 0: - PhotoPickerPhotoCell cell = (PhotoPickerPhotoCell) holder.itemView; - cell.itemWidth = itemWidth; - BackupImageView imageView = cell.imageView; - imageView.setTag(position); + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) holder.itemView; + cell.setItemSize(itemSize); + + BackupImageView imageView = cell.getImageView(); cell.setTag(position); boolean showing; imageView.setOrientation(0, true); if (selectedAlbum != null) { MediaController.PhotoEntry photoEntry = selectedAlbum.photos.get(position); - cell.setImage(photoEntry); + cell.setPhotoEntry(photoEntry, true, false); cell.setChecked(allowIndices ? selectedPhotosOrder.indexOf(photoEntry.imageId) : -1, selectedPhotos.containsKey(photoEntry.imageId), false); showing = PhotoViewer.isShowingImage(photoEntry.path); } else { @@ -1174,19 +1705,19 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else { photoEntry = searchResult.get(position); } - cell.setImage(photoEntry); - cell.videoInfoContainer.setVisibility(View.INVISIBLE); + cell.setPhotoEntry(photoEntry, true, false); + cell.getVideoInfoContainer().setVisibility(View.INVISIBLE); cell.setChecked(allowIndices ? selectedPhotosOrder.indexOf(photoEntry.id) : -1, selectedPhotos.containsKey(photoEntry.id), false); showing = PhotoViewer.isShowingImage(photoEntry.getPathToAttach()); } imageView.getImageReceiver().setVisible(!showing, true); - cell.checkBox.setVisibility(selectPhotoType != 0 || showing ? View.GONE : View.VISIBLE); + cell.getCheckBox().setVisibility(selectPhotoType != 0 || showing ? View.GONE : View.VISIBLE); break; case 1: ViewGroup.LayoutParams params = holder.itemView.getLayoutParams(); if (params != null) { - params.width = itemWidth; - params.height = itemWidth; + params.width = itemSize; + params.height = itemSize; holder.itemView.setLayoutParams(params); } break; @@ -1217,15 +1748,6 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_dialogBackground), - new ThemeDescription(shadowView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_dialogShadowLine), - - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_dialogBackground), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{PickerBottomLayout.class}, new String[]{"cancelButton"}, null, null, null, Theme.key_picker_enabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonTextView"}, null, null, null, Theme.key_picker_enabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonTextView"}, null, null, null, Theme.key_picker_disabledButton), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonBadgeTextView"}, null, null, null, Theme.key_picker_badgeText), - new ThemeDescription(pickerBottomLayout, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE, new Class[]{PickerBottomLayout.class}, new String[]{"doneButtonBadgeTextView"}, null, null, null, Theme.key_picker_badge), - new ThemeDescription(listView, 0, new Class[]{View.class}, null, new Drawable[]{Theme.chat_attachEmptyDrawable}, null, Theme.key_chat_attachEmptyImage), new ThemeDescription(listView, 0, new Class[]{View.class}, null, null, null, Theme.key_chat_attachPhotoBackground), }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java index f387d243c66..4fb783f1caa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java @@ -31,10 +31,11 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.EditTextEmoji; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ScrollSlidingTextTabStrip; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.Collections; @@ -60,6 +61,7 @@ public ViewPage(Context context) { private PhotoPickerActivity imagesSearch; private PhotoPickerActivity gifsSearch; private ActionBarMenuItem searchItem; + private EditTextEmoji commentTextView; private boolean sendPressed; private int selectPhotoType; @@ -191,8 +193,8 @@ public void onPageScrolled(float progress) { ViewConfiguration configuration = ViewConfiguration.get(context); maximumVelocity = configuration.getScaledMaximumFlingVelocity(); - FrameLayout frameLayout; - fragmentView = frameLayout = new FrameLayout(context) { + SizeNotifierFrameLayout sizeNotifierFrameLayout; + fragmentView = sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { private int startedTrackingPointerId; private boolean startedTracking; @@ -238,6 +240,18 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(widthSize, heightSize); measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); + int keyboardSize = getKeyboardHeight(); + if (keyboardSize <= AndroidUtilities.dp(20)) { + if (!AndroidUtilities.isInMultiwindow) { + heightSize -= commentTextView.getEmojiPadding(); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } + } else { + globalIgnoreLayout = true; + commentTextView.hideEmojiView(); + globalIgnoreLayout = false; + } + int actionBarHeight = actionBar.getMeasuredHeight(); globalIgnoreLayout = true; for (int a = 0; a < viewPages.length; a++) { @@ -256,10 +270,89 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (child == null || child.getVisibility() == GONE || child == actionBar) { continue; } - measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + if (commentTextView != null && commentTextView.isPopupView(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 { + 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 paddingBottom = getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.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 - l) - width - lp.rightMargin - getPaddingRight(); + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin + getPaddingLeft(); + } + + 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 (commentTextView != null && commentTextView.isPopupView(child)) { + if (AndroidUtilities.isTablet()) { + childTop = getMeasuredHeight() - child.getMeasuredHeight(); + } else { + childTop = getMeasuredHeight() + getKeyboardHeight() - child.getMeasuredHeight(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); @@ -456,13 +549,32 @@ public void onAnimationEnd(Animator animator) { return false; } }; - frameLayout.setWillNotDraw(false); + sizeNotifierFrameLayout.setWillNotDraw(false); imagesSearch.setParentFragment(this); - PickerBottomLayout pickerBottomLayout = imagesSearch.getPickerBottomLayout(); - ViewGroup parent = (ViewGroup) pickerBottomLayout.getParent(); - parent.removeView(pickerBottomLayout); - gifsSearch.setPickerBottomLayout(pickerBottomLayout); + commentTextView = imagesSearch.commentTextView; + commentTextView.setSizeNotifierLayout(sizeNotifierFrameLayout); + for (int a = 0; a < 4; a++) { + View view; + switch (a) { + case 0: + view = imagesSearch.frameLayout2; + break; + case 1: + view = imagesSearch.writeButtonContainer; + break; + case 2: + view = imagesSearch.selectedCountView; + break; + case 3: + default: + view = imagesSearch.shadow; + break; + } + ViewGroup parent = (ViewGroup) view.getParent(); + parent.removeView(view); + } + gifsSearch.setLayoutViews(imagesSearch.frameLayout2, imagesSearch.writeButtonContainer, imagesSearch.selectedCountView, imagesSearch.shadow, imagesSearch.commentTextView ); gifsSearch.setParentFragment(this); for (int a = 0; a < viewPages.length; a++) { @@ -478,7 +590,7 @@ public void setTranslationX(float translationX) { } } }; - frameLayout.addView(viewPages[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + sizeNotifierFrameLayout.addView(viewPages[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); if (a == 0) { viewPages[a].parentFragment = imagesSearch; viewPages[a].listView = imagesSearch.getListView(); @@ -531,13 +643,12 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { }); } - frameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - View shadowView = new View(context); - shadowView.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); - frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48)); + sizeNotifierFrameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - frameLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + sizeNotifierFrameLayout.addView(imagesSearch.shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); + sizeNotifierFrameLayout.addView(imagesSearch.frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + sizeNotifierFrameLayout.addView(imagesSearch.writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10)); + sizeNotifierFrameLayout.addView(imagesSearch.selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -8, 9)); updateTabs(); switchToCurrentSelectedMode(false); @@ -551,7 +662,7 @@ public void onResume() { super.onResume(); if (searchItem != null) { searchItem.openSearch(true); - getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } if (imagesSearch != null) { imagesSearch.onResume(); @@ -561,6 +672,12 @@ public void onResume() { } } + public void setCaption(CharSequence text) { + if (imagesSearch != null) { + imagesSearch.setCaption(text); + } + } + @Override public void onPause() { super.onPause(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 4bc4dba74e9..75193be088a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -1012,7 +1012,7 @@ public boolean cancelButtonPressed() { } @Override - public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo) { + public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate) { } @@ -1096,7 +1096,7 @@ public interface PhotoViewerProvider { void needAddMorePhotos(); - void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo); + void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate); int getSelectedCount(); @@ -1362,7 +1362,7 @@ public PhotoViewer() { @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.fileDidFailedLoad) { + if (id == NotificationCenter.fileDidFailToLoad) { String location = (String) args[0]; for (int a = 0; a < 3; a++) { if (currentFileNames[a] != null && currentFileNames[a].equals(location)) { @@ -1770,7 +1770,7 @@ public void setParentActivity(final Activity activity) { centerImage.setCurrentAccount(currentAccount); leftImage.setCurrentAccount(currentAccount); rightImage.setCurrentAccount(currentAccount); - if (parentActivity == activity) { + if (parentActivity == activity || activity == null) { return; } parentActivity = activity; @@ -2042,19 +2042,15 @@ public void onItemClick(int id) { int lower_part = (int) currentDialogId; int high_id = (int) (currentDialogId >> 32); if (lower_part != 0) { - if (high_id == 1) { - args.putInt("chat_id", lower_part); - } else { - if (lower_part > 0) { - args.putInt("user_id", lower_part); - } else if (lower_part < 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); - if (chat != null && chat.migrated_to != null) { - args.putInt("migrated_to", lower_part); - lower_part = -chat.migrated_to.channel_id; - } - args.putInt("chat_id", -lower_part); + if (lower_part > 0) { + args.putInt("user_id", lower_part); + } else if (lower_part < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); + if (chat != null && chat.migrated_to != null) { + args.putInt("migrated_to", lower_part); + lower_part = -chat.migrated_to.channel_id; } + args.putInt("chat_id", -lower_part); } } else { args.putInt("enc_id", high_id); @@ -2082,9 +2078,9 @@ public void onItemClick(int id) { for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, true, 0); } fragment1.finishFragment(); } else { @@ -2131,7 +2127,7 @@ public void onItemClick(int id) { builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); final boolean[] deleteForAll = new boolean[1]; - if (currentMessageObject != null) { + if (currentMessageObject != null && !currentMessageObject.scheduled) { int lower_id = (int) currentMessageObject.getDialogId(); if (lower_id != 0) { TLRPC.Chat currentChat; @@ -2200,7 +2196,7 @@ public void onItemClick(int id) { encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (obj.getDialogId() >> 32)); } - MessagesController.getInstance(currentAccount).deleteMessages(arr, random_ids, encryptedChat, obj.messageOwner.to_id.channel_id, deleteForAll[0]); + MessagesController.getInstance(currentAccount).deleteMessages(arr, random_ids, encryptedChat, obj.getDialogId(), obj.messageOwner.to_id.channel_id, deleteForAll[0], obj.scheduled); } } else if (!avatarsArr.isEmpty()) { if (currentIndex < 0 || currentIndex >= avatarsArr.size()) { @@ -2576,68 +2572,114 @@ public void didStopDragging() { pickerViewSendButton.setImageResource(R.drawable.attach_send); containerView.addView(pickerViewSendButton, LayoutHelper.createFrame(56, 56, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 14, 14)); pickerViewSendButton.setContentDescription(LocaleController.getString("Send", R.string.Send)); - pickerViewSendButton.setOnClickListener(v -> sendPressed(false)); + pickerViewSendButton.setOnClickListener(v -> { + if (parentChatActivity != null && parentChatActivity.isInScheduleMode() && !parentChatActivity.isEditingMessageMedia()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(parentChatActivity.getCurrentUser()), this::sendPressed); + } else { + sendPressed(true, 0); + } + }); pickerViewSendButton.setOnLongClickListener(view -> { - if (parentChatActivity == null) { + if (parentChatActivity == null || parentChatActivity.isInScheduleMode()) { return false; } TLRPC.Chat chat = parentChatActivity.getCurrentChat(); TLRPC.User user = parentChatActivity.getCurrentUser(); - if (parentChatActivity.getCurrentEncryptedChat() != null || ChatObject.isChannel(chat) && !chat.megagroup || UserObject.isUserSelf(user)) { + if (parentChatActivity.getCurrentEncryptedChat() != null) { return false; } - if (sendPopupLayout == null) { - sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity); - sendPopupLayout.setAnimationEnabled(false); - sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { + sendPopupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity); + sendPopupLayout.setAnimationEnabled(false); + sendPopupLayout.setOnTouchListener(new View.OnTouchListener() { - private android.graphics.Rect popupRect = new android.graphics.Rect(); + private android.graphics.Rect popupRect = new android.graphics.Rect(); - @Override - public boolean onTouch(View v, MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - if (sendPopupWindow != null && sendPopupWindow.isShowing()) { - v.getHitRect(popupRect); - if (!popupRect.contains((int) event.getX(), (int) event.getY())) { - sendPopupWindow.dismiss(); - } + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (sendPopupWindow != null && sendPopupWindow.isShowing()) { + v.getHitRect(popupRect); + if (!popupRect.contains((int) event.getX(), (int) event.getY())) { + sendPopupWindow.dismiss(); } } - return false; } - }); - sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { - if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { - sendPopupWindow.dismiss(); + return false; + } + }); + sendPopupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && sendPopupWindow != null && sendPopupWindow.isShowing()) { + sendPopupWindow.dismiss(); + } + }); + sendPopupLayout.setShowedFromBotton(false); + sendPopupLayout.getBackgroundDrawable().setColorFilter(new PorterDuffColorFilter(0xf9222222, PorterDuff.Mode.MULTIPLY)); + + int i = 0; + for (int a = 0; a < 2; a++) { + if (a == 0 && placeProvider != null && placeProvider.getSelectedPhotos() != null) { + HashMap hashMap = placeProvider.getSelectedPhotos(); + boolean hasTtl = false; + for (HashMap.Entry entry : hashMap.entrySet()) { + Object object = entry.getValue(); + if (object instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; + if (photoEntry.ttl != 0) { + hasTtl = true; + break; + } + } else if (object instanceof MediaController.SearchImage) { + MediaController.SearchImage searchImage = (MediaController.SearchImage) object; + if (searchImage.ttl != 0) { + hasTtl = true; + break; + } + } } - }); - sendPopupLayout.setShowedFromBotton(false); - sendPopupLayout.getBackgroundDrawable().setColorFilter(new PorterDuffColorFilter(0xf9222222, PorterDuff.Mode.MULTIPLY)); - + if (hasTtl) { + continue; + } + } else if (a == 1 && UserObject.isUserSelf(user)) { + continue; + } + int num = a; ActionBarMenuSubItem cell = new ActionBarMenuSubItem(parentActivity); cell.setBackgroundDrawable(Theme.createSelectorDrawable(0x24ffffff, 7)); - cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + if (num == 0) { + if (UserObject.isUserSelf(user)) { + cell.setTextAndIcon(LocaleController.getString("SetReminder", R.string.SetReminder), R.drawable.msg_schedule); + } else { + cell.setTextAndIcon(LocaleController.getString("ScheduleMessage", R.string.ScheduleMessage), R.drawable.msg_schedule); + } + } else if (num == 1) { + cell.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.input_notify_off); + } cell.setMinimumWidth(AndroidUtilities.dp(196)); cell.setColors(0xffffffff, 0xffffffff); - sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); + sendPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * i, 0, 0)); cell.setOnClickListener(v -> { if (sendPopupWindow != null && sendPopupWindow.isShowing()) { sendPopupWindow.dismiss(); } - sendPressed(true); + if (num == 0) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, UserObject.isUserSelf(user), this::sendPressed); + } else if (num == 1) { + sendPressed(false, 0); + } }); - - sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); - sendPopupWindow.setAnimationEnabled(false); - sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); - sendPopupWindow.setOutsideTouchable(true); - sendPopupWindow.setClippingEnabled(true); - sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - sendPopupWindow.getContentView().setFocusableInTouchMode(true); + i++; } + sendPopupWindow = new ActionBarPopupWindow(sendPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + sendPopupWindow.setAnimationEnabled(false); + sendPopupWindow.setAnimationStyle(R.style.PopupContextAnimation2); + sendPopupWindow.setOutsideTouchable(true); + sendPopupWindow.setClippingEnabled(true); + sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + sendPopupWindow.getContentView().setFocusableInTouchMode(true); + sendPopupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); sendPopupWindow.setFocusable(true); @@ -3276,7 +3318,7 @@ public void onContextClick(TLRPC.BotInlineResult result) { } } - private void sendPressed(boolean forceSilent) { + private void sendPressed(boolean notify, int scheduleDate) { if (captionEditText.getTag() != null) { return; } @@ -3288,11 +3330,11 @@ private void sendPressed(boolean forceSilent) { TLRPC.Chat chat = parentChatActivity.getCurrentChat(); TLRPC.User user = parentChatActivity.getCurrentUser(); if (user != null || ChatObject.isChannel(chat) && chat.megagroup || !ChatObject.isChannel(chat)) { - MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + parentChatActivity.getDialogId(), forceSilent).commit(); + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + parentChatActivity.getDialogId(), !notify).commit(); } } VideoEditedInfo videoEditedInfo = getCurrentVideoEditedInfo(); - placeProvider.sendButtonPressed(currentIndex, videoEditedInfo); + placeProvider.sendButtonPressed(currentIndex, videoEditedInfo, notify, scheduleDate); doneButtonPressed = true; closePhoto(false, false); } @@ -5471,7 +5513,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca imagesArr.add(messageObject); if (currentAnimation != null || messageObject.eventId != 0) { needSearchImageInArr = false; - } else if (!(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty)) { + } else if (!messageObject.scheduled && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty)) { needSearchImageInArr = true; imagesByIds[0].put(messageObject.getId(), messageObject); menuItem.showSubItem(gallery_menu_showall); @@ -5511,18 +5553,22 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca } setImageIndex(0, true); } else if (messages != null) { - opennedFromMedia = true; - menuItem.showSubItem(gallery_menu_showinchat); - sendItem.setVisibility(View.VISIBLE); imagesArr.addAll(messages); for (int a = 0; a < imagesArr.size(); a++) { MessageObject message = imagesArr.get(a); imagesByIds[message.getDialogId() == currentDialogId ? 0 : 1].put(message.getId(), message); } MessageObject openingObject = imagesArr.get(index); - if (openingObject.canPreviewDocument()) { - sharedMediaType = MediaDataController.MEDIA_FILE; - allMediaItem.setText(LocaleController.getString("ShowAllFiles", R.string.ShowAllFiles)); + if (!openingObject.scheduled) { + opennedFromMedia = true; + menuItem.showSubItem(gallery_menu_showinchat); + sendItem.setVisibility(View.VISIBLE); + if (openingObject.canPreviewDocument()) { + sharedMediaType = MediaDataController.MEDIA_FILE; + allMediaItem.setText(LocaleController.getString("ShowAllFiles", R.string.ShowAllFiles)); + } + } else { + totalImagesCount = imagesArr.size(); } setImageIndex(index, true); } else if (photos != null) { @@ -5592,7 +5638,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca } if (currentAnimation == null && !isEvent) { - if (currentDialogId != 0 && totalImagesCount == 0) { + if (currentDialogId != 0 && totalImagesCount == 0 && currentMessageObject != null && !currentMessageObject.scheduled) { MediaDataController.getInstance(currentAccount).getMediaCount(currentDialogId, sharedMediaType, classGuid, true); if (mergeDialogId != 0) { MediaDataController.getInstance(currentAccount).getMediaCount(mergeDialogId, sharedMediaType, classGuid, true); @@ -5607,8 +5653,10 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca Object entry = imagesArrLocals.get(index); CharSequence caption = null; TLRPC.User user = parentChatActivity != null ? parentChatActivity.getCurrentUser() : null; - boolean allowTimeItem = parentChatActivity != null && !parentChatActivity.isSecretChat() && user != null && !user.bot && !parentChatActivity.isEditingMessageMedia(); - if (entry instanceof MediaController.PhotoEntry) { + boolean allowTimeItem = parentChatActivity != null && !parentChatActivity.isSecretChat() && !parentChatActivity.isInScheduleMode() && user != null && !user.bot && !UserObject.isUserSelf(user) && !parentChatActivity.isEditingMessageMedia(); + if (entry instanceof TLRPC.BotInlineResult) { + allowTimeItem = false; + } else if (entry instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) entry); if (photoEntry.isVideo) { preparePlayer(Uri.fromFile(new File(photoEntry.path)), false, false); @@ -5668,7 +5716,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init) { captionTextView.setTranslationY(AndroidUtilities.dp(48)); } else { masksItem.setVisibility(newMessageObject.hasPhotoStickers() && (int) newMessageObject.getDialogId() != 0 ? View.VISIBLE : View.GONE); - if (newMessageObject.canDeleteMessage(null) && slideshowMessageId == 0) { + if (newMessageObject.canDeleteMessage(parentChatActivity != null && parentChatActivity.isInScheduleMode(), null) && slideshowMessageId == 0) { menuItem.showSubItem(gallery_menu_delete); } else { menuItem.hideSubItem(gallery_menu_delete); @@ -5728,7 +5776,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init) { if (currentAnimation != null) { menuItem.hideSubItem(gallery_menu_save); menuItem.hideSubItem(gallery_menu_share); - if (!newMessageObject.canDeleteMessage(null)) { + if (!newMessageObject.canDeleteMessage(parentChatActivity != null && parentChatActivity.isInScheduleMode(), null)) { menuItem.setVisibility(View.GONE); } allowShare = true; @@ -6841,7 +6889,7 @@ public boolean openPhoto(final MessageObject messageObject, final TLRPC.FileLoca parentChatActivity = chatActivity; actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, 1, 1)); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.FileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.mediaCountDidLoad); @@ -7409,7 +7457,7 @@ public void onAnimationEnd(Animator animation) { } private void removeObservers() { - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailedLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailToLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.FileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.mediaCountDidLoad); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java index a2f8e946e81..e9c9a98da5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java @@ -20,6 +20,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -34,6 +35,7 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.ContextProgressView; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; @@ -51,6 +53,7 @@ public class PollCreateActivity extends BaseFragment { private ContextProgressView progressView; private ListAdapter listAdapter; private RecyclerListView listView; + private ChatActivity parentFragment; private String[] answers = new String[10]; private int answersCount = 1; @@ -75,7 +78,7 @@ public class PollCreateActivity extends BaseFragment { private static final int done_button = 1; public interface PollCreateActivityDelegate { - void sendPoll(TLRPC.TL_messageMediaPoll poll); + void sendPoll(TLRPC.TL_messageMediaPoll poll, boolean notify, int scheduleDate); } public class TouchHelperCallback extends ItemTouchHelper.Callback { @@ -128,6 +131,11 @@ public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHol } } + public PollCreateActivity(ChatActivity chatActivity) { + super(); + parentFragment = chatActivity; + } + @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -165,8 +173,15 @@ public void onItemClick(int id) { poll.poll.answers.add(answer); } poll.results = new TLRPC.TL_pollResults(); - delegate.sendPoll(poll); - finishFragment(); + if (parentFragment.isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), UserObject.isUserSelf(parentFragment.getCurrentUser()), (notify, scheduleDate) -> { + delegate.sendPoll(poll, notify, scheduleDate); + finishFragment(); + }); + } else { + delegate.sendPoll(poll, true, 0); + finishFragment(); + } } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index f85f72c6a42..66cc451b4ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -318,14 +318,14 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { popupContainer.addView(chatActivityEnterView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, RelativeLayout.ALIGN_PARENT_BOTTOM)); chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override - public void onMessageSend(CharSequence message) { + public void onMessageSend(CharSequence message, boolean notify, int scheduleDate) { if (currentMessageObject == null) { return; } if (currentMessageNum >= 0 && currentMessageNum < popupMessages.size()) { popupMessages.remove(currentMessageNum); } - MessagesController.getInstance(currentMessageObject.currentAccount).markDialogAsRead(currentMessageObject.getDialogId(), currentMessageObject.getId(), Math.max(0, currentMessageObject.getId()), currentMessageObject.messageOwner.date, true, 0, true); + MessagesController.getInstance(currentMessageObject.currentAccount).markDialogAsRead(currentMessageObject.getDialogId(), currentMessageObject.getId(), Math.max(0, currentMessageObject.getId()), currentMessageObject.messageOwner.date, true, 0, true, 0); currentMessageObject = null; getNewMessage(); } @@ -398,7 +398,7 @@ public void didPressedAttachButton() { } @Override - public void needStartRecordVideo(int state) { + public void needStartRecordVideo(int state, boolean notify, int scheduleDate) { } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java index d697c3fff4e..b7fbb142fcb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java @@ -15,6 +15,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.text.Spannable; import android.text.method.LinkMovementMethod; @@ -45,6 +46,7 @@ import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.RadioCell; +import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.HintView; @@ -65,6 +67,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification private MessageCell messageCell; private int initialRulesType; + private int initialRulesSubType; private ArrayList initialPlus = new ArrayList<>(); private ArrayList initialMinus = new ArrayList<>(); @@ -72,8 +75,10 @@ public class PrivacyControlActivity extends BaseFragment implements Notification private ArrayList currentPlus; private ArrayList currentMinus; private int lastCheckedType = -1; + private int lastCheckedSubType = -1; private int currentType; + private int currentSubType; private boolean enableAnimation; @@ -87,6 +92,10 @@ public class PrivacyControlActivity extends BaseFragment implements Notification private int alwaysShareRow; private int neverShareRow; private int shareDetailRow; + private int phoneSectionRow; + private int phoneEverybodyRow; + private int phoneContactsRow; + private int phoneDetailRow; private int p2pSectionRow; private int p2pRow; private int p2pDetailRow; @@ -101,6 +110,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification public final static int PRIVACY_RULES_TYPE_PHOTO = 4; public final static int PRIVACY_RULES_TYPE_FORWARDS = 5; public final static int PRIVACY_RULES_TYPE_PHONE = 6; + public final static int PRIVACY_RULES_TYPE_ADDED_BY_PHONE = 7; private static class LinkMovementMethodMy extends LinkMovementMethod { @Override @@ -177,7 +187,7 @@ protected void onDraw(Canvas canvas) { if (newDrawable != null) { backgroundDrawable = newDrawable; } - if (backgroundDrawable instanceof ColorDrawable) { + if (backgroundDrawable instanceof ColorDrawable || backgroundDrawable instanceof GradientDrawable) { backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); backgroundDrawable.draw(canvas); } else if (backgroundDrawable instanceof BitmapDrawable) { @@ -338,6 +348,21 @@ public void onItemClick(int id) { currentType = newType; doneButton.setVisibility(hasChanges() ? View.VISIBLE : View.GONE); updateRows(); + } else if (position == phoneContactsRow || position == phoneEverybodyRow) { + int newType = currentSubType; + if (position == phoneEverybodyRow) { + newType = 0; + } else if (position == phoneContactsRow) { + newType = 1; + } + if (newType == currentSubType) { + return; + } + enableAnimation = true; + lastCheckedSubType = currentSubType; + currentSubType = newType; + doneButton.setVisibility(hasChanges() ? View.VISIBLE : View.GONE); + updateRows(); } else if (position == neverShareRow || position == alwaysShareRow) { ArrayList createFromArray; if (position == neverShareRow) { @@ -413,6 +438,21 @@ private void applyCurrentPrivacySettings() { TLRPC.TL_account_setPrivacy req = new TLRPC.TL_account_setPrivacy(); if (rulesType == PRIVACY_RULES_TYPE_PHONE) { req.key = new TLRPC.TL_inputPrivacyKeyPhoneNumber(); + if (currentType == 1) { + TLRPC.TL_account_setPrivacy req2 = new TLRPC.TL_account_setPrivacy(); + req2.key = new TLRPC.TL_inputPrivacyKeyAddedByPhone(); + if (currentSubType == 0) { + req2.rules.add(new TLRPC.TL_inputPrivacyValueAllowAll()); + } else { + req2.rules.add(new TLRPC.TL_inputPrivacyValueAllowContacts()); + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.TL_account_privacyRules privacyRules = (TLRPC.TL_account_privacyRules) response; + ContactsController.getInstance(currentAccount).setPrivacyRules(privacyRules.rules, PRIVACY_RULES_TYPE_ADDED_BY_PHONE); + } + }), ConnectionsManager.RequestFlagFailOnServerErrors); + } } else if (rulesType == PRIVACY_RULES_TYPE_FORWARDS) { req.key = new TLRPC.TL_inputPrivacyKeyForwards(); } else if (rulesType == PRIVACY_RULES_TYPE_PHOTO) { @@ -564,6 +604,28 @@ private void checkPrivacy() { initialPlus.addAll(currentPlus); initialMinus.addAll(currentMinus); + if (rulesType == PRIVACY_RULES_TYPE_PHONE) { + privacyRules = ContactsController.getInstance(currentAccount).getPrivacyRules(PRIVACY_RULES_TYPE_ADDED_BY_PHONE); + if (privacyRules == null || privacyRules.size() == 0) { + currentSubType = 0; + } else { + for (int a = 0; a < privacyRules.size(); a++) { + TLRPC.PrivacyRule rule = privacyRules.get(a); + if (rule instanceof TLRPC.TL_privacyValueAllowAll) { + currentSubType = 0; + break; + } else if (rule instanceof TLRPC.TL_privacyValueDisallowAll) { + currentSubType = 2; + break; + } else if (rule instanceof TLRPC.TL_privacyValueAllowContacts) { + currentSubType = 1; + break; + } + } + } + initialRulesSubType = currentSubType; + } + updateRows(); } @@ -571,6 +633,9 @@ private boolean hasChanges() { if (initialRulesType != currentType) { return true; } + if (rulesType == PRIVACY_RULES_TYPE_PHONE && currentType == 1 && initialRulesSubType != currentSubType) { + return true; + } if (initialMinus.size() != currentMinus.size()) { return true; } @@ -605,6 +670,17 @@ private void updateRows() { } else { nobodyRow = rowCount++; } + if (rulesType == PRIVACY_RULES_TYPE_PHONE && currentType == 1) { + phoneDetailRow = rowCount++; + phoneSectionRow = rowCount++; + phoneEverybodyRow = rowCount++; + phoneContactsRow = rowCount++; + } else { + phoneDetailRow = -1; + phoneSectionRow = -1; + phoneEverybodyRow = -1; + phoneContactsRow = -1; + } detailRow = rowCount++; shareSectionRow = rowCount++; if (currentType == 1 || currentType == 2) { @@ -655,6 +731,7 @@ private void setMessageText() { public void onResume() { super.onResume(); lastCheckedType = -1; + lastCheckedSubType = -1; enableAnimation = false; } @@ -748,9 +825,12 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: - default: view = messageCell; break; + case 5: + default: + view = new ShadowSectionCell(mContext); + break; } return new RecyclerListView.Holder(view); } @@ -815,7 +895,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; if (position == detailRow) { if (rulesType == PRIVACY_RULES_TYPE_PHONE) { - privacyCell.setText(LocaleController.getString("PrivacyPhoneInfo", R.string.PrivacyPhoneInfo)); + if (currentType == 1 && currentSubType == 1) { + privacyCell.setText(LocaleController.getString("PrivacyPhoneInfo3", R.string.PrivacyPhoneInfo3)); + } else { + privacyCell.setText(LocaleController.getString("PrivacyPhoneInfo", R.string.PrivacyPhoneInfo)); + } } else if (rulesType == PRIVACY_RULES_TYPE_FORWARDS) { privacyCell.setText(LocaleController.getString("PrivacyForwardsInfo", R.string.PrivacyForwardsInfo)); } else if (rulesType == PRIVACY_RULES_TYPE_PHOTO) { @@ -877,37 +961,55 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { headerCell.setText(LocaleController.getString("AddExceptions", R.string.AddExceptions)); } else if (position == p2pSectionRow) { headerCell.setText(LocaleController.getString("PrivacyP2PHeader", R.string.PrivacyP2PHeader)); + } else if (position == phoneSectionRow) { + headerCell.setText(LocaleController.getString("PrivacyPhoneTitle2", R.string.PrivacyPhoneTitle2)); } break; case 3: RadioCell radioCell = (RadioCell) holder.itemView; - int checkedType = 0; - if (position == everybodyRow) { - if (rulesType == PRIVACY_RULES_TYPE_P2P) { - radioCell.setText(LocaleController.getString("P2PEverybody", R.string.P2PEverybody), lastCheckedType == 0, true); - } else { - radioCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), lastCheckedType == 0, true); + if (position == everybodyRow || position == myContactsRow || position == nobodyRow) { + int checkedType = 0; + if (position == everybodyRow) { + if (rulesType == PRIVACY_RULES_TYPE_P2P) { + radioCell.setText(LocaleController.getString("P2PEverybody", R.string.P2PEverybody), lastCheckedType == 0, true); + } else { + radioCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), lastCheckedType == 0, true); + } + checkedType = 0; + } else if (position == myContactsRow) { + if (rulesType == PRIVACY_RULES_TYPE_P2P) { + radioCell.setText(LocaleController.getString("P2PContacts", R.string.P2PContacts), lastCheckedType == 2, nobodyRow != -1); + } else { + radioCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), lastCheckedType == 2, nobodyRow != -1); + } + checkedType = 2; + } else if (position == nobodyRow) { + if (rulesType == PRIVACY_RULES_TYPE_P2P) { + radioCell.setText(LocaleController.getString("P2PNobody", R.string.P2PNobody), lastCheckedType == 1, false); + } else { + radioCell.setText(LocaleController.getString("LastSeenNobody", R.string.LastSeenNobody), lastCheckedType == 1, false); + } + checkedType = 1; } - checkedType = 0; - } else if (position == myContactsRow) { - if (rulesType == PRIVACY_RULES_TYPE_P2P) { - radioCell.setText(LocaleController.getString("P2PContacts", R.string.P2PContacts), lastCheckedType == 2, nobodyRow != -1); - } else { - radioCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), lastCheckedType == 2, nobodyRow != -1); + if (lastCheckedType == checkedType) { + radioCell.setChecked(false, enableAnimation); + } else if (currentType == checkedType) { + radioCell.setChecked(true, enableAnimation); } - checkedType = 2; - } else if (position == nobodyRow) { - if (rulesType == PRIVACY_RULES_TYPE_P2P) { - radioCell.setText(LocaleController.getString("P2PNobody", R.string.P2PNobody), lastCheckedType == 1, false); - } else { - radioCell.setText(LocaleController.getString("LastSeenNobody", R.string.LastSeenNobody), lastCheckedType == 1, false); + } else { + int checkedType = 0; + if (position == phoneContactsRow) { + radioCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), lastCheckedSubType == 1, false); + checkedType = 1; + } else if (position == phoneEverybodyRow) { + radioCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), lastCheckedSubType == 0, true); + checkedType = 0; + } + if (lastCheckedSubType == checkedType) { + radioCell.setChecked(false, enableAnimation); + } else if (currentSubType == checkedType) { + radioCell.setChecked(true, enableAnimation); } - checkedType = 1; - } - if (lastCheckedType == checkedType) { - radioCell.setChecked(false, enableAnimation); - } else if (currentType == checkedType) { - radioCell.setChecked(true, enableAnimation); } break; } @@ -919,12 +1021,14 @@ public int getItemViewType(int position) { return 0; } else if (position == shareDetailRow || position == detailRow || position == p2pDetailRow) { return 1; - } else if (position == sectionRow || position == shareSectionRow || position == p2pSectionRow) { + } else if (position == sectionRow || position == shareSectionRow || position == p2pSectionRow || position == phoneSectionRow) { return 2; - } else if (position == everybodyRow || position == myContactsRow || position == nobodyRow) { + } else if (position == everybodyRow || position == myContactsRow || position == nobodyRow || position == phoneEverybodyRow || position == phoneContactsRow) { return 3; } else if (position == messageRow) { return 4; + } else if (position == phoneDetailRow) { + return 5; } return 0; } @@ -946,12 +1050,13 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider), - new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), - new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText), new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + + new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader), @@ -967,8 +1072,10 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextIn), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextOut), - new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck), - new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected), new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyLine), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyLine), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java index b80d30423d4..7969aaf8c33 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java @@ -519,7 +519,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index f0b54c27e28..81bdde33ce1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -504,7 +504,7 @@ public void onItemClick(final int id) { MessagesController.getInstance(currentAccount).blockUser(user_id); } else { MessagesController.getInstance(currentAccount).unblockUser(user_id); - SendMessagesHelper.getInstance(currentAccount).sendMessage("/start", user_id, null, null, false, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage("/start", user_id, null, null, false, null, null, null, true, 0); finishFragment(); } } @@ -1862,6 +1862,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { } } } else if (id == NotificationCenter.didReceiveNewMessages) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } long did; if (dialog_id != 0) { did = dialog_id; @@ -1891,6 +1895,10 @@ public void didReceivedNotification(int id, int account, final Object... args) { loadMediaCounts(); } } else if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } int channelId = (Integer) args[1]; if (ChatObject.isChannel(currentChat)) { if (!(channelId == 0 && mergeDialogId != 0 || channelId == currentChat.id)) { @@ -3067,7 +3075,7 @@ public void didSelectDialogs(DialogsActivity fragment, ArrayList dids, Cha presentFragment(new ChatActivity(args), true); removeSelfFromStack(); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); - SendMessagesHelper.getInstance(currentAccount).sendMessage(user, did, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(user, did, null, null, null, true, 0); } @Override @@ -3487,7 +3495,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider), - new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{avatarDrawable}, null, Theme.key_avatar_backgroundInProfileBlue), new ThemeDescription(writeButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_profile_actionIcon), @@ -3518,7 +3526,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 03ed553fc95..11b4c401aea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -1009,7 +1009,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText), new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText), - new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(listView, 0, new Class[]{UserCell2.class}, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange), new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java index 8b7b6f4c8e6..0c62542fa96 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java @@ -410,6 +410,10 @@ public static boolean hasInstance() { @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.messagesDeleted) { + boolean scheduled = (Boolean) args[2]; + if (scheduled) { + return; + } if (currentMessageObject == null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 8655c46bc4b..9bcaf5fc7af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -1990,7 +1990,7 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3), - new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{Theme.avatar_broadcastDrawable, Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), + new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{Theme.avatar_savedDrawable}, null, Theme.key_avatar_text), new ThemeDescription(avatarImage, 0, null, null, new Drawable[]{avatarDrawable}, null, Theme.key_avatar_backgroundInProfileBlue), new ThemeDescription(writeButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_profile_actionIcon), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index 3ffdeb9584a..20286967cf3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -9,6 +9,7 @@ package org.telegram.ui; import android.Manifest; +import android.animation.ObjectAnimator; import android.app.Activity; import android.app.TimePickerDialog; import android.content.Context; @@ -18,12 +19,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.location.Address; import android.location.Geocoder; @@ -35,6 +30,7 @@ import android.os.Bundle; import android.os.Vibrator; +import androidx.annotation.Keep; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; @@ -42,7 +38,6 @@ import android.text.InputType; import android.text.TextPaint; -import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -61,21 +56,18 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; 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.SharedConfig; -import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; +import org.telegram.messenger.support.ArrayUtils; import org.telegram.messenger.time.SunDate; -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.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.BrightnessControlCell; @@ -87,18 +79,20 @@ import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; -import org.telegram.ui.Cells.ThemeCell; +import org.telegram.ui.Cells.ThemePreviewMessagesCell; import org.telegram.ui.Cells.ThemeTypeCell; +import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.RadioButton; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SeekBarView; +import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.ThemeEditorView; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; @@ -109,18 +103,19 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public final static int THEME_TYPE_BASIC = 0; public final static int THEME_TYPE_NIGHT = 1; - public final static int THEME_TYPE_ALL = 2; + public final static int THEME_TYPE_OTHER = 2; private ListAdapter listAdapter; - private RecyclerListView innerListView; private RecyclerListView listView; @SuppressWarnings("FieldCanBeLocal") private LinearLayoutManager layoutManager; + private ThemesHorizontalListCell themesHorizontalListCell; private ArrayList darkThemes = new ArrayList<>(); private ArrayList defaultThemes = new ArrayList<>(); + private int currentType; - boolean hasCustomThemes; + boolean hasThemeAccents; private int backgroundRow; private int textSizeHeaderRow; @@ -162,15 +157,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int chatListHeaderRow; private int chatListRow; private int chatListInfoRow; - private int themeStartRow; private int themeListRow; - private int themeEndRow; - private int showThemesRows; + private int themeAccentListRow; private int themeInfoRow; - private int themeHeader2Row; - private int themeStart2Row; - private int themeEnd2Row; - private int themeInfo2Row; private int rowCount; @@ -217,10 +206,8 @@ public interface SizeChooseViewDelegate { private class TextSizeCell extends FrameLayout { - private LinearLayout messagesContainer; - private ChatMessageCell[] cells = new ChatMessageCell[2]; + private ThemePreviewMessagesCell messagesCell; private SeekBarView sizeBar; - private Drawable shadowDrawable; private int startFontSize = 12; private int endFontSize = 30; private int lastWidth; @@ -235,8 +222,6 @@ public TextSizeCell(Context context) { textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); textPaint.setTextSize(AndroidUtilities.dp(16)); - shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); - sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); sizeBar.setDelegate(progress -> { @@ -251,6 +236,7 @@ public TextSizeCell(Context context) { int firstVisPos = layoutManager.findFirstVisibleItemPosition(); View firstVisView = firstVisPos != RecyclerView.NO_POSITION ? layoutManager.findViewByPosition(firstVisPos) : null; int top = firstVisView != null ? firstVisView.getTop() : 0; + ChatMessageCell[] cells = messagesCell.getCells(); for (int a = 0; a < cells.length; a++) { cells[a].getMessageObject().resetLayout(); cells[a].requestLayout(); @@ -262,149 +248,8 @@ public TextSizeCell(Context context) { }); addView(sizeBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.LEFT | Gravity.TOP, 9, 5, 43, 0)); - messagesContainer = new LinearLayout(context) { - - private Drawable backgroundDrawable; - private Drawable oldBackgroundDrawable; - - @Override - protected void onDraw(Canvas canvas) { - Drawable newDrawable = Theme.getCachedWallpaperNonBlocking(); - if (newDrawable != backgroundDrawable && newDrawable != null) { - if (Theme.isAnimatingColor()) { - oldBackgroundDrawable = backgroundDrawable; - } - backgroundDrawable = newDrawable; - } - float themeAnimationValue = parentLayout.getThemeAnimationValue(); - for (int a = 0; a < 2; a++) { - Drawable drawable = a == 0 ? oldBackgroundDrawable : backgroundDrawable; - if (drawable == null) { - continue; - } - if (a == 1 && oldBackgroundDrawable != null && parentLayout != null) { - drawable.setAlpha((int) (255 * themeAnimationValue)); - } else { - drawable.setAlpha(255); - } - if (drawable instanceof ColorDrawable) { - drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); - drawable.draw(canvas); - } else if (drawable instanceof BitmapDrawable) { - BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; - if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) { - canvas.save(); - float scale = 2.0f / AndroidUtilities.density; - canvas.scale(scale, scale); - drawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale)); - drawable.draw(canvas); - canvas.restore(); - } else { - int viewHeight = getMeasuredHeight(); - float scaleX = (float) getMeasuredWidth() / (float) drawable.getIntrinsicWidth(); - float scaleY = (float) (viewHeight) / (float) drawable.getIntrinsicHeight(); - float scale = scaleX < scaleY ? scaleY : scaleX; - int width = (int) Math.ceil(drawable.getIntrinsicWidth() * scale); - int height = (int) Math.ceil(drawable.getIntrinsicHeight() * scale); - int x = (getMeasuredWidth() - width) / 2; - int y = (viewHeight - height) / 2; - canvas.save(); - canvas.clipRect(0, 0, width, getMeasuredHeight()); - drawable.setBounds(x, y, x + width, y + height); - drawable.draw(canvas); - canvas.restore(); - } - } - if (a == 0 && oldBackgroundDrawable != null && themeAnimationValue >= 1.0f) { - oldBackgroundDrawable = null; - } - } - shadowDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); - shadowDrawable.draw(canvas); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return false; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - return false; - } - - @Override - protected void dispatchSetPressed(boolean pressed) { - - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - return false; - } - }; - messagesContainer.setOrientation(LinearLayout.VERTICAL); - messagesContainer.setWillNotDraw(false); - messagesContainer.setPadding(0, AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11)); - addView(messagesContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 53, 0, 0)); - - int date = (int) (System.currentTimeMillis() / 1000) - 60 * 60; - TLRPC.Message message = new TLRPC.TL_message(); - message.message = LocaleController.getString("FontSizePreviewReply", R.string.FontSizePreviewReply); - message.date = date + 60; - message.dialog_id = 1; - message.flags = 259; - message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); - message.id = 1; - message.media = new TLRPC.TL_messageMediaEmpty(); - message.out = true; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = 0; - MessageObject replyMessageObject = new MessageObject(currentAccount, message, true); - - message = new TLRPC.TL_message(); - message.message = LocaleController.getString("FontSizePreviewLine2", R.string.FontSizePreviewLine2); - message.date = date + 960; - message.dialog_id = 1; - message.flags = 259; - message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); - message.id = 1; - message.media = new TLRPC.TL_messageMediaEmpty(); - message.out = true; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = 0; - MessageObject message1 = new MessageObject(currentAccount, message, true); - message1.resetLayout(); - message1.eventId = 1; - - message = new TLRPC.TL_message(); - message.message = LocaleController.getString("FontSizePreviewLine1", R.string.FontSizePreviewLine1); - message.date = date + 60; - message.dialog_id = 1; - message.flags = 257 + 8; - message.from_id = 0; - message.id = 1; - message.reply_to_msg_id = 5; - message.media = new TLRPC.TL_messageMediaEmpty(); - message.out = false; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); - MessageObject message2 = new MessageObject(currentAccount, message, true); - message2.customReplyName = LocaleController.getString("FontSizePreviewName", R.string.FontSizePreviewName); - message2.eventId = 1; - message2.resetLayout(); - message2.replyMessageObject = replyMessageObject; - - for (int a = 0; a < cells.length; a++) { - cells[a] = new ChatMessageCell(context); - cells[a].setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { - - }); - cells[a].isChat = false; - cells[a].setFullyDraw(true); - cells[a].setMessageObject(a == 0 ? message2 : message1, null, false, false); - messagesContainer.addView(cells[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } + messagesCell = new ThemePreviewMessagesCell(context, parentLayout, 0); + addView(messagesCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 53, 0, 0)); } @Override @@ -426,25 +271,22 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override public void invalidate() { super.invalidate(); - messagesContainer.invalidate(); + messagesCell.invalidate(); sizeBar.invalidate(); - for (int a = 0; a < cells.length; a++) { - cells[a].invalidate(); - } } } - private int currentType; - public ThemeActivity(int type) { super(); currentType = type; - updateRows(); + updateRows(true); } - private void updateRows() { + private void updateRows(boolean notify) { int oldRowCount = rowCount; + int prevThemeAccentListRow = themeAccentListRow; + rowCount = 0; emojiRow = -1; contactsReimportRow = -1; @@ -462,14 +304,8 @@ private void updateRows() { scheduleFromRow = -1; scheduleToRow = -1; scheduleFromToInfoRow = -1; - themeStartRow = -1; - themeHeader2Row = -1; - themeInfo2Row = -1; - themeStart2Row = -1; - themeEnd2Row = -1; themeListRow = -1; - themeEndRow = -1; - showThemesRows = -1; + themeAccentListRow = -1; themeInfoRow = -1; preferedHeaderRow = -1; automaticHeaderRow = -1; @@ -496,24 +332,17 @@ private void updateRows() { stickersSection2Row = -1; if (currentType == THEME_TYPE_BASIC) { - hasCustomThemes = false; defaultThemes.clear(); + darkThemes.clear(); for (int a = 0, N = Theme.themes.size(); a < N; a++) { Theme.ThemeInfo themeInfo = Theme.themes.get(a); - if (themeInfo.pathToFile == null) { + if (themeInfo.pathToFile != null) { + darkThemes.add(themeInfo); + } else { defaultThemes.add(themeInfo); - continue; } - hasCustomThemes = true; } - Collections.sort(defaultThemes, (o1, o2) -> { - if (o1.sortIndex > o2.sortIndex) { - return 1; - } else if (o1.sortIndex < o2.sortIndex) { - return -1; - } - return 0; - }); + Collections.sort(defaultThemes, (o1, o2) -> Integer.compare(o1.sortIndex, o2.sortIndex)); textSizeHeaderRow = rowCount++; textSizeRow = rowCount++; @@ -521,8 +350,12 @@ private void updateRows() { newThemeInfoRow = rowCount++; themeHeaderRow = rowCount++; themeListRow = rowCount++; - if (hasCustomThemes) { - showThemesRows = rowCount++; + hasThemeAccents = Theme.getCurrentTheme().accentColorOptions != null; + if (themesHorizontalListCell != null) { + themesHorizontalListCell.setDrawDivider(hasThemeAccents); + } + if (hasThemeAccents) { + themeAccentListRow = rowCount++; } themeInfoRow = rowCount++; @@ -543,36 +376,11 @@ private void updateRows() { settings2Row = rowCount++; stickersRow = rowCount++; stickersSection2Row = rowCount++; - } else if (currentType == THEME_TYPE_ALL) { - darkThemes.clear(); - defaultThemes.clear(); - for (int a = 0, N = Theme.themes.size(); a < N; a++) { - Theme.ThemeInfo themeInfo = Theme.themes.get(a); - if (themeInfo.pathToFile != null) { - darkThemes.add(themeInfo); - } else { - defaultThemes.add(themeInfo); - } - } - - themeHeaderRow = rowCount++; - themeStartRow = rowCount; - rowCount += defaultThemes.size(); - themeEndRow = rowCount; - themeInfoRow = rowCount++; - - if (!darkThemes.isEmpty()) { - themeHeader2Row = rowCount++; - themeStart2Row = rowCount; - rowCount += darkThemes.size(); - themeEnd2Row = rowCount; - themeInfo2Row = rowCount++; - } } else { darkThemes.clear(); for (int a = 0, N = Theme.themes.size(); a < N; a++) { Theme.ThemeInfo themeInfo = Theme.themes.get(a); - if (themeInfo.isLight()) { + if (themeInfo.isLight() || themeInfo.info != null && themeInfo.info.document == null) { continue; } darkThemes.add(themeInfo); @@ -600,16 +408,34 @@ private void updateRows() { } if (Theme.selectedAutoNightType != Theme.AUTO_NIGHT_TYPE_NONE) { preferedHeaderRow = rowCount++; - themeStartRow = rowCount; - rowCount += darkThemes.size(); - themeEndRow = rowCount; + themeListRow = rowCount++; + hasThemeAccents = Theme.getCurrentNightTheme().accentColorOptions != null; + if (themesHorizontalListCell != null) { + themesHorizontalListCell.setDrawDivider(hasThemeAccents); + } + if (hasThemeAccents) { + themeAccentListRow = rowCount++; + } themeInfoRow = rowCount++; } } if (listAdapter != null) { - if (currentType != THEME_TYPE_NIGHT || previousUpdatedType == -1) { - listAdapter.notifyDataSetChanged(); + if (currentType != THEME_TYPE_NIGHT || previousUpdatedType == Theme.selectedAutoNightType || previousUpdatedType == -1) { + if (notify || previousUpdatedType == -1) { + if (themesHorizontalListCell != null) { + themesHorizontalListCell.notifyDataSetChanged(listView.getWidth()); + } + listAdapter.notifyDataSetChanged(); + } else { + if (prevThemeAccentListRow == -1 && themeAccentListRow != -1) { + listAdapter.notifyItemInserted(themeAccentListRow); + } else if (prevThemeAccentListRow != -1 && themeAccentListRow == -1) { + listAdapter.notifyItemRemoved(prevThemeAccentListRow); + } else if (themeAccentListRow != -1) { + listAdapter.notifyItemChanged(themeAccentListRow); + } + } } else { int start = nightTypeInfoRow + 1; if (previousUpdatedType != Theme.selectedAutoNightType) { @@ -657,6 +483,10 @@ public boolean onFragmentCreate() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.locationPermissionGranted); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.themeListUpdated); + if (currentType == THEME_TYPE_BASIC) { + Theme.loadRemoteThemes(currentAccount, true); + Theme.checkCurrentRemoteTheme(true); + } return super.onFragmentCreate(); } @@ -679,7 +509,7 @@ public void didReceivedNotification(int id, int account, Object... args) { listView.invalidateViews(); } } else if (id == NotificationCenter.themeListUpdated) { - updateRows(); + updateRows(true); } } @@ -696,8 +526,6 @@ public View createView(Context context) { ActionBarMenuItem item = menu.addItem(0, R.drawable.ic_ab_other); item.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); item.addSubItem(create_theme, R.drawable.menu_palette, LocaleController.getString("CreateNewThemeMenu", R.string.CreateNewThemeMenu)); - } else if (currentType == THEME_TYPE_ALL) { - actionBar.setTitle(LocaleController.getString("ColorThemes", R.string.ColorThemes)); } else { actionBar.setTitle(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme)); } @@ -818,47 +646,11 @@ public void onItemClick(int id) { showDialog(builder.create()); } else if (position == stickersRow) { presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE)); - } else if (position == showThemesRows) { - presentFragment(new ThemeActivity(THEME_TYPE_ALL)); } else if (position == emojiRow) { SharedConfig.toggleBigEmoji(); if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(SharedConfig.allowBigEmoji); } - } else if (position >= themeStartRow && position < themeEndRow || position >= themeStart2Row && position < themeEnd2Row) { - int p; - ArrayList themes; - if (themeStart2Row >= 0 && position >= themeStart2Row) { - p = position - themeStart2Row; - themes = darkThemes; - } else { - p = position - themeStartRow; - if (currentType == THEME_TYPE_NIGHT) { - themes = darkThemes; - } else if (currentType == THEME_TYPE_ALL) { - themes = defaultThemes; - } else { - themes = Theme.themes; - } - } - if (p >= 0 && p < themes.size()) { - Theme.ThemeInfo themeInfo = themes.get(p); - if (currentType != THEME_TYPE_NIGHT) { - if (themeInfo == Theme.getCurrentTheme()) { - return; - } - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false); - } else { - Theme.setCurrentNightTheme(themeInfo); - } - int count = listView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = listView.getChildAt(a); - if (child instanceof ThemeCell) { - ((ThemeCell) child).updateCurrentThemeCheck(); - } - } - } } else if (position == nightThemeRow) { if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { NotificationsCheckCell checkCell = (NotificationsCheckCell) view; @@ -883,24 +675,24 @@ public void onItemClick(int id) { } } else if (position == nightDisabledRow) { Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_NONE; - updateRows(); + updateRows(true); Theme.checkAutoNightThemeConditions(); } else if (position == nightScheduledRow) { Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_SCHEDULED; if (Theme.autoNightScheduleByLocation) { updateSunTime(null, true); } - updateRows(); + updateRows(true); Theme.checkAutoNightThemeConditions(); } else if (position == nightAutomaticRow) { Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_AUTOMATIC; - updateRows(); + updateRows(true); Theme.checkAutoNightThemeConditions(); } else if (position == scheduleLocationRow) { Theme.autoNightScheduleByLocation = !Theme.autoNightScheduleByLocation; TextCheckCell checkCell = (TextCheckCell) view; checkCell.setChecked(Theme.autoNightScheduleByLocation); - updateRows(); + updateRows(true); if (Theme.autoNightScheduleByLocation) { updateSunTime(null, true); } @@ -942,8 +734,9 @@ public void onItemClick(int id) { public void onResume() { super.onResume(); if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); + updateRows(true); } + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } private void openThemeCreate() { @@ -953,7 +746,7 @@ private void openThemeCreate() { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { + builder.setPositiveButton(LocaleController.getString("Create", R.string.Create), (dialog, which) -> { }); @@ -985,6 +778,9 @@ private void openThemeCreate() { AndroidUtilities.hideKeyboard(textView); return false; }); + editText.setText(generateThemeName()); + editText.setSelection(editText.length()); + final AlertDialog alertDialog = builder.create(); alertDialog.setOnShowListener(dialog -> AndroidUtilities.runOnUIThread(() -> { editText.requestFocus(); @@ -1001,10 +797,8 @@ private void openThemeCreate() { return; } ThemeEditorView themeEditorView = new ThemeEditorView(); - String name = editText.getText().toString() + ".attheme"; - themeEditorView.show(getParentActivity(), name); - Theme.saveCurrentTheme(name, true); - updateRows(); + themeEditorView.show(getParentActivity(), Theme.createNewTheme(editText.getText().toString())); + updateRows(true); alertDialog.dismiss(); SharedPreferences preferences = MessagesController.getGlobalMainSettings(); @@ -1184,104 +978,157 @@ private String getLocationSunString() { return LocaleController.formatString("AutoNightUpdateLocationInfo", R.string.AutoNightUpdateLocationInfo, sunsetTimeStr, sunriseTimeStr); } - private class InnerThemeView extends FrameLayout { - - private RadioButton button; - private Theme.ThemeInfo themeInfo; - private RectF rect = new RectF(); - private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - private Drawable inDrawable; - private Drawable outDrawable; - private boolean isLast; - private boolean isFirst; + private static class InnerAccentView extends View { + private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private ObjectAnimator checkAnimator; + private float checkedState; + private Theme.ThemeInfo currentTheme; + private int currentColor; - public InnerThemeView(Context context) { + InnerAccentView(Context context) { super(context); - setWillNotDraw(false); + } - inDrawable = context.getResources().getDrawable(R.drawable.minibubble_in).mutate(); - outDrawable = context.getResources().getDrawable(R.drawable.minibubble_out).mutate(); + void setThemeAndColor(Theme.ThemeInfo themeInfo, int color) { + currentTheme = themeInfo; + currentColor = color; + updateCheckedState(false); + } - textPaint.setTextSize(AndroidUtilities.dp(13)); + void updateCheckedState(boolean animate) { + boolean checked = currentTheme.accentColor == currentColor; - button = new RadioButton(context) { - @Override - public void invalidate() { - super.invalidate(); - //ListView.this.invalidate(); - } - }; - button.setSize(AndroidUtilities.dp(20)); - button.setColor(0x66ffffff, 0xffffffff); - addView(button, LayoutHelper.createFrame(22, 22, Gravity.LEFT | Gravity.TOP, 27, 75, 0, 0)); + if (checkAnimator != null) { + checkAnimator.cancel(); + } + + if (animate) { + checkAnimator = ObjectAnimator.ofFloat(this, "checkedState", checked ? 1f : 0f); + checkAnimator.setDuration(200); + checkAnimator.start(); + } else { + setCheckedState(checked ? 1f : 0f); + } } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(76 + (isLast ? 22 : 15) + (isFirst ? 22 : 0)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(148), MeasureSpec.EXACTLY)); + @Keep + public void setCheckedState(float state) { + checkedState = state; + invalidate(); } - public void setTheme(Theme.ThemeInfo theme, boolean last, boolean first) { - themeInfo = theme; - isFirst = first; - isLast = last; - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) button.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(isFirst ? 22 + 27 : 27); - button.setLayoutParams(layoutParams); - inDrawable.setColorFilter(new PorterDuffColorFilter(theme.previewInColor, PorterDuff.Mode.MULTIPLY)); - outDrawable.setColorFilter(new PorterDuffColorFilter(theme.previewOutColor, PorterDuff.Mode.MULTIPLY)); + @Keep + public float getCheckedState() { + return checkedState; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - button.setChecked(themeInfo == Theme.getCurrentTheme(), false); + updateCheckedState(false); } - public void updateCurrentThemeCheck() { - button.setChecked(themeInfo == Theme.getCurrentTheme(), true); + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY) + ); } @Override protected void onDraw(Canvas canvas) { - paint.setColor(themeInfo.previewBackgroundColor); - int x = isFirst ? AndroidUtilities.dp(22) : 0; - rect.set(x, AndroidUtilities.dp(11), x + AndroidUtilities.dp(76), AndroidUtilities.dp(11 + 97)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); - - if ("Arctic Blue".equals(themeInfo.name)) { - int color = 0xffb0b5ba; - int r = Color.red(color); - int g = Color.green(color); - int b = Color.blue(color); - - button.setColor(0xffb3b3b3, 0xff37a9f0); - Theme.chat_instantViewRectPaint.setColor(Color.argb(43, r, g, b)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint); + float radius = AndroidUtilities.dp(20); + + paint.setColor(currentColor); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(AndroidUtilities.dp(3)); + paint.setAlpha(Math.round(255f * checkedState)); + canvas.drawCircle(0.5f * getMeasuredWidth(), 0.5f * getMeasuredHeight(), radius - 0.5f * paint.getStrokeWidth(), paint); + + paint.setAlpha(255); + paint.setStyle(Paint.Style.FILL); + canvas.drawCircle(0.5f * getMeasuredWidth(), 0.5f * getMeasuredHeight(), radius - AndroidUtilities.dp(5) * checkedState, paint); + } + } + + + private static class InnerCustomAccentView extends View { + private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private int[] colors = new int[7]; + + InnerCustomAccentView(Context context) { + super(context); + } + + private void setTheme(Theme.ThemeInfo themeInfo) { + int[] options = themeInfo == null ? null : themeInfo.accentColorOptions; + if (options != null && options.length >= 8) { + colors = new int[] { options[6], options[4], options[7], options[2], options[0], options[5], options[3] }; } else { - button.setColor(0x66ffffff, 0xffffffff); + colors = new int[7]; } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY) + ); + } + + @Override + protected void onDraw(Canvas canvas) { + float centerX = 0.5f * getMeasuredWidth(); + float centerY = 0.5f * getMeasuredHeight(); - inDrawable.setBounds(x + AndroidUtilities.dp(6), AndroidUtilities.dp(22), x + AndroidUtilities.dp(6 + 43), AndroidUtilities.dp(22 + 14)); - inDrawable.draw(canvas); + float radSmall = AndroidUtilities.dp(5); + float radRing = AndroidUtilities.dp(20) - radSmall; - outDrawable.setBounds(x + AndroidUtilities.dp(27), AndroidUtilities.dp(41), x + AndroidUtilities.dp(27 + 43), AndroidUtilities.dp(41 + 14)); - outDrawable.draw(canvas); + paint.setStyle(Paint.Style.FILL); - String text = TextUtils.ellipsize(themeInfo.getName(), textPaint, getMeasuredWidth() - AndroidUtilities.dp(10), TextUtils.TruncateAt.END).toString(); - int width = (int) Math.ceil(textPaint.measureText(text)); - textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - canvas.drawText(text, x + (AndroidUtilities.dp(76) - width) / 2, AndroidUtilities.dp(131), textPaint); + paint.setColor(colors[0]); + canvas.drawCircle(centerX, centerY, radSmall, paint); + + double angle = 0.0; + for (int a = 0; a < 6; a++) { + float cx = centerX + radRing * (float) Math.sin(angle); + float cy = centerY - radRing * (float) Math.cos(angle); + + paint.setColor(colors[a + 1]); + canvas.drawCircle(cx, cy, radSmall, paint); + + angle += Math.PI / 3; + } } } - private class InnerListAdapter extends RecyclerListView.SelectionAdapter { + private class ThemeAccentsListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; + private Theme.ThemeInfo currentTheme; + private int[] options; + private boolean hasExtraColor; + private int extraColor; - public InnerListAdapter(Context context) { + ThemeAccentsListAdapter(Context context) { mContext = context; + setHasStableIds(true); + notifyDataSetChanged(); + } + + @Override + public void notifyDataSetChanged() { + currentTheme = currentType == THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + options = currentTheme.accentColorOptions; + + if (options != null && ArrayUtils.indexOf(options, currentTheme.accentColor) == -1) { + extraColor = currentTheme.accentColor; + hasExtraColor = true; + } + + super.notifyDataSetChanged(); } @Override @@ -1290,30 +1137,73 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { } @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new RecyclerListView.Holder(new InnerThemeView(mContext)); + public long getItemId(int position) { + return getAccentColor(position); } @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - InnerThemeView view = (InnerThemeView) holder.itemView; - view.setTheme(defaultThemes.get(position), position == defaultThemes.size() - 1, position == 0); + public int getItemViewType(int position) { + return position == getItemCount() - 1 ? 1 : 0; } @Override - public int getItemViewType(int position) { - return 0; + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case 0: + return new RecyclerListView.Holder(new InnerAccentView(mContext)); + case 1: + default: + return new RecyclerListView.Holder(new InnerCustomAccentView(mContext)); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (getItemViewType(position)) { + case 0: { + InnerAccentView view = (InnerAccentView) holder.itemView; + view.setThemeAndColor(currentTheme, getAccentColor(position)); + break; + } + case 1: { + InnerCustomAccentView view = (InnerCustomAccentView) holder.itemView; + view.setTheme(currentTheme); + break; + } + } } @Override public int getItemCount() { - return defaultThemes.size(); + return options == null ? 0 : options.length + (hasExtraColor ? 1 : 0) + 1; + } + + int getAccentColor(int pos) { + if (options == null) { + return 0; + } + if (hasExtraColor && pos == options.length) { + return extraColor; + } else if (pos < options.length) { + return options[pos]; + } else { + return 0; + } + } + + int findCurrentAccent() { + if (hasExtraColor && extraColor == currentTheme.accentColor) { + return options.length; + } else { + return ArrayUtils.indexOf(options, currentTheme.accentColor); + } } } private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; + private boolean first = true; public ListAdapter(Context context) { mContext = context; @@ -1327,28 +1217,52 @@ public int getItemCount() { @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); - return type == 0 || type == 1 || type == 4 || type == 7 || type == 10 || type == 11; + return type == 0 || type == 1 || type == 4 || type == 7 || type == 10 || type == 11 || type == 12; } private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { - if (getParentActivity() == null) { + if (getParentActivity() == null || themeInfo.info != null && !themeInfo.themeLoaded || currentType == THEME_TYPE_NIGHT) { return; } - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); CharSequence[] items; + int[] icons; + boolean hasDelete; if (themeInfo.pathToFile == null) { + hasDelete = false; items = new CharSequence[]{ - LocaleController.getString("ShareFile", R.string.ShareFile) + null, + LocaleController.getString("ExportTheme", R.string.ExportTheme) + }; + icons = new int[]{ + 0, + R.drawable.msg_shareout }; } else { + hasDelete = themeInfo.info == null || !themeInfo.info.isDefault; items = new CharSequence[]{ - LocaleController.getString("ShareFile", R.string.ShareFile), - LocaleController.getString("Edit", R.string.Edit), - LocaleController.getString("Delete", R.string.Delete)}; + themeInfo.info != null ? LocaleController.getString("ShareFile", R.string.ShareFile) : null, + LocaleController.getString("ExportTheme", R.string.ExportTheme), + themeInfo.info == null || !themeInfo.info.isDefault && themeInfo.info.creator ? LocaleController.getString("Edit", R.string.Edit) : null, + themeInfo.info != null && themeInfo.info.creator ? LocaleController.getString("ThemeSetUrl", R.string.ThemeSetUrl) : null, + hasDelete ? LocaleController.getString("Delete", R.string.Delete) : null}; + icons = new int[]{ + R.drawable.msg_share, + R.drawable.msg_shareout, + R.drawable.msg_edit, + R.drawable.msg_link, + R.drawable.msg_delete + }; } - builder.setItems(items, (dialog, which) -> { + builder.setItems(items, icons, (dialog, which) -> { + if (getParentActivity() == null) { + return; + } if (which == 0) { + String link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/addtheme/" + themeInfo.info.slug; + showDialog(new ShareAlert(getParentActivity(), null, link, false, link, false)); + } else if (which == 1) { File currentFile; if (themeInfo.pathToFile == null && themeInfo.assetName == null) { StringBuilder result = new StringBuilder(); @@ -1397,12 +1311,14 @@ private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { } catch (Exception e) { FileLog.e(e); } - } else if (which == 1) { + } else if (which == 2) { if (parentLayout != null) { Theme.applyTheme(themeInfo); parentLayout.rebuildAllFragmentViews(true, true); - new ThemeEditorView().show(getParentActivity(), themeInfo.name); + new ThemeEditorView().show(getParentActivity(), themeInfo); } + } else if (which == 3) { + presentFragment(new ThemeSetUrlActivity(themeInfo, false)); } else { if (getParentActivity() == null) { return; @@ -1411,6 +1327,7 @@ private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { builder1.setMessage(LocaleController.getString("DeleteThemeAlert", R.string.DeleteThemeAlert)); builder1.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder1.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> { + getMessagesController().saveTheme(themeInfo, themeInfo == Theme.getCurrentNightTheme(), true); if (Theme.deleteTheme(themeInfo)) { parentLayout.rebuildAllFragmentViews(true, true); } @@ -1420,20 +1337,17 @@ private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { showDialog(builder1.create()); } }); - showDialog(builder.create()); + AlertDialog alertDialog = builder.create(); + showDialog(alertDialog); + if (hasDelete) { + alertDialog.setItemColor(alertDialog.getItemsCount() - 1, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); + } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: - view = new ThemeCell(mContext, currentType == THEME_TYPE_NIGHT); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - if (currentType != THEME_TYPE_NIGHT) { - ((ThemeCell) view).setOnOptionsClick(v -> showOptionsForTheme(((ThemeCell) v.getParent()).getCurrentThemeInfo())); - } - break; case 1: view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -1494,74 +1408,81 @@ protected void didSelectChatType(boolean threeLines) { view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 11: - default: { - RecyclerListView horizontalListView = new RecyclerListView(mContext) { + first = true; + themesHorizontalListCell = new ThemesHorizontalListCell(mContext, currentType, defaultThemes, darkThemes) { @Override - public boolean onInterceptTouchEvent(MotionEvent e) { - if (getParent() != null && getParent().getParent() != null) { - getParent().getParent().requestDisallowInterceptTouchEvent(true); - } - return super.onInterceptTouchEvent(e); + protected void showOptionsForTheme(Theme.ThemeInfo themeInfo) { + listAdapter.showOptionsForTheme(themeInfo); } @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (hasCustomThemes) { - canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); - } + protected void presentFragment(BaseFragment fragment) { + ThemeActivity.this.presentFragment(fragment); } @Override - public void setBackgroundColor(int color) { - super.setBackgroundColor(color); - invalidateViews(); + protected void updateRows() { + ThemeActivity.this.updateRows(false); } }; - horizontalListView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - horizontalListView.setItemAnimator(null); - horizontalListView.setLayoutAnimation(null); - LinearLayoutManager layoutManager = new LinearLayoutManager(mContext) { + themesHorizontalListCell.setDrawDivider(hasThemeAccents); + view = themesHorizontalListCell; + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(148))); + break; + case 12: + default: { + RecyclerListView accentsListView = new TintRecyclerListView(mContext) { @Override - public boolean supportsPredictiveItemAnimations() { - return false; + public boolean onInterceptTouchEvent(MotionEvent e) { + if (getParent() != null && getParent().getParent() != null) { + getParent().getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(e); } }; - horizontalListView.setPadding(0, 0, 0, 0); - horizontalListView.setClipToPadding(false); - layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); - horizontalListView.setLayoutManager(layoutManager); - horizontalListView.setAdapter(new InnerListAdapter(mContext)); - horizontalListView.setOnItemClickListener((view1, position) -> { - InnerThemeView innerThemeView = (InnerThemeView) view1; - Theme.ThemeInfo themeInfo = innerThemeView.themeInfo; - if (themeInfo == Theme.getCurrentTheme()) { - return; + accentsListView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + accentsListView.setItemAnimator(null); + accentsListView.setLayoutAnimation(null); + accentsListView.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), 0); + accentsListView.setClipToPadding(false); + LinearLayoutManager accentsLayoutManager = new LinearLayoutManager(mContext); + accentsLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + accentsListView.setLayoutManager(accentsLayoutManager); + ThemeAccentsListAdapter accentsAdapter = new ThemeAccentsListAdapter(mContext); + accentsListView.setAdapter(accentsAdapter); + accentsListView.setOnItemClickListener((view1, position) -> { + Theme.ThemeInfo currentTheme = currentType == THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + + if (position == accentsAdapter.getItemCount() - 1) { + presentFragment(new ThemePreviewActivity(currentTheme, false, ThemePreviewActivity.SCREEN_TYPE_ACCENT_COLOR, currentType == THEME_TYPE_NIGHT)); + } else { + int newAccent = accentsAdapter.getAccentColor(position); + if (currentTheme.accentColor != newAccent) { + Theme.saveThemeAccent(currentTheme, newAccent); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentTheme, currentType == THEME_TYPE_NIGHT); + } } - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false); + int left = view1.getLeft(); int right = view1.getRight(); - if (left < 0) { - horizontalListView.smoothScrollBy(left - AndroidUtilities.dp(8), 0); - } else if (right > horizontalListView.getMeasuredWidth()) { - horizontalListView.smoothScrollBy(right - horizontalListView.getMeasuredWidth(), 0); + int extra = AndroidUtilities.dp(52); + if (left - extra < 0) { + accentsListView.smoothScrollBy(left - extra, 0); + } else if (right + extra > accentsListView.getMeasuredWidth()) { + accentsListView.smoothScrollBy(right + extra - accentsListView.getMeasuredWidth(), 0); } - int count = innerListView.getChildCount(); + int count = accentsListView.getChildCount(); for (int a = 0; a < count; a++) { - View child = innerListView.getChildAt(a); - if (child instanceof InnerThemeView) { - ((InnerThemeView) child).updateCurrentThemeCheck(); + View child = accentsListView.getChildAt(a); + if (child instanceof InnerAccentView) { + ((InnerAccentView) child).updateCheckedState(true); } } }); - horizontalListView.setOnItemLongClickListener((view12, position) -> { - InnerThemeView innerThemeView = (InnerThemeView) view12; - showOptionsForTheme(innerThemeView.themeInfo); - return true; - }); - view = innerListView = horizontalListView; - view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(148))); + + view = accentsListView; + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(62))); break; } } @@ -1571,25 +1492,6 @@ public boolean supportsPredictiveItemAnimations() { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 0: { - ArrayList themes; - if (themeStart2Row >= 0 && position >= themeStart2Row) { - position -= themeStart2Row; - themes = darkThemes; - } else { - position -= themeStartRow; - if (currentType == THEME_TYPE_NIGHT) { - themes = darkThemes; - } else if (currentType == THEME_TYPE_ALL) { - themes = defaultThemes; - } else { - themes = Theme.themes; - } - } - Theme.ThemeInfo themeInfo = themes.get(position); - ((ThemeCell) holder.itemView).setTheme(themeInfo, position != themes.size() - 1 || hasCustomThemes); - break; - } case 1: { TextSettingsCell cell = (TextSettingsCell) holder.itemView; if (position == nightThemeRow) { @@ -1626,8 +1528,6 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { cell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); } else if (position == stickersRow) { cell.setText(LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), false); - } else if (position == showThemesRows) { - cell.setText(LocaleController.getString("ShowAllThemes", R.string.ShowAllThemes), false); } else if (position == distanceRow) { String value; if (SharedConfig.distanceSystemType == 0) { @@ -1651,7 +1551,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { break; } case 3: { - if (position == stickersSection2Row || position == themeInfo2Row || position == nightTypeInfoRow && themeInfoRow == -1 || position == themeInfoRow && nightTypeInfoRow != -1) { + if (position == stickersSection2Row || position == nightTypeInfoRow && themeInfoRow == -1 || position == themeInfoRow && nightTypeInfoRow != -1) { holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else { holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); @@ -1680,17 +1580,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == settingsRow) { headerCell.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); } else if (position == themeHeaderRow) { - if (currentType == THEME_TYPE_ALL) { - headerCell.setText(LocaleController.getString("BuiltInThemes", R.string.BuiltInThemes)); - } else { - headerCell.setText(LocaleController.getString("ColorTheme", R.string.ColorTheme)); - } + headerCell.setText(LocaleController.getString("ColorTheme", R.string.ColorTheme)); } else if (position == textSizeHeaderRow) { headerCell.setText(LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader)); } else if (position == chatListHeaderRow) { headerCell.setText(LocaleController.getString("ChatList", R.string.ChatList)); - } else if (position == themeHeader2Row) { - headerCell.setText(LocaleController.getString("CustomThemes", R.string.CustomThemes)); } break; } @@ -1735,6 +1629,26 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } break; } + case 11: { + if (first) { + themesHorizontalListCell.scrollToCurrentTheme(listView.getMeasuredWidth(), false); + first = false; + } + break; + } + case 12: { + RecyclerListView accentsList = (RecyclerListView) holder.itemView; + ThemeAccentsListAdapter adapter = (ThemeAccentsListAdapter) accentsList.getAdapter(); + adapter.notifyDataSetChanged(); + int pos = adapter.findCurrentAccent(); + if (pos == -1) { + pos = adapter.getItemCount() - 1; + } + if (pos != -1) { + ((LinearLayoutManager) accentsList.getLayoutManager()).scrollToPositionWithOffset(pos, listView.getMeasuredWidth() / 2 - AndroidUtilities.dp(42)); + } + break; + } } } @@ -1743,8 +1657,6 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); if (type == 4) { ((ThemeTypeCell) holder.itemView).setTypeChecked(holder.getAdapterPosition() == Theme.selectedAutoNightType); - } else if (type == 0) { - ((ThemeCell) holder.itemView).updateCurrentThemeCheck(); } if (type != 2 && type != 3) { holder.itemView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -1753,7 +1665,7 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { @Override public int getItemViewType(int position) { - if (position == scheduleFromRow || position == showThemesRows || position == distanceRow || + if (position == scheduleFromRow || position == distanceRow || position == scheduleToRow || position == scheduleUpdateLocationRow || position == backgroundRow || position == contactsReimportRow || position == contactsSortRow || position == stickersRow) { return 1; @@ -1761,13 +1673,13 @@ public int getItemViewType(int position) { return 2; } else if (position == themeInfoRow || position == nightTypeInfoRow || position == scheduleFromToInfoRow || position == stickersSection2Row || position == settings2Row || position == newThemeInfoRow || - position == chatListInfoRow || position == themeInfo2Row) { + position == chatListInfoRow) { return 3; } else if (position == nightDisabledRow || position == nightScheduledRow || position == nightAutomaticRow) { return 4; } else if (position == scheduleHeaderRow || position == automaticHeaderRow || position == preferedHeaderRow || position == settingsRow || position == themeHeaderRow || position == textSizeHeaderRow || - position == chatListHeaderRow || position == themeHeader2Row) { + position == chatListHeaderRow) { return 5; } else if (position == automaticBrightnessRow) { return 6; @@ -1783,17 +1695,360 @@ public int getItemViewType(int position) { return 10; } else if (position == themeListRow) { return 11; + } else if (position == themeAccentListRow) { + return 12; + } + return 1; + } + } + + private static abstract class TintRecyclerListView extends RecyclerListView { + TintRecyclerListView(Context context) { + super(context); + } + } + + private String generateThemeName() { + List adjectives = Arrays.asList( + "Ancient", + "Antique", + "Autumn", + "Baby", + "Barely", + "Baroque", + "Blazing", + "Blushing", + "Bohemian", + "Bubbly", + "Burning", + "Buttered", + "Classic", + "Clear", + "Cool", + "Cosmic", + "Cotton", + "Cozy", + "Crystal", + "Dark", + "Daring", + "Darling", + "Dawn", + "Dazzling", + "Deep", + "Deepest", + "Delicate", + "Delightful", + "Divine", + "Double", + "Downtown", + "Dreamy", + "Dusky", + "Dusty", + "Electric", + "Enchanted", + "Endless", + "Evening", + "Fantastic", + "Flirty", + "Forever", + "Frigid", + "Frosty", + "Frozen", + "Gentle", + "Heavenly", + "Hyper", + "Icy", + "Infinite", + "Innocent", + "Instant", + "Luscious", + "Lunar", + "Lustrous", + "Magic", + "Majestic", + "Mambo", + "Midnight", + "Millenium", + "Morning", + "Mystic", + "Natural", + "Neon", + "Night", + "Opaque", + "Paradise", + "Perfect", + "Perky", + "Polished", + "Powerful", + "Rich", + "Royal", + "Sheer", + "Simply", + "Sizzling", + "Solar", + "Sparkling", + "Splendid", + "Spicy", + "Spring", + "Stellar", + "Sugared", + "Summer", + "Sunny", + "Super", + "Sweet", + "Tender", + "Tenacious", + "Tidal", + "Toasted", + "Totally", + "Tranquil", + "Tropical", + "True", + "Twilight", + "Twinkling", + "Ultimate", + "Ultra", + "Velvety", + "Vibrant", + "Vintage", + "Virtual", + "Warm", + "Warmest", + "Whipped", + "Wild", + "Winsome" + ); + + List subjectives = Arrays.asList( + "Ambrosia", + "Attack", + "Avalanche", + "Blast", + "Bliss", + "Blossom", + "Blush", + "Burst", + "Butter", + "Candy", + "Carnival", + "Charm", + "Chiffon", + "Cloud", + "Comet", + "Delight", + "Dream", + "Dust", + "Fantasy", + "Flame", + "Flash", + "Fire", + "Freeze", + "Frost", + "Glade", + "Glaze", + "Gleam", + "Glimmer", + "Glitter", + "Glow", + "Grande", + "Haze", + "Highlight", + "Ice", + "Illusion", + "Intrigue", + "Jewel", + "Jubilee", + "Kiss", + "Lights", + "Lollypop", + "Love", + "Luster", + "Madness", + "Matte", + "Mirage", + "Mist", + "Moon", + "Muse", + "Myth", + "Nectar", + "Nova", + "Parfait", + "Passion", + "Pop", + "Rain", + "Reflection", + "Rhapsody", + "Romance", + "Satin", + "Sensation", + "Silk", + "Shine", + "Shadow", + "Shimmer", + "Sky", + "Spice", + "Star", + "Sugar", + "Sunrise", + "Sunset", + "Sun", + "Twist", + "Unbound", + "Velvet", + "Vibrant", + "Waters", + "Wine", + "Wink", + "Wonder", + "Zone" + ); + + HashMap colors = new HashMap<>(); + colors.put(0x8e0000, "Berry"); + colors.put(0xdec196, "Brandy"); + colors.put(0x800b47, "Cherry"); + colors.put(0xff7f50, "Coral"); + colors.put(0xdb5079, "Cranberry"); + colors.put(0xdc143c, "Crimson"); + colors.put(0xe0b0ff, "Mauve"); + colors.put(0xffc0cb, "Pink"); + colors.put(0xff0000, "Red"); + colors.put(0xff007f, "Rose"); + colors.put(0x80461b, "Russet"); + colors.put(0xff2400, "Scarlet"); + colors.put(0xf1f1f1, "Seashell"); + colors.put(0xff3399, "Strawberry"); + colors.put(0xffbf00, "Amber"); + colors.put(0xeb9373, "Apricot"); + colors.put(0xfbe7b2, "Banana"); + colors.put(0xa1c50a, "Citrus"); + colors.put(0xb06500, "Ginger"); + colors.put(0xffd700, "Gold"); + colors.put(0xfde910, "Lemon"); + colors.put(0xffa500, "Orange"); + colors.put(0xffe5b4, "Peach"); + colors.put(0xff6b53, "Persimmon"); + colors.put(0xe4d422, "Sunflower"); + colors.put(0xf28500, "Tangerine"); + colors.put(0xffc87c, "Topaz"); + colors.put(0xffff00, "Yellow"); + colors.put(0x384910, "Clover"); + colors.put(0x83aa5d, "Cucumber"); + colors.put(0x50c878, "Emerald"); + colors.put(0xb5b35c, "Olive"); + colors.put(0x00ff00, "Green"); + colors.put(0x00a86b, "Jade"); + colors.put(0x29ab87, "Jungle"); + colors.put(0xbfff00, "Lime"); + colors.put(0x0bda51, "Malachite"); + colors.put(0x98ff98, "Mint"); + colors.put(0xaddfad, "Moss"); + colors.put(0x315ba1, "Azure"); + colors.put(0x0000ff, "Blue"); + colors.put(0x0047ab, "Cobalt"); + colors.put(0x4f69c6, "Indigo"); + colors.put(0x017987, "Lagoon"); + colors.put(0x71d9e2, "Aquamarine"); + colors.put(0x120a8f, "Ultramarine"); + colors.put(0x000080, "Navy"); + colors.put(0x2f519e, "Sapphire"); + colors.put(0x76d7ea, "Sky"); + colors.put(0x008080, "Teal"); + colors.put(0x40e0d0, "Turquoise"); + colors.put(0x9966cc, "Amethyst"); + colors.put(0x4d0135, "Blackberry"); + colors.put(0x614051, "Eggplant"); + colors.put(0xc8a2c8, "Lilac"); + colors.put(0xb57edc, "Lavender"); + colors.put(0xccccff, "Periwinkle"); + colors.put(0x843179, "Plum"); + colors.put(0x660099, "Purple"); + colors.put(0xd8bfd8, "Thistle"); + colors.put(0xda70d6, "Orchid"); + colors.put(0x240a40, "Violet"); + colors.put(0x3f2109, "Bronze"); + colors.put(0x370202, "Chocolate"); + colors.put(0x7b3f00, "Cinnamon"); + colors.put(0x301f1e, "Cocoa"); + colors.put(0x706555, "Coffee"); + colors.put(0x796989, "Rum"); + colors.put(0x4e0606, "Mahogany"); + colors.put(0x782d19, "Mocha"); + colors.put(0xc2b280, "Sand"); + colors.put(0x882d17, "Sienna"); + colors.put(0x780109, "Maple"); + colors.put(0xf0e68c, "Khaki"); + colors.put(0xb87333, "Copper"); + colors.put(0xb94e48, "Chestnut"); + colors.put(0xeed9c4, "Almond"); + colors.put(0xfffdd0, "Cream"); + colors.put(0xb9f2ff, "Diamond"); + colors.put(0xa98307, "Honey"); + colors.put(0xfffff0, "Ivory"); + colors.put(0xeae0c8, "Pearl"); + colors.put(0xeff2f3, "Porcelain"); + colors.put(0xd1bea8, "Vanilla"); + colors.put(0xffffff, "White"); + colors.put(0x808080, "Gray"); + colors.put(0x000000, "Black"); + colors.put(0xe8f1d4, "Chrome"); + colors.put(0x36454f, "Charcoal"); + colors.put(0x0c0b1d, "Ebony"); + colors.put(0xc0c0c0, "Silver"); + colors.put(0xf5f5f5, "Smoke"); + colors.put(0x262335, "Steel"); + colors.put(0x4fa83d, "Apple"); + colors.put(0x80b3c4, "Glacier"); + colors.put(0xfebaad, "Melon"); + colors.put(0xc54b8c, "Mulberry"); + colors.put(0xa9c6c2, "Opal"); + colors.put(0x54a5f8, "Blue"); + + int color; + Theme.ThemeInfo themeInfo = Theme.getCurrentTheme(); + if (themeInfo.accentColor != 0) { + color = themeInfo.accentColor; + } else { + color = AndroidUtilities.calcDrawableColor(Theme.getCachedWallpaper())[0]; + } + + String minKey = null; + int minValue = Integer.MAX_VALUE; + int r1 = Color.red(color); + int g1 = Color.green(color); + int b1 = Color.blue(color); + + for (HashMap.Entry entry : colors.entrySet()) { + Integer value = entry.getKey(); + int r2 = Color.red(value); + int g2 = Color.green(value); + int b2 = Color.blue(value); + + int rMean = (r1 + r2) / 2; + int r = r1 - r2; + int g = g1 - g2; + int b = b1 - b2; + int d = (((512 + rMean) * r * r) >> 8) + (4 * g * g) + (((767 - rMean) * b * b) >> 8); + + if (d < minValue) { + minKey = entry.getValue(); + minValue = d; } - return 0; } + String result; + if (Utilities.random.nextInt() % 2 == 0) { + result = adjectives.get(Utilities.random.nextInt(adjectives.size())) + " " + minKey; + } else { + result = minKey + " " + subjectives.get(Utilities.random.nextInt(subjectives.size())); + } + return result; } @Override public ThemeDescription[] getThemeDescriptions() { return new ThemeDescription[]{ - new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, ThemeCell.class, TextSizeCell.class, ChatListCell.class, NotificationsCheckCell.class}, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, TextSizeCell.class, ChatListCell.class, NotificationsCheckCell.class, ThemesHorizontalListCell.class, TintRecyclerListView.class}, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), - new ThemeDescription(innerListView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault), @@ -1808,10 +2063,6 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider), - new ThemeDescription(listView, 0, new Class[]{ThemeCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(listView, 0, new Class[]{ThemeCell.class}, new String[]{"checkImage"}, null, null, null, Theme.key_featuredStickers_addedIcon), - new ThemeDescription(listView, 0, new Class[]{ThemeCell.class}, new String[]{"optionsButton"}, null, null, null, Theme.key_stickers_menu), - new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), @@ -1853,8 +2104,10 @@ public ThemeDescription[] getThemeDescriptions() { new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextIn), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_messageTextOut), - new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck), - new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected), new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyLine), new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyLine), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index c6b2523cc71..34d7e2afe40 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -33,10 +33,10 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.BuildVars; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; @@ -53,10 +53,12 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.MenuDrawable; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.LoadingCell; +import org.telegram.ui.Components.ColorPicker; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -64,29 +66,63 @@ import java.io.File; import java.util.ArrayList; +import java.util.List; public class ThemePreviewActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + public static final int SCREEN_TYPE_PREVIEW = 0; + public static final int SCREEN_TYPE_ACCENT_COLOR = 1; + + private final int screenType; + private boolean useDefaultThemeForButtons = true; + + private ViewPager viewPager; + private FrameLayout page1; private RecyclerListView listView; private DialogsAdapter dialogsAdapter; private ImageView floatingButton; - private View dotsContainer; - private ActionBar actionBar2; + private ActionBar actionBar2; private SizeNotifierFrameLayout page2; private RecyclerListView listView2; private MessagesAdapter messagesAdapter; + private ColorPicker colorPicker; + private int lastPickedColor; + private Runnable applyAccentAction = () -> { + applyAccentScheduled = false; + applyAccent(lastPickedColor); + }; + private boolean applyAccentScheduled; + + private View dotsContainer; + private FrameLayout buttonsContainer; + private TextView doneButton; + private TextView cancelButton; + private Theme.ThemeInfo applyingTheme; - private File themeFile; - private boolean applied; + private boolean nightTheme; + private boolean deleteOnCancel; + private List themeDescriptions; - public ThemePreviewActivity(File file, Theme.ThemeInfo themeInfo) { + public ThemePreviewActivity(Theme.ThemeInfo themeInfo) { + this(themeInfo, false, SCREEN_TYPE_PREVIEW, false); + } + + public ThemePreviewActivity(Theme.ThemeInfo themeInfo, boolean deleteFile, int screenType, boolean night) { super(); + this.screenType = screenType; swipeBackEnabled = false; + nightTheme = night; applyingTheme = themeInfo; - themeFile = file; + deleteOnCancel = deleteFile; + + if (screenType == SCREEN_TYPE_ACCENT_COLOR) { + Theme.applyThemeTemporary(new Theme.ThemeInfo(applyingTheme)); + useDefaultThemeForButtons = false; + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.goingToPreviewTheme); } @Override @@ -224,14 +260,32 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { actionBar2 = createActionBar(context); actionBar2.setBackButtonDrawable(new BackDrawable(false)); + page2.addView(actionBar2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + actionBar2.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + cancelThemeApply(); + } + } + }); + if (messagesAdapter.showSecretMessages) { actionBar2.setTitle("Telegram Beta Chat"); actionBar2.setSubtitle(LocaleController.formatPluralString("Members", 505)); } else { - actionBar2.setTitle("Reinhardt"); - actionBar2.setSubtitle(LocaleController.formatDateOnline(System.currentTimeMillis() / 1000 - 60 * 60)); + String name = applyingTheme.info != null ? applyingTheme.info.title : applyingTheme.getName(); + int index = name.lastIndexOf(".attheme"); + if (index >= 0) { + name = name.substring(0, index); + } + actionBar2.setTitle(name); + if (applyingTheme.info != null && applyingTheme.info.installs_count > 0) { + actionBar2.setSubtitle(LocaleController.formatPluralString("ThemeInstallCount", applyingTheme.info.installs_count)); + } else { + actionBar2.setSubtitle(LocaleController.formatDateOnline(System.currentTimeMillis() / 1000 - 60 * 60)); + } } - page2.addView(actionBar2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); listView2 = new RecyclerListView(context) { @Override @@ -322,10 +376,11 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { listView2.setAdapter(messagesAdapter); - fragmentView = new FrameLayout(context); - FrameLayout frameLayout = (FrameLayout) fragmentView; + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + fragmentView = linearLayout; - final ViewPager viewPager = new ViewPager(context); + viewPager = new ViewPager(context); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { @@ -361,7 +416,7 @@ public int getItemPosition(Object object) { @Override public Object instantiateItem(ViewGroup container, int position) { - View view = position == 0 ? page1 : page2; + View view = position == 0 ? page2 : page1; container.addView(view); return view; } @@ -379,15 +434,35 @@ public void unregisterDataSetObserver(DataSetObserver observer) { } }); AndroidUtilities.setViewPagerEdgeEffectColor(viewPager, Theme.getColor(Theme.key_actionBarDefault)); - frameLayout.addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); + linearLayout.addView(viewPager, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); View shadow = new View(context); shadow.setBackgroundResource(R.drawable.header_shadow_reverse); - frameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48)); + linearLayout.addView(shadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3, Gravity.NO_GRAVITY, 0, -3, 0, 0)); - FrameLayout bottomLayout = new FrameLayout(context); - bottomLayout.setBackgroundColor(0xffffffff); - frameLayout.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + if (screenType == SCREEN_TYPE_ACCENT_COLOR) { + FrameLayout colorPickerFrame = new FrameLayout(context); + linearLayout.addView(colorPickerFrame, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); + + colorPicker = new ColorPicker(context, this::scheduleApplyAccent); + + if (applyingTheme.isDark()) { + colorPicker.setMinBrightness((r, g, b) -> 255f / (0.5f * r + 0.8f * g + 0.1f * b + 500f)); + } else { + colorPicker.setMaxBrightness((r, g, b) -> 255f / (0.1f * r + 1.0f * g + 0.1f * b + 50f)); + } + + colorPicker.setColor(applyingTheme.accentColor); + colorPickerFrame.addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 342, Gravity.CENTER_HORIZONTAL)); + + View shadow2 = new View(context); + shadow2.setBackgroundColor(0x12000000); + linearLayout.addView(shadow2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 2, Gravity.NO_GRAVITY, 0, -2, 0, 0)); + } + + buttonsContainer = new FrameLayout(context); + buttonsContainer.setBackgroundColor(getButtonsColor(Theme.key_windowBackgroundWhite)); + linearLayout.addView(buttonsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); dotsContainer = new View(context) { @@ -396,57 +471,64 @@ public void unregisterDataSetObserver(DataSetObserver observer) { @Override protected void onDraw(Canvas canvas) { int selected = viewPager.getCurrentItem(); + paint.setColor(getButtonsColor(Theme.key_chat_fieldOverlayText)); for (int a = 0; a < 2; a++) { - paint.setColor(a == selected ? 0xff999999 : 0xffcccccc); + paint.setAlpha(a == selected ? 255 : 127); canvas.drawCircle(AndroidUtilities.dp(3 + 15 * a), AndroidUtilities.dp(4), AndroidUtilities.dp(3), paint); } } }; - bottomLayout.addView(dotsContainer, LayoutHelper.createFrame(22, 8, Gravity.CENTER)); + buttonsContainer.addView(dotsContainer, LayoutHelper.createFrame(22, 8, Gravity.CENTER)); - TextView cancelButton = new TextView(context); + cancelButton = new TextView(context); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - cancelButton.setTextColor(0xff19a7e8); + cancelButton.setTextColor(getButtonsColor(Theme.key_chat_fieldOverlayText)); cancelButton.setGravity(Gravity.CENTER); cancelButton.setBackgroundDrawable(Theme.createSelectorDrawable(0x2f000000, 0)); cancelButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0); cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); cancelButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - bottomLayout.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); - cancelButton.setOnClickListener(v -> { - Theme.applyPreviousTheme(); - parentLayout.rebuildAllFragmentViews(false, false); - finishFragment(); - }); + buttonsContainer.addView(cancelButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + cancelButton.setOnClickListener(v -> cancelThemeApply()); - TextView doneButton = new TextView(context); + doneButton = new TextView(context); doneButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - doneButton.setTextColor(0xff19a7e8); + doneButton.setTextColor(getButtonsColor(Theme.key_chat_fieldOverlayText)); doneButton.setGravity(Gravity.CENTER); doneButton.setBackgroundDrawable(Theme.createSelectorDrawable(0x2f000000, 0)); doneButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0); doneButton.setText(LocaleController.getString("ApplyTheme", R.string.ApplyTheme).toUpperCase()); doneButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - bottomLayout.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); + buttonsContainer.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); doneButton.setOnClickListener(v -> { - applied = true; - parentLayout.rebuildAllFragmentViews(false, false); - Theme.applyThemeFile(themeFile, applyingTheme.name, false); + if (screenType == SCREEN_TYPE_PREVIEW) { + parentLayout.rebuildAllFragmentViews(false, false); + Theme.applyThemeFile(new File(applyingTheme.pathToFile), applyingTheme.name, applyingTheme.info, false); + getMessagesController().saveTheme(applyingTheme, false, false); + } else if (screenType == SCREEN_TYPE_ACCENT_COLOR) { + Theme.saveThemeAccent(applyingTheme, colorPicker.getColor()); + Theme.applyPreviousTheme(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, applyingTheme, nightTheme); + } finishFragment(); }); + themeDescriptions = getThemeDescriptionsInternal(); + return fragmentView; } @Override public boolean onFragmentCreate() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper); return super.onFragmentCreate(); } @Override public void onFragmentDestroy() { NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); super.onFragmentDestroy(); } @@ -462,6 +544,8 @@ public void onResume() { if (page2 != null) { page2.onResume(); } + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); } @Override @@ -475,7 +559,12 @@ public void onPause() { @Override public boolean onBackPressed() { Theme.applyPreviousTheme(); - parentLayout.rebuildAllFragmentViews(false, false); + if (screenType != SCREEN_TYPE_ACCENT_COLOR) { + parentLayout.rebuildAllFragmentViews(false, false); + } + if (deleteOnCancel && applyingTheme.pathToFile != null && !Theme.isThemeInstalled(applyingTheme)) { + new File(applyingTheme.pathToFile).delete(); + } return super.onBackPressed(); } @@ -493,7 +582,47 @@ public void didReceivedNotification(int id, int account, Object... args) { cell.update(0); } } + } else if (id == NotificationCenter.didSetNewWallpapper) { + if (page2 != null) { + page2.setBackgroundImage(Theme.getCachedWallpaper(), Theme.isWallpaperMotion()); + } + } + } + + private void cancelThemeApply() { + Theme.applyPreviousTheme(); + if (screenType != SCREEN_TYPE_ACCENT_COLOR) { + parentLayout.rebuildAllFragmentViews(false, false); + } + if (deleteOnCancel && applyingTheme.pathToFile != null && !Theme.isThemeInstalled(applyingTheme)) { + new File(applyingTheme.pathToFile).delete(); } + finishFragment(); + } + + private int getButtonsColor(String key) { + return useDefaultThemeForButtons ? Theme.getDefaultColor(key) : Theme.getColor(key); + } + + private void scheduleApplyAccent(int accent) { + lastPickedColor = accent; + if (!applyAccentScheduled) { + applyAccentScheduled = true; + fragmentView.postDelayed(applyAccentAction, 16L); // To not apply accent color too often + } + } + + private void applyAccent(int accent) { + Theme.applyCurrentThemeAccent(accent); + + for (int i = 0, size = themeDescriptions.size(); i < size; i++) { + ThemeDescription description = themeDescriptions.get(i); + description.setColor(Theme.getColor(description.getCurrentKey()), false, false); + } + + listView.invalidateViews(); + listView2.invalidateViews(); + dotsContainer.invalidate(); } public class DialogsAdapter extends RecyclerListView.SelectionAdapter { @@ -508,8 +637,8 @@ public DialogsAdapter(Context context) { int date = (int) (System.currentTimeMillis() / 1000); DialogCell.CustomDialog customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Eva Summer"; - customDialog.message = "Reminds me of a Chinese prove..."; + customDialog.name = LocaleController.getString("ThemePreviewDialog1", R.string.ThemePreviewDialog1); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage1", R.string.ThemePreviewDialogMessage1); customDialog.id = 0; customDialog.unread_count = 0; customDialog.pinned = true; @@ -522,8 +651,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Your inner Competition"; - customDialog.message = "hey, I've updated the source code."; + customDialog.name = LocaleController.getString("ThemePreviewDialog2", R.string.ThemePreviewDialog2); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage2", R.string.ThemePreviewDialogMessage2); customDialog.id = 1; customDialog.unread_count = 2; customDialog.pinned = false; @@ -536,8 +665,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Mike Apple"; - customDialog.message = "\uD83E\uDD37\u200D♂️ Sticker"; + customDialog.name = LocaleController.getString("ThemePreviewDialog3", R.string.ThemePreviewDialog3); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage3", R.string.ThemePreviewDialogMessage3); customDialog.id = 2; customDialog.unread_count = 3; customDialog.pinned = false; @@ -550,8 +679,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Paul Newman"; - customDialog.message = "Any ideas?"; + customDialog.name = LocaleController.getString("ThemePreviewDialog4", R.string.ThemePreviewDialog4); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage4", R.string.ThemePreviewDialogMessage4); customDialog.id = 3; customDialog.unread_count = 0; customDialog.pinned = false; @@ -564,8 +693,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Old Pirates"; - customDialog.message = "Yo-ho-ho!"; + customDialog.name = LocaleController.getString("ThemePreviewDialog5", R.string.ThemePreviewDialog5); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage5", R.string.ThemePreviewDialogMessage5); customDialog.id = 4; customDialog.unread_count = 0; customDialog.pinned = false; @@ -578,8 +707,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Kate Bright"; - customDialog.message = "Hola!"; + customDialog.name = LocaleController.getString("ThemePreviewDialog6", R.string.ThemePreviewDialog6); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage6", R.string.ThemePreviewDialogMessage6); customDialog.id = 5; customDialog.unread_count = 0; customDialog.pinned = false; @@ -592,8 +721,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Nick K"; - customDialog.message = "These are not the droids you are looking for"; + customDialog.name = LocaleController.getString("ThemePreviewDialog7", R.string.ThemePreviewDialog7); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage7", R.string.ThemePreviewDialogMessage7); customDialog.id = 6; customDialog.unread_count = 0; customDialog.pinned = false; @@ -606,8 +735,8 @@ public DialogsAdapter(Context context) { dialogs.add(customDialog); customDialog = new DialogCell.CustomDialog(); - customDialog.name = "Adler Toberg"; - customDialog.message = "Did someone say peanut butter?"; + customDialog.name = LocaleController.getString("ThemePreviewDialog8", R.string.ThemePreviewDialog8); + customDialog.message = LocaleController.getString("ThemePreviewDialogMessage8", R.string.ThemePreviewDialogMessage8); customDialog.id = 0; customDialog.unread_count = 0; customDialog.pinned = false; @@ -665,7 +794,7 @@ public class MessagesAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; private ArrayList messages; - private boolean showSecretMessages = Utilities.random.nextInt(100) <= (BuildVars.DEBUG_VERSION ? 5 : 1); + private boolean showSecretMessages = Utilities.random.nextInt(100) <= 1; public MessagesAdapter(Context context) { mContext = context; @@ -731,7 +860,7 @@ public MessagesAdapter(Context context) { messages.add(new MessageObject(currentAccount, message, true)); } else { message = new TLRPC.TL_message(); - message.message = "Reinhardt, we need to find you some new tunes \uD83C\uDFB6."; + message.message = LocaleController.getString("ThemePreviewLine1", R.string.ThemePreviewLine1); message.date = date + 60; message.dialog_id = 1; message.flags = 259; @@ -744,7 +873,7 @@ public MessagesAdapter(Context context) { MessageObject replyMessageObject = new MessageObject(currentAccount, message, true); message = new TLRPC.TL_message(); - message.message = "I can't even take you seriously right now."; + message.message = LocaleController.getString("ThemePreviewLine2", R.string.ThemePreviewLine2); message.date = date + 960; message.dialog_id = 1; message.flags = 259; @@ -769,8 +898,8 @@ public MessagesAdapter(Context context) { message.media.document.file_reference = new byte[0]; TLRPC.TL_documentAttributeAudio audio = new TLRPC.TL_documentAttributeAudio(); audio.duration = 243; - audio.performer = "David Hasselhoff"; - audio.title = "True Survivor"; + audio.performer = LocaleController.getString("ThemePreviewSongPerformer", R.string.ThemePreviewSongPerformer); + audio.title = LocaleController.getString("ThemePreviewSongTitle", R.string.ThemePreviewSongTitle); message.media.document.attributes.add(audio); message.out = false; message.to_id = new TLRPC.TL_peerUser(); @@ -778,7 +907,7 @@ public MessagesAdapter(Context context) { messages.add(new MessageObject(currentAccount, message, true)); message = new TLRPC.TL_message(); - message.message = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!"; + message.message = LocaleController.getString("ThemePreviewLine3", R.string.ThemePreviewLine3); message.date = date + 60; message.dialog_id = 1; message.flags = 257 + 8; @@ -790,7 +919,7 @@ public MessagesAdapter(Context context) { message.to_id = new TLRPC.TL_peerUser(); message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); messageObject = new MessageObject(currentAccount, message, true); - messageObject.customReplyName = "Lucio"; + messageObject.customReplyName = LocaleController.getString("ThemePreviewLine3Reply", R.string.ThemePreviewLine3Reply); messageObject.replyMessageObject = replyMessageObject; messages.add(messageObject); @@ -845,7 +974,7 @@ public MessagesAdapter(Context context) { photoSize.type = "s"; photoSize.location = new TLRPC.TL_fileLocationUnavailable(); message.media.photo.sizes.add(photoSize); - message.message = "Bring it on! I LIVE for this!"; + message.message = LocaleController.getString("ThemePreviewLine4", R.string.ThemePreviewLine4); message.out = false; message.to_id = new TLRPC.TL_peerUser(); message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); @@ -936,4 +1065,42 @@ public int getItemViewType(int i) { return 4; } } + + + private List getThemeDescriptionsInternal() { + List items = new ArrayList<>(); + items.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); + items.add(new ThemeDescription(viewPager, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + + items.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); + items.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); + items.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); + items.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch)); + items.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); + + items.add(new ThemeDescription(actionBar2, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); + items.add(new ThemeDescription(actionBar2, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); + items.add(new ThemeDescription(actionBar2, ThemeDescription.FLAG_AB_SUBTITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubtitle)); + items.add(new ThemeDescription(actionBar2, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); + + items.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + items.add(new ThemeDescription(listView2, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + + items.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionIcon)); + items.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chats_actionBackground)); + items.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chats_actionPressedBackground)); + + if (!useDefaultThemeForButtons) { + items.add(new ThemeDescription(buttonsContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); + items.add(new ThemeDescription(cancelButton, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + items.add(new ThemeDescription(doneButton, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + } + + if (colorPicker != null) { + colorPicker.provideThemeDescriptions(items); + } + + return items; + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeSetUrlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeSetUrlActivity.java new file mode 100644 index 00000000000..532ae1e89c5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeSetUrlActivity.java @@ -0,0 +1,705 @@ +/* + * This is the source code of Telegram for Android v. 5.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2018. + */ + +package org.telegram.ui; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.Selection; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +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.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; +import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Cells.ThemePreviewMessagesCell; +import org.telegram.ui.Cells.ThemesHorizontalListCell; +import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.ArrayList; + +public class ThemeSetUrlActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + + private EditTextBoldCursor linkField; + private EditTextBoldCursor nameField; + private View doneButton; + private TextInfoPrivacyCell helpInfoCell; + private TextInfoPrivacyCell checkInfoCell; + private ThemePreviewMessagesCell messagesCell; + private TextSettingsCell createCell; + private TextInfoPrivacyCell createInfoCell; + + private AlertDialog progressDialog; + + private View divider; + private HeaderCell headerCell; + private EditText editText; + private LinearLayout linearLayoutTypeContainer; + + private int checkReqId; + private String lastCheckName; + private Runnable checkRunnable; + private boolean lastNameAvailable; + private boolean ignoreCheck; + private CharSequence infoText; + private boolean creatingNewTheme; + + private Theme.ThemeInfo themeInfo; + + private final static int done_button = 1; + + public class LinkSpan extends ClickableSpan { + + private String url; + + public LinkSpan(String value) { + url = value; + } + + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + } + + @Override + public void onClick(View widget) { + try { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("label", url); + clipboard.setPrimaryClip(clip); + Toast.makeText(getParentActivity(), LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + FileLog.e(e); + } + } + } + + private static class LinkMovementMethodMy extends LinkMovementMethod { + @Override + public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { + try { + boolean result = super.onTouchEvent(widget, buffer, event); + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + Selection.removeSelection(buffer); + } + return result; + } catch (Exception e) { + FileLog.e(e); + } + return false; + } + } + + public ThemeSetUrlActivity(Theme.ThemeInfo theme, boolean newTheme) { + super(); + themeInfo = theme; + creatingNewTheme = newTheme; + } + + @Override + public boolean onFragmentCreate() { + getNotificationCenter().addObserver(this, NotificationCenter.themeUploadedToServer); + getNotificationCenter().addObserver(this, NotificationCenter.themeUploadError); + return super.onFragmentCreate(); + + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + getNotificationCenter().removeObserver(this, NotificationCenter.themeUploadedToServer); + getNotificationCenter().removeObserver(this, NotificationCenter.themeUploadError); + } + + @Override + public View createView(Context context) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + if (creatingNewTheme) { + actionBar.setTitle(LocaleController.getString("NewThemeTitle", R.string.NewThemeTitle)); + } else { + actionBar.setTitle(LocaleController.getString("EditThemeTitle", R.string.EditThemeTitle)); + } + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } else if (id == done_button) { + saveTheme(); + } + } + }); + + ActionBarMenu menu = actionBar.createMenu(); + doneButton = menu.addItem(done_button, LocaleController.getString("Done", R.string.Done).toUpperCase()); + + fragmentView = new LinearLayout(context); + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + LinearLayout linearLayout = (LinearLayout) fragmentView; + linearLayout.setOrientation(LinearLayout.VERTICAL); + fragmentView.setOnTouchListener((v, event) -> true); + + linearLayoutTypeContainer = new LinearLayout(context); + linearLayoutTypeContainer.setOrientation(LinearLayout.VERTICAL); + linearLayoutTypeContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + linearLayout.addView(linearLayoutTypeContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + headerCell = new HeaderCell(context, 23); + headerCell.setText(LocaleController.getString("Info", R.string.Info)); + linearLayoutTypeContainer.addView(headerCell); + + nameField = new EditTextBoldCursor(context); + nameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + nameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); + nameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameField.setMaxLines(1); + nameField.setLines(1); + nameField.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + nameField.setBackgroundDrawable(null); + nameField.setPadding(0, 0, 0, 0); + nameField.setSingleLine(true); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(128); + nameField.setFilters(inputFilters); + nameField.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + nameField.setImeOptions(EditorInfo.IME_ACTION_DONE); + nameField.setHint(LocaleController.getString("ThemeNamePlaceholder", R.string.ThemeNamePlaceholder)); + nameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameField.setCursorSize(AndroidUtilities.dp(20)); + nameField.setCursorWidth(1.5f); + linearLayoutTypeContainer.addView(nameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50, 23, 0, 23, 0)); + nameField.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_DONE) { + AndroidUtilities.hideKeyboard(nameField); + return true; + } + return false; + }); + + divider = new View(context) { + @Override + protected void onDraw(Canvas canvas) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + }; + linearLayoutTypeContainer.addView(divider, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1)); + + LinearLayout linkContainer = new LinearLayout(context); + linkContainer.setOrientation(LinearLayout.HORIZONTAL); + linearLayoutTypeContainer.addView(linkContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50, 23, 0, 23, 0)); + + editText = new EditText(context); + editText.setText(getMessagesController().linkPrefix + "/addtheme/"); + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + editText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); + editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + editText.setMaxLines(1); + editText.setLines(1); + editText.setEnabled(false); + editText.setBackgroundDrawable(null); + editText.setPadding(0, 0, 0, 0); + editText.setSingleLine(true); + editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + linkContainer.addView(editText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 50)); + + linkField = new EditTextBoldCursor(context); + linkField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + linkField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); + linkField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + linkField.setMaxLines(1); + linkField.setLines(1); + linkField.setBackgroundDrawable(null); + linkField.setPadding(0, 0, 0, 0); + linkField.setSingleLine(true); + linkField.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + linkField.setImeOptions(EditorInfo.IME_ACTION_DONE); + linkField.setHint(LocaleController.getString("SetUrlPlaceholder", R.string.SetUrlPlaceholder)); + linkField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + linkField.setCursorSize(AndroidUtilities.dp(20)); + linkField.setCursorWidth(1.5f); + linkContainer.addView(linkField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); + linkField.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == EditorInfo.IME_ACTION_DONE && doneButton != null) { + doneButton.performClick(); + return true; + } + return false; + }); + linkField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + if (ignoreCheck) { + return; + } + checkUrl(linkField.getText().toString(), false); + } + + @Override + public void afterTextChanged(Editable editable) { + if (creatingNewTheme) { + return; + } + if (linkField.length() > 0) { + String url = "https://" + MessagesController.getInstance(themeInfo.account).linkPrefix + "/addtheme/" + linkField.getText(); + String text = LocaleController.formatString("ThemeHelpLink", R.string.ThemeHelpLink, url); + int index = text.indexOf(url); + SpannableStringBuilder textSpan = new SpannableStringBuilder(text); + if (index >= 0) { + textSpan.setSpan(new LinkSpan(url), index, index + url.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + helpInfoCell.setText(TextUtils.concat(infoText, "\n\n", textSpan)); + } else { + helpInfoCell.setText(infoText); + } + } + }); + if (creatingNewTheme) { + linkField.setOnFocusChangeListener((v, hasFocus) -> { + if (hasFocus) { + helpInfoCell.setText(AndroidUtilities.replaceTags(LocaleController.getString("ThemeCreateHelp2", R.string.ThemeCreateHelp2))); + } else { + helpInfoCell.setText(AndroidUtilities.replaceTags(LocaleController.getString("ThemeCreateHelp", R.string.ThemeCreateHelp))); + } + }); + } + + checkInfoCell = new TextInfoPrivacyCell(context); + checkInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + checkInfoCell.setVisibility(View.GONE); + checkInfoCell.setBottomPadding(0); + linearLayout.addView(checkInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + helpInfoCell = new TextInfoPrivacyCell(context); + helpInfoCell.getTextView().setMovementMethod(new LinkMovementMethodMy()); + helpInfoCell.getTextView().setHighlightColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection)); + if (creatingNewTheme) { + helpInfoCell.setText(AndroidUtilities.replaceTags(LocaleController.getString("ThemeCreateHelp", R.string.ThemeCreateHelp))); + } else { + helpInfoCell.setText(infoText = AndroidUtilities.replaceTags(LocaleController.getString("ThemeSetUrlHelp", R.string.ThemeSetUrlHelp))); + } + linearLayout.addView(helpInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + if (creatingNewTheme) { + helpInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + messagesCell = new ThemePreviewMessagesCell(context, parentLayout, 1); + linearLayout.addView(messagesCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + createCell = new TextSettingsCell(context); + createCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); + createCell.setText(LocaleController.getString("UseDifferentTheme", R.string.UseDifferentTheme), false); + linearLayout.addView(createCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + createCell.setOnClickListener(v -> { + if (getParentActivity() == null) { + return; + } + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, 1); + builder.setApplyBottomPadding(false); + + LinearLayout container = new LinearLayout(context); + container.setOrientation(LinearLayout.VERTICAL); + + TextView titleView = new TextView(context); + titleView.setText(LocaleController.getString("ChooseTheme", R.string.ChooseTheme)); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + container.addView(titleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 12, 22, 4)); + titleView.setOnTouchListener((v2, event) -> true); + builder.setCustomView(container); + + ArrayList themes = new ArrayList<>(); + for (int a = 0, N = Theme.themes.size(); a < N; a++) { + Theme.ThemeInfo themeInfo = Theme.themes.get(a); + if (themeInfo.info != null && themeInfo.info.document == null) { + continue; + } + themes.add(themeInfo); + } + ThemesHorizontalListCell cell = new ThemesHorizontalListCell(context, ThemeActivity.THEME_TYPE_OTHER, themes, new ArrayList<>()) { + @Override + protected void updateRows() { + builder.getDismissRunnable().run(); + } + }; + container.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 148, 0, 7, 0, 1)); + cell.scrollToCurrentTheme(fragmentView.getMeasuredWidth(), false); + showDialog(builder.create()); + }); + + createInfoCell = new TextInfoPrivacyCell(context); + createInfoCell.setText(AndroidUtilities.replaceTags(LocaleController.getString("UseDifferentThemeInfo", R.string.UseDifferentThemeInfo))); + createInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + linearLayout.addView(createInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } else { + helpInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } + + if (themeInfo != null) { + ignoreCheck = true; + nameField.setText(themeInfo.name); + nameField.setSelection(nameField.length()); + linkField.setText(themeInfo.info.slug); + linkField.setSelection(linkField.length()); + ignoreCheck = false; + } + + return fragmentView; + } + + @Override + public void onResume() { + super.onResume(); + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean animations = preferences.getBoolean("view_animations", true); + if (!animations && creatingNewTheme) { + linkField.requestFocus(); + AndroidUtilities.showKeyboard(linkField); + } + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.themeUploadedToServer) { + Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; + if (theme == themeInfo && progressDialog != null) { + try { + progressDialog.dismiss(); + progressDialog = null; + } catch (Exception e) { + FileLog.e(e); + } + Theme.applyTheme(themeInfo, false); + finishFragment(); + } + } else if (id == NotificationCenter.themeUploadError) { + Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; + if (theme == themeInfo && progressDialog != null) { + try { + progressDialog.dismiss(); + progressDialog = null; + } catch (Exception e) { + FileLog.e(e); + } + } + } + } + + private boolean checkUrl(final String url, boolean alert) { + if (checkRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(checkRunnable); + checkRunnable = null; + lastCheckName = null; + if (checkReqId != 0) { + ConnectionsManager.getInstance(themeInfo.account).cancelRequest(checkReqId, true); + } + } + lastNameAvailable = false; + if (url != null) { + if (url.startsWith("_") || url.endsWith("_")) { + setCheckText(LocaleController.getString("SetUrlInvalid", R.string.SetUrlInvalid), Theme.key_windowBackgroundWhiteRedText4); + return false; + } + for (int a = 0; a < url.length(); a++) { + char ch = url.charAt(a); + if (a == 0 && ch >= '0' && ch <= '9') { + if (alert) { + AlertsCreator.showSimpleAlert(this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("SetUrlInvalidStartNumber", R.string.SetUrlInvalidStartNumber)); + } else { + setCheckText(LocaleController.getString("SetUrlInvalidStartNumber", R.string.SetUrlInvalidStartNumber), Theme.key_windowBackgroundWhiteRedText4); + } + return false; + } + if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_')) { + if (alert) { + AlertsCreator.showSimpleAlert(this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("SetUrlInvalid", R.string.SetUrlInvalid)); + } else { + setCheckText(LocaleController.getString("SetUrlInvalid", R.string.SetUrlInvalid), Theme.key_windowBackgroundWhiteRedText4); + } + return false; + } + } + } + if (url == null || url.length() < 5) { + if (alert) { + AlertsCreator.showSimpleAlert(this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("SetUrlInvalidShort", R.string.SetUrlInvalidShort)); + } else { + setCheckText(LocaleController.getString("SetUrlInvalidShort", R.string.SetUrlInvalidShort), Theme.key_windowBackgroundWhiteRedText4); + } + return false; + } + if (url.length() > 64) { + if (alert) { + AlertsCreator.showSimpleAlert(this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("SetUrlInvalidLong", R.string.SetUrlInvalidLong)); + } else { + setCheckText(LocaleController.getString("SetUrlInvalidLong", R.string.SetUrlInvalidLong), Theme.key_windowBackgroundWhiteRedText4); + } + return false; + } + + if (!alert) { + String currentUrl = themeInfo != null && themeInfo.info.slug != null ? themeInfo.info.slug : ""; + if (url.equals(currentUrl)) { + setCheckText(LocaleController.formatString("SetUrlAvailable", R.string.SetUrlAvailable, url), Theme.key_windowBackgroundWhiteGreenText); + return true; + } + + setCheckText(LocaleController.getString("SetUrlChecking", R.string.SetUrlChecking), Theme.key_windowBackgroundWhiteGrayText8); + lastCheckName = url; + checkRunnable = () -> { + TLRPC.TL_account_createTheme req = new TLRPC.TL_account_createTheme(); + req.slug = url; + req.title = ""; + req.document = new TLRPC.TL_inputDocumentEmpty(); + checkReqId = ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + checkReqId = 0; + if (lastCheckName != null && lastCheckName.equals(url)) { + if (error == null || !"THEME_SLUG_INVALID".equals(error.text) && !"THEME_SLUG_OCCUPIED".equals(error.text)) { + setCheckText(LocaleController.formatString("SetUrlAvailable", R.string.SetUrlAvailable, url), Theme.key_windowBackgroundWhiteGreenText); + lastNameAvailable = true; + } else { + setCheckText(LocaleController.getString("SetUrlInUse", R.string.SetUrlInUse), Theme.key_windowBackgroundWhiteRedText4); + lastNameAvailable = false; + } + } + }), ConnectionsManager.RequestFlagFailOnServerErrors); + }; + AndroidUtilities.runOnUIThread(checkRunnable, 300); + } + return true; + } + + private void setCheckText(String text, String colorKey) { + if (TextUtils.isEmpty(text)) { + checkInfoCell.setVisibility(View.GONE); + if (creatingNewTheme) { + helpInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(getParentActivity(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + } else { + helpInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(getParentActivity(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } + } else { + checkInfoCell.setVisibility(View.VISIBLE); + checkInfoCell.setText(text); + checkInfoCell.setTag(colorKey); + checkInfoCell.setTextColor(colorKey); + if (creatingNewTheme) { + helpInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(getParentActivity(), R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); + } else { + helpInfoCell.setBackgroundDrawable(null); + } + } + } + + private void saveTheme() { + if (!checkUrl(linkField.getText().toString(), true)) { + return; + } + if (getParentActivity() == null) { + return; + } + if (nameField.length() == 0) { + AlertsCreator.showSimpleAlert(this, LocaleController.getString("Theme", R.string.Theme), LocaleController.getString("ThemeNameInvalid", R.string.ThemeNameInvalid)); + return; + } + if (creatingNewTheme) { + String oldName = themeInfo.name; + String oldSlug = themeInfo.info.slug; + progressDialog = new AlertDialog(getParentActivity(), 3); + progressDialog.setOnCancelListener(dialog -> { + + }); + progressDialog.show(); + themeInfo.name = themeInfo.info.title = nameField.getText().toString(); + themeInfo.info.slug = linkField.getText().toString(); + Theme.saveCurrentTheme(themeInfo, true, true, true); + return; + } + String currentUrl = themeInfo.info.slug == null ? "" : themeInfo.info.slug; + String currentName = themeInfo.name == null ? "" : themeInfo.name; + String newUrl = linkField.getText().toString(); + String newName = nameField.getText().toString(); + if (currentUrl.equals(newUrl) && currentName.equals(newName)) { + finishFragment(); + return; + } + + progressDialog = new AlertDialog(getParentActivity(), 3); + + final TLRPC.TL_account_updateTheme req = new TLRPC.TL_account_updateTheme(); + TLRPC.TL_inputTheme inputTheme = new TLRPC.TL_inputTheme(); + inputTheme.id = themeInfo.info.id; + inputTheme.access_hash = themeInfo.info.access_hash; + req.theme = inputTheme; + req.format = "android"; + req.slug = newUrl; + req.flags |= 1; + + req.title = newName; + req.flags |= 2; + + final int reqId = ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> { + if (response instanceof TLRPC.TL_theme) { + TLRPC.TL_theme theme = (TLRPC.TL_theme) response; + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.dismiss(); + progressDialog = null; + } catch (Exception e) { + FileLog.e(e); + } + Theme.setThemeUploadInfo(themeInfo, theme, false); + finishFragment(); + }); + } else { + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.dismiss(); + progressDialog = null; + } catch (Exception e) { + FileLog.e(e); + } + AlertsCreator.processError(themeInfo.account, error, ThemeSetUrlActivity.this, req); + }); + } + }, ConnectionsManager.RequestFlagFailOnServerErrors); + ConnectionsManager.getInstance(themeInfo.account).bindRequestToGuid(reqId, classGuid); + + progressDialog.setOnCancelListener(dialog -> ConnectionsManager.getInstance(themeInfo.account).cancelRequest(reqId, true)); + progressDialog.show(); + } + + @Override + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen && !creatingNewTheme) { + linkField.requestFocus(); + AndroidUtilities.showKeyboard(linkField); + } + } + + @Override + public ThemeDescription[] getThemeDescriptions() { + return new ThemeDescription[]{ + new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), + + new ThemeDescription(linearLayoutTypeContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite), + + new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), + + new ThemeDescription(headerCell, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader), + + new ThemeDescription(createInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + new ThemeDescription(createInfoCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), + + new ThemeDescription(helpInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + new ThemeDescription(helpInfoCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4), + + new ThemeDescription(checkInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow), + new ThemeDescription(checkInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText4), + new ThemeDescription(checkInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText8), + new ThemeDescription(checkInfoCell, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGreenText), + + new ThemeDescription(createCell, 0, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(createCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_listSelector), + new ThemeDescription(createCell, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_windowBackgroundWhite), + + new ThemeDescription(linkField, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(linkField, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText), + new ThemeDescription(linkField, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField), + new ThemeDescription(linkField, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated), + + new ThemeDescription(linkField, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(linkField, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText), + new ThemeDescription(linkField, ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(nameField, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(nameField, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText), + new ThemeDescription(nameField, ThemeDescription.FLAG_CURSORCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(editText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(editText, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText), + + new ThemeDescription(divider, 0, null, Theme.dividerPaint, null, null, Theme.key_divider), + new ThemeDescription(divider, ThemeDescription.FLAG_BACKGROUND, null, Theme.dividerPaint, null, null, Theme.key_divider), + + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgInDrawable, Theme.chat_msgInMediaDrawable}, null, Theme.key_chat_inBubble), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgInSelectedDrawable, Theme.chat_msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgInShadowDrawable, Theme.chat_msgInMediaShadowDrawable}, null, Theme.key_chat_inBubbleShadow), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutDrawable, Theme.chat_msgOutMediaDrawable}, null, Theme.key_chat_outBubble), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutSelectedDrawable, Theme.chat_msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleSelected), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_messageTextIn), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_messageTextOut), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected), + new ThemeDescription(messagesCell, 0, null, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inReplyLine), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outReplyLine), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inReplyNameText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outReplyNameText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inReplyMessageText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outReplyMessageText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inReplyMediaMessageSelectedText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outReplyMediaMessageSelectedText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inTimeText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outTimeText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_inTimeSelectedText), + new ThemeDescription(messagesCell, 0, null, null, null, null, Theme.key_chat_outTimeSelectedText), + }; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java index 7884035a1b6..6e52fd3f902 100755 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java @@ -39,7 +39,6 @@ import android.os.Build; import android.os.Bundle; import androidx.annotation.IntRange; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.palette.graphics.Palette; import android.text.Editable; @@ -105,7 +104,7 @@ import java.io.ByteArrayOutputStream; -public class VoIPActivity extends Activity implements VoIPService.StateListener, NotificationCenter.NotificationCenterDelegate{ +public class VoIPActivity extends Activity implements VoIPService.StateListener, NotificationCenter.NotificationCenterDelegate { private int currentAccount = -1; private static final String TAG = "tg-voip-ui"; @@ -128,16 +127,16 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, private TextAlphaSpan[] ellSpans; private AnimatorSet ellAnimator; private String lastStateText; - private ImageView[] keyEmojiViews=new ImageView[4]; + private ImageView[] keyEmojiViews = new ImageView[4]; private boolean keyEmojiVisible; - private AnimatorSet emojiAnimator; + private AnimatorSet emojiAnimator; private TextView hintTextView; private Animator tooltipAnim; private Runnable tooltipHider; - private LinearLayout emojiWrap; + private LinearLayout emojiWrap; boolean emojiTooltipVisible; boolean emojiExpanded; - private Bitmap blurredPhoto1, blurredPhoto2; + private Bitmap blurredPhoto1, blurredPhoto2; private ImageView blurOverlayView1, blurOverlayView2; private TextView emojiExpandedText; private FrameLayout content; @@ -159,8 +158,8 @@ protected void onCreate(Bundle savedInstanceState) { return; } - currentAccount=VoIPService.getSharedInstance().getAccount(); - if(currentAccount==-1){ + currentAccount = VoIPService.getSharedInstance().getAccount(); + if (currentAccount == -1) { finish(); return; } @@ -177,10 +176,10 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setStatusBarColor(0); getWindow().setNavigationBarColor(0); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){ - getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + } user = VoIPService.getSharedInstance().getUser(); if (user.photo != null) { @@ -204,13 +203,14 @@ public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb) setVolumeControlStream(AudioManager.STREAM_VOICE_CALL); nameText.setOnClickListener(new View.OnClickListener() { - private int tapCount=0; + private int tapCount = 0; + @Override public void onClick(View v) { - if(BuildVars.DEBUG_VERSION || tapCount==9){ + if (BuildVars.DEBUG_VERSION || tapCount == 9) { showDebugAlert(); - tapCount=0; - }else{ + tapCount = 0; + } else { tapCount++; } } @@ -227,7 +227,7 @@ public boolean onLongClick(View v) { @Override public void onClick(View v) { endBtn.setEnabled(false); - if(retrying){ + if (retrying) { Intent intent = new Intent(VoIPActivity.this, VoIPService.class); intent.putExtra("user_id", user.id); intent.putExtra("is_outgoing", true); @@ -239,15 +239,15 @@ public void onClick(View v) { FileLog.e(e); } hideRetry(); - endBtn.postDelayed(new Runnable(){ + endBtn.postDelayed(new Runnable() { @Override - public void run(){ - if(VoIPService.getSharedInstance()==null && !isFinishing()){ + public void run() { + if (VoIPService.getSharedInstance() == null && !isFinishing()) { endBtn.postDelayed(this, 100); return; } - if(VoIPService.getSharedInstance()!=null) - VoIPService.getSharedInstance().registerStateListener(VoIPActivity.this); + if (VoIPService.getSharedInstance() != null) + VoIPService.getSharedInstance().registerStateListener(VoIPActivity.this); } }, 100); return; @@ -257,42 +257,33 @@ public void run(){ } }); - spkToggle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - VoIPService svc=VoIPService.getSharedInstance(); - if (svc == null) - return; - svc.toggleSpeakerphoneOrShowRouteSheet(VoIPActivity.this); - } + spkToggle.setOnClickListener(v -> { + VoIPService svc = VoIPService.getSharedInstance(); + if (svc == null) + return; + svc.toggleSpeakerphoneOrShowRouteSheet(VoIPActivity.this); }); - micToggle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (VoIPService.getSharedInstance() == null) { - finish(); - return; - } - boolean checked = !micToggle.isChecked(); - micToggle.setChecked(checked); - VoIPService.getSharedInstance().setMicMute(checked); + micToggle.setOnClickListener(v -> { + if (VoIPService.getSharedInstance() == null) { + finish(); + return; } + boolean checked = !micToggle.isChecked(); + micToggle.setChecked(checked); + VoIPService.getSharedInstance().setMicMute(checked); }); - chatBtn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if(isIncomingWaiting){ - showMessagesSheet(); - return; - } - Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); - intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); - intent.putExtra("currentAccount", currentAccount); - intent.setFlags(32768); - intent.putExtra("userId", user.id); - startActivity(intent); - finish(); + chatBtn.setOnClickListener(v -> { + if (isIncomingWaiting) { + showMessagesSheet(); + return; } + Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); + intent.setAction("com.tmessages.openchat" + Math.random() + Integer.MAX_VALUE); + intent.putExtra("currentAccount", currentAccount); + intent.setFlags(32768); + intent.putExtra("userId", user.id); + startActivity(intent); + finish(); }); /*addMemberBtn.setOnClickListener(new View.OnClickListener(){ @Override @@ -315,8 +306,8 @@ public void onClick(View v){ public void onDragComplete() { acceptSwipe.setEnabled(false); declineSwipe.setEnabled(false); - if(VoIPService.getSharedInstance()==null){ - finish(); + if (VoIPService.getSharedInstance() == null) { + finish(); return; } didAcceptFromHere = true; @@ -379,8 +370,8 @@ public void onAnimationEnd(Animator animation) { public void onDragComplete() { acceptSwipe.setEnabled(false); declineSwipe.setEnabled(false); - if(VoIPService.getSharedInstance()!=null) - VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, null); + if (VoIPService.getSharedInstance() != null) + VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, null); else finish(); } @@ -431,9 +422,9 @@ public void onAnimationEnd(Animator animation) { acceptSwipe.startAnimatingArrows(); } }); - cancelBtn.setOnClickListener(new View.OnClickListener(){ + cancelBtn.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v){ + public void onClick(View v) { finish(); } }); @@ -444,83 +435,83 @@ public void onClick(View v){ hintTextView.setText(LocaleController.formatString("CallEmojiKeyTooltip", R.string.CallEmojiKeyTooltip, user.first_name)); emojiExpandedText.setText(LocaleController.formatString("CallEmojiKeyTooltip", R.string.CallEmojiKeyTooltip, user.first_name)); - AccessibilityManager am=(AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE); - if(am.isTouchExplorationEnabled()){ - nameText.postDelayed(new Runnable(){ + AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE); + if (am.isTouchExplorationEnabled()) { + nameText.postDelayed(new Runnable() { @Override - public void run(){ + public void run() { nameText.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } }, 500); } } - private View createContentView(){ - FrameLayout content=new FrameLayout(this){ - private void setNegativeMargins(Rect insets, LayoutParams lp){ - lp.topMargin=-insets.top; - lp.bottomMargin=-insets.bottom; - lp.leftMargin=-insets.left; - lp.rightMargin=-insets.right; + private View createContentView() { + FrameLayout content = new FrameLayout(this) { + private void setNegativeMargins(Rect insets, LayoutParams lp) { + lp.topMargin = -insets.top; + lp.bottomMargin = -insets.bottom; + lp.leftMargin = -insets.left; + lp.rightMargin = -insets.right; } - @Override - protected boolean fitSystemWindows(Rect insets){ - setNegativeMargins(insets, (LayoutParams) photoView.getLayoutParams()); + @Override + protected boolean fitSystemWindows(Rect insets) { + setNegativeMargins(insets, (LayoutParams) photoView.getLayoutParams()); setNegativeMargins(insets, (LayoutParams) blurOverlayView1.getLayoutParams()); setNegativeMargins(insets, (LayoutParams) blurOverlayView2.getLayoutParams()); - return super.fitSystemWindows(insets); - } - }; + return super.fitSystemWindows(insets); + } + }; content.setBackgroundColor(0); content.setFitsSystemWindows(true); content.setClipToPadding(false); - BackupImageView photo=new BackupImageView(this){ - private Drawable topGradient=getResources().getDrawable(R.drawable.gradient_top); - private Drawable bottomGradient=getResources().getDrawable(R.drawable.gradient_bottom); - private Paint paint=new Paint(); + BackupImageView photo = new BackupImageView(this) { + private Drawable topGradient = getResources().getDrawable(R.drawable.gradient_top); + private Drawable bottomGradient = getResources().getDrawable(R.drawable.gradient_bottom); + private Paint paint = new Paint(); @Override - protected void onDraw(Canvas canvas){ + protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(0x4C000000); canvas.drawRect(0, 0, getWidth(), getHeight(), paint); topGradient.setBounds(0, 0, getWidth(), AndroidUtilities.dp(170)); topGradient.setAlpha(128); topGradient.draw(canvas); - bottomGradient.setBounds(0, getHeight()-AndroidUtilities.dp(220), getWidth(), getHeight()); + bottomGradient.setBounds(0, getHeight() - AndroidUtilities.dp(220), getWidth(), getHeight()); bottomGradient.setAlpha(178); bottomGradient.draw(canvas); } }; - content.addView(photoView=photo); - blurOverlayView1=new ImageView(this); + content.addView(photoView = photo); + blurOverlayView1 = new ImageView(this); blurOverlayView1.setScaleType(ImageView.ScaleType.CENTER_CROP); - blurOverlayView1.setAlpha(0f); + blurOverlayView1.setAlpha(0f); content.addView(blurOverlayView1); - blurOverlayView2=new ImageView(this); + blurOverlayView2 = new ImageView(this); blurOverlayView2.setScaleType(ImageView.ScaleType.CENTER_CROP); blurOverlayView2.setAlpha(0f); content.addView(blurOverlayView2); - TextView branding=new TextView(this); + TextView branding = new TextView(this); branding.setTextColor(0xCCFFFFFF); branding.setText(LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)); - Drawable logo=getResources().getDrawable(R.drawable.notification).mutate(); + Drawable logo = getResources().getDrawable(R.drawable.notification).mutate(); logo.setAlpha(0xCC); logo.setBounds(0, 0, AndroidUtilities.dp(15), AndroidUtilities.dp(15)); - signalBarsDrawable=new SignalBarsDrawable(); + signalBarsDrawable = new SignalBarsDrawable(); signalBarsDrawable.setBounds(0, 0, signalBarsDrawable.getIntrinsicWidth(), signalBarsDrawable.getIntrinsicHeight()); branding.setCompoundDrawables(LocaleController.isRTL ? signalBarsDrawable : logo, null, LocaleController.isRTL ? logo : signalBarsDrawable, null); branding.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); branding.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); branding.setCompoundDrawablePadding(AndroidUtilities.dp(5)); branding.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - content.addView(branding, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 18, 18, 18, 0)); - brandingText=branding; + content.addView(branding, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 18, 18, 18, 0)); + brandingText = branding; - TextView name=new TextView(this); + TextView name = new TextView(this); name.setSingleLine(); name.setTextColor(0xFFFFFFFF); name.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 40); @@ -528,9 +519,9 @@ protected void onDraw(Canvas canvas){ name.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); name.setShadowLayer(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(.666666667f), 0x4C000000); name.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL)); - content.addView(nameText=name, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|Gravity.LEFT, 16, 43, 18, 0)); + content.addView(nameText = name, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 16, 43, 18, 0)); - TextView state=new TextView(this); + TextView state = new TextView(this); state.setTextColor(0xCCFFFFFF); state.setSingleLine(); state.setEllipsize(TextUtils.TruncateAt.END); @@ -539,10 +530,10 @@ protected void onDraw(Canvas canvas){ state.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); state.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); //state.setAllCaps(true); - content.addView(stateText=state, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|Gravity.LEFT, 18, 98, 18, 0)); - durationText=state; + content.addView(stateText = state, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 18, 98, 18, 0)); + durationText = state; - state=new TextView(this); + state = new TextView(this); state.setTextColor(0xCCFFFFFF); state.setSingleLine(); state.setEllipsize(TextUtils.TruncateAt.END); @@ -552,44 +543,44 @@ protected void onDraw(Canvas canvas){ state.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); //state.setAllCaps(true); state.setVisibility(View.GONE); - content.addView(stateText2=state, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|Gravity.LEFT, 18, 98, 18, 0)); + content.addView(stateText2 = state, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 18, 98, 18, 0)); - ellSpans=new TextAlphaSpan[]{new TextAlphaSpan(), new TextAlphaSpan(), new TextAlphaSpan()}; + ellSpans = new TextAlphaSpan[]{new TextAlphaSpan(), new TextAlphaSpan(), new TextAlphaSpan()}; - LinearLayout buttons=new LinearLayout(this); + LinearLayout buttons = new LinearLayout(this); buttons.setOrientation(LinearLayout.HORIZONTAL); content.addView(buttons, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); FrameLayout wrap; - TextView accountName=new TextView(this); + TextView accountName = new TextView(this); accountName.setTextColor(0xCCFFFFFF); accountName.setSingleLine(); accountName.setEllipsize(TextUtils.TruncateAt.END); accountName.setShadowLayer(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(.6666667f), 0x4c000000); accountName.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); accountName.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - content.addView(accountNameText=accountName, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|Gravity.LEFT, 18, 120, 18, 0)); + content.addView(accountNameText = accountName, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 18, 120, 18, 0)); - CheckableImageView mic=new CheckableImageView(this); + CheckableImageView mic = new CheckableImageView(this); mic.setBackgroundResource(R.drawable.bg_voip_icon_btn); - Drawable micIcon=getResources().getDrawable(R.drawable.ic_mic_off_white_24dp).mutate(); + Drawable micIcon = getResources().getDrawable(R.drawable.ic_mic_off_white_24dp).mutate(); mic.setAlpha(204); mic.setImageDrawable(micIcon); mic.setScaleType(ImageView.ScaleType.CENTER); mic.setContentDescription(LocaleController.getString("AccDescrMuteMic", R.string.AccDescrMuteMic)); - wrap=new FrameLayout(this); - wrap.addView(micToggle=mic, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); + wrap = new FrameLayout(this); + wrap.addView(micToggle = mic, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); - ImageView chat=new ImageView(this); - Drawable chatIcon=getResources().getDrawable(R.drawable.ic_chat_bubble_white_24dp).mutate(); + ImageView chat = new ImageView(this); + Drawable chatIcon = getResources().getDrawable(R.drawable.ic_chat_bubble_white_24dp).mutate(); chatIcon.setAlpha(204); chat.setImageDrawable(chatIcon); chat.setScaleType(ImageView.ScaleType.CENTER); chat.setContentDescription(LocaleController.getString("AccDescrOpenChat", R.string.AccDescrOpenChat)); - wrap=new FrameLayout(this); - wrap.addView(chatBtn=chat, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); + wrap = new FrameLayout(this); + wrap.addView(chatBtn = chat, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); /*ImageView addMember=new ImageView(this); @@ -604,70 +595,70 @@ protected void onDraw(Canvas canvas){ wrap.addView(addMemberBtn=addMember, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f));*/ - CheckableImageView speaker=new CheckableImageView(this); + CheckableImageView speaker = new CheckableImageView(this); speaker.setBackgroundResource(R.drawable.bg_voip_icon_btn); - Drawable speakerIcon=getResources().getDrawable(R.drawable.ic_volume_up_white_24dp).mutate(); + Drawable speakerIcon = getResources().getDrawable(R.drawable.ic_volume_up_white_24dp).mutate(); speaker.setAlpha(204); speaker.setImageDrawable(speakerIcon); speaker.setScaleType(ImageView.ScaleType.CENTER); speaker.setContentDescription(LocaleController.getString("VoipAudioRoutingSpeaker", R.string.VoipAudioRoutingSpeaker)); - wrap=new FrameLayout(this); - wrap.addView(spkToggle=speaker, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); + wrap = new FrameLayout(this); + wrap.addView(spkToggle = speaker, LayoutHelper.createFrame(38, 38, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 10)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); - bottomButtons=buttons; + bottomButtons = buttons; - LinearLayout swipesWrap=new LinearLayout(this); + LinearLayout swipesWrap = new LinearLayout(this); swipesWrap.setOrientation(LinearLayout.HORIZONTAL); - CallSwipeView acceptSwipe=new CallSwipeView(this); + CallSwipeView acceptSwipe = new CallSwipeView(this); acceptSwipe.setColor(0xFF45bc4d); acceptSwipe.setContentDescription(LocaleController.getString("Accept", R.string.Accept)); - swipesWrap.addView(this.acceptSwipe=acceptSwipe, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 70, 1f, 4, 4, -35, 4)); + swipesWrap.addView(this.acceptSwipe = acceptSwipe, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 70, 1f, 4, 4, -35, 4)); - CallSwipeView declineSwipe=new CallSwipeView(this); + CallSwipeView declineSwipe = new CallSwipeView(this); declineSwipe.setColor(0xFFe61e44); declineSwipe.setContentDescription(LocaleController.getString("Decline", R.string.Decline)); - swipesWrap.addView(this.declineSwipe=declineSwipe, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 70, 1f, -35, 4, 4, 4)); + swipesWrap.addView(this.declineSwipe = declineSwipe, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 70, 1f, -35, 4, 4, 4)); - content.addView(swipeViewsWrap=swipesWrap, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 20, 0, 20, 68)); + content.addView(swipeViewsWrap = swipesWrap, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 20, 0, 20, 68)); - ImageView acceptBtn=new ImageView(this); - FabBackgroundDrawable acceptBtnBg=new FabBackgroundDrawable(); + ImageView acceptBtn = new ImageView(this); + FabBackgroundDrawable acceptBtnBg = new FabBackgroundDrawable(); acceptBtnBg.setColor(0xFF45bc4d); acceptBtn.setBackgroundDrawable(acceptBtnBg); acceptBtn.setImageResource(R.drawable.ic_call_end_white_36dp); acceptBtn.setScaleType(ImageView.ScaleType.MATRIX); - Matrix matrix=new Matrix(); + Matrix matrix = new Matrix(); matrix.setTranslate(AndroidUtilities.dp(17), AndroidUtilities.dp(17)); matrix.postRotate(-135, AndroidUtilities.dp(35), AndroidUtilities.dp(35)); acceptBtn.setImageMatrix(matrix); - content.addView(this.acceptBtn=acceptBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM|Gravity.LEFT, 20, 0, 0, 68)); + content.addView(this.acceptBtn = acceptBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM | Gravity.LEFT, 20, 0, 0, 68)); - ImageView declineBtn=new ImageView(this); - FabBackgroundDrawable rejectBtnBg=new FabBackgroundDrawable(); + ImageView declineBtn = new ImageView(this); + FabBackgroundDrawable rejectBtnBg = new FabBackgroundDrawable(); rejectBtnBg.setColor(0xFFe61e44); declineBtn.setBackgroundDrawable(rejectBtnBg); declineBtn.setImageResource(R.drawable.ic_call_end_white_36dp); declineBtn.setScaleType(ImageView.ScaleType.CENTER); - content.addView(this.declineBtn=declineBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM|Gravity.RIGHT, 0, 0, 20, 68)); + content.addView(this.declineBtn = declineBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, 20, 68)); acceptSwipe.setViewToDrag(acceptBtn, false); declineSwipe.setViewToDrag(declineBtn, true); - FrameLayout end=new FrameLayout(this); - FabBackgroundDrawable endBtnBg=new FabBackgroundDrawable(); + FrameLayout end = new FrameLayout(this); + FabBackgroundDrawable endBtnBg = new FabBackgroundDrawable(); endBtnBg.setColor(0xFFe61e44); - end.setBackgroundDrawable(this.endBtnBg=endBtnBg); - ImageView endInner=new ImageView(this); + end.setBackgroundDrawable(this.endBtnBg = endBtnBg); + ImageView endInner = new ImageView(this); endInner.setImageResource(R.drawable.ic_call_end_white_36dp); endInner.setScaleType(ImageView.ScaleType.CENTER); - end.addView(endBtnIcon=endInner, LayoutHelper.createFrame(70, 70)); + end.addView(endBtnIcon = endInner, LayoutHelper.createFrame(70, 70)); end.setForeground(getResources().getDrawable(R.drawable.fab_highlight_dark)); end.setContentDescription(LocaleController.getString("VoipEndCall", R.string.VoipEndCall)); - content.addView(endBtn=end, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0, 0, 68)); + content.addView(endBtn = end, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 68)); - ImageView cancelBtn=new ImageView(this); - FabBackgroundDrawable cancelBtnBg=new FabBackgroundDrawable(); + ImageView cancelBtn = new ImageView(this); + FabBackgroundDrawable cancelBtnBg = new FabBackgroundDrawable(); cancelBtnBg.setColor(0xFFFFFFFF); cancelBtn.setBackgroundDrawable(cancelBtnBg); cancelBtn.setImageResource(R.drawable.edit_cancel); @@ -675,29 +666,29 @@ protected void onDraw(Canvas canvas){ cancelBtn.setScaleType(ImageView.ScaleType.CENTER); cancelBtn.setVisibility(View.GONE); cancelBtn.setContentDescription(LocaleController.getString("Cancel", R.string.Cancel)); - content.addView(this.cancelBtn=cancelBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM|Gravity.LEFT, 52, 0, 0, 68)); - + content.addView(this.cancelBtn = cancelBtn, LayoutHelper.createFrame(78, 78, Gravity.BOTTOM | Gravity.LEFT, 52, 0, 0, 68)); - emojiWrap=new LinearLayout(this); + + emojiWrap = new LinearLayout(this); emojiWrap.setOrientation(LinearLayout.HORIZONTAL); emojiWrap.setClipToPadding(false); emojiWrap.setPivotX(0); emojiWrap.setPivotY(0); - emojiWrap.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(10), AndroidUtilities.dp(14), AndroidUtilities.dp(10)); - for(int i=0;i<4;i++){ - ImageView emoji=new ImageView(this); + emojiWrap.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(10), AndroidUtilities.dp(14), AndroidUtilities.dp(10)); + for (int i = 0; i < 4; i++) { + ImageView emoji = new ImageView(this); emoji.setScaleType(ImageView.ScaleType.FIT_XY); - emojiWrap.addView(emoji, LayoutHelper.createLinear(22, 22, i==0 ? 0 : 4, 0, 0, 0)); - keyEmojiViews[i]=emoji; + emojiWrap.addView(emoji, LayoutHelper.createLinear(22, 22, i == 0 ? 0 : 4, 0, 0, 0)); + keyEmojiViews[i] = emoji; } - emojiWrap.setOnClickListener(new View.OnClickListener(){ + emojiWrap.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v){ - if(emojiTooltipVisible){ + public void onClick(View v) { + if (emojiTooltipVisible) { setEmojiTooltipVisible(false); - if(tooltipHider!=null){ + if (tooltipHider != null) { hintTextView.removeCallbacks(tooltipHider); - tooltipHider=null; + tooltipHider = null; } } setEmojiExpanded(!emojiExpanded); @@ -705,22 +696,22 @@ public void onClick(View v){ }); //keyEmojiText=new TextView(this); //keyEmojiText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - content.addView(emojiWrap, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP|(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); - emojiWrap.setOnLongClickListener(new View.OnLongClickListener(){ + content.addView(emojiWrap, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); + emojiWrap.setOnLongClickListener(new View.OnLongClickListener() { @Override - public boolean onLongClick(View v){ - if(emojiExpanded) + public boolean onLongClick(View v) { + if (emojiExpanded) return false; - if(tooltipHider!=null){ + if (tooltipHider != null) { hintTextView.removeCallbacks(tooltipHider); - tooltipHider=null; + tooltipHider = null; } setEmojiTooltipVisible(!emojiTooltipVisible); - if(emojiTooltipVisible){ - hintTextView.postDelayed(tooltipHider=new Runnable(){ + if (emojiTooltipVisible) { + hintTextView.postDelayed(tooltipHider = new Runnable() { @Override - public void run(){ - tooltipHider=null; + public void run() { + tooltipHider = null; setEmojiTooltipVisible(false); } }, 5000); @@ -728,11 +719,11 @@ public void run(){ return true; } }); - emojiExpandedText=new TextView(this); + emojiExpandedText = new TextView(this); emojiExpandedText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); emojiExpandedText.setTextColor(0xFFFFFFFF); emojiExpandedText.setGravity(Gravity.CENTER); - emojiExpandedText.setAlpha(0); + emojiExpandedText.setAlpha(0); content.addView(emojiExpandedText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 10, 32, 10, 0)); hintTextView = new CorrectlyMeasuringTextView(this); @@ -745,8 +736,8 @@ public void run(){ hintTextView.setAlpha(0.0f); content.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.RIGHT, 0, 42, 10, 0)); - int ellMaxAlpha=stateText.getPaint().getAlpha(); - ellAnimator=new AnimatorSet(); + int ellMaxAlpha = stateText.getPaint().getAlpha(); + ellAnimator = new AnimatorSet(); ellAnimator.playTogether( createAlphaAnimator(ellSpans[0], 0, ellMaxAlpha, 0, 300), createAlphaAnimator(ellSpans[1], 0, ellMaxAlpha, 150, 300), @@ -755,30 +746,31 @@ public void run(){ createAlphaAnimator(ellSpans[1], ellMaxAlpha, 0, 1000, 400), createAlphaAnimator(ellSpans[2], ellMaxAlpha, 0, 1000, 400) ); - ellAnimator.addListener(new AnimatorListenerAdapter(){ - private Runnable restarter=new Runnable(){ + ellAnimator.addListener(new AnimatorListenerAdapter() { + private Runnable restarter = new Runnable() { @Override - public void run(){ - if(!isFinishing()) + public void run() { + if (!isFinishing()) ellAnimator.start(); } }; + @Override - public void onAnimationEnd(Animator animation){ - if(!isFinishing()){ + public void onAnimationEnd(Animator animation) { + if (!isFinishing()) { VoIPActivity.this.content.postDelayed(restarter, 300); } } }); - content.setClipChildren(false); - this.content=content; + content.setClipChildren(false); + this.content = content; return content; } - @SuppressLint("ObjectAnimatorBinding") - private ObjectAnimator createAlphaAnimator(Object target, int startVal, int endVal, int startDelay, int duration){ - ObjectAnimator a=ObjectAnimator.ofInt(target, "alpha", startVal, endVal); + @SuppressLint("ObjectAnimatorBinding") + private ObjectAnimator createAlphaAnimator(Object target, int startVal, int endVal, int startDelay, int duration) { + ObjectAnimator a = ObjectAnimator.ofInt(target, "alpha", startVal, endVal); a.setDuration(duration); a.setStartDelay(startDelay); a.setInterpolator(CubicBezierInterpolator.DEFAULT); @@ -797,7 +789,7 @@ protected void onDestroy() { @Override public void onBackPressed() { - if(emojiExpanded){ + if (emojiExpanded) { setEmojiExpanded(false); return; } @@ -816,7 +808,7 @@ protected void onResume() { @Override protected void onPause() { super.onPause(); - if(retrying) + if (retrying) finish(); if (VoIPService.getSharedInstance() != null) VoIPService.getSharedInstance().onUIForegroundStateChanged(false); @@ -826,19 +818,19 @@ protected void onPause() { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 101) { - if(VoIPService.getSharedInstance()==null){ + if (VoIPService.getSharedInstance() == null) { finish(); return; } - if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { VoIPService.getSharedInstance().acceptIncomingCall(); callAccepted(); } else { - if(!shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)){ + if (!shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)) { VoIPService.getSharedInstance().declineIncomingCall(); - VoIPHelper.permissionDenied(this, new Runnable(){ + VoIPHelper.permissionDenied(this, new Runnable() { @Override - public void run(){ + public void run() { finish(); } }); @@ -851,7 +843,7 @@ public void run(){ } private void updateKeyView() { - if(VoIPService.getSharedInstance()==null) + if (VoIPService.getSharedInstance() == null) return; IdenticonDrawable img = new IdenticonDrawable(); img.setColors(new int[]{0x00FFFFFF, 0xFFFFFFFF, 0x99FFFFFF, 0x33FFFFFF}); @@ -859,14 +851,15 @@ private void updateKeyView() { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); buf.write(VoIPService.getSharedInstance().getEncryptionKey()); - buf.write(VoIPService.getSharedInstance().getGA()); + buf.write(VoIPService.getSharedInstance().getGA()); encryptedChat.auth_key = buf.toByteArray(); - }catch(Exception checkedExceptionsAreBad){} + } catch (Exception checkedExceptionsAreBad) { + } byte[] sha256 = Utilities.computeSHA256(encryptedChat.auth_key, 0, encryptedChat.auth_key.length); - String[] emoji=EncryptionKeyEmojifier.emojifyForCall(sha256); + String[] emoji = EncryptionKeyEmojifier.emojifyForCall(sha256); //keyEmojiText.setText(Emoji.replaceEmoji(TextUtils.join(" ", emoji), keyEmojiText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(32), false)); - emojiWrap.setContentDescription(LocaleController.getString("EncryptionKey", R.string.EncryptionKey)+", "+TextUtils.join(", ", emoji)); - for(int i=0;i<4;i++) { + emojiWrap.setContentDescription(LocaleController.getString("EncryptionKey", R.string.EncryptionKey) + ", " + TextUtils.join(", ", emoji)); + for (int i = 0; i < 4; i++) { Drawable drawable = Emoji.getEmojiDrawable(emoji[i]); if (drawable != null) { drawable.setBounds(0, 0, AndroidUtilities.dp(22), AndroidUtilities.dp(22)); @@ -875,48 +868,48 @@ private void updateKeyView() { } } - private CharSequence getFormattedDebugString(){ - String in=VoIPService.getSharedInstance().getDebugString(); - SpannableString ss=new SpannableString(in); - - int offset=0; - do{ - int lineEnd=in.indexOf('\n', offset+1); - if(lineEnd==-1) - lineEnd=in.length(); - String line=in.substring(offset, lineEnd); - if(line.contains("IN_USE")){ + private CharSequence getFormattedDebugString() { + String in = VoIPService.getSharedInstance().getDebugString(); + SpannableString ss = new SpannableString(in); + + int offset = 0; + do { + int lineEnd = in.indexOf('\n', offset + 1); + if (lineEnd == -1) + lineEnd = in.length(); + String line = in.substring(offset, lineEnd); + if (line.contains("IN_USE")) { ss.setSpan(new ForegroundColorSpan(0xFF00FF00), offset, lineEnd, 0); - }else{ - if(line.contains(": ")){ - ss.setSpan(new ForegroundColorSpan(0xAAFFFFFF), offset, offset+line.indexOf(':')+1, 0); + } else { + if (line.contains(": ")) { + ss.setSpan(new ForegroundColorSpan(0xAAFFFFFF), offset, offset + line.indexOf(':') + 1, 0); } } - }while((offset=in.indexOf('\n', offset+1))!=-1); + } while ((offset = in.indexOf('\n', offset + 1)) != -1); return ss; } private void showDebugAlert() { - if(VoIPService.getSharedInstance()==null) + if (VoIPService.getSharedInstance() == null) return; - VoIPService.getSharedInstance().forceRating(); - final LinearLayout debugOverlay=new LinearLayout(this); + VoIPService.getSharedInstance().forceRating(); + final LinearLayout debugOverlay = new LinearLayout(this); debugOverlay.setOrientation(LinearLayout.VERTICAL); debugOverlay.setBackgroundColor(0xCC000000); - int pad=AndroidUtilities.dp(16); - debugOverlay.setPadding(pad, pad*2, pad, pad*2); + int pad = AndroidUtilities.dp(16); + debugOverlay.setPadding(pad, pad * 2, pad, pad * 2); - TextView title=new TextView(this); + TextView title = new TextView(this); title.setTextColor(0xFFFFFFFF); title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); title.setTypeface(Typeface.DEFAULT_BOLD); title.setGravity(Gravity.CENTER); - title.setText("libtgvoip v"+VoIPController.getVersion()); + title.setText("libtgvoip v" + VoIPController.getVersion()); debugOverlay.addView(title, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 16)); - ScrollView scroll=new ScrollView(this); - final TextView debugText=new TextView(this); + ScrollView scroll = new ScrollView(this); + final TextView debugText = new TextView(this); debugText.setTypeface(Typeface.MONOSPACE); debugText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11); debugText.setMaxWidth(AndroidUtilities.dp(350)); @@ -925,7 +918,7 @@ private void showDebugAlert() { scroll.addView(debugText); debugOverlay.addView(scroll, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 1f)); - TextView closeBtn=new TextView(this); + TextView closeBtn = new TextView(this); closeBtn.setBackgroundColor(0xFFFFFFFF); closeBtn.setTextColor(0xFF000000); closeBtn.setPadding(pad, pad, pad, pad); @@ -933,12 +926,12 @@ private void showDebugAlert() { closeBtn.setText(LocaleController.getString("Close", R.string.Close)); debugOverlay.addView(closeBtn, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 0)); - final WindowManager wm=(WindowManager) getSystemService(WINDOW_SERVICE); + final WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.addView(debugOverlay, new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, 0, PixelFormat.TRANSLUCENT)); - closeBtn.setOnClickListener(new View.OnClickListener(){ + closeBtn.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v){ + public void onClick(View v) { wm.removeView(debugOverlay); } }); @@ -956,7 +949,7 @@ public void run() { debugOverlay.postDelayed(r, 500); } - private void showInviteFragment(){ + private void showInviteFragment() { /*KeyguardManager km=(KeyguardManager) getSystemService(KEYGUARD_SERVICE); if(km.inKeyguardRestrictedInputMode()){ VoIPHelper.dismissKeyguard(this, new VoIPHelper.OnKeyguardDismissListener(){ @@ -993,9 +986,9 @@ public void run() { if (isFinishing() || VoIPService.getSharedInstance() == null) { return; } - if(callState==VoIPService.STATE_ESTABLISHED || callState==VoIPService.STATE_RECONNECTING){ - long duration=VoIPService.getSharedInstance().getCallDuration()/1000; - durationText.setText(duration>3600 ? String.format("%d:%02d:%02d", duration/3600, duration%3600/60, duration%60) : String.format("%d:%02d", duration/60, duration%60)); + if (callState == VoIPService.STATE_ESTABLISHED || callState == VoIPService.STATE_RECONNECTING) { + long duration = VoIPService.getSharedInstance().getCallDuration() / 1000; + durationText.setText(duration > 3600 ? String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60) : String.format("%d:%02d", duration / 60, duration % 60)); durationText.postDelayed(this, 500); } } @@ -1006,8 +999,8 @@ public void run() { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (isIncomingWaiting && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) { - if(VoIPService.getSharedInstance()!=null) - VoIPService.getSharedInstance().stopRinging(); + if (VoIPService.getSharedInstance() != null) + VoIPService.getSharedInstance().stopRinging(); else finish(); return true; @@ -1017,7 +1010,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { private void callAccepted() { endBtn.setVisibility(View.VISIBLE); - if(VoIPService.getSharedInstance().hasEarpiece()) + if (VoIPService.getSharedInstance().hasEarpiece()) spkToggle.setVisibility(View.VISIBLE); else spkToggle.setVisibility(View.GONE); @@ -1094,14 +1087,14 @@ public void onAnimationEnd(Animator animation) { } } - private void showRetry(){ - if(retryAnim!=null) + private void showRetry() { + if (retryAnim != null) retryAnim.cancel(); endBtn.setEnabled(false); - retrying=true; + retrying = true; cancelBtn.setVisibility(View.VISIBLE); cancelBtn.setAlpha(0); - AnimatorSet set=new AnimatorSet(); + AnimatorSet set = new AnimatorSet(); ObjectAnimator colorAnim; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { colorAnim = ObjectAnimator.ofArgb(endBtnBg, "color", 0xFFe61e44, 0xFF45bc4d); @@ -1111,7 +1104,7 @@ private void showRetry(){ } set.playTogether( ObjectAnimator.ofFloat(cancelBtn, "alpha", 0, 1), - ObjectAnimator.ofFloat(endBtn, "translationX", 0, content.getWidth()/2-AndroidUtilities.dp(52)-endBtn.getWidth()/2), + ObjectAnimator.ofFloat(endBtn, "translationX", 0, content.getWidth() / 2 - AndroidUtilities.dp(52) - endBtn.getWidth() / 2), colorAnim, ObjectAnimator.ofFloat(endBtnIcon, "rotation", 0, -135)//, //ObjectAnimator.ofFloat(spkToggle, "alpha", 0), @@ -1121,22 +1114,22 @@ private void showRetry(){ set.setStartDelay(200); set.setDuration(300); set.setInterpolator(CubicBezierInterpolator.DEFAULT); - set.addListener(new AnimatorListenerAdapter(){ + set.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation){ + public void onAnimationEnd(Animator animation) { //bottomButtons.setVisibility(View.GONE); - retryAnim=null; + retryAnim = null; endBtn.setEnabled(true); } }); - retryAnim=set; + retryAnim = set; set.start(); } - private void hideRetry(){ - if(retryAnim!=null) + private void hideRetry() { + if (retryAnim != null) retryAnim.cancel(); - retrying=false; + retrying = false; //bottomButtons.setVisibility(View.VISIBLE); ObjectAnimator colorAnim; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -1145,7 +1138,7 @@ private void hideRetry(){ colorAnim = ObjectAnimator.ofInt(endBtnBg, "color", 0xFF45bc4d, 0xFFe61e44); colorAnim.setEvaluator(new ArgbEvaluator()); } - AnimatorSet set=new AnimatorSet(); + AnimatorSet set = new AnimatorSet(); set.playTogether( colorAnim, ObjectAnimator.ofFloat(endBtnIcon, "rotation", -135, 0), @@ -1156,45 +1149,45 @@ private void hideRetry(){ set.setStartDelay(200); set.setDuration(300); set.setInterpolator(CubicBezierInterpolator.DEFAULT); - set.addListener(new AnimatorListenerAdapter(){ + set.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation){ + public void onAnimationEnd(Animator animation) { cancelBtn.setVisibility(View.GONE); endBtn.setEnabled(true); - retryAnim=null; + retryAnim = null; } }); - retryAnim=set; + retryAnim = set; set.start(); } @Override public void onStateChanged(final int state) { - final int prevState=callState; - callState=state; + final int prevState = callState; + callState = state; runOnUiThread(new Runnable() { @Override public void run() { - boolean wasFirstStateChange=firstStateChange; + boolean wasFirstStateChange = firstStateChange; if (firstStateChange) { - spkToggle.setChecked(((AudioManager)getSystemService(AUDIO_SERVICE)).isSpeakerphoneOn()); + spkToggle.setChecked(((AudioManager) getSystemService(AUDIO_SERVICE)).isSpeakerphoneOn()); if (isIncomingWaiting = state == VoIPService.STATE_WAITING_INCOMING) { swipeViewsWrap.setVisibility(View.VISIBLE); endBtn.setVisibility(View.GONE); //bottomButtons.setVisibility(View.GONE); - acceptSwipe.startAnimatingArrows(); - declineSwipe.startAnimatingArrows(); - if(UserConfig.getActivatedAccountsCount()>1){ - TLRPC.User self=UserConfig.getInstance(currentAccount).getCurrentUser(); - accountNameText.setText(LocaleController.formatString("VoipAnsweringAsAccount", R.string.VoipAnsweringAsAccount, ContactsController.formatName(self.first_name, self.last_name))); - }else{ - accountNameText.setVisibility(View.GONE); - } + acceptSwipe.startAnimatingArrows(); + declineSwipe.startAnimatingArrows(); + if (UserConfig.getActivatedAccountsCount() > 1) { + TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); + accountNameText.setText(LocaleController.formatString("VoipAnsweringAsAccount", R.string.VoipAnsweringAsAccount, ContactsController.formatName(self.first_name, self.last_name))); + } else { + accountNameText.setVisibility(View.GONE); + } getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - VoIPService svc=VoIPService.getSharedInstance(); - if(svc!=null) - svc.startRingtoneAndVibration(); - setTitle(LocaleController.getString("VoipIncoming", R.string.VoipIncoming)); + VoIPService svc = VoIPService.getSharedInstance(); + if (svc != null) + svc.startRingtoneAndVibration(); + setTitle(LocaleController.getString("VoipIncoming", R.string.VoipIncoming)); } else { swipeViewsWrap.setVisibility(View.GONE); acceptBtn.setVisibility(View.GONE); @@ -1207,7 +1200,7 @@ public void run() { firstStateChange = false; } - if (isIncomingWaiting && state != VoIPService.STATE_WAITING_INCOMING && state!=VoIPBaseService.STATE_ENDED && state!=VoIPService.STATE_HANGING_UP) { + if (isIncomingWaiting && state != VoIPService.STATE_WAITING_INCOMING && state != VoIPBaseService.STATE_ENDED && state != VoIPService.STATE_HANGING_UP) { isIncomingWaiting = false; if (!didAcceptFromHere) callAccepted(); @@ -1248,31 +1241,31 @@ public void run() { } }, 2000);*/ showRetry(); - } else if (state == VoIPService.STATE_ESTABLISHED || state==VoIPService.STATE_RECONNECTING) { + } else if (state == VoIPService.STATE_ESTABLISHED || state == VoIPService.STATE_RECONNECTING) { /*if(VoIPService.getSharedInstance().canUpgrate()){ addMemberBtn.setEnabled(true); addMemberBtn.setAlpha(1f); }*/ setTitle(null); - if(!wasFirstStateChange && state==VoIPService.STATE_ESTABLISHED){ - int count= MessagesController.getGlobalMainSettings().getInt("call_emoji_tooltip_count", 0); - if(count<3){ + if (!wasFirstStateChange && state == VoIPService.STATE_ESTABLISHED) { + int count = MessagesController.getGlobalMainSettings().getInt("call_emoji_tooltip_count", 0); + if (count < 3) { setEmojiTooltipVisible(true); - hintTextView.postDelayed(tooltipHider=new Runnable(){ + hintTextView.postDelayed(tooltipHider = new Runnable() { @Override - public void run(){ - tooltipHider=null; + public void run() { + tooltipHider = null; setEmojiTooltipVisible(false); } }, 5000); - MessagesController.getGlobalMainSettings().edit().putInt("call_emoji_tooltip_count", count+1).commit(); + MessagesController.getGlobalMainSettings().edit().putInt("call_emoji_tooltip_count", count + 1).commit(); } } - if(prevState!=VoIPService.STATE_ESTABLISHED && prevState!=VoIPService.STATE_RECONNECTING){ + if (prevState != VoIPService.STATE_ESTABLISHED && prevState != VoIPService.STATE_RECONNECTING) { setStateTextAnimated("0:00", false); startUpdatingCallDuration(); updateKeyView(); - if(emojiWrap.getVisibility()!=View.VISIBLE){ + if (emojiWrap.getVisibility() != View.VISIBLE) { emojiWrap.setVisibility(View.VISIBLE); emojiWrap.setAlpha(0f); emojiWrap.animate().alpha(1).setDuration(200).setInterpolator(new DecelerateInterpolator()).start(); @@ -1280,21 +1273,21 @@ public void run(){ } } else if (state == VoIPService.STATE_FAILED) { setStateTextAnimated(LocaleController.getString("VoipFailed", R.string.VoipFailed), false); - int lastError=VoIPService.getSharedInstance()!=null ? VoIPService.getSharedInstance().getLastError() : VoIPController.ERROR_UNKNOWN; - if (lastError== VoIPController.ERROR_INCOMPATIBLE) { + int lastError = VoIPService.getSharedInstance() != null ? VoIPService.getSharedInstance().getLastError() : VoIPController.ERROR_UNKNOWN; + if (lastError == VoIPController.ERROR_INCOMPATIBLE) { showErrorDialog(AndroidUtilities.replaceTags(LocaleController.formatString("VoipPeerIncompatible", R.string.VoipPeerIncompatible, - ContactsController.formatName(user.first_name, user.last_name)))); - }else if (lastError== VoIPController.ERROR_PEER_OUTDATED) { + ContactsController.formatName(user.first_name, user.last_name)))); + } else if (lastError == VoIPController.ERROR_PEER_OUTDATED) { showErrorDialog(AndroidUtilities.replaceTags(LocaleController.formatString("VoipPeerOutdated", R.string.VoipPeerOutdated, - ContactsController.formatName(user.first_name, user.last_name)))); - }else if(lastError==VoIPController.ERROR_PRIVACY){ + ContactsController.formatName(user.first_name, user.last_name)))); + } else if (lastError == VoIPController.ERROR_PRIVACY) { showErrorDialog(AndroidUtilities.replaceTags(LocaleController.formatString("CallNotAvailable", R.string.CallNotAvailable, ContactsController.formatName(user.first_name, user.last_name)))); - }else if(lastError==VoIPController.ERROR_AUDIO_IO){ + } else if (lastError == VoIPController.ERROR_AUDIO_IO) { showErrorDialog("Error initializing audio hardware"); - }else if(lastError==VoIPController.ERROR_LOCALIZED){ + } else if (lastError == VoIPController.ERROR_LOCALIZED) { finish(); - }else if(lastError==VoIPController.ERROR_CONNECTION_SERVICE){ + } else if (lastError == VoIPController.ERROR_CONNECTION_SERVICE) { showErrorDialog(LocaleController.getString("VoipErrorUnknown", R.string.VoipErrorUnknown)); } else { stateText.postDelayed(new Runnable() { @@ -1311,17 +1304,17 @@ public void run() { } @Override - public void onSignalBarsCountChanged(final int count){ - runOnUiThread(new Runnable(){ + public void onSignalBarsCountChanged(final int count) { + runOnUiThread(new Runnable() { @Override - public void run(){ - signalBarsCount=count; + public void run() { + signalBarsCount = count; brandingText.invalidate(); } }); } - private void showErrorDialog(CharSequence message){ + private void showErrorDialog(CharSequence message) { AlertDialog dlg = new DarkAlertDialog.Builder(VoIPActivity.this) .setTitle(LocaleController.getString("VoipFailed", R.string.VoipFailed)) .setMessage(message) @@ -1334,91 +1327,91 @@ public void onDismiss(DialogInterface dialog) { finish(); } }); - } + } @Override public void onAudioSettingsChanged() { - VoIPBaseService svc=VoIPBaseService.getSharedInstance(); - if(svc==null) + VoIPBaseService svc = VoIPBaseService.getSharedInstance(); + if (svc == null) return; micToggle.setChecked(svc.isMicMute()); - if(!svc.hasEarpiece() && !svc.isBluetoothHeadsetConnected()){ + if (!svc.hasEarpiece() && !svc.isBluetoothHeadsetConnected()) { spkToggle.setVisibility(View.INVISIBLE); - }else{ + } else { spkToggle.setVisibility(View.VISIBLE); - if(!svc.hasEarpiece()){ + if (!svc.hasEarpiece()) { spkToggle.setImageResource(R.drawable.ic_bluetooth_white_24dp); spkToggle.setChecked(svc.isSpeakerphoneOn()); - }else if(svc.isBluetoothHeadsetConnected()){ - switch(svc.getCurrentAudioRoute()){ - case VoIPBaseService.AUDIO_ROUTE_BLUETOOTH: - spkToggle.setImageResource(R.drawable.ic_bluetooth_white_24dp); - break; - case VoIPBaseService.AUDIO_ROUTE_SPEAKER: - spkToggle.setImageResource(R.drawable.ic_volume_up_white_24dp); - break; - case VoIPBaseService.AUDIO_ROUTE_EARPIECE: - spkToggle.setImageResource(R.drawable.ic_phone_in_talk_white_24dp); - break; + } else if (svc.isBluetoothHeadsetConnected()) { + switch (svc.getCurrentAudioRoute()) { + case VoIPBaseService.AUDIO_ROUTE_BLUETOOTH: + spkToggle.setImageResource(R.drawable.ic_bluetooth_white_24dp); + break; + case VoIPBaseService.AUDIO_ROUTE_SPEAKER: + spkToggle.setImageResource(R.drawable.ic_volume_up_white_24dp); + break; + case VoIPBaseService.AUDIO_ROUTE_EARPIECE: + spkToggle.setImageResource(R.drawable.ic_phone_in_talk_white_24dp); + break; } spkToggle.setChecked(false); - }else{ + } else { spkToggle.setImageResource(R.drawable.ic_volume_up_white_24dp); spkToggle.setChecked(svc.isSpeakerphoneOn()); } } } - private void setStateTextAnimated(String _newText, boolean ellipsis){ - if(_newText.equals(lastStateText)) + private void setStateTextAnimated(String _newText, boolean ellipsis) { + if (_newText.equals(lastStateText)) return; - lastStateText=_newText; - if(textChangingAnim!=null) + lastStateText = _newText; + if (textChangingAnim != null) textChangingAnim.cancel(); CharSequence newText; - if(ellipsis){ - if(!ellAnimator.isRunning()) + if (ellipsis) { + if (!ellAnimator.isRunning()) ellAnimator.start(); - SpannableStringBuilder ssb=new SpannableStringBuilder(_newText.toUpperCase()); - for(TextAlphaSpan s:ellSpans) + SpannableStringBuilder ssb = new SpannableStringBuilder(_newText.toUpperCase()); + for (TextAlphaSpan s : ellSpans) s.setAlpha(0); - SpannableString ell=new SpannableString("..."); + SpannableString ell = new SpannableString("..."); ell.setSpan(ellSpans[0], 0, 1, 0); ell.setSpan(ellSpans[1], 1, 2, 0); ell.setSpan(ellSpans[2], 2, 3, 0); ssb.append(ell); - newText=ssb; - }else{ - if(ellAnimator.isRunning()) + newText = ssb; + } else { + if (ellAnimator.isRunning()) ellAnimator.cancel(); - newText=_newText.toUpperCase(); + newText = _newText.toUpperCase(); } stateText2.setText(newText); stateText2.setVisibility(View.VISIBLE); stateText.setPivotX(LocaleController.isRTL ? stateText.getWidth() : 0); - stateText.setPivotY(stateText.getHeight()/2); + stateText.setPivotY(stateText.getHeight() / 2); stateText2.setPivotX(LocaleController.isRTL ? stateText.getWidth() : 0); - stateText2.setPivotY(stateText.getHeight()/2); - durationText=stateText2; - AnimatorSet set=new AnimatorSet(); + stateText2.setPivotY(stateText.getHeight() / 2); + durationText = stateText2; + AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(stateText2, "alpha", 0, 1), - ObjectAnimator.ofFloat(stateText2, "translationY", stateText.getHeight()/2, 0), + ObjectAnimator.ofFloat(stateText2, "translationY", stateText.getHeight() / 2, 0), ObjectAnimator.ofFloat(stateText2, "scaleX", 0.7f, 1), ObjectAnimator.ofFloat(stateText2, "scaleY", 0.7f, 1), ObjectAnimator.ofFloat(stateText, "alpha", 1, 0), - ObjectAnimator.ofFloat(stateText, "translationY", 0, -stateText.getHeight()/2), + ObjectAnimator.ofFloat(stateText, "translationY", 0, -stateText.getHeight() / 2), ObjectAnimator.ofFloat(stateText, "scaleX", 1, 0.7f), ObjectAnimator.ofFloat(stateText, "scaleY", 1, 0.7f) ); set.setDuration(200); set.setInterpolator(CubicBezierInterpolator.DEFAULT); - set.addListener(new AnimatorListenerAdapter(){ + set.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation){ - textChangingAnim=null; + public void onAnimationEnd(Animator animation) { + textChangingAnim = null; stateText2.setVisibility(View.GONE); - durationText=stateText; + durationText = stateText; stateText.setTranslationY(0); stateText.setScaleX(1); stateText.setScaleY(1); @@ -1426,55 +1419,55 @@ public void onAnimationEnd(Animator animation){ stateText.setText(stateText2.getText()); } }); - textChangingAnim=set; + textChangingAnim = set; set.start(); } @Override - public void didReceivedNotification(int id, int account, Object... args){ - if(id==NotificationCenter.emojiDidLoad){ - for(ImageView iv:keyEmojiViews){ + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiDidLoad) { + for (ImageView iv : keyEmojiViews) { iv.invalidate(); } } - if(id==NotificationCenter.closeInCallActivity){ + if (id == NotificationCenter.closeInCallActivity) { finish(); } } - private void setEmojiTooltipVisible(boolean visible){ - emojiTooltipVisible=visible; - if(tooltipAnim!=null) - tooltipAnim.cancel(); - hintTextView.setVisibility(View.VISIBLE); - ObjectAnimator oa=ObjectAnimator.ofFloat(hintTextView, "alpha", visible ? 1 : 0); - oa.setDuration(300); - oa.setInterpolator(CubicBezierInterpolator.DEFAULT); - oa.addListener(new AnimatorListenerAdapter(){ - @Override - public void onAnimationEnd(Animator animation){ - tooltipAnim=null; - } - }); - tooltipAnim=oa; - oa.start(); + private void setEmojiTooltipVisible(boolean visible) { + emojiTooltipVisible = visible; + if (tooltipAnim != null) + tooltipAnim.cancel(); + hintTextView.setVisibility(View.VISIBLE); + ObjectAnimator oa = ObjectAnimator.ofFloat(hintTextView, "alpha", visible ? 1 : 0); + oa.setDuration(300); + oa.setInterpolator(CubicBezierInterpolator.DEFAULT); + oa.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + tooltipAnim = null; + } + }); + tooltipAnim = oa; + oa.start(); } - private void setEmojiExpanded(boolean expanded){ - if(emojiExpanded==expanded) + private void setEmojiExpanded(boolean expanded) { + if (emojiExpanded == expanded) return; - emojiExpanded=expanded; - if(emojiAnimator!=null) + emojiExpanded = expanded; + if (emojiAnimator != null) emojiAnimator.cancel(); - if(expanded){ - int[] loc={0, 0}, loc2={0, 0}; + if (expanded) { + int[] loc = {0, 0}, loc2 = {0, 0}; emojiWrap.getLocationInWindow(loc); emojiExpandedText.getLocationInWindow(loc2); - Rect rect=new Rect(); + Rect rect = new Rect(); getWindow().getDecorView().getGlobalVisibleRect(rect); - int offsetY=loc2[1]-(loc[1]+emojiWrap.getHeight())-AndroidUtilities.dp(32)-emojiWrap.getHeight(); - int firstOffsetX=(rect.width()/2-Math.round(emojiWrap.getWidth()*2.5f)/2)-loc[0]; - AnimatorSet set=new AnimatorSet(); + int offsetY = loc2[1] - (loc[1] + emojiWrap.getHeight()) - AndroidUtilities.dp(32) - emojiWrap.getHeight(); + int firstOffsetX = (rect.width() / 2 - Math.round(emojiWrap.getWidth() * 2.5f) / 2) - loc[0]; + AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(emojiWrap, "translationY", offsetY), ObjectAnimator.ofFloat(emojiWrap, "translationX", firstOffsetX), @@ -1486,20 +1479,20 @@ private void setEmojiExpanded(boolean expanded){ ); set.setDuration(300); set.setInterpolator(CubicBezierInterpolator.DEFAULT); - emojiAnimator=set; - set.addListener(new AnimatorListenerAdapter(){ + emojiAnimator = set; + set.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation){ - emojiAnimator=null; + public void onAnimationEnd(Animator animation) { + emojiAnimator = null; } }); set.start(); - }else{ - AnimatorSet set=new AnimatorSet(); + } else { + AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(emojiWrap, "translationX", 0), ObjectAnimator.ofFloat(emojiWrap, "translationY", 0), - ObjectAnimator.ofFloat(emojiWrap, "scaleX", 1), + ObjectAnimator.ofFloat(emojiWrap, "scaleX", 1), ObjectAnimator.ofFloat(emojiWrap, "scaleY", 1), ObjectAnimator.ofFloat(blurOverlayView1, "alpha", blurOverlayView1.getAlpha(), blurOverlayView1.getAlpha(), 0), ObjectAnimator.ofFloat(blurOverlayView2, "alpha", blurOverlayView2.getAlpha(), 0, 0), @@ -1507,11 +1500,11 @@ public void onAnimationEnd(Animator animation){ ); set.setDuration(300); set.setInterpolator(CubicBezierInterpolator.DEFAULT); - emojiAnimator=set; - set.addListener(new AnimatorListenerAdapter(){ + emojiAnimator = set; + set.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation){ - emojiAnimator=null; + public void onAnimationEnd(Animator animation) { + emojiAnimator = null; } }); set.start(); @@ -1540,13 +1533,10 @@ public void run() { canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); blurredPhoto1 = blur1; blurredPhoto2 = blur2; - runOnUiThread(new Runnable() { - @Override - public void run() { - blurOverlayView1.setImageBitmap(blurredPhoto1); - blurOverlayView2.setImageBitmap(blurredPhoto2); - src.release(); - } + runOnUiThread(() -> { + blurOverlayView1.setImageBitmap(blurredPhoto1); + blurOverlayView2.setImageBitmap(blurredPhoto2); + src.release(); }); } catch (Throwable ignore) { @@ -1555,245 +1545,219 @@ public void run() { }).start(); } - private void sendTextMessage(final String text){ - AndroidUtilities.runOnUIThread(new Runnable(){ - @Override - public void run(){ - SendMessagesHelper.getInstance(currentAccount).sendMessage(text, user.id, null, null, false, null, null, null); - } - }); + private void sendTextMessage(final String text) { + AndroidUtilities.runOnUIThread(() -> SendMessagesHelper.getInstance(currentAccount).sendMessage(text, user.id, null, null, false, null, null, null, true, 0)); } - private void showMessagesSheet(){ - if(VoIPService.getSharedInstance()!=null) + private void showMessagesSheet() { + if (VoIPService.getSharedInstance() != null) VoIPService.getSharedInstance().stopRinging(); - SharedPreferences prefs=getSharedPreferences("mainconfig", MODE_PRIVATE); - final String[] msgs={prefs.getString("quick_reply_msg1", LocaleController.getString("QuickReplyDefault1", R.string.QuickReplyDefault1)), + SharedPreferences prefs = getSharedPreferences("mainconfig", MODE_PRIVATE); + final String[] msgs = {prefs.getString("quick_reply_msg1", LocaleController.getString("QuickReplyDefault1", R.string.QuickReplyDefault1)), prefs.getString("quick_reply_msg2", LocaleController.getString("QuickReplyDefault2", R.string.QuickReplyDefault2)), prefs.getString("quick_reply_msg3", LocaleController.getString("QuickReplyDefault3", R.string.QuickReplyDefault3)), prefs.getString("quick_reply_msg4", LocaleController.getString("QuickReplyDefault4", R.string.QuickReplyDefault4))}; - LinearLayout sheetView=new LinearLayout(this); + LinearLayout sheetView = new LinearLayout(this); sheetView.setOrientation(LinearLayout.VERTICAL); - final BottomSheet sheet=new BottomSheet(this, true, 0); - if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){ - getWindow().setNavigationBarColor(0xff2b2b2b); - sheet.setOnDismissListener(new DialogInterface.OnDismissListener(){ - @Override - public void onDismiss(DialogInterface dialog){ - getWindow().setNavigationBarColor(0); - } - }); + final BottomSheet sheet = new BottomSheet(this, true, 0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setNavigationBarColor(0xff2b2b2b); + sheet.setOnDismissListener(dialog -> getWindow().setNavigationBarColor(0)); } - View.OnClickListener listener=new View.OnClickListener(){ - @Override - public void onClick(final View v){ - sheet.dismiss(); - if(VoIPService.getSharedInstance()!=null) - VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, new Runnable(){ - @Override - public void run(){ - sendTextMessage((String)v.getTag()); - } - }); - } + View.OnClickListener listener = v -> { + sheet.dismiss(); + if (VoIPService.getSharedInstance() != null) + VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, () -> sendTextMessage((String) v.getTag())); }; - for(String msg:msgs){ - BottomSheet.BottomSheetCell cell=new BottomSheet.BottomSheetCell(this, 0); + for (String msg : msgs) { + BottomSheet.BottomSheetCell cell = new BottomSheet.BottomSheetCell(this, 0); cell.setTextAndIcon(msg, 0); cell.setTextColor(0xFFFFFFFF); cell.setTag(msg); - cell.setOnClickListener(listener); + cell.setOnClickListener(listener); sheetView.addView(cell); } - FrameLayout customWrap=new FrameLayout(this); - final BottomSheet.BottomSheetCell cell=new BottomSheet.BottomSheetCell(this, 0); - cell.setTextAndIcon(LocaleController.getString("QuickReplyCustom", R.string.QuickReplyCustom), 0); - cell.setTextColor(0xFFFFFFFF); - customWrap.addView(cell); - - final FrameLayout editor=new FrameLayout(this); - final EditText field=new EditText(this); - field.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - field.setTextColor(0xFFFFFFFF); - field.setHintTextColor(DarkTheme.getColor(Theme.key_chat_messagePanelHint)); - field.setBackgroundDrawable(null); - field.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(11), AndroidUtilities.dp(16), AndroidUtilities.dp(12)); - field.setHint(LocaleController.getString("QuickReplyCustom", R.string.QuickReplyCustom)); - field.setMinHeight(AndroidUtilities.dp(48)); - field.setGravity(Gravity.BOTTOM); - field.setMaxLines(4); - field.setSingleLine(false); - field.setInputType(field.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); - editor.addView(field, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 48 : 0, 0, LocaleController.isRTL ? 0 : 48, 0)); - - final ImageView sendBtn=new ImageView(this); - sendBtn.setScaleType(ImageView.ScaleType.CENTER); - sendBtn.setImageDrawable(DarkTheme.getThemedDrawable(this, R.drawable.ic_send, Theme.key_chat_messagePanelSend)); - if(LocaleController.isRTL) - sendBtn.setScaleX(-0.1f); - else - sendBtn.setScaleX(0.1f); - sendBtn.setScaleY(0.1f); - sendBtn.setAlpha(0f); - editor.addView(sendBtn, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); - sendBtn.setOnClickListener(new View.OnClickListener(){ - @Override - public void onClick(View v){ - if(field.length()==0) - return; - sheet.dismiss(); - if(VoIPService.getSharedInstance()!=null) - VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, new Runnable(){ - @Override - public void run(){ - sendTextMessage(field.getText().toString()); - } - }); - } - }); - sendBtn.setVisibility(View.INVISIBLE); - - final ImageView cancelBtn=new ImageView(this); - cancelBtn.setScaleType(ImageView.ScaleType.CENTER); - cancelBtn.setImageDrawable(DarkTheme.getThemedDrawable(this, R.drawable.edit_cancel, Theme.key_chat_messagePanelIcons)); - editor.addView(cancelBtn, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); - cancelBtn.setOnClickListener(new View.OnClickListener(){ - @Override - public void onClick(View v){ - editor.setVisibility(View.GONE); - cell.setVisibility(View.VISIBLE); - field.setText(""); - InputMethodManager imm=(InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(field.getWindowToken(), 0); - } - }); - - field.addTextChangedListener(new TextWatcher(){ - boolean prevState=false; - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after){ - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count){ - - } - - @Override - public void afterTextChanged(Editable s){ - boolean hasText=s.length()>0; - if(prevState!=hasText){ - prevState=hasText; - if(hasText){ - sendBtn.setVisibility(View.VISIBLE); - sendBtn.animate().alpha(1).scaleX(LocaleController.isRTL ? -1 : 1).scaleY(1).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); - cancelBtn.animate().alpha(0).scaleX(0.1f).scaleY(0.1f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(200).withEndAction(new Runnable(){ - @Override - public void run(){ - cancelBtn.setVisibility(View.INVISIBLE); - } - }).start(); - }else{ - cancelBtn.setVisibility(View.VISIBLE); - cancelBtn.animate().alpha(1).scaleX(1).scaleY(1).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); - sendBtn.animate().alpha(0).scaleX(LocaleController.isRTL ? -0.1f : 0.1f).scaleY(0.1f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(200).withEndAction(new Runnable(){ - @Override - public void run(){ - sendBtn.setVisibility(View.INVISIBLE); - } - }).start(); - } - } - } - }); - - editor.setVisibility(View.GONE); - customWrap.addView(editor); - - cell.setOnClickListener(new View.OnClickListener(){ - @Override - public void onClick(View v){ - editor.setVisibility(View.VISIBLE); - cell.setVisibility(View.INVISIBLE); - field.requestFocus(); - InputMethodManager imm=(InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); - imm.showSoftInput(field, 0); - } - }); - - sheetView.addView(customWrap); + FrameLayout customWrap = new FrameLayout(this); + final BottomSheet.BottomSheetCell cell = new BottomSheet.BottomSheetCell(this, 0); + cell.setTextAndIcon(LocaleController.getString("QuickReplyCustom", R.string.QuickReplyCustom), 0); + cell.setTextColor(0xFFFFFFFF); + customWrap.addView(cell); + + final FrameLayout editor = new FrameLayout(this); + final EditText field = new EditText(this); + field.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + field.setTextColor(0xFFFFFFFF); + field.setHintTextColor(DarkTheme.getColor(Theme.key_chat_messagePanelHint)); + field.setBackgroundDrawable(null); + field.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(11), AndroidUtilities.dp(16), AndroidUtilities.dp(12)); + field.setHint(LocaleController.getString("QuickReplyCustom", R.string.QuickReplyCustom)); + field.setMinHeight(AndroidUtilities.dp(48)); + field.setGravity(Gravity.BOTTOM); + field.setMaxLines(4); + field.setSingleLine(false); + field.setInputType(field.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); + editor.addView(field, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 48 : 0, 0, LocaleController.isRTL ? 0 : 48, 0)); + + final ImageView sendBtn = new ImageView(this); + sendBtn.setScaleType(ImageView.ScaleType.CENTER); + sendBtn.setImageDrawable(DarkTheme.getThemedDrawable(this, R.drawable.ic_send, Theme.key_chat_messagePanelSend)); + if (LocaleController.isRTL) + sendBtn.setScaleX(-0.1f); + else + sendBtn.setScaleX(0.1f); + sendBtn.setScaleY(0.1f); + sendBtn.setAlpha(0f); + editor.addView(sendBtn, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); + sendBtn.setOnClickListener(v -> { + if (field.length() == 0) + return; + sheet.dismiss(); + if (VoIPService.getSharedInstance() != null) + VoIPService.getSharedInstance().declineIncomingCall(VoIPService.DISCARD_REASON_LINE_BUSY, new Runnable() { + @Override + public void run() { + sendTextMessage(field.getText().toString()); + } + }); + }); + sendBtn.setVisibility(View.INVISIBLE); + + final ImageView cancelBtn = new ImageView(this); + cancelBtn.setScaleType(ImageView.ScaleType.CENTER); + cancelBtn.setImageDrawable(DarkTheme.getThemedDrawable(this, R.drawable.edit_cancel, Theme.key_chat_messagePanelIcons)); + editor.addView(cancelBtn, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); + cancelBtn.setOnClickListener(v -> { + editor.setVisibility(View.GONE); + cell.setVisibility(View.VISIBLE); + field.setText(""); + InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(field.getWindowToken(), 0); + }); + + field.addTextChangedListener(new TextWatcher() { + boolean prevState = false; + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + boolean hasText = s.length() > 0; + if (prevState != hasText) { + prevState = hasText; + if (hasText) { + sendBtn.setVisibility(View.VISIBLE); + sendBtn.animate().alpha(1).scaleX(LocaleController.isRTL ? -1 : 1).scaleY(1).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + cancelBtn.animate().alpha(0).scaleX(0.1f).scaleY(0.1f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(200).withEndAction(new Runnable() { + @Override + public void run() { + cancelBtn.setVisibility(View.INVISIBLE); + } + }).start(); + } else { + cancelBtn.setVisibility(View.VISIBLE); + cancelBtn.animate().alpha(1).scaleX(1).scaleY(1).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + sendBtn.animate().alpha(0).scaleX(LocaleController.isRTL ? -0.1f : 0.1f).scaleY(0.1f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(200).withEndAction(new Runnable() { + @Override + public void run() { + sendBtn.setVisibility(View.INVISIBLE); + } + }).start(); + } + } + } + }); + + editor.setVisibility(View.GONE); + customWrap.addView(editor); + + cell.setOnClickListener(v -> { + editor.setVisibility(View.VISIBLE); + cell.setVisibility(View.INVISIBLE); + field.requestFocus(); + InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + imm.showSoftInput(field, 0); + }); + + sheetView.addView(customWrap); sheet.setCustomView(sheetView); sheet.setBackgroundColor(0xff2b2b2b); sheet.show(); } - private class TextAlphaSpan extends CharacterStyle{ + private class TextAlphaSpan extends CharacterStyle { private int alpha; - public TextAlphaSpan(){ - this.alpha=0; + public TextAlphaSpan() { + this.alpha = 0; } - public int getAlpha(){ + public int getAlpha() { return alpha; } - public void setAlpha(int alpha){ - this.alpha=alpha; + public void setAlpha(int alpha) { + this.alpha = alpha; stateText.invalidate(); stateText2.invalidate(); } @Override - public void updateDrawState(TextPaint tp){ + public void updateDrawState(TextPaint tp) { tp.setAlpha(alpha); } } - private class SignalBarsDrawable extends Drawable{ + private class SignalBarsDrawable extends Drawable { - private int[] barHeights={AndroidUtilities.dp(3), AndroidUtilities.dp(6), AndroidUtilities.dp(9), AndroidUtilities.dp(12)}; - private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG); - private RectF rect=new RectF(); - private int offsetStart=6; + private int[] barHeights = {AndroidUtilities.dp(3), AndroidUtilities.dp(6), AndroidUtilities.dp(9), AndroidUtilities.dp(12)}; + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private RectF rect = new RectF(); + private int offsetStart = 6; @Override - public void draw(@NonNull Canvas canvas){ - if(callState!=VoIPService.STATE_ESTABLISHED && callState!=VoIPService.STATE_RECONNECTING) + public void draw(Canvas canvas) { + if (callState != VoIPService.STATE_ESTABLISHED && callState != VoIPService.STATE_RECONNECTING) return; paint.setColor(0xFFFFFFFF); - int x=getBounds().left+AndroidUtilities.dp(LocaleController.isRTL ? 0 : offsetStart); - int y=getBounds().top; - for(int i=0;i<4;i++){ - paint.setAlpha(i+1<=signalBarsCount ? 242 : 102); - rect.set(x+AndroidUtilities.dp(4*i), y+getIntrinsicHeight()-barHeights[i], x+AndroidUtilities.dp(4)*i+AndroidUtilities.dp(3), y+getIntrinsicHeight()); + int x = getBounds().left + AndroidUtilities.dp(LocaleController.isRTL ? 0 : offsetStart); + int y = getBounds().top; + for (int i = 0; i < 4; i++) { + paint.setAlpha(i + 1 <= signalBarsCount ? 242 : 102); + rect.set(x + AndroidUtilities.dp(4 * i), y + getIntrinsicHeight() - barHeights[i], x + AndroidUtilities.dp(4) * i + AndroidUtilities.dp(3), y + getIntrinsicHeight()); canvas.drawRoundRect(rect, AndroidUtilities.dp(.3f), AndroidUtilities.dp(.3f), paint); } } @Override - public void setAlpha(@IntRange(from=0, to=255) int alpha){ + public void setAlpha(@IntRange(from = 0, to = 255) int alpha) { } @Override - public void setColorFilter(@Nullable ColorFilter colorFilter){ + public void setColorFilter(@Nullable ColorFilter colorFilter) { } @Override - public int getIntrinsicWidth(){ - return AndroidUtilities.dp(15+offsetStart); + public int getIntrinsicWidth() { + return AndroidUtilities.dp(15 + offsetStart); } @Override - public int getIntrinsicHeight(){ + public int getIntrinsicHeight() { return AndroidUtilities.dp(12); } @Override - public int getOpacity(){ + public int getOpacity() { return PixelFormat.TRANSLUCENT; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java index cdb9c25e904..4ea6b2712e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java @@ -17,34 +17,22 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ComposeShader; -import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; -import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.SweepGradient; import android.graphics.drawable.Drawable; -import android.text.Editable; -import android.text.InputFilter; -import android.text.InputType; import android.text.TextPaint; import android.text.TextUtils; -import android.text.TextWatcher; import android.util.Property; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; -import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; @@ -75,8 +63,8 @@ import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.ColorPicker; import org.telegram.ui.Components.CubicBezierInterpolator; -import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; @@ -97,7 +85,6 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle private RecyclerListView listView; private BackupImageView backgroundImage; private FrameLayout buttonsContainer; - private Drawable themedWallpaper; private AnimatorSet motionAnimation; private RadialProgress2 radialProgress; private FrameLayout bottomOverlayChat; @@ -125,8 +112,6 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle private float currentIntensity = 0.4f; private float previousIntensity; - private boolean viewCreated; - private PorterDuff.Mode blendMode = PorterDuff.Mode.SRC_IN; private int TAG; @@ -164,328 +149,6 @@ public interface WallpaperActivityDelegate { void didSetNewBackground(); } - private class ColorPicker extends FrameLayout { - - private LinearLayout linearLayout; - - private final int paramValueSliderWidth = AndroidUtilities.dp(20); - - private Paint colorWheelPaint; - private Paint valueSliderPaint; - private Paint circlePaint; - private Drawable circleDrawable; - - private int centerX; - private int centerY; - private int lx; - private int ly; - - boolean ignoreTextChange; - - private Bitmap colorWheelBitmap; - - private EditTextBoldCursor[] colorEditText = new EditTextBoldCursor[2]; - - private int colorWheelRadius; - - private float[] colorHSV = new float[] { 0.0f, 0.0f, 1.0f }; - - private float[] hsvTemp = new float[3]; - private LinearGradient colorGradient; - - private boolean circlePressed; - private boolean colorPressed; - - public ColorPicker(Context context) { - super(context); - - setWillNotDraw(false); - - circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - circleDrawable = context.getResources().getDrawable(R.drawable.knob_shadow).mutate(); - - colorWheelPaint = new Paint(); - colorWheelPaint.setAntiAlias(true); - colorWheelPaint.setDither(true); - - valueSliderPaint = new Paint(); - valueSliderPaint.setAntiAlias(true); - valueSliderPaint.setDither(true); - - linearLayout = new LinearLayout(context); - linearLayout.setOrientation(LinearLayout.HORIZONTAL); - addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.LEFT | Gravity.TOP, 12, 14, 21, 0)); - for (int a = 0; a < 2; a++) { - final int num = a; - - colorEditText[a] = new EditTextBoldCursor(context); - colorEditText[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - colorEditText[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - colorEditText[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - colorEditText[a].setBackgroundDrawable(null); - colorEditText[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - colorEditText[a].setCursorSize(AndroidUtilities.dp(20)); - colorEditText[a].setCursorWidth(1.5f); - colorEditText[a].setSingleLine(true); - colorEditText[a].setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - colorEditText[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); - colorEditText[a].setTransformHintToHeader(true); - colorEditText[a].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); - colorEditText[a].setPadding(0, 0, 0, 0); - if (a == 0) { - colorEditText[a].setInputType(InputType.TYPE_CLASS_TEXT); - colorEditText[a].setHintText(LocaleController.getString("BackgroundHexColorCode", R.string.BackgroundHexColorCode)); - } else { - colorEditText[a].setInputType(InputType.TYPE_CLASS_NUMBER); - colorEditText[a].setHintText(LocaleController.getString("BackgroundBrightness", R.string.BackgroundBrightness)); - } - colorEditText[a].setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - InputFilter[] inputFilters = new InputFilter[1]; - inputFilters[0] = new InputFilter.LengthFilter(a == 0 ? 7 : 3); - colorEditText[a].setFilters(inputFilters); - linearLayout.addView(colorEditText[a], LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, a == 0 ? 0.67f : 0.31f, 0, 0, a != 1 ? 23 : 0, 0)); - colorEditText[a].addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - - } - - @Override - public void afterTextChanged(Editable editable) { - if (ignoreTextChange) { - return; - } - ignoreTextChange = true; - if (num == 0) { - for (int a = 0; a < editable.length(); a++) { - char ch = editable.charAt(a); - if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F' || ch == '#' && a == 0)) { - editable.replace(a, a + 1, ""); - a--; - } - } - if (editable.length() == 0) { - editable.append("#"); - } else if (editable.charAt(0) != '#') { - editable.insert(0, "#"); - } - try { - setColor(Integer.parseInt(editable.toString().substring(1), 16) | 0xff000000); - } catch (Exception e) { - setColor(0xffffffff); - } - WallpaperActivity.this.setBackgroundColor(getColor()); - colorEditText[1].setText("" + (int) (255 * colorHSV[2])); - } else { - int value = Utilities.parseInt(editable.toString()); - if (value > 255 || value < 0) { - if (value > 255) { - value = 255; - } else { - value = 0; - } - editable.replace(0, editable.length(), "" + value); - } - colorHSV[2] = value / 255.0f; - WallpaperActivity.this.setBackgroundColor(getColor()); - int red = Color.red(backgroundColor); - int green = Color.green(backgroundColor); - int blue = Color.blue(backgroundColor); - colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); - } - ColorPicker.this.invalidate(); - ignoreTextChange = false; - } - }); - colorEditText[a].setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_DONE) { - AndroidUtilities.hideKeyboard(textView); - return true; - } - return false; - }); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - int size = Math.min(widthSize, heightSize); - measureChild(linearLayout, MeasureSpec.makeMeasureSpec(widthSize - AndroidUtilities.dp(42), MeasureSpec.EXACTLY), heightMeasureSpec); - setMeasuredDimension(size, size); - } - - @Override - protected void onDraw(Canvas canvas) { - centerX = getWidth() / 2 - paramValueSliderWidth * 2 + AndroidUtilities.dp(11); - centerY = getHeight() / 2 + AndroidUtilities.dp(34); - - canvas.drawBitmap(colorWheelBitmap, centerX - colorWheelRadius, centerY - colorWheelRadius, null); - - float hueAngle = (float) Math.toRadians(colorHSV[0]); - int colorPointX = (int) (-Math.cos(hueAngle) * colorHSV[1] * colorWheelRadius) + centerX; - int colorPointY = (int) (-Math.sin(hueAngle) * colorHSV[1] * colorWheelRadius) + centerY; - - float pointerRadius = 0.075f * colorWheelRadius; - - hsvTemp[0] = colorHSV[0]; - hsvTemp[1] = colorHSV[1]; - hsvTemp[2] = 1.0f; - - drawPointerArrow(canvas, colorPointX, colorPointY, Color.HSVToColor(hsvTemp)); - - lx = centerX + colorWheelRadius + paramValueSliderWidth * 2; - ly = centerY - colorWheelRadius; - int width = AndroidUtilities.dp(9); - int height = colorWheelRadius * 2; - if (colorGradient == null) { - colorGradient = new LinearGradient(lx, ly, lx + width, ly + height, new int[]{Color.BLACK, Color.HSVToColor(hsvTemp)}, null, Shader.TileMode.CLAMP); - } - valueSliderPaint.setShader(colorGradient); - canvas.drawRect(lx, ly, lx + width, ly + height, valueSliderPaint); - drawPointerArrow(canvas, lx + width / 2, (int) (ly + colorHSV[2] * height), Color.HSVToColor(colorHSV)); - } - - private void drawPointerArrow(Canvas canvas, int x, int y, int color) { - int side = AndroidUtilities.dp(13); - circleDrawable.setBounds(x - side, y - side, x + side, y + side); - circleDrawable.draw(canvas); - - circlePaint.setColor(0xffffffff); - canvas.drawCircle(x, y, AndroidUtilities.dp(11), circlePaint); - circlePaint.setColor(color); - canvas.drawCircle(x, y, AndroidUtilities.dp(9), circlePaint); - } - - @Override - protected void onSizeChanged(int width, int height, int oldw, int oldh) { - if (colorWheelRadius != AndroidUtilities.dp(120)) { - colorWheelRadius = AndroidUtilities.dp(120);//Math.max(1, width / 2 - paramValueSliderWidth - AndroidUtilities.dp(20)); - colorWheelBitmap = createColorWheelBitmap(colorWheelRadius * 2, colorWheelRadius * 2); - colorGradient = null; - } - } - - private Bitmap createColorWheelBitmap(int width, int height) { - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - - int colorCount = 12; - int colorAngleStep = 360 / 12; - int[] colors = new int[colorCount + 1]; - float[] hsv = new float[]{0.0f, 1.0f, 1.0f}; - for (int i = 0; i < colors.length; i++) { - hsv[0] = (i * colorAngleStep + 180) % 360; - colors[i] = Color.HSVToColor(hsv); - } - colors[colorCount] = colors[0]; - - SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, colors, null); - RadialGradient radialGradient = new RadialGradient(width / 2, height / 2, colorWheelRadius, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP); - ComposeShader composeShader = new ComposeShader(sweepGradient, radialGradient, PorterDuff.Mode.SRC_OVER); - - colorWheelPaint.setShader(composeShader); - - Canvas canvas = new Canvas(bitmap); - canvas.drawCircle(width / 2, height / 2, colorWheelRadius, colorWheelPaint); - - return bitmap; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_MOVE: - - int x = (int) event.getX(); - int y = (int) event.getY(); - int cx = x - centerX; - int cy = y - centerY; - double d = Math.sqrt(cx * cx + cy * cy); - - if (circlePressed || !colorPressed && d <= colorWheelRadius) { - if (d > colorWheelRadius) { - d = colorWheelRadius; - } - if (!circlePressed) { - getParent().requestDisallowInterceptTouchEvent(true); - } - circlePressed = true; - colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180.0f); - colorHSV[1] = Math.max(0.0f, Math.min(1.0f, (float) (d / colorWheelRadius))); - colorGradient = null; - } - if (colorPressed || !circlePressed && x >= lx && x <= lx + paramValueSliderWidth && y >= ly && y <= ly + colorWheelRadius * 2) { - float value = (y - ly) / (colorWheelRadius * 2.0f); - if (value < 0.0f) { - value = 0.0f; - } else if (value > 1.0f) { - value = 1.0f; - } - colorHSV[2] = value; - if (!colorPressed) { - getParent().requestDisallowInterceptTouchEvent(true); - } - colorPressed = true; - } - if (colorPressed || circlePressed) { - WallpaperActivity.this.setBackgroundColor(getColor()); - if (!ignoreTextChange) { - int red = Color.red(backgroundColor); - int green = Color.green(backgroundColor); - int blue = Color.blue(backgroundColor); - ignoreTextChange = true; - colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); - colorEditText[1].setText("" + (int) (255 * colorHSV[2])); - for (int b = 0; b < 2; b++) { - colorEditText[b].setSelection(colorEditText[b].length()); - } - ignoreTextChange = false; - } - invalidate(); - } - - return true; - case MotionEvent.ACTION_UP: - colorPressed = false; - circlePressed = false; - break; - } - return super.onTouchEvent(event); - } - - public void setColor(int color) { - if (!ignoreTextChange) { - ignoreTextChange = true; - int red = Color.red(color); - int green = Color.green(color); - int blue = Color.blue(color); - Color.colorToHSV(color, colorHSV); - colorEditText[0].setText(String.format("#%02x%02x%02x", (byte) red, (byte) green, (byte) blue)); - colorEditText[1].setText("" + (int) (255 * colorHSV[2])); - for (int b = 0; b < 2; b++) { - colorEditText[b].setSelection(colorEditText[b].length()); - } - ignoreTextChange = false; - } else { - Color.colorToHSV(color, colorHSV); - } - colorGradient = null; - invalidate(); - } - - public int getColor() { - return (Color.HSVToColor(colorHSV) & 0x00ffffff) | 0xff000000; - } - } - private class PatternCell extends BackupImageView implements DownloadController.FileDownloadProgressListener { private RectF rect = new RectF(); @@ -1036,6 +699,7 @@ public void onDraw(Canvas canvas) { } } long id; + String slug = null; long saveId = 0; long access_hash = 0; int color = 0; @@ -1046,6 +710,7 @@ public void onDraw(Canvas canvas) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; saveId = id = wallPaper.id; access_hash = wallPaper.access_hash; + slug = wallPaper.slug; } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; if (selectedPattern != null) { @@ -1057,6 +722,7 @@ public void onDraw(Canvas canvas) { id = -1; } pattern = selectedPattern.id; + slug = selectedPattern.slug; } else { id = -1; } @@ -1079,13 +745,18 @@ public void onDraw(Canvas canvas) { color = 0; } - MessagesController.getInstance(currentAccount).saveWallpaperToServer(path, saveId, access_hash, isBlurred, isMotion, color, currentIntensity, access_hash != 0, 0); + MessagesController.getInstance(currentAccount).saveWallpaperToServer(path, saveId, slug, access_hash, isBlurred, isMotion, color, currentIntensity, access_hash != 0, 0); if (done) { Theme.serviceMessageColorBackup = Theme.getColor(Theme.key_chat_serviceBackground); SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putLong("selectedBackground2", id); + if (!TextUtils.isEmpty(slug)) { + editor.putString("selectedBackgroundSlug", slug); + } else { + editor.remove("selectedBackgroundSlug"); + } editor.putBoolean("selectedBackgroundBlurred", isBlurred); editor.putBoolean("selectedBackgroundMotion", isMotion); editor.putInt("selectedColor", color); @@ -1353,7 +1024,7 @@ public boolean onTouchEvent(MotionEvent event) { }); patternLayout[a].addView(intensitySeekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.TOP | Gravity.LEFT, 9, 153, 9, 0)); } else { - colorPicker = new ColorPicker(context); + colorPicker = new ColorPicker(context, this::setBackgroundColor); patternLayout[a].addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 48)); } } @@ -1391,6 +1062,8 @@ public void onResume() { if (isMotion) { parallaxEffect.setEnabled(true); } + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); } @Override @@ -1955,19 +1628,12 @@ public ThemeDescription[] getThemeDescriptions() { for (int a = 0; a < patternsSaveButton.length; a++) { arrayList.add(new ThemeDescription(patternsSaveButton[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); } - for (int a = 0; a < patternsSaveButton.length; a++) { - arrayList.add(new ThemeDescription(patternsSaveButton[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); + for (int a = 0; a < patternsCancelButton.length; a++) { + arrayList.add(new ThemeDescription(patternsCancelButton[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_fieldOverlayText)); } if (colorPicker != null) { - for (int a = 0; a < colorPicker.colorEditText.length; a++) { - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_HINTTEXTCOLOR | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader)); - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - arrayList.add(new ThemeDescription(colorPicker.colorEditText[a], ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_windowBackgroundWhiteRedText3)); - } + colorPicker.provideThemeDescriptions(arrayList); } arrayList.add(new ThemeDescription(intensitySeekBar, 0, new Class[]{SeekBarView.class}, new String[]{"innerPaint1"}, null, null, null, Theme.key_player_progressBackground)); @@ -1983,8 +1649,10 @@ public ThemeDescription[] getThemeDescriptions() { arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutShadowDrawable, Theme.chat_msgOutMediaShadowDrawable}, null, Theme.key_chat_outBubbleShadow)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextIn)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_messageTextOut)); - arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheck)); - arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckDrawable}, null, Theme.key_chat_outSentCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckSelected)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadDrawable, Theme.chat_msgOutHalfCheckDrawable}, null, Theme.key_chat_outSentCheckRead)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgOutCheckReadSelectedDrawable, Theme.chat_msgOutHalfCheckSelectedDrawable}, null, Theme.key_chat_outSentCheckReadSelected)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_msgMediaCheckDrawable, Theme.chat_msgMediaHalfCheckDrawable}, null, Theme.key_chat_mediaSentCheck)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyLine)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyLine)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java index be6a1bf16b9..c43f64107c9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java @@ -379,6 +379,7 @@ public void onItemClick(int id) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putLong("selectedBackground2", selectedBackground); + editor.remove("selectedBackgroundSlug"); editor.putBoolean("selectedBackgroundBlurred", false); editor.putBoolean("selectedBackgroundMotion", false); editor.putInt("selectedColor", 0); @@ -428,9 +429,9 @@ public void onItemClick(int id) { for (int a = 0; a < dids.size(); a++) { long did = dids.get(a); if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null, true, 0); } fragment1.finishFragment(); } else { @@ -457,7 +458,7 @@ public void onItemClick(int id) { ChatActivity chatActivity = new ChatActivity(args1); presentFragment(chatActivity, true); - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null); + SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessage.toString(), did, null, null, true, null, null, null, true, 0); } }); presentFragment(fragment); @@ -907,7 +908,7 @@ private void fillWallpapersWithCustom() { } return 0; }); - if (Theme.hasWallpaperFromTheme()) { + if (Theme.hasWallpaperFromTheme() && !Theme.isThemeWallpaperPublic()) { if (themeWallpaper == null) { themeWallpaper = new FileWallpaper(Theme.THEME_BACKGROUND_ID, -2, -2); } @@ -1246,10 +1247,8 @@ private void searchImages(final String query, final String offset, boolean searc bingImage.id = result.id; bingImage.type = 0; - bingImage.localUrl = ""; searchResult.add(bingImage); - searchResultKeys.put(bingImage.id, bingImage); } bingSearchEndReached = oldCount == searchResult.size() || nextImagesSearchOffset == null; diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png index f20c8c706dc..9d31f4f94f8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_calendar1.png b/TMessagesProj/src/main/res/drawable-hdpi/input_calendar1.png new file mode 100644 index 00000000000..4aed846c3c8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_calendar1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_calendar2.png b/TMessagesProj/src/main/res/drawable-hdpi/input_calendar2.png new file mode 100644 index 00000000000..f89d4c68b40 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_schedule.png b/TMessagesProj/src/main/res/drawable-hdpi/input_schedule.png new file mode 100644 index 00000000000..83a6a9b3e3e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_schedule.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_schedule.png new file mode 100644 index 00000000000..d4da876f7b5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/preview_custom.png b/TMessagesProj/src/main/res/drawable-hdpi/preview_custom.png new file mode 100644 index 00000000000..377e2b98ffb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/preview_custom.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/preview_dots.png b/TMessagesProj/src/main/res/drawable-hdpi/preview_dots.png new file mode 100644 index 00000000000..2a9fb6ba7a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/preview_dots.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_pin.png index 508056633cb..d4d37a95f7d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_calendar1.png b/TMessagesProj/src/main/res/drawable-mdpi/input_calendar1.png new file mode 100644 index 00000000000..71b8a6bff1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_calendar1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_calendar2.png b/TMessagesProj/src/main/res/drawable-mdpi/input_calendar2.png new file mode 100644 index 00000000000..c582f03c37e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_schedule.png b/TMessagesProj/src/main/res/drawable-mdpi/input_schedule.png new file mode 100644 index 00000000000..4a27f4e1de0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_schedule.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_schedule.png new file mode 100644 index 00000000000..eb3518506c5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/preview_custom.png b/TMessagesProj/src/main/res/drawable-mdpi/preview_custom.png new file mode 100644 index 00000000000..ce256dab2de Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/preview_custom.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/preview_dots.png b/TMessagesProj/src/main/res/drawable-mdpi/preview_dots.png new file mode 100644 index 00000000000..b16b6c43451 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/preview_dots.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_back.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_back.png new file mode 100644 index 00000000000..30cc417630e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_dots.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_dots.png new file mode 100644 index 00000000000..0bcc0ffe463 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_dots.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_mic.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_mic.png new file mode 100644 index 00000000000..82e0db77f32 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_mic.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_in.9.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_in.9.png new file mode 100755 index 00000000000..2049a8446a0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_in.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_out.9.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_out.9.png new file mode 100755 index 00000000000..2303548c2ff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_msg_out.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-nodpi/preview_smile.png b/TMessagesProj/src/main/res/drawable-nodpi/preview_smile.png new file mode 100644 index 00000000000..a402bce66c4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-nodpi/preview_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_pin.png index e564fc17d17..2009266707f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar1.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar1.png new file mode 100644 index 00000000000..97f763fb46d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar2.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar2.png new file mode 100644 index 00000000000..71a0ebd1597 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_schedule.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_schedule.png new file mode 100644 index 00000000000..2fee8859491 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_schedule.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_schedule.png new file mode 100644 index 00000000000..6109f1b6ac5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/preview_custom.png b/TMessagesProj/src/main/res/drawable-xhdpi/preview_custom.png new file mode 100644 index 00000000000..2617bceb2d2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/preview_custom.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/preview_dots.png b/TMessagesProj/src/main/res/drawable-xhdpi/preview_dots.png new file mode 100644 index 00000000000..a5aaf312739 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/preview_dots.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_pin.png index 0c1fe3fabd9..a923b75d91d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar1.png new file mode 100644 index 00000000000..4cd7f75b826 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar2.png new file mode 100644 index 00000000000..01357204812 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_schedule.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_schedule.png new file mode 100644 index 00000000000..c116d43e021 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_schedule.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_schedule.png new file mode 100644 index 00000000000..b6f32af1db3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_schedule.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/preview_custom.png b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_custom.png new file mode 100644 index 00000000000..e5654bdeb69 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_custom.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/preview_dots.png b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_dots.png new file mode 100644 index 00000000000..9d902d1bba0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_dots.png differ diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index a61129ebc25..45fab7a62fd 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -357,6 +357,7 @@ المعذرة، يوجد الكثير من حسابات البوت في هذه القناة. المعذرة، يمكنك إضافة أول 200 عضو للقناة فقط. يمكن لعدد غير محدود من الناس الانضمامُ للقناة عبرَ رابطها. المعذرة، أنت عضو في الكثير من المجموعات والقنوات. الرجاء مغادرة بعض منها قبل إنشاء واحدة جديدة. + Sorry, you are a member of too many groups and channels. Please leave some before joining a new one. un1 أضافك لهذه القناة انضممتَ للقناة قمتَ بالانضمام لهذه المجموعة @@ -690,6 +691,7 @@ استعراض فوري فتح المجموعة عرض الخلفية + عرض النمط فتح القناة عرض الرسالة سيتم تفعيل النمط المظلم في الليل تلقائيًا @@ -711,6 +713,7 @@ ملف الكاميرا ما من رسائل هنا بعد... + ما من رسائل مجدولة هنا بعد... تم التحويل من من %1$s @@ -718,6 +721,7 @@ لا توجد رسائل أحدث الرسالة الرسالة + Schedule message مشاركة رقم هاتفي مشاركة جهة اتصالي إضافة لجهات الاتصال @@ -879,12 +883,27 @@ تم تفعيل الوضع البطيء. يمكنك إرسال\nرسالتك التالية خلال %1$s انقر لأخذ صورة، اضغط باستمرار لتصوير مقطع مرئي إرسال بدون صوت + إرسال الآن> + إعادة جدولة + اليوم + Schedule + جدولة الرسالة + الرسائل المجدولة + التذكيرات + إنشاء تذكير + الرسائل المجدولة لـ %1$s + المعذرة، لا يمكنك جدولة أكثر من 100 رسالة. + This action will become available after the message is published. + Voting will become available after the message is published. + 📅 تذكير عيّن %1$s عداد التدمير الذاتي ليصبح %2$s قمت بتعيين عداد التدمير الذاتي ليصبح %1$s %1$s عطّل عداد التدمير الذاتي لقد عطلتَ عداد التدمير الذاتي لديك رسالة جديدة + 📅 أنت: %1$s + 📅 أنت %1$s: %2$s أرسل لك %1$s %2$s أرسل لك %1$s حُزمة وسائط @@ -1202,7 +1221,7 @@ أزرق غامق غرافيت ثلجي - أزرق + أحادي هل ترغب حقًا في حذف هذا النمط؟ ملف النمط غير صحيح أدخل اسم النمط @@ -1212,6 +1231,8 @@ لون النمط الأنماط الافتراضية الأنماط المخصصة + تعيين رابط + رابط النمط عرض قائمة المحادثات خطين اثنين ثلاثة خطوط @@ -1221,9 +1242,44 @@ اختر لونًا الأنماط عرض جميع الأنماط + لم يتم العثور على النمط + Sorry, this color theme doesn’t support your device yet. إنشاء نمط جديد + New Theme + تعديل النمط اضغط على أيقونة الألوان لاستعراض قائمة الخيارات في كل شاشة - ثم قم بتعديلها. يمكنك إنشاء النمط الخاص بك عبر تغيير الألوان داخل التطبيق.\n\nيمكنك العودة إلى نمط تيليجرام الافتراضي في أي وقت من هنا. + يمْكنك استخدام الأحرف والأرقام الإنجليزية، والشرطاتِ السفلية.\nالحد الأدنى هو 5 خانات. + Your theme will be updated for all users each time you change it. Anyone can install it using this link:\n%1$s + Anyone can install your theme using this link. When you change the theme, it will be updated for all users who installed it.\n\nThe theme will be based on your currently selected theme and wallpaper. + You can change the link of your theme.\n\nTheme links must be longer than 5 characters and can use a-z, 0-9 and underscores. + Sorry, theme name is invalid. + المعذرة، هذا الرابط غير مقبول. + يجب ألا يقل الرابط عن 5 حروف. + لا يمكن أن يتخطى الرابط 64 حرفًا كحد أقصى. + عذرًا، لا يمكن للرابط بأن يبدأ برقم. + يتم التحقق من الرابط... + عذرًا، هذا الرابط محجوز. + %1$s متاح. + الرابط + Name + Reinhardt + هل أنت جاهز أم أنك تحتاج لبعض الوقت؟ + سنخبرهم بالطبع! هل تتذكر كيف انتهت آخر مفاجأة؟ + بلى، أنا جاهز للانطلاق في أي وقت! هل سنخبرهم بقدومنا أم نجعلها مفاجأة؟ + Lucio + "أنا متحمس للغاية! " + هلا بالخميس + معن برغوث + Bob Harris + Good morning! 👋 + Do you know what time it is? + It\'s morning in Tokyo 😎 + Use a different theme + You can also use an existing custom theme as a foundation for your theme. + Choose theme + تصدير + Create تم تعيين كل الإشعارات إلى الوضع الافتراضي هل ترغب حقًا في إعادة تعيين جميع إعدادات الإشعارات إلى الوضع الافتراضي؟ @@ -2093,7 +2149,9 @@ يمكنك إضافة مستخدمين أو مجموعات بأكملها كاستثناءات ليتجاوزوا القيم في الأعلى. رقم الهاتف من يمْكنه رؤية رقم هاتفي؟ + من يمْكنه إيجادي عبر رقم هاتفي؟ المستخدمون الذين يملكون رقمك محفوظًا في دليل عناوينهم سيتمكنون من رؤيته في تيليجرام. + Users who add your number to their contacts will see it on Telegram only if they are your contacts. يمكنك إضافة مستخدمين أو مجموعات بأكملها كاستثناءات ليتجاوزوا القيم في الأعلى. الرسائل المحوَّلة رابط إلى حسابك @@ -2859,6 +2917,12 @@ %1$d عناصر محددة %1$d عنصرًا محددًا %1$d عنصر محدد + %1$d شخص يستخدم هذا النمط + شخص واحد يستخدم هذا النمط + شخصان يستخدمان هذا النمط + %1$d أشخاص يستخدمون هذا النمط + %1$d شخصًا يستخدم هذا النمط + %1$d شخص يستخدم هذا النمط مجموعة قناة @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s الساعة %2$s - MMM d EEE + d MMM + yyyy MMM d + \'إرسال اليوم عند\' HH:mm + \'إرسال بتاريخ\' d MMM \'عند\' HH:mm + \'إرسال بتاريخ\' d MMM yyyy \'عند\' HH:mm + \'Remind today at\' HH:mm + \'Remind on\' MMM d \'at\' HH:mm + \'Remind on\' MMM d yyyy \'at\' HH:mm diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 6ec4be24e71..be749a41ecd 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -357,6 +357,7 @@ Es gibt bereits zu viele Bots. "Du kannst nur die ersten 200 Leute einladen, aber unbegrenzt viele können dem Kanal über den Einladungslink beitreten. " Du bist Mitglied in zu vielen Gruppen und Kanälen. Bitte verlasse einige, damit du eine neue erstellen kannst. + Du bist bereits in zu vielen Gruppen und Kanälen. Bitte erst einige verlassen. un1 hat dich hinzugefügt Du bist dem Kanal beigetreten Du bist der Gruppe beigetreten @@ -628,7 +629,7 @@ Nachrichten anheften Alle Aktionen Neue Ausnahmen - Neue Admins + Adminrechte Neue Mitglieder Gruppen-Info Kanal-Info @@ -690,6 +691,7 @@ SCHNELLANSICHT GRUPPE ANZEIGEN HINTERGRUND ANZEIGEN + THEMA ANSEHEN KANAL ÖFFNEN NACHRICHT ANZEIGEN Das dunkle Farbthema wird Nachts automatisch aktiviert @@ -711,6 +713,7 @@ Datei Kamera Noch keine Nachrichten... + Noch keine geplanten Nachrichten... Weitergeleitete Nachricht Von Von %1$s @@ -718,6 +721,7 @@ Keine aktuellen Nachricht Nachricht + Nachricht planen MEINE NUMMER TEILEN Meine Nummer teilen Zu Kontakten hinzufügen @@ -879,12 +883,27 @@ Langsamer Modus aktiv.\nBitte warte %1$s. Tippen für Foto, halten für Video Ohne Ton senden + Jetzt senden> + Umplanen + Heute + Planen + Nachricht planen + Später senden + Erinnerungen + Eine Erinnerung festlegen + Geplant am %1$s + Mehr als 100 Nachrichten kann man nicht planen. + Diese Aktion wird erst nach Veröffentlichung der Nachricht verfügbar sein. + Das Abstimmen wird erst nach Veröffentlichung der Nachricht verfügbar sein. + 📅 Erinnerung %1$s hat den Selbstzerstörungs-Timer auf %2$s gesetzt Du hast den Selbstzerstörungs-Timer auf %1$s gesetzt %1$s hat den Selbstzerstörungs-Timer deaktiviert Du hast den Selbstzerstörungs-Timer deaktiviert Du hast eine neue Nachricht + 📅 Du: %1$s + 📅 Du %1$s: %2$s %1$s hat dir %2$s gesendet %1$s hat dir ein Album gesendet @@ -1201,8 +1220,8 @@ Dunkel Dunkel (Blau) Graphit - Arktisblau - Blau + Arktis + Mono Möchtest du wirklich dieses Thema löschen? Themen-Datei ist fehlerhaft. Einen Namen festlegen @@ -1212,6 +1231,8 @@ Farbthema Eingebaute Themen Eigene Themen + Link festlegen + Link zum Thema Ansicht der Chatliste Zwei Zeilen Drei Zeilen @@ -1221,9 +1242,44 @@ Farbe wählen Farbthemen Alle Themen zeigen + Thema nicht gefunden + Dieses Farbschema unterstützt dein Gerät leider noch nicht. Neues Thema erstellen + Neues Thema + Thema bearbeiten Tippe auf das kleine Palettensymbol um eine Auswahl des jeweiligen Bildschirms anzuzeigen und wähle deine Wunschfarben. Du kannst dein eigenes Farbthema erstellen, indem du die Farben innerhalb der App änderst.\n\nJederzeit kannst du hier zum Standard-Farbthema von Telegram zurückkehren. + Erlaubt sind a-z, 0-9 und Unterstriche.\nDie Mindestlänge beträgt 5 Zeichen. + Sobald du dein Thema anpasst, aktualisiert es sich bei allen Nutzern, die es ebenfalls benutzen.\n\nJeder kann es über diesen Link installieren:\n%1$s + Jeder kann dein Thema über diesen Link installieren. Wenn du das Thema änderst, wird es für alle Nutzer aktualisiert, die es installiert haben.\n\nDas Farbthema wird auf dem aktuell ausgewählten Thema und dem Hintergrundbild basieren. + Du kannst den Link deines Themas ändern.\n\nLinks müssen länger als 5 Zeichen sein und dürfen a-z, 0-9 und Unterstriche enthalten. + Der Name ist leider ungültig. + Dieser Link ist leider ungültig. + Ein Link muss mindestens Zeichen haben. + Link darf 64 Zeichen nicht überschreiten. + Links dürfen nicht mit einer Zahl beginnen. + Prüfe Link... + Dieser Link ist bereits vergeben. + %1$s ist verfügbar. + Link + Name + Reinhardt + Reinhardt, du brauchst unbedingt neue Musik 🎶. + Ich kann dich jetzt nicht ernst nehmen. + Oh je, ihr mit eurer Techno-Musik! Genießt lieber Klassiker, wie Hasselhoff! + Lucio + Auf geht\'s! + True Survivor + David Hasselhoff + Bob Harris + Guten Morgen! 👋 + Wie spät ist es gerade? + Es ist Morgen in Tokio 😎 + Ein anderes Thema wählen + Du kannst auch ein bestehendes eigenes Thema als Grundlage für dein Thema verwenden. + Thema wählen + Exportieren + Erstellen Einstellungen wurden zurückgesetzt Möchtest du wirklich alle Benachrichtigungseinstellungen auf die Standardeinstellungen zurücksetzen? @@ -1448,8 +1504,8 @@ Dringend Niemals Erneut benachrichtigen - Du kannst deine Telefonnummer hier ändern. Dein Konto und alle Daten in der Telegram-Cloud, also Nachrichten, Medien, Kontakte, etc. werden auf das neue Konto übertragen.\n\n**Wichtig:** Alle deine Kontakte erhalten deine **neue Nummer** ihrem Telefonbuch hinzugefügt, sofern sie deine alte Nummer gespeichert hatten und du sie nicht blockiert hattest. - Deinen Kontakten wird deine neue Nummer ihrem Telefonbuch hinzugefügt, sofern sie deine alte Nummer gespeichert hatten und du sie nicht blockiert hattest. + Du kannst deine Telefonnummer hier ändern. Dein Konto und alle Daten in der Telegram-Cloud, also Nachrichten, Medien, Kontakte, etc. werden auf das neue Konto übertragen. + Nutzer werden deine neue Nummer sehen, wenn sie diese in ihrem Adressbuch gespeichert haben oder deine Einstellungen es erlauben. Unter Einstellungen > Privatsphäre und Sicherheit > Telefonnummer kannst du es jederzeit anpassen. Nummer ändern Nummer ändern Neue Nummer @@ -2093,7 +2149,9 @@ Du kannst Kontakte oder ganze Gruppen hinzufügen, für die eine Ausnahme gemacht werden soll. Telefonnummer Wer darf meine Nummer sehen? - Nutzer, die bereits deine Nummer in ihren Kontakten gespeichert haben, sehen sie auch bei Telegram. + Wer darf mich unter meiner Nummer finden? + Nutzer, die deine Nummer in ihren Kontakten gespeichert haben, sehen sie auch bei Telegram. + Nutzer, die deine Nummer zu ihren Kontakten hinzufügen, sehen sie bei Telegram nur, wenn sie in deinen Kontakten gespeichert sind. Fügst du einzelne Nutzer oder eine komplette Gruppe als Ausnahme hinzu, werden die festgelegten Einstellungen oben überschrieben. Weiterleitungen Verknüpfung mit deinem Konto @@ -2859,6 +2917,12 @@ %1$d Medien ausgewählt %1$d Medien ausgewählt %1$d Medien ausgewählt + %1$d Leute benutzen dieses Thema + %1$d Person benutzt dieses Thema + %1$d Leute benutzen dieses Thema + %1$d Leute benutzen dieses Thema + %1$d Leute benutzen dieses Thema + %1$d Leute benutzen dieses Thema Gruppe Kanal @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s um %2$s - EEE d MMM + d MMM + d MMM yyyy + \'Heute um\' HH:mm \'senden\' + \'Am\' d MMM \'um\' HH:mm \'senden\' + \'Am\' d MMM yyyy \'um\' HH:mm \'senden\' + \'Heute um\' HH:mm \'erinnern\' + \'Am\' d MMM \'um\' HH:mm \'erinnern\' + \'Am\' d MMM yyyy \'um\' HH:mm \'erinnern\' diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 330bdd015a6..f0652744f47 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -357,6 +357,7 @@ Lo sentimos, hay demasiados bots en el canal. Lo sentimos, sólo puedes añadir a los primeros 200 miembros a un canal. Sin embargo, una cantidad ilimitada de personas pueden unirse por el enlace del canal. Lo sentimos, eres miembro de demasiados grupos y canales. Por favor, sal de algunos antes de crear uno nuevo. + Lo sentimos, eres miembro de demasiados grupos y canales. Por favor, sal de algunos antes de unirte. un1 te añadió a este canal Te uniste a este canal Te uniste a este grupo @@ -380,7 +381,7 @@ %1$s publicó un audio %1$s publicó un sticker %1$s publicó un %2$s sticker - ¿Quién puede invitar? + ¿Quién puede añadir miembros? Todos Administradores Tu publicación será notificada @@ -628,7 +629,7 @@ Anclar mensajes Todas las acciones Nuevas excepciones - Nuevos administradores + Permisos de administrador Nuevos miembros Información del grupo Información del canal @@ -690,6 +691,7 @@ INSTANT VIEW VER GRUPO VER FONDO + VER TEMA VER CANAL VER MENSAJE El tema oscuro se usará automáticamente en la noche @@ -711,6 +713,7 @@ Archivo Cámara Aún no hay mensajes... + Aún no hay mensajes programados… Mensaje reenviado De De %1$s @@ -718,6 +721,7 @@ No hay recientes Mensaje Mensaje + Programar mensaje COMPARTIR MI NÚMERO DE TELÉFONO Compartir mi número Añadir a contactos @@ -879,12 +883,27 @@ Modo lento activado. Puedes enviar\ntu próximo mensaje en %1$s. Toca para foto, mantén para video Enviar sin sonido + Enviar ahora> + Reprogramar + Hoy + Programar + Programar mensaje + Mensajes programados + Recordatorios + Establecer recordatorio + Programado para el %1$s + Lo sentimos, no puedes programar más de 100 mensajes. + Esta acción estará disponible una vez publicado el mensaje. + La votación estará disponible una vez publicado el mensaje. + 📅 Recordatorio %1$s activó la autodestrucción en %2$s Activaste la autodestrucción en %1$s %1$s desactivó la autodestrucción Desactivaste la autodestrucción Tienes un mensaje nuevo + 📅 Tú: %1$s + 📅 Tú %1$s: %2$s %1$s te envió %2$s %1$s te envió un álbum @@ -1124,7 +1143,7 @@ Un alias debe tener al menos 5 caracteres. El alias no debe exceder los 32 caracteres. Lo sentimos, un alias no puede comenzar con un número. - Puedes elegir un alias en **Telegram**. Si lo haces, otras personas te podrán encontrar por ese alias y contactarte sin saber tu número de teléfono.\n\nPuedes usar **a–z**, **0–9** y guiones bajos. La longitud mínima es de **5** caracteres. + Puedes elegir un alias en **Telegram**. Si lo haces, otras personas te podrán encontrar por ese alias y contactarte sin saber tu número de teléfono.\n\nPuedes usar **a–z**, **0–9** y guiones bajos.\nLa longitud mínima es de **5** caracteres. Este enlace abre un chat contigo:\n%1$s Verificando alias... %1$s está disponible. @@ -1201,8 +1220,8 @@ Oscuro Azul oscuro Grafito - Azul ártico - Azul + Ártico + Mono ¿Quieres eliminar este tema? Archivo de tema incorrecto Pon el nombre del tema @@ -1212,6 +1231,8 @@ Tema Temas incorporados Temas personalizados + Establecer enlace + Enlace del tema Vista de lista de chats Dos líneas Tres líneas @@ -1221,9 +1242,44 @@ Elegir color Temas Mostrar todos los temas + Tema no encontrado + Lo sentimos, este tema aún no es compatible con tu dispositivo. Crear nuevo tema + Nuevo tema + Editar tema Toca sobre el icono de la paleta de colores para ver la lista de elementos en cada ventana y editarlos. Puedes crear tu propio tema cambiando los colores dentro de la aplicación.\n\nSiempre puedes volver al tema por defecto de Telegram aquí. + Puedes usar a-z, 0-9 y guiones bajos.\nLa longitud mínima es de 5 caracteres. + Tu tema será actualizado para todos los usuarios cada vez que lo modifiques. Cualquiera puede instalarlo usando este enlace:\n%1$s + Cualquiera puede instalar tu tema usando este enlace. Cuando modifiques el tema, será actualizado para todos los usuarios que lo hayan instalado.\n\nEl tema se basará en tus colores y fondo de chat seleccionados actualmente. + Puedes cambiar el enlace de tu tema.\n\nLos enlaces de temas deben tener más de 5 caracteres y pueden usar a-z, 0-9 y guiones bajos. + Lo siento, el nombre del tema no es válido. + Lo sentimos, este enlace no es válido. + Un enlace debe tener al menos 5 caracteres. + El enlace no debe exceder los 64 caracteres. + Lo sentimos, el enlace no puede comenzar con un número. + Comprobando enlace… + Lo sentimos, este enlace ya está ocupado. + %1$s está disponible. + Enlace + Nombre + Reinhardt + Reinhardt, necesitamos encontrarte algunas nuevas canciones 🎶. + Ya no te puedo tomar en serio. + ¡Ah! Los niños de hoy en día con la música tecno. Disfruten los clásicos, ¡como Hasselhoff! + Lúcio + ¡Dale! ¡VIVO para esto! + True Survivor + David Hasselhoff + Bob Harris + ¡Buenos días! 👋 + ¿Sabes qué hora es? + Es de mañana en Tokio 😎 + Usar un tema diferente + También puedes usar un tema personalizado existente como base para tu tema. + Elegir tema + Exportar + Crear Todos los ajustes de notificaciones fueron restablecidos a los valores por defecto ¿Quieres restablecer todos los ajustes de notificaciones? @@ -1448,8 +1504,8 @@ Urgente Nunca Repetir notificaciones - Puedes cambiar tu número de Telegram aquí. Tu cuenta y todos tus datos de la nube, mensajes, archivos, grupos, contactos, etc., se moverán al nuevo número.\n\n**Importante:** Todos tus contactos de Telegram tendrán tu **nuevo número** añadido a sus agendas de contactos, siempre que hayan tenido tu número viejo y no los hayas bloqueado en Telegram. - Todos tus contactos de Telegram tendrán tu número nuevo añadido a sus agendas de contactos, siempre que hayan tenido tu número viejo y no los hayas bloqueado en Telegram. + Puedes cambiar tu número de Telegram aquí. Tu cuenta y todos tus datos de la nube, mensajes, archivos, grupos, contactos, etc., se moverán al nuevo número. + Los usuarios verán tu nuevo número si lo tienen en sus agendas de contactos o si tus ajustes de privacidad lo permiten. Puedes modificar esto en Ajustes > Privacidad y seguridad > Número de teléfono. Cambiar número Cambiar número Nuevo número @@ -2092,15 +2148,17 @@ Puedes restringir quién puede ver tu foto de perfil con gran precisión. Puedes añadir usuarios o grupos como excepciones que anularán los ajustes de arriba. Número de teléfono - ¿Quién puede ver mi número de teléfono? - Los usuarios que ya tienen tu número guardado en sus contactos también lo verán en Telegram. + ¿Quién puede ver mi número? + ¿Quién puede encontrarme por mi número? + Los usuarios que tengan tu número guardado en sus contactos también lo verán en Telegram. + Los usuarios que añadan tu número a sus contactos lo verán en Telegram sólo si son tus contactos. Puedes añadir usuarios o grupos como excepciones que anularán los ajustes de arriba. Mensajes reenviados Enlace a tu cuenta Enlace según los ajustes de abajo Sin un enlace a tu cuenta ¿Quién puede añadir un enlace a mi cuenta al reenviar mis mensajes? - Los mensajes que envías no enlazarán a tu cuenta al ser reenviados a otros chats. + Los mensajes que envíes no enlazarán a tu cuenta al ser reenviados a otros chats. Puedes añadir usuarios o grupos como excepciones que anularán los ajustes de arriba. Reinhardt, necesitamos encontrarte algunas nuevas canciones 🎶. Peer-to-peer @@ -2137,7 +2195,7 @@ ¿Quién puede ver mi última conexión? Añadir excepciones Añadir a excepciones - No verás el estado de última conexión ni el de en línea de las personas con las que no compartes el tuyo. En su lugar, se mostrarán conexiones indeterminadas (recientemente, hace unos días, hace unas semanas). + No verás el estado de última conexión ni el de en línea de las personas con las que no compartas el tuyo. En su lugar, se mostrarán conexiones indeterminadas (recientemente, hace unos días, hace unas semanas). Cambiaste algunos ajustes de privacidad. ¿Aplicar cambios? Compartir con No compartir con @@ -2859,6 +2917,12 @@ %1$d archivos multimedia seleccionados %1$d archivos multimedia seleccionados %1$d archivos multimedia seleccionados + %1$d personas están usando este tema + %1$d persona está usando este tema + %1$d personas están usando este tema + %1$d personas están usando este tema + %1$d personas están usando este tema + %1$d personas están usando este tema Grupo Canal @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s a las %2$s - EEE d MMM + d \'de\' MMM + d \'de\' MMM \'de\' yyyy + \'Enviar hoy a las\' HH:mm + \'Enviar el\' d \'de\' MMM \'a las\' HH:mm + \'Enviar el\' d \'de\' MMM \'de\' yyyy \'a las\' HH:mm + \'Recordar hoy a las\' HH:mm + \'Recordar el\' d \'de\' MMM \'a las\' HH:mm + \'Recordar el\' d \'de\' MMM \'de\' yyyy \'a las\' HH:mm diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 209749fb5fd..d6e8a474c5b 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -259,8 +259,8 @@ Nuovo canale Nome del canale Aggiungi contatti al tuo canale - Se imposti un link permanente, le altre persone potranno trovare il tuo canale e unirsi.\n\nPuoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è di 5 caratteri. - Se imposti un link permanente, le altre persone potranno trovare il tuo gruppo e unirsi.\n\nPuoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è di 5 caratteri. + Se imposti un link permanente, le altre persone potranno trovare il tuo canale e unirsi.\n\nPuoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è 5 caratteri. + Se imposti un link permanente, le altre persone potranno trovare il tuo gruppo e unirsi.\n\nPuoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è 5 caratteri. link Le persone possono unirsi al tuo canale seguendo questo link. Puoi revocare il link in ogni momento. Le persone possono unirsi al tuo gruppo seguendo questo link. Puoi revocare il link in ogni momento. @@ -357,6 +357,7 @@ Spiacenti, troppi bot in questo canale. Spiacenti, puoi aggiungere solo i primi 200 membri a un canale. Ricorda che un numero illimitato di persone potrebbe unirsi tramite il link del canale. Spiacenti, sei membro di troppi gruppi e canali. Per favore lasciane qualcuno prima di crearne uno nuovo. + Spiacenti, sei membro di troppi gruppi e canali. Per favore lasciane qualcuno prima di unirti ad uno. un1 ti ha aggiunto a questo canale Ti sei unito a questo canale Ti sei unito a questo gruppo @@ -386,7 +387,7 @@ I post saranno notificati ai membri I membri riceveranno una notifica silenziosa Firma messaggi - " Aggiungi i nomi degli amministratori nei messaggi da loro pubblicati." + Aggiungi i nomi degli amministratori nei messaggi che pubblicano. Permessi amministratore Titolo personalizzato Sarà mostrato un titolo personalizzato a tutti i membri invece di \'%1$s\'. @@ -403,12 +404,12 @@ Trasferisci proprietà canale Controllo di sicurezza Puoi trasferire questo gruppo a **%1$s** solo se hai: - Puoi trasferire questo canale a **%1$s** solo se lo hai: - La **Verifica in due passaggi** abilitata da più di **7 giorni**. + Puoi trasferire questo canale a **%1$s** solo se hai: + La **Verifica in due passaggi** attivata da più di **7 giorni**. Eseguito l\'accesso su questo dispositivo da più di **24 ore**. Per favore ritorna più tardi. Imposta password - Questo trasferirà tutti i **diritti di proprietà** per **%1$s** a **%2$s*. + Questo trasferirà tutti i **diritti di proprietà** per **%1$s** a **%2$s**. Cambia proprietario **%1$s** è ora il proprietario del gruppo. **%1$s** è ora il proprietario del canale. @@ -504,7 +505,7 @@ DISCUTI canale Modalità lenta - Spenta + No %1$ds %1$dm %1$dh @@ -628,7 +629,7 @@ Fissare messaggi Tutte le azioni Nuove eccezioni - Nuovi amministratori + Diritti di amministrazione Nuovi membri Info gruppo Info canale @@ -690,6 +691,7 @@ APERTURA RAPIDA APRI GRUPPO VISUALIZZA SFONDO + VISUALIZZA TEMA APRI CANALE APRI MESSAGGIO Il tema scuro si attiverà automaticamente durante la notte @@ -711,6 +713,7 @@ File Foto Ancora nessun messaggio... + Ancora nessun messaggio programmato qui... Messaggio inoltrato Da Da %1$s @@ -718,6 +721,7 @@ Nessun recente Messaggio Messaggio + Programma messaggio CONDIVIDI IL MIO NUMERO Condividi il mio contatto Aggiungi ai contatti @@ -879,12 +883,27 @@ La modalità lenta è attiva. Puoi inviare\nil prossimo messaggio tra %1$s Tocca per le foto, tieni premuto per i video Invia senza suono + Invia ora> + Riprogramma + Oggi + Programma + Programma messaggio + Messaggi programmati + Promemoria + Imposta un promemoria + Programmato per il %1$s + Spiacenti, non puoi programmare più di 100 messaggi. + Questa azione sarà disponibile dopo la pubblicazione del messaggio. + La votazione sarà disponibile dopo la pubblicazione del messaggio. + 📅 Promemoria %1$s ha impostato il timer di autodistruzione a %2$s Hai impostato il timer di autodistruzione a %1$s %1$s ha disattivato il timer di autodistruzione Hai disattivato il timer di autodistruzione Hai un nuovo messaggio + 📅 Tu: %1$s + 📅 Tu %1$s: %2$s %1$s ti ha inviato %2$s %1$s ti ha inviato un album @@ -900,7 +919,7 @@ %1$s ti ha inviato una posizione %1$s ti ha inviato una posizione attuale %1$s ti ha invitato a giocare %2$s - %1$s ha totalizzato %3$s nel gioco %2$s + %1$s ha totalizzato %3$s a %2$s %1$s ti ha inviato un file %1$s ti ha inviato una GIF %1$s ti ha inviato un messaggio vocale @@ -917,7 +936,7 @@ %1$s ha inviato una posizione nel gruppo %2$s %1$s ha condiviso una posizione attuale nel gruppo %2$s %1$s ha invitato il gruppo %2$s a giocare %3$s - %1$s ha totalizzato %4$s nel gioco %3$s nel gruppo %2$s + %1$s ha totalizzato %4$s a %3$s nel gruppo %2$s %1$s ha inviato un file nel gruppo %2$s %1$s ha inviato una GIF nel gruppo %2$s %1$s ha inviato una fattura nel gruppo %2$s per %3$s @@ -1201,8 +1220,8 @@ Scuro Blu scuro Grafite - Blu artico - Blu + Artico + Mono Sei sicuro di voler eliminare questo tema? File tema non valido Inserisci il nome del tema @@ -1212,6 +1231,8 @@ Tema Temi predefiniti Temi personalizzati + Imposta link + Link tema Visualizzazione lista chat Due righe Tre righe @@ -1221,9 +1242,44 @@ Seleziona colore Temi Mostra tutti i temi + Tema non trovato + Spiacenti, questo tema non supporta ancora il tuo dispositivo. Crea nuovo tema + Nuovo tema + Modifica tema Tocca sull\'icona della tavolozza per vedere la lista degli elementi in ogni schermata - e modificarli. Puoi creare il tuo tema cambiando i colori all\'interno dell\'app.\n\nPuoi sempre tornare al tema Telegram di default qui. + Puoi usare a-z, 0-9 e underscore.\nLa lunghezza minima è 5 caratteri. + Il tuo tema sarà aggiornato per tutti gli utenti ogni volta che lo modifichi. Chiunque può installarlo usando questo link:\n%1$s + Chiunque può installare il tuo tema utilizzando questo link. Quando modifichi il tema, sarà aggiornato per tutti gli utenti che lo hanno installato.\n\nIl tema sarà basato sul tema e sullo sfondo attualmente selezionati. + Puoi modificare il link del tuo tema.\n\nI link dei temi devono essere più lunghi di 5 caratteri e possono usare a-z, 0-9 e underscore. + Spiacenti, nome del tema non valido. + Spiacenti, questo link non è valido. + Un link deve avere almeno 5 caratteri. + Il link non deve avere più di 64 caratteri. + Spiacenti, il link non può iniziare con un numero. + Controllo il link... + Spiacenti, questo link è già stato preso. + %1$s è disponibile. + Link + Nome + Reinhardt + Reinhardt, dobbiamo trovarti qualche nuova canzone 🎶. + Non posso prenderti sul serio adesso. + Ah, i ragazzi di oggi con la musica techno! Godetevi i classici, come Hasselhoff! + Lucio + Coraggio! Io VIVO per questo! + True Survivor + David Hasselhoff + Bob Harris + Buongiorno! 👋 + Sai che ore sono? + È mattina a Tokyo 😎 + Usa un tema diverso + Puoi anche usare un tema personalizzato esistente come base per il tuo tema. + Scegli tema + Esporta + Crea Tutte le impostazioni di notifica sono state ripristinate Sei sicuro di voler ripristinare tutte le impostazioni di notifica sui valori predefiniti? @@ -1448,8 +1504,8 @@ Urgente Mai Ripeti notifiche - Puoi cambiare il tuo numero di telefono qui. Il tuo account e tutti i tuoi dati cloud — messaggi, file, contatti, etc. saranno trasferiti sul nuovo numero.\n\n**Importante:** a tutti i tuoi contatti di Telegram verrà aggiunto il tuo **nuovo numero** ai contatti, purché abbiano il tuo vecchio numero e tu non li abbia bloccati su Telegram. - Tutti i tuoi contatti Telegram avranno il tuo nuovo numero tra i loro contatti, purché abbiano il tuo vecchio numero e tu non li abbia bloccati su Telegram. + Puoi cambiare il tuo numero di telefono qui. Il tuo account e tutti i tuoi dati cloud — messaggi, media, contatti, etc. saranno trasferiti sul nuovo numero + Gli utenti vedranno il tuo nuovo numero se lo hanno nella loro rubrica o se le tue impostazioni sulla privacy lo consentono. Puoi modificarle in Impostazioni > Privacy e sicurezza > Numero di telefono. Cambia numero Cambia numero Nuovo numero @@ -1715,7 +1771,7 @@ Seleziona data di nascita Eliminare il selfie? Il documento deve contenere la tua foto, il nome, il cognome, la data di nascita, il numero del documento, il paese di emissione e la data di scadenza. - "Sei sicuro di voler annullare tutte le informazione che hai inserito? " + "Sei sicuro di voler scartare tutte le informazione che hai inserito? " Scarta Scansioni Elimina documento @@ -1905,7 +1961,7 @@ Stai condividendo la tua posizione attuale in %1$s Scegli per quanto tempo %1$s vedrà la tua posizione precisa. Scegli per quanto tempo le persone in questa chat vedranno la tua posizione attuale. - Sembra che il tuo GPS sia disattivato, per favore attivalo per utilizzare le funzioni che necessitano della posizione. + Sembra che il tuo GPS sia disattivato, per favore attivalo per usare le funzioni che necessitano della posizione. Persone vicine Aggiungi persone vicine Aggiungi rapidamente persone vicine che stanno guardando questa sezione e scopri chat di gruppo locali.\n\nPer favore concedi l\'accesso alla posizione per abilitare questa funzione. @@ -2092,15 +2148,17 @@ Puoi decidere chi può vedere la tua foto profilo con precisione granulare. Puoi aggiungere utenti o interi gruppi come eccezioni che annulleranno le impostazioni precedenti. Numero di telefono - Chi può vedere il mio numero di telefono? - Gli utenti che hanno già il tuo numero salvato in rubrica lo vedranno anche su Telegram. + Chi può vedere il mio numero? + Chi può trovarmi con il mio numero + Gli utenti che hanno il tuo numero salvato in rubrica lo vedranno anche su Telegram. + Gli utenti che aggiungono il tuo numero ai loro contatti lo vedranno su Telegram solo se sono tuoi contatti. Puoi aggiungere utenti o interi gruppi come eccezioni che annulleranno le impostazioni precedenti. Messaggi inoltrati Collegato al tuo account Collegato se permesso dalle impostazioni Non collegato al tuo account Chi può aggiungere un collegamento al mio account quando inoltra i miei messaggi? - Quando inoltrati in altre chat, i tuoi messaggi non saranno collegati al tuo account. + I messaggi che invii non saranno ricollegati al tuo account quando inoltrati da altri utenti. Puoi aggiungere utenti o interi gruppi come eccezioni che annulleranno le impostazioni precedenti. Reinhardt, dobbiamo trovarti qualche nuova canzone 🎶. Peer-to-peer @@ -2112,7 +2170,7 @@ Siti web in cui hai usato Telegram per accedere. Info di spedizione Info di pagamento - Elimina tutte le bozze + Elimina tutte le bozze cloud Tutti I miei contatti Nessuno @@ -2859,6 +2917,12 @@ %1$d media selezionati %1$d media selezionati %1$d media selezionati + %1$d persone stanno usando questo tema + %1$d persona sta usando questo tema + %1$d persone stanno usando questo tema + %1$d persone stanno usando questo tema + %1$d persone stanno usando questo tema + %1$d persone stanno usando questo tema Gruppo Canale @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s alle %2$s - EEE MMM d + d MMM + d MMM yyyy + \'Invia oggi alle\' HH:mm + \'Invia il\' d MMM \'alle\' HH:mm + \'Invia il\' d MMM yyyy \'alle\' HH:mm + \'Ricorda oggi alle\' HH:mm + \'Ricorda il\' d MMM \'alle\' HH:mm + \'Ricorda il\' d MMM yyyy \'alle\' HH:mm diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 60146d531e2..d65061e748c 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -233,7 +233,7 @@ 죄송합니다, 그룹의 인원이 최대치입니다. 죄송합니다. 이 사용자는 스스로 그룹에서 나갔기에, 다시 초대하실 수 없습니다. 죄송합니다, 그룹에 너무 많은 관리자가 있습니다. - Sorry, the target user has too many public groups or channels already. Please ask them to make one of their existing groups or channels private first. + 죄송합니다. 대상이 되는 사용자에게 너무 많은 공개 그룹과 채널이 있습니다. 먼저 기존 그룹이나 채널을 비공개로 만들도록 요청해 주세요. 죄송합니다. 대상이 되는 사용자가 위치 기반 그룹을 너무 많이 소유하고 있습니다. 먼저 그룹을 하나 삭제하거나 소유권을 넘기도록 요청해 주세요. 죄송합니다. 위치 기반 그룹을 너무 많이 만드셨습니다. 먼저 하나를 삭제해 주세요. 죄송합니다. 이 그룹에는 봇이 너무 많습니다. @@ -356,7 +356,8 @@ 죄송합니다, 채널에 너무 많은 관리자가 있습니다. 죄송합니다. 이 채널에는 봇이 너무 많습니다. 죄송합니다. 처음 200명까지만 채널에 추가하실 수 있습니다. 채널 링크로는 사람들을 무한정 들이실 수 있는 점 알아두세요. - Sorry, you are a member of too many groups and channels. Please leave some before creating a new one. + 죄송합니다. 너무 많은 그룹과 채널에 들어가 계십니다. 몇 군데에서 나온 뒤 새로 만들어 주세요. + Sorry, you are a member of too many groups and channels. Please leave some before joining a new one. un1 님이 회원님을 이 채널에 추가했습니다 채널에 들어오셨습니다 그룹에 들어오셨습니다 @@ -388,7 +389,7 @@ 메시지 서명 메시지에 게시한 관리자의 이름을 추가합니다. 관리자 권한 - 맞춤 제목 + 맞춤 칭호 맞춤 제목이 모든 참가자에게 \'%1$s\' 대신 보입니다. 이 관리자가 할 수 있는 일 채널 정보 수정 @@ -508,7 +509,7 @@ %1$d초 %1$d분 %1$d시간 - Choose how long each member must wait before sending their next message. + 각 참가자가 다음 메시지를 보내기 전까지 얼마나 기다려야 할지 정하세요. 참가자는 메시지를 %1$s초에 하나씩만 보낼 수 있습니다. 저속 모드가 켜져 있습니다. 한 번에 메시지를 하나 이상 보내실 수 없습니다. 저속 모드가 켜져 있습니다. 항목을 더 선택하실 수 없습니다. @@ -580,7 +581,7 @@ un1 님이 메시지를 고정했습니다. un1 님이 설문을 마감했습니다: un1 님이 아래 메시지를 삭제했습니다: - un1 님이 그룹 위치를 \"%1$s\"로 바꿨습니다 + un1 님이 그룹 위치를 \"%1$s\"(으)로 바꿨습니다 un1 님이 그룹 위치를 제거했습니다 %1$s 님에게 소유권을 넘겼습니다 un1 님이 그룹 스티커 묶음을 변경했습니다 @@ -690,6 +691,7 @@ 즉시 보기 그룹 보기 배경 보기 + VIEW THEME 채널로 이동 메시지 보기 어두운 테마가 밤 시간에 자동으로 켜집니다 @@ -711,6 +713,7 @@ 파일 카메라 메시지가 없습니다... + No scheduled messages here yet... 전달된 메시지 보낸 사람: %1$s 보냄 @@ -718,6 +721,7 @@ 최근 이모지 없음 메시지 메시지 + Schedule message 내 전화번호 공유 내 연락처 공유 연락처에 추가 @@ -757,7 +761,7 @@ 보내기 취소 %1$s이(가) 앞으로 여실 페이지로 회원님의 텔레그램 이름과 아이디(전화번호 아님)를 전달할 수 있도록 허락할까요? 이 장소와 관련 없는 그룹인가요? - 상관 없는 그룹 신고 + 그룹이 관련 없음 신고 그룹이 이 장소와 관련 없는 경우 알려 주세요:\n\n**%1$s** 그룹이 이 장소와 관련 없는 경우 알려 주세요. 스팸 신고 @@ -771,7 +775,7 @@ 텔레그램 메시지와 전화 수신에서 **%1$s** 님을 차단하시겠습니까? 정말 이 사용자가 보낸 스팸을 신고하시겠습니까? 이 그룹 메시지를 스팸신고 하시겠습니까? - 이 채널을 스팸 신고하시겠습니까? + 정말 이 채널에 게시된 스팸 메시지를 신고하시겠습니까? 죄송합니다. 연락처를 교환한 상대에게만 메시지를 보내실 수 있습니다. 죄송합니다. 연락처를 교환한 상대만 그룹에 초대하실 수 있습니다. 죄송합니다. 현재 회원님은 공개 그룹에 게시하실 수 없습니다. @@ -879,12 +883,27 @@ 저속 모드가 켜져 있습니다. %1$s 뒤에 다음 메시지를 보내실 수 있습니다. 사진은 짧게 누르고, 동영상은 꾹 누르세요 소리 없이 보내기 + 지금 보내기> + 시간 조정하기 + Today + Schedule + Schedule message + Scheduled messages + Reminders + Set a reminder + Scheduled for %1$s + Sorry, you can not schedule more than 100 messages. + This action will become available after the message is published. + Voting will become available after the message is published. + 📅 Reminder %1$s 님이 자동 삭제 타이머를 %2$s(으)로 맞췄습니다 자동 삭제 타이머를 %1$s(으)로 맞추셨습니다 %1$s 님이 자동 삭제 타이머를 껐습니다 자동 삭제 타이머를 끄셨습니다 새로운 메시지가 왔습니다 + 📅 You: %1$s + 📅 You %1$s: %2$s %1$s 님이 회원님에게 %2$s을(를) 보냈습니다 %1$s 님이 나에게 앨범을 보냈습니다 @@ -1045,7 +1064,7 @@ 사용자나 그룹을 검색하세요... 참가자 - 공유된 미디어 + 공유한 미디어 설정 구독자 추가 참가자 추가 @@ -1094,7 +1113,7 @@ 비밀 대화 시작 공통 그룹 공통 그룹 - 공통 그룹 없음 + 공통 그룹이 없습니다 오류가 발생했습니다. 암호화 키 자동 삭제 타이머 @@ -1212,6 +1231,8 @@ 색 테마 내장 테마 맞춤 테마 + Set link + Theme Link 대화방 목록 뷰 두 줄 세 줄 @@ -1221,9 +1242,44 @@ 색 선택 색 테마 모든 테마 보기 + Theme not found + Sorry, this color theme doesn’t support your device yet. 새로운 테마 만들기 + New Theme + Edit Theme 각 화면의 구성 요소 목록을 보려면 팔레트 아이콘을 누르세요. 이들을 수정하실 수 있습니다. 앱 안에서 색들을 바꾸어 회원님만의 테마를 만드실 수 있습니다.\n\n여기서 언제든지 기본 텔레그램 테마로 돌리실 수 있습니다. + You can use a-z, 0-9 and underscores.\nMinimum length is 5 characters. + Your theme will be updated for all users each time you change it. Anyone can install it using this link:\n%1$s + Anyone can install your theme using this link. When you change the theme, it will be updated for all users who installed it.\n\nThe theme will be based on your currently selected theme and wallpaper. + You can change the link of your theme.\n\nTheme links must be longer than 5 characters and can use a-z, 0-9 and underscores. + Sorry, theme name is invalid. + Sorry, this link is invalid. + A link must have at least 5 characters. + The link must not exceed 64 characters. + Sorry, the link can\'t start with a number. + Checking link... + Sorry, this link is already taken. + %1$s is available. + Link + Name + Reinhardt + Reinhardt, we need to find you some new tunes 🎶. + I can\'t even take you seriously right now. + Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff! + Lucio + Bring it on! I LIVE for this! + True Survivor + David Hasselhoff + Bob Harris + Good morning! 👋 + Do you know what time it is? + It\'s morning in Tokyo 😎 + Use a different theme + You can also use an existing custom theme as a foundation for your theme. + Choose theme + Export + Create 모든 알림 설정이 기본으로 설정되었습니다 정말 모든 알림 설정을 기본으로 초기화하시겠습니까? @@ -1856,10 +1912,10 @@ 링크 오디오 음성 - 공유된 파일 + 공유한 파일 공유하는 콘텐츠 - 공유된 링크 - 공유된 음악 + 공유한 링크 + 공유한 음악 사진과 동영상을 이 대화방에 공유하여\n어느 기기에서나 열람해 보세요. 이 대화방에 음악을 공유해두면 회원님의 모든 기기에서 접근하실 수 있습니다. 파일과 문서를 이 대화방에 공유하여\n어느 기기에서나 열람해 보세요. @@ -2047,7 +2103,7 @@ %1$s 이메일에 접근하는 데 문제가 있으신가요? 이메일에 접근하지 못한다면, 비밀번호를 기억해 내거나 계정을 초기화하시는 수밖에 없습니다. 계정 초기화 - 계정 초기화를 진행하시면 대화방과 메시지, 공유받은 파일 모두가 사라집니다. + 계정 초기화를 진행하시면, 대화방, 메시지와 더불어 공유한 미디어와 파일이 모두 사라집니다. 경고 이 작업은 되돌릴 수 없습니다.\n\n계정을 초기화하시면, 메시지와 대화방이 모두 삭제됩니다. 계정 초기화 @@ -2093,7 +2149,9 @@ 앞선 설정을 무시하고 사용자나 그룹 전체를 예외로 추가하실 수 있습니다. 전화번호 내 전화번호를 볼 수 있는 사람 - Users who already have your number saved in their contacts will see it on Telegram. + Who can find me by my number? + 이미 연락처에 회원님의 전화번호를 저장한 사용자는 텔레그램에서 전화번호를 볼 수 있습니다. + Users who add your number to their contacts will see it on Telegram only if they are your contacts. 앞선 설정을 무시하고 사용자와 그룹을 예외로 추가하실 수 있습니다. 전달된 메시지 회원님 계정으로 연결합니다 @@ -2336,7 +2394,7 @@ 봇이 요청을 받을 때마다 회원님의 위치를 확인합니다.이는 상세 위치 정보를 제공하는 데 사용됩니다. 전화번호를 공유할까요? 봇이 회원님의 전화번호를 감지할 것입니다. 이는 다른 서비스와 통합하는 데 도움이 됩니다. - " **%2$s**님에게 %1$s번호를 공유하겠습니까?" + " 정말 %1$s 번호를 %2$s 님과 공유하겠습니까?" 정말 전화번호를 공유하시겠습니까? 정말 **%1$s** 님을 차단하시겠습니까? 차단을 해제할까요? @@ -2373,8 +2431,8 @@ 인라인 봇은 제3 개발자가 제공한다는 점을 유의하시기 바랍니다. 봇이 작동하는 과정에서, 봇의 사용자명 뒤에 입력하신 부호가 각 개발자에게 보내집니다 죄송합니다. 메시지를 수정할 수 없습니다. 텔레그램이 전화를 수신 할 수 있도록 설정해주셔야 자동으로 코드 입력이 가능합니다. - Please allow Telegram to receive calls and read the call log so that we can automatically enter your code for you. - Please allow Telegram to read the call log so that we can automatically enter your code for you. + 텔레그램이 전화를 수신하고 통화 기록을 살필 수 있도록 허용해 주세요. 코드를 자동으로 입력해 드릴 수 있습니다. + 텔레그램이 통화 기록을 살필 수 있도록 허용해 주세요. 코드를 자동으로 입력해 드릴 수 있습니다. 텔레그램이 전화를 받을 수 있도록 허용해 주셔야 회원님의 전화번호를 자동으로 확인할 수 있습니다. 죄송합니다. 이 작업은 진행하실 수 없습니다. 죄송합니다. 차단된 사용자나 봇은 그룹에 추가하실 수 없습니다. 먼저 차단을 해제해 주세요. @@ -2485,7 +2543,7 @@ 기술적 정보 포함 대화 내용이 공개되지 않으며 빠른 시일 내로 문제를 해결해 드리는 데 도움이 됩니다. 텔레그램 전화를 개선할 수 있도록 도와주셔서 감사합니다. - %s 님으로 수신 중 + %s 님으로 받는 중 문자로 응답 이 빠른 응답 문구들을 전화가 걸려올 때 텔레그램 메시지로 보내실 수 있습니다. 무엇이든지 원하는 말로 바꾸세요. 지금 대화할 수 없어요. 무슨 일인가요? @@ -2859,6 +2917,12 @@ 미디어 %1$d개 선택됨 미디어 %1$d개 선택됨 미디어 %1$d개 선택됨 + %1$d people are using this theme + %1$d person is using this theme + %1$d people are using this theme + %1$d people are using this theme + %1$d people are using this theme + %1$d people are using this theme 그룹 채널 @@ -2959,5 +3023,12 @@ HH:mm a h:mm %1$s %2$s - EEE MMM d + MMM d + MMM d yyyy + \'Send today at\' HH:mm + \'Send on\' MMM d \'at\' HH:mm + \'Send on\' MMM d yyyy \'at\' HH:mm + \'Remind today at\' HH:mm + \'Remind on\' MMM d \'at\' HH:mm + \'Remind on\' MMM d yyyy \'at\' HH:mm diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 1d67d318ab2..e662f7465dd 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -357,6 +357,7 @@ Maximaal aantal bots bereikt. Je kunt 200 leden handmatig toevoegen aan een kanaal. Een ongelimiteerd aantal mensen kan lid worden via de link van het kanaal. Sorry, je bent lid van teveel groepen en kanalen, verlaat er wat voordat je een nieuwe maakt. + Sorry, je bent lid van teveel groepen en kanalen, verlaat er wat om lid hiervan te worden. un1 heeft je toegevoegd aan dit kanaal Je bent nu lid van dit kanaal Je bent nu lid van deze groep @@ -628,7 +629,7 @@ Berichten vastzetten Alle gebeurtenissen Nieuwe uitzonderingen - Nieuwe beheerders + Beheerdersrechten Nieuwe leden Groepsinformatie Kanaalinformatie @@ -690,6 +691,7 @@ SNELLE WEERGAVE BEKIJK GROEP ACHTERGROND WEERGEVEN + THEMA BEKIJKEN KANAAL OPENEN BEKIJK BERICHT Donker thema schakelt automatisch in tijdens de nacht @@ -711,6 +713,7 @@ Bestand Camera Nog geen berichten + Nog geen geplande berichten Doorgestuurd bericht Van Van %1$s @@ -718,6 +721,7 @@ Niets recents Bericht Bericht + Plan bericht DEEL MIJN NUMMER Mijn contactgegevens delen Toevoegen aan contacten @@ -879,12 +883,27 @@ Tempolimiet is ingeschakeld. Je kunt het\nvolgende bericht sturen over %1$s. Tik voor foto, hou vast voor video Stuur zonder geluid + Stuur nu> + Plan opnieuw + Vandaag + Plannen + Plan bericht + Geplande berichten + Herinneringen + Stel een herinnering in + Gepland op %1$s + Sorry, je kunt niet meer dan 100 berichten plannen. + Deze actie is beschikbaar na publicatie van het bericht. + Stemmen is beschikbaar naar publicatie van het bericht. + 📅 Herinnering %1$s heeft de zelfvernietigingstimer ingesteld op %2$s Je hebt de zelfvernietigingstimer ingesteld op %1$s %1$s heeft de zelfvernietigingstimer uitgeschakeld Je hebt de zelfvernietigingstimer uitgeschakeld Je hebt een nieuw bericht + 📅 Jij: %1$s + 📅 Jij %1$s: %2$s %1$s heeft je %2$s gestuurd %1$s stuurde je een album @@ -1201,8 +1220,8 @@ Donker Donkerblauw Grafiet - Arctisch Blauw - Blauw + Arctisch + Mono Thema echt verwijderen? Themabestand is ongeldig Geef een naam aan je thema @@ -1212,6 +1231,8 @@ Kleurenthema Ingebouwde thema\'s Aangepaste thema\'s + Link instellen + Themalink Weergave chatoverzicht Twee regels Drie regels @@ -1221,9 +1242,44 @@ Selecteer kleur Kleurenthema\'s Alle thema\'s weergeven + Thema niet gevonden + Sorry, this color theme doesn’t support your device yet. Nieuw thema maken + New Theme + Edit Theme Tik op het palet-icoon om een lijst met elementen voor elk scherm te zien en deze te bewerken. Je kunt je eigen thema maken door kleuren in de app aan te passen.\n\nJe kunt hier altijd het standaardthema weer instellen. + Je kun a-z, 0-9 en underscore gebruiken.\nMinimale lengte 5 karakters. + Je thema zal worden bijgewerkt voor alle gebruikers iedere keer als je deze wijzigt. Iedereen kan het installeren via deze link.\n\n%1$s + Anyone can install your theme using this link. When you change the theme, it will be updated for all users who installed it.\n\nThe theme will be based on your currently selected theme and wallpaper. + You can change the link of your theme.\n\nTheme links must be longer than 5 characters and can use a-z, 0-9 and underscores. + Sorry, theme name is invalid. + Sorry, deze link is ongeldig. + Een link moet minimaal 5 karakters bevatten + De link mag niet langer zijn dan 64 karakters. + Sorry, een begincijfer is niet toegestaan. + Link controleren... + Sorry, deze link is bezet. + %1$s is beschikbaar. + Link + Name + Reinhardt + Reinhardt, we need to find you some new tunes 🎶. + I can\'t even take you seriously right now. + Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff! + Lucio + Bring it on! I LIVE for this! + True Survivor + David Hasselhoff + Bob Harris + Good morning! 👋 + Do you know what time it is? + It\'s morning in Tokyo 😎 + Use a different theme + You can also use an existing custom theme as a foundation for your theme. + Choose theme + Export + Create Alle meldingen gereset Alle meldingsinstellingen herstellen naar de standaardwaarden? @@ -1448,8 +1504,8 @@ Dringend Nooit Meldingen herhalen - Je kan je telefoonnummer hier wijzigen. Al je clouddata — berichten, bestanden, groepen, contacten, etc. zullen worden gekopieërd naar je nieuwe nummer.\n\n**Let op:** al je Telegram-contacten krijgen je **nieuwe nummer** in hun adresboek, ervan uitgaande dat ze je oude nummer hadden en je hen niet had geblokkeerd in Telegram. - Al je Telegram-contacten krijgen je nieuwe nummer in hun adresboek, ervan uitgaande dat ze je oude nummer hadden en je hen niet had geblokkeerd in Telegram. + Je kan je telefoonnummer hier wijzigen. Al je clouddata — berichten, bestanden, groepen, contacten, etc. zullen worden verplaatst naar je nieuwe nummer. + Gebruikers zien je nieuwe nummer als ze deze in hun adresboek hebben of als je privacy-instellingen dat toestaat. Je kunt dit aanpassen via Instellingen > Privacy en Veiligheid > Telefoonnummer. Nummer wijzigen Nummer wijzigen Nieuw nummer @@ -2093,7 +2149,9 @@ Je kunt gebruikers of groepen toevoegen als uitzondering op de instelling hierboven. Telefoonnummer Wie kan mijn telefoonnummer zien? + Wie kan me vinden via mijn nummer? Gebruikers die je nummer al hebben opgeslagen in contacten zien je nummer op ook Telegram. + Gebruikers die je nummer aan contacten toevoegen zien jouw nummer alleen als ze ook in jouw contacten staan. Je kunt gebruikers of groepen toevoegen als uitzondering op de instelling hierboven. Doorgestuurde berichten Link naar je account @@ -2859,6 +2917,12 @@ %1$d media geselecteerd %1$d media geselecteerd %1$d media geselecteerd + %1$d people are using this theme + %1$d person is using this theme + %1$d people are using this theme + %1$d people are using this theme + %1$d people are using this theme + %1$d people are using this theme Groep Kanaal @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s om %2$s - EEE MMM d + d MMM + d MMM yyyy + \'Stuur vandaag om\' HH:mm + \'Stuur op\' d MMM \'om\' HH:mm + \'Stuur op\' d MMM yyyy \'om\' HH:mm + \'Herinner vandaag om HH:mm + \'Herinner op\' d MMM \'om\' HH:mm + \'Herinner op\' d MMM yyyy \'om\' HH:mm diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index e2ff417959b..2354cbf3118 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -60,7 +60,7 @@ Métodos de envio Desculpe, não é possível entregar neste endereço. Dados de Envio - Dados de envio + Endereço de envio Endereço 1 (Rua) Endereço 2 (Rua) Cidade @@ -143,7 +143,7 @@ %s entrou no chat secreto Você entrou no chat secreto Limpar histórico - Histórico limpo. + Histórico apagado. Silenciar Ativar Som Chat apagado. @@ -187,7 +187,7 @@ Remover %1$s das sugestões? Prévia do link Rascunho - O histórico foi apagado + O histórico foi apagado. por %1$s %1$s por %2$s Deixar um comentário sobre essa prévia @@ -357,6 +357,7 @@ Desculpe, há bots demais neste canal. Desculpe, você só pode adicionar os primeiros 200 membros ao canal. Note que um número ilimitado de pessoas podem entrar via link do canal. Desculpe, você é um membro de muitos grupos e canais. Por favor, saia de alguns antes de criar um novo. + Desculpe, você é membro de muitos grupos e canais. Por favor, saia de alguns antes de entrar em outro. un1 adicionou você ao canal Você entrou neste canal Você entrou neste grupo @@ -504,7 +505,7 @@ CONVERSAR canal Modo Lento - Inativo + Não %1$ds %1$dm %1$dh @@ -527,7 +528,7 @@ Parar enquete? Se você parar esta enquete agora, ninguém poderá mais votar nela. Essa ação não pode ser desfeita. Descartar enquete? - Tem certeza de que deseja descartar esta enquete? + Deseja descartar esta enquete? Remover Voto Resultados Finais Sem votos @@ -628,7 +629,7 @@ Fixar mensagens Todas as ações Novas exceções - Novos admins + Permissões de administrador Novos membros Info do grupo Info do canal @@ -690,6 +691,7 @@ LEITURA RÁPIDA VER GRUPO VER PAPEL DE PAREDE + VER TEMA VER CANAL VER MENSAGEM O tema noturno será ativado automaticamente à noite. @@ -711,6 +713,7 @@ Arquivo Câmera Ainda não há mensagens aqui... + Não há mensagens agendadas aqui ainda... Mensagem encaminhada De De %1$s @@ -718,6 +721,7 @@ Nada recente Mensagem Mensagem + Agendar mensagem COMPARTILHAR MEU NÚMERO Compartilhar meu contato Add Contato @@ -879,12 +883,27 @@ Modo Lento ativado. Poderá enviar\nsua próxima mensagem em %1$s. Toque para foto, segure para vídeo Enviar sem som + Enviar Agora> + Reagendar + Hoje + Agendar + Agendar mensagem + Mensagens agendadas + Lembretes + Criar Lembrete + Agendada para %1$s + Desculpe, você não pode agendar mais de 100 mensagens. + Esta ação vai estar disponível após a publicação da mensagem. + A enquete vai estar disponível após a publicação da mensagem. + 📅 Lembrete "%1$s alterou o timer de autodestruição para %2$s " Você alterou o timer de autodestruição para %1$s %1$s desativou o timer de autodestruição Você desativou o timer de autodestruição Você tem uma nova mensagem + 📅 Você: %1$s + 📅 Você %1$s: %2$s %1$s te enviou %2$s %1$s te enviou um álbum @@ -1201,8 +1220,8 @@ Escuro Azul Escuro Grafite - Azul Ártico - Azul + Ártico + Mono Tem certeza de que deseja apagar este tema? Arquivo de tema incorreto Insira o nome do tema @@ -1212,6 +1231,8 @@ Tema de cores Temas padrão Temas personalizados + Criar link + Link do Tema Visão da Lista de Chats Duas linhas Três linhas @@ -1221,9 +1242,44 @@ Selecionar cor Tema de Cores Mostrar Todos os Temas + Tema não encontrado + Desculpe, este tema de cores não é compatível com o seu dispositivo ainda. Criar tema + Novo Tema + Editar Tema Toque no ícone da paleta para visualizar a lista de elementos de cada tela - e editá-los. Você pode criar seu próprio tema alterando as cores dentro do aplicativo.\n\nVocê sempre pode voltar para o tema padrão do Telegram aqui. + Você pode usar a-z, 0-9 e underline.\nO tamanho mínimo é de 5 caracteres. + O seu tema será atualizado para todos sempre que você atualizar ele. Qualquer um pode instalar usando este link:\n%1$s + Qualquer pessoa pode instalar o seu tema usando este link. Quando você alterar o tema, ele será atualizado para todos os usuários que o instalaram.\n\nO tema terá como base o tema e o papel de parede selecionados atualmente. + Você pode alterar o link do seu tema.\n\nOs links de temas devem ter mais de 5 caracteres e podem usar a-z, 0-9 e underlines. + Desculpe, o nome do tema é inválido. + Desculpe, este link é inválido. + O link tem que ter no mínimo 5 caracteres. + O link não pode ter mais de 64 caracteres. + Desculpe, o link não pode começar com um número. + Verificando link... + Desculpe, este link já está sendo usado. + %1$s está disponível. + Link + Nome + Reinhardt + Reinhardt, precisamos encontrar músicas novas. 🎶 + Não consigo nem te levar a sério agora. + Ahh, vocês crianças de hoje em dia com essas músicas eletrônicas! Ouçam os clássicos, como Hasselhoff! + Lúcio + Manda ver, eu vivo pra isso! + True Survivor + David Hasselhoff + Bob Harris + Bom dia! 👋 + Você sabe que horas são? + É manhã em Tóquio 😎 + Use a different theme + Você também pode usar um tema personalizado existente como base para o seu tema. + Choose theme + Exportar + Criar Todas as configurações de notificação foram redefinidas Tem certeza de que deseja restaurar todas as configurações de notificação para o padrão? @@ -1448,8 +1504,8 @@ Urgente Nunca Repetir Notificações - Você pode alterar seu número do Telegram aqui. Sua conta e todos os seus dados — mensagens, mídia, contatos, etc. serão movidos para o novo número.\n\n**Importante:** todos os seus contatos do Telegram terão seu **novo número** adicionado às listas de contatos deles, desde que tenham seu número antigo e você não os tenha bloqueado no Telegram. - Todos os seus contatos do Telegram terão seu novo número adicionado às listas de contatos deles, desde que tenham seu número antigo e você não os tenha bloqueado no Telegram. + Você pode alterar o seu número do Telegram aqui. Sua conta e todos os seus dados — mensagens, mídia, contatos, etc. serão movidos para o novo número. + Os usuários irão ver o seu novo número se eles tiverem salvo na agenda deles ou se as suas configurações de privacidade permitirem. Você pode alterar isso em Configurações > Privacidade e Segurança > Número de Telefone. Alterar Número Alterar número Novo Número @@ -1835,7 +1891,7 @@ Toque no sensor. Digital não reconhecida, tente de novo. Mostrar Conteúdo no Multitarefas - Se desativado você não poderá fazer capturas de tela no aplicativo, mas o conteúdo dos seus chats não será mostrado no multitarefas. + Se desativado, você não poderá fazer capturas de tela no aplicativo – porém, o conteúdo dos seus chats não será mostrado no multitarefas. Isso ocultará o conteúdo de seus chats ou lista de chats do multitarefas, mas você não poderá tirar capturas de tela no Telegram.\n\nPode ser necessário reiniciar o aplicativo para que isso entre em vigor. Muitas tentativas.\nPor favor, tente de novo em %1$s. @@ -2093,14 +2149,16 @@ Você pode adicionar usuários ou grupos inteiros como exceções que substituirão as configurações acima. Número de Telefone Quem pode ver meu número? + Quem pode me encontrar pelo meu número? Usuários que já tiverem o seu número salvo nos contatos também irão ver no Telegram. + Usuários que adicionarem o seu número aos contatos deles irão te ver no Telegram apenas se estiverem nos seus contatos também. Você pode adicionar usuários ou grupos inteiros como exceções que substituirão as configurações acima. Mensagens Encaminhadas Link para sua conta É um link se permitido pelas configurações abaixo Não é um link para sua conta Quem pode adicionar um link para minha conta ao encaminhar minhas mensagens? - Quando encaminhadas para outros chats, as mensagens enviadas não terão um link para sua conta. + As mensagens que você enviar não terão um link para a sua conta quando outras pessoas encaminharem. Você pode adicionar usuários ou grupos inteiros como exceções que substituirão as configurações acima. Reinhardt, precisamos encontrar músicas novas. Ponta a Ponta @@ -2285,7 +2343,7 @@ Apagar Tudo Parar de carregar? Atualizar Telegram - Perdão, seu Telegram está desatualizado e não consegue atender a este pedido. Por favor atualize o Telegram. + Desculpe, seu Telegram está desatualizado e não consegue atender a este pedido. Por favor, atualize o Telegram. Número de telefone inválido. Por favor, verifique o número e tente de novo. Por favor, entre com sua conta do Telegram para usar o Telegram Passport. Este número de telefone está banido. @@ -2362,7 +2420,7 @@ Tem certeza de que deseja apagar essa mensagem para todos? Tem certeza de que deseja apagar essas mensagens para todos? Apagar Minhas Mensagens - Apagar também para %1$s + Apagar para %1$s também Limpar também para %1$s Enviar mensagens para %1$s? Compartilhar jogo com %1$s? @@ -2859,6 +2917,12 @@ %1$d mídias selecionadas %1$d mídias selecionadas %1$d mídias selecionadas + %1$d pessoas estão usando este tema + %1$d pessoa está usando este tema + %1$d pessoas estão usando este tema + %1$d pessoas estão usando este tema + %1$d pessoas estão usando este tema + %1$d pessoas estão usando este tema Grupo Canal @@ -2959,5 +3023,12 @@ HH:mm h:mm a %1$s às %2$s - EEE, d \'de\' MMM + d \'de\' MMM + d \'de\' MMM \'de\' yyyy + \'Enviar hoje às\' HH:mm + \'Enviar em\' d \'de\' MMM \'às\' HH:mm + \'Enviar em\' d \'de\' MMM \'de\' yyyy \'às\' HH:mm + \'Lembrar hoje às\' HH:mm + \'Lembrar em\' d \'de\' MMM \'às\' HH:mm + \'Lembrar em\' d \'de\' MMM \'de\' yyyy \'às\' HH:mm diff --git a/TMessagesProj/src/main/res/values-v21/styles.xml b/TMessagesProj/src/main/res/values-v21/styles.xml index 9786c7c724e..f95d0dc4e75 100644 --- a/TMessagesProj/src/main/res/values-v21/styles.xml +++ b/TMessagesProj/src/main/res/values-v21/styles.xml @@ -36,7 +36,8 @@ #33000000 #527da3 @style/Theme.TMessages.Dialog.Alert - #4991cc + #808080 + #60808080 @style/Theme.TMessages.DatePicker @style/Theme.TMessages.Dialog.Alert @style/Theme.TMessages.TimePicker @@ -60,7 +61,7 @@